有这样的问题:
如下代码使用数组产生图片,然后保存该图片。
SaveBmp是网上找的代码。
这段代码可以得到结果,但需要CreateBitmap中的颜色位数和系统一致(就是说我电脑设置32位色,这个函数参数也要设置为32,否则电脑设置16位色,CreateBitmap函数参数也要为16),否则图像就是全黑色。我感觉CreateBitmap得到的bitmap没有问题,问题应该是save中的红色字体部分,但是我不知道如何去改....
有点疑问:
1 能正确保存图片是说明bmp和系统的颜色一致,如果不一致如何保存?(比如我电脑设置16位色,我想保存图片32位色的)
2 16\24\32位色系统有默认调色板? 调色板是个表格吗? 这几种调色板是否一直存在系统中,想用的时候直接切换就可以?
3 如果是如何切换? CBitmap bitmapmatrix;
char m_pMatrixImage[100000];
int i,retval;
for(i=0;i<10000;i++)
m_pMatrixImage[i] = i&0xFF;
retval = bitmapmatrix.CreateBitmap(100,100,1,32,m_pMatrixImage);
if(retval)
SaveBmp((HBITMAP)bitmapmatrix.GetSafeHandle(),"C:\\t.bmp");  BOOL   SaveBmp(HBITMAP   hBitmap,   CString   FileName)  
  {  
  //设备描述表  
  HDC   hDC;  
  //当前分辨率下每象素所占字节数  
  int   iBits;  
  //位图中每象素所占字节数  
  WORD   wBitCount;  
  //定义调色板大小,   位图中像素字节大小   ,位图文件大小   ,   写入文件字节数    
  DWORD   dwPaletteSize=0,   dwBmBitsSize=0,   dwDIBSize=0,   dwWritten=0;    
  //位图属性结构    
  BITMAP   Bitmap;      
  //位图文件头结构  
  BITMAPFILEHEADER   bmfHdr;      
  //位图信息头结构    
  BITMAPINFOHEADER   bi;      
  //指向位图信息头结构      
  LPBITMAPINFOHEADER   lpbi;      
  //定义文件,分配内存句柄,调色板句柄    
  HANDLE   fh,   hDib,   hPal,hOldPal=NULL;    
   
  //计算位图文件每个像素所占字节数    
  hDC   =   CreateDC("DISPLAY",   NULL,   NULL,   NULL);  
  iBits   =   GetDeviceCaps(hDC,   BITSPIXEL)   *   GetDeviceCaps(hDC,   PLANES);    
  DeleteDC(hDC);    
  if   (iBits   <=   1)   wBitCount   =   1;    
  else   if   (iBits   <=   4)     wBitCount   =   4;    
  else   if   (iBits   <=   8)     wBitCount   =   8;    
  else       wBitCount   =   24;    
   
  GetObject(hBitmap,   sizeof(Bitmap),   (LPSTR)&Bitmap);  
  bi.biSize   =   sizeof(BITMAPINFOHEADER);  
  bi.biWidth   =   Bitmap.bmWidth;  
  bi.biHeight   =   Bitmap.bmHeight;  
  bi.biPlanes   =   1;  
  bi.biBitCount   =   wBitCount;  
  bi.biCompression   =   BI_RGB;  
  bi.biSizeImage   =   0;  
  bi.biXPelsPerMeter   =   0;  
  bi.biYPelsPerMeter   =   0;  
  bi.biClrImportant   =   0;  
  bi.biClrUsed   =   0;  
   
  dwBmBitsSize   =   ((Bitmap.bmWidth   *   wBitCount   +   31)   /   32)   *   4   *   Bitmap.bmHeight;  
   
  //为位图内容分配内存    
  hDib   =   GlobalAlloc(GHND,dwBmBitsSize   +   dwPaletteSize   +   sizeof(BITMAPINFOHEADER));    
  lpbi   =   (LPBITMAPINFOHEADER)GlobalLock(hDib);    
  *lpbi   =   bi;    
   
  //   处理调色板      
  hPal   =   GetStockObject(DEFAULT_PALETTE);    
  if   (hPal)    
  {    
  hDC   =   ::GetDC(NULL);    
  hOldPal   =   ::SelectPalette(hDC,   (HPALETTE)hPal,   FALSE);    
  RealizePalette(hDC);    
  }  
   
  //   获取该调色板下新的像素值    
  GetDIBits(hDC,   hBitmap,   0,   (UINT)   Bitmap.bmHeight,   (LPSTR)lpbi   +   sizeof(BITMAPINFOHEADER)    
  +dwPaletteSize,   (BITMAPINFO   *)lpbi,   DIB_RGB_COLORS);    
   
  //恢复调色板      
  if   (hOldPal)    
  {    
  ::SelectPalette(hDC,   (HPALETTE)hOldPal,   TRUE);    
  RealizePalette(hDC);    
  ::ReleaseDC(NULL,   hDC);    
  }    

   
  //创建位图文件      
  fh   =   CreateFile(FileName,   GENERIC_WRITE,0,   NULL,   CREATE_ALWAYS,    
  FILE_ATTRIBUTE_NORMAL   |   FILE_FLAG_SEQUENTIAL_SCAN,   NULL);    
   
  if   (fh   ==   INVALID_HANDLE_VALUE)     return   FALSE;    
   
  //   设置位图文件头    
  bmfHdr.bfType   =   0x4D42;   //   "BM"    
  dwDIBSize   =   sizeof(BITMAPFILEHEADER)   +   sizeof(BITMAPINFOHEADER)   +   dwPaletteSize   +   dwBmBitsSize;      
  bmfHdr.bfSize   =   dwDIBSize;    
  bmfHdr.bfReserved1   =   0;    
  bmfHdr.bfReserved2   =   0;    
  bmfHdr.bfOffBits   =   (DWORD)sizeof(BITMAPFILEHEADER)   +   (DWORD)sizeof(BITMAPINFOHEADER)   +   dwPaletteSize;    
  //   写入位图文件头    
  WriteFile(fh,   (LPSTR)&bmfHdr,   sizeof(BITMAPFILEHEADER),   &dwWritten,   NULL);    
  //   写入位图文件其余内容    
  WriteFile(fh,   (LPSTR)lpbi,   dwDIBSize,   &dwWritten,   NULL);    
  //清除      
  GlobalUnlock(hDib);    
  GlobalFree(hDib);    
  CloseHandle(fh);    
   
  return   TRUE;  
  }  
  

解决方案 »

  1.   

    问题1:如果要显示位图,系统会做颜色变换。如果要自己写代码保存位图,需要自己做颜色变换。
    问题2: 16\24\32位色属于真彩色,不需要调色板,本身就包含了足够的颜色信息(R,G,B)。建议你看一下位图结构的资料,位图结构很简单,包括:文件头、位图信息头、数据块,8位的还有调色板。16\24\32位色之间的颜色变换也很简单,主要就是一位操作。
      

  2.   

    建议LZ先看一下24位真彩图,把24位BMP文件结构搞明白(没有调色板),以后就好办了LZ应该是把DDB和DIB搞混了,建议从DIB看起,不要理会DDB(以后根据需要看)
    Windows 中位图有两种格式:
    设备相关位图 Device Depend Bitmap DDB
    设备无关位图 Device Independ Bitmap DIBDDB 位图格式 ------------ BITMAP(结构体) CBitmap(MFC类) HBITMAP(HANDLE)//这三个先不要碰
    由 BITMAP 数据类型的结构 + 图像数据构成。
    因为DDB没有保存位图的调色板,在不同类设备显示时可能造成完全失真。DIB 位图格式 ----------- BITMAPINFO //重点学这个
    BITMAP INFOHEADER (BMP 文件信息头) + RGBQUAD (BMP 文件调色板) + BITMAP DATA (BMP 文件数据) 三部分构成
    它实际就是BMP文件去掉BITMAP FILEHEADER (BMP 文件头),即一个BITMAPINFO结构后面接上调色板再加上图像数据。BMP文件的显示 ---- DIB
    首先将BMP读成DIB格式,当显示时直接DIB显示,只要读入BITMAPINFO结构和图像数据即可。BMP文件的显示 ---- DDB
    首先要先将DIB位图转化为DDB位图,再由MFC的CBitmap类显示。
    最后再看一下8位的灰度图,常用的只有24位彩图和8位灰度图(这个有调色板)http://hi.baidu.com/codeworkman/blog/item/af6c8ad0f5b742309a502754.html