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 ...
随机推荐
- Python之路第一课Day8--随堂笔记(socket 承接上节---网络编程)
本节内容 Socket介绍 Socket参数介绍 基本Socket实例 Socket实现多连接处理 通过Socket实现简单SSH 通过Socket实现文件传送 作业:开发一个支持多用户在线的FTP程 ...
- WPF整理-Style
"Consistency in a user interface is an important trait; there are many facets of consistency, ...
- XPath注入跟SQL注入差不多,只不过这里的数据库走的xml格式
SQL注入这块不想细聊了,相信很多朋友都听到耳朵长茧,不外乎是提交含有SQL操作语句的信息给后端,后端如果没有做好过滤就执行该语句,攻击者自然可以随意操纵该站点的数据库. 比如有一个图书馆站点book ...
- MySQL 注册码
最近开发是用MySQL数据库,之前安装后,每次打开Navicat Premium 都提示 “试用一个月”,“ 注册”,然后为了方便,就都选择了 试用的, 一个月后,就必须的输入注册码,(还有一个是 什 ...
- 1035-Spell checker(模糊匹配)
一,题意: 给出一组字典的单词,以'#'结束,之后给出一组要执行模糊匹配的单词序列,以'#'结束 1,若某个单词能在字典中找到,则输出corret 2,若某个单词能通过 变换 或 删除 或 添加一个字 ...
- iOS 开发快速导引:TableView 和 CoreData【草】
所有列表式的数据都是用 TableView 显示的 预览 待补充 原料 NSFetchedResultsController 用来操作 NSFetchRequst,有执行查询,监听变化,数据缓存等功能 ...
- matlab size、numel、length、fix函数的使用,补充nargin
size():获取矩阵的行数和列数 (1)s=size(A), 当只有一个输出参数时,返回一个行向量,该行向量的第一个元素时矩阵的行数,第二个元素是矩阵的列数.(2)[r,c]=size(A), 当有 ...
- Android中SQLite数据库小计
2016-03-16 Android数据库支持 本文节选并翻译<Enterprise Android - Programing Android Database Applications for ...
- 多线程中的锁系统(三)-WaitHandle、AutoResetEvent、ManualResetEvent
本章主要介绍下基于内核模式构造的线程同步方式,事件,信号量. 阅读目录: 理论 WaitHandle AutoResetEvent ManualResetEvent 总结 理论 Windows的线程同 ...
- 前端er是否忽略了某些东西?——读《ppk谈JavaScript》
关于书 “不知道ppk的网站QuirksMode,说明你可能还没有真正成为资深的JavaScript程序员.” ——Roger Johansson,瑞典资深Web专家. ppk是世界级前端技术专家,W ...