/* chs.cpp */ #include #include using namespace std; // .bmp ファイルのヘッダー 少し省略しています typedef struct { char bfType[2]; // 'BM' int bfSize; // ファイルサイズ、4 byte char bfReserved1[2]; // 常に 0 char bfReserved2[2]; int bfOffBits; // ファイル先頭から画像データまでのオフセット int bcSize; // ヘッダーサイズ int bcWidth; // 画像の幅 (ピクセル) int bcHeight; // 画像の高さ (ピクセル)、負数なら画像データは上から下 short int bcPlanes; // プレーン数、常に 1 short int bcBitCount; // 1 画素あたりのデータサイズ (bit)、256 色ビットマップなら 8 int biCompresson; // 圧縮形式、0:無圧縮 int biSizeImage; // 画像データ部のサイズ (byte) int biPad[4]; } bmp_hdr; bmp_hdr* q; int a_c, a_v[3]; // command line argument unsigned char *p0; // malloc() で確保したメモリーの先頭アドレス int bsz = 3*(516*516)+512; /* 2点間の距離の計算 float dist2(int ox, int oy, int i, int j) { float xd, xe, xf; xd = pow(ox - i, 2); xe = pow(oy - j, 2); xf = pow(xd + xe, 0.5); // (ox, oy) からの距離 return xf; } */ // 座標上の定点(x, y: 0 .. 511) int pt1[] = {71, 71}; int pt2[] = {71, 512-71}; int pt3[] = {512-71, 71}; int pt4[] = {512-71, 512-71}; // 実際に描画したカラー値の最大最小 unsigned char cmx = 0, cmi = 255; // 定点からの距離 float df_pt(int pt[], int i, int j) { return (pow(pow(pt[0]-i, 2) + pow(pt[1]-j, 2), 0.5)); } // 定点からの距離に応じて、0..255 の値を返す unsigned char cdav1(int pt[], int i, int j) { float cf1 = 213/(sqrt(2)*(512-2*71)); float ds; unsigned char c; ds = df_pt(pt, i, j); c = 255 - cf1*ds; if (c > cmx) cmx = c; if (c < cmi) cmi = c; return((c == 10) ? 9 : c); // 0x0a 描画はヨクナイ } // 定点からの距離に応じて、色の強度を波打たせる float cf2 = (3*M_PI) / (sqrt(2)*(512-2*71)); // 距離から cos() の引数への変換係数 unsigned char cdav2(int pt[], int i, int j) { float a; unsigned char c; a = cf2 * pow(pow(pt[0]-i, 2) + pow(pt[1]-j, 2), 0.5); c = (cos(a)+1)*(256/2); if (c > cmx) cmx = c; if (c < cmi) cmi = c; return((c == 10) ? 9 : c); } // 描画 df1 int df1(unsigned char* s0) { unsigned char (*cdav)(int pt[], int i, int j); // 使う関数 unsigned char* d; int i, j; if (a_v[0] == 1) { // 関数選択と第2アーギュメントの処理 cdav = &cdav1; } else if (a_v[0] == 2) { cdav = &cdav2; if (a_c == 3 && (1 <= a_v[1] && a_v[1] < 512)) cf2 = (a_v[1]*M_PI) / (sqrt(2)*(512-2*71)); } else if (a_v[0] == 3) cdav = &cdav2; for (i = 0; i < 512; i += 1) { d = s0 + 3*(516*(i+2) + 2); // 左下隅に XY 各 2dot 開ける for (j = 0; j < 512; j += 1) { *d++ = cdav(pt1, i, j); // B 色 *d++ = cdav(pt2, i, j); // R 色 *d++ = cdav(pt3, i, j); // G 色 } if (a_v[0] == 3) cf2 *= 1.008; // 波数/距離 を漸次増加させる } printf("c: max %d, min %d\n", cmx, cmi); return 0; } // 距離からカラー値への変換関数(df2) inline unsigned char cdv(int pt[], int i, int j) { float dm = sqrt(2)*(512-71); float ds; int ci; unsigned char c; ds = pow(pow(pt[0]-i, 2) + pow(pt[1]-j, 2), 0.5); ci = 255*cos(6.0*M_PI*pow((ds/dm), 2)); c = (ci > 0) ? ci : 0; return c; } int df2(unsigned char* s0) { // a_v[0] >= 4 unsigned char *d, cb, cr, cg, cy, c; int i, j; for (i = 0; i < 512; i += 1) { d = s0 + 3*(516*(i+2) + 2); // 左下隅に XY 各 2dot 開ける for (j = 0; j < 512; j += 1) { cb = cdv(pt1, i, j); cr = cdv(pt2, i, j); cg = cdv(pt3, i, j); cy = cdv(pt4, i, j); if (a_v[1] < 1) { // 1ピクセルごとに argv を調べるのはヨクナイ *d++ = (cb == 10) ? 9 : cb; // B 色 c = (cr > cy) ? cr : cy; *d++ = (c == 10) ? 9 : c; // R 色 c = (cg > cy) ? cg : cy; *d++ = (c == 10) ? 9 : c; // G 色 } else if (a_v[1] == 1) { *d++ = (cb == 10) ? 9 : cb; // B 色 *d++ = (cr == 10) ? 9 : cr; // R 色 *d++ = (cg == 10) ? 9 : cg; // G 色 } else if (a_v[1] == 2) { c = (cy == 10) ? 9 : cy; *d++ = 0; *d++ = c; *d++ = c; } } } return 0; } int main(int argc, char* argv[]) { FILE* fp; // 入出力ファイルの FILE* size_t n; // fread() などの戻り値 unsigned char *s; // コマンドライン アーギュメント の処理 a_c = argc; if (a_c >= 2) sscanf(argv[1], "%d", &a_v[0]); if (a_c >= 3) sscanf(argv[2], "%d", &a_v[1]); printf("a_c %d: a_v %d, %d, %d\n", a_c, a_v[0], a_v[1], a_v[2]); if (a_c < 2 || a_c > 3) { printf("Bye.\n"); return -1; } // malloc() 実行 p0 = (unsigned char *)malloc(bsz); if (!p0) { printf("malloc() fail.\n"); return -1; } printf("p0 0x%x, size %d\n", p0, bsz); // 読み込み fp = fopen("white24.bmp", "r"); if (!fp) { printf("fopen(r) fail.\n"); return -1; } n = fread(p0, sizeof(unsigned char), bsz, fp); // ホントは size を調べるべき printf("%d byte read.\n", n); if (n <= 0) return -1; fclose(fp); // ファイル *.bmp のヘッダーを表示 q = (bmp_hdr *)(p0-2); // 謎の -2 です s = (unsigned char *)p0; printf("%c%c, ", *s, *(s+1)); printf("fSize %d, offset 0x%x, width %d, height %d, planes %d, bit/px %d\n", q->bfSize, q->bfOffBits, q->bcWidth, q->bcHeight, q->bcPlanes, q->bcBitCount); printf("compr %d, imSize %d, biPad 0x%x 0x%x 0x%x 0x%x\n", q->biCompresson, q->biSizeImage, q->biPad[0], q->biPad[1], q->biPad[2], q->biPad[3]); if (q->biSizeImage < 798768) { printf("'white.bmp' too small.\n"); return -1; } // ヘッダーの内容が妥当であるかのチェックは、だいぶ省略 // 出力ファイル open fp = fopen("chs.bmp", "w"); if (!fp) { printf("fopen(w) fail.\n"); return -1; } // 描画 if (a_v[0] < 4) df1(p0 + q->bfOffBits); else df2(p0 + q->bfOffBits); // ファイル書き込み n = fwrite(p0, sizeof(unsigned char), n, fp); printf("chs.bmp: %d byte written.\n", n); // 終了 fclose(fp); free(p0); system("mspaint chs.bmp"); // mspaint 実行 return 0; }