« Mojolicious でコマンド | ホーム | Playlist: Vocaloids 2011 Enter Winter »

2012年1月 2日

AtomicParsley で貼れる JPEG ファイル

AtomicParsley でアートワークに JPEG ファイルを貼付けようと思ったら、エラーになった。

image file is not jpg/png and cannot be embedded.

JPEG ファイルが壊れているのかと思って、プレビューを使って別名で保存したものは、エラーにならなかった。

調べてみると、ひとくちに JPEG と言っても、「 JPEG は画像のデータ圧縮の規格でありフォーマットそのものではありません」とのこと。ではフォーマットは、というと JFIF というのが至極一般的との事。エラーになったのは、 JFIF ではない JPEG ファイルだったからなんだろう(確認する前に捨ててしまった... )。

いずれにせよ、今作っているツールでは、 AtomicParsley 実行して初めてエラーで知るのでは都合が悪い。 AtomicParsley を実行する前にそれを判断したいので、 AtomicParsley がどんなふうに画像フォーマットを調べそしてエラーに導いたのか、そこの判定処理を、今作っているツールの事前処理のところに埋め込みたいと思う。

従って、ソースをあたってみる事にした。

AtomicParsley のソース( AtomicParsley.cpp )を見てみると、 PNG 形式と、 JPEG の次の二つの形式をチェックしている、らしきところが見つかった:

173 int APar_TestArtworkBinaryData(const char* artworkPath) {
174         int artwork_dataType = 0;
175         FILE *artfile = APar_OpenFile(artworkPath, "rb");
176         if (artfile != NULL) {          
177                 fread(twenty_byte_buffer, 1, 8, artfile);
178                 if ( strncmp(twenty_byte_buffer, "\x89\x50\x4E\x47\x0D\x0A\x1A\x0A", 8) == 0 ) {
179                         artwork_dataType = AtomFlags_Data_PNGBinary;
180                 } else if ( strncmp(twenty_byte_buffer, "\xFF\xD8\xFF\xE0", 4) == 0 || memcmp(twenty_byte_buffer, "\xFF\xD8\xFF\xE1", 4) == 0 ) {
181                         artwork_dataType = AtomFlags_Data_JPEGBinary;
182                 } else {
183                         fprintf(stdout, "AtomicParsley error: %s\n\t image file is not jpg/png and cannot be embedded.\n", artworkPath);
184                         exit(1);
185                 }
186                 fclose(artfile);
187                 
188         } else {
189                 fprintf(stdout, "AtomicParsley error: %s\n\t image file could not be opened.\n", artworkPath);
190                 exit(1);
191         }
192         return artwork_dataType;
193 }

ファイルの先頭 8 バイトを読み込んで、バイトの並び方をチェック。 PNG 形式と JPEG 形式と。特に難しい事ではないけれど、ここでは、 AtomicParsley が実際にどんなパターンでチェックしているのかを確認できたことが重要だ。そのマニュアルには、アートワークに貼付けられる画像は png または jpeg 、とあったけれども jpeg にはいろいろなフォーマットがあって、そのうちの、この二種類のマジックナンバーが対応しているにすぎない。ということが、これで判った。

さてこうして、 AtomicParsley で埋め込み出来るイメージファイルであるかをチェックだけするルーチンを Perl で書く事が出来た。未対応の形式だったら、 PNG もしくは JFIF にコンバートすればよいだろう。

https://gist.github.com/1549186

余事ながら、この中で3カ所、ヘッダパターンをチェックしている記述があるけれど、ふたつは strncmp でチェックしているのに、あとの一つは memcmp でチェックしているのはなぜだろう? むしろすべてを memcmp でチェックすべきかな?

コメントする

OpenID対応しています OpenIDについて

このブログ記事について

このページは、hiroakiが2012年1月 2日 12:43に書いたブログ記事です。

ひとつ前のブログ記事は「Mojolicious でコマンド」です。

次のブログ記事は「Playlist: Vocaloids 2011 Enter Winter」です。

最近のコンテンツはインデックスページで見られます。過去に書かれたものはアーカイブのページで見られます。