Automatizando a varredura de arquivos gráficos por corrupção

26

Alguém sabe de uma maneira de verificar arquivos gráficos (particularmente JPEG, GIF e PNG) por corrupção (de preferência de forma automatizada)?

Explicação:

Alguns dias atrás, um comando funcionou incorretamente e acabou excluindo milhares de arquivos gráficos de um volume FAT32 que estava praticamente sem espaço. Usei vários programas diferentes de recuperação de arquivos / fotos, mas, naturalmente, eles são limitados em quanto podem recuperar (embora, felizmente, o volume tenha clusters de 8 KB, o que ajuda um pouco).

De qualquer forma, alguns dos arquivos maiores, que estavam fragmentados, agora estão corrompidos. Alguns deles nem sequer são arquivos reais (o software de recuperação simplesmente descartou os clusters que foram apontados pelas entradas de diretório sobrescritas), enquanto outros são quebrados por causa da fragmentação.

Além disso, como alguns formatos de imagem incorporam uma versão menor da imagem como miniatura, a verificação das miniaturas por corrupção não é confiável porque pode estar intacta enquanto o arquivo real (ou seja, a imagem quando visualizada em tamanho real) poderia ser corrupto.

Aqui estão alguns exemplos:

Esteéosegundo.Estátãodanificadoquenãoexibenada.

(Um terceiro nem sequer carregou porque nem sequer tem o cabeçalho correto!)

    
por Synetech 27.04.2011 / 21:15

10 respostas

9

Como me deparei com isso enquanto tentava responder à mesma pergunta, adicionarei outra ótima solução que encontrei:

Bad Peggy

Uso
Nomenu,selecioneFile>Scaneuseacaixadediálogodearquivoparaprocurarapastanaqualasimagensestãolocalizadas.Oprogramaentãocomeçaráaescanearapastaetodasassubpastasparaimagens(.jpg,.png,.bmp,.gif).Sevocêquiserdigitalizarmuitasfotos,issolevaráalgumtempo,porqueoprogramaprecisacarregareanalisarcompletamenteoarquivodeimagem,portanto,convémdeixá-lorodarduranteanoite.

Enquantoestiverdigitalizando,mostraráumaporcentagemdeprogressonabarradestatus.Qualquerimagemencontradaquenãosejaperfeitaaparecerádiretamentenalista.Sevocêclicaremqualquerimagemnalista,elamostraráumapréviadaaparênciadaimagem.Muitasvezesumaimagemsóteráumproblemamenorcomoformatodoarquivoeaimagemaindaficarábem.Outrasvezesaimagemnãoserárenderizadaeavisualizaçãoseráapenaspreta.Àsvezesaimagemserádanificadaevocêveráalgocomonaimagemacima.

UmtruquemuitoútiléclicarnocabeçalhodacolunaReasoneasimagensserãoclassificadasdeacordocomograudedanoqueelascausam(porexemplo,todososformatosdearquivoincorretosqueaindasãoprocessadoscorretamenteserãomovidosparabaixo,permitindoquevocêseconcentrenoscasosmaisgraves).

Alémdisso,seaprimeiraverificaçãotiverterminadoevocêiniciaroutraverificação,osresultadosserãosimplesmenteadicionadosàlista.Portanto,sevocêtivermuitaspastasdiferentescomimagens,poderásimplesmentedigitalizá-lassequencialmente,semquealistasejalimpaquandovocêiniciarumanovadigitalização.Sevocêquiserlimparalista,useomenudecontextoecliqueemClearlist.

Links
DownloadsparaWindows,LinuxeOSXpodemserencontradosaqui: link

O código-fonte está aqui: link

    
por 01.06.2016 / 17:03
8

Experimente a opção jpeginfo ' -c ' para seus arquivos JPEG.

Eu vi a corrupção que você mostra acontecer com cartões de memória ruins também.
O que você quer que seja possível e disponível, verifique Corrupção de arquivos gráficos ; uma seção da Enciclopédia de formatos de arquivos gráficos on-line

.

Veja também Verificações de integridade de arquivos em Introdução básica ao PNG Recursos .

Você pode estar interessado nesta questão do Stackoverflow,
Como faço para verificar programaticamente se uma imagem (PNG, JPEG ou GIF ) está corrompido ?

Atualizar : tarball de origem para version 1.6.1 por Timo Kokkonen .
Você deve ser capaz de construir um binário para sua máquina.

    
por 28.04.2011 / 03:26
3

Isso pode ser feito usando o comando .verify() da biblioteca de imagens do Python . [1]

Para executar isso no Windows, instale o Python (instalei a última versão atual do Python 2) e instale < href="https://pypi.python.org/pypi/Pillow"> Almofada (um fork da Python Imaging Library (PIL)). Em seguida, copie o código de jpeg_corrupt.py [2] e salve seu conteúdo em um arquivo .PY, por exemplo jpeg_corrupt.py.

Note que eu mudei a seguinte linha de código em jpeg_corrupt.py :
self.globs = ['*.jpg', '*.jpe', '*.jpeg']
para self.globs = ['*.jpg', '*.jpe', '*.jpeg', '*.png', '*.gif']
Assim, os arquivos .PNG e .GIF também serão verificados.

Ele pode ser executado através do prompt de comando do Windows (cmd.exe) assim: C:\Python27\python.exe "C:\Directory containing the .PY file\jpeg_corrupt.py" "C:\Directory of folder to be scanned"

A primeira parte do comando, ' C: \ Python27 \ python.exe ', pode ser diferente dependendo da versão do Python que você instalou e do diretório em que você o instalou. No meu exemplo, é o diretório de instalação padrão do Python 2.7.

Ele deve verificar todas as imagens JPG, GIF e PNG no diretório especificado e em todos os seus subdiretórios. Ele mostrará uma saída se detectar um arquivo de imagem corrompido.

Eu corri isso na imagem de exemplo do OP e ele deu esta mensagem de erro: ...\YcB9n.png: string index out of range .

O código também pode ser inserido em um arquivo de script .BAT, para que você possa executá-lo facilmente em um diretório especificado sem precisar usar o prompt de comando:

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


Fontes:

[1]: Resposta em estouro de pilha -" Como faço para verificar programaticamente se uma imagem (PNG, JPEG ou GIF) está corrompida? " por ChristopheD
[2]: Comentário de Denilson Sá na resposta do SO link on [1]

    
por 22.07.2014 / 13:29
3

O programa de identificação do ImageMagick permite que você saiba se uma imagem está corrompida. Um teste de loop 'for i in find' para um código de retorno nenhum-0 de identificador permite que você faça o script do teste com bastante facilidade para despejar uma lista de arquivos danificados ou corrompidos. Ele também funciona no Windows com o PowerShell.

Oseguintecódigocomalteraçõesparaoseucaminhofuncionabemnopowershell

$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()
    
por 16.08.2011 / 20:48
2

Eu modifiquei o código da resposta do galacticninja para fazer exatamente o que o OP queria. Ele é executado da mesma maneira, no entanto, ele moverá os arquivos para uma pasta de captura no diretório raiz C:\ em vez de apenas listar as imagens no prompt de comando.

Você pode encontrar meu código modificado no Pastebin ou abaixo:

#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()
    
por 19.08.2015 / 22:04
2

Instale imagemagick, se você estiver no Mac, você pode usar o Homebrew.

brew update && brew install imagemagick

Então você pode usar este pequeno 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)

Substitua /Your/Path/To/Files/ e remova o comentário da última linha se quiser excluir as imagens corrompidas.

    
por 06.02.2017 / 17:20
1

Use identify do pacote ImageMagick.

Exemplo de exemplo:

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

O seguinte comando identifica todos os arquivos JPEG corrompidos na pasta atual:

find . -name \*.jpg -exec identify -verbose -regard-warnings {} >/dev/null "+"
    
por 26.02.2015 / 19:34
0

Meu script Pyhton de código aberto integridade da verificação de mídia verifica a integridade de fotos e arquivos de vídeo / áudio. Ele usa módulos Pillow, ImageMagick e FFmpeg para tentar decodificar os arquivos.

Pillow image.verify não vê todos os defeitos (por exemplo, ignora o truncamento) por esse motivo também executei image / decode + manipulação.

    
por 01.12.2018 / 19:09
0

Esta postagem no blog lista cinco ferramentas que podem (detectar e) reparar arquivos de imagem corrompidos. O único gratuito entre eles é o File Repair 2.1.

    
por 06.01.2019 / 12:48
0

Se você tiver o Perl instalado, poderá usar esse script. Você precisa salvar a lista de arquivos para verificar em f.txt antes de executar o script. Você pode fazer essa lista usando o Irfanview. (carregue todos os polegares das subpastas e salve em txt). A lista de arquivos bons é salva em okf.txt e os arquivos corrompidos são listados em 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);
    
por 24.04.2015 / 12:47