Automatizar el escaneo de archivos gráficos en busca de corrupción


28

¿Alguien sabe de una manera de verificar los archivos gráficos (particularmente JPEG, GIF y PNG) en busca de corrupción (preferiblemente de forma automatizada)?


Explicación:

Hace unos días, un comando funcionó incorrectamente y terminó eliminando miles de archivos gráficos de un volumen FAT32 que prácticamente no tenía espacio. He usado varios programas diferentes de recuperación de archivos / fotos, pero naturalmente, están limitados en cuanto pueden recuperarse (aunque afortunadamente el volumen tiene clústeres de 8 KB, lo que ayuda un poco).

De todos modos, algunos de los archivos más grandes, que estaban fragmentados, ahora están corruptos. Algunos de ellos ni siquiera son archivos reales (el software de recuperación simplemente descartó los clústeres señalados por las entradas de directorio ahora sobrescritas), mientras que otros están rotos debido a la fragmentación.

Además, debido a que algunos formatos de imagen incorporan una versión más pequeña de la imagen como una miniatura, el escaneo de las miniaturas en busca de corrupción no es confiable porque puede estar intacto, mientras que el archivo real (es decir, la imagen cuando se ve a tamaño completo) podría estar dañado.


Aquí hay un par de ejemplos:

Aquí está el segundo. Está tan dañado que no muestra nada.

imagen dañada

(¡Un tercero ni siquiera subiría porque ni siquiera tiene el encabezado correcto!)


¿Te refieres a corrupción visual, supongo? Me ENCANTARÍA esto ... finalmente podría dejar de mirar las miniaturas de mis libros de historietas por jpgs rotos.
Shinrai

Visual o estructural. Encontré una aplicación que supuestamente hizo esto, ¡pero se perdió muchos archivos que ni siquiera tenían el encabezado !
Synetech

Oh, esas cosas ni siquiera se me ocurrieron. Sí, por favor ... esto tiene que existir EN ALGÚN LUGAR ¿verdad?
Shinrai

1
¿Puedes subir uno o más ejemplos de un archivo tan roto y vincularlos en tu pregunta?
slhck

@Shinrai, examinar las miniaturas no es confiable porque muchos formatos de imagen incluyen una versión en miniatura separada incrustada en la imagen, y eso puede estar intacto. Es por eso que a veces una imagen cuya miniatura se ve bien, está corrupta cuando se abre.
Synetech

Respuestas:


12

Como me topé con esto al intentar responder la misma pregunta, agregaré otra gran solución que encontré:

Bad Peggy

Captura de pantalla de la aplicación.

Uso
En el menú, seleccione File > Scany luego use el cuadro de diálogo de archivo para buscar la carpeta en la que se encuentran las imágenes. El programa comenzará a escanear la carpeta y todas las subcarpetas en busca de imágenes (.jpg, .png, .bmp, .gif). Si desea escanear muchas imágenes, esto llevará algún tiempo, ya que el programa necesita cargar y analizar completamente el archivo de imagen, por lo que es posible que desee dejar que se ejecute durante la noche.

Mientras está escaneando, mostrará un porcentaje de progreso en la barra de estado. Cualquier imagen que encuentre que no es perfecta aparecerá directamente en la lista. Si hace clic en cualquier imagen de la lista, mostrará una vista previa del aspecto de la imagen. Muy a menudo, una imagen solo tendrá un problema menor con el formato del archivo y la imagen se verá bien. Otras veces, la imagen no se mostrará en absoluto y la vista previa será solo negra. A veces, la imagen se dañará y verá algo como en la captura de pantalla anterior.

Un truco muy útil es hacer clic en el encabezado de la columna Reasony las imágenes se ordenarán de acuerdo con la gravedad de su daño (por ejemplo, todos los formatos de archivo incorrectos que aún se procesan correctamente se moverán hacia la parte inferior, lo que le permitirá centrarse en los casos más graves) .

Además, si la primera exploración ha finalizado y comienza otra exploración, los resultados simplemente se agregarán a la lista. Entonces, si tiene muchas carpetas diferentes con imágenes, simplemente puede escanearlas secuencialmente sin borrar la lista cuando comience un nuevo escaneo. Si desea borrar la lista, use el menú contextual y haga clic Clear list.

Las
descargas de enlaces para Windows, Linux y OS X se pueden encontrar aquí:
https://www.coderslagoon.com

El código fuente está aquí:
https://github.com/llaith/BadPeggy


Gracias por el arreglo. He agregado un poco de información de uso (aunque el programa se explica por sí mismo).
Paul

El enlace del código fuente está roto.
Nicolas Raoul

9

Pruebe la opción jpeginfo ' -c' para sus archivos JPEG.

También he visto que la corrupción que muestra sucede con tarjetas de memoria defectuosas.
Lo que desea debe ser posible y estar disponible, verifique Corrupción de archivos gráficos ;
una sección de la Enciclopedia en línea de formatos de archivos gráficos .

Consulte también Verificaciones de integridad de archivos en Introducción básica a las funciones PNG .

Puede que le interese esta pregunta de Stackoverflow,
¿Cómo verifico mediante programación si una imagen (PNG, JPEG o GIF) está dañada ?


Actualización : Source tarball para la versión 1.6.1 de Timo Kokkonen .
Debería poder construir un binario para su máquina.


Desafortunadamente, no puedo encontrar ningún puerto de Windows.
Synetech

jpeginfo es de código abierto; debería poder obtener el tarball y compilarlo en su sistema (tal vez con Cygwin que tiene libjpeg).
Nik

Es discutible de cualquier manera, porque también necesito escanear al menos GIF y PNG.
Synetech

1
@nik: el directorio auxiliar, que forma parte del tarball de jpeginfo no se puede crear con ese nombre en Windows, lo que hace que sea muy difícil incluso extraerlo en Windows, y mucho menos construirlo. ¿Has logrado construirlo en Windows?
Torre

jpeginfo -c *.JPG | ag (WARNING|ERROR)funcionó para mí
Selrond

3

El programa de identificación de ImageMagick le permitirá saber si una imagen está dañada. Una prueba de bucle 'for i in find' para un código de retorno de 0 a partir de la identificación le permitiría escribir la prueba con bastante facilidad para volcar una lista de archivos dañados o corruptos. También funciona en Windows con PowerShell.

ingrese la descripción de la imagen aquí

El siguiente código con cambios para su ruta funciona bien en 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()

No he usado ImageMagick en mucho tiempo (tenía errores la última vez que lo intenté), pero lo investigaré. Gracias por la sugerencia.
Synetech

1
La herramienta de visualización todavía tiene errores, pero Identify funcionó muy bien para mí con un problema similar. Utilicé un script de PowerShell como este para obtener una lista de archivos de imagen corruptos o de longitud 0.
OldWolf

@Synetech inc. Lo sentimos, no puedo actualizar la publicación original con código formateado ya que se publicó una imagen en ella y tampoco parece que pueda formatearlo bien. Script de muestra de Powershell: (ajuste sus rutas, tipos de archivo, etc.) $ stream = [System.IO.StreamWriter] "corrupto_jpegs.txt" get-childitem "c: \" -include * .jpg -recurse | foreach ($ _) {& "C: \ Archivos de programa \ ImageMagick-6.7.1-Q16 \ generate.exe" $ _. nombre completo> $ null if ($ LastExitCode -ne 0) {$ stream.writeline ($ _. nombre completo)}} $ stream.close ()
OldWolf

1
Desde la línea de comandos, identifypuede mostrar datos JPEG corruptos -verbose, normalmente no se muestran.
kenorb

3

Esto se puede hacer usando el comando de la Biblioteca de imágenes de Python.verify() . [1]

Para ejecutar esto en Windows, instale Python (instalé la última versión actual de Python 2), y luego instale Pillow (una bifurcación de Python Imaging Library (PIL)). Luego, copie el código de jpeg_corrupt.py [2] y guarde su contenido en un archivo .PY, por ejemplo, jpeg_corrupt.py.

Tenga en cuenta que cambié la siguiente línea de código en jpeg_corrupt.py :
self.globs = ['*.jpg', '*.jpe', '*.jpeg']
a
self.globs = ['*.jpg', '*.jpe', '*.jpeg', '*.png', '*.gif']
Esto para que también se escaneen los archivos .PNG y .GIF.

Luego se puede ejecutar a través del símbolo del sistema de Windows (cmd.exe) de esta manera: C:\Python27\python.exe "C:\Directory containing the .PY file\jpeg_corrupt.py" "C:\Directory of folder to be scanned"

La primera parte del comando, ' C: \ Python27 \ python.exe ', puede ser diferente dependiendo de la versión de Python que instaló y en qué directorio lo instaló. En mi ejemplo, es el directorio de instalación predeterminado de Python 2.7.

Debe escanear todas las imágenes JPG, GIF y PNG en el directorio especificado y todos sus subdirectorios. Mostrará una salida si detecta un archivo de imagen dañado.

Me encontré con esta imagen de la muestra del PO sobre y se lo di este mensaje de error: ...\YcB9n.png: string index out of range.

El código también se puede ingresar en un archivo de script .BAT, por lo que puede ejecutarlo fácilmente en un directorio específico sin necesidad de usar el símbolo del sistema:

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



Fuentes:

[1]: Respuesta en Stack Overflow: "¿Cómo verifico mediante programación si una imagen (PNG, JPEG o GIF) está dañada?" por ChristopheD
[2]: Comentario de Denilson Sá en la respuesta SO vinculada en [1]


44
Eliminé algunas partes de un archivo jpg al azar: el script no mostraba nada. Detecta errores solo en los peores casos, cuando el encabezado se pierde por completo, por ejemplo ...
Pavel Vlasov

Exactamente, lo mismo vale para jpeginfo.
wp78de

2

Modifiqué el código de la respuesta de galacticninja para hacer exactamente lo que OP quería. Se ejecuta de la misma manera, sin embargo, moverá los archivos a una carpeta de captura en el C:\directorio raíz en lugar de simplemente enumerar las imágenes en el símbolo del sistema.

Puede encontrar mi código modificado en Pastebin o debajo:

#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

Instala imagemagick, si estás en Mac puedes usar Homebrew.

brew update && brew install imagemagick

Entonces puedes usar este pequeño script de 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)

Reemplace /Your/Path/To/Files/y descomente la última línea si desea eliminar las imágenes dañadas.


1

Uso identifydel paquete ImageMagick.

Ejemplo de muestra:

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

Y el siguiente comando identificaría todos los archivos JPEG dañados en la carpeta actual:

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

0

Si tiene instalado Perl, puede usar este script. Debe guardar la lista de archivos para registrar f.txt antes de ejecutar el script. Puedes hacer esta lista usando Irfanview. (Cargue todos los pulgares de las subcarpetas y guárdelos en txt). La lista de archivos buenos se guarda en okf.txt y los archivos dañados se enumeran en 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

Mi código abierto Pyhton script check-media-integridad verifica la integridad de las imágenes y los archivos de video / audio. Utiliza módulos Pillow, ImageMagick y envoltorios FFmpeg para intentar decodificar los archivos.

Pillow image.verify no ve todos los defectos (por ejemplo, ignora el truncamiento) por esta razón también realicé la imagen / decodificación + manipulación.


Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.