/* cht.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; float a_v[2]; // command line argument unsigned char *m0, *m1; // malloc() で確保したメモリーの先頭アドレス int bsz1 = 3*(516*516)+512; // white24.bmp を読み込み、描画する int bsz2 = 3*(510*510); // 計算結果を一時格納する領域 // メモリー内容を 16 進表示でダンプ void dump(unsigned char* d0, unsigned char* bse, int nl) { int n, m; for (n = 0; n < nl; n += 1) { printf(" %06d: ", d0 - bse); // 注: 相対アドレスは 10 進数 for (m = 0; m < 8; m += 1) { // ↓ *d0++ はヨクナイ printf("%02x %02x %02x ", *d0, *(d0+1), *(d0+2)); d0 += 3; } printf("\n"); } } // 「朱に交われば赤くなる」の 二次元版 float npx4(unsigned char* p0, unsigned char* p1, unsigned char* p2) { // float k0 = 1.0; const float k1 = sqrt(2); // 重みづけ係数 const float k2 = 4*(sqrt(2)+1); // 中心点は全体9点の 1/2 の重み const float k3 = 1/(8*(sqrt(2)+1)); // 1に正規化 float rv; rv = *p2 + *(p2+6) + *p0 + *(p0+6); // 地図で言う、北西・北東・南西・南東方向の斜め隣 rv += k1*(*(p2+3) + *p1 + *(p1+6) + *(p0+3)); // 同、北・西・東・南の隣 rv += k2*(*(p1+3)); // 注目する中心点 return k3*rv; } // 以下、中心点の重みが、順に小さくなる関数 float npx3(unsigned char* p0, unsigned char* p1, unsigned char* p2) { const float k1 = sqrt(2); // 重みづけ係数 const float k2 = 3*(sqrt(2)+1); // 中心点は全体9点の 3/7 の重み const float k3 = 1/(7*(sqrt(2)+1)); float rv; rv = *p2 + *(p2+6) + *p0 + *(p0+6); rv += k1*(*(p2+3) + *p1 + *(p1+6) + *(p0+3)); rv += k2*(*(p1+3)); return k3*rv; } float npx2(unsigned char* p0, unsigned char* p1, unsigned char* p2) { const float k1 = sqrt(2); // 重みづけ係数 const float k2 = 2*(sqrt(2)+1); // 中心点は全体9点の 1/3 の重み const float k3 = 1/(6*(sqrt(2)+1)); float rv; rv = *p2 + *(p2+6) + *p0 + *(p0+6); rv += k1*(*(p2+3) + *p1 + *(p1+6) + *(p0+3)); rv += k2*(*(p1+3)); return k3*rv; } float npx1(unsigned char* p0, unsigned char* p1, unsigned char* p2) { const float k1 = sqrt(2); // 重みづけ係数 const float k2 = sqrt(2)+1; // 中心点は全体9点の 1/5 の重み const float k3 = 1/(5*(sqrt(2)+1)); float rv; rv = *p2 + *(p2+6) + *p0 + *(p0+6); rv += k1*(*(p2+3) + *p1 + *(p1+6) + *(p0+3)); rv += k2*(*(p1+3)); return k3*rv; } // 描画 void df1(unsigned char* s0) { unsigned char *p0, *p1, *p2, *d, c; int i, j, k1, k2, n, nmax = 0; // 背景 c = 64; for (i = 0; i < 512; i += 1) { d = s0 + 3*(516*(i+2) + 2); // 余白 2 pixel づつ for (j = 0; j < 512; j += 1) *d++ = c, *d++ = c, *d++ = c; } // 「タネ」 を作る #if 0 // 縦長三角形 if (a_c >= 2) if (a_v[0] > 0 && a_v[0] <= 400) { nmax = a_v[0]; printf(" nmax: %d\n", nmax); } c = 255; k1 = 256-70; k2 = 256+70; for (i = 256-92; i < 512; i += 1) { d = s0 + 3*(516*(i+2) + 2); for (j = 0; j < 512; j += 1) { if (k1 <= j && j < k2) *d++ = 0, *d++ = c, *d++ = c; else d += 3; } if (i % 3 == 2) k1 += 1, k2 -= 1; if (k1 >= k2) break; } printf("df1: i %d, k1 %d, k2 %d\n", i, k1, k2); #else // 楕円形モドキ float oxi, oyj; float a, b, th, mt = 0.25; if (a_c >= 2) mt = a_v[0]; if (a_c >= 3) nmax = (int)a_v[1]; printf(" mt: %f, nmax %d\n", mt, nmax); c = 255; for (i = 0; i < 512; i += 1) { d = s0 + 3*(516*(i+2) + 2); oxi = 256-i; for (j = 0; j < 512; j += 1) { oyj = 256-j; a = pow(pow(oxi, 2) + pow(oyj, 2), 0.5); th = (oxi != 0) ? atan(oyj/oxi) : M_PI/2; b = 120 + 80*cos(mt*th); if (a < b) *d++ = 0, *d++ = c, *d++ = c; // 黄色 else d += 3; } } #endif #if 0 // 計算処理のテスト用データ(左下隅に転送する) unsigned char tda[] = { 0xc0, 0x80, 0x40, 0xc0, 0x80, 0x40, 0xc0, 0x80, 0x40, 0xc0, 0x80, 0x40, 0xc0, 0x80, 0x40, 0xc0, 0x80, 0x40, 0xc0, 0x80, 0x40, 0xc0, 0x80, 0x40, 0xc0, 0x80, 0x40 }; unsigned char *tdp = tda; for (i = 0; i < 3; i += 1) { d = s0 + 3*(516*(i+2) + 2); // 余白 2 pixel for (j = 0; j < 3; j += 1) { *d++ = *tdp++; *d++ = *tdp++; *d++ = *tdp++; } } for (i = 0; i < 3; i += 1) dump(s0 + 3*(516*(i+2) + 2), s0, 1); #endif // 描画の本体 for (n = 0; n < (int)nmax; n += 1) { // 一回では変化が僅かなので、繰り返す d = m1; // 計算結果の一時格納場所 for (i = 1; i < 511; i += 1) { // i, j の範囲に注意 p0 = s0 + 3*(516*(i+2-1) + 2); p1 = s0 + 3*(516*(i+2) + 2); p2 = s0 + 3*(516*(i+2+1) + 2); for (j = 1; j < 511; j += 1) { c = npx1(p0++, p1++, p2++); *d++ = (c == 10) ? 9 : c; c = npx1(p0++, p1++, p2++); *d++ = (c == 10) ? 9 : c; c = npx1(p0++, p1++, p2++); *d++ = (c == 10) ? 9 : c; } } // 結果を書き戻す d = m1; for (i = 1; i < 511; i += 1) { p1 = s0 + (3*(516*(i+2) + 2) + 3); for (j = 1; j < 511; j += 1) *p1++ = *d++, *p1++ = *d++, *p1++ = *d++; } if (n % 20 == 0) dump(s0 + 3*(516*(190+2) + 184), s0, 1); } } 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], "%f", &a_v[0]); if (a_c >= 3) sscanf(argv[2], "%f", &a_v[1]); printf("a_c %d: a_v %f, %f\n", a_c, a_v[0], a_v[1]); if (a_c > 3) { printf("Bye.\n"); return -1; } // malloc() 実行 m0 = (unsigned char *)malloc(bsz1 + bsz2); if (!m0) { printf("malloc() fail.\n"); return -1; } m1 = m0 + bsz1; printf("m0 0x%x, size %d, m1 0x%x size %d\n", m0, bsz1, m1, bsz2); // 読み込み fp = fopen("white24.bmp", "r"); if (!fp) { printf("fopen(r) fail.\n"); return -1; } n = fread(m0, sizeof(unsigned char), bsz1, fp); // ホントは size を調べるべき printf("%d byte read.\n", n); if (n <= 0) return -1; fclose(fp); // ファイル *.bmp のヘッダーを表示 q = (bmp_hdr *)(m0-2); // 謎の -2 です s = (unsigned char *)m0; 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 < 3*516*516) { printf("'white24.bmp' too small.\n"); return -1; } // ヘッダーの内容が妥当であるかのチェックは、だいぶ省略 // 出力ファイル open fp = fopen("cht.bmp", "w"); if (!fp) { printf("fopen(w) fail.\n"); return -1; } // 描画 df1(m0 + q->bfOffBits); // ファイル書き込み n = fwrite(m0, sizeof(unsigned char), n, fp); printf("cht.bmp: %d byte written.\n", n); // 終了 fclose(fp); free(m0); system("mspaint cht.bmp"); // mspaint 実行 return 0; }