From 4a41685a88e83755d4bfe889d5e10b1fd7cc34b3 Mon Sep 17 00:00:00 2001 From: John Evans Date: Wed, 26 Jun 2013 07:15:47 -0400 Subject: [PATCH] Abstracted XML testing into own class. Added more negative cdef tests. --- glymur/jp2k.py | 13 +++ glymur/test/test_jp2box.py | 214 +++++++++++++++++++++++-------------- 2 files changed, 146 insertions(+), 81 deletions(-) diff --git a/glymur/jp2k.py b/glymur/jp2k.py index 6f20ae9..d755cb0 100644 --- a/glymur/jp2k.py +++ b/glymur/jp2k.py @@ -468,6 +468,19 @@ class Jp2k(Jp2kBox): msg = "The jp2 header box must contain a color definition box." raise IOError(msg) + # Any cdef box must be in the jp2 header following the image header. + cdef_lst = [j for (j, box) in enumerate(boxes) if box.id == 'cdef'] + if len(cdef_lst) != 0: + msg = "Any channel defintion box must be in the JP2 header " + msg += "following the image header." + raise IOError(msg) + + cdef_lst = [j for (j, box) in enumerate(jp2h.box) if box.id == 'cdef'] + if len(cdef_lst) > 1: + msg = "Only one channel definition box is allowed in the " + msg += "JP2 header." + raise IOError(msg) + with open(filename, 'wb') as ofile: for box in boxes: if box.id != 'jp2c': diff --git a/glymur/test/test_jp2box.py b/glymur/test/test_jp2box.py index 4b929cd..d39cc64 100644 --- a/glymur/test/test_jp2box.py +++ b/glymur/test/test_jp2box.py @@ -17,17 +17,61 @@ 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() + j2k = Jp2k(self.j2kfile) + c = j2k.get_codestream() + height = c.segment[1].Ysiz + width = c.segment[1].Xsiz + num_components = len(c.segment[1].XRsiz) + + self.jP = JPEG2000SignatureBox() + self.ftyp = FileTypeBox() + self.jp2h = JP2HeaderBox() + self.jp2c = ContiguousCodestreamBox() + self.ihdr = ImageHeaderBox(height=height, width=width, + num_components=num_components) + self.colr_rgb = ColourSpecificationBox(colorspace=glymur.core.SRGB) + def tearDown(self): pass + def test_only_one_cdef_in_jp2_header(self): + """There can only be one channel definition box in the jp2 header.""" + j2k = Jp2k(self.j2kfile) + + cdef = glymur.jp2box.ChannelDefinitionBox(index=[0, 1, 2], + channel_type=[0, 0, 0], + association=[0, 1, 2]) + + boxes = [self.ihdr, cdef, self.colr_rgb, cdef] + self.jp2h.box = boxes + + boxes = [self.jP, self.ftyp, self.jp2h, self.jp2c] + + with tempfile.NamedTemporaryFile(suffix=".jp2") as tfile: + with self.assertRaises(IOError): + j2k.wrap(tfile.name, boxes=boxes) + + def test_not_in_jp2_header(self): + j2k = Jp2k(self.j2kfile) + boxes = [self.ihdr, self.colr_rgb] + self.jp2h.box = boxes + + cdef = glymur.jp2box.ChannelDefinitionBox(index=[0, 1, 2], + channel_type=[0, 0, 0], + association=[0, 1, 2]) + + boxes = [self.jP, self.ftyp, self.jp2h, cdef, self.jp2c] + + with tempfile.NamedTemporaryFile(suffix=".jp2") as tfile: + with self.assertRaises(IOError): + j2k.wrap(tfile.name, boxes=boxes) + 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 @@ -45,6 +89,93 @@ class TestChannelDefinition(unittest.TestCase): channel_type=[0, 0], association=[0, 1, 2]) +class TestXML(unittest.TestCase): + + def setUp(self): + self.jp2file = glymur.data.nemo() + self.j2kfile = glymur.data.goodstuff() + + j2k = Jp2k(self.j2kfile) + c = j2k.get_codestream() + height = c.segment[1].Ysiz + width = c.segment[1].Xsiz + num_components = len(c.segment[1].XRsiz) + + self.jP = JPEG2000SignatureBox() + self.ftyp = FileTypeBox() + self.jp2h = JP2HeaderBox() + self.jp2c = ContiguousCodestreamBox() + self.ihdr = ImageHeaderBox(height=height, width=width, + num_components=num_components) + self.colr = ColourSpecificationBox(colorspace=glymur.core.SRGB) + + def tearDown(self): + pass + + def test_basic_xml(self): + j2k = Jp2k(self.j2kfile) + + self.jp2h.box = [self.ihdr, self.colr] + + the_xml = ET.fromstring('0') + xml = glymur.jp2box.XMLBox(xml=the_xml) + boxes = [self.jP, self.ftyp, self.jp2h, xml, self.jp2c] + + with tempfile.NamedTemporaryFile(suffix=".jp2") as tfile: + j2k.wrap(tfile.name, boxes=boxes) + jp2 = Jp2k(tfile.name) + self.assertEqual(jp2.box[3].id, 'xml ') + + def test_xml_from_file(self): + raw_xml = b""" + + + 1 + 2008 + 141100 + + + + + 4 + 2011 + 59900 + + + + 68 + 2011 + 13600 + + + + """ + with tempfile.NamedTemporaryFile(suffix=".xml") as tfile: + tfile.write(raw_xml) + tfile.flush() + + j2k = Jp2k(self.j2kfile) + + self.jp2h.box = [self.ihdr, self.colr] + + xmlb = glymur.jp2box.XMLBox(filename=tfile.name) + boxes = [self.jP, self.ftyp, self.jp2h, xmlb, self.jp2c] + with tempfile.NamedTemporaryFile(suffix=".jp2") as tfile: + j2k.wrap(tfile.name, boxes=boxes) + jp2 = Jp2k(tfile.name) + + output_boxes = [box.id for box in jp2.box] + self.assertEqual(output_boxes, ['jP ', 'ftyp', 'jp2h', 'xml ', + 'jp2c']) + + elts = jp2.box[3].xml.findall('country') + self.assertEqual(len(elts), 3) + + neighbor = elts[1].find('neighbor') + self.assertEqual(neighbor.attrib['name'], 'Malaysia') + self.assertEqual(neighbor.attrib['direction'], 'N') + + @unittest.skipIf(glymur.lib.openjp2._OPENJP2 is None, "Missing openjp2 library.") class TestJp2Boxes(unittest.TestCase): @@ -370,84 +501,5 @@ class TestJp2Boxes(unittest.TestCase): with self.assertRaises(IOError): j2k.wrap(tfile.name, boxes=boxes) - def test_basic_xml(self): - j2k = Jp2k(self.raw_codestream) - c = j2k.get_codestream() - height = c.segment[1].Ysiz - width = c.segment[1].Xsiz - num_components = len(c.segment[1].XRsiz) - - jP = JPEG2000SignatureBox() - ftyp = FileTypeBox() - jp2h = JP2HeaderBox() - jp2c = ContiguousCodestreamBox() - ihdr = ImageHeaderBox(height=height, width=width, - num_components=num_components) - colr = ColourSpecificationBox(colorspace=glymur.core.SRGB) - jp2h.box = [ihdr, colr] - - the_xml = ET.fromstring('0') - xml = glymur.jp2box.XMLBox(xml=the_xml) - boxes = [jP, ftyp, jp2h, xml, jp2c] - with tempfile.NamedTemporaryFile(suffix=".jp2") as tfile: - j2k.wrap(tfile.name, boxes=boxes) - jp2 = Jp2k(tfile.name) - self.assertEqual(jp2.box[3].id, 'xml ') - - def test_xml_from_file(self): - raw_xml = b""" - - - 1 - 2008 - 141100 - - - - - 4 - 2011 - 59900 - - - - 68 - 2011 - 13600 - - - - """ - with tempfile.NamedTemporaryFile(suffix=".xml") as tfile: - tfile.write(raw_xml) - tfile.flush() - - j2k = Jp2k(self.raw_codestream) - c = j2k.get_codestream() - height = c.segment[1].Ysiz - width = c.segment[1].Xsiz - num_components = len(c.segment[1].XRsiz) - - jP = JPEG2000SignatureBox() - ftyp = FileTypeBox() - jp2h = JP2HeaderBox() - jp2c = ContiguousCodestreamBox() - ihdr = ImageHeaderBox(height=height, width=width, - num_components=num_components) - colr = ColourSpecificationBox(colorspace=glymur.core.SRGB) - jp2h.box = [ihdr, colr] - - xmlb = glymur.jp2box.XMLBox(filename=tfile.name) - boxes = [jP, ftyp, jp2h, xmlb, jp2c] - with tempfile.NamedTemporaryFile(suffix=".jp2") as tfile: - j2k.wrap(tfile.name, boxes=boxes) - jp2 = Jp2k(tfile.name) - - output_boxes = [box.id for box in jp2.box] - self.assertEqual(output_boxes, ['jP ', 'ftyp', 'jp2h', 'xml ', - 'jp2c']) - self.assertIsNotNone(jp2.box[3].xml) - - if __name__ == "__main__": unittest.main()