1.     位图格式
  位图文件主要分为4个部分组成:文件头,信息头,调色板,图像数据。<?xml:namespace prefix = o ns = "urn:schemas-microsoft-com:office:office" />

<?xml:namespace prefix = v ns = "urn:schemas-microsoft-com:vml" />
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         //
每像素的位数(14824
       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~78个子节点.
   }SNode ;
  
插入的过程中,如果节点不存在,则需要创建新的节点,然后增加节点计数以及RGB各分量的总和.当在插入时,发现节点已经存在,且是叶子节点,则停止该颜色后续层数节点的插入。插入完一个颜色之后,如果叶子节点数超过了我们要得到的颜色数(256色需要得到256种颜色),这时候就需要合并一些呀字节点了,使的叶子节点的个数不超过我们要得到的颜色数。
  
由于越底层的节点,数据的敏感度越低,所以,我们将从最底层的节点开始合并。按节点计数值小的优先合并策略,将其字节点的所有RGB分量以及节点计数全部记录到该节点中,并删除其所有子节点。依此进行,直到合并后的叶子数符合要求为止。
2.)
提取调色板
  
按照上述的步骤插入完所有的颜色之后,便建立起一颗叶子节点不超过256的八叉树。此时,取出叶子节点中的RGB分量的平均值(分量总和 / 节点计数),即是得到的调色板颜色值。
3.)
匹配调色板索引
  
所谓匹配调色板索引,就是根据原始的RGB值,在调色板中查找出最接近的颜色的索引。对每个RGB颜色,分别对调色板数据求各分量的差值的平方和,求的的最小值对应的调色板颜色的索引,即是该RGB颜色匹配到的调色板索引