• ベストアンサー

JPGのwidhtとheight

JPGのヘッダからwidhtとheightを得るソースを教えてください。 Perlの ($m, $c, $l) = unpack("a a n", $t); みたいなやつを C++のコードにしたものを探しています。

質問者が選んだベストアンサー

  • ベストアンサー
  • onosuke
  • ベストアンサー率67% (310/456)
回答No.4

こんな簡単なソースでいいんです~。 >>buf[2] buf[3]の length 勘定って何ですか? う,これは日本語として見直すと句読点が足りない! 「length(の分), 勘定するのを....」 正しくはこうです。 *buf={ 。。0xFF, 0xC0, 。。length_high, length_low, 。。precision, 。。y_high, y_low, 。。x_high, x_low }; 要は上記のようなヘッダフォーマットだという話。 >>もっと直した方がいいところがあったら教えてください。 処理としては,何も口を出すところはありませんよ。 if(feof(fp)){    exit(1); ここで「exit() 使わずともよいのでは?」ってぐらいかな。 return で値返すと,戻り先で処理判断させる選択肢を残せますからね。 最後に気をつけたほうがよいことを。 私自身,まじめに仕様書を読んでいないので,以下のような状況の有無がわかりません。 1. Start Code とは無関係の部分で 0xFFC0 の判別コードが現れる。 2. 0xFFC0 で始まるsegmentをもたないjpegファイル。つまり,規格の拡張により,0xFFC0以外のsegmentがwidthとheightの情報を持っているjpegファイル。 モノによって,うまく動作しないファイルが出てきたときは,こういう可能性も疑ってください。 # 専用ライブラリやそのコードを再利用すると,こういう点を気にせずに済む。

A__
質問者

お礼

3度のfgetc(fp);でファイルポインタを進めた部分は length_high, length_low, precision だったんですね。 何のlengthなのか分からないし、precisionって聞いたことないけど 今後の参考になりそうです。 SOFマーカーが無い場合はアプリを終了させました。 縦横を得るだけの実験アプリだから、べつに終わらせなくても よかったんだけどね。 exit(1);の前にfclose(fp);を書き忘れていました。 JPGにはその中にまたいくつかの細かい分類が多くあるらしいですね。 最後に教えてもらったことも、今後、エラーが起こった場合に 参考にします。 ありがとうございました。

すると、全ての回答が全文表示されます。

その他の回答 (3)

  • onosuke
  • ベストアンサー率67% (310/456)
回答No.3

アレレ? 縦と横入れ替わるはずはないぞぅ,なんて思っていたら… 説明間違ってるぅぅぅぅ! buf[2] buf[3]の length 勘定するのすっかり忘れとりました。 というわけで,訂正すると buf[5] buf[6] が YSize buf[7] buf[8] が XSize # fgetcで済ますとは思いつかなんだぁ~ >h2がやたらと大きな値に fgetcの返す値を符号付きな (signed) char型 に代入? さらにその後,なにかここには記載してない秘密の演算を施したりしていませんか? そのあたりに原因があると思うなぁ。 よくわからなかったら,debugでh2が関与している部分の値を16進数表示にて追いかけてみましょう。

A__
質問者

補足

FILE *fp; int c, w1, w2, h1, h2; //int型にした //  fp = fopen("a.jpg", "rb");  while(1){   if(fgetc(fp) == 0xFF){    if(fgetc(fp) == 0xC0) break;   }else if(feof(fp)){    exit(1);   }  }  fgetc(fp);  fgetc(fp); //これを追加した  fgetc(fp); //これを追加した  h1 = fgetc(fp); //縦と横を入れ替えた  h2 = fgetc(fp);  w1 = fgetc(fp);  w2 = fgetc(fp);  fclose(fp); ありがとうございます。 buf[0]=FF; buf[1]=C0; buf[5] buf[6] が YSize buf[7] buf[8] が XSize ということからこのソースにしてできました。 例えばYSizeなら、buf[5] × 256 + buf[6] が実際のサイズに なるみたいですね。 こんな簡単なソースでいいんですか? 今のところこれでできているけど、もっと直した方がいいところが あったら教えてください。 buf[2] buf[3]の length 勘定って何ですか?

すると、全ての回答が全文表示されます。
  • onosuke
  • ベストアンサー率67% (310/456)
回答No.2

jpeg header で検索してみると… Start of frame marker (FFC0) the first two bytes, the length, after the marker indicate the number of bytes, including the two length bytes, that this header contains P -- one byte: sample precision in bits (usually 8, for baseline JPEG) Y -- two bytes X -- two bytes てな話なもんで,まず ファイルから 読み取りバッファに読み込んで,読み取りバッファから frame marker の開始バイト列 char framemaker[2]={FF,C0}; と一致する部分を探す。次に char buf[16] 程度なバッファに buf[0]=FF; buf[1]=C0; となるよう,読み取りバッファから一致する部分の辺りをコピーしてやる。すると, buf[3],buf[4]がY方向,縦のサイズ buf[5],buf[6]がX方向,横のサイズ となるわけだ。 後はエインディアンに注意して,2バイトのバイト列を16bit整数に型変換,適当なint変数に代入すれば,ハイ出来上がり。 処理の流れはこんなもんですね。 ファイル入出力,ポインタ,アドレッシング,型を理解していれば簡単に,理解が足りなければ後学のために,ソースコード書き上げてしまいましょ~。

A__
質問者

お礼

ありがとうございます。 縦と横はその逆ですね。 ビッグエンディアンだとして、 FILE *fp; int c; char w1, w2, h1, h2; //  fp = fopen("a.jpg", "rb");  while(1){   if(fgetc(fp) == 0xFF){    if(fgetc(fp) == 0xC0) break;   }else if(feof(fp)){    exit(1);   }  }  fgetc(fp);  w1 = fgetc(fp);  w2 = fgetc(fp);  h1 = fgetc(fp);  h2 = fgetc(fp);  fclose(fp); これで、h1が0で、h2だけによって高さが得られたJPGも あったけど、同じく小さい画像でも高さが正確に得られず h1が0でh2がやたらと大きな値になってしまったものもありました。 そのことと、幅の取得について実験中です。

すると、全ての回答が全文表示されます。
  • onosuke
  • ベストアンサー率67% (310/456)
回答No.1

C++なら素直にlibjpeg等のjpegライブラリを使えばいけるでしょう。 ライブラリ使うのが駄目なら,jpegの仕様に関して調べて,jpegヘッダ内でのその情報の格納位置を調べるのが早いですよ。 「JPGのヘッダからwidhtとheightを得るC++ソース」は「JPGのヘッダ内でのwidhtとheightのアドレス」に比べて,相当稀な情報でしょうから…

A__
質問者

お礼

Perlルが見つかって、だいたいは 分かったし、JPGのヘッダのどこに大きさがあるかも だいたい分かったけど、Perlのサンプルだとパックの 部分がよく分からなかったし、ずっと前にどこかで ダウンロードしたjpeg-6bっていうファイル郡を 見てみたけど、ファイルが多すぎて、大きさを得る 部分だけを抜き出すことができませんでした。 今もたまにJPGのヘッダの資料を見たりしているけど ソースがあれば理解が早いです。 どこかに公開されているソースはないですかねー。

すると、全ての回答が全文表示されます。

関連するQ&A