Merge branch 'issue165' into devel
This commit is contained in:
commit
1a4d6a54c6
4 changed files with 77 additions and 34 deletions
|
|
@ -1837,10 +1837,10 @@ class ReaderRequirementsBox(Jp2kBox):
|
|||
Jp2kBox.__init__(self, box_id='rreq', longname='Reader Requirements')
|
||||
self.fuam = fuam
|
||||
self.dcm = dcm
|
||||
self.standard_flag = standard_flag
|
||||
self.standard_mask = standard_mask
|
||||
self.vendor_feature = vendor_feature
|
||||
self.vendor_mask = vendor_mask
|
||||
self.standard_flag = tuple(standard_flag)
|
||||
self.standard_mask = tuple(standard_mask)
|
||||
self.vendor_feature = tuple(vendor_feature)
|
||||
self.vendor_mask = tuple(vendor_mask)
|
||||
self.length = length
|
||||
self.offset = offset
|
||||
|
||||
|
|
@ -1902,6 +1902,9 @@ class ReaderRequirementsBox(Jp2kBox):
|
|||
read_buffer = fptr.read(1)
|
||||
mask_length, = struct.unpack('>B', read_buffer)
|
||||
|
||||
if mask_length == 3:
|
||||
return _parse_rreq3(fptr, length, offset)
|
||||
|
||||
# Fully Understands Aspect Mask
|
||||
# Decodes Completely Mask
|
||||
read_buffer = fptr.read(2 * mask_length)
|
||||
|
|
@ -1911,6 +1914,7 @@ class ReaderRequirementsBox(Jp2kBox):
|
|||
|
||||
# The mask length tells us the format string to use when unpacking
|
||||
# from the buffer read from file.
|
||||
|
||||
try:
|
||||
mask_format = {1: 'B', 2: 'H', 4: 'I', 8: 'Q'}[mask_length]
|
||||
fuam, dcm = struct.unpack('>' + mask_format * 2, read_buffer)
|
||||
|
|
@ -1931,6 +1935,62 @@ class ReaderRequirementsBox(Jp2kBox):
|
|||
return box
|
||||
|
||||
|
||||
def _parse_rreq3(fptr, length, offset):
|
||||
"""Parse a reader requirements box. Special case when mask length is 3."""
|
||||
# Fully Understands Aspect Mask
|
||||
# Decodes Completely Mask
|
||||
read_buffer = fptr.read(2 * 3)
|
||||
|
||||
fuam = dcm = standard_flag = standard_mask = []
|
||||
vendor_feature = vendor_mask = []
|
||||
|
||||
# The mask length tells us the format string to use when unpacking
|
||||
# from the buffer read from file.
|
||||
lst = struct.unpack('>BBBBBB', read_buffer)
|
||||
fuam = lst[0] << 16 | lst[1] << 8 | lst[2]
|
||||
dcm = lst[3] << 16 | lst[4] << 8 | lst[5]
|
||||
|
||||
read_buffer = fptr.read(2)
|
||||
num_standard_features, = struct.unpack('>H', read_buffer)
|
||||
|
||||
fmt = '>' + 'HBBB' * num_standard_features
|
||||
read_buffer = fptr.read(num_standard_features * 5)
|
||||
lst = struct.unpack(fmt, read_buffer)
|
||||
|
||||
standard_flag = lst[0::4]
|
||||
standard_mask = []
|
||||
for j in range(num_standard_features):
|
||||
items = lst[slice(j * 4 + 1, j * 4 + 4)]
|
||||
mask = items[0] << 16 | items[1] << 8 | items[2]
|
||||
standard_mask.append(mask)
|
||||
|
||||
read_buffer = fptr.read(2)
|
||||
num_vendor_features, = struct.unpack('>H', read_buffer)
|
||||
|
||||
fmt = '>' + 'HBBB' * num_vendor_features
|
||||
read_buffer = fptr.read(num_vendor_features * 5)
|
||||
lst = struct.unpack(fmt, read_buffer)
|
||||
|
||||
# Each vendor feature consists of a 16-byte UUID plus a mask whose
|
||||
# length is specified by, you guessed it, "mask_length".
|
||||
entry_length = 16 + 3
|
||||
read_buffer = fptr.read(num_vendor_features * entry_length)
|
||||
vendor_feature = []
|
||||
vendor_mask = []
|
||||
for j in range(num_vendor_features):
|
||||
ubuffer = read_buffer[j * entry_length:(j + 1) * entry_length]
|
||||
vendor_feature.append(uuid.UUID(bytes=ubuffer[0:16]))
|
||||
|
||||
lst = struct.unpack('>BBB', ubuffer[16:])
|
||||
vmask = lst[0] << 16 | lst[1] << 8 | lst[2]
|
||||
vendor_mask.append(vmask)
|
||||
|
||||
box = ReaderRequirementsBox(fuam, dcm, standard_flag, standard_mask,
|
||||
vendor_feature, vendor_mask,
|
||||
length=length, offset=offset)
|
||||
return box
|
||||
|
||||
|
||||
def _parse_standard_flag(fptr, mask_length):
|
||||
"""Construct standard flag, standard mask data from the file.
|
||||
|
||||
|
|
|
|||
|
|
@ -580,10 +580,7 @@ class TestWrap(unittest.TestCase):
|
|||
|
||||
def test_jpx_to_jp2(self):
|
||||
"""basic test for rewrapping a jpx file"""
|
||||
with warnings.catch_warnings():
|
||||
# This file has a rreq mask length that we do not recognize.
|
||||
warnings.simplefilter("ignore")
|
||||
jpx = Jp2k(self.jpxfile)
|
||||
jpx = Jp2k(self.jpxfile)
|
||||
idx = [0, 1, 3, 6]
|
||||
boxes = [jpx.box[idx] for idx in [0, 1, 3, 6]]
|
||||
with tempfile.NamedTemporaryFile(suffix=".jp2") as tfile:
|
||||
|
|
|
|||
|
|
@ -135,7 +135,6 @@ class TestJPXWrap(unittest.TestCase):
|
|||
jpx = jp2.wrap(tfile.name, boxes=boxes)
|
||||
|
||||
|
||||
@unittest.skipIf(sys.hexversion < 0x03000000, "Warning assert on 2.x.")
|
||||
@unittest.skipIf(os.name == "nt", "Temporary file issue on window.")
|
||||
class TestJPX(unittest.TestCase):
|
||||
"""Test suite for other JPX boxes."""
|
||||
|
|
@ -146,22 +145,18 @@ class TestJPX(unittest.TestCase):
|
|||
def tearDown(self):
|
||||
pass
|
||||
|
||||
def test_rreq_box_strange_mask_length(self):
|
||||
"""The standard says that the mask length should be 1, 2, 4, or 8."""
|
||||
with warnings.catch_warnings():
|
||||
# This file has a rreq mask length that we do not recognize.
|
||||
warnings.simplefilter("ignore")
|
||||
j = Jp2k(self.jpxfile)
|
||||
self.assertEqual(j.box[2].box_id, 'rreq')
|
||||
self.assertEqual(type(j.box[2]),
|
||||
def test_jpx_rreq_mask_length_3(self):
|
||||
"""There are some JPX files with rreq mask length of 3."""
|
||||
jpx = Jp2k(self.jpxfile)
|
||||
self.assertEqual(jpx.box[2].box_id, 'rreq')
|
||||
self.assertEqual(type(jpx.box[2]),
|
||||
glymur.jp2box.ReaderRequirementsBox)
|
||||
self.assertEqual(jpx.box[2].standard_flag,
|
||||
(5, 42, 45, 2, 18, 19, 1, 8, 12, 31, 20))
|
||||
|
||||
def test_free_box(self):
|
||||
"""Verify that we can handle a free box."""
|
||||
with warnings.catch_warnings():
|
||||
# This file has a rreq mask length that we do not recognize.
|
||||
warnings.simplefilter("ignore")
|
||||
j = Jp2k(self.jpxfile)
|
||||
j = Jp2k(self.jpxfile)
|
||||
self.assertEqual(j.box[16].box[0].box_id, 'free')
|
||||
self.assertEqual(type(j.box[16].box[0]), glymur.jp2box.FreeBox)
|
||||
|
||||
|
|
@ -183,10 +178,7 @@ class TestJPX(unittest.TestCase):
|
|||
|
||||
tfile.flush()
|
||||
|
||||
with warnings.catch_warnings():
|
||||
# This file has a rreq mask length that we do not recognize.
|
||||
warnings.simplefilter("ignore")
|
||||
jpx = Jp2k(tfile.name)
|
||||
jpx = Jp2k(tfile.name)
|
||||
|
||||
self.assertEqual(jpx.box[-1].box_id, 'dtbl')
|
||||
self.assertEqual(len(jpx.box[-1].DR), 2)
|
||||
|
|
@ -212,8 +204,7 @@ class TestJPX(unittest.TestCase):
|
|||
|
||||
tfile.flush()
|
||||
|
||||
with self.assertWarns(UserWarning):
|
||||
jpx = Jp2k(tfile.name)
|
||||
jpx = Jp2k(tfile.name)
|
||||
|
||||
self.assertEqual(jpx.box[-1].box_id, 'ftbl')
|
||||
self.assertEqual(jpx.box[-1].box[0].box_id, 'flst')
|
||||
|
|
@ -223,10 +214,7 @@ class TestJPX(unittest.TestCase):
|
|||
|
||||
def test_nlst(self):
|
||||
"""Verify that we can handle a free box."""
|
||||
with warnings.catch_warnings():
|
||||
# This file has a rreq mask length that we do not recognize.
|
||||
warnings.simplefilter("ignore")
|
||||
j = Jp2k(self.jpxfile)
|
||||
j = Jp2k(self.jpxfile)
|
||||
self.assertEqual(j.box[16].box[1].box[0].box_id, 'nlst')
|
||||
self.assertEqual(type(j.box[16].box[1].box[0]),
|
||||
glymur.jp2box.NumberListBox)
|
||||
|
|
|
|||
|
|
@ -379,9 +379,7 @@ class TestJp2k(unittest.TestCase):
|
|||
def test_jpx_mult_codestreams_jp2_brand(self):
|
||||
"""Read JPX codestream when jp2-compatible."""
|
||||
# The file in question has multiple codestreams.
|
||||
with warnings.catch_warnings():
|
||||
warnings.simplefilter("ignore")
|
||||
jpx = Jp2k(self.jpxfile)
|
||||
jpx = Jp2k(self.jpxfile)
|
||||
data = jpx.read()
|
||||
if re.match(r"""1\.[0123]""", glymur.version.openjpeg_version):
|
||||
# openjpeg 1.3 doesn't apply the palette, so it's a 2D image here
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue