list2.c
1|/***********************************************************************
2|* <<< ビットマップ・ファイルをプログラムの変数値にする [bmp2nvc] >>>
3|*【補足】
4|*・データ配列が書かれたソースファイルを出力します。
5|*・コンパイルは、cl bmp2nvc.c とします。
6|*・bmp2nvc.htm を参照
7|************************************************************************/
8|
9|#include <windows.h>
10|#include <string.h>
11|#include <stdio.h>
12|#include <stdlib.h>
13|
14|
15|FILE* file; /* 表示する画像のファイル */
16|BITMAPFILEHEADER head; /* 画像情報 1 */
17|BITMAPINFOHEADER info; /* 画像情報 2 */
18|int nPalettes; /* パレットの数 */
19|int iColumn = 0; /* ソース上の配列の列番号(0〜3) */
20|int pixelArray_n; /* ピクセル配列の要素数 */
21|long pixelArray_left; /* ピクセル配列の要素の残り数 */
22|const int pixelArray_max = 19920; /* 1つのピクセル配列の要素数の最大 */
23|int nPixelArray; /* ピクセル配列の数 */
24|int clip_use = 0; /* true/flase */
25|int clip_x = 0;
26|int clip_y = 0;
27|int clip_width = 9999;
28|int clip_height = 9999;
29|char* bmp_fname;
30|static char bmp_fname1[256]; /* 拡張子を抜いたファイル名 */
31|enum { CLang, Asm };
32|int outLang = CLang;
33|
34|
35|
36|/***********************************************************************
37|* <<< [main] メイン ★>>>
38|************************************************************************/
39|int main( int argc, char* argv[] )
40|{
41| read_header( argc, argv ); /* ヘッダ(画像情報)を読み込む */
42| status_print(); /* 画像の情報を表示する */
43| clip_set(); /* クリップ領域をビット・マップ・ファイルの大きさに合わせる */
44| clip_print(); /* クリップ領域の情報を表示する */
45| img_out(); /* 画像とその補助情報を標準出力に出力する */
46| fclose( file ); /* ファイルを閉じる */
47|
48| return 0;
49|}
50|
51|
52|/***********************************************************************
53|* <<< [read_header] ヘッダ(画像情報)を読み込む >>>
54|************************************************************************/
55|int read_header( int argc, char** argv )
56|{
57| char* p;
58|
59| /* 表示する画像のファイル file を開く */
60| if ( argc < 2 || argc > 3 ) return -1;
61| bmp_fname = argv[argc-1];
62| strcpy( bmp_fname1, bmp_fname );
63| p = strchr( bmp_fname1, '.' );
64| if ( p ) *p = '\0';
65|
66| file = fopen( bmp_fname, "rb" );
67| if ( file == NULL ) except();
68|
69| /* オプションの解析 */
70| if ( argc == 3 || argc == 4 || argc == 5 ) {
71| for ( i = 1; i < argc-1; i++ ) {
72| if ( memcmp( argv[i], "-clip", 5 ) == 0 ) {
73| sscanf( argv[i]+5, "%d,%d,%d,%d",
74| &clip_x, &clip_y, &clip_width, &clip_height );
75| clip_use = 1;
76| }
77| if ( memcmp( argv[i], "-a", 3 ) == 0 )
78| outLang = Asm;
79| }
80| }
81| /* 読み込む */
82| fread( &head, sizeof(head), 1, file );
83| fread( &info, sizeof(info), 1, file );
84|
85| /* 対応しているファイル形式かチェックする */
86| if ( head.bfType != 0x4D42 ) except();
87| if ( info.biCompression != 0 ) except();
88|
89| /* パレットの数 nPalettes を得る */
90| if ( info.biBitCount == 8 ) nPalettes = 256;
91| else if ( info.biBitCount == 4 ) nPalettes = 16;
92| else except();
93|}
94|
95|
96|/***********************************************************************
97|* <<< [status_print] 画像の情報を表示する(標準エラー表示する) >>>
98|************************************************************************/
99|void status_print()
100|{
101| fprintf( stderr, "%s\n", bmp_fname );
102| fprintf( stderr, " colors : %d\n", nPalettes );
103| fprintf( stderr, " size : %ld x %ld\n", info.biWidth, info.biHeight );
104| if ( clip_use ) {
105| fprintf( stderr, " clip : (%d, %d)-(%d, %d) [size=%d,%d]\n",
106| clip_x, clip_y, clip_x + clip_width - 1, clip_y + clip_height - 1,
107| clip_width, clip_height );
108| }
109|}
110|
111|/***********************************************************************
112|* <<< [clip_set] クリップ領域をビット・マップ・ファイルの大きさに合わせる >>>
113|*【補足】
114|*・クリップ領域を 4で割り切れるようにしています。
115|************************************************************************/
116|void clip_set()
117|{
118| if ( clip_x < 0 ) { clip_width -= -clip_x; clip_x = 0; }
119| if ( clip_x + clip_width > info.biWidth ) clip_width = (int)(info.biWidth - clip_x);
120| if ( clip_y < 0 ) { clip_height -= -clip_y; clip_y = 0; }
121| if ( clip_y + clip_height > info.biHeight ) clip_height = (int)(info.biHeight - clip_y);
122| clip_width = ((clip_x + clip_width + 3) & 0xFFFC) - clip_x;
123| clip_x &= 0xFFFC;
124|}
125|
126|/***********************************************************************
127|* <<< [clip_print] クリップ領域の情報を表示する(標準エラー表示する) >>>
128|************************************************************************/
129|void clip_print()
130|{
131| if ( clip_use ) {
132| fprintf( stderr, " bmp : (%d, %d)-(%d, %d) [size=%d,%d]\n",
133| clip_x, clip_y, clip_x + clip_width - 1, clip_y + clip_height - 1,
134| clip_width, clip_height );
135| }
136|}
137|
138|
139|/***********************************************************************
140|* <<< [img_out] 画像とその補助情報を標準出力に出力する >>>
141|************************************************************************/
142|void img_out()
143|{
144| int y;
145| RGBQUAD rgb; /* パレットの色 */
146| unsigned char* iPalette; /* パレット番号(ピクセル)の配列[x] */
147| int fileWidth; /* ファイルの中のピクセル幅(byte) */
148|
149| /* fileWidth を初期化する。4 byte アラインメントする */
150| if ( info.biBitCount == 24 ) fileWidth = (int)(info.biWidth) * 3;
151| else if ( nPalettes == 256 ) fileWidth = (int)(info.biWidth);
152| else if ( nPalettes == 16 ) fileWidth = (int)(info.biWidth / 2);
153| fileWidth += (int)( info.biWidth % 4 == 0 ? 0 : 4 - info.biWidth % 4 );
154|
155| iPalette = (unsigned char*)
156| malloc( sizeof(unsigned char) * (int)(info.biWidth + 1) );
157| memset( iPalette, 0, (size_t)info.biWidth + 1 );
158|
159| /* ビットマップデータを出力する */
160| out_palette();
161| out_pixel_pattern();
162| out_data_func();
163|
164| /* 後始末する */
165| free( iPalette );
166|}
167|
168|/***********************************************************************
169|* <<< [out_palette] パレット情報を出力する >>>
170|************************************************************************/
171|void out_palette()
172|{
173| /* サイズとパレット数を出力する */
174| if ( outLang == CLang ) {
175| printf( "/* the data of %s (%d colors, size = %ldx%ld) */\n\n",
176| bmp_fname, nPalettes, info.biWidth, info.biHeight );
177| }
178| else { /* Asm */
179| printf( "# the data of %s (%d colors, size = %ldx%ld)\n\n",
180| bmp_fname, nPalettes, info.biWidth, info.biHeight );
181| printf( " .data\n" );
182| }
183|
184| /* パレット情報を出力する */
185| if ( outLang==CLang )
186| printf( "int %s_palette[%d] = {\n", bmp_fname1, nPalettes );
187| else /* Asm */
188| printf( " .globl _%s_palette\n_%s_palette:\n", bmp_fname1, bmp_fname1 );
189| for ( i = 0; i < nPalettes; i++ ) {
190| fread( &rgb, sizeof(rgb), 1, file );
191| if ( i % 8 == 0 ) {
192| if ( outLang==CLang ) printf( " " );
193| else /* Asm */ printf( " .word " );
194| }
195| printf( "0x%03X", ((unsigned int)(rgb.rgbRed & 0xF0) << 4) |
196| ((unsigned int)(rgb.rgbGreen & 0xF0)) |
197| ((unsigned int)(rgb.rgbBlue & 0xF0) >> 4) );
198| if ( i % 8 < 7 ) printf( ", " );
199| else {
200| if ( outLang == CLang ) printf( ",\n" );
201| else /* Asm */ printf( "\n" );
202| }
203| }
204| if ( outLang==CLang ) printf( "};\n\n" );
205| else /* Asm */ printf( "\n" );
206|}
207|
208|/***********************************************************************
209|* <<< [out_pixel_pattern] 画像のピクセルパターンを出力する >>>
210|************************************************************************/
211|void out_pixel_pattern()
212|{
213| nPixelArray = 1; pixelArray_n = 0;
214| pixelArray_left = (long)clip_width * clip_height / 4;
215| if ( outLang == CLang ) {
216| printf( "/* ピクセル・データは画像の下から上へ格納されています */\n" );
217| printf( "int %s_pixel%d[%ld] = {\n", bmp_fname1, nPixelArray,
218| (pixelArray_left < pixelArray_max ? pixelArray_left : (long)pixelArray_max) );
219| }
220| else { /* Asm */
221| printf( "# ピクセル・データは画像の下から上へ格納されています\n" );
222| printf( " .globl _%s_pixel%d\n_%s_pixel%d:\n",
223| bmp_fname1, nPixelArray, bmp_fname1, nPixelArray );
224| }
225| for ( y = (int)info.biHeight - 1; y >= 0; y-- ) {
226| int x;
227|
228| /* ファイルから 1行分のピクセル列(パレット番号列)を */
229| /* iPalette に読み込む */
230| fread( iPalette, 1, fileWidth, file );
231|
232| /* クリッピング領域外ならスキップ */
233| if ( y < clip_y || y >= clip_y + clip_height )
234| continue;
235|
236| /* 16色の場合、PixelParByte==2 の iPalette を */
237| /* PixelParByte==1 に変更 */
238| if ( nPalettes == 16 ) {
239| for ( x = fileWidth - 1; x >= 0; x-- ) {
240| if ( x % 2 == 1 )
241| iPalette[x] = iPalette[x/2] & 0x0F;
242| else
243| iPalette[x] = iPalette[x/2] >> 4;
244| }
245| }
246|
247| /* ピクセル列(パレット番号列)iPalette を出力する */
248| {
249| #define nPixel_byLine 4
250| for ( x = 0; x < fileWidth / nPixel_byLine; x++ ) {
251| if ( x >= clip_x / 4 && x < (clip_x + clip_width) / 4 ) {
252| if ( iColumn == 0 ) {
253| if ( outLang == CLang ) printf( " " );
254| else /* Asm */ printf( " .word " );
255| }
256|
257| /* ピクセル列の出力 */
258| printf( "0x%08lX", *(long*)(iPalette + x *nPixel_byLine) );
259|
260| /* 4列ごとの改行 */
261| if ( iColumn != nPixel_byLine-1 ) {
262| if ( y!=0 || x != fileWidth / nPixel_byLine - 1 )
263| { printf( ", " ); iColumn++; }
264| else
265| printf( "\n" );
266| }
267| else {
268| if ( outLang == CLang ) printf( ",\n" );
269| else /* Asm */ printf( "\n" );
270| iColumn = 0;
271| }
272| /* 配列の要素数が pixelArray_max を超えたら次の配列を作る */
273| /* pixelArray_max を超えると、ca732 が次のエラーになる */
274| /* Abnormal program termination: Memory protection fault */
275| pixelArray_n ++;
276| if ( pixelArray_n >= pixelArray_max &&
277| pixelArray_left > pixelArray_max ) {
278| if ( outLang == CLang ) printf( "};\n" );
279| else /* Asm */ printf( "\n" );
280|
281| nPixelArray ++;
282| pixelArray_n = 0;
283| pixelArray_left -= pixelArray_max;
284| if ( outLang == CLang )
285| printf( "int %s_pixel%d[%ld] = {\n", bmp_fname1, nPixelArray,
286| (pixelArray_left < pixelArray_max ? pixelArray_left : (long)pixelArray_max) );
287| else /* Asm */
288| printf( " .globl _%s_pixel%d\n_%s_pixel%d:\n",
289| bmp_fname1, nPixelArray, bmp_fname1, nPixelArray );
290| }
291| }
292| }
293| #undef nPixel_byLine
294| }
295| }
296| if ( outLang==CLang ) printf( "};\n\n" );
297| else /* Asm */ printf( "\n" );
298|}
299|
300|/***********************************************************************
301|* <<< [out_data_func] データ参照関数を出力する >>>
302|************************************************************************/
303|void out_data_func()
304|{
305| if ( outLang == CLang ) {
306|
307| /* ピクセル配列へのポインタの配列を出力する。理由は pixelArray_max より */
308| printf( "int* %s_pixelArray[%d];\n", bmp_fname1, nPixelArray );
309| printf( "int %s_pixelArray_n[%d];\n\n", bmp_fname1, nPixelArray );
310| printf( "#include \"nvcbmp.h\"\n" );
311| printf( "static NvcBmp_File %s_file;\n\n", bmp_fname1 );
312|
313| /* データ参照関数を出力する */
314| printf( "/*\n" );
315| printf( "* ビットマップ・ファイル・データ %s を返す\n", bmp_fname1 );
316| printf( "*/\n" );
317| printf( "NvcBmp_File* %s_get()\n", bmp_fname1 );
318| printf( "{\n" );
319| printf( " %s_file.width = %d;\n", bmp_fname1, clip_width );
320| printf( " %s_file.height = %d;\n", bmp_fname1, clip_height );
321| printf( " %s_file.nPalette = %d;\n", bmp_fname1, nPalettes );
322| printf( " %s_file.palette = %s_palette;\n",
323| bmp_fname1, bmp_fname1, nPalettes );
324| printf( " %s_file.nPixelArray = %d;\n", bmp_fname1, nPixelArray );
325| printf( " %s_file.pPixelArray = %s_pixelArray;\n",
326| bmp_fname1, bmp_fname1, nPixelArray );
327| printf( " %s_file.pPixelArray_n = %s_pixelArray_n;\n\n",
328| bmp_fname1, bmp_fname1, nPixelArray );
329|
330| for ( i = 0; i < nPixelArray; i++ ) {
331| printf( " %s_pixelArray[%d] = %s_pixel%d;\n",
332| bmp_fname1, i, bmp_fname1, i+1 );
333| printf( " %s_pixelArray_n[%d] = %d;\n", bmp_fname1, i,
334| ( i < nPixelArray -1 ? pixelArray_max : pixelArray_left ) );
335| }
336| printf( "\n return &%s_file;\n", bmp_fname1 );
337| printf( "}\n" );
338| }
339| else { /* Asm */
340| printf( " .globl _%s_pixelArray\n_%s_pixelArray:\n",
341| bmp_fname1, bmp_fname1 );
342| for ( i = 1; i <= nPixelArray; i++ ) {
343| if ( i % 4 == 1 ) printf( " .word " );
344| printf( "#_%s_pixel%d", bmp_fname1, i );
345| if ( i < nPixelArray ) {
346| if ( i % 4 != 0 && i!=nPixelArray) printf( ", " );
347| else printf( "\n" );
348| }
349| else printf( "\n" );
350| }
351| printf( "\n" );
352|
353| printf( " .globl _%s_pixelArray_n\n_%s_pixelArray_n:\n",
354| bmp_fname1, bmp_fname1 );
355| for ( i = 1; i <= nPixelArray; i++ ) {
356| if ( i % 4 == 1 ) printf( " .word " );
357| printf( "%d",
358| ( i < nPixelArray ? pixelArray_max : pixelArray_left ) );
359| if ( i < nPixelArray ) {
360| if ( i % 4 != 0 && i!=nPixelArray) printf( ", " );
361| else printf( "\n" );
362| }
363| else printf( "\n" );
364| }
365| printf( "\n" );
366|
367| printf( " .globl _%s_file\n_%s_file:\n", bmp_fname1, bmp_fname1 );
368| printf( " .word %d, %d, %d, #_%s_palette\n",
369| clip_width, clip_height, nPalettes, bmp_fname1 );
370| printf( " .word #_%s_pixelArray, #_%s_pixelArray_n, %d\n\n",
371| bmp_fname1, bmp_fname1, nPixelArray );
372| printf( "# C 言語の %s_get() 関数の代わり\n", bmp_fname1 );
373| printf( " .text\n" );
374| printf( " .globl _%s_get\n_%s_get:\n", bmp_fname1, bmp_fname1 );
375| printf( " mov #_%s_file, r10\n", bmp_fname1 );
376| printf( " jmp [lp]\n" );
377| }
378|}
379|
380|
381|/***********************************************************************
382|* <<< [except] エラー時の処理 >>>
383|************************************************************************/
384|void except()
385|{
386| fprintf( stderr, " Can't generate the file.\n" );
387| fprintf( stderr, " usage: bmp2nvc [-clipX,Y,W,H | -a] (bmp file name) > source.c\n" );
388|
389| exit(1);
390|}
391|
392|