自动扫描图形文件是否损坏


27

有谁知道一种检查图形文件(尤其是JPEG,GIF和PNG)是否损坏(最好是自动方式)的方法吗?


说明:

几天前,一个命令无法正常工作,并最终从实际上空间不足的FAT32卷中删除了数千个图形文件。我使用了几种不同的文件/照片恢复程序,但是自然地,它们的恢复能力有限(尽管幸运的是该卷具有8KB群集,这有所帮助)。

无论如何,一些较大的文件(已碎片化)现在已损坏。其中一些甚至根本不是真实文件(恢复软件仅转储了现在被覆盖的目录条目指向的群集),而另一些则由于碎片而损坏。

此外,由于某些图片格式将图片的较小版本嵌入到缩略图中,因此扫描缩略图不可靠是不可靠的,因为它可能会完整无损,而实际文件(即全尺寸查看时的图片)可能会损坏。


以下是几个示例:

这是第二个。它是如此损坏,以至于什么也没显示。

损坏的图像

(第三个甚至都不会上传,因为它甚至没有正确的标题!)


我想你是说视觉腐败?我很喜欢这个...最后,我可以不再盯着漫画缩略图中的破碎的jpg。
Shinrai 2011年

视觉或结构上的。我找到了一个应该执行此操作的应用程序,但是它错过了很多甚至没有标题的文件
Synetech 2011年

哦,这些东西甚至都没有出现在我身上。是的,请...这必须存在于某些地方吧?
Shinrai 2011年

1
您可以上传一个或多个此类损坏文件的示例并在您的问题中链接到它们吗?
slhck 2011年

@Shinrai,检查缩略图是不可靠的,因为许多图片格式包括嵌入在图片中的单独的缩略图版本,并且可能是完整的。这就是有时打开缩略图的图片有时会损坏的原因。
Synetech

Answers:


12

由于我在尝试回答同一问题时偶然发现了这一点,因此我添加了另一个很棒的解决方案:

坏佩吉

该应用程序的屏幕截图

用法
从菜单中选择File > Scan,然后使用文件对话框浏览到图像所在的文件夹。然后,程序将开始扫描文件夹和所有子文件夹中的图像(.jpg,.png,.bmp,.gif)。如果您要扫描很多图片,这将需要一些时间,因为该程序需要完全加载并解析图像文件,因此您可能希望使其运行一整夜。

在扫描过程中,它将在状态栏中显示进度百分比。它发现的任何不完美的图像都将直接显示在列表中。如果单击列表上的任何图像,它将显示该图像的预览。通常,图像的文件格式只有很小的问题,并且图像看起来仍然很好。其他时候,图像根本不会渲染,预览只是黑色。有时图像会被损坏,您会在上面的屏幕截图中看到类似的内容。

一个非常方便的技巧是单击列标题,Reason然后根据损坏程度对图像进行排序(例如,所有仍能正确呈现的不良文件格式都将移至底部,让您专注于更严重的情况) 。

同样,如果第一次扫描已完成,而您又开始了另一次扫描,则结果将仅添加到列表中。因此,如果您有许多带有图像的文件夹,则可以简单地顺序扫描它们,而在开始新的扫描时不会清除列表。如果确实要清除列表,请使用上下文菜单,然后单击Clear list


可在以下位置找到适用于Windows,Linux和OS X的链接下载:https :
//www.coderslagoon.com

源代码在这里:https :
//github.com/llaith/BadPeggy


感谢您的修复。我添加了一些用法信息(即使该程序非常不言自明)。
Paul

源代码链接已断开。
尼古拉斯·拉乌尔

9

为您的JPEG文件尝试jpeginfo ' -c'选项。

我已经看到您显示的损坏也发生在坏的存储卡上。
您想要的东西应该可能并且可用,请检查“图形文件损坏”
在线图形文件格式百科全书的一部分

另请参阅文件完整性检查的基本介绍PNG特点

您可能对以下Stackoverflow问题感兴趣,
如何以编程方式检查图像(PNG,JPEG或GIF)是否损坏


更新源码包1.6.1版本蒂莫Kokkonen
您应该能够为您的计算机构建二进制文件。


不幸的是,我找不到任何Windows端口。
Synetech 2011年

jpeginfo是开源的;您应该能够获取tarball并在系统上对其进行编译(也许使用具有libjpeg的Cygwin)。
尼克

无论哪种方式都无济于事,因为我还需要至少扫描GIF和PNG。
Synetech 2011年

1
@nik-aux目录(它是jpeginfo的tarball的一部分)无法在Windows上以该名称创建,这使得即使在Windows下也很难解压缩,更不用说构建它了。您是否设法在Windows下构建它?
2015年

jpeginfo -c *.JPG | ag (WARNING|ERROR)为我工作
-Selrond

3

ImageMagick的识别程序将让您知道图像是否损坏。从identify获得none-0返回代码的“ for in in find”循环测试将使您可以轻松编写测试脚本,以转储损坏或损坏的文件列表。它也可以在Windows和PowerShell上运行。

在此处输入图片说明

以下代码对您的路径进行了更改,在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()

我已经有一段时间没有使用ImageMagick了(上次尝试时有bug),但我将对其进行研究。谢谢你的建议。
Synetech

1
查看器工具仍然存在问题,但遇到类似问题对我来说非常有用。我使用了像这样的powershell脚本来获取损坏的或长度为0的图像文件的列表。
OldWolf 2011年

@Synetech公司 抱歉,由于已发布图像,因此无法使用格式化的代码更新原始帖子,而且我似乎也无法很好地对其进行格式化。示例的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($ _。全名)}} $ stream.close()
OldWolf 2011年

1
在命令行中,identify可以使用显示损坏的JPEG数据-verbose,通常不显示。
kenorb

3

这可以通过使用Python Imaging Library的.verify()command来完成。[1]

要在Windows中运行此程序,请安装Python(我安装了最新版本的Python 2),然后安装Pillow(Python Imaging Library(PIL)的分支)。然后,复制jpeg_corrupt.py [2]代码并将其内容保存到.PY文件,例如jpeg_corrupt.py。

请注意,我将jpeg_corrupt.py中的以下代码行更改为:
self.globs = ['*.jpg', '*.jpe', '*.jpeg']

self.globs = ['*.jpg', '*.jpe', '*.jpeg', '*.png', '*.gif']
因此.PNG和.GIF文件也将被扫描。

然后可以通过Windows命令提示符(cmd.exe)执行该命令,如下所示: C:\Python27\python.exe "C:\Directory containing the .PY file\jpeg_corrupt.py" "C:\Directory of folder to be scanned"

命令的第一部分“ C:\ Python27 \ python.exe ”可能会有所不同,具体取决于安装的Python版本和安装目录。在我的示例中,它是Python 2.7的默认安装目录。

它应扫描指定目录及其所有子目录中的所有JPG,GIF和PNG图像。如果检测到损坏的图像文件,它将显示输出。

我在OP的示例图片上运行了它,并给出了此错误消息:...\YcB9n.png: string index out of range

该代码也可以输入.BAT脚本文件中,因此您可以轻松地在指定目录下运行它,而无需使用命令提示符:

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



资料来源:

[1]:堆栈溢出中的答案-“如何以编程方式检查图像(PNG,JPEG或GIF)是否损坏?” 通过ChristopheD
[2]:在链接的SO答复德尼尔森Sá评论[1]


4
我随机删除了jpg文件的某些部分-该脚本未显示任何内容。它仅在最坏的情况下才检测错误-例如,当标头完全丢失时……
Pavel Vlasov 2015年

确实,jpeginfo也是如此。
wp78de

2

我已经修改了galacticninja的答案中代码,以准确执行OP想要的操作。它以相同的方式运行,但是它将文件移动到根C:\目录中的catch文件夹中,而不仅仅是在命令提示符下列出图像。

您可以在Pastebin或以下找到我修改过的代码:

#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

安装imagemagick,如果您使用的是Mac,则可以使用Homebrew。

brew update && brew install imagemagick

然后,您可以使用这个小的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)

/Your/Path/To/Files/如果要删除损坏的图像,请替换并取消注释最后一行。


1

identify从ImageMagick包中使用。

示例示例:

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

并且以下命令将识别当前文件夹中的所有损坏的JPEG文件:

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

0

如果安装了Perl,则可以使用此脚本。运行脚本之前,需要保存文件列表以检入f.txt。您可以使用Irfanview列出此列表。(从子文件夹加载所有缩略图并保存为txt)。好的文件列表保存在okf.txt中,损坏的文件列在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

这篇博客文章列出了五个可以(检测和)修复损坏的图像文件的工具。其中唯一免费的是File Repair 2.1。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.