灰度化图像时,一定要根据原图像的像素格式,采取与之对应的灰度化方法,否则会出问题。
此函数灰度化原图像,并把灰度化后的图像保存在*pDesBitmap中( 注:有内存泄露,因为没有及时释放开辟的调色板空间,下面有修正版本)
- void NewImageView::ToGray(Bitmap * pOrgBitmap,Bitmap **pDesBitmap)
- {
-
- int width=pOrgBitmap->GetWidth();
- int height=pOrgBitmap->GetHeight();
-
- switch(pOrgBitmap->GetPixelFormat())
- {
- case PixelFormat24bppRGB:
- {
- Rect rect(0,0,width,height);
- BYTE byte;
- 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=0;
-
- for (int m=0;m<256;m++)
- {
- pal->Entries[m]=Color::MakeARGB(255,m,m,m);
- }
-
- pGrayImg->SetPalette(pal);
-
- pGrayImg->LockBits(&rect,ImageLockModeWrite,PixelFormat8bppIndexed,&bitmapData_new);
- Status iSucess=pOrgBitmap->LockBits(
- &rect,
- ImageLockModeWrite,
- PixelFormat24bppRGB ,
- &bitmapData_org);
-
- BYTE *p=(BYTE*)bitmapData_org.Scan0;
- BYTE *q=(BYTE*)bitmapData_new.Scan0;
- BYTE *pt=p, *qt=q;
- BYTE val;
-
- for (int i=0;i<height;i++)
- {
- pt=p+i*bitmapData_org.Stride;
- qt=q+i*bitmapData_new.Stride;
-
- for (int j=0;j<width;j++)
- {
- val=*(pt)*0.114+(*(pt+1))*0.587+(*(pt+2))*0.299;
- if (val>255)
- {
- val=255;
- }
-
- if (val<0)
- {
- val=0;
- }
-
- *qt=val;
- pt+=3;
- qt+=1;
-
- }
- }
- pOrgBitmap->UnlockBits(&bitmapData_org);
- pGrayImg->UnlockBits(&bitmapData_new);
- *pDesBitmap=pGrayImg;
- }
- break;
-
- case PixelFormat32bppARGB:
- {
- Rect rect(0,0,width,height);
- BYTE byte;
- 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=0;
-
- for (int m=0;m<256;m++)
- {
- pal->Entries[m]=Color::MakeARGB(255,m,m,m);
- }
-
- pGrayImg->SetPalette(pal);
-
- pGrayImg->LockBits(&rect,ImageLockModeWrite,PixelFormat8bppIndexed,&bitmapData_new);
-
-
- Status iSucess=pOrgBitmap->LockBits(
- &rect,
- ImageLockModeWrite,
- PixelFormat32bppARGB ,
- &bitmapData_org);
-
- BYTE *p=(BYTE*)bitmapData_org.Scan0;
- BYTE *q=(BYTE*)bitmapData_new.Scan0;
- BYTE *pt=p, *qt=q;
- BYTE val;
-
- for (int i=0;i<height;i++)
- {
- pt=p+i*bitmapData_org.Stride;
- qt=q+i*bitmapData_new.Stride;
-
- for (int j=0;j<width;j++)
- {
- val=*(pt+1)*0.114+(*(pt+2))*0.587+(*(pt+3))*0.299;
- if (val>255)
- {
- val=255;
- }
-
- if (val<0)
- {
- val=0;
- }
-
- *qt=val;
- pt+=4;
- qt+=1;
- }
- }
- pOrgBitmap->UnlockBits(&bitmapData_org);
- pGrayImg->UnlockBits(&bitmapData_new);
- *pDesBitmap=pGrayImg;
- }
- break;
- case PixelFormat8bppIndexed:
-
-
-
- {
- Rect rect(0,0,width,height);
- BYTE byte;
- 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=0;
- for (int m=0;m<256;m++)
- {
- pal->Entries[m]=Color::MakeARGB(255,m,m,m);
- }
- pGrayImg->SetPalette(pal);
- pGrayImg->LockBits(&rect,ImageLockModeWrite,PixelFormat8bppIndexed,&bitmapData_new);
- Status iSucess=pOrgBitmap->LockBits(
- &rect,
- ImageLockModeWrite,
- PixelFormat8bppIndexed,
- &bitmapData_org);
-
- BYTE *p=(BYTE*)bitmapData_org.Scan0;
- BYTE *q=(BYTE*)bitmapData_new.Scan0;
- BYTE *pt=p, *qt=q;
- BYTE val;
-
- for (int i=0;i<height;i++)
- {
- pt=p+i*bitmapData_org.Stride;
- qt=q+i*bitmapData_new.Stride;
- for (int j=0;j<width;j++)
- {
- val=*pt;
- *qt=val;
- pt+=1;
- qt+=1;
- }
- }
- pOrgBitmap->UnlockBits(&bitmapData_org);
- pGrayImg->UnlockBits(&bitmapData_new);
- *pDesBitmap=pGrayImg;
- }
- break;
- default:
- *pDesBitmap=pOrgBitmap;
- break;
- }
-
- }
调用方式如下:
- if (m_pMemBmp)
- {
- delete m_pMemBmp;
- m_pMemBmp=NULL;
- }
-
-
- Rect rect(0,0,m_pImage->GetWidth(),m_pImage->GetHeight());
- m_pMemBmp=m_pImage->Clone(rect,m_pImage->GetPixelFormat());
- Bitmap *p=m_pMemBmp;
- ToGray(m_pMemBmp,&m_pMemBmp);
- delete p;
-
- ReDraw();
- InvalidateRect(m_ClientRect);
上述灰度化图像有内存泄露问题 ,因为没有及时free掉开辟出来的调色板空间。
修改后的灰度化函数如下,只是添加了free (pal); // 释放掉了malloc开辟的空间
此函数将原图像灰度化,并把灰度化后的图像保存在*pDesBitmap中
- void NewImageView::ToGray(Bitmap * pOrgBitmap,Bitmap **pDesBitmap)
- {
-
- int width=pOrgBitmap->GetWidth();
- int height=pOrgBitmap->GetHeight();
-
- switch(pOrgBitmap->GetPixelFormat())
- {
- case PixelFormat24bppRGB:
- {
- Rect rect(0,0,width,height);
- BYTE byte;
- 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 m=0;m<256;m++)
- {
- pal->Entries[m]=Color::MakeARGB(255,m,m,m);
- }
-
- pGrayImg->SetPalette(pal);
- free (pal);
- pGrayImg->LockBits(&rect,ImageLockModeWrite,PixelFormat8bppIndexed,&bitmapData_new);
- Status iSucess=pOrgBitmap->LockBits(
- &rect,
- ImageLockModeWrite,
- PixelFormat24bppRGB ,
- &bitmapData_org);
-
- BYTE *p=(BYTE*)bitmapData_org.Scan0;
- BYTE *q=(BYTE*)bitmapData_new.Scan0;
- BYTE *pt=p, *qt=q;
- BYTE val;
-
- for (int i=0;i<height;i++)
- {
- pt=p+i*bitmapData_org.Stride;
- qt=q+i*bitmapData_new.Stride;
-
- for (int j=0;j<width;j++)
- {
- val=*(pt)*0.114+(*(pt+1))*0.587+(*(pt+2))*0.299;
- if (val>255)
- {
- val=255;
- }
-
- if (val<0)
- {
- val=0;
- }
-
- *qt=val;
- pt+=3;
- qt+=1;
-
- }
- }
- pOrgBitmap->UnlockBits(&bitmapData_org);
- pGrayImg->UnlockBits(&bitmapData_new);
- *pDesBitmap=pGrayImg;
- }
- break;
-
- case PixelFormat32bppARGB:
- {
- Rect rect(0,0,width,height);
- BYTE byte;
- 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=0;
-
- for (int m=0;m<256;m++)
- {
- pal->Entries[m]=Color::MakeARGB(255,m,m,m);
- }
-
- pGrayImg->SetPalette(pal);
- free (pal);
-
- pGrayImg->LockBits(&rect,ImageLockModeWrite,PixelFormat8bppIndexed,&bitmapData_new);
- Status iSucess=pOrgBitmap->LockBits(
- &rect,
- ImageLockModeWrite,
- PixelFormat32bppARGB ,
- &bitmapData_org);
-
- BYTE *p=(BYTE*)bitmapData_org.Scan0;
- BYTE *q=(BYTE*)bitmapData_new.Scan0;
- BYTE *pt=p, *qt=q;
- BYTE val;
-
- for (int i=0;i<height;i++)
- {
- pt=p+i*bitmapData_org.Stride;
- qt=q+i*bitmapData_new.Stride;
-
- for (int j=0;j<width;j++)
- {
- val=*(pt+1)*0.114+(*(pt+2))*0.587+(*(pt+3))*0.299;
- if (val>255)
- {
- val=255;
- }
-
- if (val<0)
- {
- val=0;
- }
-
- *qt=val;
- pt+=4;
- qt+=1;
- }
- }
- pOrgBitmap->UnlockBits(&bitmapData_org);
- pGrayImg->UnlockBits(&bitmapData_new);
- *pDesBitmap=pGrayImg;
- }
- break;
- case PixelFormat8bppIndexed:
-
-
-
- {
- Rect rect(0,0,width,height);
- BYTE byte;
- 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=0;
- for (int m=0;m<256;m++)
- {
- pal->Entries[m]=Color::MakeARGB(255,m,m,m);
- }
- pGrayImg->SetPalette(pal);
- free (pal);
-
- pGrayImg->LockBits(&rect,ImageLockModeWrite,PixelFormat8bppIndexed,&bitmapData_new);
- Status iSucess=pOrgBitmap->LockBits(
- &rect,
- ImageLockModeWrite,
- PixelFormat8bppIndexed,
- &bitmapData_org);
-
- BYTE *p=(BYTE*)bitmapData_org.Scan0;
- BYTE *q=(BYTE*)bitmapData_new.Scan0;
- BYTE *pt=p, *qt=q;
- BYTE val;
-
- for (int i=0;i<height;i++)
- {
- pt=p+i*bitmapData_org.Stride;
- qt=q+i*bitmapData_new.Stride;
- for (int j=0;j<width;j++)
- {
- val=*pt;
- *qt=val;
- pt+=1;
- qt+=1;
- }
- }
- pOrgBitmap->UnlockBits(&bitmapData_org);
- pGrayImg->UnlockBits(&bitmapData_new);
- *pDesBitmap=pGrayImg;
- }
- break;
- default:
- *pDesBitmap=pOrgBitmap;
- break;
- }
-
- }
使用free (pal); // 释放掉malloc开辟的空间 。
因为SetPalette(pal);已经将调色板信息放入位图中了,所以NEW 出来的这个调色板已经不需要了,因此要及时释放资源。
既然能将调色板信息直接放入位图中,那是不是也可以将调色板设置成局部变量呢?
- ColorPalette pal;
- pal.Count=256;
- pal.Flags=0;
- for (int m=0;m<256;m++)
- pal.Entries[m]=Color::MakeARGB(255,m,m,m);
- pGrayImg->SetPalette(&pal);
运行时,虽不报错,但是不显示图像,而且直接程序就退出了。 这是什么原因呢?
看下调色板的定义:
- typedef struct {
- UINT Flags;
- UINT Count;
- ARGB Entries[1];
- } ColorPalette;
其中,颜色矩阵大小为1,这是需要我们手动开辟空间更改的,所以将调色板设置成局部变量,而不给颜色矩阵开辟空间,直接访问pal[i]的话,便会出错。
|