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 ...
随机推荐
- K线图学习
本博文(适合入门的股民朋友)内容来自网络,股市有风险,入市需谨慎 一.起源 K线图(Candlestick Charts)又称蜡烛图.日本线.阴阳线.棒线等,常用说法是“K线”,起源于日本十八世纪德川 ...
- Search in Rotated Sorted Array
Suppose a sorted array is rotated at some pivot unknown to you beforehand. (i.e., 0 1 2 4 5 6 7 migh ...
- android 之httpclient方式提交数据
HttpClient: 今天实战下httpclient请求网络json数据,解析json数据返回信息,显示在textview, 起因:学校查询饭卡余额,每次都要访问校园网(内网),才可以查询,然后才是 ...
- 百度编辑器ueditor的简单使用
最近刚被分配了以个消息发布的任务,其中用到了富文本编辑器.以前也用过,不过这次我选择的是百度富文本编辑器ueditor1_4_3-utf8-jsp版的. 其实看ueditor功能很强大,不过百度的设计 ...
- C/C++编译和链接过程详解 (重定向表,导出符号表,未解决符号表)
详解link 有 些人写C/C++(以下假定为C++)程序,对unresolved external link或者duplicated external simbol的错误信息不知所措(因为这样的错 ...
- 最后一周psp
团队项目PSP 一:表格 C类型 C内容 S开始时间 E结束时间 I时间间隔 T净时间(mins) 预计花费时间(mins) 讨论 讨论用户界面 10:20 11:45 25 40 80 分析 ...
- Linux内核分析作业7:Linux内核如何装载和启动一个可执行程序
1.可执行文件的格式 在 Linux 平台下主要有以下三种可执行文件格式: 1.a.out(assembler and link editor output 汇编器和链接编辑器的输出) ...
- EF 连接sql2000
正常连接会提示版本低 可以先用ef连接高版本的sql然后新建好EDMX文件后,在右键xml方式打开,把ProviderManifestToken="2008" 改为2000 然后再 ...
- 使用 OWIN Self-Host ASP.NET Web API 2
Open Web Interface for .NET (OWIN)在Web服务器和Web应用程序之间建立一个抽象层.OWIN将网页应用程序从网页服务器分离出来,然后将应用程序托管于OWIN的程序而离 ...
- Hadoop学习笔记—9.Partitioner与自定义Partitioner
一.初步探索Partitioner 1.1 再次回顾Map阶段五大步骤 在第四篇博文<初识MapReduce>中,我们认识了MapReduce的八大步凑,其中在Map阶段总共五个步骤,如下 ...