2010-03-23

プレーンテキストの画像形式

少し前から「プレーンテキストの画像形式」というものを探していた。

レイトレーシングなど、絵が出力結果であるプログラムを作って遊んでいると、レンダリングの結果を出す先に困ることがある。

画面表示のできるライブラリを持ってくるのも大仰だ。画像に保存したいところだ。しかも、printfとかで適当に。

BMPの構造体の定義や、PNGやGIFのアルゴリズムを空で書き下すには修行が必要だ。(windows.hは反則)

UNIX系列であればPNMというかなり理想的な形式がある。しかし、残念ながらWindows付属のビューアでは見られない。

SVG形式も考えたが、これはビットマップには向かない。rectを一面に並べる変換器を作ってみたら200KB程度の画像が9MBに膨れ上がった。

サイズはテキストの時点である程度諦めるべきところだが、どちらにしろ表示が極端に重たかった。

SVGの形式を眺めていて、HTMLで一時期流行った遊びを思い出した。

「tableタグでbgcolorを指定したtdをひたすら並べる」

<code><html>
  <head>
    <style>
      tr{height:1px}
      td{width:1px}
    </style>
  </head>
  <body>
    <table border="0" cellpadding="0" cellspacing="0">
      <tr><td bgcolor="#000000"></td><td bgcolor="#000000"></td><td bgcolor="#000000"></td><td...
      <tr><td bgcolor="#000000"></td><td bgcolor="#000000"></td><td bgcolor="#000000"></td><td...
      ...
    </table>
  </body>
</html>
</code>

本当にfprintfしか使わない実装。

void dump(int w, int h, const char *pixels, FILE *fp)
{
    int x, y;

    fprintf(fp, "<html><head><style>tr{height:1px}td{width:1px}</style></head><body><table cellpadding=0 cellspacing=0 width=%d height=%d>", w, h);

    for(y=0; y<h; y++)
    {
        fprintf(fp, "<tr>");

        for(x=0; x<w; x++)
        {
            fprintf(fp, "<td bgcolor=#%02x%02x%02x></td>", pixels[x + y * w], pixels[x + y * w + 1], pixels[x + y * w + 2]);
        }

        fprintf(fp, "</tr>");
    }

    fprintf(fp, "</body></html>");
}

これでとりあえずブラウザに表示させてプリントスクリーンすれば画像になる。

いまどきならCanvasでImageDataなどを使うのかもしれない。

(copied from tumblr)