1. 程式人生 > >BMP--24位真彩色轉換為灰度影象

BMP--24位真彩色轉換為灰度影象

以下文字內容來自http://zhidao.baidu.com/question/152910968.html中的部分內容

把RGB值轉換為灰度值的公式:
Gray   :=   Trunc(0.3   *   Red   +   0.59   *   Green   +   0.11   *   Blue);//這句用的是浮點運算
在影象處理中,速度就是生命,能不用浮點運算,就最好不要用!
Gray   :=   (30   *   Red   +   59   *   Green   +   11   *   Blue)   div   100;
雖然這樣一改,運算次數多了一次,但在我的雷鳥1.1G上,處理速度大概能提高5%左右!而同主頻下
(或略低,如Athlon   1600+相當於P4   1.6G)AMD的CPU浮點運算能力比Intel的較強,整數運算能力較弱,所以用Intel的CPU在這裡更能體現出優勢!
注:x   div   100   和   Trunc(x/100)的效果是相同的,但檢視其彙編程式碼可知一個用的指令是div,而另一個是fdiv(即進行浮點運算),
還要呼叫函式Trunc,其處理速度差距非常大,所以能用   x   div   100   的時候就不要用   Trunc(x/100)。
但這還不是最快的,再看一個:
  Gray   :=   HiByte(77   *   Red   +   151   *   Green   +   28   *   Blue);
  即
  Gray   :=   (77   *   Red   +   151   *   Green   +   28   *   Blue)   shr   8;
  (建議用後一種,不要呼叫函式)
  這種方法比最原始的方法快了近3/4!
  什麼意思呢?用77,151,28分別除以256試試~~~
  移位是什麼意思呢,和10進位制的進位,退位聯絡一下,是不是可以近似的理解為乘除2的n次方呢?當然這和真正意義的乘除法是不一樣的!
比如shr(右移),和真正的除法相比,比如shr   1,只有最後一個字位為0時(既為2的倍數),它才等於除2!如二進位制數110(6)右移1位變為11(3),和6/2=3結果相同。
  當然這和一開始的灰度化效果有了些誤差!
  如果允許存在更大的誤差,還可以考慮另一種方法:
  Gray   :=   (Red   shr   2)   +   (Red   shr   4)   +   (Green   shr   1)   +   (Green   shr   4)   +   (Blue   shr   3);
  連乘法都沒用,完全用移位實現,結合上面的解釋,用除法來理解該表示式,其值只是約等於(0.3125   *   Red   +   0.5625   *   Green   +   0.125   *   Blue),
和一開始的加權平均值有了比較大的誤差!但如果對速度有苛刻的要求的話,可以怎麼用!這比上一種方法還能再快5%!

  1. /** 
  2. * 程式名: Convert.cpp 
  3. * 功  能: 將24位真彩色圖轉換為8位灰度圖片 
  4. *         測試圖片test1.bmp放到工程目錄下 
  5. */
  6. #include <iostream>
  7. #include <fstream>
  8. #include <windows.h>
  9. #include <cstring>
  10. usingnamespace std;  
  11. BITMAPFILEHEADER bmpFileHeader; //點陣圖檔案頭
  12. BITMAPINFOHEADER bmpInfoHeader; //點陣圖資訊頭
  13. RGBQUAD *pColorTable;           //顏色表,注:24位真彩色圖無顏色表
  14. unsigned char *pBmpData;        //點陣圖資料
  15. unsigned char *pGrayData;       //灰度影象資料
  16. /** 
  17. * 函式名: readBmp 
  18. * 參  數: fileName -- 要轉換的圖片名 
  19. * 功  能: 讀取fileName檔案資訊,讀取成功返回TRUE,反之,返回FALSE 
  20. */
  21. bool readBmp(char *fileName)  
  22. {  
  23.     FILE *fp = fopen(fileName,"rb");    //以二進位制讀方式開啟
  24.     if(NULL == fp)  
  25.     {  
  26.         cout<<"File is opened failure!"
    <<endl;  
  27.         return FALSE;  
  28.     }  
  29.     //讀取資料
  30.     fread(&bmpFileHeader,sizeof(BITMAPFILEHEADER),1,fp);  
  31.     fread(&bmpInfoHeader,sizeof(BITMAPINFOHEADER),1,fp);  
  32.     pBmpData = new unsigned char[bmpInfoHeader.biSizeImage];   //申請空間,大小為點陣圖資料大小
  33.     fread(pBmpData,sizeof(unsigned char),bmpInfoHeader.biSizeImage,fp);  
  34.     fclose(fp);         //不要忘了關閉檔案
  35.     return TRUE;  
  36. }  
  37. /** 
  38. * 函式名: convert 
  39. * 功  能: 實現24位真彩色圖到灰度圖的轉換 
  40. */
  41. void convert()  
  42. {  
  43.     //因為轉換後多了個顏色表,所以要改變,對bmp檔案結構不清楚的看筆記1
  44.     bmpFileHeader.bfOffBits += (sizeof(RGBQUAD) * 256);   
  45.      //biSizeImg儲存的為點陣圖資料佔用的位元組數,轉換為灰度影象後值發生改變,
  46.     //因為24為真彩色點陣圖資料的一個畫素用3各位元組表示,灰度影象為1個位元組
  47.     bmpInfoHeader.biBitCount = 8;  
  48.     int lineBytes = (bmpInfoHeader.biWidth * 8 + 31) / 32 * 4;  
  49.     int oldLineBytes = (bmpInfoHeader.biWidth * 24 + 31) / 32 * 4;  
  50.     int oldSize = bmpInfoHeader.biSizeImage;        //原圖資料大小
  51.     bmpInfoHeader.biSizeImage = lineBytes * bmpInfoHeader.biHeight;  
  52.     //定義灰度影象的顏色表
  53.     pColorTable = new RGBQUAD[256];  
  54.     for(int i = 0; i < 256; i++ )  
  55.     {  
  56.         (*(pColorTable + i)).rgbBlue = i;  
  57.         (*(pColorTable + i)).rgbGreen = i;  
  58.         (*(pColorTable + i)).rgbRed = i;  
  59.         (*(pColorTable + i)).rgbReserved = 0;  
  60.     }  
  61.     //將RGB轉換為灰度值
  62.     int red,green,blue;  
  63.     BYTE gray;  
  64.     pGrayData = new unsigned char[bmpInfoHeader.biSizeImage];  
  65.     memset(pGrayData,0,bmpInfoHeader.biSizeImage);  
  66.     //這裡要注意,Windows規定一個掃描行所佔的位元組數必須是
  67.     //4的倍數(即以long為單位),不足的以0填充,所以如果當前biWidth如果不是
  68.     //4的倍數時,要在後面補0直到為4的倍數
  69.     for(i = 0; i < bmpInfoHeader.biHeight; i++ )  
  70.     {  
  71.         //點陣圖資料(pBmpData)中儲存的實際畫素數為biWidth個,而一個掃描行要lineByte個位元組,
  72.         //多餘出來的是上面補的0,所以要轉換的要是實際的畫素數,
  73.         //因為轉換前後biWidth是相同的,而lineByte是不同的,也就是後面補的0不同
  74.         //如果還有疑惑,請留言提問,我會即時回覆
  75.         for(int j = 0; j < bmpInfoHeader.biWidth; j++ )  
  76.         {  
  77.             red = *(pBmpData + i*oldLineBytes + 3*j );  
  78.             green = *(pBmpData + i*oldLineBytes + 3*j + 1);  
  79.             blue = *(pBmpData + i*oldLineBytes + 3*j + 2);  
  80.             gray = (BYTE)((77 * red + 151 * green + 28 * blue) >> 8);  
  81.             *(pGrayData + i*lineBytes + j) = gray;  
  82.         }  
  83.     }  
  84. }  
  85. /** 
  86. * 函式名: writeBmp 
  87. * 參  數: fileName -- 轉換之後的檔名 
  88. * 功  能: 將轉換後的影象資訊寫入到fileName檔案中 
  89. */
  90. bool writeBmp(char *fileName)  
  91. {  
  92.     FILE *fp = fopen(fileName,"wb");   //以二進位制寫方式開啟
  93.     if(NULL == fp)  
  94.     {  
  95.         cout<<"File is opened failure!"<<endl;  
  96.         return FALSE;  
  97.     }  
  98.     //寫入資料
  99.     fwrite(&bmpFileHeader,sizeof(BITMAPFILEHEADER),1,fp);  
  100.     fwrite(&bmpInfoHeader,sizeof(BITMAPINFOHEADER),1,fp);  
  101.     fwrite(pColorTable,sizeof(RGBQUAD),256,fp);  
  102.     fwrite(pGrayData,sizeof(unsigned char),bmpInfoHeader.biSizeImage,fp);  
  103.     fclose(fp);  
  104.     //釋放記憶體空間
  105.     delete []pColorTable;  
  106.     delete []pBmpData;  
  107.     delete []pGrayData;  
  108.     return TRUE;  
  109. }  
  110. /** 
  111. * 函式名: work 
  112. * 功  能: 主要處理步驟 
  113. */
  114. void work()  
  115. {  
  116.     char readFileName[] = "test1.bmp";  
  117.     if(!readBmp(readFileName))  
  118.         cout<<"The function of readBmp error!"<<endl;  
  119.     convert();  
  120.     char writeFileName[] = "gray.bmp";  
  121.     if(!writeBmp(writeFileName))  
  122.         cout<<"The function of writebmp error!"<<endl;  
  123.     cout<<"convert success!"<<endl;  
  124. }  
  125. int main()  
  126. {  
  127.     work();  
  128.     return 0;  
轉自:http://blog.csdn.net/sun1956/article/details/8665946 (二) #include <stdio.h>    
#include <windows.h>  


#define WIDTHBYTES(i) ( ( (i+31)/32 )*4) //使每一行的寬度是4個位元組的倍數  
#define IMAGETYPE 0x4d42                 //表示字元BM  


int main(int argc, char* argv)
{
BITMAPFILEHEADER bmpfileheader;     //檔案頭  
BITMAPINFOHEADER bmpinfoheader;     //資訊頭  


unsigned char *matrix;              //畫素矩陣,用unsigned char是因為它的範圍剛好為0—255  
FILE *finput;                       //讀取操作流  
FILE *foutput;                      //出操作流  
DWORD imageSize = 0;                //影象畫素資料部分大小  


//開啟檔案  
//finput = fopen("lll.bmp", "r+b");
fopen_s(&finput, "56.bmp", "r+b");
if (finput == NULL)
{
printf("Open failed\n");
return EXIT_FAILURE;
}
else
{
printf("Open Successsfully\n");
}


fread(&bmpfileheader, sizeof(BITMAPFILEHEADER), 1, finput);//讀取檔案頭  
fread(&bmpinfoheader, sizeof(BITMAPINFOHEADER), 1, finput);//讀取資訊頭  


//判斷是否為24位真彩圖  
if (bmpfileheader.bfType != IMAGETYPE || bmpinfoheader.biBitCount != 24)
{
printf("The error picture!");
return EXIT_FAILURE;
}
//計算點陣圖畫素部分的大小,也可以是bmpinfoheader.biSizeImage 但它有時候是0,不可靠。  
imageSize = WIDTHBYTES(bmpinfoheader.biWidth*bmpinfoheader.biBitCount) * bmpinfoheader.biHeight;


matrix = new unsigned char[imageSize];
memset(matrix, 0, imageSize);


//讀取象素矩陣  
fread(matrix, 1, imageSize, finput);
fclose(finput);




//每個畫素點轉化為灰度值,用的公式是:Gray = R*0.299 + G*0.587 + B*0.114  
for (unsigned long k = 0; k<imageSize; k = k + 3)
{
*(matrix + k) = *(matrix + k + 1) = *(matrix + k + 2) = (*(matrix + k)*0.299 + *(matrix + k + 1)*0.587 + *(matrix + k + 2)*0.114);
}


//建立新的灰度圖  
//foutput = fopen("test.bmp", "w+b");
fopen_s(&foutput,"test5.bmp", "w+b");
fwrite(&bmpfileheader, sizeof(BITMAPFILEHEADER), 1, foutput);
fwrite(&bmpinfoheader, sizeof(BITMAPINFOHEADER), 1, foutput);


fwrite(matrix, 1, imageSize, foutput);
fclose(foutput);


delete[]matrix;
printf("轉化成功\n");
return EXIT_SUCCESS;
}

相關推薦

BMP--24彩色轉換影象

以下文字內容來自http://zhidao.baidu.com/question/152910968.html中的部分內容 把RGB值轉換為灰度值的公式: Gray   :=   Trunc(0.3   *   Red   +   0.59   *   Green  

完整24彩色點陣圖化原始碼

貼出來不為別的,就為萬一以後硬碟出問題資料在網上還有個備份。//Code By xets007//轉載請註明出處//////////////////////////////////////////////////////////////////////////#include <windows.h>

Java實現24轉換8圖片

         Windows下的點陣圖檔案即我們通常所熟悉的BMP圖片,其儲存結構的格式可以在WINGDI.h檔案中找到定義。BMP檔案大體上分為四個部分: 1.      點陣圖檔案頭(BITMAPFILEHEADER) 2.      點陣圖資訊頭(BITMAPIN

-01-RGB彩色影象轉換影象【ARM NEON加速】

1. NEON簡介 NEON官方的簡介網址:NEON NEON的主要特點就是single instruction, multiple data(SIMD),擁有專用的ALU和暫存器(d0-d32,q0-q16),基於這種結構很容易實現資料的平行計算,尤其是數學中的向量計算、音訊中雙聲道資料處理、影象中RG

彩色影象批量轉換影象

       最近在做haar分類器的訓練,要用到大量的正負樣本,在網上找了一些,有一份樣本集除了它是彩色影象外還算滿意,為了後期訓練時間能夠縮短一點,決定把它們都轉換成灰度影象!       說幹就幹,一幅影象的轉換很簡單了,但是批量轉換就稍微複雜了一丟丟,在網上找了下沒

彩色影象轉換影象

方法一:     對於彩色轉灰度,有一個很著名的心理學公式:                           Gray = R*0.299 + G*0.587 + B*0.114      方法二:      而實際應用時,希望避免低速的浮點運算,所以需要整數演算法

C/C++ BMP24彩色影象處理(2)------影象の擷取

對上一篇部落格《C/C++ BMP(24位真彩色)影象處理(1)------影象開啟與資料區處理》的程式碼做小部分的修改,就可以進行BMP影象的擷取操作,程式碼如下: #include <string.h> #include <math.h>

C/C++ BMP24彩色影象處理(3)------影象の放大縮小(雙線性插值)

    影象的放大縮小其實是一回事,都是先建立一張空白目標影象(放大縮小後的影象),其大小就是想要放大縮小後所得到的影象大小。建立影象後我們並不知道這張影象裡面的各個畫素點RGB(或灰度)值是多少,這個時候就需要經過一個演算法去算目標影象的畫素點RGB(或灰度)值。基本上所

MFC-Toolbar(24彩色)

先準備一個24位的真彩色工具欄BMP圖片 如圖所示: 然後新增到Bitmap資源裡 接著上一篇16位工具欄的程式碼,進行稍微修改即可 //建立Toolbar m_toolbar.CreateEx(this, TBSTYLE_FLAT,

如何使用 python3 將RGB 圖片轉換

首先,介紹第一種方法, 使用  PIL  庫,   PIL庫是一種python語言常用的一個圖形處理庫。 關於   PIL  庫的安裝本文就不介紹了。   from PIL import Image I = Image

影象RGB值轉換值的四個方法

前言 影象從RGB值轉灰度值非常重要,下面介紹四個方法. 1.opencv中的cv2.imread()方法 import cv2 img0 = cv2.imread('image0.jpg', 0) cv2.imshow('image',img0)

轉變影象的演算法優化及馬賽克實現程式碼

彩色影象轉為灰度影象:   1.三個顏色通道畫素值加和取均值(B+G+R)/3;   2.三個通道按照公式:r*0.299+g*0.587+b*0.114   計算效率:定點大於浮點,+-  >  */,移位(左移<<為乘,右移>>為除)大於乘除,所以演

RGB轉換影象

RGB轉換成灰度影象的一個常用公式是: Gray = R*0.299 + G*0.587 + B*0.114 //******************灰度轉換函式************************* //第一個引數image輸入的彩色RGB影象的引用; //第二個引數imageGray是轉換後輸

利用OpenCV的imread將RGB影象轉化影象!

通常,我們是利用cvtColor將影象轉化為灰度圖,但實際上在讀取影象的時候便可以將影象轉化為灰度圖, 很簡單的操作,只需要將imread的第二個引數置為0即可 如下面的程式碼: cv::Mat srcImage = cv::imread("lakeWater.jpg"

BYTE[]陣列轉化影象CBitimage顯示到mfc視窗中(opencv結果在mfc中的顯示)

// THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF // ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO // THE IMPLIED

【數字影象】C++824BMP點陣圖的平滑、銳化、二值化處理,以及24彩圖的

BMP標頭檔案: #ifndef BMP_H//前處理器 #define BMP_H typedef unsigned char BYTE; typedef unsigned short WORD; typedef unsigned int DWORD; typedef

bmp點陣圖檔案:讀取、寫入、24彩轉8圖的二值化

影象的二值化處理就是講影象上的點的灰度置為0或255,也就是講整個影象呈現出明顯的黑白效果。即將256個亮度等級的灰度影象通過適當的閥值選取而獲得仍然可以反映影象整體和區域性特徵的二值化影象。在數字影象處理中,二值影象佔有非常重要的地位,特別是在實用的影象處理中,以二值影象處理實現而構成的系統是很多的,要進行

24RGB資料儲存BMP圖片

在做Qt與ffmpeg結合的視訊播放器時,由於解碼後是RGB24資料格式,不知道解碼的資料是否正確,於是在網上找了很久才找到一個RGB24轉bmp檔案的方法,於是嘗試了一下,發現生成的bmp檔案是電影中的片段截圖,才知道解碼的RGB24資料是正確的,最終才成功用

24bmp影象轉成影象

private void 灰度轉換ToolStripMenuItem_Click(object sender, EventArgs e) { if (curBitmap != null) {

C++實現24BMP圖平移,映象,旋轉90、180

一、BMP檔案格式解析 BMP檔案格式,又稱為Bitmap(點陣圖)或是DIB(Device-Independent Device,裝置無關點陣圖),是Window系統中廣泛使用的影象檔案格式。由於它可以不作任何變換地儲存影象畫素域的資料,因此成為我們取得RA