0

化学実験室からのデータの画像を作成するプログラムを書いています。元素などからの放射と、分光器を通して周波数帯域がどのように見えるかの例を含めるためのデータの書き込みに取り組んでいます。色鉛筆ではなく、自分でやってくれるプログラムを作ったほうがいいなと思ったので、きちんと整理整頓されています。また、色鉛筆は持っていません。

画像データを RGB 値として int 配列に格納します。画像の長さは幅×高さで、幅は 320、高さは 50 です。最後に、24 ビットの BGR 順序でファイルに書き込みます。ピクセル。

データをファイルに書き込む前に、もちろん BMP ヘッダーを書き込もうとします。MSDN には、ファイル セクションの一般的な順序を示すチャートがあり、RBGQuads に関する情報が含まれていましたが、段落の説明では、それらの使用方法が説明されていませんでした。オプションだと思いますか?私が予想していたのがヘッダーの唯一の必須部分であることがわかるこのグラフを見つけました: http://www.fastgraph.com/help/bmp_header_format.html、私はそこで正しい軌道に乗っていると思います。

ペイントまたは 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;

もちろん、その順番で書きます。-- いずれにせよ値 'B' 'M' でなければならないため、型は char[] です。

最初に、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 );
  }
}

もともとリトルエンディアンのファイルに書き込まれ、fw_()関数の名前が間違っている可能性がありますが、念のため、サイズ 0 と 0 サイズからも試しました。

関連があると思われる場合は、ここにデータが書き込まれます。

  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.

投稿はすでに長いので、関連するコードが十分に含まれていることを願っています。そこにはたくさんの情報があることを知っているので、申し訳ありませんが、これ以上は意味がありません. この種のことを行うためのより良いイディオムがあれば、正しい方向に向けられることを望みます.

それで、私はすべての入力に感謝します。

4

1 に答える 1

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;
}
于 2013-02-11T16:09:11.490 に答える