ホームに戻る
 アイコンを作る

ビットマップから32*32で256色のアイコンを作ります。
LSIC-86(試食版)用です。

Borland C++ Compilerで使えるアイコンを作りたかったのがそもそもの作ろうと思った動機で、
アイコンファイルの仕様を調べようと思ったのですがいまいちよくわかりませんでした。
よって頭のアイコン情報部分は他のアイコンファイルのデータをそのままコピー。
実データ部分のみを作るようにしました(いい加減です)。

そういうわけで実データなのですが、
256色ぶんのカラーテーブル、32×32での色番号、透明部分情報、
の順になっているようです。

カラーテーブルは1色につき32ビットぶんの領域が必要。
色は「00BBGGRR」と指定し各RGB成分でそれぞれ8ビット使います。
とすると色自体は256×256×256色指定できるようです。
テーブルには色を必ず256個指定します。
よってテーブルサイズは4(32ビット)×256となります。

色情報はカラーテーブルの登録順に番号を指定します。
カラーテーブル1番の色を使う時は8ビットの領域で1を指定。
テーブルの色は256個なので1ピクセルにつき8ビットで足りる。
色情報は32×32ピクセルなのでサイズは32×32×1だけ必要。

透明部分情報はビット単位でビットに1をたてると透明になるようです。
よって8ピクセルの透明情報を1バイトで表せる。
32×32ピクセルだからサイズは32×32÷8だけ必要。
透明にしたい部分の色は必ず「00000000」とする。

カラーテーブルと色情報の間に1バイトの0を挟んでるところなど不明なところもありますが、
Borland C++ Compilerではなんとかこれでアイコンとして通るようです。

使い方はコンソールで

ico before.bmp after.ico

のようにします。

ビットマップは32×32ピクセルで24ビット、256色まで使ったものを用意。
(256色より多い色の対応は考えてませんのでどんな動作になるかは不明)
いちばん左下のピクセルを勝手に透明色にします。

とりあえずアイコンが出来ればよいときに使ってください。

#include <stdio.h>
#include <stdlib.h>

typedef struct tagBITMAPFILEHEADER{   /* ファイルそのものの情報 */
  char bfType[2];   /* BM の2文字 */
  unsigned long bfSize;   /* ファイルのサイズ */
  unsigned int bfReserved1;   /* 予約領域1 */
  unsigned int bfReserved2;   /* 予約領域2 */
  unsigned long bfOffBits;   /* 実データまでのオフセット */
}BITMAPFILEHEADER;

typedef struct tagBITMAPINFOHEADER{ /* BITMAPの情報 */
  unsigned long biSize;   /* この構造体のサイズ */
  long biWidth;   /* ビットマップの横幅(ピクセル) */
  long biHeight;   /* ビットマップの縦幅(ピクセル) */
  unsigned int biPlanes;    /* プレーン数 (1) */
  unsigned int biBitCount;   /* ピクセルあたりの色数 (1 4 8 24) */
  unsigned long biCompression;   /* 圧縮方式 (圧縮なし=0) */
  unsigned long biSizeImage;   /* ビットマップビット (圧縮時のみ) */
  long biXPelsPerMeter;   /* 水平解像度 (ピクセル数/1メートル) */
  long biYPelsPerMeter;   /* 垂直解像度 (ピクセル数/1メートル) */
  unsigned long biClrUsed;   /* 使用する色数 */
  unsigned long biClrImportant;   /* 使用する実色数 */
}BITMAPINFOHEADER;

/*
*   32*32 24ビット のビットマップから色情報部分を取り出しファイルセーブ
*/
int read_bmp(char *read_file, char *write_file){
  char *bitmap_data;

  FILE *fp, *fp2;
  BITMAPFILEHEADER FileHeader;
  BITMAPINFOHEADER InfoHeader;

  if((fp = fopen(read_file, "rb")) == NULL){
    printf("Read Failed:%s\n", read_file);
    return 0;
  }

  fread(&FileHeader, sizeof(BITMAPFILEHEADER), 1, fp);
  fread(&InfoHeader, sizeof(BITMAPINFOHEADER), 1, fp);

  if(InfoHeader.biWidth != 32 || InfoHeader.biHeight != 32){
    fclose(fp);
    return 0;
  }

  if(InfoHeader.biBitCount != 24){
    fclose(fp);
    return 0;
  }

  fseek(fp, FileHeader.bfOffBits, 0);

  bitmap_data = (char *)malloc(32 * 32 * 3);

  fread(bitmap_data, sizeof(char), 32 * 32 * 3, fp);

  fclose(fp);

  if((fp2 = fopen(write_file, "wb")) == NULL){
    free(bitmap_data);
    return 0;
  }

  fwrite(bitmap_data, sizeof(char), 32 * 32 * 3, fp2);

  free(bitmap_data);

  fclose(fp2);

  return 1;
}

#define TEMP_FILE_NAME "temp.out"

#define HEADER_SIZE 61
#define MAX_COLOR_TABLE 256
#define ICON_WIDTH 32
#define ICON_HEIGHT 32
#define ICON_MASK 128

char header[HEADER_SIZE] = {
  0x00,0x00,0x01,0x00,0x01,0x00,0x20,0x20,
  0x00,0x00,0x00,0x00,0x00,0x00,0xA8,0x08,
  0x00,0x00,0x16,0x00,0x00,0x00,0x28,0x00,
  0x00,0x00,0x20,0x00,0x00,0x00,0x40,0x00,
  0x00,0x00,0x01,0x00,0x08,0x00,0x00,0x00,
  0x00,0x00,0x80,0x04,0x00,0x00,0x00,0x00,
  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
  0x00,0x00,0x00,0x00,0x00};

typedef struct _color_table{
  char clear;
  char blue;
  char green;
  char red;
}color_table;

typedef int color_table_index;
typedef unsigned char color_data;
typedef char mask_data;

color_table_index ct_index;
color_table ct[MAX_COLOR_TABLE];
color_data cd[ICON_WIDTH * ICON_HEIGHT];
mask_data md[ICON_MASK];

void init(){
  int i;
  ct_index = 0;
  for(i = 0; i < MAX_COLOR_TABLE; i++){
    ct[i].clear = 0x00;
    ct[i].blue = 0x00;
    ct[i].green = 0x00;
    ct[i].red = 0x00;
  }
  for(i = 0; i < ICON_HEIGHT * ICON_WIDTH; i++){
    cd[i] = 0x00;
  }
  for(i = 0; i < ICON_MASK; i++){
    md[i] = 0x00;
  }
}

int set_data(char *file_name){
  int i, j;
  char rgb[3];
  FILE *fp;

  if((fp = fopen(file_name, "rb")) == NULL){
    return 0;
  }

  for(i = 0; i < 32 * 32; i++){
    int flag = 0;
    fread(rgb, sizeof(char), 3, fp);
    for(j = 0; j < ct_index; j++){
      if(rgb[2] == ct[j].red && rgb[1] == ct[j].green && rgb[0] == ct[j].blue){
        flag = 1;
        break;
      }
    }

    if(flag == 0){
      cd[i] = ct_index;
      if(ct_index < MAX_COLOR_TABLE - 1){
        ct[ct_index].red = rgb[2];
        ct[ct_index].green = rgb[1];
        ct[ct_index].blue = rgb[0];
        ct_index++;
      }
    }
    else{
      cd[i] = j;
    }

    if(cd[i] == 0){
      if(i / 8 < ICON_MASK){
        md[i / 8] |= 0x80 >> (i % 8);
      }
    }
  }

  ct[0].red = 0x00;
  ct[0].green = 0x00;
  ct[0].blue = 0x00;

  fclose(fp);

  return 1;
}

int save_icon(char *file_name){
  int i;
  FILE *fp;

  if((fp = fopen(file_name, "wb")) == NULL){
    printf("Save Failed.\n");
    return 0;
  }

  for(i = 0; i < HEADER_SIZE; i++){
    fprintf(fp, "%c" ,header[i]);
  }
  for(i = 0; i < MAX_COLOR_TABLE; i++){
    fprintf(fp, "%c%c%c%c" ,ct[i].clear, ct[i].blue, ct[i].green, ct[i].red);
  }
  fprintf(fp, "%c" ,0x00);
  for(i = 0; i < ICON_HEIGHT * ICON_WIDTH; i++){
    fprintf(fp, "%c" ,cd[i]);
  }
  for(i = 0; i < ICON_MASK; i++){
    fprintf(fp, "%c" ,md[i]);
  }

  fclose(fp);

  return 1;
}

int main(int argc, char *argv[]){
  if(argc != 3){
    printf("usage:ico before.bmp after.ico\n");
    return 1;
  }

  printf("start\n");

  if(!read_bmp(argv[1], TEMP_FILE_NAME)){
    printf("read_bitmap_error\n");
    printf("32*32 24bit bitmap only\n");
    return 1;
  }

  printf("read_bitmap\n");

  init();

  if(!set_data(TEMP_FILE_NAME)){
    printf("make_icon_error\n");
    return 1;
  }

  printf("make_icon\n");

  if(!save_icon(argv[2])){
    printf("save_icon_error\n");
    return 1;
  }

  printf("save_icon\n");

  return 0;
}

inserted by FC2 system