結局libtgaをそのまま使うのは諦めて、コードを一部流用するほかは全部自分で書くことにしました。
まあ、そのほうがビルドしやすいし、使いやすいですからね。
vstgareader-0.1.0.7z
https://github.com/chikuzen/vstgareader
さて、これでBMP,JPEG,PNG,TGAとだいたい揃ってきたので、これらをなんとか一つに統合したいところですが…どうしようかなぁ。
2012年10月29日月曜日
2012年10月25日木曜日
libtga
PNGもなんとかなったので今度はTGAに挑戦です。
TGAを扱うライブラリにはlibtgaとその改造版のlibtga-exがあります。
で、使い方を確認するために、とりあえずこんなのを書いてみました。
こいつにtgaファイルを食わせてやればBGRなrawデータとして出力するわけですが、試しにtgaではないファイルを食わせるとなぜかクラッシュします。
いちおうTGAReadHeaderのところでチェックはしているみたいなんですが…はて?
で、TGAReadHeaderの部分のコードを読んでみると
ではTGA_OKの中身は何かとtga.hのほうを読んでみると…
TGA_OKが全然OKになってねえよ…そりゃクラッシュもするわ。
なんで誰もこれを直してないんだ?
TGAを扱うライブラリにはlibtgaとその改造版のlibtga-exがあります。
で、使い方を確認するために、とりあえずこんなのを書いてみました。
/* TARGA2BGR */ #include <stdio.h> #include <stdlib.h> #include "tga.h" typedef struct { TGA *tga; unsigned char *buff; } tga_read_t; int close(const char *msg, tga_read_t *tr, int ret) { fprintf(stderr, "%s\n", msg); if (tr->buff) { free(tr->buff); } if (tr->tga) { TGAClose(tr->tga); } return ret; } int main(int argc, char **argv) { if (argc < 2) { return -1; } tga_read_t tr = {0}; tr.tga = TGAOpen(argv[1], "rb"); if (!tr.tga || tr.tga->last != TGA_OK) { return close("TGAOpen failed", &tr, -1); } if (TGAReadHeader(tr.tga) != TGA_OK) { return close("TGAReadHeader failed", &tr, -1); } fprintf(stderr, "width: %u\n", tr.tga->hdr.width); fprintf(stderr, "height: %u\n", tr.tga->hdr.height); fprintf(stderr, "depth: %d\n", tr.tga->hdr.depth); fprintf(stderr, "alpha: %d\n", tr.tga->hdr.alpha); size_t buf_size = tr.tga->hdr.width * tr.tga->hdr.height * tr.tga->hdr.depth >> 3; tr.buff = malloc(buf_size); if (!tr.buff) { return close("malloc failed", &tr, -1); } if (TGAReadScanlines(tr.tga, tr.buff, 0, tr.tga->hdr.height, TGA_BGR) != tr.tga->hdr.height) { return close("couldn't read all lines\n", &tr, -1); } char out_name[1024]; sprintf(out_name, "%s.raw", argv[1]); FILE *out = fopen(out_name, "wb"); if (!out) { return close("open output file failed", &tr, -1); } fwrite(tr.buff, 1, buf_size, out); fclose(out); return close("finish", &tr, 0); }
こいつにtgaファイルを食わせてやればBGRなrawデータとして出力するわけですが、試しにtgaではないファイルを食わせるとなぜかクラッシュします。
いちおうTGAReadHeaderのところでチェックはしているみたいなんですが…はて?
で、TGAReadHeaderの部分のコードを読んでみると
int TGAReadHeader (TGA *tga) { tbyte *tmp; if (!tga) return 0; __TGASeek(tga, 0, SEEK_SET); if (tga->off != 0) { TGA_ERROR(tga, TGA_SEEK_FAIL); return 0; } /* 中略 */ return TGA_OK; }と問題なしならTGA_OKを返し、問題有りなら0を返すようになっています。
ではTGA_OKの中身は何かとtga.hのほうを読んでみると…
/* error codes */ enum { TGA_OK = 0, /* success */ TGA_ERROR, TGA_OOM, /* out of memory */ TGA_OPEN_FAIL, TGA_SEEK_FAIL, TGA_READ_FAIL, TGA_WRITE_FAIL, TGA_UNKNOWN_SUB_FORMAT /* invalid bit depth */ };
TGA_OKが全然OKになってねえよ…そりゃクラッシュもするわ。
なんで誰もこれを直してないんだ?
2012年10月23日火曜日
vsbmpreader/vspngreader
vsjpgreaderに続いて今度はbmpとpngです。
vsbmpreader-0.1.0.7z
vspngreader-0.1.0.7z
https://github.com/chikuzen/
TurboJPEG/OSSが非常に簡単だったので「じゃあ次はlibpngだぜ、ヘヘッ」てな感じでまずvspngreaderのほうに取り掛かったわけですが、これがなんともまあ厄介なシロモノでした。
前世紀から開発継続中の非常に歴史のあるライブラリなせいか、とにかくドキュメントの情報量はやたら充実してはおりますが、これが非常に読みにくい。
サンプルコード見てみても、そこら中に#ifdef/#elseifが散りばめられており、追うのが辛い。
void*をわざわざpng_voidpにしたり、unsigned charをpng_byteはいいとしてpng_byte*がpng_bytep、png_bytep*をpng_byteppと、わざと使いにくくしてるとしか思えないtypedefの乱発もまた辛い。
おまえらそこまでアスタリスク嫌いなのかよと小一時間…。
なんとか書き上げてはみたものの、動かしてみると原因不明のクラッシュで、もうすっかりお手上げです。
で、とりあえず気分転換にとbmpのほうを半日で書き上げてみてから、ふと気づいたのがlibpngのバージョン。
それまでは最新の1.5.13を使っていたわけですが、libpng.orgの説明書き(これも無駄に冗長でわかりにくい)をよくよく読んでみると、どうも自分の目的(48bitRGB/16bitGrayscaleの読み込み)は1.2.50でもよさそうです。
で、ものは試しと1.2.50に差し替えてみたらあっさりと動きました…。
vsbmpreader-0.1.0.7z
vspngreader-0.1.0.7z
https://github.com/chikuzen/
TurboJPEG/OSSが非常に簡単だったので「じゃあ次はlibpngだぜ、ヘヘッ」てな感じでまずvspngreaderのほうに取り掛かったわけですが、これがなんともまあ厄介なシロモノでした。
前世紀から開発継続中の非常に歴史のあるライブラリなせいか、とにかくドキュメントの情報量はやたら充実してはおりますが、これが非常に読みにくい。
サンプルコード見てみても、そこら中に#ifdef/#elseifが散りばめられており、追うのが辛い。
void*をわざわざpng_voidpにしたり、unsigned charをpng_byteはいいとしてpng_byte*がpng_bytep、png_bytep*をpng_byteppと、わざと使いにくくしてるとしか思えないtypedefの乱発もまた辛い。
おまえらそこまでアスタリスク嫌いなのかよと小一時間…。
なんとか書き上げてはみたものの、動かしてみると原因不明のクラッシュで、もうすっかりお手上げです。
で、とりあえず気分転換にとbmpのほうを半日で書き上げてみてから、ふと気づいたのがlibpngのバージョン。
それまでは最新の1.5.13を使っていたわけですが、libpng.orgの説明書き(これも無駄に冗長でわかりにくい)をよくよく読んでみると、どうも自分の目的(48bitRGB/16bitGrayscaleの読み込み)は1.2.50でもよさそうです。
で、ものは試しと1.2.50に差し替えてみたらあっさりと動きました…。
2012年10月19日金曜日
vsrawsource その2
更新しました。
vsrawsource-0.2.0.7z
https://github.com/chikuzen/vsrawsource
* 新オプション 'rowbytes_align'を追加
* Windows Bitmap(.bmp)の読み込みサポート
rowbytes_alignは、画像のstrideの境界指定用です(と書いて、分かる人は説明しなくてもわかる人だよなぁ)。
とりあえず世に出回ってるファイルの殆どはwidth==strideか、さもなくばDWORD(4バイト)境界のどちらかだと思いますので、1か4のどちらかにすればいけると思います。
まあ、中にはv210みたいに128バイトにアライメントされてるクソ仕様もありますが…どのみち対応する気もないから別にいいやってことで。ffms2で読めるし。
vsrawsource-0.2.0.7z
https://github.com/chikuzen/vsrawsource
* 新オプション 'rowbytes_align'を追加
* Windows Bitmap(.bmp)の読み込みサポート
rowbytes_alignは、画像のstrideの境界指定用です(と書いて、分かる人は説明しなくてもわかる人だよなぁ)。
とりあえず世に出回ってるファイルの殆どはwidth==strideか、さもなくばDWORD(4バイト)境界のどちらかだと思いますので、1か4のどちらかにすればいけると思います。
まあ、中にはv210みたいに128バイトにアライメントされてるクソ仕様もありますが…どのみち対応する気もないから別にいいやってことで。ffms2で読めるし。
2012年10月16日火曜日
vsjpgreader その2
更新しました。
vsjpgreader-0.1.2-2.7z
https://github.com/chikuzen/vsjpgreader
*デコード時の幅の計算を間違えていたのを修正。
ところでこれに関するバグ報告をDoom9でもらったついでにわかったのですが、どうも現時点ではVSFSはwidthがmod8でないと変になるようです。
vsjpgreader-0.1.2-2.7z
https://github.com/chikuzen/vsjpgreader
*デコード時の幅の計算を間違えていたのを修正。
ところでこれに関するバグ報告をDoom9でもらったついでにわかったのですが、どうも現時点ではVSFSはwidthがmod8でないと変になるようです。
2012年10月14日日曜日
vsjpgreader
VapourSynth用のJPEG入力プラグインを書きました。
vsjpgreader-0.1.1.7z
https://github.com/chikuzen/vsjpgreader
追記:
JPEG圧縮時のYUV変換がYUV420/YUV440だった場合の高さが奇数の際の処理を忘れていたので修正しました。
JPEGの読み込みはffms2でも出来ますし、vsavsreaderを使えばavisynthのimagesourceも利用できますが、前者は読み込むファイルの数だけffindexが作られるのがウザすぎるし、後者はWindowsでしか動きません。
imagemagickとか使えばJPEGだけでなく色々な形式に対応できるんだろうけど、なんか巨大すぎてわけわからんし、「ぽーたびりてぃ」ってもんに欠けるような気がしたので、よさげなライブラリはないものかと探してみたら、TurboJPEG/OSSなるものが見つかりました。
いやぁ、これ、いいっすねぇ。
ヘッダも小さくすっきりしててほんの数時間で完読できるし、それでいて必要な機能はあらかた揃ってるじゃないですか。それにlibjpeg-turboのラッパーだから、SIMD化も進んでいてスピードも文句なし。
ヘッダ読みながらこんなコードを書いてみて感じもつかめたので、そのまま一気にVSプラグインに仕上げました。
vsjpgreader-0.1.1.7z
https://github.com/chikuzen/vsjpgreader
追記:
JPEG圧縮時のYUV変換がYUV420/YUV440だった場合の高さが奇数の際の処理を忘れていたので修正しました。
JPEGの読み込みはffms2でも出来ますし、vsavsreaderを使えばavisynthのimagesourceも利用できますが、前者は読み込むファイルの数だけffindexが作られるのがウザすぎるし、後者はWindowsでしか動きません。
imagemagickとか使えばJPEGだけでなく色々な形式に対応できるんだろうけど、なんか巨大すぎてわけわからんし、「ぽーたびりてぃ」ってもんに欠けるような気がしたので、よさげなライブラリはないものかと探してみたら、TurboJPEG/OSSなるものが見つかりました。
いやぁ、これ、いいっすねぇ。
ヘッダも小さくすっきりしててほんの数時間で完読できるし、それでいて必要な機能はあらかた揃ってるじゃないですか。それにlibjpeg-turboのラッパーだから、SIMD化も進んでいてスピードも文句なし。
ヘッダ読みながらこんなコードを書いてみて感じもつかめたので、そのまま一気にVSプラグインに仕上げました。
2012年10月12日金曜日
HBVFWSource.dll その3
更新しました。
HighBitDepth_VFWSource-0.2.2.7z
https://github.com/chikuzen/HighBitDepth_VFWSource
マクロをinline関数に変更した際にとってもおバカさんなことをしておりました…orz
HighBitDepth_VFWSource-0.2.2.7z
https://github.com/chikuzen/HighBitDepth_VFWSource
マクロをinline関数に変更した際にとってもおバカさんなことをしておりました…orz
2012年10月11日木曜日
vsrawsource
rawsource.dllをVapourSynth用に一から書き直しました。
vsrawsource-0.1.0.7z
https://github.com/chikuzen/vsrawsource
一応VSがサポートしている全色空間で使えるようになっています。
ところでMacOS X用にビルドする場合、configureはどう書けばいいんでしょうかね?
最近Wipple氏が音信不通なので、相談相手がおりません。
vsrawsource-0.1.0.7z
https://github.com/chikuzen/vsrawsource
一応VSがサポートしている全色空間で使えるようになっています。
ところでMacOS X用にビルドする場合、configureはどう書けばいいんでしょうかね?
最近Wipple氏が音信不通なので、相談相手がおりません。
2012年10月7日日曜日
HBVFWSource.dll その2
更新しました。
HighBitDepth_VFWSource-0.2.1.7z
https://github.com/chikuzen/HighBitDepth_VFWSource
* Dither stacked formatでの出力をサポート
stacked formatでの出力はinterleaved formatよりも遅くなります。
特に必要でない場合はinterleaved formatで使って下さい。
追記:
0.2.1に更新。
stacked formatが少し速くなりました。
HighBitDepth_VFWSource-0.2.1.7z
https://github.com/chikuzen/HighBitDepth_VFWSource
* Dither stacked formatでの出力をサポート
stacked formatでの出力はinterleaved formatよりも遅くなります。
特に必要でない場合はinterleaved formatで使って下さい。
追記:
0.2.1に更新。
stacked formatが少し速くなりました。
2012年10月6日土曜日
vsavsreader.dll その5
更新しました。
vsavsreader-d219012.7z
https://github.com/chikuzen/VS_AvsReader
* 入力がRGB24/RGB32の場合のplaneの順番をG->B->RからR->G->Bに変更。
vsavsreaderは入力するavsがRGB24/32の場合、planar-RGBに変換します。
これはVSがpacked-RGBで展開することを禁止しているためです。
さて、RGB24/32をplanarに変換すること自体はとても簡単なのですが、問題はR,G,B各planeをどの順番でVSに渡すべきかです。
VapourSynth.hを読む限りでは特にどの順番で渡すのが既定なのか書かれていませんし、AviSynthのplanar-YUVのようにPLANAR_RとがPLANAR_Bのようなマクロも定義されていません。
で、とりあえずswscaleにあわせてG->B->Rの順番にしていましたが、つい先程vfw経由でプレビューしてみたら、どうやらR->G->Bで渡すのが標準のようでした。
ついでに今回から要求スペックをSSE2以上に上げました。
これはVSの大きな特徴であるマルチスレッド処理を活かすなら、最低でもCore2が要求されるからです。
と言っても、ビルド時のオプションで-msse2をつけただけなので、どうしてもPentium3やAthlonXPで使いたい人は、自分でオプションいじってビルドして下さい。
追記:
Myrsloik氏の公式発表により、VapourSynthはSSE2が使えるCPUを最低ラインとすることが決定しました。というわけで、Pen3/AthlonXPは完全にさようならです。
vsavsreader-d219012.7z
https://github.com/chikuzen/VS_AvsReader
* 入力がRGB24/RGB32の場合のplaneの順番をG->B->RからR->G->Bに変更。
vsavsreaderは入力するavsがRGB24/32の場合、planar-RGBに変換します。
これはVSがpacked-RGBで展開することを禁止しているためです。
さて、RGB24/32をplanarに変換すること自体はとても簡単なのですが、問題はR,G,B各planeをどの順番でVSに渡すべきかです。
VapourSynth.hを読む限りでは特にどの順番で渡すのが既定なのか書かれていませんし、AviSynthのplanar-YUVのようにPLANAR_RとがPLANAR_Bのようなマクロも定義されていません。
で、とりあえずswscaleにあわせてG->B->Rの順番にしていましたが、つい先程vfw経由でプレビューしてみたら、どうやらR->G->Bで渡すのが標準のようでした。
ついでに今回から要求スペックをSSE2以上に上げました。
これはVSの大きな特徴であるマルチスレッド処理を活かすなら、最低でもCore2が要求されるからです。
と言っても、ビルド時のオプションで-msse2をつけただけなので、どうしてもPentium3やAthlonXPで使いたい人は、自分でオプションいじってビルドして下さい。
追記:
Myrsloik氏の公式発表により、VapourSynthはSSE2が使えるCPUを最低ラインとすることが決定しました。というわけで、Pen3/AthlonXPは完全にさようならです。
2012年10月5日金曜日
vsavsreader.dll その4
vsavsreaderは最初からdither hackのinterleaved formatに対応していたわけですが、readmeにはそのことについては何も書いていませんでした。
これは単にreadmeに書くのが非常にめんどかったので放置していただけなわけですが、この度Doom9のほうで奇特にも書いてくれた人がいましたので追加しました。
vsavsreader-8c6c94a.7z
http://github.com/chikuzen/VS_AvsReader
いやはや、ありがたいことです。
これは単にreadmeに書くのが非常にめんどかったので放置していただけなわけですが、この度Doom9のほうで奇特にも書いてくれた人がいましたので追加しました。
vsavsreader-8c6c94a.7z
http://github.com/chikuzen/VS_AvsReader
いやはや、ありがたいことです。
P216改めP21x VFW Reader for AviUtl
HBVFWSourceのほうをいろいろいじっているうちに、P210やP010といったフォーマットについて誤解していたことに気づきました。
P210は10bitYUVだと思い込んでいたのですが、こちらをよくよく読んでみると
たしかにそのほうが色々扱いやすいわけですな。
で、P210もP216と全く同じ計算式でYC48に変換できることになりますので、P210も読めるように変更しました。
P21x_VFW_Reader_for_AviUtl-0.2.0.7z
https://github.com/chikuzen/P216_VFW_Reader_for_AviUtl
P210も読めるのであれば名前がP216 Readerってのもなんかおかしいので、ついでに名前をP21x VFW Readerに変更しましたが、gitレポはP216のままと、だんだんカオスなことに…まあ、いいか。
P210は10bitYUVだと思い込んでいたのですが、こちらをよくよく読んでみると
The 10-bit formats also use 16 bits for each channel, with the lowest 6 bits set to zero, as shown in the following diagram. Because the 10-bit and 16-bit representations of the same YUV format have the same memory layout, it is possible to cast a 10-bit representation to a 16-representation with no loss of precision. It is also possible to cast a 16-bit representation down to a 10-bit representation.と、まあ、P210/P010は10bitYUVを左に6bitシフトして16bitYUVにしたものでした。
たしかにそのほうが色々扱いやすいわけですな。
で、P210もP216と全く同じ計算式でYC48に変換できることになりますので、P210も読めるように変更しました。
P21x_VFW_Reader_for_AviUtl-0.2.0.7z
https://github.com/chikuzen/P216_VFW_Reader_for_AviUtl
P210も読めるのであれば名前がP216 Readerってのもなんかおかしいので、ついでに名前をP21x VFW Readerに変更しましたが、gitレポはP216のままと、だんだんカオスなことに…まあ、いいか。
2012年10月4日木曜日
HBVFWSource.dll
P216 VFW ReaderはAviUtl用ですが、こちらはAviSynth用です。
HighBitDepth_VFWSource-0.1.3.7z
https://github.com/chikuzen/HighBitDepth_VFWSource
P010/P016/P210/P216なクリップをVFW使って読み込みます。
読み込まれたクリップはdither hackのinterleaved formatの状態になります。
色変換の手間が要らないのとplanarフォーマットをサポートしてる分、やっぱAviSynthのほうが書きやすかったです。
追記:
やはり色々まずいところがあったようです。
0.1.3を上げたのですでにDLしてしまった人は差し替えて下さい。
HighBitDepth_VFWSource-0.1.3.7z
https://github.com/chikuzen/HighBitDepth_VFWSource
P010/P016/P210/P216なクリップをVFW使って読み込みます。
読み込まれたクリップはdither hackのinterleaved formatの状態になります。
色変換の手間が要らないのとplanarフォーマットをサポートしてる分、やっぱAviSynthのほうが書きやすかったです。
追記:
やはり色々まずいところがあったようです。
0.1.3を上げたのですでにDLしてしまった人は差し替えて下さい。
P216 VFW Reader for AviUtl
VapourSynthがVFWでP010/P016/P210/P216を出力するようになりました。
これをなるべく高品質でプレビューしたくなったので、AviUtl用の入力プラグインを書きました。
P216_VFW_Reader_for_AviUtl-0.1.0.7z
https://github.com/chikuzen/P216_VFW_Reader_for_AviUtl
使い方はreadmeのほうで。
色変換のコードをいろいろ書くのがメンドイので、P216専用です。
音声もVSが対応してないのでこっちも無視です。
それにしてもVFWって息が長いですね。
最後に仕様が改訂されたのはWindows95の時代ですよ…。
これをなるべく高品質でプレビューしたくなったので、AviUtl用の入力プラグインを書きました。
P216_VFW_Reader_for_AviUtl-0.1.0.7z
https://github.com/chikuzen/P216_VFW_Reader_for_AviUtl
使い方はreadmeのほうで。
色変換のコードをいろいろ書くのがメンドイので、P216専用です。
音声もVSが対応してないのでこっちも無視です。
それにしてもVFWって息が長いですね。
最後に仕様が改訂されたのはWindows95の時代ですよ…。
2012年10月1日月曜日
vsavsreader.dll その3
更新しました。
vsavsreader-4dafb1b.7z
https://github.com/chikuzen/VS_AvsReader
*vsavsreaderで作ったクリップをSplice()で結合出来なかったりしたのを修正
vsavsreader-4dafb1b.7z
https://github.com/chikuzen/VS_AvsReader
*vsavsreaderで作ったクリップをSplice()で結合出来なかったりしたのを修正
登録:
投稿 (Atom)