CImage类简介与使用

CImage类简介与使用

CImage类的成员可分为连接与创建、输入与输出、位图类型与参数,以及图形绘制与位图块传送等4类。
(1) 连接与创建
Attach 将一个DIB(或DDB)位图与CImage对象相连接
Detach 位图与CImage对象相分离
Create 创建一个DIB位图并将它与已有CImage对象相连接
Destroy 位图与Cimage对象相分离并删除
(2) 输入与输出
GetImporterFilterString 返回系统支持的输入文件格式类型及其描述
GetExporterFilterString 返回系统支持的输出文件格式类型及其描述
Load 读入指定图像文件中的图像
LoadFromResource 读入指定资源文件中的图像
Save 按指定类型保存图像,文件名中不能省略后缀
IsNull 判别源图像文件是否已经读入
(3) 位图类型与参数
GetWidth 返回当前图像的宽度(以像素为单位)
GetHeight 返回当前图像的高度
GetBPP 返回当前图像的每像素位数
GetBits 返回当前图像像素数据的指针
GetPitch 返回相邻两行像素首地址之间的间隔
GetPixelAddress 返回指定像素数据存放位置的存储地址
GetMaxColorTableEntries返回调色板单元数
IsDibSection 确定位图是否为DIB位图
IsIndexed 判别位图中是否有调色板
IsTransparencySupported判别应用程序是否支持透明位图
AlphaBlend 是否支持透明或半透明显示的状态
(4) 图形绘绘与位图块传送
GetDC 返回当前位图的设备描述表
ReleaseDC 释放设备描述表
GetPixel 返回指定位置像素的颜色
SetPixel 设置指定位置像素的颜色
SetPixelIndexed 设置指定位置像素颜色的索引值
SetPixelRGB 设置指定位置像素的红绿蓝分量
GetColorTable 获取调色板颜色分量(红、绿、蓝)值
SetColorTable 设置调色板颜色分量(红、绿、蓝)值
SetTransparentColor 设置透明颜色的索引值,只能有一种颜色可为透明
Draw 从源矩形复制到目标矩形,支持伸缩、a融合与透明
BitBlt 位图的一个举行区域复制到另一位图上的制定区域
MaskBlt 为图块传送时须与指定的模板图像做逻辑操作
PlgBlt 为图的矩形区域到另一位图上平行四边形间的位块传输
StretchBlt 从源矩形复制到目标矩形,支持伸缩
TransparentBlt 位图块传送时复制带透明色的位图


FAQ:
1. 关于GetBits()函数的使用.对于一幅DIB图像来说,图像的左下角为像素数据的起点。通常我们会认为GetBits()函数返回的是图像左下角的数据指针,但是CImage实现却不是这样。GetBits()返回的是图像左上角的像素数据指针。从这个角度上来讲,它的功能等效于函数 GetPixelAddress(0,0)调用。而且CImage的成员函数中坐标是以左上角为坐标原点来表示的。

   2. 关于SetPixelIndexed()函数的使用. 从函数名我们可以得知,该函数应该应用于非真彩色图像,特别是8位的图像。在测试该函数时,发现应用于8位BMP图像时,不管设置什么索引值,操作后的结果显示索引值变成了0。这个现象确实让人匪夷所思。不知道是不是CImage类的该函数设计有问题。当然,如果将它不合理地应用于真彩色图像,操作的结果还是黑色。

   3. 另外,CImage类中还有一些函数,譬如SetPixel()和SetPixelRGB()函数,理论上应该将它们应用于真彩色图像,但是如果强硬的将它们应用于非真彩色图像(测试中将它们应用于8位BMP图像),操作结果显示设置的值都会被“合理”的变成灰阶数据,比如说,如果我们设置RGB值为 (180,0,0),操作结果为调色板里的数据变为RGB(60,60,60).

4. 直接调用CImage类的GetPixel和SetPixel效率是很低的, 如果要循环遍历所有Pixels的话,需要用GetPixelAddress直接取得像素数据的存储地址, 然后进行操作。这种方法有个问题: How to handle the PixelAddresses correctly with diffrent kinds of BPPs (Bits Per Pixel).
   For 24 BPP Images:
       for setting
   inline void setPixel(int x, int y, COLORREF &c)
   {
    BYTE *p = (BYTE*)imgage.GetPixelAddress(x, y);
    *p++ = GetRValue(c);
    *p++ = GetGValue(c);
    *p = GetBValue(c);
   }


   & for getting a pixel

   inline COLORREF getPixel(int x, int y) const
   {
    return(*(COLORREF*)(image.GetPixelAddress(x, y)));
   }

For 16 BPP Images:
   16-bit images would be easy to support, and they are much similar to 32-bit images.
   16-bit colour pixels are stored in 5-6-5 format (five bits for red, six bits for green, and five for blue).

   inline void setPixel(int x, int y, COLORREF &c)
   {
    WORD *p = (WORD*)imgage.GetPixelAddress(x, y);
    *p = ((GetRValue(c) >> 3) << 11) + ((GetGValue(c) >> 2) << 5) + (GetBValue(c) >> 3);
   }

   inline COLORREF getPixel(int x, int y) const
   {
    WORD *p = (WORD*)image.GetPixelAddress(x, y);
    return RGB(((*p & 0xF800) >> 8), ((*p & 0x07E0) >> 3), ((*p & 0x001F) << 3));
   }

转自http://hi.baidu.com/%C6%BF%D6%D0%B5%C4%C5%AE%CE%D7/blog/item/ca620e4bd8bc222409f7ef06.html

1.在CImage类中,对像素访问最方便的是用GetPixel,MSDN中给出的例子simpleImage的代码如下:

   COLORREF pixel;
   int maxY = imgOriginal.GetHeight(), maxX = imgOriginal.GetWidth();
   byte r,g,b,avg;

   for (int y=0; y<maxY; y++) {
    for (int x=0; x<maxX; x++) {
     pixel = imgOriginal.GetPixel(x,y);
     r = GetRValue(pixel);
     g = GetGValue(pixel);
     b = GetBValue(pixel);
     avg = (r+ g+ b)/3;
     imgOriginal.SetPixelRGB(x,y,avg,avg,avg);

}}

发现执行速度特别慢。因为每次调用getpixel,都包含着程序的进栈和出栈。//函数参数传递

所以,面对大量需要处理的数据,采用直接访问内存地址的方法。

   byte* pRealData;
   pRealData=(byte*)imgOriginal.GetBits();

   int pit=imgOriginal.GetPitch();

   int bitCount=imgOriginal.GetBPP()/8;

   for (int y=0; y<maxY; y++) {
    for (int x=0; x<maxX; x++) {

int grayVal=(int)(int)(*(pRealData + pit*y + x*bitCount))*0.3
      +
      (int)(int)(*(pRealData + pit*y + x*bitCount +1))*0.59
      +
      (int)(int)(*(pRealData + pit*y + x*bitCount +2))*0.11;

     *(pRealData + pit*y + x*bitCount)=grayVal;
     *(pRealData + pit*y + x*bitCount +1)=grayVal;
     *(pRealData + pit*y + x*bitCount +2)=grayVal;

//如果是8位灰度图像,直接读取一个BYTE位为灰度值

//如果是24位RGB图像,则依次读取pixAddr,pixAddr+1,pixAddr+2为B、G、R分量值

}}

用两种方法对同一张图片(3264*2448像素)进行处理,前者需要1分钟,后者只需1秒左右。

所以,后者比前者至少快60倍。

2. 如果处理比较复杂的话,可把所有点颜色全部读到一个二维数组里面,然后对这个数组进行读写和处理。 再把处理后的图像显示出来。这样速度才会快!

本文来自CSDN博客,转载请标明出处:http://blog.csdn.net/gaowen1860/archive/2009/09/18/4566579.aspx

CImage支持JPEG,GIF,BMP,PNG (Portable Network Graphics)等各种图像格式,它将图像载入内存后是一个DIB(Device-Independent Bitmap),可以通过 .GetWidth(),.GetHeight()函数获得图像的宽和高(像素),可以用.Getpixel(int x,int y)获得COLORREF类型的颜色数据,必要时可用类型转换函数与RGB类型互相转换。程序例:

CImage Timg ; 
 COLORREF color ; 
 BYTE r ,g ,b ; 
 int i ,j ,width ,height ;

Timg.Load("test.JPG"); //load an image

width = Timg.GetWidth(); //get width of image 
 height = Timg.GetHeight(); //get height of image

for(i = 0;i < width;i++)
 for(j = 0;j < height; j++){

 color = Timg.GetPixel(i,j); //get pixel data from image

 r = GetRValue(color); //get R value from color
 g = GetGValue(color); //get G value from color
 b = GetBValue(color); //get B value from color

 }
 ......

COLORREF color1 = RGB(BYTE Red,BYTE Green,BYTE Blue); //RGB to COLORREF

也可以用GetBits(),GetPitch()来获得图像数据。

 BYTE *pImgData = (BYTE *)Timg.GetBits();

 int nRowByte =Timg.GetPitch();

 存取第i行,第j列像素:

 8位灰度图像: *(pImgData + j * nRowByte + i)

 24位彩色图像: *(pImgData + j * nRowByte + i*3)

 *(pImgData + j * nRowByte + i*3 +1)

 *(pImageData + j * nRowByte + i*3 +2)

通过GetPitch()函数获得图像字节数返回值为正时,bitmap是top -down,即DIB从左上→右下,此时上面三个式子从上到下依次为R,G,B,如果返回的是负值,bitmap是bottom-up, DIB从左下→右上(上面三个式子从上到下为B,G,R)。

以上两种RGB取值方法中,由于第一种函数调用比较花时间,用第二种坐标取值的方法,运行速度会明显提高。同样,坐标赋值也比用Setpixel函数赋值来得快。

来自:  http://hi.baidu.com/szcitysg/blog/item/58b69cccbef5581a7e3e6f65.html
  

你可能感兴趣的:(c,测试,存储,NetWork,byte,图形)