关于修改图像文件的问题 我在MFC中用CFile打开了一个bmp图像,它的信息(就是那些信息头和图像像素数据等之类的)我都基本得到了。如果我想在图像上随便加一行字,然后保存图像(另存为一个新的图像文件也行),使得以后每次打开该图像文件时该文字是存在的,请问怎样做? 给整个过程的代码或者几个关键步骤的函数都行。谢谢了。 解决方案 » 免费领取超大流量手机卡,每月29元包185G流量+100分钟通话, 中国电信官方发货 http://topic.csdn.net/t/20010330/13/90523.html 用GDI+吧,用bmp图像文件创建一个IStream,然后用这个IStream创建一个Bitmap对象,之后创建一个Graphics对象将这个Bitmap对象选入,然后调用DrawString,之后再调用Bitmap的Save方法保存成另外一个文件就可以了。 要把你的BMP选入DC然后再上面写字,最后保存,例如:IBmp bmp;bmp.Load( bmpName );// 取来GDI作图CDC *pDrawDC = CDC::FromHandle( bmp.BeginDraw() );// 设置字体背景透明// pDrawDC->SetBKMode( TRANSPARENT );// 字体颜色// pDrawDC->SetTextColors( RGB( x, x, x ) );// 写字// pDrawDC->TextOut( x, y, "hello, world!" );// 写完释放bmp.EndDraw();// 保存.bmp.Save( bmpName );简单吧.. 找不到BeginDraw()函数啊。还有,IBmp bmp;是什么意思? 先将BMP文件贴到DC上来,然后用TextOut写字,然后将HBITMAP对象保存为BMP文件即可。这里面最大的问题是将HBitmap对象保存为BMP文件,下面有示例代码:http://blog.csdn.net/wltg2001/archive/2008/04/17/2300258.aspx 去这里找到IBmp类:http://blog.csdn.net/lambochan/archive/2009/12/31/5115776.aspx然后导入到你的工程(或者自己新建个类copy粘贴),就可以如法炮制了... 我只把那个IBmp.h 和IBmp.cpp通过“工程-增加到工程-文件”添加到了我的工程。我把头文件IBmp.h通过#include"IBmp.h"添加到了我的工程的View类的cpp文件中,因为我只在View类进行操作,但是出现如下错误:fatal error C1083: Cannot open include file: 'IBmp.h': No such file or directory真的不知道为什么,请教楼上。 呵呵!方法很多,就看你会不会用了,另:6楼的方法值得一试,至于将HBitmap对象保存为bmp文件的代码,我这有,可以发给你,或你到我的资源中去下。 要把它copy到你工程的目录下."No such file or directory"就是找不到文件..估计你是单纯引用没有copy到目录吧.#include "xxx.h"时,只会在当前目录找文件的 我用自己的方法解决了,其实也不算是自己的方法。有一点我要说明一下,我本来就是用CFile 打开了一个BMP文件,就是它的BITMAPINFOHEADER,BITMAPFILEHEADER,RGBQUAD,还有实际的图像数据的指针lpBuf四部分的数据我都得到了。之后我用dc在图片上写字,然后用dc.GetPixel去把修改后每点的像素再存放一个lpBuf_new指向的区域。然后我又用CFile建了一个新的文件,之后把先前得到的修改前BMP文件的BITMAPINFOHEADER,BITMAPFILEHEADER,RGBQUAD用Write函数依次写进这个文件,最后一部分用lpBuf_new代替就得到一个新的文件,这个文件保存的就是修改后的效果。而且有一点我要声明,我刚才处理的是24位彩色图,lpBuf里存放的就是实际的图像的颜色值。 现在问题来了,假如我处理的是256色图,那么这时lpBuf里存放的是索引值,RGBQUAD存放的是真正的颜色值,我还想用类似的方法怎么做。因为我在图像上加了一些字,万一这些字的颜色在RGBQUAD里没有对应项,那么我这些字就找不到对应的索引值。请问怎么做?谢谢 有简单方法不用,要绕个大圈子去GDI getpixel(),慢且不说,还只能对付ddb...上面那个只需8行代码就搞定的,用你的方法恐怕得转来转去..dib to ddb-->gdi作图-->ddb to dib...good luck.. 呵呵,您有点着急了,我是初学者,刚开始还是想试一下自己的想法,请谅解。您的方法我试过了,确实是很好用,有空我会自习钻研一下那个类的代码,应该封装了不少东西吧,不然几行代码就搞定了。 我再问个问题,如果这次我不在上面写字了,我想把某部分的像素颜色变一下,比如说反色吧。如果还借助你这个IBmp类该怎么做啊? 十分感谢!!! 那个类很简单的,而且比你这:"我本来就是用CFile 打开了一个BMP文件,就是它的BITMAPINFOHEADER,BITMAPFILEHEADER,RGBQUAD,还有实际的图像数据的指针lpBuf四部分的数据我都得到了。" 多不了多少东西.有如它的说明一样,只能打开/保存/显示和写写画画. 要处理位图,其实90%以上都是在处理它的位数据,你用GDI的SetPixel/GetPixel其实也就是在改变它的位数据,不过是选了个最慢的方法而已,通常的方法就是直接对其位数据指针赋值从而改变位图.当然了,你要操作的时候,你必须知道你所要做的算法,就举例你说的反色: 本来反色颇简单的,没记错的话,应该是取原图的pixel的三通道R/G/B,然后用255减去后再赋给原pixel,但你要"局部反色"的话,难听点讲句,你在异想天开~~ 对于8Bit以上(含8Bit灰度),你的"局部反色"和全部反色一样,没有问题,但当8bit或以下时,局部反色就涉及到色彩表溢出的问题,例如1Bit位图:这个位图只含有黑色和红色两种,现在你要把局部的黑色来"反色",得出白色;现在就看出了,原图应该变成3种色了..但那是1Bit位图,怎能容下3种颜色呢?解决的办法估计就只能够"曲线救国",把要"反色"的只反成另一种:也就是黑变红/红变黑..那和反色的意思差远了.(实际上全部反色的话,应该是黑变白,红RGB(0xFF,0,0)变青RGB(0,0xFF,0xFF),那只是改改色彩表的颜色就搞定的玩意) 最后说说256色的标准灰度图的反色,由于这是种像素=灰度且r=g=b的情况,所以你随便乱反局部,都不会导致它的colors table颜色溢出. 当然,有了算法,做起来就简单,举例说说全局反色:伪代码..BOOL FanSe(){ if( GetBitCount() <= 8 ){ LPRGBQUAD lpRGB = GetColorsTable(); DWORD dwNumColors = GetNumColors(); for( i = 0; i < dwNumColors;++i ){ lpRGB[i].rgbBlue = 0xFF = lpRGB[i].rgbBlue; green.. red.. } } // 8 bit or lower end else { LPBYTE lpDibBits = GetBmpBits(); // 取位数据指针操作 BYTE, r, g, b; for( i = 0; i < GetHeight(); ++i ){ for( j = 0; j < GetWidth(); ++j ){ switch(GetBitCount()){ case 16: do this.. break; case 24: do this & this; break; case 32: do this & this & this; break; } // end switch } // end for j } // end for i } // 16bit or up end.}这是全部反色的大约方法,不过无论是"全局"或"局部",靠你自己去实现了,hohoho...貌似偶那附带了个反转的例子就是操作它的位数据指针. lpRGB[i].rgbBlue = 0xFF = lpRGB[i].rgbBlue; //手快快打错.汗应为:lpRGB[i].rgbBlue = 0xFF - lpRGB[i].rgbBlue; 现在我对256色图和24位图都可以做到全局反色了。关于256色图我有两个问题请教一下:1.lambochan,不知你写上去的那些文字是怎么保存的,那些文字完全可以是ColorsTable中没有的颜色。2.对于256色图,不能做任意的图像处理?比如我提取出了一个目标,我想让这个目标用Colorstable外的颜色表示,其它部分还保持原来的颜色,但是最后还是保存为256色图的格式。 关于第二问,如果我不关心最终数据量的大小问题,是不是把256色图保存成24位图的格式就很容易实现该功能了? 谢谢高手们赐教! 自己的方法,不错其实很多win低层实现都是和自己饶来饶去的方法是一样的,只不过他们封装起来了 1: 看上去不变那只不过是被GDI用近似色map了,很简单的,在灰度图上你画条红色的线就知道了,根本没那种颜色的话,它只能用近似色来映射,但灰度图上映射的话,出来的红线肯定是灰色的(因为色彩表里全是灰度)...也就是偶所说的色彩表溢出的问题..2: 答案是一样的,色彩表溢出的话,你要处理后再保存256色只有一种可能:把它转成真彩色做了你的处理后重新量化为8Bit...不过后果是难以预料的,可能因此前后两图面目全非.last: 你转成真彩来做处理的话,那肯定是完全没烦恼(只要你也保存成真彩色) To everybody: 好了,问大家困扰了我很久的问题: 1.我知道图像分类中有256色图,24位图。我这样理解对不对,256色图实际上也就是24位图,它的每个点也是有R,G,B三个值,一般情况下也就是24位,不考虑什么保留位什么的。只不过它只选用了其中的256种颜色而已,所以对应的索引值有256个。有时又称它为8位图,就因为它的索引值是8位。这样理解对不对? 2.有没有256色灰度图这个概念,有的话它的意思是色彩表里一定是(0,0,0),(1,1,1),(2,2,2),(3,3,3)...(255,255,255)?还是这些色彩值仍然是任意的? 我是新手,如果说我的问题很白痴的话我不介意的。欢迎大家解答。 1:256色和24位色唯一相同的地方就是都是BMP以及都是用RGB来显示颜色.不过格式不一样,所以用来保存颜色的方法也不一样.2:当然有,要是灰度图里的话,色彩表里的RGB三通道总是相等的,不过由于各个软件处理灰度图的方法不一样,所以它们在colors table的排位可能是任意的,而标准的灰度图的色彩表应该是按顺序的,也就是色彩表里的各项应该是由1~255,这样的好处是(和乱排的比较):index = 灰度,直接处理index即可,而无须要考虑index所对应的灰度(因为它们是相等的,而乱排的是不等的)..btw:去google一下位图格式look look吧,摸清了就随便搞的,不要嫌闷啊~~~ Combo box问题 如何从一个字符串中获取最后的一部分 求助,使用ATL开发基于Edit的控件不能设置文本自动滚动. 100分求解决一个问题 谁有《C和指针》《C专家编程》的中文电子版啊???? 我刚刚学习vc,有一个问题向各位高手请教 为什么我以下的写操作,有时候好用,有时候出问题? 一个关于NetMessageBufferSend()的问题 sdk的问题,sos!sos!sos! 请问:如何在音乐播放过程中用Ese中止? CMFCToolTar按钮问题,求教 奇怪的问题?
bmp.Load( bmpName );
// 取来GDI作图
CDC *pDrawDC = CDC::FromHandle( bmp.BeginDraw() );
// 设置字体背景透明
// pDrawDC->SetBKMode( TRANSPARENT );
// 字体颜色
// pDrawDC->SetTextColors( RGB( x, x, x ) );
// 写字
// pDrawDC->TextOut( x, y, "hello, world!" );
// 写完释放
bmp.EndDraw();
// 保存.
bmp.Save( bmpName );
简单吧..
还有,IBmp bmp;是什么意思?
这里面最大的问题是将HBitmap对象保存为BMP文件,下面有示例代码:http://blog.csdn.net/wltg2001/archive/2008/04/17/2300258.aspx
http://blog.csdn.net/lambochan/archive/2009/12/31/5115776.aspx然后导入到你的工程(或者自己新建个类copy粘贴),就可以如法炮制了...
fatal error C1083: Cannot open include file: 'IBmp.h': No such file or directory真的不知道为什么,请教楼上。
要把它copy到你工程的目录下.
"No such file or directory"就是找不到文件..估计你是单纯引用没有copy到目录吧.
#include "xxx.h"时,只会在当前目录找文件的
有一点我要说明一下,我本来就是用CFile 打开了一个BMP文件,就是它的BITMAPINFOHEADER,BITMAPFILEHEADER,RGBQUAD,还有实际的图像数据的指针lpBuf四部分的数据我都得到了。之后我用dc在图片上写字,然后用dc.GetPixel去把修改后每点的像素再存放一个lpBuf_new指向的区域。
然后我又用CFile建了一个新的文件,之后把先前得到的修改前BMP文件的BITMAPINFOHEADER,BITMAPFILEHEADER,RGBQUAD用Write函数依次写进这个文件,最后一部分用lpBuf_new代替就得到一个新的文件,这个文件保存的就是修改后的效果。而且有一点我要声明,我刚才处理的是24位彩色图,lpBuf里存放的就是实际的图像的颜色值。
现在问题来了,假如我处理的是256色图,那么这时lpBuf里存放的是索引值,RGBQUAD存放的是真正的颜色值,我还想用类似的方法怎么做。因为我在图像上加了一些字,万一这些字的颜色在RGBQUAD里没有对应项,那么我这些字就找不到对应的索引值。请问怎么做?谢谢
有简单方法不用,要绕个大圈子去GDI getpixel(),慢且不说,还只能对付ddb...
上面那个只需8行代码就搞定的,用你的方法恐怕得转来转去..dib to ddb-->gdi作图-->ddb to dib...
good luck..
我再问个问题,如果这次我不在上面写字了,我想把某部分的像素颜色变一下,比如说反色吧。如果还借助你这个IBmp类该怎么做啊?
十分感谢!!!
那个类很简单的,而且比你这:
"我本来就是用CFile 打开了一个BMP文件,就是它的BITMAPINFOHEADER,BITMAPFILEHEADER,RGBQUAD,还有实际的图像数据的指针lpBuf四部分的数据我都得到了。"
多不了多少东西.有如它的说明一样,只能打开/保存/显示和写写画画.
要处理位图,其实90%以上都是在处理它的位数据,你用GDI的SetPixel/GetPixel其实也就是在改变它的位数据,不过是选了个最慢的方法而已,通常的方法就是直接对其位数据指针赋值从而改变位图.当然了,你要操作的时候,你必须知道你所要做的算法,就举例你说的反色: 本来反色颇简单的,没记错的话,应该是取原图的pixel的三通道R/G/B,然后用255减去后再赋给原pixel,但你要"局部反色"的话,难听点讲句,你在异想天开~~
对于8Bit以上(含8Bit灰度),你的"局部反色"和全部反色一样,没有问题,但当8bit或以下时,局部反色就涉及到色彩表溢出的问题,例如1Bit位图:这个位图只含有黑色和红色两种,现在你要把局部的黑色来"反色",得出白色;现在就看出了,原图应该变成3种色了..但那是1Bit位图,怎能容下3种颜色呢?解决的办法估计就只能够"曲线救国",把要"反色"的只反成另一种:也就是黑变红/红变黑..那和反色的意思差远了.(实际上全部反色的话,应该是黑变白,红RGB(0xFF,0,0)变青RGB(0,0xFF,0xFF),那只是改改色彩表的颜色就搞定的玩意)
最后说说256色的标准灰度图的反色,由于这是种像素=灰度且r=g=b的情况,所以你随便乱反局部,都不会导致它的colors table颜色溢出. 当然,有了算法,做起来就简单,举例说说全局反色:
伪代码..
BOOL FanSe()
{
if( GetBitCount() <= 8 ){
LPRGBQUAD lpRGB = GetColorsTable();
DWORD dwNumColors = GetNumColors();
for( i = 0; i < dwNumColors;++i ){
lpRGB[i].rgbBlue = 0xFF = lpRGB[i].rgbBlue;
green..
red..
}
} // 8 bit or lower end
else {
LPBYTE lpDibBits = GetBmpBits(); // 取位数据指针操作
BYTE, r, g, b;
for( i = 0; i < GetHeight(); ++i ){
for( j = 0; j < GetWidth(); ++j ){
switch(GetBitCount()){
case 16:
do this..
break;
case 24:
do this & this;
break;
case 32:
do this & this & this;
break;
} // end switch
} // end for j
} // end for i
} // 16bit or up end.
}这是全部反色的大约方法,不过无论是"全局"或"局部",靠你自己去实现了,hohoho...
貌似偶那附带了个反转的例子就是操作它的位数据指针.
应为:
lpRGB[i].rgbBlue = 0xFF - lpRGB[i].rgbBlue;
1.lambochan,不知你写上去的那些文字是怎么保存的,那些文字完全可以是ColorsTable中没有的颜色。
2.对于256色图,不能做任意的图像处理?比如我提取出了一个目标,我想让这个目标用Colorstable外的颜色表示,其它部分还保持原来的颜色,但是最后还是保存为256色图的格式。 关于第二问,如果我不关心最终数据量的大小问题,是不是把256色图保存成24位图的格式就很容易实现该功能了?
谢谢高手们赐教!
其实很多win低层实现都是和自己饶来饶去的方法是一样的,只不过他们封装起来了
1: 看上去不变那只不过是被GDI用近似色map了,很简单的,在灰度图上你画条红色的线就知道了,根本没那种颜色的话,它只能用近似色来映射,但灰度图上映射的话,出来的红线肯定是灰色的(因为色彩表里全是灰度)...也就是偶所说的色彩表溢出的问题..
2: 答案是一样的,色彩表溢出的话,你要处理后再保存256色只有一种可能:把它转成真彩色做了你的处理后重新量化为8Bit...不过后果是难以预料的,可能因此前后两图面目全非.
last: 你转成真彩来做处理的话,那肯定是完全没烦恼(只要你也保存成真彩色)
好了,问大家困扰了我很久的问题:
1.我知道图像分类中有256色图,24位图。我这样理解对不对,256色图实际上也就是24位图,它的每个点也是有R,G,B三个值,一般情况下也就是24位,不考虑什么保留位什么的。只不过它只选用了其中的256种颜色而已,所以对应的索引值有256个。有时又称它为8位图,就因为它的索引值是8位。这样理解对不对?
2.有没有256色灰度图这个概念,有的话它的意思是色彩表里一定是(0,0,0),(1,1,1),(2,2,2),(3,3,3)...(255,255,255)?还是这些色彩值仍然是任意的? 我是新手,如果说我的问题很白痴的话我不介意的。欢迎大家解答。
2:当然有,要是灰度图里的话,色彩表里的RGB三通道总是相等的,不过由于各个软件处理灰度图的方法不一样,所以它们在colors table的排位可能是任意的,而标准的灰度图的色彩表应该是按顺序的,也就是色彩表里的各项应该是由1~255,这样的好处是(和乱排的比较):index = 灰度,直接处理index即可,而无须要考虑index所对应的灰度(因为它们是相等的,而乱排的是不等的)..btw:去google一下位图格式look look吧,摸清了就随便搞的,不要嫌闷啊~~~