2011-01-03 7 views
17

私は自分のサーバからクライアントに多くのイメージを連続的に送信しています。クライアントでは、これが自分のイメージの最後であることを効率的に検出する必要があります。次の画像など。JPGイメージのEOFを検出する

敬具、 ...

+0

「送信」はどのプロトコルを使用していますか?あなたのプロトコルは、ファイルが自動的に終了する時を知らないのですか? –

+1

イメージの長さをあらかじめ送信しておきましょうか? – Kornel

+0

プロトコルを使用します。 –

答えて

26

まあ、jpeg画像内でFFD9が見つからないという保証はありません。 jpegイメージの終わりを見つける最良の方法は、それを解析することです。 FFD0〜FFD9とFF01(予約済み)を除くすべてのマーカーの直後に、マーカーではなく長さ指定子を含むマーカーセグメントの長さを示す長さ指定子が続きます。 FF00はマーカーではありませんが、目的のために長さ指定子なしのマーカーとして扱うことができます。

長さ指定子は2バイト長で、ビッグエンディアンです。したがって、FFを検索することです。次のバイトが0x00,0x01または0xD0-0xD8のいずれかでない場合は、長さ指定子を読み、長さ指定子がマイナス2バイトである限り、ストリーム内をスキップします。

また、すべてのマーカーには任意の数のFFを先頭に埋め込むことができます。

FFD9になると、ストリームの最後に移動します。

もちろん、パフォーマンスを求めている場合はFFで検索しても、読者の練習問題として残っています。なぜあなたはEOIを見つけることが保証されていないと言っている

onemase ;-)

+1

最初の文を明確にする必要があります。 FFD9は画像の最後にあることは明らかです。しかしFFD9はEOIマーカーではなくJPEG画像内に埋め込まれたように見えるかもしれません。そのため、EOIマーカーを見つけるためにJPEGを解析する必要があります。 – onemasse

+4

**要約**:0xFFを読み込みます。マーカーを読む。長さ指定子Lを読み込み、L - 2バイトだけスキップします。 SOS(0xFFDA)セグメントの後に(圧縮されたデータが続きます)、最初の0xFF **にスキップしてから** 0x00または0xD0-0xD8をスキップします。 0xFFD9に遭遇するまで、最初から繰り返す。 [このマルチスキャンJPEG](http://hodapple.com/blag/assets/obscure_jpeg_features/20100713-0107-interleave.jpg)で動作します。 –

+1

この方法は、壊れた画像(偶発的に作成されたファイルまたは悪意を持って改ざんされた偽の画像のいずれか)に対して脆弱です。 –

12

Wikipedia's JPEG articleで簡単に見はあなたに答え与えているだろう:

  • バイトは0xFF、0xD8を、画像
  • バイト0xFFでの開始を示します0xD9は画像の最後を示す
+5

JPEGに埋め込まれたJPEG(サムネイル画像など)があるため、SOI SOI EOI EOIマーカーが表示されることがあります。それを考慮に入れてください。 –

+0

@SB:true。簡単な方法は、ストリームからの読み取りが終了していない場合はEOI SOIマーカーを順番にスキャンし、終了した場合はEOIのマーカーをスキャンすることです。 – darioo

-3

? 最後にそこにいる必要があります。

少なくとも2つの長さフィールドの後に続くマーカーがもう1つあります。これはSOS、スキャンの開始、0xFFDAです。これは

長が続く - Lsがこのヘッダの

次のフィールドは、エントロピデータのサイズが含まれていないNs個(1バイト)6 + 2xNs(2バイト)セグメントの

数として指定しますSOSヘッダーに従います。 したがって、サイズを見つける唯一の方法は、EOI(End Of Image)= 0xFFD9のバイト単位で調べることです。

私は他の方法を見つけるのが大好きです。

+0

間違っています。 jpeg画像がAPPセグメント内にサムネイルとして埋め込まれているという保証はありません。逐次スキャンすることで、EOIが時期尚早に見つかるでしょう。 – onemasse

+0

はい。私は埋め込まれたイメージについては言及しなかった。したがって、ストリームのサイズを調べる唯一の方法は、すべてのStartOfImage、EndOfImageのペアimhoを探すことです。 SOSマーカーに長さが付いていないため、長さに依存することはできません。 – whobertoos

+1

いいえ。埋め込みイメージは単なる例に過ぎません。 APPセグメントには、FFD9を含む何でも含めることができます。順番に検索する必要がありますが、できるセグメントをスキップしてください。それを行う方法は私の答えに記載されています。 – onemasse

0

イメージをバイト配列経由で送信する場合は、イメージのファイルサイズをファイルの開始前にバイトのペアとして追加するだけです。
クライアントは、指定されたバイト数(最初は、xと呼ぶ)を探して破棄し、次のxバイト数をバッファに書き込んでファイルに書き出します。
以降のすべてのjpegについて、すすぎとリピートを繰り返します。

代わりに、FFD9マーカーを探しています。私が誤って圧縮した値ではない場合、FFはFF00としてエンコードされます(00バイトは破棄され、FFバイトは保持されます)。
この問題は、独自のFFD9ヘッダーを持つサムネイルのようなものが得られるが、ヘッダーのセグメント内に含まれているということです。これらのセグメントはマーカーの後の2バイトの長さの値を持つので、遭遇するセグメントの終わりまでスキップして、早期の凍結検出を避けることができます。

関連する問題