Automatyzacja skanowania plików graficznych pod kątem uszkodzeń

28

Czy ktoś zna sposób sprawdzania plików graficznych (zwłaszcza JPEG, GIF i PNG) pod kątem uszkodzeń (najlepiej w sposób zautomatyzowany)?


Wyjaśnienie:

Kilka dni temu polecenie działało niepoprawnie i spowodowało usunięcie tysięcy plików graficznych z woluminu FAT32, który praktycznie nie miał miejsca. Użyłem kilku różnych programów do odzyskiwania plików / zdjęć, ale naturalnie są one ograniczone w tym, ile mogą odzyskać (choć na szczęście wolumin ma klastry 8 KB, co nieco pomaga).

W każdym razie niektóre większe pliki, które zostały pofragmentowane, są teraz uszkodzone. Niektóre z nich wcale nie są prawdziwymi plikami (oprogramowanie do odzyskiwania zrzuciło tylko klastry, na które wskazywały teraz zastąpione wpisy w katalogu), podczas gdy inne są uszkodzone z powodu fragmentacji.

Ponadto, ponieważ niektóre formaty obrazów zawierają mniejszą wersję obrazu jako miniaturę, skanowanie miniaturek w poszukiwaniu uszkodzeń nie jest niezawodne, ponieważ może być nienaruszone, podczas gdy rzeczywisty plik (tj. Obraz, gdy jest wyświetlany w pełnym rozmiarze), może być uszkodzony.


Oto kilka przykładów:

Oto drugi. Jest tak uszkodzony, że niczego nie wyświetla.

uszkodzony obraz

(Trzeci nawet nie załaduje, bo nie ma nawet poprawnego nagłówka!)

Synetech
źródło
Masz na myśli zepsucie wizualne, zakładam? Uwielbiam to ... w końcu mogłem przestać oglądać miniatury moich komiksów w poszukiwaniu uszkodzonych plików JPG.
Shinrai
Wizualny lub strukturalny. Znalazłem jedną aplikację, która podobno to zrobiła, ale brakowało jej wielu plików, które nawet nie miały nagłówka !
Synetech
Och, te rzeczy nawet mi się nie przydarzyły. Tak, proszę ... to musi istnieć gdzieś, prawda?
Shinrai
1
Czy możesz przesłać jeden lub więcej przykładów takiego zepsutego pliku i link do nich w swoim pytaniu?
slhck
@Shinrai, badanie miniaturek nie jest wiarygodne, ponieważ wiele formatów obrazów zawiera osobną wersję miniatury osadzoną w obrazie, która może być nienaruszona. Dlatego czasami zdjęcie, którego miniatura wygląda dobrze, jest uszkodzone po otwarciu.
Synetech

Odpowiedzi:

12

Ponieważ natknąłem się na to, próbując odpowiedzieć na to samo pytanie, dodam kolejne świetne rozwiązanie:

Zła Peggy

Zrzut ekranu aplikacji

Użycie
Z menu wybierz, File > Scana następnie użyj okna dialogowego pliku, aby przejść do folderu, w którym znajdują się obrazy. Następnie program rozpocznie skanowanie folderu i wszystkich podfolderów w poszukiwaniu obrazów (.jpg, .png, .bmp, .gif). Jeśli chcesz zeskanować wiele zdjęć, zajmie to trochę czasu, ponieważ program wymaga pełnego załadowania i przeanalizowania pliku obrazu, więc możesz pozwolić mu działać przez noc.

Podczas skanowania pokaże procent postępu na pasku stanu. Wszelkie znalezione obrazy, które nie są idealne, pojawią się bezpośrednio na liście. Kliknięcie dowolnego obrazu na liście spowoduje wyświetlenie podglądu tego obrazu. Dość często obraz będzie miał niewielki problem z formatem pliku, a obraz nadal będzie wyglądał dobrze. Innym razem obraz w ogóle nie będzie renderowany, a podgląd będzie po prostu czarny. Czasami obraz zostanie uszkodzony i zobaczysz coś takiego jak na zrzucie ekranu powyżej.

Bardzo przydatną sztuczką jest kliknięcie nagłówka kolumny na, Reasona obrazy zostaną posortowane według stopnia ich uszkodzenia (np. Wszystkie złe formaty plików, które nadal renderują się poprawnie, zostaną przeniesione na dół, umożliwiając skupienie się na poważniejszych przypadkach) .

Również jeśli pierwsze skanowanie zakończy się i rozpocznie się kolejne skanowanie, wyniki zostaną po prostu dodane do listy. Więc jeśli masz wiele różnych folderów z obrazami, możesz po prostu zeskanować je sekwencyjnie bez usuwania listy po rozpoczęciu nowego skanowania. Jeśli chcesz wyczyścić listę, użyj menu kontekstowego i kliknij Clear list.

Linki
Pliki do pobrania dla systemów Windows, Linux i OS X można znaleźć tutaj:
https://www.coderslagoon.com

Kod źródłowy jest tutaj:
https://github.com/llaith/BadPeggy

Paweł
źródło
Dzięki za poprawkę. Dodałem trochę informacji o użytkowaniu (mimo że program jest bardzo zrozumiały).
Paul
Link do kodu źródłowego jest uszkodzony.
Nicolas Raoul,
9

Wypróbuj opcję jpeginfo ' -c' dla swoich plików JPEG.

Widziałem korupcję, którą pokazujesz, także w przypadku złych kart pamięci.
To, co chcesz, powinno być możliwe i dostępne, sprawdź Uszkodzenie plików graficznych ;
część z internetowej encyklopedii formatów plików graficznych .

Zobacz także Sprawdzanie integralności plików w Podstawowym wprowadzeniu do funkcji PNG .

Być może zainteresuje Cię to pytanie Stackoverflow:
Jak programowo sprawdzić, czy obraz (PNG, JPEG lub GIF) jest uszkodzony ?


Aktualizacja : Źródło tarball dla wersji 1.6.1 autorstwa Timo Kokkonen .
Powinieneś być w stanie zbudować plik binarny dla swojego komputera.

nik
źródło
Niestety nie mogę znaleźć żadnych portów systemu Windows.
Synetech
jpeginfo jest oprogramowaniem typu open source; powinieneś być w stanie pobrać tarball i skompilować go w swoim systemie (może z Cygwin, który ma libjpeg).
nik
Tak czy inaczej, bo muszę przeskanować przynajmniej GIF-y i PNG.
Synetech
1
@nik - katalog aux, który jest częścią tarballa jpeginfo, nie może zostać utworzony pod tą nazwą w systemie Windows, co sprawia, że ​​bardzo trudno jest go nawet wyodrębnić w systemie Windows, a mniej sam go budować. Czy udało Ci się zbudować go w systemie Windows?
Gawron
jpeginfo -c *.JPG | ag (WARNING|ERROR)pracował dla mnie
Selrond
3

Program identyfikacji ImageMagick poinformuje cię, jeśli obraz jest uszkodzony. Testowanie pętli „for i in find” dla kodu zwrotnego „zero” z identyfikatora pozwoli ci dość łatwo napisać test, aby zrzucić listę uszkodzonych lub uszkodzonych plików. Działa również w systemie Windows z programem PowerShell.

wprowadź opis zdjęcia tutaj

Poniższy kod ze zmianami dla ścieżki działa dobrze w 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()
OldWolf
źródło
Od jakiegoś czasu nie korzystałem z ImageMagick (podczas ostatniej próby miałem błędy), ale przyjrzę się temu. Dzieki za sugestie.
Synetech
1
Narzędzie przeglądarki wciąż jest wadliwe, ale identyfikacja działała dla mnie świetnie z podobnym problemem. Użyłem takiego skryptu PowerShell, aby uzyskać listę uszkodzonych plików graficznych lub plików o długości 0.
OldWolf
@Synetech inc. Niestety, nie mogę zaktualizować oryginalnego postu za pomocą sformatowanego kodu, ponieważ obraz został do niego opublikowany i wydaje mi się, że nie mogę go ładnie sformatować. Przykładowy skrypt Powershell: (dostosuj ścieżki, typy plików itp.) $ Stream = [System.IO.StreamWriter] „uszkodzony_jpegs.txt” get-childitem "c: \" -include * .jpg -recurse | foreach ($ _) {& "C: \ Program Files \ ImageMagick-6.7.1-Q16 \ ident.exe" $ _. pełna nazwa> $ null if ($ LastExitCode -ne 0) {$ stream.writeline ($ _. pełna nazwa)}} $ stream.close ()
OldWolf
1
Z wiersza poleceń identifymożna wyświetlać uszkodzone dane JPEG za pomocą -verbose, zwykle się nie wyświetla.
kenorb
3

Można to zrobić za pomocą Imaging Library jest Python .verify()polecenia . [1]

Aby uruchomić to w systemie Windows, zainstaluj Python (zainstalowałem najnowszą wersję Python 2), a następnie zainstaluj Pillow (rozwidlenie biblioteki Python Imaging Library (PIL)). Następnie skopiuj kod jpeg_corrupt.py [2] i zapisz jego zawartość w pliku .PY, np. Jpeg_corrupt.py.

Zauważ, że zmieniłem następujący wiersz kodu w pliku jpeg_corrupt.py :
self.globs = ['*.jpg', '*.jpe', '*.jpeg']
na
self.globs = ['*.jpg', '*.jpe', '*.jpeg', '*.png', '*.gif']
To, aby pliki .PNG i .GIF również zostały przeskanowane.

Można go następnie wykonać za pomocą wiersza polecenia systemu Windows (cmd.exe) w następujący sposób: C:\Python27\python.exe "C:\Directory containing the .PY file\jpeg_corrupt.py" "C:\Directory of folder to be scanned"

Pierwsza część polecenia, „ C: \ Python27 \ python.exe ”, może się różnić w zależności od zainstalowanej wersji Pythona i katalogu, w którym został zainstalowany. W moim przykładzie jest to domyślny katalog instalacyjny Python 2.7.

Powinien skanować wszystkie obrazy JPG, GIF i PNG w określonym katalogu i wszystkich swoich podkatalogach. Pokaże wyjście, jeśli wykryje uszkodzony plik obrazu.

Wpadłem na ten przykładowy obrazek OP i dała ten komunikat o błędzie: ...\YcB9n.png: string index out of range.

Kod można również wprowadzić w pliku skryptu .BAT, dzięki czemu można go łatwo uruchomić w określonym katalogu bez konieczności używania wiersza polecenia:

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



Źródła:

[1]: Odpowiedź w przepełnieniu stosu - „Jak programowo sprawdzić, czy obraz (PNG, JPEG lub GIF) jest uszkodzony?” autor: ChristopheD
[2]: Komentarz Denilsona Sá w odpowiedzi SO na link w [1]

galacticninja
źródło
4
Niektóre części pliku jpg usunąłem losowo - skrypt nic nie pokazał. Wykrywa błędy tylko w najgorszych przypadkach - gdy nagłówek jest całkowicie pominięty, na przykład ...
Pavel Vlasov
Dokładnie to samo dotyczy jpeginfo.
wp78de
2

Zmodyfikowałem kod z odpowiedzi galacticninja, aby zrobić dokładnie to, czego chciał OP. Jest uruchamiany w ten sam sposób, jednak przenosi pliki do folderu catch w C:\katalogu głównym, zamiast wyświetlać obrazy w wierszu polecenia.

Mój zmodyfikowany kod możesz znaleźć na Pastebin lub poniżej:

#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()
CosmicNaut
źródło
2

Zainstaluj imagemagick, jeśli jesteś na Macu, możesz użyć Homebrew.

brew update && brew install imagemagick

Następnie możesz użyć tego małego skryptu w języku 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)

Zastąp /Your/Path/To/Files/i odkomentuj ostatni wiersz, jeśli chcesz usunąć uszkodzone obrazy.

Gotenks
źródło
1

Użyj identifyz pakietu ImageMagick.

Przykładowy przykład:

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

A następujące polecenie zidentyfikuje wszystkie uszkodzone pliki JPEG w bieżącym folderze:

find . -name \*.jpg -exec identify -verbose -regard-warnings {} >/dev/null "+"
kenorb
źródło
0

Jeśli masz zainstalowany Perl, możesz użyć tego skryptu. Musisz zapisać listę plików do sprawdzenia w f.txt przed uruchomieniem skryptu. Możesz zrobić tę listę za pomocą Irfanview. (załaduj wszystkie kciuki z podfolderów i zapisz w txt). Lista dobrych plików jest zapisywana w pliku okf.txt, a uszkodzone pliki - w pliku 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);
ijin
źródło
0

Mój otwarty skrypt Pyhton sprawdzający integralność mediów sprawdza integralność zdjęć oraz plików wideo / audio. Wykorzystuje moduły Pillow, opakowania ImageMagick i FFmpeg, aby spróbować dekodować pliki.

Poduszka image.verify nie widzi wszystkich wad (np. Ignoruje obcięcie) z tego powodu wykonałem także image / decode + manipulację.

Fabiano Tarlao
źródło
0

W tym blogu wymieniono pięć narzędzi, które mogą (wykrywać i) naprawiać uszkodzone pliki obrazów. Jedyną bezpłatną z nich jest File Repair 2.1.

korzeń
źródło