Automatizzare la scansione di file grafici per corruzione


28

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


Spiegazione:

Alcuni giorni fa, un comando ha funzionato in modo errato e ha finito per eliminare migliaia di file grafici da un volume FAT32 che era praticamente senza spazio. Ho usato diversi programmi di recupero file / foto, ma naturalmente sono limitati in quanto possono recuperare (anche se fortunatamente il volume ha cluster da 8 KB, il che aiuta in qualche modo).

Ad ogni modo, alcuni dei file più grandi, che erano frammentati, ora sono corrotti. Alcuni di essi non sono nemmeno file reali (il software di recupero ha semplicemente scaricato i cluster a cui puntavano le voci della directory ora sovrascritte), mentre altri sono rotti a causa della frammentazione.

Inoltre, poiché alcuni formati di immagine incorporano una versione più piccola dell'immagine come anteprima, la scansione delle miniature per corruzione non è affidabile perché potrebbe essere intatta mentre il file effettivo (ovvero l'immagine visualizzata a dimensioni reali) potrebbe essere corrotto.


Qui ci sono un paio di esempi:

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

immagine danneggiata

(Un terzo non avrebbe nemmeno caricato perché non ha nemmeno l'intestazione corretta!)


Intendi dire corruzione visiva, suppongo? ADORO questo ... finalmente potrei smettere di guardare le anteprime dei miei fumetti per jpg rotti.
Shinrai,

Visivo o strutturale. Ho trovato un'app che presumibilmente ha fatto questo, ma ha perso molti file che non avevano nemmeno l'intestazione !
Synetech,

Oh, quella roba non mi è nemmeno venuta in mente. Sì, per favore ... deve esistere QUALCUNO, vero?
Shinrai,

1
Puoi caricare uno o più esempi di un file così rotto e collegarti ad essi nella tua domanda?
slhck,

@Shinrai, esaminare le anteprime non è affidabile perché molti formati di immagine includono una versione di anteprima separata incorporata nell'immagine e che potrebbe essere intatta. Ecco perché a volte un'immagine la cui miniatura sembra soddisfacente, quando viene aperta, è corrotta.
Synetech,

Risposte:


12

Dal momento che mi sono imbattuto in questo mentre cercavo di rispondere alla stessa domanda, aggiungerò un'altra grande soluzione che ho trovato:

Bad Peggy

Schermata dell'applicazione

Utilizzo
Dal menu selezionare File > Scane quindi utilizzare la finestra di dialogo del file per selezionare la cartella in cui si trovano le immagini. Il programma inizierà quindi la scansione della cartella e di tutte le sottocartelle alla ricerca di immagini (.jpg, .png, .bmp, .gif). Se vuoi scansionare molte immagini, ci vorrà del tempo, perché il programma ha bisogno di caricare e analizzare completamente il file di immagine, quindi potresti volerlo eseguire durante la notte.

Durante la scansione mostrerà una percentuale di avanzamento nella barra di stato. Qualsiasi immagine trovata non perfetta verrà visualizzata direttamente nell'elenco. Se fai clic su un'immagine nell'elenco, verrà mostrata un'anteprima dell'aspetto dell'immagine. Molto spesso un'immagine avrà solo un piccolo problema con il formato del file e l'immagine continuerà ad avere un bell'aspetto. Altre volte l'immagine non verrà visualizzata per niente e l'anteprima sarà solo nera. A volte l'immagine viene danneggiata e vedrai qualcosa di simile nello screenshot sopra.

Un trucco molto utile è fare clic nell'intestazione della colonna Reasone le immagini verranno ordinate in base a quanto gravemente sono danneggiate (ad esempio, tutti i formati di file danneggiati che vengono comunque visualizzati correttamente si sposteranno in basso, permettendoti di concentrarti sui casi più gravi) .

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

Collegamenti I
download per Windows, Linux e OS X sono disponibili qui:
https://www.coderslagoon.com

Il codice sorgente è qui:
https://github.com/llaith/BadPeggy


Grazie per la correzione. Ho aggiunto alcune informazioni sull'utilizzo (anche se il programma è molto esplicativo).
Paul,

Il collegamento al codice sorgente è interrotto.
Nicolas Raoul,

9

Prova il jpeginfo ' -c' opzione per i file JPEG.

Ho visto la corruzione che mostri accadere anche con schede di memoria difettose.
Quello che vuoi dovrebbe essere possibile e disponibile, controlla Corruzione dei file grafici ;
una sezione dall'enciclopedia online dei formati di file grafici .

Vedi anche Controlli di integrità dei file in Un'introduzione di base alle funzionalità PNG .

Potresti essere interessato a questa domanda StackOverflow,
come posso verificare a livello di codice se un'immagine (PNG, JPEG o GIF) è danneggiata ?


Aggiornamento : sorgente tarball per la versione 1.6.1 di Timo Kokkonen .
Dovresti essere in grado di creare un file binario per la tua macchina.


Sfortunatamente, non riesco a trovare alcuna porta di Windows.
Synetech,

jpeginfo è open-source; dovresti essere in grado di ottenere il tarball e compilarlo sul tuo sistema (forse con Cygwin che ha libjpeg).
nik,

È discutibile in ogni caso, perché ho bisogno di scansionare almeno GIF e PNG.
Synetech,

1
La directory @nik - aux, che fa parte del tarball di jpeginfo, non può essere creata con quel nome su Windows, rendendolo molto difficile da estrarre anche sotto Windows, meno solo costruirlo. Sei riuscito a costruirlo sotto Windows?
Torre del

jpeginfo -c *.JPG | ag (WARNING|ERROR)ha funzionato per me
Selrond il

3

Il programma di identificazione di ImageMagick ti farà sapere se un'immagine è corrotta. Un test del ciclo 'for i in find' per un codice di ritorno none-0 da identificherebbe consentirebbe di eseguire lo script del test abbastanza facilmente per scaricare un elenco di file danneggiati o corrotti. Funziona anche su Windows con PowerShell.

inserisci qui la descrizione dell'immagine

Il seguente codice con modifiche per il tuo percorso 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()

Non uso ImageMagick da un po 'di tempo (ha avuto dei bug l'ultima volta che ho provato), ma lo esaminerò. Grazie per il suggerimento
Synetech,

1
Lo strumento visualizzatore è ancora difettoso, ma l'identificazione ha funzionato perfettamente per me con un problema simile. Ho usato uno script PowerShell come questo per ottenere un elenco di file di immagine corrotti o di lunghezza 0.
OldWolf,

@Synetech inc. Siamo spiacenti, non riesco ad aggiornare il post originale con codice formattato poiché è stata pubblicata un'immagine e non riesco nemmeno a farlo formattarlo bene. Script Powershell di esempio: (modifica percorsi, tipi di file ecc.) $ Stream = [System.IO.StreamWriter] "corrotti_jpegs.txt" get-childitem "c: \" -include * .jpg -recurse | foreach ($ _) {& "C: \ Programmi \ ImageMagick-6.7.1-Q16 \ ident.exe" $ _. nome completo> $ null if ($ LastExitCode -ne 0) {$ stream.writeline ($ _. nome completo)}} $ stream.close ()
OldWolf,

1
Dalla riga di comando, identifypuò mostrare dati JPEG corrotti con -verbose, normalmente non mostra.
Kenorb,

3

Questo può essere fatto usando il comando della libreria Python Imaging.verify() . [1]

Per eseguirlo in Windows, installa Python (ho installato l'ultima versione corrente di Python 2), quindi installa Pillow (un fork 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.

Si noti che ho modificato la seguente riga di codice in jpeg_corrupt.py :
self.globs = ['*.jpg', '*.jpe', '*.jpeg']
in
self.globs = ['*.jpg', '*.jpe', '*.jpeg', '*.png', '*.gif']
questo modo verranno scansionati anche i file .PNG e .GIF.

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

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

Dovrebbe scansionare tutte le immagini JPG, GIF e PNG nella directory specificata e in tutte le sue sottodirectory. Mostrerà un output se rileva un file di immagine corrotto.

Ho eseguito questa immagine Campione del PO su ed ha dato questo messaggio di errore: ...\YcB9n.png: string index out of range.

Il codice può anche essere inserito in un file di script .BAT, quindi è possibile eseguirlo facilmente in una directory specificata senza la necessità di utilizzare il prompt dei comandi:

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



fonti:

[1]: Risposta in Stack Overflow - "Come posso verificare a livello di codice se un'immagine (PNG, JPEG o GIF) è danneggiata?" di ChristopheD
[2]: Commento di Denilson Sá nella risposta SO collegata in [1]


4
Ho eliminato alcune parti di un file jpg in modo casuale - lo script non mostrava nulla. Rileva gli errori solo nei casi peggiori, ad esempio quando manca completamente l'intestazione ...
Pavel Vlasov,

Lo stesso vale per jpeginfo.
wp78de,

2

Ho modificato il codice dalla risposta di galacticninja per fare esattamente ciò che OP voleva. Viene eseguito allo stesso modo, tuttavia sposta i file in una cartella di cattura nella C:\directory principale anziché elencare le immagini sul 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()

2

Installa imagemagick, se sei su Mac puoi usare Homebrew.

brew update && brew install imagemagick

Quindi puoi usare 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 decommenta l'ultima riga se desideri eliminare le immagini danneggiate.


1

Utilizzare identifydal 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 comando identificherebbe tutti i file JPEG corrotti nella cartella corrente:

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

0

Se hai installato Perl, puoi usare questo script. È necessario salvare l'elenco dei file per verificare in f.txt prima di eseguire lo script. Puoi creare questo elenco usando Irfanview. (carica tutti i pollici dalle sottocartelle e salva in txt). L'elenco dei file validi viene salvato in okf.txt e i file danneggiati 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);

0

Il mio script open source Pyhton controlla l'integrità dei media controlla l'integrità delle immagini e dei file video / audio. Utilizza i moduli Pillow, i wrapper ImageMagick e FFmpeg per provare a decodificare i file.

Pillow image.verify non vede tutti i difetti (es. Ignora il troncamento) per questo motivo ho anche eseguito image / decode + manipolazione.


0

Questo post sul blog elenca cinque strumenti che possono (rilevare e) riparare file di immagine danneggiati. L'unico gratuito tra questi è File Repair 2.1.

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.