Automatisation de l'analyse des fichiers graphiques pour la corruption


28

Quelqu'un connaît-il un moyen de vérifier la corruption des fichiers graphiques (en particulier JPEG, GIF et PNG) (de préférence de manière automatisée)?


Explication:

Il y a quelques jours, une commande a mal fonctionné et a fini par supprimer des milliers de fichiers graphiques d'un volume FAT32 qui était pratiquement à court d'espace. J'ai utilisé plusieurs programmes différents de récupération de fichiers / photos, mais naturellement, ils sont limités dans la quantité qu'ils peuvent récupérer (bien que heureusement, le volume ait des grappes de 8 Ko, ce qui aide quelque peu).

Quoi qu'il en soit, certains des fichiers plus volumineux, qui étaient fragmentés, sont maintenant corrompus. Certains d'entre eux ne sont même pas du tout de vrais fichiers (le logiciel de récupération a simplement vidé les clusters qui étaient indiqués par des entrées de répertoire désormais écrasées), tandis que d'autres sont cassés en raison de la fragmentation.

De plus, comme certains formats d'image incorporent une version plus petite de l'image sous forme de miniature, la numérisation des miniatures n'est pas fiable car elle peut être intacte tandis que le fichier réel (c'est-à-dire l'image lorsqu'elle est visualisée en taille réelle) peut être corrompu.


Voici quelques exemples:

Voici le deuxième. Il est tellement endommagé qu'il n'affiche rien.

image endommagée

(Un troisième ne serait même pas téléchargé car il n'a même pas l'en-tête correct!)


Vous parlez de corruption visuelle, je suppose? J'adorerais ça ... enfin je pourrais arrêter de regarder les miniatures de mes bandes dessinées pour les jpgs cassés.
Shinrai

Visuel ou structurel. J'ai trouvé une application qui aurait fait cela, mais il manquait beaucoup de fichiers qui n'avaient même pas d'en-tête !
Synetech

Oh, ce truc ne m'est même pas venu à l'esprit. Oui, s'il vous plaît ... cela doit exister PARTOUT non?
Shinrai

1
Pouvez-vous télécharger un ou plusieurs exemples d'un tel fichier cassé et les lier à votre question?
slhck

@Shinrai, l'examen des vignettes n'est pas fiable car de nombreux formats d'image incluent une version de vignette distincte intégrée à l'image, et celle-ci peut être intacte. C'est pourquoi, parfois, une image dont la vignette semble correcte est corrompue lorsqu'elle est ouverte.
Synetech

Réponses:


12

Depuis que je suis tombé sur cela en essayant de répondre à la même question, j'ajouterai une autre excellente solution que j'ai trouvée:

Bad Peggy

Capture d'écran de l'application

Utilisation
Dans le menu, sélectionnez File > Scan, puis utilisez la boîte de dialogue de fichier pour accéder au dossier dans lequel se trouvent les images. Le programme commencera alors à analyser le dossier et tous les sous-dossiers pour les images (.jpg, .png, .bmp, .gif). Si vous souhaitez numériser beaucoup d'images, cela prendra un certain temps, car le programme a besoin de charger et d'analyser complètement le fichier image, vous pouvez donc le laisser s'exécuter pendant la nuit.

Pendant la numérisation, un pourcentage de progression s'affiche dans la barre d'état. Toutes les images trouvées qui ne sont pas parfaites s'afficheront directement dans la liste. Si vous cliquez sur une image de la liste, elle affichera un aperçu de son apparence. Très souvent, une image n'aura qu'un problème mineur avec le format de fichier et l'image sera toujours très bien. D'autres fois, l'image ne sera pas rendue du tout et l'aperçu sera juste noir. Parfois, l'image sera endommagée et vous verrez quelque chose comme dans la capture d'écran ci-dessus.

Une astuce très pratique consiste à cliquer dans l'en-tête de la colonne Reasonet les images seront triées en fonction de leur gravité (par exemple, tous les mauvais formats de fichier qui s'affichent toujours correctement se déplaceront vers le bas pour vous permettre de vous concentrer sur les cas les plus graves) .

De plus, si la première analyse est terminée et que vous lancez une autre analyse, les résultats seront simplement ajoutés à la liste. Donc, si vous avez de nombreux dossiers différents avec des images, vous pouvez simplement les numériser séquentiellement sans effacer la liste lorsque vous lancez une nouvelle numérisation. Si vous souhaitez effacer la liste, utilisez le menu contextuel et cliquez sur Clear list.

Liens
téléchargement pour Windows, Linux et OS X peuvent être trouvés ici:
https://www.coderslagoon.com

Le code source est ici:
https://github.com/llaith/BadPeggy


Merci pour le correctif. J'ai ajouté quelques informations sur l'utilisation (même si le programme est très explicite).
Paul

Le lien du code source est rompu.
Nicolas Raoul

9

Essayez le jpeginfo '-c option ' pour vos fichiers JPEG.

J'ai également vu la corruption que vous montrez avec de mauvaises cartes mémoire.
Ce que vous voulez devrait être possible et disponible, vérifiez la corruption des fichiers graphiques ;
une section de l' Encyclopédie en ligne des formats de fichiers graphiques .

Voir également Vérifications de l'intégrité des fichiers dans une introduction de base aux fonctionnalités PNG .

Vous pouvez être intéressé par cette question Stackoverflow,
comment puis-je vérifier par programme si une image (PNG, JPEG ou GIF) est corrompue ?


Mise à jour : tarball source pour la version 1.6.1 par Timo Kokkonen .
Vous devriez pouvoir créer un binaire pour votre machine.


Malheureusement, je ne trouve aucun port Windows.
Synetech

jpeginfo est open-source; vous devriez pouvoir récupérer l'archive tar et la compiler sur votre système (peut-être avec Cygwin qui a libjpeg).
nik

C'est théorique dans les deux cas, car je dois également numériser au moins des GIF et des PNG.
Synetech

1
@nik - le répertoire aux, qui fait partie de l'archive tar de jpeginfo, ne peut pas être créé sous ce nom sous Windows, ce qui rend très difficile même l'extraction sous Windows, moins seul à le construire. Avez-vous réussi à le construire sous Windows?
Tour du

jpeginfo -c *.JPG | ag (WARNING|ERROR)a travaillé pour moi
Selrond

3

Le programme d' identification d'ImageMagick vous fera savoir si une image est corrompue. Un test de boucle `` for i in find '' pour un code de retour nul à partir de identifier vous permettrait de scripter le test assez facilement pour vider une liste de fichiers endommagés ou corrompus. Il fonctionne également sur Windows avec PowerShell.

entrez la description de l'image ici

Le code suivant avec des modifications pour votre chemin fonctionne bien dans 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()

Je n'ai pas utilisé ImageMagick depuis un moment (il y avait des bugs la dernière fois que j'ai essayé), mais je vais y jeter un œil. Merci pour la suggestion.
Synetech

1
L'outil de visualisation est toujours bogué, mais identifier a très bien fonctionné pour moi avec un problème similaire. J'ai utilisé un script PowerShell comme celui-ci pour obtenir une liste de fichiers d'image corrompus et de longueur 0.
OldWolf

@Synetech inc. Désolé, je ne peux pas mettre à jour le message d'origine avec du code formaté car une image y a été publiée et je n'arrive pas non plus à le faire correctement. Exemple de script Powershell: (ajustez vos chemins, types de fichiers, etc.) $ stream = [System.IO.StreamWriter] "corrupt_jpegs.txt" get-childitem "c: \" -include * .jpg -recurse | foreach ($ _) {& "C: \ Program Files \ ImageMagick-6.7.1-Q16 \ identifier.exe" $ _. nom complet> $ null si ($ LastExitCode -ne 0) {$ stream.writeline ($ _. nom complet)}} $ stream.close ()
OldWolf

1
À partir de la ligne de commande, identifypeut afficher des données JPEG corrompues avec -verbose, normalement, il ne s'affiche pas.
kenorb

3

Cela peut être fait en utilisant la commande de la bibliothèque d'imagerie Python.verify() . [1]

Pour exécuter cela dans Windows, installez Python (j'ai installé la dernière version actuelle de Python 2), puis installez Pillow (un fork de Python Imaging Library (PIL)). Ensuite, copiez le code de jpeg_corrupt.py [2] et enregistrez son contenu dans un fichier .PY, par exemple jpeg_corrupt.py.

Notez que j'ai changé la ligne de code suivante dans jpeg_corrupt.py :
self.globs = ['*.jpg', '*.jpe', '*.jpeg']
en
self.globs = ['*.jpg', '*.jpe', '*.jpeg', '*.png', '*.gif']
que les fichiers .PNG et .GIF soient également analysés.

Il peut ensuite être exécuté via l'invite de commande Windows (cmd.exe) comme ceci: C:\Python27\python.exe "C:\Directory containing the .PY file\jpeg_corrupt.py" "C:\Directory of folder to be scanned"

La première partie de la commande, « C: \ Python27 \ python.exe », peut être différente selon la version de Python que vous avez installée et le répertoire dans lequel vous l'avez installé. Dans mon exemple, c'est le répertoire d'installation par défaut de Python 2.7.

Il doit numériser toutes les images JPG, GIF et PNG dans le répertoire spécifié et tous ses sous-répertoires. Il affichera une sortie s'il détecte un fichier image corrompu.

J'ai couru ceci sur l'image de l' échantillon de l' OP et lui a donné ce message d'erreur: ...\YcB9n.png: string index out of range.

Le code peut également être entré dans un fichier de script .BAT, vous pouvez donc l'exécuter facilement dans un répertoire spécifié sans avoir besoin d'utiliser l'invite de commande:

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



Sources:

[1]: Réponse dans Stack Overflow - "Comment puis-je vérifier par programme si une image (PNG, JPEG ou GIF) est corrompue?" par ChristopheD
[2]: Commentaire de Denilson Sá dans la réponse SO liée dans [1]


4
J'ai supprimé certaines parties d'un fichier jpg au hasard - le script ne montrait rien. Il ne détecte les erreurs que dans les pires cas - lorsque l'en-tête est complètement manqué par exemple ...
Pavel Vlasov

Exactement, il en va de même pour jpeginfo.
wp78de

2

J'ai modifié le code de la réponse de galacticninja pour faire exactement ce que voulait OP. Il est exécuté de la même manière, mais il déplacera les fichiers vers un dossier catch dans le C:\répertoire racine au lieu de simplement lister les images sur l'invite de commande.

Vous pouvez trouver mon code modifié sur Pastebin ou ci-dessous:

#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

Installez imagemagick, si vous êtes sur Mac, vous pouvez utiliser Homebrew.

brew update && brew install imagemagick

Ensuite, vous pouvez utiliser ce petit 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)

Remplacez /Your/Path/To/Files/et décommentez la dernière ligne si vous souhaitez supprimer les images corrompues.


1

Utiliser à identifypartir du package ImageMagick.

Exemple d'échantillon:

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

Et la commande suivante identifierait tous les fichiers JPEG corrompus dans le dossier actuel:

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

0

Si Perl est installé, vous pouvez utiliser ce script. Vous devez enregistrer la liste des fichiers à archiver dans f.txt avant d'exécuter le script. Vous pouvez faire cette liste en utilisant Irfanview. (chargez tous les pouces des sous-dossiers et enregistrez-les en txt). La liste des bons fichiers est enregistrée dans okf.txt et les fichiers corrompus sont répertoriés dans 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

Mon script open source Pyhton vérifier l'intégrité des médias vérifie l'intégrité des images et des fichiers vidéo / audio. Il utilise des modules Pillow, des wrappers ImageMagick et FFmpeg pour essayer de décoder les fichiers.

Oreiller image.verify ne voit pas tous les défauts (par exemple, ignore la troncature) pour cette raison, j'ai également effectué l'image / décodage + manipulation.


0

Ce billet de blog répertorie cinq outils qui peuvent (détecter et) réparer les fichiers d'image corrompus. Le seul gratuit parmi eux est File Repair 2.1.

En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.