2011-11-07 9 views
9

に破損した画像(PNG、JPG)を検出するためにはどのようにイメージファイルがJavaで破損しているかどうかを検出する必要があります。私はPNG、JPG画像だけで作業しています。これはSanselanと関係がありますか?それとも、ImageIOでできるのですか?私はImageIOを使用してみました。それは動作するように見えます。しかし、画像のすべての種類のエラーを検出できるかどうかはわかりません。私はベストプラクティスが何であるかを知りたい。は、Java

+2

イメージ内のすべての種類のエラーを検出する唯一の方法(「エラー」は、不完全な動作の原因となる不一致と定義されます)は、先に進みイメージを使用することです。それでも画像が壊れてしまう可能性はありますが、「間違ったピクセル」のファイルでも有効なファイルになります。それはあなたが何を検出したいかについて非常に具体的に考えることが有用かもしれません。 –

+2

ImageIOは例外がスローされたときに切り捨てられたPNGを検出できますが、切り捨てられたJPGに対しては例外をスローすることができません。 –

+0

これにはどんな解決策がありましたか? –

答えて

1

画像ファイルを解析できない場合は破損している、そうでない場合は、ファイルが有効である必要がありますが、アンジェイが指摘したように、間違ったピクセルを含みます。 「間違った」ピクセルを見つける方法を定義できない場合、それを検出することはかなり難しいかもしれません。

あなたがベースイメージの情報をお持ちの場合は、例えばヒストグラム、元のピクセルさえ知っている場合は、読み込んだ画像と比較してみてください。ただし、圧縮によっていくつかのエラーが発生する可能性があるので、いくつかの許容値を追加する必要があります。

追加サイドノート:あなたがここにImageIOでを使用する必要があると思いますので、Sanselanは、JPEG画像を読みません。ここで

9

は壊れたGIF、JPGやPNGのチェックを扱うでしょう私の解決策です。それならば

JPEGImageDecoder decoder = new JPEGImageDecoder(new FileImageSource(f) ,new FileInputStream(f)); 
decoder.produceImage(); 

:それはこれを使用し、JPEGの画像場合EOFExceptionでは

public static ImageAnalysisResult analyzeImage(final Path file) 
     throws NoSuchAlgorithmException, IOException { 
    final ImageAnalysisResult result = new ImageAnalysisResult(); 

    final InputStream digestInputStream = Files.newInputStream(file); 
    try { 
     final ImageInputStream imageInputStream = ImageIO 
       .createImageInputStream(digestInputStream); 
     final Iterator<ImageReader> imageReaders = ImageIO 
       .getImageReaders(imageInputStream); 
     if (!imageReaders.hasNext()) { 
      result.setImage(false); 
      return result; 
     } 
     final ImageReader imageReader = imageReaders.next(); 
     imageReader.setInput(imageInputStream); 
     final BufferedImage image = imageReader.read(0); 
     if (image == null) { 
      return result; 
     } 
     image.flush(); 
     if (imageReader.getFormatName().equals("JPEG")) { 
      imageInputStream.seek(imageInputStream.getStreamPosition() - 2); 
      final byte[] lastTwoBytes = new byte[2]; 
      imageInputStream.read(lastTwoBytes); 
      if (lastTwoBytes[0] != (byte)0xff || lastTwoBytes[1] != (byte)0xd9) { 
       result.setTruncated(true); 
      } else { 
       result.setTruncated(false); 
      } 
     } 
     result.setImage(true); 
    } catch (final IndexOutOfBoundsException e) { 
     result.setTruncated(true); 
    } catch (final IIOException e) { 
     if (e.getCause() instanceof EOFException) { 
      result.setTruncated(true); 
     } 
    } finally { 
     digestInputStream.close(); 
    } 
    return result; 
} 

public class ImageAnalysisResult { 
    boolean image; 
    boolean truncated; 
    public void setImage(boolean image) { 
     this.image = image; 
    } 
    public void setTruncated(boolean truncated) { 
     this.truncated = truncated; 
    } 
} 
} 
+2

JPEG条件チェックの2つの節を論理ANDでANDの代わりに接続してはいけませんか? – mnicky

+0

このクラスをリンクすることはできますかImageAnalysisResult –

+0

答えにすべてのインポートステートメントを含めることができますか –

4

を使用して境界例外チェックやPNGのうち、インデックスを使用してJPEG EOFマーカーを使用して切り捨てJPEG、GIFをチェック例外をスローします。これは画像が壊れていることを意味します。他の例について

。妥当性を確認するにはnew ImageIcon(file)を使用してください。

+0

私のためには機能しません(http://i.imgur.com/rE89Bpl.jpg)。 – mnicky