从CBitmap到StretchDIBits

        最近遇到一个问题,我的BMP文件放在资源里,在程序中使用CBitmap的LoadBitmapW加载,然后使用StretchBlt函数贴到打印机上(因为原图太小,必须放大),这时候出现一个问题,那就是在打印预览里明明显示很好的位图,打印到pdfcreator(一种模拟打印机的软件,其生成pdf)时,却什么也没有显示。

        后来在网上看了许多文章,才知道有些打印机是不支持StretchBlt函数的。后来,设想使用内存DC过渡的方法,即先将位图StretchBlt到内存DC上,再使用BitBlt函数将内存DC贴到打印机DC上,结果问题依旧,事后分析,是因为内存DC与打印机DC是兼容的,因此同样不支持StretchBlt函数。

        唯一的希望,只剩StretchDIBits(这个每个打印机都支持),它是一个API函数,负责绘制设备无关位图。从网上,我只看到将bmp文件加载后,使用StretchDIBits函数的方法,可是我的BMP文件放在资源里。难道只能编程转换bmp到DIB?那可是不小的工作量呀!于是动手尝试利用CBitmap的信息,来使用StretchDIBits函数,几经周折终于成功了!请看下文!

 

        其实原理很简单,首先导出位图像素数据到内存lpBits,利用CBitmap的信息初始化BITMAPINFO,利用它们就可以调用StretchDIBits啦!

 

  1. CBitmap bm;
  2. bm.LoadBitmapW(IDB_LOGO);
  3. BITMAP bmpInfo;
  4. bm.GetBitmap(&bmpInfo);
  5. void *lpBits = 0;
  6. int biSizeImage = bmpInfo.bmWidthBytes * bmpInfo.bmHeight; //计算位图数据需要多少字节
  7. lpBits = malloc(biSizeImage);
  8. bm.GetBitmapBits(biSizeImage, lpBits);
  9. BITMAPINFO   BitmapInfo;
  10. BitmapInfo.bmiHeader.biSize=sizeof(BITMAPINFOHEADER);  BitmapInfo.bmiHeader.biWidth=bmpInfo.bmWidth;   
  11. BitmapInfo.bmiHeader.biHeight=bmpInfo.bmHeight;   
  12. BitmapInfo.bmiHeader.biPlanes=1;   
  13. BitmapInfo.bmiHeader.biBitCount=32;//这里是位图的颜色位数,如果你的位图不是真彩色的,也就是小于等于8位,那就麻烦了,你还要编程实现BitmapInfo.bmiColors结构,所以建议将位图设计成真彩色的,不要吝惜那点空间!
  14. BitmapInfo.bmiHeader.biCompression=BI_RGB;   
  15. BitmapInfo.bmiHeader.biClrUsed=0;  
  16. BitmapInfo.bmiHeader.biSizeImage=0;   
  17. BitmapInfo.bmiHeader.biXPelsPerMeter=0;   
  18. BitmapInfo.bmiHeader.biYPelsPerMeter=0;   
  19. BitmapInfo.bmiHeader.biClrImportant=0; 
  20. StretchDIBits(*pDC, 700, 700, 3000, 3000, 0, 0, bmpInfo.bmWidth, bmpInfo.bmHeight, lpBits, &BitmapInfo, DIB_RGB_COLORS, SRCCOPY);
  21. free(lpBits);

你可能感兴趣的:(Visual,C++.Net,colors,编程,api,工作,bi)