vc下打印透明背景图片
一、前言
刚接到个任务,要把带有透明背景的章子图片打印出来,开始觉得不是很简单吗,直接用vc自动生成的打印功能不就ok了。不过问题却不是想像的那么简单!
二、窗口中显示透明图片
在窗口中显示图片,可以用强大的CImage类,这个类能加载很多常见格式的图像文件,当然对于我要加载的png格式的透明图片也是可以的。具体的代码如下:
CImage m_image;
m_image.Load(_T("picture.png"));
if (m_image.IsNull())
{
MessageBox(_T("图片没加载成功"));
return;
}
加载png图片到CImage对象后,CImage提供了一个函数Draw,可以直接将图片画到窗口上下文中,在CDrawView类的OnDraw加入下面的代码:
m_Image.Draw(pDC->m_hDC,0,0);
就这几行代码就可以了,直接点运行,图片确实画到了窗口上,不过却不是透明显示的。透明图片中每个像素都有一个ALPHA(0-255)值来表示透明的程度,如果某个像素不是透明的,那么它的ALPHA为0。一般在已有像素上画带有ALPHA值的像素,可以用下面的方法实现:假设源像素的RGB分别为srcR,srcG,srcB,要画的带有ALPHA值的像素的RGB和ALPHA为desR,desG,desB和desA,新像素的RGB为newR,newG,newB。具体计算方法为:
newR = srcR * (1-desA) / 255 + desR * desA / 255
newG = srcR * (1-desA) / 255 + desG * desA / 255
newB = srcB * (1-desA) / 255 + desB * desA / 255
CImage类中的Draw函数的实现确实根据下面实现的:
newR = srcR * (1-desA) / 255 + desR
newG = srcR * (1-desA) / 255 + desG
newB = srcB * (1-desA) / 255 + desB
对于超过255的,都按255处理,显然,如果desR,desG,desB比较大的话,最终得到的newR,newG,newB都将会是255,导致图片的背景都是白色。所以在调用Draw函数之前必须先对desR,desG,desB进行下面的处理:
desR = desR * desA / 255
desG = desG * desA / 255
desG = desG * desA / 255
具体的实现代码如下:
for(int i = ; i < m_image.GetWidth(); i++)
{
for(int j = ; j < m_image.GetHeight(); j++)
{
unsigned char* pucColor = reinterpret_cast<unsigned char *>(m_image.GetPixelAddress(i , j));
pucColor[] = pucColor[] * pucColor[] / ; //pucColor[3]为ALPHA值
pucColor[] = pucColor[] * pucColor[] / ;
pucColor[] = pucColor[] * pucColor[] / ;
}
}
三、放大打印预览中图片的大小
直接点打印预览的时候,发现图片显示的很小。这是由于显示器设备每英寸的像素是96,而打印机每英寸的像素是600,也就是说打印机预览显示的图像的大小只有显示器显示图像的1/6。必须要放大打印机显示视口的比例,使得其显示的图像和显示器中显示的图像大小一致。办法是在CDrawView类中重载OnPrepareDC函数,具体代码如下:
void CDrawView::OnPrepareDC(CDC* pDC, CPrintInfo* pInfo)
{
// TODO: 在此添加专用代码和/或调用基类
CView::OnPrepareDC(pDC, pInfo);
pDC->SetMapMode(MM_ANISOTROPIC);//转换坐标映射方式
CSize size=CSize(,);
pDC->SetWindowExt(size);
//得到实际设备每逻辑英寸的象素数量
int xLogPixPerInch=pDC->GetDeviceCaps(LOGPIXELSX);
int yLogPixPerInch=pDC->GetDeviceCaps(LOGPIXELSY);
long xExt=(long)size.cx*xLogPixPerInch/;
long yExt=(long)size.cy*yLogPixPerInch/;
//确定视口大小
pDC->SetViewportExt((int)xExt,(int)yExt);
}
这样使用打印预览的时候,图像的大小就恢复正常了。本以为到这里就大功告成了,没想到点打印的时候,居然打出的是白纸(汗!!)。
四、打印出透明图片
打印预览能显示出来,却打印不出来,这让我百思不得其解啊!后来想想也许是Draw函数与打印机设备不兼容,然后换做CDC的SetPixel来画图像,结果还是打印不出来,就这样白白浪费了一天的时间啊!过了一天突然想到是不是打印机的问题或者是打印程序的问题,于是在窗口上打印几个字来显示看看,发现可以打印出来,说明不是打印机和打印程序的问题。然后我试着画个矩形,看看能不能打印出来,最终发现还是可以打印出来的。既然可以打印出矩形来,那么打印出图像来也应该不是问题,把图像中的每个像素用一个长和高为1的矩形画出来不就行了吗。根据这个思想,稍微改了下代码,点打印终于可以了,具体代码如下:
int i;
int j;
for (i=; i<m_image.GetWidth(); i++)
{
for (j=; j<m_image.GetHeight(); j++)
{
byte *pByte = (byte *)m_image.GetPixelAddress(i, j); if (m_image.GetBPP() == ) //确认该图像包含Alpha通道
{
if (pByte[])//确保透明背景不被画出
{
pDC->FillSolidRect(i,j,,,m_image.GetPixel(i,j));
} }
else
{
pDC->FillSolidRect(i,j,,,m_image.GetPixel(i,j));
}
}
}
五、总结
从这个小任务的完成,很多事情其实就是那么一点的思想,如果你对问题转变个思路,而不是一条道走到黑,问题也许一下就解决了。某个问题的解决方法不止一种,特别在计算机软件开发中。即使但你尝试了所有方法都解决不了一个问题的时候,也不要放弃,或许过片刻,或许过一天,一个新的idea就突然出现在你脑子里,把这个问题解决了。
vc下打印透明背景图片的更多相关文章
- 网页中PNG透明背景图片的完美应用
PNG 图片在网站设计中是不可或缺的部分,最大的特点应该在于 PNG 可以无损压缩,而且还可以设置透明,对于增强网站的图片色彩效果有重要的作用. 但为什么 PNG 图片却没有 GIF 和 JPG 图片 ...
- Qt 制作透明背景图片与裁剪图片(很实用)
这两天想做一个五子棋游戏,想从零开始自己绘制各种图片素材,将经验心得整理如下. 制作透明背景图片: void MyPainter::DrawKit() { QImage image(30, 30, Q ...
- 【计算机视觉】OPENCV对于有alpha通道的透明背景图片的读取和图片叠加
这个是我自己做的粗略的螺旋丸的图,导出为png并带有alpha通道. 最后和一只狗合成成这个样子. 效果还是可以的. 为了实现这个效果,首先我们要明白具有透明通道的图片的OpenCV的读取方式.在Op ...
- C++ 设置透明背景图片
背景: 有两个图片,一个是目标背景图片, 一个是带有自身背景色彩的彩色图片 先将这彩色图片绘制到目标背景图片中, 这一步通过BITBLT就可实现. 但实 ...
- 关于imagic拼接透明背景图片的问题
目标: 为了做图片水印,需要水平拼接多个logo和文字... 之前用过imagick,所以继续使用. 第一个版本:实现了图片和文字的拼接,代码如下: package main import ( &qu ...
- java 生成透明背景图片
//开始绘图 graphics2d.setBackground(Color.WHITE); graphics2d.clearRect(0, 0, width, height); graphics2d. ...
- vc++加载透明png图片方法-GDI+和CImage两种
转载自:http://blog.csdn.net/zhongbin104/article/details/8730935 先看看GDI+的方法方法1: 1.GDI+画透明图层(alpha)的png ...
- 如何在VC中显示透明背景位图
简单的调用系统API. Windows NT/2000/XP: Included in Windows 2000 and later.Windows 95/98/Me: Included in Win ...
- php 处理透明背景的图片时的问题
PHP图象处理之透明背景的gif和png图片的一些问题 1,直接读取有透明背景的PNG格式文件,然后直接输出,背景变成了黑色,gif则没有这种情况. 解决方法:使用 imagesavealpha ...
随机推荐
- PL/SQL Developer如何连接64位的Oracle图解
在64位Win7系统上安装64位的Oracle数据库,但是没有对应的64位PL/SQL Developer,此时就不能使用PL/SQL Developer来进行直接连接的,所以要想实现连接还得需要其他 ...
- Mac 终端 Linux 命令总结(简单命令)
目录操作 命令名 功能描述 使用举例 mkdir 创建一个目录 mkdir dirname rmdir 删除一个目录 rmdir dirname mvdir 移动或重命名一个目录 mvdir dir1 ...
- Android带边框表格的实现
最近做项目需要用到表格,数据是动态指定的,本来用GridView是很方便的,可是老大不同意用这么重量级的控件,想办法吧. 做表格很容易想到用TableLayout,那就自定义一个来搞. 一.表格最蛋疼 ...
- ios设备中openGL所支持的最大纹理尺寸
这几天碰到一个在iphone4上显示图片未黑色矩形的bug,在其他机器上都正常 最后发现是图片打包尺寸的关系,iphone4无法读取2048以上大小的单个图片,所以其中的图片都显示成了黑色,希望对碰到 ...
- 【luogu】 P1880 石子合并
原题原题原题原题原题 先贴上错误代码... ↓错误代码↓ #include <iostream> #include <cstdio> #include <cstring& ...
- 启动项目的时候报驱动错误: not support oracle driver 1.0
问题:今天在使用pom导入oracle14的包时候发现怎么都下载不过来.网上查了一下发现是因为Oracle驱动需要官方授权,所以在pom.xml文件直接配置,无法下载成功. 解决方法就是下载oracl ...
- 反向传播(BP)算法
著作权归作者所有.商业转载请联系作者获得授权,非商业转载请注明出处.作者:刘皮皮链接:https://www.zhihu.com/question/24827633/answer/29120394来源 ...
- 微软StockTrader应用程序
这是一个采用 .NET Enterprise Application Server 技术的端到端示例应用程序.应用程序代码可以从 这里 下载. 代码中演示了WCF服务和移动开发,包括用Xamarin ...
- ENode框架Conference案例分析系列之 - 上下文划分和领域建模
前面一片文章,我介绍了Conference案例的核心业务,为了方便后面的分析,我这里再列一下: 业务描述 Conference是这样一个系统,它提供了一个在线创建会议以及预订会议座位的平台.这个系统的 ...
- 避免Castle Windsor引起的内存泄露
原文地址: http://nexussharp.wordpress.com/2012/04/21/castle-windsor-avoid-memory-leaks-by-learning-the-u ...