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|