2011-11-07 26 views
9

Devo rilevare se il file immagine è danneggiato in Java. Sto lavorando solo con immagini PNG, JPG. E 'possibile farlo con Sanselan? Oppure può essere fatto con ImageIO? Ho provato a utilizzare ImageIO.read sembra che funzioni. Ma non sono sicuro che possa rilevare ogni tipo di errore nelle immagini. Mi piacerebbe sapere qual è la migliore pratica.Come rilevare immagini danneggiate (PNG, JPG) in Java

+2

Suggerirei che l'unico modo per rilevare * ogni * tipo di errore in un'immagine (dove "errore" è definito come qualsiasi discrepanza che causa un comportamento imperfetto) è quello di andare avanti e utilizzare l'immagine. È del tutto possibile che un'immagine subisca una corruzione che comunque produce un file valido, anche se con "pixel errati". Potrebbe essere utile pensare in modo molto specifico a ciò che vuoi rilevare. –

+2

ImageIO può rilevare il PNG troncato con un'eccezione generata, ma per JPG che viene troncato, non riesco a ottenere un'eccezione. –

+0

Hai trovato qualche soluzione per questo? –

risposta

1

Se l'immagine non può essere analizzata, il file è corrotto, altrimenti il ​​file dovrebbe essere valido ma contiene i pixel errati come sottolineato da Andrzej. Rilevare che potrebbe essere piuttosto difficile se non è possibile definire come si troveranno i pixel "sbagliati".

Se si dispone di informazioni sull'immagine di base, ad es. un istogramma o anche i pixel originali, si potrebbe provare a confrontare quelli con l'immagine di lettura. Si noti, tuttavia, che a causa della compressione potrebbero esserci alcuni errori, quindi è necessario aggiungere un valore di tolleranza.

Un'ulteriore nota a margine: Sanselan non leggerà le immagini JPEG, quindi è necessario utilizzare ImageIO qui.

9

Ecco la mia soluzione che gestirà il controllo di file GIF, JPG e PNG danneggiati. Si verifica la presenza di troncata JPEG usando il marcatore JPEG EOF, GIF utilizzando un indice di controllo limiti eccezione e PNG utilizzando un 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

Le due clausole del controllo delle condizioni JPEG non dovrebbero essere collegate con OR logico invece di AND? – mnicky

+0

Puoi collegare questa classe ImageAnalysisResult –

+0

Puoi includere tutte le istruzioni di importazione nella tua risposta per favore –

4

Se l'immagine in formato JPEG, utilizzare questo:

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

se lancia un'eccezione; questo significa che l'immagine è corrotta.

per gli altri casi; basta usare new ImageIcon(file) per verificare la validità.

+0

Non funziona per me (http://i.imgur.com/rE89Bpl.jpg). – mnicky

Problemi correlati