TypeScript による Alembic の読み込み 1

#TypeScript で Alembic を読み込んでみる.
普段は C++ で仕事プログラムをしているのですが、Private の時間で JavaScript の勉強をし始めて数日. Alembic 自体の調査を兼ねて、JavaScript で読み込む処理を書いてみる. JavaScript 自体は素人なので、いろいろ時間がかかりながらも、鋭意実装中.

#方針と現状
普通に JavaScript で書いてもいいけど、折角なので JavaScript を生成する別の言語を使ってみようという事でいくつか調査. CoffeeScript よりも C++ に記述が近い事から TypeScript で書くことに.

Unit Test は Jasmine+Karma+PhantomJS を使って構築. いろいろあったけど、今は元気に動いています.

#Alembic
![Alembic](https://avatars0.githubusercontent.com/u/1066203?v=3&s=200)

##情報元
Alembic の調査. 下記が Alembic フォーマットのポータルっぽい.
http://www.alembic.io/

ここの Download リンクから飛んだ先にある GoogleCode のページから ZIP に固められた Alembic を扱う Library のソースコードなどが入手可能.
https://code.google.com/p/alembic/

ただ、GoogleCode なので ReadOnly になっていたりして大層不安. さらに検索してみたら、GitHub にもページがあり、現在のメインはこっちっぽい. ここからソースコードを取得して調査している.
https://github.com/alembic

##データ
サンプルデータは、GoogleCode にあった Alembic_Octopus_Example を利用.

そのほかに、去年あたり Perfume の Event で提供していたファイルもとってきて参考にしている. 現在も取得可能で、下記の #003 から取得可能.
http://www.perfume-global.com/

##データ確認用のツール
今回は Private での制作という事で、Non-Commercial 版の Houdini を利用.
http://www.sidefx.jp/index.php?option=com_content&view=article&id=1&Itemid=435

Non-Commercial 版では、Alembic の Export はできないものの Import はでき、上記の取得してきたデータは確認できた.

GitHub で提供されているコードの中にも AbcView という Viewer のコードがついており、build する事で使えそうだったんだけど、いろいろ依存しているものが多く Library や build 用のツールをインストールする必要があり、あまり Private の環境を汚したくなかったので今回は見送り. そもそも、現状では *Windows support is experimental* となっていたし…. こっちの方が、データの中身をいろいろ見れそうだったんだけど.

##ファイルフォーマット
現状、CoreType として 2 つ定義されている.それぞれの CoreType には全く互換性はないようで、提供されている Library 内でもかなり上位のレベルで実装が分かれている.

###HDF5
下記で定義されているフォーマットをベースとするファイルフォーマット.
https://www.hdfgroup.org/HDF5/

HDF5 としての Attribute として、Alembic としての定義がある. 上記で示したデータは、どれもこの CoreType だった.
###Ogawa
HDF5 に比べていろいろ改善されている新しいファイルフォーマット. HDF5 などの外部のフォーマットを用いず、独自のフォーマットになっている. GitHub 内に HDF5 と同等の機能を提供していると思われるソースが lib/Alembic/Ogawa の中に入っている.

#TypeScript での実装と発生した問題
**2015/10/21 追記**
最終的に対応した方法を下記に記載しました.
[参考リンク](http://qiita.com/wokia/items/28be250ad80e792ad937)

**2015/10/18 追記**
下記の問題は解決しました.
[参考リンク](http://qiita.com/wokia/items/63a99bd8675172e774f1)

----

まずは用意できたサンプルデータが HDF5 だったので、この CoreType のファイルフォーマットの読み込み処理から実装していく. HDF5 のファイルフォーマットは、下記に詳しく書かれてる.
https://www.hdfgroup.org/HDF5/doc/H5.format.html

…が、ヘッダの読み込みで早速躓く…

最初の Format Signature が一致しない. いろいろ Debug してみたところ、XMLHttpRequest で読み込んだ時点で、ファイルの先頭部分が化けてしまっている. 読み込み処理は下記の通り.

```ts
beforeAll(function (done) {
	request.open('GET', filename, true);

	request.responseType = 'arraybuffer';
	request.addEventListener('loadend', function () {
		done();
	});

	request.overrideMimeType('application/octet-stream');
	request.send();
})
```

内容の表示に利用しているのは、下記のコード.

```ts
var buffer = <ArrayBuffer>request.response;
console.log(new Uint8Array(buffer, 0, 8));
```

上記のドキュメントにもある通り、下記の様な 8 bytes が並んでいる事を期待している.
`[0x89, 0x48, 0x44, 0x46, 0x0d, 0x0a, 0x1a, 0x0a]`

実際、バイナリエディタでサンプルデータの先頭部分を見てみると、期待しているデータ通りの 8 bytes が並んでいる事が確認できる. でも、読み込むと先頭部分がおかしい.いろいろ調べた結果、最初の 1 byte の内容（もしくは、先頭の 1 bit ?）の状況によって、変なデータが挿入されてしまう事が分かった.

試しに、Alembic_Octopus_Example の Alembic ファイルをバイナリエディタで開き、先頭の 1 byte を 0x7F に書き換え、下記のコードで表示してみると期待通りの結果が得られた.

```
LOG: Object{0: 127, 1: 72, 2: 68, 3: 70, 4: 13, 5: 10, 6: 26, 7: 10, length: 8, byteOffset: 0, buffer: Object{byteLength: 68364627}, byteLength: 8}
```

対して、先頭の 1 byte を 0x80 に書き換えた時の出力は下記になった

```
LOG: Object{0: 239, 1: 191, 2: 189, 3: 72, 4: 68, 5: 70, 6: 13, 7: 10, length: 8, byteOffset: 0, buffer: Object{byteLength: 68364629}, byteLength: 8}
```

比較すると、正しく読めている時の 2 byte 目以降と、化けてしまった時の 4 byte 目以降は一致している. つまり、0x80 が 3 byte のデータに書き換わっている. これは、Karma が起動させる Browser を Chrome に変えても一緒だった.

とりあえず、4 byte 目以降は一致しているという事なので、1 byte 目を無視して、4 byte 目以降と Signature を比較してみたら一致した. が、とても気持ち悪い. 2 進数データと定義しているから、最初の bit がたっている事がトリガーかなと思うけど、ただ、データが変わるのはそういうものなの？誰も困ってないの？？ 情報もとむ !!

#という訳で…
つづく。

#追記 (2015/10/17)
上記の、XMLHttpRequest で Binary Data を読み込んだ場合、先頭の値によって内容が化けてしまう症状を再現したコードを、下記にあげてみた. 情報もとむ !!

っていうか、全部の Browser で失敗しているって事は、原因は Karma の Web-Server の方 ?

[xmlhttprequest-data-corrupt](https://github.com/wokia/xmlhttprequest-data-corrupt)