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|