アプリ版:「スタンプのみでお礼する」機能のリリースについて

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

A 回答 (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ファイル。

モノによって,うまく動作しないファイルが出てきたときは,こういう可能性も疑ってください。
# 専用ライブラリやそのコードを再利用すると,こういう点を気にせずに済む。
    • good
    • 0
この回答へのお礼

3度のfgetc(fp);でファイルポインタを進めた部分は
length_high, length_low, precision だったんですね。
何のlengthなのか分からないし、precisionって聞いたことないけど
今後の参考になりそうです。

SOFマーカーが無い場合はアプリを終了させました。
縦横を得るだけの実験アプリだから、べつに終わらせなくても
よかったんだけどね。
exit(1);の前にfclose(fp);を書き忘れていました。

JPGにはその中にまたいくつかの細かい分類が多くあるらしいですね。
最後に教えてもらったことも、今後、エラーが起こった場合に
参考にします。
ありがとうございました。

お礼日時:2002/07/09 00:21

アレレ? 縦と横入れ替わるはずはないぞぅ,なんて思っていたら…


説明間違ってるぅぅぅぅ!
buf[2] buf[3]の length 勘定するのすっかり忘れとりました。

というわけで,訂正すると

buf[5] buf[6] が YSize
buf[7] buf[8] が XSize

# fgetcで済ますとは思いつかなんだぁ~

>h2がやたらと大きな値に
fgetcの返す値を符号付きな (signed) char型 に代入?
さらにその後,なにかここには記載してない秘密の演算を施したりしていませんか?
そのあたりに原因があると思うなぁ。

よくわからなかったら,debugでh2が関与している部分の値を16進数表示にて追いかけてみましょう。

この回答への補足

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 勘定って何ですか?

補足日時:2002/07/07 06:59
    • good
    • 0

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変数に代入すれば,ハイ出来上がり。

処理の流れはこんなもんですね。
ファイル入出力,ポインタ,アドレッシング,型を理解していれば簡単に,理解が足りなければ後学のために,ソースコード書き上げてしまいましょ~。
    • good
    • 0
この回答へのお礼

ありがとうございます。
縦と横はその逆ですね。
ビッグエンディアンだとして、

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がやたらと大きな値になってしまったものもありました。
そのことと、幅の取得について実験中です。

お礼日時:2002/06/29 00:49

C++なら素直にlibjpeg等のjpegライブラリを使えばいけるでしょう。



ライブラリ使うのが駄目なら,jpegの仕様に関して調べて,jpegヘッダ内でのその情報の格納位置を調べるのが早いですよ。

「JPGのヘッダからwidhtとheightを得るC++ソース」は「JPGのヘッダ内でのwidhtとheightのアドレス」に比べて,相当稀な情報でしょうから…
    • good
    • 0
この回答へのお礼

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

お礼日時:2002/06/21 20:10

お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!