fix: jp2 image size bytes header
This commit is contained in:
@@ -29,6 +29,32 @@ def determine_file_ext(data: bytes) -> Optional[str]:
|
|||||||
return None
|
return None
|
||||||
|
|
||||||
|
|
||||||
|
def _determine_jp2_size(data: bytes) -> Optional[Tuple[int, int]]:
|
||||||
|
''' Read raw bytes and extract JPEG2000 image size. '''
|
||||||
|
if data[:4] == b'\xFF\x4F\xFF\x51':
|
||||||
|
w, h = struct.unpack('>II', data[8:16])
|
||||||
|
return w, h
|
||||||
|
|
||||||
|
# fixed "jP" file header 0000000C 6A502020 0D0A870A
|
||||||
|
off = 12
|
||||||
|
filesize = len(data)
|
||||||
|
|
||||||
|
while off < filesize:
|
||||||
|
box_size, box_type = struct.unpack('>I4s', data[off:off+8])
|
||||||
|
# find JP2 Header box
|
||||||
|
if box_type == b'jp2h':
|
||||||
|
child = off + 8 # skip parent header
|
||||||
|
while child < (off + box_size):
|
||||||
|
# find Image Header box
|
||||||
|
if data[child+4:child+8] == b'ihdr':
|
||||||
|
h, w = struct.unpack('>II', data[child+8:child+16])
|
||||||
|
return w, h
|
||||||
|
|
||||||
|
child += struct.unpack('>I', data[child:child+4])[0]
|
||||||
|
off += box_size
|
||||||
|
return None
|
||||||
|
|
||||||
|
|
||||||
def determine_image_size(data: bytes, ext: Optional[str] = None) \
|
def determine_image_size(data: bytes, ext: Optional[str] = None) \
|
||||||
-> Optional[Tuple[int, int]]:
|
-> Optional[Tuple[int, int]]:
|
||||||
''' Supports PNG, ARGB, and Jpeg 2000 image data. '''
|
''' Supports PNG, ARGB, and Jpeg 2000 image data. '''
|
||||||
@@ -45,14 +71,7 @@ def determine_image_size(data: bytes, ext: Optional[str] = None) \
|
|||||||
data = data[4:] # without it32 header
|
data = data[4:] # without it32 header
|
||||||
return IcnsType.match_maxsize(PackBytes.get_size(data), 'rgb').size
|
return IcnsType.match_maxsize(PackBytes.get_size(data), 'rgb').size
|
||||||
elif ext == 'jp2':
|
elif ext == 'jp2':
|
||||||
if data[:4] == b'\xFF\x4F\xFF\x51':
|
return _determine_jp2_size(data)
|
||||||
w, h = struct.unpack('>II', data[8:16])
|
|
||||||
return w, h
|
|
||||||
len_ftype = struct.unpack('>I', data[12:16])[0]
|
|
||||||
# file header + type box + header box (super box) + image header box
|
|
||||||
offset = 12 + len_ftype + 8 + 8
|
|
||||||
h, w = struct.unpack('>II', data[offset:offset + 8])
|
|
||||||
return w, h
|
|
||||||
return None # icns does not support other image types except binary
|
return None # icns does not support other image types except binary
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
BIN
tests/fixtures/32x32.jpf
vendored
Normal file
BIN
tests/fixtures/32x32.jpf
vendored
Normal file
Binary file not shown.
@@ -146,6 +146,7 @@ class TestCLI_compose(unittest.TestCase):
|
|||||||
def test_jp2(self):
|
def test_jp2(self):
|
||||||
self.assert_conv_file('256x256.jp2', 'ic08')
|
self.assert_conv_file('256x256.jp2', 'ic08')
|
||||||
self.assert_conv_file('18x18.j2k', 'icsb', arg=['-f'])
|
self.assert_conv_file('18x18.j2k', 'icsb', arg=['-f'])
|
||||||
|
self.assert_conv_file('32x32.jpf', 'icp5', arg=['-f'])
|
||||||
|
|
||||||
def test_argb(self):
|
def test_argb(self):
|
||||||
self.assert_conv_file('rgb.icns.argb', 'ic04')
|
self.assert_conv_file('rgb.icns.argb', 'ic04')
|
||||||
|
|||||||
@@ -444,6 +444,7 @@ class TestRawData(unittest.TestCase):
|
|||||||
self.assertEqual(fn('rgb.icns.argb'), (16, 16))
|
self.assertEqual(fn('rgb.icns.argb'), (16, 16))
|
||||||
self.assertEqual(fn('256x256.jp2'), (256, 256))
|
self.assertEqual(fn('256x256.jp2'), (256, 256))
|
||||||
self.assertEqual(fn('18x18.j2k'), (18, 18))
|
self.assertEqual(fn('18x18.j2k'), (18, 18))
|
||||||
|
self.assertEqual(fn('32x32.jpf'), (32, 32))
|
||||||
|
|
||||||
def test_ext(self):
|
def test_ext(self):
|
||||||
for data, ext in (
|
for data, ext in (
|
||||||
|
|||||||
Reference in New Issue
Block a user