CImage访问像素及其像素操作总结
MSDN的代码
- 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倍
直接访问内存地址的另一种方式:
int i,j,temp; int pixel[4]; int width = yuantu.GetWidth(); int height = yuantu.GetHeight(); int widthBytes = yuantu.GetPitch(); bianyuantu.Create(width,height,yuantu.GetBPP()); if(yuantu.IsIndexed()) { yuantu.GetColorTable(0,256,colorTable); bianyuantu.SetColorTable(0,256,colorTable); } BYTE *pYuantuData = (BYTE*)yuantu.GetBits(); BYTE *pBianyuantuData =(BYTE*)bianyuantu.GetBits(); for(j=0;j<height-1;j++) { for(i=0;i<width-1;i++) { pixel[0]=pYuantuData[j*widthBytes+i]; pixel[1]=pYuantuData[j*widthBytes+i+1]; pixel[2]=pYuantuData[(j+1)*widthBytes+i]; pixel[3]=pYuantuData[(j+1)*widthBytes+i+1]; temp=(int)sqrt((double)((pixel[0]-pixel[3])*(pixel[0]-pixel[3]) +(pixel[1]-pixel[2])*(pixel[1]-pixel[2]))); //罗伯特算子 pBianyuantuData[j*widthBytes+i]=temp; } }
彩色图像转化为灰度图的处理方式
//真彩色图像变为灰度图,直接修改像素点的值
- void PixelsChangedToGray(CImage *pImage)
- {
- int nByte,j,i,nWidth,nHeight,nBytesPerPixel;
- BYTE *pPixelLine,cNewPixelValue;
- nWidth=pImage->GetWidth(); nHeight=pImage->GetHeight();
- nBytesPerPixel= pImage->GetBPP()/8;
- for (i=0;i<nHeight;i++){
- pPixelLine =(BYTE*) pImage->GetPixelAddress(0,i);
- nByte=0;
- for (j=0;j<nWidth;j++){ cNewPixelValue=(BYTE)(0.11*pPixelLine[nByte]
- +0.59*pPixelLine[nByte+1]
- +0.30*pPixelLine[nByte+2]);
- pPixelLine[nByte] = pPixelLine[nByte+1] = pPixelLine[nByte+2]
- = cNewPixelValue;
- nByte+=nBytesPerPixel;
- }
- }
- }
//非真彩色图像变为灰度图,修改调色板信息
- void PaletteChangedToGray(CImage *pImage)
- {
- RGBQUAD ColorTabs[256];
- int i,nColorTableEntries,nNewGrayColor;
- nColorTableEntries=pImage->GetMaxColorTableEntries();
- pImage->GetColorTable(0,nColorTableEntries,ColorTabs);
- for (i=0;i<nColorTableEntries;i++){
- nNewGrayColor=(int)(0.11*ColorTabs[i].rgbBlue
- + 0.59*ColorTabs[i].rgbGreen
- + 0.30*ColorTabs[i].rgbRed);
- ColorTabs[i].rgbBlue = (BYTE)nNewGrayColor;
- ColorTabs[i].rgbGreen = (BYTE)nNewGrayColor;
- ColorTabs[i].rgbRed = (BYTE)nNewGrayColor;
- }
- pImage->SetColorTable(0,nColorTableEntries,ColorTabs);
- }