これを画像に使ったらどうなるかと思って、プログラムにしてみました。
タイトルの通りフルカラー(24ビット)BMPを読み込んで16色BMPに変換するプログラムです。
使い方は、コマンドラインで
fto16color [/d]
と指定します。
/dオプションを付けると、error diffusionを使って見た目が良い画像を生成します。
デモ
元の画像 /dなし
- 変換後の画像1です。
- ryujin_16.png (22.79 KiB) 閲覧数: 248 回
Windows APIは使わずに、C言語の標準ライブラリで書きました。
► スポイラーを表示
#include
#include
#include
typedef struct {
double r;
double g;
double b;
} rgb_t;
int main(int argc,char* argv[]) {
FILE* fp;
/*入力変数*/
unsigned char header[0x36];
unsigned char* data;
int datasize;
int xsize,ysize;
int rivflag;
/*中間変数*/
rgb_t* colordata;
int linesize;
int x,y,yy,i;
double mindist;
double nowdist;
int minindex;
rgb_t gosa;
/*出力変数*/
int* outindex;
unsigned char* outdata;
int outsize;
/*カラーテーブル*/
const rgb_t colorlist[16]={
{ 0, 0, 0},
{ 0, 0,128},
{ 0,128, 0},
{ 0,128,128},
{128, 0, 0},
{128, 0,128},
{128,128, 0},
{128,128,128},
{192,192,192},
{ 0, 0,255},
{ 0,255, 0},
{ 0,255,255},
{255, 0, 0},
{255, 0,255},
{255,255, 0},
{255,255,255},
};
const unsigned char colortable[4*16]={
0x00,0x00,0x00,0x00,
0x00,0x00,0x80,0x00,
0x00,0x80,0x00,0x00,
0x00,0x80,0x80,0x00,
0x80,0x00,0x00,0x00,
0x80,0x00,0x80,0x00,
0x80,0x80,0x00,0x00,
0x80,0x80,0x80,0x00,
0xC0,0xC0,0xC0,0x00,
0x00,0x00,0xFF,0x00,
0x00,0xFF,0x00,0x00,
0x00,0xFF,0xFF,0x00,
0xFF,0x00,0x00,0x00,
0xFF,0x00,0xFF,0x00,
0xFF,0xFF,0x00,0x00,
0xFF,0xFF,0xFF,0x00
};
/*引数チェック*/
if(argc4 || (argc==4 && strcmp(argv[3],"/d"))) {
fprintf(stderr,"Usage: fto16color [/d]\n");
fprintf(stderr,"/d: use error diffusion\n");
return 1;
}
/*ファイルオープン*/
fp=fopen(argv[1],"rb");
if(fp==NULL) {
fprintf(stderr,"Can't open input file.\n");
return 2;
}
/*ヘッダの読み込み*/
if(fread(header,1,sizeof(header),fp)!=sizeof(header)) {
fprintf(stderr,"Can't read the header.\n");
fclose(fp);
return 3;
}
/*最初の部分の確認*/
if(header[0]!=0x42 || header[1]!=0x4D) {
fprintf(stderr,"This is not a bitmap file.\n");
fclose(fp);
return 4;
}
/*ビット数の確認*/
if(header[0x1C]+(header[0x1D]0) {
colordata[(y+1)*xsize+(x-1)].r+=gosa.r*3.0/16.0;
colordata[(y+1)*xsize+(x-1)].g+=gosa.g*3.0/16.0;
colordata[(y+1)*xsize+(x-1)].b+=gosa.b*3.0/16.0;
}
}
}
}
}
/*色のリストを開放*/
free(colordata);
/*出力データの作成*/
linesize=xsize/2;
if(xsize%2)linesize++;
if(linesize%4)linesize+=4-linesize%4;
outdata=calloc(ysize*linesize,1);
if(outdata==NULL) {
fprintf(stderr,"Can't allocate memory.(4)\n");
free(outindex);
return 12;
}
for(yy=0;yy> 8)&0xFF;
header[0x04]=(outsize>>16)&0xFF;
header[0x05]=(outsize>>24)&0xFF;
outsize=ysize*linesize;
/*画像データサイズ*/
header[0x22]= outsize &0xFF;
header[0x23]=(outsize>> 8)&0xFF;
header[0x24]=(outsize>>16)&0xFF;
header[0x25]=(outsize>>24)&0xFF;
/*ビット数*/
header[0x1C]=0x04;
/*ファイルに出力*/
fp=fopen(argv[2],"wb");
if(fp==NULL) {
fprintf(stderr,"Can't open output file.\n");
free(outdata);
return 13;
}
if(fwrite(header,1,sizeof(header),fp)!=sizeof(header)) {
fprintf(stderr,"File write failed.(1)\n");
fclose(fp);
free(outdata);
return 14;
}
if(fwrite(colortable,1,sizeof(colortable),fp)!=sizeof(colortable)) {
fprintf(stderr,"File write failed.(2)\n");
fclose(fp);
free(outdata);
return 15;
}
if(fwrite(outdata,1,outsize,fp)!=outsize) {
fprintf(stderr,"File write failed.(3)\n");
fclose(fp);
free(outdata);
return 16;
}
/*ファイルクローズ*/
fclose(fp);
/*出力画像データの開放*/
free(outdata);
/*正常終了*/
return 0;
}