如何在Java中检测损坏的图像(PNG,JPG)

时间:2011-11-07 16:29:09

标签: java image javax.imageio

我需要检测图像文件是否在Java中被破坏。我只使用PNG,JPG图像。这可能与Sanselan有关吗?或者可以用ImageIO完成吗?我尝试过使用ImageIO.read似乎很有效。但我不确定它是否可以检测到图像中的各种错误。我想知道什么是最好的做法。

4 个答案:

答案 0 :(得分:11)

这是我的解决方案,可以处理损坏的GIF,JPG和PNG。它使用JPEG EOF标记检查截断的JPEG,使用索引超出边界的异常检查检查GIF,使用EOFException检查PNG

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;
    }
 }
}

答案 1 :(得分:6)

如果是JPEG图像,请使用:

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

如果它抛出异常;这意味着图像已损坏。

其他案件;只需使用new ImageIcon(file)来检查有效性。

答案 2 :(得分:2)

以下代码在Java中验证.jpeg,.png,.jpg,.tiff图像

public boolean isValidImage(File f) {
  boolean isValid = true;
  try {
    ImageIO.read(f).flush();
  } catch (Exception e) {
    isValid = false;
  }
  return isValid;
}

答案 3 :(得分:1)

如果无法解析图像,则文件已损坏,否则文件应该有效但包含错误的像素,正如Andrzej所指出的那样。如果您无法定义如何找到“错误”的像素,则检测到这可能会非常困难。

如果您有关于基本影像的信息,例如直方图甚至是原始像素,您可以尝试将它们与读取的图像进行比较。但请注意,由于压缩可能会出现一些错误,因此您需要添加一些容差值。

另外注意:Sanselan不会读取JPEG图像,因此您必须在此处使用ImageIO。