diff --git a/glymur/jp2box.py b/glymur/jp2box.py index bf88e4d..6f628df 100644 --- a/glymur/jp2box.py +++ b/glymur/jp2box.py @@ -2122,6 +2122,7 @@ class UUIDBox(Jp2kBox): text = raw_data.decode('utf-8') elt = ET.fromstring(text) self.data = ET.ElementTree(elt) + self._type = 'XMP' elif the_uuid.bytes == b'JpgTiffExif->JP2': exif_obj = Exif(raw_data) ifds = OrderedDict() @@ -2130,8 +2131,16 @@ class UUIDBox(Jp2kBox): ifds['GPSInfo'] = exif_obj.exif_gpsinfo ifds['Iop'] = exif_obj.exif_iop self.data = ifds + self._type = 'Exif' else: self.data = raw_data + self._type = 'unknown' + + if length == 0: + # Need to compute the length. + # The length is 8 (L and T fields) + 16 (length of UUID identifier) + # + length of uuid data. + length = 24 + len(self.data) self.length = length self.offset = offset @@ -2164,6 +2173,16 @@ class UUIDBox(Jp2kBox): return msg + def write(self, fptr): + """Write a UUID box box to file. + """ + if self._type != 'XMP': + msg = "Only XMP UUID boxes can currently be written." + raise NotImplementedError(msg) + read_buffer = struct.pack('>I4s', self.length, 'uuid') + fptr.write(read_buffer) + fptr.write(self.data) + @staticmethod def parse(fptr, offset, length): """Parse UUID box. diff --git a/glymur/jp2k.py b/glymur/jp2k.py index 1bd36a4..45eaf39 100644 --- a/glymur/jp2k.py +++ b/glymur/jp2k.py @@ -514,14 +514,17 @@ class Jp2k(Jp2kBox): Parameters ---------- box : Jp2Box - Instance of a JP2 box. Currently only XML boxes are allowed. + Instance of a JP2 box. Only UUID and XML boxes can currently be + appended. """ if self._codec_format == opj2.CODEC_J2K: msg = "Only JP2 files can currently have boxes appended to them." raise IOError(msg) - if box.box_id != 'xml ': - raise IOError("Only XML boxes can currently be appended.") + if not ((box.box_id == 'xml ') or + (box.box_id == 'uuid' and box._type == 'XMP')): + msg = "Only XML boxes and XMP UUID boxes can currently be appended." + raise IOError(msg) # Check the last box. If the length field is zero, then rewrite # the length field to reflect the true length of the box. diff --git a/glymur/test/test_jp2box.py b/glymur/test/test_jp2box.py index ef62460..ff61bc5 100644 --- a/glymur/test/test_jp2box.py +++ b/glymur/test/test_jp2box.py @@ -429,14 +429,14 @@ class TestAppend(unittest.TestCase): with tempfile.NamedTemporaryFile(suffix=".j2k") as tfile: shutil.copyfile(self.j2kfile, tfile.name) - jp2 = Jp2k(tfile.name) + j2k = Jp2k(tfile.name) - # Make a UUID box. - uuid_instance = uuid.UUID('00000000-0000-0000-0000-000000000000') - data = b'0123456789' - uuidbox = glymur.jp2box.UUIDBox(uuid_instance, data) + # Make an XML box. XML boxes should always be appendable to jp2 + # files. + the_xml = ET.fromstring('0') + xmlbox = glymur.jp2box.XMLBox(xml=the_xml) with self.assertRaises(IOError): - jp2.append(uuidbox) + j2k.append(xmlbox) def test_length_field_is_zero(self): """L=0 (length field in box header) is handled. @@ -473,14 +473,14 @@ class TestAppend(unittest.TestCase): self.assertEqual(ET.tostring(jp2.box[-1].xml.getroot()), b'0') - def test_only_xml_allowed_to_append(self): + def test_append_allowable_boxes(self): """Only XML boxes are allowed to be appended.""" with tempfile.NamedTemporaryFile(suffix=".jp2") as tfile: shutil.copyfile(self.jp2file, tfile.name) jp2 = Jp2k(tfile.name) - # Make a UUID box. + # Make a UUID box. Only XMP UUID boxes can currently be appended. uuid_instance = uuid.UUID('00000000-0000-0000-0000-000000000000') data = b'0123456789' uuidbox = glymur.jp2box.UUIDBox(uuid_instance, data) diff --git a/setup.py b/setup.py index 89e69f7..b780e4d 100644 --- a/setup.py +++ b/setup.py @@ -42,7 +42,7 @@ kwargs['classifiers'] = clssfrs # Get the version string. Cannot do this by importing glymur! version_file = os.path.join('glymur', 'version.py') -with open('glymur/version.py', 'rt') as fptr: +with open(version_file, 'rt') as fptr: contents = fptr.read() match = re.search('version\s*=\s*"(?P\d*.\d*.\d*.*)"\n', contents) kwargs['version'] = match.group('version')