Automatizzare la scansione dei file grafici per la corruzione

Qualcuno sa di un modo per controllare i file grafici (in particolare JPEG, GIF e PNG) per la corruzione (preferibilmente in modo automatizzato)?


Spiegazione:

Alcuni giorni fa un command ha funzionato in modo non corretto e ha finito per eliminare migliaia di file grafici da un volume FAT32 praticamente fuori spazio. Ho usato diversi programmi di ripristino di file / foto, ma naturalmente sono limitati a quanto possono recuperare (anche se fortunatamente il volume ha cluster 8KB, che aiuta un po ').

Comunque, alcuni dei file più grandi, che sono stati frammentati, sono ora corrotti. Alcuni di loro non sono nemless i file reali (il software di recupero ha semplicemente scaricato i cluster che sono stati indicati da voci di directory già sovrascritte), mentre altri sono rotti a causa della frammentazione.

Inoltre, poiché alcuni formati di immagini incorporano una versione più piccola dell'image come miniatura, la scansione delle miniature per la corruzione non è affidabile perché potrebbe essere intatta mentre il file effettivo (cioè l'image quando è visibile a pieno formato) potrebbe essere danneggiato.


Qui ci sono un paio di esempi:

Ecco il secondo. È così danneggiato che non mostra nulla.

immagine danneggiata

(Un terzo non carica nemless perché non ha nemless l'intestazione corretta!)

Provate l' opzione jpeginfo ' -c ' per i tuoi file JPEG.

Ho visto la corruzione che mostri accadere con carte di memory difettose troppo.
Quello che vuoi dovrebbe essere ansible e disponibile, controllare la corruzione dei file grafici ;
una sezione dall'Enciclopedia in linea dei formati di file grafici .

Vedere anche Controlli di integrità file in un'introduzione di base alle funzionalità PNG .

Potresti essere interessato a questa domanda di Stackoverflow,
Come controllare a livello di programmazione se un'image (PNG, JPEG o GIF) è danneggiata ?


Aggiornamento : tarball di origine per la versione 1.6.1 di Timo Kokkonen .
Dovresti essere in grado di build un binario per la tua macchina.

Da quando mi sono imbattuto in questo mentre cercavo di rispondere alla stessa domanda, aggiungo un'altra grande soluzione che ho trovato:

Bad Peggy

Schermata dell'applicazione

uso
Dal menu, select File > Scan e quindi utilizzare la window di dialogo per individuare la cartella in cui si trovano le immagini. Il programma avvia quindi la scansione della cartella e tutte le sottocartelle per le immagini (.jpg, .png, .bmp, .gif). Se si desidera eseguire una scansione di molte immagini, ci vorrà un po 'di tempo, perché il programma ha bisogno di caricare e analizzare completamente il file di image, pertanto è consigliabile farlo funzionare durante la notte.

Mentre sta scansionando, mostrerà una percentuale di progresso nella barra di stato. Tutte le immagini che trovano non perfette verranno visualizzate direttamente nell'elenco. Se fai clic su un'image nell'elenco, visualizzerà un'anteprima di come l'image sembra. Molto spesso un'image avrà solo un problema minore con il formato di file e l'image rimarrà perfetta. Altre volte l'image non sarà in grado di rendere affatto e l'anteprima sarà solo nero. A volte l'image sarà danneggiata e vedrai qualcosa come nello screenshot sopra.

Un trucco molto comodo è fare clic nell'intestazione della colonna su Reason e le immagini verranno ordinate in base a quanto sono danneggiati (ad esempio tutti i file di file difettosi che ancora rendono correttamente si spostano verso il basso consentendo di concentrarsi sui casi più gravi ).

Anche se la prima scansione è terminata e si avvia un'altra scansione, i risultati saranno semplicemente aggiunti all'elenco. Quindi, se hai molte cartelle diverse con le immagini, puoi semplicemente scannerli in sequenza senza che l'elenco venga eliminato quando si avvia una nuova scansione. Se si desidera che l'elenco venga cancellato, utilizzare il menu di scelta rapida e fare clic su Clear list .

link
È ansible trovare i download per Windows, Linux e OS X:
https://www.coderslagoon.com

Il codice sorgente è qui:
https://github.com/coderslagoon/badpeggy

Ciò può essere fatto utilizzando il command .verify() Python Imaging Library . [1]

Per eseguire questa operazione in Windows, installare Python (ho installato l'ultima versione corrente di Python 2) e quindi installare Cuscino (una forchetta di Python Imaging Library (PIL)). Quindi, copia il codice di jpeg_corrupt.py [2] e salva il suo contenuto in un file .PY, ad esempio jpeg_corrupt.py.

Notare che ho modificato la seguente row di codice in jpeg_corrupt.py :
self.globs = ['*.jpg', '*.jpe', '*.jpeg']
a
self.globs = ['*.jpg', '*.jpe', '*.jpeg', '*.png', '*.gif']
Questo così i file .PNG e .GIF verranno scansionati.

Può quindi essere eseguito tramite il prompt dei comandi di Windows (cmd.exe) come questo: C:\Python27\python.exe "C:\Directory containing the .PY file\jpeg_corrupt.py" "C:\Directory of folder to be scanned"

La prima parte del command, ' C: \ Python27 \ python.exe ', potrebbe essere diversa a seconda della versione di Python installata e della directory in cui è stato installato. Nel mio esempio, è la directory di installazione predefinita di Python 2.7.

Dovrebbe scannerizzare tutte le immagini JPG, GIF e PNG nella directory specificata e in tutte le sue sottodirectory. Essa mostra un'output se rileva un file di image danneggiato.

Ho eseguito questa operazione sull'image di esempio di OP e ho dato questo messaggio di errore: ...\YcB9n.png: string index out of range .

Il codice potrebbe anche essere inserito in un file di script BAT, in modo da poterlo gestire facilmente una directory specificata senza wherer utilizzare il prompt dei comandi:

 C:\Python27\python.exe "C:\Directory containing the .PY file\jpeg_corrupt.py" "%CD%" pause 


fonti:

[1]: Risposta in overflow dello stack – "Come controllare a livello di programmazione se un'image (PNG, JPEG o GIF) è danneggiata?" di ChristopheD
[2]: Commento di Denilson Sá nella risposta SO collegata in [1]

Il programma di identificazione di ImageMagick vi informsrà se un'image è danneggiata. Un test per la ricerca in lo stato di i in find per un codice restituito da zero non consentirà di eseguire la scrittura del test abbastanza facilmente per scaricare una list di file danneggiati o danneggiati. Funziona anche su Windows con PowerShell.

immettere qui la descrizione dell'immagine

Il seguente codice con le modifiche per il path funziona bene in powershell

 $stream = [System.IO.StreamWriter] "corrupt_jpegs.txt" get-childitem "c:\" -include *.jpg -recurse | foreach ($_) { & "C:\Program Files\ImageMagick-6.7.1-Q16\identify.exe" $_.fullname > $null if($LastExitCode -ne 0){ $stream.writeline($_.fullname) } } $stream.close() 

Ho modificato il codice dalla risposta di galacticninja per fare esattamente quello che voleva OP. Viene eseguito allo stesso modo, tuttavia sposterà i file in una cartella di cattura nella directory C:\ root, invece di elencare le immagini nel prompt dei comandi.

Puoi trovare il mio codice modificato su Pastebin o sotto:

 #This program will scan a directory and all it's subdirectories for corrupted jpg, png, gif, and bmp images and collect them in a Catch folder #To run this program you will need to install Python 2.7 and PILLOW #Once installed save this file in a notepad document with the .py extension #Than run cmd.exe and type the following: C:\Python27\python.exe "C:\Directory this is saved in\this.py" "C:\Directory to be scanned" #You must make a folder called Catch in your root C:\ directory for the corrupted images to be collected in #!/usr/bin/env python2 # -*- coding: utf-8 -*- # vi:ts=4 sw=4 et # Okay, this code is a bit ugly, with a few "anti-patterns" and "code smell". # But it works and I don't want to refactor it *right now*. # TODO: # * Refactor it a little # * Add support for custom filename filter (instead of the hardcoded one) #Big thanks to denilsonsa for writing most of this code at https://bitbucket.org/denilsonsa/small_scripts/src/542edd54d290d476603e939027ca654b25487d85/jpeg_corrupt.py?at=default import getopt import fnmatch import re import os import os.path import sys import PIL.Image available_parameters = [ ("h", "help", "Print help"), ("v", "verbose", "Also print clean files"), ] class ProgramOptions(object): """Holds the program options, after they are parsed by parse_options()""" def __init__(self): self.globs = ['*.jpg', '*.jpe', '*.jpeg', '*.gif', '*.png', '*.bmp'] self.glob_re = re.compile('|'.join( fnmatch.translate(g) for g in self.globs ), re.IGNORECASE) self.verbose = False self.args = [] def print_help(): global opt scriptname = os.path.basename(sys.argv[0]) print "Usage: {0} [options] files_or_directories".format(scriptname) print "Recursively checks for corrupt image files" print "" print "Options:" long_length = 2 + max(len(long) for x,long,y in available_parameters) for short, long, desc in available_parameters: if short and long: comma = ", " else: comma = " " if short == "": short = " " else: short = "-" + short[0] if long: long = "--" + long print " {0}{1}{2:{3}} {4}".format(short,comma,long,long_length, desc) print "" print "Currently (it is hardcoded), it only checks for these files:" print " " + " ".join(opt.globs) def parse_options(argv, opt): """argv should be sys.argv[1:] opt should be an instance of ProgramOptions()""" try: opts, args = getopt.getopt( argv, "".join(short for short,x,y in available_parameters), [long for x,long,y in available_parameters] ) except getopt.GetoptError as e: print str(e) print "Use --help for usage instructions." sys.exit(2) for o,v in opts: if o in ("-h", "--help"): print_help() sys.exit(0) elif o in ("-v", "--verbose"): opt.verbose = True else: print "Invalid parameter: {0}".format(o) print "Use --help for usage instructions." sys.exit(2) opt.args = args if len(args) == 0: print "Missing filename" print "Use --help for usage instructions." sys.exit(2) def is_corrupt(imagefile): """Returns None if the file is okay, returns an error string if the file is corrupt.""" #http://stackoverflow.com/questions/1401527/how-do-i-programmatically-check-whether-an-image-png-jpeg-or-gif-is-corrupted/1401565#1401565 try: im = PIL.Image.open(imagefile) im.verify() except Exception as e: return str(e) return None def check_files(files): """Receives a list of files and check each one.""" global opt i = 0 for f in files: # Filtering JPEG, GIF, PNG, and BMP images i=i+1 if opt.glob_re.match(f): status = is_corrupt(f) if opt.verbose and status is None: status = "Ok" if status: file = "{0}".format(f, status) print file shorthand = file.rsplit('\\', 1) extention =shorthand[1] fullFileName = "C:\Catch" + "\\" + extention os.rename(file, fullFileName) def main(): global opt opt = ProgramOptions() parse_options(sys.argv[1:], opt) for pathname in opt.args: if os.path.isfile(pathname): check_files([pathname]) elif os.path.isdir(pathname): for dirpath, dirnames, filenames in os.walk(pathname): check_files(os.path.join(dirpath, f) for f in filenames) else: print "ERROR: '{0}' is neither a file or a dir.".format(pathname) if __name__ == "__main__": main() 

Utilizza l' identify da un pacchetto ImageMagick.

Esempio di esempio:

 identify -verbose -regard-warnings my_file.jpg >/dev/null && echo File is OK. || echo File is corrupted. 

E il seguente command identifica tutti i file JPEG danneggiati nella cartella corrente:

 find . -name \*.jpg -exec identify -verbose -regard-warnings {} >/dev/null "+" 

Se hai installato Perl allora puoi utilizzare questo script. È necessario salvare l'elenco dei file da controllare in f.txt prima di eseguire lo script. Puoi fare questo elenco utilizzando Irfanview. (caricare tutti i pollici dalle sottocartelle e salvare in txt). L'elenco di buoni file viene salvato in okf.txt e i file corrotti sono elencati in brokenf.txt.

=====================

 use Image::Magick; open(BROKEN, ">>brokenf.txt"); # Open for appending open(OK, ">>okf.txt"); # Open for appending $list='f.txt'; open(TOSORT, $list) or die("Could not open file."); foreach $pic (<TOSORT>) { chomp($pic); $p = new Image::Magick; $s = 0; $error = $p->Read($pic); if ($error) {print BROKEN $pic . "\n"; } else { print OK $pic . "\n"; } } close(TOSORT); close(BROKEN); close(OK); } close(TOSORT); close(BROKEN); close(OK); 

Installa imagemagick, se sei in Mac, puoi usare Homebrew.

 brew update && brew install imagemagick 

Quindi puoi utilizzare questo piccolo script Python.

 import os from subprocess import Popen, PIPE def checkImage(fn): proc = Popen(['identify', '-verbose', fn], stdout=PIPE, stderr=PIPE) out, err = proc.communicate() exitcode = proc.returncode return exitcode, out, err for directory, subdirectories, files in os.walk('/Your/Path/To/Files/'): for file in files: filePath = os.path.join(directory, file) code, output, error = checkImage(filePath) if code != 0 or error != '': print(str(code)+' '+error) #os.remove(filePath) 

Sostituisci /Your/Path/To/Files/ e deseleziona l'ultima row se si desidera eliminare le immagini danneggiate.