日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

使用GDI+保存图像为8bpp的灰度图像

發布時間:2023/12/15 编程问答 24 豆豆
生活随笔 收集整理的這篇文章主要介紹了 使用GDI+保存图像为8bpp的灰度图像 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

使用GDI+保存圖像為8bpp的灰度圖像,GDI+真的有些特殊。。。。。


// Greyscale conversion #define GREY(r, g, b) (BYTE)(((WORD)r * 77 + (WORD)g * 150 + (WORD)b * 29) >> 8) // .299R + .587G + .114B //#define GREY(r, g, b) (BYTE)(((WORD)r * 169 + (WORD)g * 256 + (WORD)b * 87) >> 9) // .33R + 0.5G + .17B

// BOOL GDIPlusImage::SaveToFileWith8pp(TCHAR *pszPath) // 功能:保存圖片為8位的灰度圖像 // 參數: pszPath要保存的文件名 BOOL GDIPlusImage::SaveToFileWith8pp(TCHAR *pszPath) {Bitmap *ima = this->m_pBitmap; // GDIPlusImage的Bitmap對象if (!ima || !pszPath || !*pszPath){return FALSE;}int width = m_pBitmap->GetWidth();int height = m_pBitmap->GetHeight();int bitcount = 8; //1, 4, 8, 24, 32////Build bitmap headerBITMAPFILEHEADER bitmapFileHeader; BITMAPINFOHEADER bitmapInfoHeader; BYTE rgbquad[4]; // RGBQUADint index = 0;DWORD stride = ((bitcount*width + 31)/32)*4; //每行都是4的倍數,或者說是DWORD大小的倍數switch(bitcount) { case 1: index = 2; bitmapFileHeader.bfOffBits = (DWORD)(sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFOHEADER) + 2*4); break; case 4: index = 16; bitmapFileHeader.bfOffBits = (DWORD)(sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFOHEADER) + 16*4); break; case 8: index = 256; bitmapFileHeader.bfOffBits = (DWORD)(sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFOHEADER) + 256*sizeof(RGBQUAD)); break; case 24: case 32: index = 0; bitmapFileHeader.bfOffBits = (DWORD)(sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFOHEADER)); break; default:break;} //構造Bitmap文件頭BITMAPFILEHEADER bitmapFileHeader.bfType = 0x4d42; // 很重要的標志位 BM 標識bitmapFileHeader.bfSize = (DWORD)(bitmapFileHeader.bfOffBits + height * stride); //bmp文件長度 bitmapFileHeader.bfReserved1 = 0; bitmapFileHeader.bfReserved2 = 0; //構造Bitmap文件信息頭BITMAPINFOHEADER bitmapInfoHeader.biSize = sizeof(BITMAPINFOHEADER); bitmapInfoHeader.biWidth = width; bitmapInfoHeader.biHeight = height; bitmapInfoHeader.biPlanes = 1; bitmapInfoHeader.biBitCount = bitcount;bitmapInfoHeader.biCompression = BI_RGB; // 未壓縮bitmapInfoHeader.biSizeImage = height * stride; bitmapInfoHeader.biXPelsPerMeter = 3780; bitmapInfoHeader.biYPelsPerMeter = 3780; bitmapInfoHeader.biClrUsed = 0; bitmapInfoHeader.biClrImportant = 0; //創建BMP內存映像,寫入位圖頭部BYTE *pMyBmp = new BYTE[bitmapFileHeader.bfSize]; // 我的位圖pMyBmpBYTE *curr = pMyBmp; // curr指針指示pMyBmp的位置memset(curr, 0, bitmapFileHeader.bfSize); //寫入頭信息 memcpy(curr, &bitmapFileHeader,sizeof(BITMAPFILEHEADER));curr = pMyBmp + sizeof(BITMAPFILEHEADER); memcpy(curr, &bitmapInfoHeader,sizeof(BITMAPINFOHEADER)); curr += sizeof(BITMAPINFOHEADER);//構造調色板 if(8 == bitcount) {rgbquad[3] = 0; //rgbReservedfor(int i = 0; i < 256; i++) { rgbquad[0] = rgbquad[1] = rgbquad[2] = i; memcpy(curr, rgbquad, sizeof(RGBQUAD)); curr += sizeof(RGBQUAD); } }else if (4 == bitcount){rgbquad[3] = 0;for (int i = 0; i < 16; i++){rgbquad[0] = rgbquad[1] = rgbquad[2] = i; memcpy(curr, rgbquad, sizeof(RGBQUAD)); curr += sizeof(RGBQUAD); }}else if(1 == bitcount) { rgbquad[3] = 0; //rgbReservedfor(int i = 0; i < 2; i++) { rgbquad[0] = rgbquad[1] = rgbquad[2] = (256 - i)%256; memcpy(curr, rgbquad, sizeof(RGBQUAD)); curr += sizeof(RGBQUAD); } }//用GDI+加載數據源,也可以是其他的,寫入文件數據Rect rect(0,0,width,height); // Gdiplus+BitmapData bmData;Status iSucess = ima->LockBits(&rect,ImageLockModeRead,ima->GetPixelFormat() ,&bmData);BYTE *_pixels = (BYTE*)bmData.Scan0; //原圖rect區域內存位置的起始指針,以BYTE作為單元類型BYTE *_pRow;int _strideoff8 = stride - width; //前面計算的索引圖像的strideBYTE _grey;// build pixles, GDI+ (windows)的圖像數據的原點在左下角,參考一下OpenCV的IplImage結構體switch(ima->GetPixelFormat()){case PixelFormat24bppRGB:{int _strideoff24 = stride - 3*width; //前面計算的索引圖像的stride// 灰度化for (int i=height-1; i >= 0; i--){_pRow = _pixels + i*bmData.Stride; // 當前的行for (int j=width-1; j >= 0; j--){ BYTE* _pixels_b; //bBYTE* _pixels_g; //gBYTE* _pixels_r; //r_pixels_b = _pRow++; //blue_pixels_g = _pRow++; //green_pixels_r = _pRow++; //red_grey = GREY(*_pixels_r, *_pixels_g, *_pixels_b); *curr = _grey; //根據紅綠藍求出此像素的灰度值curr++;}curr += _strideoff8;}}break;case PixelFormat32bppARGB:{// 灰度化for (int i=height-1;i>=0;i--){_pRow = _pixels + i*bmData.Stride;for (int j=width-1;j>=0;j--){ BYTE* _pixels_b;BYTE* _pixels_g; BYTE* _pixels_r; _pixels_b = _pRow++; //blue_pixels_g = _pRow++; //green_pixels_r = _pRow++; //red_pRow++;_grey = GREY(*_pixels_r, *_pixels_g, *_pixels_b); *curr = _grey;curr++;}curr += _strideoff8;}}break;case PixelFormat8bppIndexed: // Gdi+只能保存成24位真彩色的圖像{// 不能直接用memcpy復制,需要水平鏡像,memcpy(curr, _pixels, height * stride);for (int i=height-1; i >= 0; i--){_pRow = _pixels + i*bmData.Stride; // for (int j=width-1;j >= 0;j--) // { // _grey = *_pRow++; // *curr = _grey; // curr++; // }memcpy(curr, _pRow, width);curr += stride;}}break;default:break;}// 保存圖像 pMyBmp 到文件try{CFile f(pszPath, CFile::modeCreate | CFile::modeWrite );f.Write(pMyBmp, bitmapFileHeader.bfSize);f.Close();}catch( CFileException* e ){TCHAR szCause[255];e->GetErrorMessage(szCause, 255);CString msg;msg.Format(_T("file error: %s, m_cause:%d\n"),szCause, e->m_cause);TRACE1("%s",msg);AfxMessageBox(msg);e->Delete();}//clean:ima->UnlockBits(&bmData);delete[] pMyBmp;return TRUE; }

總結

以上是生活随笔為你收集整理的使用GDI+保存图像为8bpp的灰度图像的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。