Jitter ファイルフォーマット(JXF)では、マトリックスデータをバイナリ(人間には可読でないフォーム)で格納します。 Jitter を使用する際、jit.matrix オブジェクトに write メッセージを送信して JXF ファイルを作ることができます。逆に、read メッセージを使って、ディスクから JXF ファイルを読み出すことができます。このセクションではまず、JXF ファイルの write、read を C から行なうために使用できる API 関数について説明します。その後、ビットレベルでファイルフォーマットについて見ていきます。
ほとんどの Jtter ユーザは、JXF ファイルのバイナリフォーマットについて知る必要も、興味もないでしょう。C から JXF ファイルの読み込み、書き出しを行なおうとするユーザであっても、バイナリインターフェイスを使用する Jitter API の関数を使えば、特に内部に関する詳細を知る必要はありません。API は単に便利なだけでなく、Cycling '74 によって提供された関数を使用するため、将来的に Jitter の仕様が変更された場合であっても、あなたのコードを変更せずに済むであろうという利点を持っています。2つの基本的な関数があり、その1つは JXF ファイルからデータを読み込むために使用すべきものです。jit_bin_read_header はバージョンナンバやファイルサイズをヘッダから読み込む関数です。次のようなシグネチャを持っています。
t_jit_err jit_bin_read_header(t_filehandle fh, ulong *version, long *filesize)
jit_bin_read_matrix はファイルからマトリックスへデータをインポートし、必要ならばマトリックスのサイズ変更を行ないます。次のようなシグネチャを持っています。
t_jit_err jit_bin_read_matrix(t_filehandle fh, void *matrix)
次は、ディスクからマトリックスを読み込む処理を行なっているコードの部分です。
if (!(err=path_opensysfile(filename, path, &fh, READ_PERM))) { // すべてうまくいった場合 } else { error("jit.matrix: can't open file %s",name->s_name); goto out; }
if (jit_bin_read_header(fh,&version,&filesize)) { error("jit.matrix: improper file format %s",name->s_name); sysfile_close(fh); goto out; }
if (jit_bin_read_matrix(fh,matrix)) { error("jit.matrix: improper file format %s",name->s_name); sysfile_close(fh); goto out; } sysfile_close(fh);
同様に、JXF ファイルにデータを書き出す場合に使用しなければならない関数が2つあります。jit_bin_write_header はファイルのヘッダを書き込みます。次のようなシグネチャを持っています。
t_jit_err jit_bin_write_header(t_filehandle fh, long filesize)
jit_bin_write_matrixはファイルにマトリックスを書き出します。次のようなシグネチャを持っています。
t_jit_err jit_bin_write_matrix(t_filehandle fh, void *matrix)
次のコードは、1つのマトリックスをファイルに書き出す方法を示しています。最初に jit_bin_write_header へ渡されるファイルサイズを表す引数はダミーです。マトリックスの書き出しが終了し、そのファイルポジションによってファイルサイズが決定できるようになった後、処理の最後にもう一度ヘッダを書き直している点に注意して下さい。
if (err=path_createsysfile(filename, path, type, &fh)) { error("jit.matrix: could not create file %s",name->s_name); goto out; }
if (jit_bin_write_header(fh,0)) { error("jit.matrix: could not write header %s", matrixName->s_name); sysfile_close(fh); goto out; }
if (jit_bin_write_matrix(fh,pointerToMatrix)) { error("jit.matrix: could not write matrix %s", matrixName->s_name); sysfile_close(fh); goto out; }
sysfile_getpos(fh, &position); sysfile_seteof(fh, position);
if (jit_bin_write_header(fh,position)) { error("jit.matrix: could not write header %s", matrixName->s_name); sysfile_close(fh); goto out; }
sysfile_close(fh);
JXFファイルの内部フォーマットは Interchange File Format (IFF) に基づいています。(http://en.wikipedia.org/wiki/Interchange_File_Format)
訳注:日本語版のWikipedia http://ja.wikipedia.org/wiki/Interchange_File_Format
IFF ファイルはチャンクからできています。IFF ファイルのすべてのデータはビッグエンディアンを仕様しています。jit.byteorder.h で定義されているいくつかの便利なマクロは、JXF ファイルへの書き出しや JXF ファイルからの読み込みに際して、値を適当なフォーマットに変換する手助けとして利用できます。BE_I32() は 32ビット整数で、BE_F32() は 32 ビット浮動小数点数で、BE_F64() は 64ビット浮動小数点数で呼び出すことができます。 IFF ファイルの各チャンクは4文字の char によるタイプID(Type ID)で始まります。その次に 32 ビット符号なし整数によってバイト単位でチャンクサイズを指定します。JXF ファイルでは、最初のチャンクの 32 ビット整数部分はファイルサイズを示し、その後に続くすべてのチャンクにマトリックスを格納します。将来的には、別の種類のデータを格納する目的でチャンクが使用されることもあるかもしれません。次の表は、小さな JXF ファイルの例を示したものです。
コンテナ・チャンク(Container Chunk) | |
グループID (groupID) | JIT_BIN_CHUNK_CONTAINER ('FORM') |
ファイルサイズ (File size) | 32ビット整数(32-bit int) |
IFFタイプ (IFF Type) | JIT_BIN_FORMAT ('JIT!') |
フォーマット・チャンク(Format Chunk) | |
チャンクID (chunkID) | JIT_BIN_CHUNK_FORMAT_VERSION ('FVER') |
チャンクサイズ (Chunk size) | 12 バイト(12 bytes) |
バージョン情報 (Version) | JIT_BIN_VERSION_1 (0x3C93DC80) |
マトリックス・チャンク(Matrix Chunk) | |
チャンクID (chunk ID) | JIT_BIN_CHUNK_MATRIX ('MTRX') |
チャンクサイズ (Chunk size) | 32ビット整数(32-bit int) |
オフセット (offset) | 32ビット整数(32-bit int) |
型 (type) | 4文字の char (4-char) |
プレーン数 (planecount) | 32ビット整数(32-bit int) |
ディメンション数 (dimcount) | 32ビット整数(32-bit int) |
ディメンションの大きさ (dim) | ディメンションの大きさを表す32ビット整数の配列 |
データ(data) |
マトリックス・チャンクのデータオフセットは オフセット(offset) で表されます。これは、チャンクの先頭位置からチャンク内のデータの先頭位置までをバイト単位で表したものです。型(type)は、CHAR、LONG、FL32、FL64 のうちのどれか1つになります。dim という配列には、ディメンションの数だけ「大きさ」が、それぞれ 32 ビット整数で格納されます。データ(data)部分にはマトリックスのセルの内容が Row-major order の順序で書き込まれます。(訳注:英語版の Wikipedia ですが、Row-major-order の説明があります。http://en.wikipedia.org/wiki/Row-major_order)プレーンのデータは、セル内で多重化されます。例えば、3 プレーンで、2×2 のマトリックスでは、次の順序で書き出されます。
プレーン(Plane) |
Dim 0 |
Dim 1 |
0 |
0 |
0 |
1 |
0 |
0 |
2 |
0 |
0 |
0 |
1 |
0 |
1 |
1 |
0 |
2 |
1 |
0 |
0 |
0 |
1 |
1 |
0 |
1 |
2 |
0 |
1 |
0 |
1 |
1 |
1 |
1 |
1 |
2 |
1 |
1 |
上記のような様々なチャンクは、次のような Cの構造体によって表現することができます。
typedef struct _jit_bin_chunk_container { ulong ckid; //'FORM' long cksize; // ファイルサイズ ulong formtype; //'JIT!' } t_jit_bin_chunk_container; typedef struct _jit_bin_chunk_format_version { ulong ckid; //'FVER' long cksize; // 12 ulong vers; // タイムスタンプ } t_jit_bin_chunk_format_version; typedef struct _jit_bin_chunk_matrix { ulong ckid; //'MTRX' long cksize; // 変化します。 // (24+(4*dimcount) // +(typesize*planecount*totalpoints) // と同じ値でなければなりません。 long offset; // データオフセット(24+(4*dimcount) と同じ値でなければ // なりません) ulong type; //'CHAR','LONG','FL32','FL64' long planecount; long dimcount; long dim[1]; } t_jit_bin_chunk_matrix;