Merge branch 'issue143' into devel

This commit is contained in:
jevans 2014-01-30 20:00:57 -05:00
commit ff668a4967
2 changed files with 97 additions and 40 deletions

View file

@ -1903,6 +1903,72 @@ class LabelBox(Jp2kBox):
return box
class NumberListBox(Jp2kBox):
"""Container for Number List box information.
Attributes
----------
box_id : str
4-character identifier for the box.
length : int
length of the box in bytes.
offset : int
offset of the box from the start of the file.
longname : str
more verbose description of the box.
AN : list
Descriptors of an entity with which the data contained within the same
Association box is associated.
"""
def __init__(self, associations, length=0, offset=-1):
Jp2kBox.__init__(self, box_id='nlst', longname='Number List')
self.associations = associations
self.length = length
self.offset = offset
def __str__(self):
msg = Jp2kBox.__str__(self)
for j, association in enumerate(self.associations):
if association == 0:
msg += '\n Association[{0}]: the rendered result'.format(j)
elif (association >> 24) == 1:
idx = association & 0x00FFFFFF
msg += '\n Association[{0}]: Codestream {0} '.format(idx)
elif (association >> 24) == 2:
idx = association & 0x00FFFFFF
msg += '\n Association[{0}]: Compositing Layer {0}'
msg = msg.format(idx)
return msg
def __repr__(self):
msg = 'glymur.jp2box.NumberListBox()'
return msg
@staticmethod
def parse(fptr, offset, length):
"""Parse Label box.
Parameters
----------
fptr : file
Open file object.
offset : int
Start position of box in bytes.
length : int
Length of the box in bytes.
Returns
-------
LabelBox instance
"""
num_bytes = offset + length - fptr.tell()
raw_data = fptr.read(num_bytes)
num_associations = int(len(raw_data) / 4)
lst = struct.unpack('>' + 'I' * num_associations, raw_data)
box = NumberListBox(lst, length=length, offset=offset)
return box
class XMLBox(Jp2kBox):
"""Container for XML box information.
@ -2865,6 +2931,7 @@ _BOX_WITH_ID = {
'free': FreeBox,
'jp2h': JP2HeaderBox,
'lbl ': LabelBox,
'nlst': NumberListBox,
'pclr': PaletteBox,
'res ': ResolutionBox,
'resc': CaptureResolutionBox,

View file

@ -20,46 +20,6 @@ from glymur import Jp2k
from glymur.jp2box import ReaderRequirementsBox
@unittest.skipIf(sys.hexversion < 0x03000000, "Warning assert on 2.x.")
@unittest.skipIf(os.name == "nt", "Temporary file issue on window.")
class TestReaderRequirements(unittest.TestCase):
"""Test suite for XML boxes."""
def setUp(self):
self.jp2file = glymur.data.nemo()
pass
def tearDown(self):
pass
def test_mask_length_is_3(self):
"""The standard says that the mask length should be 1, 2, 4, or 8."""
# Rewrite nemo to include this kind of rreq box.
with tempfile.NamedTemporaryFile(suffix=".jpx") as tfile:
with open(self.jp2file, 'rb') as nemof:
# Read the jP and ftyp boxes as-is.
write_buffer = nemof.read(32)
tfile.write(write_buffer)
# Fake a rreq box with ML = 3.
write_buffer = struct.pack('>I4sB', 74, b'rreq', 3)
tfile.write(write_buffer)
# pad the rest with zeros
write_buffer = struct.pack('>65s', b'\x00' * 65)
tfile.write(write_buffer)
# Write the rest of nemo.
tfile.write(nemof.read())
tfile.flush()
with self.assertWarns(UserWarning):
j = Jp2k(tfile.name)
self.assertEqual(j.box[2].box_id, 'rreq')
self.assertEqual(type(j.box[2]),
glymur.jp2box.ReaderRequirementsBox)
@unittest.skipIf(sys.hexversion < 0x03000000, "Warning assert on 2.x.")
@unittest.skipIf(os.name == "nt", "Temporary file issue on window.")
class TestJPXOther(unittest.TestCase):
@ -72,6 +32,16 @@ class TestJPXOther(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]),
glymur.jp2box.ReaderRequirementsBox)
def test_free_box(self):
"""Verify that we can handle a free box."""
with warnings.catch_warnings():
@ -81,3 +51,23 @@ class TestJPXOther(unittest.TestCase):
self.assertEqual(j.box[16].box[0].box_id, 'free')
self.assertEqual(type(j.box[16].box[0]), glymur.jp2box.FreeBox)
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)
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)
# Two associations.
self.assertEqual(len(j.box[16].box[1].box[0].associations), 2)
# Codestream 0
self.assertEqual(j.box[16].box[1].box[0].associations[0], 1 << 24)
# Compositing Layer 0
self.assertEqual(j.box[16].box[1].box[0].associations[1], 2 << 24)