[Tips] ビットマップファイルの書き込み
書き込む画像データの作成
まず,データを用意する.
データは,1次元配列で以下のようなコードで用意する.
int x,y; int width = 131; int height= 121; unsigned char *pixel = (unsigned char*)malloc(sizeof(unsigned char)*width*height*3); for( x=0;x<width;x++){ for( y=0;y<height;y++){ int pix1=0,pix2=0; if(x<width/2) pix1 = 255; if(y<height/2) pix2 = 255; *(pixel+3*(x+y*width) )=pix1; *(pixel+3*(x+y*width)+1)=pix2; *(pixel+3*(x+y*width)+2)=0; } }
このデータは左上四半分が黄色,右上四半分が緑色,左下四半分が赤色,右下四半分が黒色となる.
以下はその画像である.
画像データの書き込み
このデータを以下のWriteBitmapで書き込む.
まず,ビットマップファイルのヘッダを準備する.改めて書き込む必要があるのは,画像のサイズに関する部分だけだ.
// calculate alignment size if( nWidth*3%4 == 0) writeWidth = nWidth*3; else writeWidth = nWidth*3 + 4 - (nWidth*3)%4;
この部分で,ビットマップファイルの横幅のマージンを入れたバイト単位の横幅サイズを計算する.
そして,この構造体をそのまま書き込まないようにする.
一般的にC言語等では,構造体のサイズを2バイト単位(だったかな?)で確保するため,構造体をそのままファイルに書き込むと,空白のダミーデータが書き込まれてしまう.(確かこれを回避する構造体の宣言方法もあったはず)
よって,ビットマップファイルの時は,構造体の中のデータをひとつずつ書き込んでいく.
最後にピクセルデータを書き込んでいく.
ピクセルデータは,フォーマットに従い,マージンを書き込む必要がある.
int WriteBitmap(char*pFileName, unsigned char *pPixel,int nWidth, int nHeight) { FILE *fp; BitmapHeader header; BitmapInfoHeader info; int x,y; unsigned char dummy=0; int writeWidth=0; // open file if(!( fp = fopen(pFileName, "wb") )) return 0; // initialize headers InitHeaders(&header, &info); // image size info.m_nWidth = nWidth; info.m_nHeight = nHeight; // calculate alignment size if( nWidth*3%4 == 0) writeWidth = nWidth*3; else writeWidth = nWidth*3 + 4 - (nWidth*3)%4; // set file size header.m_nFilesize = writeWidth*nHeight // bitmap size + 14 // header size + 40; // information header size #ifdef __ENDIAN // Macのときは__ENDIANを定義し,エンディアン変換を行う. SwapByteOrderHeaders(&header, &info); #endif // write headers WriteHeader(&header,fp); WriteInfoHeader(&info,fp); // write pixels for( y=nHeight-1 ; y>=0 ; y--){ // sort RGB -> BGR for( x=0 ; x < nWidth ; x++ ){ fwrite((pPixel+3*(x+nWidth*y)+2),sizeof(unsigned char),1,fp); fwrite((pPixel+3*(x+nWidth*y)+1),sizeof(unsigned char),1,fp); fwrite((pPixel+3*(x+nWidth*y) ),sizeof(unsigned char),1,fp); } // fill in margin memory with zero if( nWidth*3%4 != 0) for( int j=0;j<4-(nWidth*3)%4;j++) fwrite(&dummy,sizeof(unsigned char),1,fp); } fclose(fp); return 1; }
サンプルコード
http://code.google.com/p/sonson-code/source/browse/#svn/trunk/src/bitmapSrc