2011-11-07 55 views
9

我需要檢測圖像文件是否在Java中損壞。我只使用PNG,JPG圖片。這可能與桑塞蘭有關嗎?或者可以用ImageIO完成嗎?我試過使用ImageIO.read似乎是有效的。但我不確定它是否可以檢測圖像中的各種錯誤。我想知道最佳做法是什麼。如何在Java中檢測損壞的圖像(PNG,JPG)

+2

我建議檢測圖像中每一種錯誤的唯一方法就是繼續前進並使用該圖像(其中「錯誤」被定義爲導致不完美行爲的任何差異)。對於圖像來說,完全有可能遭受腐敗,儘管如此卻導致了一個有效的文件,儘管其中有一個「錯誤的像素」。非常具體地考慮你想要檢測的是什麼可能是有用的。 –

+2

ImageIO可以檢測到被截斷的PNG,並拋出一個異常,但對於截斷的JPG,我無法讓它拋出異常。 –

+0

你有沒有得到任何解決方案? –

回答

1

如果無法解析圖像,則該文件已損壞,否則該文件應該是有效的,但包含錯誤的像素,正如Andrzej指出的那樣。如果你無法定義你將如何找到「錯誤」的像素,檢測這可能是非常困難的。

如果您有關於基礎圖像的信息,例如直方圖甚至原始像素,您可以試着將它們與讀取的圖像進行比較。但請注意,由於壓縮,可能會出現一些錯誤,因此您需要添加一些容差值。

附加註意事項:Sanselan不會讀取JPEG圖像,因此您必須在此處使用ImageIO。

9

這是我的解決方案,將處理檢查損壞的GIF,JPG和PNG。它檢查使用截斷JPEG的JPEG EOF標記,GIF使用索引越界異常檢查,並使用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條件檢查的兩個子句不應該用邏輯OR而不是AND連接? – mnicky

+0

您能否連接此課程ImageAnalysisResult –

+0

您是否可以在您的答案中包含所有導入語句 –

4

PNG如果JPEG圖像,使用:

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

如果拋出異常;這意味着圖像已損壞。

其他情況;只需使用new ImageIcon(file)來檢查有效性。

+0

不適用於我(http://i.imgur.com/rE89Bpl.jpg)。 – mnicky