diff --git a/glymur/jp2k.py b/glymur/jp2k.py index 988e814..6db0198 100644 --- a/glymur/jp2k.py +++ b/glymur/jp2k.py @@ -1134,7 +1134,6 @@ def _validate_jp2_box_sequence(boxes): def _validate_jpx_box_sequence(boxes): """Run through series of tests for JPX box legality.""" - _validate_association(boxes) _validate_label(boxes) _validate_jpx_brand(boxes, boxes[1].brand) _validate_jpx_compatibility(boxes, boxes[1].compatibility_list) @@ -1283,6 +1282,12 @@ def _validate_top_level(boxes): if 'dtbl' in multiples: raise IOError('There can only be one dtbl box in a file.') + # If there is one data reference box, then there must also be one ftbl. + if 'dtbl' in count and 'ftbl' not in count: + msg = 'The presence of a data reference box requires the presence of ' + msg += 'a fragment table box as well.' + raise IOError(msg) + def _validate_singletons(boxes): """Several boxes can only occur once.""" count = _collect_box_count(boxes) @@ -1336,23 +1341,6 @@ def _validate_label(boxes): # Same set of checks on any child boxes. _validate_label(box.box) -def _validate_association(boxes): - """ - Association boxes can only contain number list boxes and xml boxes, as far - as we know. - """ - for box in boxes: - if box.box_id == 'asoc': - if box.box[0].box_id != 'nlst' or box.box[1].box_id != 'xml ': - msg = "An Association box can only contain a NumberList box " - msg += "followed by an XML box." - raise RuntimeError(msg) - if hasattr(box, 'box') != 0: - # Same set of checks on any child boxes. - _validate_association(box.box) - - - def extract_image_cube(image): """Extract 3D image from openjpeg data structure. """ diff --git a/glymur/test/test_jp2box_jpx.py b/glymur/test/test_jp2box_jpx.py index e50d4f9..1eb5198 100644 --- a/glymur/test/test_jp2box_jpx.py +++ b/glymur/test/test_jp2box_jpx.py @@ -270,6 +270,7 @@ class TestJPX(unittest.TestCase): """Test suite for other JPX boxes.""" def setUp(self): + self.jp2file = glymur.data.nemo() self.jpxfile = glymur.data.jpxfile() def tearDown(self): @@ -354,6 +355,25 @@ class TestJPX(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_data_reference_requires_dtbl(self): + """The existance of a data reference box requires a ftbl box as well.""" + flag = 0 + version = (0, 0, 0) + url1 = 'file:////usr/local/bin' + url2 = 'http://glymur.readthedocs.org' + jpx1 = glymur.Jp2k(self.jp2file) + boxes = jpx1.box + boxes[1].brand = 'jpx ' + + deurl1 = glymur.jp2box.DataEntryURLBox(flag, version, url1) + deurl2 = glymur.jp2box.DataEntryURLBox(flag, version, url2) + dref = glymur.jp2box.DataReferenceBox([deurl1, deurl2]) + boxes.append(dref) + + with tempfile.NamedTemporaryFile(suffix='.jpx') as tfile: + with self.assertRaises(IOError): + jpx2 = jpx1.wrap(tfile.name, boxes=boxes) + def test_dtbl(self): """Verify that we can interpret Data Reference boxes.""" # Copy the existing JPX file, add a data reference box onto the end.