1. 程式人生 > >24位點陣圖轉成8位灰度點陣圖

24位點陣圖轉成8位灰度點陣圖

24位轉8位灰度比較簡單,先設定調色盤,如下樣子

(0,0,0,0)(1,1,1,0)(2,2,2,0)……一共256個,用公式gray = (0.114*Blue+0.587*Green+0.299*Red)得到的gray為該畫素點在8位點陣圖中調色盤的索引,所以,只要把24位中每個畫素點中的資料按公式算出索引,再寫入,就完成了,程式碼如下:

void CDib::ConverTo8BitGray()
{
 //24位轉換為8位灰度
 LPBITMAPINFOHEADER  lpbi;
 if(!hdib)
  return;
 lpbi = (BITMAPINFOHEADER*)hdib;
 int height = lpbi->biHeight;
 //兩個寬度
 LONG lLineBytes24=((lpbi->biWidth*24+31)/32*4);
 LONG lLineBytes8=((lpbi->biWidth*8+31)/32*4);
 //源影象的指標,申請一塊足夠大的記憶體
 BYTE* srcBits ;//= (BYTE*)malloc(lLineBytes24*height);
 //使其指向源影象的影象資料起始地址
 srcBits = (BYTE*)lpbi+sizeof(BITMAPINFOHEADER);
 //轉換後的影象資料指標(大小為圖片大小和調色盤大小之和
 int iPaletteSize = sizeof(RGBQUAD)*256;//調色盤大小
 BYTE* dstBits = (BYTE*)malloc(iPaletteSize+lLineBytes8*height);
 RGBQUAD* pRGB = (RGBQUAD *)dstBits;//調色盤指標,指向資料部分開始地址
 //寫入調色盤資料
 for(int i=0; i<256; i++)
 {
  pRGB->rgbBlue = pRGB->rgbGreen = pRGB->rgbRed = i;
  pRGB->rgbReserved = 0;
  pRGB++;
 }
 for(int y=0; y<height; y++)
 {
  for(int x=0, n=0; x<lLineBytes24; x+=3)
  {
   BYTE B = *(srcBits+lLineBytes24*y+x);//藍
   BYTE G = *(srcBits+lLineBytes24*y+x+1);//綠
   BYTE R = *(srcBits+lLineBytes24*y+x+2);//紅
   int gray = (int)(0.114*B+0.587*G+0.299*R);//灰度公式
   *(dstBits + iPaletteSize + lLineBytes8*y + n) = gray;//寫入灰度值
   n++;
  }
 }
 //8位BMP的資訊頭
 BITMAPINFOHEADER bi;
 bi.biBitCount=8;
 bi.biClrImportant=0;
 bi.biClrUsed=0;
 bi.biCompression=0L;
 bi.biHeight=Height();
 bi.biPlanes=1;
 bi.biSize=sizeof(BITMAPINFOHEADER);
 bi.biSizeImage=Height()*lLineBytes24;
 bi.biWidth=Width();
 bi.biXPelsPerMeter=0;
 bi.biYPelsPerMeter=0;
 SetBitmapinfoAndBits(bi, dstBits);
 CString FileName;
 strFileName.Delete(strFileName.GetLength()-4, 4);
 FileName.Format("%s的8位灰度圖.bmp",strFileName);
 //呼叫儲存檔案函式
 SaveFile(FileName);
 //收尾清除指標記憶體
 //free(srcBits);
 srcBits = NULL;
 free(dstBits);
 dstBits = NULL;
 AfxMessageBox("已經轉換成8位灰度圖,另存為:"+FileName);
}

關於讀取儲存設定等會在別的文章中寫