BMP标题 - MSDN模糊,是我的字节错误吗?

时间:2013-02-10 19:11:20

标签: c++ header endianness bmp

我正在编写一个程序来为化学实验室的某些数据创建图像。我们正在研究元素等的发射,并且数据写入包括通过分光镜观察频带的示例。我认为为我做一个程序是很好的,而不是彩色铅笔,所以这一切都很整洁。另外,我没有彩色铅笔。

我将图像数据作为RGB值存储在一个int数组中,长度宽度*我想要的图像高度,宽度为320,高度为50.最后我将它们写为24位文件BGR有序像素。

在将数据写入文件之前,我当然会尝试编写BMP头。 MSDN有一个图表来显示文件部分的一般顺序,其中包含一些关于RBGQuads的内容,但在段落中的解释没有描述如何使用它们。我认为他们是可选的?我发现此图表显示了我所期望的标题中唯一的强制部分: http://www.fastgraph.com/help/bmp_header_format.html,所以我觉得我在那里正确。

然后我得到了endianness,因为在尝试使用Paint或Windows图像查看器打开时,我的文件总是“损坏或损坏”。

所有消息来源都说BMP标题是小端。我尝试在写入时双向交换字节的顺序,但文件仍然无法打开。家庭酿造的腐败文件还有其他常见的罪魁祸首吗?

这是我存储标题信息的地方:

typedef struct
{
  char type[2];
  unsigned int fsize;
  unsigned short res1;
  unsigned short res2;
  unsigned int data_offset;
} BMPFILEHEADER;

typedef struct
{
  unsigned int sizebytes;
  int  width_pix;
  int  height_pix;                   // negative for top down.
  unsigned short  planes;            // must be 1
  unsigned short  bits_per_pix;
  unsigned int compression;          // zero for BI_RGB (uncompressed)
  unsigned int SizeImage;            // may be set to 0 for BI_RGB images.
  int  pix_per_meter_x;
  int  pix_per_meter_y;
  unsigned int color_used;           // set to 0
  unsigned int color_important;      // set to 0
} BMPINFOHEADER;

当然,我按顺序写下它们。 - type是char []因为它必须是值'B''M'。

首先我尝试用fwrite()编写它们:

  fwrite ( &header , 1 , 14 , fhandle );
  fwrite ( &headerext , 1 , 40 , fhandle );

然后我尝试这样写:

  fputc ( 'B' , fhandle );
  fputc ( 'M' , fhandle );
  fw_little_end ( fhandle , &header.fsize , 4 );
  fw_little_end ( fhandle , &header.res1 , 2);
  fw_little_end ( fhandle , &header.res2 , 2);
  fw_little_end ( fhandle , &header.data_offset , 4);

其中fw_little_end()如下所示:

void fw_little_end ( FILE * fhandle , void * data , int size )
{
  int i;
  char * cdata = data;
  for ( i = size; i > 0; i-- )
  {
    fputc ( *(cdata+i-1) , fhandle );
  }
}

最初它可能是写入文件little endian并且我的fw_()函数名称错误,但我也尝试过从size-0和0-size来确定。

如果它听起来相关,那就是写入数据的地方:

  int shift1 = 256;
  int shift2 = 256*256;
  for ( i = 0; i < img_size; i++)
  {
    fputc ( (unsigned char) (data[i]%256) , fhandle ); // B
    fputc ( (unsigned char) (data[i]/shift1)%256 , fhandle ); // G
    fputc ( (unsigned char) (data[i]/shift2)%256 , fhandle ); // R
  } // theoretically B only needs the typecast, not the %256 but oh well lol.

帖子已经很长了,希望我已经包含了足够的相关代码。我很抱歉,因为我知道那里有很多信息,除此之外对我来说没有任何意义。如果对于如何做这些事情有更好的习语,我很乐意指出正确的方向。

所以,我感谢你提供任何和所有的意见。

1 个答案:

答案 0 :(得分:0)

我发布直接答案:

/* ======================================================================================== */
BOOL SaveBitmap24(LPCTSTR pszFilename, LPBYTE pPixelColorTriplets, INT nWidth, INT nHeight)
{
    BOOL bState = FALSE;
    // sizes
    INT nOfsetToPixel = sizeof(BITMAPFILEHEADER) + sizeof(BITMAPCOREHEADER);
    INT nPixelSize = nWidth * nHeight * 3;
    INT nFileSize = nOfsetToPixel + nPixelSize;
    // setup bitmap file header --------------
    BITMAPFILEHEADER bmFileHeader = { 0 };
    // "BM" signature
    bmFileHeader.bfType = 0x4D42;
    bmFileHeader.bfOffBits = nOfsetToPixel;
    bmFileHeader.bfSize = nFileSize;
    // setup bitmap info header --------------
    BITMAPCOREHEADER bmCoreHeader = { 0 };
    bmCoreHeader.bcSize = sizeof(BITMAPCOREHEADER);
    bmCoreHeader.bcWidth = nWidth;
    bmCoreHeader.bcHeight = nHeight;
    bmCoreHeader.bcBitCount = 24;
    bmCoreHeader.bcPlanes = 1;
    // write file -----------------------
    FILE *fileBitmap = fopen(pszFilename, _T("wb"));
    if (fileBitmap)
    {   fwrite(&bmFileHeader, sizeof(BITMAPFILEHEADER), 1, fileBitmap);
        fwrite(&bmCoreHeader, sizeof(bmCoreHeader), 1, fileBitmap);
        fwrite(pPixelColorTriplets, nPixelSize, 1, fileBitmap);
        fclose(fileBitmap);
        bState = TRUE;
    }
    return bState;
}