位元影像八叉樹演算法

來源:互聯網
上載者:User

標 題:位元影像八叉樹演算法

時 間:2008/11/08

源 碼:BmpConverter.rar

 

1.位元影像格式
  位元影像檔案主要分為4個部分組成:檔案頭,資訊頭,調色盤,映像資料。 

  

1.) 檔案頭
   結構定義如下:
   typedef struct tagBITMAPFILEHEADER
   {
       WORD   bfType ;         // 檔案類型,必須為 BM .
       DWORD  bfSize ;         // 整個檔案的位元組大小
       WORD   bfReserved1 ;    // 保留,為0
       WORD   bfReserved2 ;    // 保留,為0
       DWORD  bfOffBits ;      // 映像資料在檔案中相對頭結構的位移位元組數.
   }BITMAPFILEHEADER ;
2.) 資訊頭 ;
   結構定義如下:
   typedef struct tagBITMAPINFOHEADER
   {
       DWORD biSize;            // 結構大小
       LONG biWidth;            // 映像寬度(像素)
       LONG biHeight;           // 映像高度(像素)
       WORD biPlanes;           // 圖象位平面數目,必須為1
       WORD biBitCount         // 每像素的位元(1,4,8,24)
       DWORD biCompression;    // 壓縮類型
       DWORD biSizeImage;      // 壓縮圖象大小的位元組值
       LONG biXPelsPerMeter;    // 水平解析度
       LONG biYPelsPerMeter;    // 垂直解析度
       DWORD biClrUsed;        // 使用的顏色數目
       DWORD biClrImportant;    // 重要顏色數目
   } BITMAPINFOHEADER;
3.) 調色盤
   每個調色盤元素的結構體定義如下:
   typedef struct tagRGBQUAD
   {
       BYTE rgbBlue;
       BYTE rgbGreen;
       BYTE rgbRed;
       BYTE rgbReserved;
   } RGBQUAD;
   對於高位位元影像,將沒有調色盤存在.
4.) 映像資料
   包含實際的映像資料,N位位元影像,每N Bits表示一個像素的值,按從下到上行優先儲存,同時每行按4位元組對齊.
5.) 讀取位元影像檔案
   開啟檔案 :
       FILE * fBmp = _tfopen(fileName,_T("rb"));
   讀取檔案頭:
       BITMAPFILEHEADER FileHeader;
       fread(&FileHeader,sizeof(BITMAPFILEHEADER),1,fBmp);
   讀取資訊頭:
       BITMAPINFOHEADER InfoHeader;
       fread(&InfoHeader,sizeof(BITMAPINFOHEADER),1,fBmp);
   讀取調色盤(以256色為例,調色盤有256項):
       RGBQUAD quard[256] ;
       fread(quard,sizeof(RGBQUARD),256,fBmp);
   讀取映像資料:
       int nDataLen = (((InfoHeader.biWidth*InfoHeader.biBitCount/8) + 3) / 4) * 4 * InfoHeader.biHeight ;
       BYTE * pbyDataBuf = new BYTE[ nDataLen ] ;
       fseek(fBmp,FileHeader.bfOffBits,SEEK_SET);
       fread(pbyDataBuf ,nDataLen ,1,fBmp);

2.八叉樹演算法
   使用八叉樹演算法實現真彩色(24Bits)轉256色.要實現此功能,主要就是從真彩色中尋找出最能代表整張映像的256種顏色,建立調色盤.八叉樹就是為了找出這256種顏色.
1.) 建立八叉樹
   八叉樹節點的特性就是每個節點最多有8個位元組點,編號為0~7 . 
   

   以RGB值建立八叉樹,首先建立根節點(Root),然後分別以RGB的每一位分別組成一個0~7的值,依次插入樹中。以RGB(123,54,78)為例, 
      

  以此類推,將所有的RGB值逐層插入到八叉樹中,在每個節點上,記錄所有經過的節點的RGB值的總和,已及RGB顏色個數。八叉樹節點結構如下:
   typedef struct tagNode
   {
       DWORD  dwCounter ;      // 經過該節點的個數
       DWORD  dwRedSum ;     //  R分量的總和
       DWORD  dwGreenSum ;    // G 分量的總和
       DWORD  dwBlueSum ;     // B 分量的總和
       BOOL    bLeafNode ;      // 是否為葉子節點.
       tagNode *  psChild[8];      // 分別指向該節點編號為0~7的8個子節點.
   }SNode ;
   插入的過程中,如果節點不存在,則需要建立新的節點,然後增加節點計數以及RGB各分量的總和.當在插入時,發現節點已經存在,且是葉子節點,則停止該顏色後續層數節點的插入。插入完一個顏色之後,如果葉子節點數超過了我們要得到的顏色數(256色需要得到256種顏色),這時候就需要合并一些呀位元組點了,使的葉子節點的個數不超過我們要得到的顏色數。
   由于越底層的節點,資料的敏感度越低,所以,我們將從最底層的節點開始合并。按節點計數值小的優先合并策略,將其位元組點的所有RGB分量以及節點計數全部記錄到該節點中,並刪除其所有子節點。依此進行,直到合并後的葉子數符合要求為止。
2.) 提取調色盤
   按照上述的步驟插入完所有的顏色之後,便建立起一顆葉子節點不超過256的八叉樹。此時,取出葉子節點中的RGB分量的平均值(分量總和 / 節點計數),即是得到的調色盤顏色值。
3.) 匹配調色盤索引
   所謂匹配調色盤索引,就是根據原始的RGB值,在調色盤中尋找出最接近的顏色的索引。對每個RGB顏色,分別對調色盤資料求各分量的差值的平方和,求的的最小值對應的調色盤顏色的索引,即是該RGB顏色匹配到的調色盤索引。

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.