Automatizando a verificação de arquivos gráficos quanto à corrupção


28

Alguém conhece uma maneira de verificar arquivos gráficos (particularmente JPEG, GIF e PNG) quanto à corrupção (de preferência de maneira 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. Eu 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 foram fragmentados, agora estão corrompidos. Alguns deles nem sequer são arquivos reais (o software de recuperação simplesmente descartou os clusters apontados pelas entradas de diretório agora sobrescritas), enquanto outros foram danificados por causa da fragmentação.

Além disso, como alguns formatos de imagem incorporam uma versão menor da imagem como miniatura, a digitalização das miniaturas não é confiável, pois pode estar intacta enquanto o arquivo real (ou seja, a imagem quando vista em tamanho real) pode estar corrompido.


Aqui estão alguns exemplos:

Aqui está o segundo. Está tão danificado que não exibe nada.

imagem danificada

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


Você quer dizer corrupção visual, presumo? Eu adoraria isso ... finalmente, eu poderia parar de olhar as miniaturas dos meus quadrinhos para jpgs quebrados.
Shinrai

Visual ou estrutural. Eu encontrei um aplicativo que supostamente fez isso, mas faltou muitos arquivos que nem sequer tinham o cabeçalho !
Synetech

Oh, essas coisas nem me ocorreram. Sim, por favor ... isso tem que existir EM ALGUM LUGAR, certo?
Shinrai

1
Você pode fazer upload de um ou mais exemplos de um arquivo quebrado e vincular a eles na sua pergunta?
slhck

@Shinrai, examinar as miniaturas não é confiável, porque muitos formatos de imagem incluem uma versão em miniatura separada incorporada à imagem e que pode estar intacta. É por isso que às vezes uma imagem cuja miniatura parece boa fica corrompida quando aberta.
Synetech

Respostas:


12

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

Bad Peggy

Captura de tela do aplicativo

Uso
No menu, selecione File > Scane use a caixa de diálogo de arquivo para procurar a pasta na qual as imagens estão localizadas. O programa começará a digitalizar a pasta e todas as subpastas em busca de imagens (.jpg, .png, .bmp, .gif). Se você quiser digitalizar muitas fotos, isso levará algum tempo, porque o programa precisa carregar e analisar completamente o arquivo de imagem; portanto, você pode deixá-lo em execução durante a noite.

Enquanto estiver digitalizando, mostrará uma porcentagem de progresso na barra de status. Quaisquer imagens que não sejam perfeitas serão exibidas diretamente na lista. Se você clicar em qualquer imagem da lista, ela exibirá uma prévia da aparência da imagem. Frequentemente, uma imagem apresenta apenas um pequeno problema com o formato do arquivo e a imagem ainda fica bem. Outras vezes, a imagem não será renderizada e a visualização será apenas preta. Às vezes, a imagem é danificada e você verá algo como na captura de tela acima.

Um truque muito útil é clicar no cabeçalho da coluna Reasone as imagens serão classificadas de acordo com o grau de danificação (por exemplo, todos os formatos de arquivo incorretos que ainda são renderizados corretamente serão movidos para o fundo, permitindo que você se concentre nos casos mais graves) .

Além disso, se a primeira verificação terminar e você iniciar outra verificação, os resultados serão simplesmente adicionados à lista. Portanto, se você tiver muitas pastas diferentes com imagens, poderá digitalizá-las seqüencialmente, sem que a lista seja limpa ao iniciar uma nova digitalização. Se você deseja que a lista seja limpa, use o menu de contexto e clique em Clear list.

Links
para Windows, Linux e OS X podem ser encontrados aqui:
https://www.coderslagoon.com

O código fonte está aqui:
https://github.com/llaith/BadPeggy


Obrigado pela correção. Adicionei algumas informações de uso (mesmo que o programa seja muito auto-explicativo).
Paul

O link do código-fonte está quebrado.
Nicolas Raoul

9

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

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

Consulte também Verificações de integridade de arquivo em Uma introdução básica aos recursos PNG .

Você pode estar interessado nesta pergunta do Stackoverflow:
Como verifico programaticamente se uma imagem (PNG, JPEG ou GIF) está corrompida ?


Atualização : Tarball de origem para a versão 1.6.1 por Timo Kokkonen .
Você deve conseguir construir um binário para sua máquina.


Infelizmente, não consigo encontrar nenhuma porta do Windows.
Synetech

O jpeginfo é de código aberto; você deve conseguir o tarball e compilá-lo no seu sistema (talvez com Cygwin que possui libjpeg).
Nik

É discutível de qualquer maneira, porque eu preciso digitalizar pelo menos GIFs e PNGs também.
Synetech 9/09/11

1
O diretório @nik - aux, que faz parte do tarball do jpeginfo, não pode ser criado com esse nome no Windows, tornando muito difícil extrair no Windows, menos construindo-o sozinho. Você conseguiu compilar no Windows?
Rook

jpeginfo -c *.JPG | ag (WARNING|ERROR)trabalhou para mim
Selrond

3

O programa de identificação do ImageMagick informará se uma imagem está corrompida. Um teste de loop 'for i in find' para um código de retorno zero-zero do identificador deixaria você fazer o script com bastante facilidade para despejar uma lista de arquivos danificados ou corrompidos. Também funciona no Windows com o PowerShell.

insira a descrição da imagem aqui

O código a seguir com alterações para o seu caminho funciona bem no 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()

Eu não uso o ImageMagick há algum tempo (ele tinha bugs na última vez que tentei), mas vou dar uma olhada. Obrigado pela sugestão.
Synetech

1
A ferramenta de visualização ainda está com erros, mas a identificação funcionou muito bem para mim com um problema semelhante. Usei um script do PowerShell como esse para obter uma lista de arquivos de imagem corrompidos e / ou com tamanho 0.
OldWolf 17/08/19

@Synetech inc. Desculpe, não é possível atualizar a postagem original com código formatado, pois uma imagem foi postada nela e também não consigo fazer isso. Exemplo de script do Powershell: (ajuste seus caminhos, tipos de arquivo etc.) $ stream = [System.IO.StreamWriter] "corrupt_jpegs.txt" get-childitem "c: \" -include * .jpg -recurse | foreach ($ _) {& "C: \ Arquivos de Programas \ ImageMagick-6.7.1-Q16 \ identity.exe" $ _. fullname> $ null if ($ LastExitCode -ne 0) {$ stream.writeline ($ _. nome completo)}} $ stream.close ()
OldWolf

1
Na linha de comando, identifypode mostrar dados JPEG corrompidos com -verbose, normalmente não é exibido.
kenorb 26/02

3

Isso pode ser feito usando o comando da Python Imaging Library.verify() . [1]

Para executar isso no Windows, instale o Python (instalei a versão atual mais recente do Python 2) e instale o Pillow (uma bifurcação 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.

Observe que eu alterei a seguinte linha de código em jpeg_corrupt.py :
self.globs = ['*.jpg', '*.jpe', '*.jpeg']
para
self.globs = ['*.jpg', '*.jpe', '*.jpeg', '*.png', '*.gif']
Isso, para que os arquivos .PNG e .GIF também sejam verificados.

Em seguida, ele pode ser executado através do prompt de comando do Windows (cmd.exe), desta forma: 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 em qual diretório 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 todos os seus subdiretórios. Ele mostrará uma saída se detectar um arquivo de imagem corrompido.

Eu corri isso em imagem de amostra do OP e 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 no estouro de pilha - "Como verifico programaticamente se uma imagem (PNG, JPEG ou GIF) está corrompida?" por ChristopheD
[2]: Comentário de Denilson Sá na resposta ao SO vinculada em [1]


4
Eu apaguei algumas partes de um arquivo jpg aleatoriamente - o script não mostrou nada. Ele detecta erros em apenas os piores casos mais - quando o cabeçalho é completamente perdidas, por exemplo ...
Pavel Vlasov

Exatamente, o mesmo vale para jpeginfo.
Wp78de

2

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

Você pode encontrar meu código modificado em 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()

2

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

brew update && brew install imagemagick

Então você pode usar esse 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 desejar excluir as imagens corrompidas.


1

Use identifydo pacote ImageMagick.

Exemplo de exemplo:

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

E o comando a seguir identificaria todos os arquivos JPEG corrompidos na pasta atual:

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

0

Se você tiver o Perl instalado, poderá usar este script. Você precisa salvar a lista de arquivos para fazer check-in 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);

0

Meu script Pyhton de código aberto, check-media-integridade, verifica a integridade de imagens e arquivos de vídeo / áudio. Ele usa módulos Pillow, ImageMagick e FFmpeg wrappers para tentar decodificar os arquivos.

O travesseiro image.verify não vê todos os defeitos (por exemplo, ignora o truncamento) por esse motivo, também realizei imagem / decodificação + manipulação.


0

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

Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.