将RGB彩色图像转为8位的索引颜色
先定义一个宏
// Greyscale conversion
#define GREY(r, g, b) (BYTE)(((WORD)r * 77 + (WORD)g * 150 + (WORD)b * 29) >> 8
//#define GREY(r, g, b) (BYTE)(((WORD)r * 169 + (WORD)g * 256 + (WORD)b * 87) >> 9)
// Grayscale, 将RGB转为8bit
void GDIPlusImage::IPFuncGrayscale()
{
Bitmap* ima = this->m_pBitmap;
if (!ima) {
return;
}
// Build new 8bpp greyscale bitmap
int width = ima->GetWidth();
int height = ima->GetHeight();
Rect rect(0, 0, width, height);
BitmapData bitmapData_org, bitmapData_new;
Bitmap *pGrayImg = new Bitmap(width, height,PixelFormat8bppIndexed);
ColorPalette *pal = (ColorPalette *)malloc(sizeof(ColorPalette)+256*sizeof(ARGB));
pal->Count = 256;
pal->Flags = 2;
for (int i = 0; i < 256; i++)
{
pal->Entries[i] = Color::MakeARGB(255,i,i,i);
}
pGrayImg->SetPalette(pal);
pGrayImg->LockBits(&rect,
ImageLockModeWrite,
PixelFormat8bppIndexed,
&bitmapData_new); //锁定位图,然后对其进行读写内存操作,相关信息保存到BitmapData中
Status iSucess = ima->LockBits(
&rect,
ImageLockModeRead | ImageLockModeWrite,
ima->GetPixelFormat() ,
&bitmapData_org);
BYTE *_pixels = (BYTE*)bitmapData_org.Scan0; //原图rect区域内存位置的起始指针,以BYTE作为单元类型
BYTE *_newpixles = (BYTE*)bitmapData_new.Scan0; //目标位图rect区域的起始指针
BYTE _grey;
// build pixles
switch(ima->GetPixelFormat()) //像素格式不同,灰度化处理方式也不同
{
case PixelFormat24bppRGB:
{
int _strideoff24 = bitmapData_org.Stride - 3*width;
int _strideoff8 = bitmapData_new.Stride - width;
// 灰度化
for (int i=0; i < height; i++)
{
for (int j=0;j < width;j++)
{
BYTE* _pixels_b; //b
BYTE* _pixels_g; //g
BYTE* _pixels_r; //r
_pixels_b = _pixels++; //blue
_pixels_g = _pixels++; //green
_pixels_r = _pixels++; //red
_grey = GREY(*_pixels_r, *_pixels_g, *_pixels_b);
*_newpixles = _grey; //根据红绿蓝求出此像素的灰度值
_newpixles += 1;
}
_pixels += _strideoff24;
_newpixles += _strideoff8;
}
}
break;
case PixelFormat32bppARGB:
{
int _strideoff32 = bitmapData_org.Stride - 4*width;
int _strideoff8 = bitmapData_new.Stride - width;
// 灰度化
for (int i=0;i<height;i++)
{
for (int j=0;j<width;j++)
{
BYTE* _pixels_b;
BYTE* _pixels_g;
BYTE* _pixels_r;
_pixels_b = _pixels++; //blue
_pixels_g = _pixels++; //green
_pixels_r = _pixels++; //red
_grey = GREY(*_pixels_r, *_pixels_g, *_pixels_b);
*_newpixles = _grey;
_pixels ++; //忽略alpha位置
_newpixles += 1;
}
_pixels += _strideoff32;
_newpixles += _strideoff8;
}
}
break;
case PixelFormat8bppIndexed: // 因为比Clone(rect,ima->GetPixelFormat())要快
{
// 直接复制
memcpy(_newpixles, _pixels, height * bitmapData_new.Stride);
}
break;
default:
break;
}
ima->UnlockBits(&bitmapData_org);
pGrayImg->UnlockBits(&bitmapData_new);
free (pal); // 释放掉malloc开辟的空间
m_pBitmap = pGrayImg;
}