すのものの「変わり玉 gif ファイル」

2009 年九月の末のことだ。 泊まっていた大阪・梅田の「ホテルサンルート梅田」の前の道を西へ進み、 阪急電車の高架の手前、道の右側にある、 「専門学校ESPエンタテインメント」か、その本館だと思うのだが、 夜に見たら、非常に私好みのイルミネーションが光っていた。 ある色でしばらく光り、それが別の色に変わってまたしばらく光る。 このようにして一周することを、ずっとくり返しているようだった。

すのものの自作壁紙(その3) でやったように、1ドット×1ドットの .bmp ファイルを、 次々と色が変わってゆくよう、C言語で書いたプログラムに出力させ、 それをホームページビルダーのツールの中の「ウェブ アニメータ」でつなげれば、 .html ファイル上で似たものが作れそうである。 特定の色のところでは、長く表示するようにさせればよい。 (「ウェブ アニメータ」の使用法のうち、 すのものの自作壁紙(その3) に書いたのと同じ部分については省略する。)

プログラムは、前とほとんど同じであるが、 色を表す数値は 5 ずつでなく 15 ずつ変えることにした。 (そして、できたと思ったが、15 * 15 を 255 とカン違いしていることに気がついた。 色が 255 - 15 * 15 = 30 とぶところができてしまった。やり直した。)

最初の色が青()のもの、 シアン()のもの、 緑()のもの、 黄()のもの、 赤()のもの、 マゼンタ()のものと6つ作る。 「ウェブ アニメータ」でファイルの順序を入れ替えるのは面倒だとわかったので、 プログラムを書き換えて、 出力された .bmp ファイルはファイル名順に並べて合成すればよいようにした。 そのため、次のプログラムでは、N の値を 17 の 0 倍、 1 倍、2 倍、3 倍、4 倍、5 倍に変えて6回の作業を行なう。 (また、色の変わってゆく方向を、 すのものの自作壁紙(その3) のときとは逆にした。上にあげた6色を、逆の順に回ってゆく。 これで、虹の色を外側から内側へとたどる順に近くなった。)

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

#define N (17*0)    /* 17 の 0, 1, 2, 3, 4, 5 倍 */

char str[] = \
    "\x42\x4d\x3a\x00\x00\x00\x00\x00\x00\x00\x36\x00\x00\x00\x28\x00" \
    "\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x01\x00\x18\x00\x00\x00" \
    "\x00\x00\x04\x00\x00\x00\xc4\x0e\x00\x00\xc4\x0e\x00\x00\x00\x00" \
    "\x00\x00\x00\x00\x00\x00";

    /* ↑ 1×1の .bmp ファイルの先頭に書いてあるもの */
 
main() {
    int i, j;
    char fname[128+1];
    FILE* out;
 
    for (i = 0; i < 102; i++) {
        sprintf(fname, "%04d.bmp", i);
        if ((out = fopen(fname, "wb")) == NULL) {
            fprintf(stderr, "can't open %s.\n", fname); exit(1);
        }
 
        for (j = 0; j < sizeof(str) - 1; j++) {
            fputc(str[j], out);
        }
 
                                        /* 色の指定。青、緑、赤の順 */
        j = N - i;
        if (j < 0) {
            j += 102;
        }

        if (j <= 17) {
            fprintf(out, "%c%c%c", 255, 15*j, 0);
        } else if (j <= 34) {
            fprintf(out, "%c%c%c", 255-15*(j-17), 255, 0);
        } else if (j <= 51) {
            fprintf(out, "%c%c%c", 0, 255, 15*(j-34));
        } else if (j <= 68) {
            fprintf(out, "%c%c%c", 0, 255-15*(j-51), 255);
        } else if (j <= 85) {
            fprintf(out, "%c%c%c", 15*(j-68), 0, 255);
        } else {
            fprintf(out, "%c%c%c", 255, 0, 255-15*(j-85));
        }
        fputc(0, out);          /* そのあと、最後に 0 が1バイトついている */
        fclose(out);
    }
}

「ウェブ アニメータ」は各画像ファイルの表示時間を全て同じにしか設定できないことがわかった。 しかたがないので、上にあげた6色のみ、コピーして増やすことにした。 そのためのバッチファイルが次である。 (バッチからバッチを呼べばこんなに長く書かなくて済んだかも。 でも、copy & paste して replace するだけだから、作るのは簡単だった。)

copy 0000.bmp 0000a.bmp
copy 0000.bmp 0000b.bmp
copy 0000.bmp 0000c.bmp
copy 0000.bmp 0000d.bmp
copy 0000.bmp 0000e.bmp
copy 0000.bmp 0000f.bmp
copy 0000.bmp 0000g.bmp
copy 0000.bmp 0000h.bmp
copy 0000.bmp 0000i.bmp
ren 0000.bmp 0000k.bmp

copy 0017.bmp 0017a.bmp
copy 0017.bmp 0017b.bmp
copy 0017.bmp 0017c.bmp
copy 0017.bmp 0017d.bmp
copy 0017.bmp 0017e.bmp
copy 0017.bmp 0017f.bmp
copy 0017.bmp 0017g.bmp
copy 0017.bmp 0017h.bmp
copy 0017.bmp 0017i.bmp
ren 0017.bmp 0017k.bmp

copy 0034.bmp 0034a.bmp
copy 0034.bmp 0034b.bmp
copy 0034.bmp 0034c.bmp
copy 0034.bmp 0034d.bmp
copy 0034.bmp 0034e.bmp
copy 0034.bmp 0034f.bmp
copy 0034.bmp 0034g.bmp
copy 0034.bmp 0034h.bmp
copy 0034.bmp 0034i.bmp
ren 0034.bmp 0034k.bmp

copy 0051.bmp 0051a.bmp
copy 0051.bmp 0051b.bmp
copy 0051.bmp 0051c.bmp
copy 0051.bmp 0051d.bmp
copy 0051.bmp 0051e.bmp
copy 0051.bmp 0051f.bmp
copy 0051.bmp 0051g.bmp
copy 0051.bmp 0051h.bmp
copy 0051.bmp 0051i.bmp
ren 0051.bmp 0051k.bmp

copy 0068.bmp 0068a.bmp
copy 0068.bmp 0068b.bmp
copy 0068.bmp 0068c.bmp
copy 0068.bmp 0068d.bmp
copy 0068.bmp 0068e.bmp
copy 0068.bmp 0068f.bmp
copy 0068.bmp 0068g.bmp
copy 0068.bmp 0068h.bmp
copy 0068.bmp 0068i.bmp
ren 0068.bmp 0068k.bmp

copy 0085.bmp 0085a.bmp
copy 0085.bmp 0085b.bmp
copy 0085.bmp 0085c.bmp
copy 0085.bmp 0085d.bmp
copy 0085.bmp 0085e.bmp
copy 0085.bmp 0085f.bmp
copy 0085.bmp 0085g.bmp
copy 0085.bmp 0085h.bmp
copy 0085.bmp 0085i.bmp
ren 0085.bmp 0085k.bmp

できた .bmp ファイルをつなげる際、 すのものの自作壁紙(その3) ではなぜか最後にくるはずの名前のファイルが先頭にくる、 という現象が起きて手作業で直したが、 「最後のファイルを指定してから、shift を押しながら最初のファイルを指定する」 とすればこの問題が起こらないことに気がついた。 (われながら、よく気がついたと思う。)

一枚の画像を 0.5 秒ずつ表示するようにして、合成。

青()から始まるものの名前はkawaridama?a.gif
シアン()から始まるものの名前はkawaridama?b.gif
緑()から始まるものの名前はkawaridama?c.gif
黄()から始まるものの名前はkawaridama?d.gif
赤()から始まるものの名前はkawaridama?e.gif
マゼンタ()から始まるものの名前はkawaridama?f.gif
とした。

次は、img src タグでこれらのファイルを指定し、width と height も指定し、上の順で table にしてみたもの。

太さを変えてみた。太いと、色が変わってゆく様子が見えて気になるかもしれない。 また、ディスプレイによっても感じが変わる。

以下、色の変わり方を変えたものを示すが、すべて、上の二つの table のスタイルで示す。

色が変わるとき、白に近づいて変わるほうがきれいかな、と考えて、次のようにプログラムを改変。 関数 f() を通すことで、変化の途中では色が白 (255, 255, 255) に近づくようにした。

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

#define N (17*0)    /* 17 の 0, 1, 2, 3, 4, 5 倍 */

int f(int x, int n);

char str[] = \
    "\x42\x4d\x3a\x00\x00\x00\x00\x00\x00\x00\x36\x00\x00\x00\x28\x00" \
    "\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x01\x00\x18\x00\x00\x00" \
    "\x00\x00\x04\x00\x00\x00\xc4\x0e\x00\x00\xc4\x0e\x00\x00\x00\x00" \
    "\x00\x00\x00\x00\x00\x00";

    /* ↑ 1×1の .bmp ファイルの先頭に書いてあるもの */
 
main() {
    int i, j;
    char fname[128+1];
    FILE* out;
 
    for (i = 0; i < 102; i++) {
        sprintf(fname, "%04d.bmp", i);
        if ((out = fopen(fname, "wb")) == NULL) {
            fprintf(stderr, "can't open %s.\n", fname); exit(1);
        }
 
        for (j = 0; j < sizeof(str) - 1; j++) {
            fputc(str[j], out);
        }
 
                                        /* 色の指定。青、緑、赤の順 */
        j = N - i;
        if (j < 0) {
            j += 102;
        }

        if (j < 17) {
            fprintf(out, "%c%c%c", f(255, j), f(15*j, j), f(0, j));
        } else if (j < 34) {
            fprintf(out, "%c%c%c", f(255-15*(j-17), j-17), f(255, j-17), f(0, j-17));
        } else if (j < 51) {
            fprintf(out, "%c%c%c", f(0, j-34), f(255, j-34), f(15*(j-34), j-34));
        } else if (j < 68) {
            fprintf(out, "%c%c%c", f(0, j-51), f(255-15*(j-51), j-51), f(255, j-51));
        } else if (j < 85) {
            fprintf(out, "%c%c%c", f(15*(j-68), j-68), f(0, j-68), f(255, j-68));
        } else {
            fprintf(out, "%c%c%c", f(255, j-85), f(0, j-85), f(255-15*(j-85), j-85));
        }
        fputc(0, out);          /* そのあと、最後に 0 が1バイトついている */
        fclose(out);
    }
}


int f(int x, int n) {
    int j;

    j = (n - 8 < 0 ? 8 - n : n - 8);

    return (x * (64 + j*j) + 255 * (64 - j*j)) / 128;
}

色が変わってゆく過程では、パステル調と言われるぐらいまで色が薄くなる。

最後の関数 f() だけを、以下のように変えてみた。

int f(int x, int n) {
    int j;

    j = (n - 8 < 0 ? 8 - n : n - 8);

    return (x * (j*j) + 255 * (64 - j*j)) / 64;
}

色が変わってゆく過程で、完全に真っ白になるまで色が薄くなる。

さらに、次のように変えてみた。

int f(int x, int n) {
    int j;

    j = (n - 8 < 0 ? 8 - n : n - 8);

    return ((x + 255) / 2 * (j*j) + 255 * (64 - j*j)) / 64;
}

本当は、二番目と三番目の中間のようなものを作ってみたかった。 つまり、色が変わってゆく過程で、二番目のよりは白に近づくが、三番目のように真っ白にはならない、 というものにしたかったのだが、上の関数を間違えて、 実際には、最初にあげた6色になるときがパステル調、 色が変わる過程でもっとも薄くなると真っ白、というものができてしまった。 が、これはこれでおもしろい。

次は f()

int f(int x, int n) {
    return (2*x + 3*255) / 5;
}
としたもの。

“原色”と完全な白の間を 3:2 に内分しているので、パステル調のまま色が変わってゆく。 これだと、右下の幅の太いものでも、色が変わってゆくのが目につかない。 1:1 ではなく 3:2 としたのは、 最初のプログラムでは、色の濃さを示す数がすべて 5 の倍数だからである。

f()

int f(int x, int n) {
    return (3*x + 2*255) / 5;
}
としたもの。

一つ上のよりはやや濃い。 “原色”と完全な白の間を 3:2 でなく 2:3 に内分しているから。

最後は、f()

int f(int x, int n) {
    return (x + 4*255) / 5;
}
としたもの。

かなり薄い色のまま、変化する。 “原色”と完全な白の間を 4:1 に内分しているから。

次は、上のそれぞれについて、六個を2×3に並べたもの。 表の上に書いた数字列は、.gif ファイル名に含まれている数字列である。 ファイル名の .gif の直前は a から f で一組になっているが、それを

a b c
f e d
のように、循環するように並べてある。 9, 10 あたりはなかなかきれいだと思う。 (いわゆる)ホームページのどこかにさりげなく置いておき、 色が変わることに気づいてもらえればよし、もらえなくても、 それはそれでいいか……。

5
6
7
8
9
10
11


すのもの Sunomono