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


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


3315
2017-11-07 16:29


起源

我会建议检测的唯一方法 一切 图像中的一种错误(其中“错误”被定义为导致不完美行为的任何差异)是继续使用图像。尽管如此,图像完全有可能遭受损坏,但仍会产生有效的文件,尽管其中包含“错误的像素”。可能有用的是非常具体地考虑您想要检测的内容。 - Andrzej Doyle
ImageIO可以在抛出异常的情况下检测截断的PNG,但是对于被截断的JPG,我无法让它抛出异常。 - Archimedes Trajano
你有没有得到任何解决方案? - Manohar Perepa


答案:


这是我的解决方案,可以处理损坏的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;
    }
 }
}

10
2018-04-09 05:55



JPEG条件检查的两个子句不应该与逻辑OR而不是AND连接吗? - mnicky
你可以链接这个类ImageAnalysisResult - Manohar Perepa
你能否在答案中包含所有的进口陈述? - Manohar Perepa


如果是JPEG图像,请使用:

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

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

对于其他情况;只是用 new ImageIcon(file) 检查有效性。


5
2017-09-19 08:23



对我不起作用(i.imgur.com/rE89Bpl.jpg)。 - mnicky
它也适用于你的形象:) - Bassel Kh
它工作正常,如果它是无效的jpeg图像,那么它将抛出ImageFormatException。有没有办法检查mp4文件是否已损坏? - Sumanth Varada


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

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

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


1
2017-11-07 17:05





   //below code is for  How to check corrupted .jpeg, .png, .jpg, .tiff   
    images in java

     public boolean isValidImage(File f) {
     boolean isCorrupted=false;
     try {
            BufferedImage bi = ImageIO.read(f);
            bi.flush();
            isCorrupted=true;  //if image file is not corrupted then it is true...
        } catch (Exception e) {
            isCorrupted=false;  //if image file is corrupted then it is false...
        }

    return isCorrupted;
}

0
2017-08-23 06:04