使用Python (PIL)读取有损坏头部的JPEG

5 投票
1 回答
4470 浏览
提问于 2025-04-17 23:39

我正在尝试在Python 2.7中打开一个jpeg文件,

from PIL import Image
im = Image.open(filename)

但是这对我来说没用,

>>> im = Image.open(filename)
Traceback (most recent call last):
  File "<pyshell#810>", line 1, in <module>
    im = Image.open(filename)
  File "/usr/lib/python2.7/dist-packages/PIL/Image.py", line 1980, in open
    raise IOError("cannot identify image file")
IOError: cannot identify image file

不过在其他查看器上试的时候,它打开得很好。深入研究后发现,PILJpegImagePlugin.py文件中的JpegImageFile._open方法因为JPEG文件头中在0xFFDA标记之前有几个多余的0x00字节而引发了SyntaxError异常,

Corrupt JPEG data: 5 extraneous bytes before marker 0xda

也就是说,虽然我尝试的其他程序只是忽略了文件头末尾的未知0x00标记,但PIL选择抛出异常,这让我无法打开这个图片。

问题:除了直接编辑PIL的代码,还有什么方法可以打开有问题的JPEG文件吗?

下面是引发异常的JpegImageFile类的相关代码,供你参考:

def _open(self):

    s = self.fp.read(1)

    if ord(s[0]) != 255:
        raise SyntaxError("not a JPEG file")

    # Create attributes
    self.bits = self.layers = 0

    # JPEG specifics (internal)
    self.layer = []
    self.huffman_dc = {}
    self.huffman_ac = {}
    self.quantization = {}
    self.app = {} # compatibility
    self.applist = []
    self.icclist = []

    while 1:

        s = s + self.fp.read(1)

        i = i16(s)

        if MARKER.has_key(i):
            name, description, handler = MARKER[i]
            # print hex(i), name, description
            if handler is not None:
                handler(self, i)
            if i == 0xFFDA: # start of scan
                rawmode = self.mode
                if self.mode == "CMYK":
                    rawmode = "CMYK;I" # assume adobe conventions
                self.tile = [("jpeg", (0,0) + self.size, 0, (rawmode, ""))]
                # self.__offset = self.fp.tell()
                break
            s = self.fp.read(1)
        elif i == 0 or i == 65535:
            # padded marker or junk; move on
            s = "\xff"
        else:
            raise SyntaxError("no marker found")

1 个回答

5

PIL(Python Imaging Library)对损坏的文件头数据很敏感,正如你发现的那样,它会出现问题。

我已经向Pillow(PIL的一个友好的分支)提交了一个请求,希望能解决这个问题。

这个请求还没有被接受,但希望在几个月后即将发布的2.5.0版本中能包含这个修复。在此期间,你可以在这里试用一下:https://github.com/python-imaging/Pillow/pull/647

作为一个临时解决办法,你可以先用ImageMagick把有问题的图片转换成png格式,然后再在PIL/Pillow中使用它们。

撰写回答