Относительно Фред Фантастик ответ :
Не каждый маркер JPEG между C0
- CF
является SOF
маркерами; Я исключил DHT (C4
), DNL (C8
) и DAC (CC
). Обратите внимание, что я не изучал, возможно ли таким образом анализировать любые кадры, кроме C0
и C2
. Тем не менее, другие, кажется, довольно редко (лично я не встречал ничего, кроме C0
и C2
).
В любом случае, это решает проблему, упомянутую в комментариях Маланди с Bangles.jpg
(DHT ошибочно анализируется как SOF).
Другая проблема, упомянутая с 1431588037-WgsI3vK.jpg
, связана с тем, что imghdr
может обнаружить только заголовки APP0 (EXIF) и APP1 (JFIF).
Это можно исправить, добавив более слабый тест в imghdr (например, просто FFD8
или, может быть, FFD8FF
?) Или что-то гораздо более сложное (возможно, даже проверку данных). При более сложном подходе я обнаружил проблемы только с: APP14 (FFEE
) (Adobe); первый маркер - DQT (FFDB
); и APP2 и проблемы со встроенными ICC_PROFILEs .
Пересмотренный код ниже также немного изменил вызов на imghdr.what()
:
import struct
import imghdr
def test_jpeg(h, f):
# SOI APP2 + ICC_PROFILE
if h[0:4] == '\xff\xd8\xff\xe2' and h[6:17] == b'ICC_PROFILE':
print "A"
return 'jpeg'
# SOI APP14 + Adobe
if h[0:4] == '\xff\xd8\xff\xee' and h[6:11] == b'Adobe':
return 'jpeg'
# SOI DQT
if h[0:4] == '\xff\xd8\xff\xdb':
return 'jpeg'
imghdr.tests.append(test_jpeg)
def get_image_size(fname):
'''Determine the image type of fhandle and return its size.
from draco'''
with open(fname, 'rb') as fhandle:
head = fhandle.read(24)
if len(head) != 24:
return
what = imghdr.what(None, head)
if what == 'png':
check = struct.unpack('>i', head[4:8])[0]
if check != 0x0d0a1a0a:
return
width, height = struct.unpack('>ii', head[16:24])
elif what == 'gif':
width, height = struct.unpack('<HH', head[6:10])
elif what == 'jpeg':
try:
fhandle.seek(0) # Read 0xff next
size = 2
ftype = 0
while not 0xc0 <= ftype <= 0xcf or ftype in (0xc4, 0xc8, 0xcc):
fhandle.seek(size, 1)
byte = fhandle.read(1)
while ord(byte) == 0xff:
byte = fhandle.read(1)
ftype = ord(byte)
size = struct.unpack('>H', fhandle.read(2))[0] - 2
# We are at a SOFn block
fhandle.seek(1, 1) # Skip `precision' byte.
height, width = struct.unpack('>HH', fhandle.read(4))
except Exception: #IGNORE:W0703
return
else:
return
return width, height
Примечание. Создан полный ответ вместо комментария, поскольку мне еще не разрешено.