24位位图转8位位图时的文件头有关问题

24位位图转8位位图时的文件头问题我的一个程序中需要将一个24位位图转为8位位图后保存,我的思路是在读取原

24位位图转8位位图时的文件头问题
我的一个程序中需要将一个24位位图转为8位位图后保存,我的思路是在读取原图后得到原图的图像数据,然后重新申请内存空间,构造新的BITMAPFILEHEADER和BITMAPINFOR结构,里边包括BITMAPINFOHEADER和颜色表,之后是紧跟新的位图信息,然后再保存。我的思路对不对?有没有更好的方法?在生成新的位图数据时,新图每行所占的字节数变了,图像大小变了,那么在构造BITMAPFILEHEADER结构时它的那个bfSize和bfOffBits怎么确定?

[解决办法]
你这其实就是转换成灰度图象,就按你的思路弄就行,只不过把各个象素值重新计算一下,用(R+G+B)/3代替即可。
[解决办法]
bfsize不就是 width*height 么?
bfOffBits灰度数据起始地址应该没什么变化吧

真彩的255*255*255 size = 3 * width * height,灰度占一个byte,0~255

[解决办法]

探讨
在生成新的位图数据时,新图每行所占的字节数变了,图像大小变了,那么在构造BITMAPFILEHEADER结构时它的那个bfSize和bfOffBits怎么确定?

[解决办法]
LZ我想你说的8位位图应该是 8位彩色(256色)而不是256灰度吧?
没理解错吧?
[解决办法]
图像大小没变,bfSize是文件的大小,也就是文件头加上颜色表加上位图数据的大小;bfOffBits是位图数据的开始位置,也就是文件头加上颜色表的大小。
[解决办法]
C/C++ code
        HANDLE   hFile   =   ::CreateFile("E:\\bitmap.bmp",GENERIC_READ,FILE_SHARE_READ,                 NULL,OPEN_EXISTING,FILE_ATTRIBUTE_NORMAL,NULL);           if(hFile   ==   0)           {                 MessageBox("不能打开文件,请重新选择!");           }                 DWORD   dwWriteNum;                   BITMAPFILEHEADER   Bmp_file_head;   //文件头             ReadFile(hFile,&Bmp_file_head,14,&dwWriteNum,NULL);//读取文件头,共14个字节                 if((Bmp_file_head.bfType   !=   'MB')||(dwWriteNum   !=   sizeof(BITMAPFILEHEADER)))             {                     MessageBox("不是BMP位图文件或数据有误!");             }         BITMAPINFOHEADER   Bmp_info_head;   //信息头     ReadFile(hFile,&Bmp_info_head,40,&dwWriteNum,NULL);         if(dwWriteNum   !=   sizeof(BITMAPINFOHEADER))     {     MessageBox("读取信息头错误!");     }         //读取24位图像素数据     DWORD   Bitmap_bit_len;     Bitmap_bit_len   =   Bmp_file_head.bfSize-sizeof(BITMAPFILEHEADER)-sizeof(BITMAPINFOHEADER);         BYTE   *lpOldBmpData   =   new   BYTE[Bitmap_bit_len];     ReadFile(hFile,lpOldBmpData,Bitmap_bit_len,&dwWriteNum,NULL);               if(dwWriteNum   !=   Bitmap_bit_len)     {     MessageBox("位图像素数据读取错误!");     }                 int       nScanWidth;             //转换后其每行扫描宽度             int     nLineWidth;             //将其转换成8位位图后每行宽度(即每行字节数)                   int       nSrcWidth,nSrcHeight;                       nSrcHeight   =   Bmp_info_head.biHeight;         //原24位位图高度(像素数)             nSrcWidth   =   Bmp_info_head.biWidth;             //原24位位图宽度(像素数)                 nLineWidth   =   ((nSrcWidth*3)/4)*4;                     if(nLineWidth<nSrcWidth*3)                   nLineWidth=nLineWidth+4;                                 //保证以DWORD对齐(为4的整数倍)(原图象每行字节数)                         nScanWidth=(nSrcWidth/4)*4;                   if(nScanWidth<nSrcWidth)                   nScanWidth=nScanWidth+4;                                 //保证以DWORD对齐(为4的整数倍)(转换图象每行像素数)                 //申请8位图的空间             int   intnDataLen   =   nScanWidth*nSrcHeight;//+2;     //原图像素数         BYTE   *   lpNewBmpData   =   new   BYTE[intnDataLen];         //为8位位图像素赋值             for(int   i=0;i<nSrcHeight;i++)           //像素       {                   for(int   j=0;j<nSrcWidth;j++)             //像素           {                                 BYTE       color[3];                                 unsigned   int       dwColorTemp;                                 for(int       s=0;   s<3;   s++)                                     color[s]=lpOldBmpData[i*nLineWidth+j*3+s];                                   dwColorTemp=unsigned   int(color[2]*0.299+color[1]*0.587+color[0]*0.114);                                                     if(dwColorTemp>255)                                       dwColorTemp=255;                               if(   dwColorTemp<   0   )                                 dwColorTemp   =   0;                     //***************the   problem   is   here****************************//                           lpNewBmpData[i*nScanWidth+j]=(unsigned   char)dwColorTemp;             }             }                         //设置8位位图调色板     RGBQUAD   *rgbQuad   =   new   RGBQUAD[256];     for(i=0;i<256;i++)     {     rgbQuad[i].rgbBlue   =   i;       rgbQuad[i].rgbGreen   =   i;       rgbQuad[i].rgbRed   =   i;       rgbQuad[i].rgbReserved   =   0;       }             //设置8位位图文件头     BITMAPFILEHEADER   Bmp_new_file_head;     Bmp_new_file_head.bfOffBits   =   sizeof(BITMAPFILEHEADER)+sizeof(BITMAPINFOHEADER)+256*sizeof(RGBQUAD);             Bmp_new_file_head.bfReserved1   =   Bmp_file_head.bfReserved1;     Bmp_new_file_head.bfReserved2   =   Bmp_file_head.bfReserved2;     Bmp_new_file_head.bfType   =   Bmp_file_head.bfType;     Bmp_new_file_head.bfSize   =   Bmp_new_file_head.bfOffBits+intnDataLen;         //设置8位位图信息头     Bmp_info_head.biBitCount=8;         //关闭24位位图文件       if(   !CloseHandle(   hFile   )   )                 MessageBox("关闭文件时失败");           HANDLE   hSaveFile   =   CreateFile("E:\\bitmap_8.bmp",   GENERIC_WRITE,   FILE_SHARE_WRITE,                 NULL,   CREATE_ALWAYS,   FILE_ATTRIBUTE_NORMAL,   NULL);             if(   !hSaveFile   )       {                     MessageBox(   "创建文件出错");       }                 //写位图文件头               WriteFile(   hSaveFile,   &Bmp_new_file_head,   sizeof(BITMAPFILEHEADER),   &dwWriteNum,   NULL);         //写位图信息头               WriteFile(   hSaveFile,   &Bmp_info_head,   sizeof(BITMAPINFOHEADER),   &dwWriteNum,   NULL);         //写位图调色板               WriteFile(   hSaveFile,   rgbQuad,   256*sizeof(RGBQUAD),   &dwWriteNum,   NULL);         //写位图像素数据               WriteFile(   hSaveFile,   lpNewBmpData,   intnDataLen,   &dwWriteNum,   NULL);           //关闭8位位图               CloseHandle(   hSaveFile   );