Python3 - 解析jpeg尺寸信息

5
我正在尝试编写一个Python函数来解析JPEG文件的宽度和高度。我目前的代码如下:
import struct

image = open('images/image.jpg','rb')
image.seek(199)
#reverse hex to deal with endianness...
hex = image.read(2)[::-1]+image.read(2)[::-1]
print(struct.unpack('HH',hex))
image.close()

然而,这里有几个问题。首先,我需要查看文件以确定从哪里读取(在 ff c0 00 11 08 之后),其次,我需要避免获取嵌入式缩略图的数据。有什么建议吗?

4个回答

4

由于字节和字符串的变化,我无法在Python3中使用任何解决方案。在Acorn的解决方案的基础上,我想出了以下解决方案,在Python3中可以成功运行:

import struct
import io

height = -1
width = -1

dafile = open('test.jpg', 'rb')
jpeg = io.BytesIO(dafile.read())
try:

    type_check = jpeg.read(2)
    if type_check != b'\xff\xd8':
      print("Not a JPG")
    else:
      byte = jpeg.read(1)

      while byte != b"":

        while byte != b'\xff': byte = jpeg.read(1)
        while byte == b'\xff': byte = jpeg.read(1)

        if (byte >= b'\xC0' and byte <= b'\xC3'):
          jpeg.read(3)
          h, w = struct.unpack('>HH', jpeg.read(4))
          break
        else:
          jpeg.read(int(struct.unpack(">H", jpeg.read(2))[0])-2)

        byte = jpeg.read(1)

      width = int(w)
      height = int(h)

      print("Width: %s, Height: %s" % (width, height))
finally:
    jpeg.close()

1
你打开了 'dafile' 但没有关闭它。除此之外,它运行良好。 - user136036

3
这个函数中的JPEG部分可能会有所帮助: http://code.google.com/p/bfg-pages/source/browse/trunk/pages/getimageinfo.py
jpeg.read(2)
b = jpeg.read(1)
try:
    while (b and ord(b) != 0xDA):
        while (ord(b) != 0xFF): b = jpeg.read(1)
        while (ord(b) == 0xFF): b = jpeg.read(1)
        if (ord(b) >= 0xC0 and ord(b) <= 0xC3):
            jpeg.read(3)
            h, w = struct.unpack(">HH", jpeg.read(4))
            break
        else:
            jpeg.read(int(struct.unpack(">H", jpeg.read(2))[0])-2)
        b = jpeg.read(1)
    width = int(w)
    height = int(h)
except struct.error:
    pass
except ValueError:
    pass

谢谢,看起来非常有用,对于开始使用struct.unpack('>HH',hex))肯定更加整洁。 - Tired Tove

1
我的建议是:使用PIL(Python Imaging Library)。
>>> import Image
>>> img= Image.open("test.jpg")
>>> print img.size
(256, 256)

否则,使用Hachoir,它是一个纯Python库;特别是hachoir-metadata似乎具有您想要的功能。

2
据我所知,PIL仍然无法在py3k上运行。 - Daenyth
1
使用 pillow - malat

0

Acorn和manafire提供了更加现代化、简化的、符合pep8标准的代码。还有一些可以改进的地方,例如使用大块大小以提高效率,但对于一个快速示例来说已经足够好了。

import sys
from struct import unpack


with open(sys.argv[1], 'rb') as jpegfile:

    if jpegfile.read(2) == b'\xff\xd8':

        byte = jpegfile.read(1)
        h = w = -1
        while byte != b'':

            # skip early segments
            while byte != b'\xff':
                byte = jpegfile.read(1)
            while byte == b'\xff':
                byte = jpegfile.read(1)

            # read dimensions
            if byte >= b'\xC0' and byte <= b'\xC3':
                jpegfile.read(3)
                h, w = unpack('>HH', jpegfile.read(4))
                break
            else:
                size = int(unpack('>H', jpegfile.read(2))[0])
                jpegfile.read(size - 2)

            byte = jpegfile.read(1)

        print(f'Width: {w}, Height: {h}')
    else:
        print('Not a JPG!')

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接