2017-12-05 5 views
0

1つまたは複数の画像を含むストリームがあり、連続してフラグを付けずに格納されています。 javas ImageIOを使用してストリームを開いて解析すると、最初のイメージが正しく解析されますが、ストリームが閉じられ、次のイメージをストリームできなくなります。ストリーム内に連続して格納された複数のjpegを解析する

私はファイル内の各圧縮イメージの大きさを把握しようとしているので、そのイメージの正確なバイト数をバッファに読み込み、そのバッファからByteArrayInputStreamを作成し、 BufferedImage新しい小さなバッファを使用しています。私の問題は、画像の大きさを調べることです。幅/高さは、圧縮が幅*高さよりも小さいので助けになりません。

バッファを読み取って各画像の終わりを簡単に見つける方法はありますか?ストリームの終わりには1つのeofを除いて、ソイ、エイ、ソフ、eof、タグはありません。

これを行うには良い方法がありますか? ImageIO.read()にストリームを閉じないで、それを使って作業を続ける方法?

+0

複数のSOI/EOIなしで、複数の画像を持つJPEG(JFIF)があるとは思えません。どのソフトウェアがそれを書いたのか知​​っていますか?共有するサンプルファイルがありますか?もしそうなら、私はおそらく助けることができます。 – haraldK

+0

私はnitfファイルを扱っていましたが、共有できませんが、JPEG画像を含むことができるDoDイメージ形式です。私が探していたファイルはjpegに準拠していなかったと思います.DoDのウェブサイトのサンプルファイルには、soi、eoiというタグがあります。 – broccolli

答えて

0

まず、ImageIO.read(...)は任意の形式のファイルの単一の(最初の)イメージを読むことができる便利な方法です。

場合は、代わりに、あなたの入力のためのImageReaderを得るには、(一般的に)getNumImages(boolean allowSearch)を使用して入力して画像の数を取得することができ、かつ読み(またはスキップ)個々の画像はread(int imageIndex, ImageReadParam param)を使用。以下のような

何か:

// Create input stream 
try (ImageInputStream input = ImageIO.createImageInputStream(file)) { 
    // Get the reader 
    Iterator<ImageReader> readers = ImageIO.getImageReaders(input); 

    if (!readers.hasNext()) { 
     throw new IllegalArgumentException("No reader for: " + file); 
    } 

    ImageReader reader = readers.next(); 

    try { 
     reader.setInput(input); 

     // Optionally, listen for read warnings, progress, etc. 
     reader.addIIOReadWarningListener(...); 
     reader.addIIOReadProgressListener(...); 

     ImageReadParam param = reader.getDefaultReadParam(); 

     // Note: For some formats (ie. GIF), finding the number of images 
     // requires searching the entire stream. In this case, it may 
     // be more convenient to just read until you get an IndexOutOfBoundsException 
     for (int i = 0; i < reader.getNumImages(true); i++) { 
      // Optionally, control read settings like sub sampling, source region or destination etc. 
      param.setSourceSubsampling(...); 
      param.setSourceRegion(...); 
      param.setDestination(...); 
      // ... 

      // Finally read the image, using settings from param 
      BufferedImage image = reader.read(i, param); 

      // Optionally, read thumbnails, meta data, etc... 
      int numThumbs = reader.getNumThumbnails(0); 
      // ... 
     } 
    } 
    finally { 
     // Dispose reader in finally block to avoid memory leaks 
     reader.dispose(); 
    } 
} 

JREバンドルJPEGImageReaderは理論的にも、単一ストリームで複数のJFIFのサブをサポートする必要があります。しかし、私はあなたがサポートが壊れていることがわかると思います(少なくともImageIOプラグインプロジェクトにはopen issue to fix thisがあります)。

残念ながら、デコードせずに(またはJFIFストリームの外に保存された長さの)JPEG圧縮画像の長さを見つけることはできません。あなたが試みることができる

ことの一つは、(「スタート・オブ・イメージ」、0xffd8)次SOIため、その後、前方スキャン最初の画像を読み取るために(おそらくImageInputStreamがラップ)されたマーカーは、は2つのバイトはバック求めます(SOIマーカーの場合)、次のイメージの読み取りを試みます。 SOIマーカーは、JPEGエンコードされたデータの内部には存在しません。

JPEGJFIF segmentsについては、Wikipediaでもっと詳しく読むことができます。

+0

これはすばらしい解決策でした。私がしなければならなかったことは、読者を引き出してそこからすべてのイメージを繰り返していただけでした。感謝しました。 – broccolli

関連する問題