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

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

有谁知道检查图形文件(特别是 JPEG、GIF 和 PNG)是否损坏的方法(最好以自动化方式)?


解释:

几天前,一个命令运行错误,最终删除了 FAT32 卷中数千个图形文件,而该卷实际上已经没有空间了。我使用过几种不同的文件/照片恢复程序,但它们的恢复量自然是有限的(不过幸运的是,该卷有 8KB 簇,这多少有点帮助)。

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

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


以下是几个示例:

这是第二张。它已经损坏得什么都显示不出来。

图像受损

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

答案1

因为我在尝试回答同样的问题时偶然发现了这一点,所以我将添加我发现的另一个很好的解决方案:

坏佩吉

应用程序截图

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

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

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

此外,如果第一次扫描已完成,您开始另一次扫描,结果将直接添加到列表中。因此,如果您有许多包含图像的不同文件夹,您可以简单地按顺序扫描它们,而不会在开始新扫描时清除列表。如果您确实希望清除列表,请使用上下文菜单并单击Clear list

链接
可在此处找到适用于 Windows、Linux 和 OS X 的下载:
https://www.coderslagoon.com

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

答案2

尝试jpeg信息' -c' 选项适用于您的 JPEG 文件。

我也见过你展示的损坏情况发生在坏的存储卡上。
你想要的应该是可能的和可用的,检查一下图形文件损坏
在线部分图形文件格式百科全书

另请参阅文件完整性检查基本介绍巴布亚新几内亚特征

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


更新源代码为了版本 1.6.1经过蒂莫·科科宁.
您应该能够为您的机器构建一个二进制文件。

答案3

ImageMagick 的标识程序会告诉您图像是否损坏。使用“for i in find”循环测试来自identify的非0返回代码可以让您轻松编写测试脚本以转储损坏或损坏的文件列表。它也适用于带有PowerShell的Windows。

在此处输入图片描述

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

答案4

我已经修改了来自 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()

相关内容