From 2ea53f35cfadf422b7b4fb0cc0cfba10cb5fd941 Mon Sep 17 00:00:00 2001 From: John Evans Date: Tue, 25 Jun 2013 18:22:19 -0400 Subject: [PATCH] Added two negative tests for ChannelDefinition. --- glymur/jp2box.py | 52 +++++++++++++++++++++++------------ glymur/test/test_jp2box.py | 33 ++++++++++++++++++---- glymur/test/test_opj_suite.py | 8 +++--- glymur/test/test_printing.py | 10 +++---- 4 files changed, 71 insertions(+), 32 deletions(-) diff --git a/glymur/jp2box.py b/glymur/jp2box.py index 363611a..034dec5 100644 --- a/glymur/jp2box.py +++ b/glymur/jp2box.py @@ -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, diff --git a/glymur/test/test_jp2box.py b/glymur/test/test_jp2box.py index 32e95a6..4b929cd 100644 --- a/glymur/test/test_jp2box.py +++ b/glymur/test/test_jp2box.py @@ -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() diff --git a/glymur/test/test_opj_suite.py b/glymur/test/test_opj_suite.py index 0566d6c..4e47971 100644 --- a/glymur/test/test_opj_suite.py +++ b/glymur/test/test_opj_suite.py @@ -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 diff --git a/glymur/test/test_printing.py b/glymur/test/test_printing.py index f948c3e..7ad0105 100644 --- a/glymur/test/test_printing.py +++ b/glymur/test/test_printing.py @@ -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)