Added two negative tests for ChannelDefinition.

This commit is contained in:
John Evans 2013-06-25 18:22:19 -04:00
commit 2ea53f35cf
4 changed files with 71 additions and 32 deletions

View file

@ -392,7 +392,7 @@ class _ICCProfile(object):
self.header = header
class ComponentDefinitionBox(Jp2kBox):
class ChannelDefinitionBox(Jp2kBox):
"""Container for component definition box information.
Attributes
@ -405,27 +405,43 @@ class ComponentDefinitionBox(Jp2kBox):
offset of the box from the start of the file.
longname : str
more verbose description of the box.
component_number : int
number of the component
component_type : int
type of the component
index : int
number of the channel
channel_type : int
type of the channel
association : int
number of the associated color
index of the associated color
"""
def __init__(self, **kwargs):
Jp2kBox.__init__(self, id='', longname='Component Definition')
def __init__(self, index, channel_type, association, **kwargs):
Jp2kBox.__init__(self, id='cdef', longname='Channel Definition')
if len(index) != len(channel_type) or len(index) != len(association):
msg = "Length of channel definition box inputs must be the same."
raise IOError(msg)
# channel types must be one of 0, 1, 2, 65535
if any(x not in [0, 1, 2, 65535] for x in channel_type):
msg = "Channel types must be in the set of\n\n"
msg += " 0 - colour image data for associated color\n"
msg += " 1 - opacity\n"
msg += " 2 - premultiplied opacity\n"
msg += " 65535 - unspecified"
raise IOError(msg)
self.index = index
self.channel_type = channel_type
self.association = association
self.__dict__.update(**kwargs)
def __str__(self):
msg = Jp2kBox.__str__(self)
for j in range(len(self.association)):
color_type_string = _color_type_map_display[self.component_type[j]]
color_type_string = _color_type_map_display[self.channel_type[j]]
if self.association[j] == 0:
assn = 'whole image'
else:
assn = str(self.association[j])
msg += '\n Component {0} ({1}) ==> ({2})'
msg = msg.format(self.component_number[j], color_type_string, assn)
msg += '\n Channel {0} ({1}) ==> ({2})'
msg = msg.format(self.index[j], color_type_string, assn)
return msg
@staticmethod
@ -456,17 +472,17 @@ class ComponentDefinitionBox(Jp2kBox):
buffer = f.read(2)
N, = struct.unpack('>H', buffer)
component_number = []
component_type = []
index = []
chan_type = []
association = []
buffer = f.read(N * 6)
data = struct.unpack('>' + 'HHH' * N, buffer)
kwargs['component_number'] = data[0:N * 6:3]
kwargs['component_type'] = data[1:N * 6:3]
kwargs['association'] = data[2:N * 6:3]
index = data[0:N * 6:3]
channel_type = data[1:N * 6:3]
association = data[2:N * 6:3]
box = ComponentDefinitionBox(**kwargs)
box = ChannelDefinitionBox(index, channel_type, association, **kwargs)
return box
@ -2426,7 +2442,7 @@ class _ExifInteroperabilityIfd(_Ifd):
# Map each box ID to the corresponding class.
_box_with_id = {
'asoc': AssociationBox,
'cdef': ComponentDefinitionBox,
'cdef': ChannelDefinitionBox,
'cmap': ComponentMappingBox,
'colr': ColourSpecificationBox,
'jP ': JPEG2000SignatureBox,

View file

@ -17,6 +17,34 @@ def load_tests(loader, tests, ignore):
return tests
@unittest.skipIf(glymur.lib.openjp2._OPENJP2 is None,
"Missing openjp2 library.")
class TestChannelDefinition(unittest.TestCase):
def setUp(self):
self.jp2file = glymur.data.nemo()
self.j2kfile = glymur.data.goodstuff()
def tearDown(self):
pass
def test_bad_type(self):
# Channel types are limited to 0, 1, 2, 65535
# Should reject if not all of index, channel_type, association the
# same length.
with self.assertRaises(IOError):
box = glymur.jp2box.ChannelDefinitionBox(index=[0, 1, 2],
channel_type=[0, 0, 3],
association=[0, 1, 2])
def test_wrong_lengths(self):
# Should reject if not all of index, channel_type, association the
# same length.
with self.assertRaises(IOError):
box = glymur.jp2box.ChannelDefinitionBox(index=[0, 1, 2],
channel_type=[0, 0],
association=[0, 1, 2])
@unittest.skipIf(glymur.lib.openjp2._OPENJP2 is None,
"Missing openjp2 library.")
class TestJp2Boxes(unittest.TestCase):
@ -225,11 +253,6 @@ class TestJp2Boxes(unittest.TestCase):
with self.assertRaises(NotImplementedError):
j2k.wrap(tfile.name, boxes=boxes)
def test_default_component_definition(self):
# Should be able to specify a component definition box in order to,
# say, create an image with an alpha layer.
self.assertTrue(False)
def test_first_2_boxes_not_jP_and_ftyp(self):
j2k = Jp2k(self.raw_codestream)
c = j2k.get_codestream()

View file

@ -4170,8 +4170,8 @@ class TestSuiteDump(unittest.TestCase):
# Jp2 Header
# Channel Definition
self.assertEqual(jp2.box[2].box[2].component_number, (0, 1, 2))
self.assertEqual(jp2.box[2].box[2].component_type, (0, 0, 0)) # color
self.assertEqual(jp2.box[2].box[2].index, (0, 1, 2))
self.assertEqual(jp2.box[2].box[2].channel_type, (0, 0, 0)) # color
self.assertEqual(jp2.box[2].box[2].association, (3, 2, 1)) # reverse
def test_NR_file3_dump(self):
@ -6706,8 +6706,8 @@ class TestSuiteDump(unittest.TestCase):
# Jp2 Header
# Channel Definition
self.assertEqual(jp2.box[2].box[2].component_number, (0, 1))
self.assertEqual(jp2.box[2].box[2].component_type, (0, 1)) # opacity
self.assertEqual(jp2.box[2].box[2].index, (0, 1))
self.assertEqual(jp2.box[2].box[2].channel_type, (0, 1)) # opacity
self.assertEqual(jp2.box[2].box[2].association, (0, 0)) # both main
c = jp2.box[3].main_header

View file

@ -676,15 +676,15 @@ class TestPrinting(unittest.TestCase):
@unittest.skipIf(data_root is None,
"OPJ_DATA_ROOT environment variable not set")
def test_component_definition(self):
def test_channel_definition(self):
filename = os.path.join(data_root, 'input/conformance/file2.jp2')
j = glymur.Jp2k(filename)
print(j.box[2].box[2])
actual = sys.stdout.getvalue().strip()
lines = ['Component Definition Box (cdef) @ (81, 28)',
' Component 0 (color) ==> (3)',
' Component 1 (color) ==> (2)',
' Component 2 (color) ==> (1)']
lines = ['Channel Definition Box (cdef) @ (81, 28)',
' Channel 0 (color) ==> (3)',
' Channel 1 (color) ==> (2)',
' Channel 2 (color) ==> (1)']
expected = '\n'.join(lines)
self.assertEqual(actual, expected)