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