#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#include <tchar.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <windows.h>
/// ソースコード中のBMPファイルに関するコメントは削除
/// 32ビット形式では、
BITMAPFILEHEADER(14Byte)
、
BITMAPINFOHEADER(40Byte)
に続いて
、
一画素あたり4バイト
///
(BGRA:リトルエンディアン)
で記録されている。 Y軸方向のライン数(bmpIH.biHeight)が、正の数の場合は、
/// 画像の左下を開始点に
に、右上までを連続して記録し、
(bmpIH.biHeight)が、負の数の場合は、
画像の左上
///
を
開始点に
に、右下までのデータが連続して記録されている。 画像が24ビット形式の場合は、X
軸方向の
///
データは4バイト境界になる様に調整用のダミーデータが入っているので注意する事
。
/// プログラムは、Y軸のマイナス
を
考慮しない。
BITMAPFILEHEADER bmpFH ;
BITMAPINFOHEADER bmpIH ;
void *originalBMP ;
int *labelData ;
unsigned char *imageData ;
////////////////////////////////////////////////////////////////////////////////
int saveDataAsBMP( char *fname, unsigned char *b, BITMAPFILEHEADER *bmpFH, BITMAPINFOHEADER *bmpIH )
{/** 処理結果を 32ビット形式の BMPファイルとして書き出す。 */
FILE *fp ;
bmpIH->biBitCount = 32 ;
bmpIH->biCompression = BI_RGB ;
bmpIH->biSizeImage = bmpIH->biWidth * abs(bmpIH->biHeight) * 4 ;
bmpFH->bfOffBits = sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFOHEADER) ;
bmpFH->bfSize = bmpIH->biSizeImage + bmpFH->bfOffBits ;
if( (fp=fopen(fname, "wb")) == NULL ) {
fprintf( stderr, "File '%s' cannot create.\n", fname );
return -1;
} else if ( fwrite( bmpFH, sizeof(BITMAPFILEHEADER), 1, fp ) != 1 ) {
fclose(fp) ; return -1;
} else if ( fwrite( bmpIH, sizeof(BITMAPINFOHEADER), 1, fp ) != 1 ) {
fclose(fp) ; return -1;
} else if ( fwrite( b, bmpIH->biSizeImage, 1, fp ) != 1 ) {
fclose(fp) ; return -1;
}
fclose(fp) ;
return 0;
}
void processing( unsigned char *imageData, int *labelData, int label, int lx , int ly )
{/** 指定されたラベル番号とラベルデータを比較してイメージデータに操作を行う。 */
register unsigned char *d = imageData ;
register int x, y, v=label, *n = (int *)labelData ;
for( y=0; y<ly; y++ ) { // イメージデータの位置と、ラベルデータの位置は整合している
for( x=0; x<lx; x++, d+=4, n++ ) { // IMAGE[Y][X] ≡ LABEL[Y][X]
if( *n == v ) { // 指定番号と一致したら、R,G,B に 255,255,255 をセットする
*(d+0) = 0xFF ; // B
*(d+1) = 0xFF ; // G
*(d+2) = 0xFF ; // R
*(d+3) = 0x00 ; // A
} else if( *n != 0 ) { // 背景以外なら中間色をセットする
*(d+0) = 0x1F ; // B *(d+0) = *(d+0) >> 1 ; 原画の輝度を1/2にする場合
*(d+1) = 0x1F ; // G *(d+1) = *(d+1) >> 1 ; 原画の輝度を1/2にする
場合
*(d+2) = 0x1F ; // R *(d+2) = *(d+2) >> 1 ; 原画の輝度を1/2にする場合
*(d+3) = 0x00 ; // A
} else {
*(d+0) = 0x00 ; // B
*(d+1) = 0x00 ; // G
*(d+2) = 0x00 ; // R
*(d+3) = 0x00 ; // A
}
}
}
}
void img2image(unsigned char *img, unsigned char *image, BITMAPINFOHEADER bmpIH)
{/** BMPファイルのデータを BGRA(32bite) 形式の作業エリアにコピーする */
register int type=bmpIH.biBitCount, lx=bmpIH.biWidth, ly=abs(bmpIH.biHeight) ;
register int x, y, bytePerLine=((type==32) ? lx*4 : (lx*3+3)&~0x3) ;
register int *si=(int *)img, *di=(int *)image ;
register unsigned char *s=img, *d=image ;
if( type == 32 ) {
for( y=0; y<ly; y++ ) {
for( x=0; x<lx; x++ ) {
*di++ = *si++ ; // 4バイト(BGRA)の一括コピー
}
// 32ビット環境(sizeof(int)==4)のみで有効。推奨される方法ではない。
}
} else if( type == 24 ) {
for( y=0; y<ly; y++ ) {
s = img + y * bytePerLine; // パディングを考慮したアドレス計算
for( x=0; x<lx; x++ ) {
*d++ = *s++ ;
*d++ = *s++ ;
*d++ = *s++ ;
*d++ = 0 ;
}
}
}
}
int main(int argc, char *argv[])
{
FILE *fp ;
struct stat fileInfo1, fileInfo2 ;
unsigned char *img ;
char *oname = "processed.bmp" ;
int labelNumber ;
if( argc != 4 ) { // 引数の評価とデータの読み込み
fprintf( stderr, "Usage: %s bmp_file label_file object_No\n", argv[0] ) ;
exit(1) ;
} else labelNumber = atoi(argv[3]) ; // object_No
if ((fp=fopen(argv[1],"rb")) == NULL ) { // load bmp_file BMP ファイルの読み込み
fprintf( stderr, "File '%s' cannot open.\n", argv[1] ); exit(1) ;
} else if ( fstat(fileno(fp), &fileInfo1) != 0 ) {
fprintf( stderr, "File '%s' fstat error.\n", argv[1] ); exit(1) ;
} else if( (originalBMP=(void *)malloc(fileInfo1.st_size) ) == NULL ) {// 動的メモリーの確保
fprintf( stderr, "Couldn't allocate memory.(%dbyte)\n", (int)fileInfo1.st_size ) ; exit(1) ;
} else if ( fread(originalBMP, fileInfo1.st_size, 1, fp) != 1 ) {
fprintf( stderr, "File '%s' read error.\n", argv[1] ); exit(1) ;
} else fclose(fp) ;
if ((fp=fopen(argv[2],"rb")) == NULL ) { // load label_file ラベルファイルの読み込み
fprintf( stderr, "File '%s' cannot open.\n", argv[2] ); exit(1) ;
} else if ( fstat(fileno(fp), &fileInfo2) != 0 ) {
fprintf( stderr, "File '%s' fstat error.\n", argv[2] ); exit(1) ;
} else if( (labelData=(int *)malloc(fileInfo2.st_size) ) == NULL ) {// 動的メモリーの確保
fprintf( stderr, "Couldn't allocate memory.(%dbyte)\n", (int)fileInfo2.st_size ) ; exit(1) ;
} else if ( fread(labelData, fileInfo2.st_size, 1, fp) != 1 ) {
fprintf( stderr, "File '%s' read error.\n", argv[2] ); exit(1) ;
} else fclose(fp) ;
bmpFH = *(BITMAPFILEHEADER *)(originalBMP) ; // BMPファイルの構造を確認
bmpIH = *(BITMAPINFOHEADER *)((unsigned char *)originalBMP + sizeof(BITMAPFILEHEADER)) ;
if( bmpFH.bfType != 0x4D42 || bmpFH.bfReserved1 != 0 || bmpFH.bfReserved2 != 0 ) {
fprintf( stderr, "Bad BMP file format.\n" );
free(originalBMP); free(labelData); exit(1) ;
// 動的メモリーの開放(free)も exit() に全て任せる方法もある
} else if( bmpIH.biBitCount != 24 && bmpIH.biBitCount != 32 ) {
fprintf( stderr, "BITMAPINFOHEADER->biBitCount must be 24|32.\n" ) ;
free(originalBMP); free(labelData); exit(1) ;
// 動的メモリーの開放(free)も exit() に全て任せる方法もある
} else img = ((unsigned char *)originalBMP + bmpFH.bfOffBits) ;
// 32ビット形式の処理用バッファーを確保 (BGRAタイプのデーター形式)
if( bmpIH.biWidth*abs(bmpIH.biHeight)*4 != fileInfo2.st_size ) {
fprintf( stderr, "The size of a label data file is different from the BMP file.\n" ) ;
free(originalBMP); free(labelData); exit(1) ;
} else if( (imageData=(unsigned char *)malloc(bmpIH.biWidth*abs(bmpIH.biHeight)*4)) == NULL ) {// 動的メモリーの確保
fprintf( stderr, "Couldn't allocate memory.(%dbyte)\n", (int)(bmpIH.biWidth*abs(bmpIH.biHeight)*4) ) ;
free(originalBMP); free(labelData); exit(1) ;
} else img2image(img, imageData, bmpIH) ;
// 32ビット形式の処理用バッファーに画像データをコピー
// BMPデータと、ラベルデータと、特定の対象物を示すラベル番号 を使った処理の実行
processing( imageData, labelData, labelNumber, bmpIH.biWidth , abs(bmpIH.biHeight) ) ;
// 処理結果をBMPファイルとして書き出す。
saveDataAsBMP( oname, imageData, &bmpFH, &bmpIH ) ;
free(imageData) ; // 動的に確保したメモリーの解放
free(labelData) ; // 動的に確保したメモリーの解放
free(originalBMP) ; // 動的に確保したメモリーの解放
return 0 ;
}