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)

2010-02-17

Mix_LoadMUS_RW の引数に int freesrc がない件

最近ZinniaさんのSDL_RWops解説を読み直して、fopen/fcloseをRWops系の関数で書き直した。これを抽象化の点として、そのうち暗号化したzipなどから読ませるようにしたいと思う。
画像ファイル(SDL_Image)は問題なく置き換えることができたが、音声ファイル(SDL_Mixer)の部分で落ちるようになった。
検索でGameDev.netのフォーラムのトピックを見つけた。以下会話の流れ。


Mix_LoadMUS_RWで落ちる。どういうこと?
<状況説明とMix_LoadMUS_RWを使ったコード。SDL_Mixerのバージョンは1.2.7で、プラットフォームはOS X>


SDL_mixerのソース(load_ogg.c, music.c, music_ogg.c)を読んでみた。
Ogg形式ならMix_LoadWAV_RW()が代わりに使える。
ただ、データを内部でコピーするから、長い音楽には向かない。
5MB程度のOggでも、メモリ上に解凍すると45MBになってしまう。
Mix_LoadMUS() はディスクから少しずつ解凍しながらストリーミングするから、4KB程度のバッファですむ。
Ogg形式の場合は、Vorbisライブラリがストリーミングの処理を直接扱う。つまり、Vorbisがファイルを開いて、直接FILE *からチャンクを読んでいく。
Mix_LoadMUS_RW() の場合はSDL_RWopsをコピーする手段が無いから、引数に渡したものをそのまま使うしかない。つまり、処理が帰ってきてもfreeされないことになる。
要は、引数に渡したRWopsをfreeせず、 SDL_RWclose(rw) も使わなければOK。
(注:普段私はSDL_Mixerを使わない)


ありがとう。私も読んだけどそこまでは読み取れなかった。
まだ疑問が残っているのは、これが二重freeのエラーになることだ。

Mix_FreeMusic(music);
SDL_FreeRW(rwops);

Mix_FreeMusic()がfreeしているということ?ソースからはわからなかったけど。
まあ、二重free以外は全部うまくいっています。ありがとう。


その通り。RWopsはMix_FreeMusic()でfreeされる。
この処理はVorbisライブラリ(正確に言うと、vorbisfile.c)側でしているから、SDL_Mixerのソースにはない。
どういたしまして :)


なるほど。丁寧な解説をありがとう。Thanks again :)



ということで、Mix_LoadMUS_RWに渡したRWopsはMix_FreeMusicが閉じてくれるらしい。
手元のコードもSDL_RWcloseを省くとうまく動いた。

(copied from tumblr)

2009-12-23

Tumblrに乗り換え

テーブルが使えないのが気に入らなかったのでtumblrに乗り換えたが、向こうも別にテーブルが扱えるわけではなかった。

MarkdownというなんかTextileというなんかWiki記法のしょぼくなったようなやつのしょぼくなったようなやつが使えるので、それで試してみたらこういう記法が通じた。

死ぬほど使いにくい。

First Header  | Second Header
------------- | -------------
Content Cell  | Content Cell
Content Cell  | Content Cell

Edit 2011-02-14: Tumblrが最近よく落ちるので、こちらにも並行して投稿するようにした。

Wiki記法が無いことは、ScribeFireを使い始めたことで結局関係なくなった。Google Chrome用のAJAXなブログエディタ。TinyMCE Editorを搭載してはいるが、相変わらずテーブルは扱えない。

2009-12-09

gitをgraphvizにかけて集計してみた

集計した。全体図
モジュール名
#includeされている回数
commit
73
parse-options
56
refs
53
diff
47
tag
43
revision
34
tree
34
run-command
34
blob
33
exec_cmd
28
dir
25
quote
25
tree-walk
22
cache-tree
21
string-list
19
object
18
remote
17
xdiff-interface
12
log-tree
12
pkt-line
11
color
11
utf8
11
strbuf
10
attr
10
unpack-trees
8
sigchain
8
transport
7
progress
6
list-objects
6
sideband
4
branch
4
rerere
4
sha1-lookup
4
pack-revindex
4
csum-file
4
walker
4
merge-recursive
4
archive
4
fsck
3
http
3
reflog-walk
3
userdiff
3
graph
3
decorate
3
mailmap
3
reachable
2
patch-ids
2
help
2
wt-status
2
ll-merge
2
bundle
2
bisect
2
grep
2
pack-refs
2
thread-utils
1
hash
1
levenshtein
1

2009-12-08

CRCおぼえがき

(途中から調べずにイメージで書いています。たぶんどこか誤解しています。親切な方はご指摘ください)
  • 送る側の処理
    • D(X)・X^r = G(X)・Q(X) + R(X) が基本の式
    • CRC = R(X)を二進数で表したもの
    • R(X)= (D(X) ・ X^r) ÷ G(X) の余り
    • D(X)=送信したいデータを多項式にしたもの
    • r = G(X)の最高次数
    • G(X)は生成多項式 (方式ごとに異なる。CRC-16やパリティなど)
    • 送るデータはD(X)とR(X)をビット順でくっつけたもの
      • つまり、D(X) ・ X^r + R(X)
多項式を2進数で表すことは、多項式が Σ^r_(i=0) b_i x^i という形で、係数の列 b_i が0か1だけからなるときに可能。b_iを多項式に対応する2進数のiビット目の数とする。つまり、多項式の最高次数はMSBの桁数となる。
  • 受け取る側の処理
    • 届いたデータをまるごと生成多項式G(X)で割る
      • (D(X) ・ X^r + R(X)) ÷ G(X)
    • 余りが0ならOK (誤りが無い)
      • D(X)・X^r = G(X)・Q(X) + R(X) が元の定義
      • D(X)・X^r  + R(X) = G(X)・Q(X) + 2R(X)
      • 余りは 2R(X) になるの?
    • 商は元のデータになる
      • Q(X) = D(X)?

2009-12-07

git.c

git.cからはこう。(拡張子は省略してある)

gitをgraphvizにかけてみた

GithubでGitのGitリポジトリを見つけた。
大元の人がLinusなので、当然C++は一切使っておらず、いくつかのモジュールと、小さいコマンドを沢山平たくおいた構成になっている。
依存関係を適当に集めてgraphvizにかけるとこうなった。

拡張子は省略してある。
左中央のhas_mainというのはmainという文字があったファイルをボックスで囲んである。builtinsはbuiltins-*.cというのをまとめたもの。
そのままではさっぱりわからないので、だんだん小分けして見てみようと思う。