From ffe17f12cbb9545e0d5abcc4f57ffe48dd6ebdba Mon Sep 17 00:00:00 2001 From: jevans Date: Thu, 23 Jan 2014 21:50:48 -0500 Subject: [PATCH] Introducing python-xmp-toolkit requirement. #104 Down to 3 failures and 1 error. --- glymur/_uuid_io/Exif.py | 83 +++++++-------------------------- glymur/_uuid_io/XMP.py | 46 ------------------ glymur/_uuid_io/__init__.py | 6 +-- glymur/_uuid_io/generic.py | 27 ----------- glymur/jp2box.py | 77 ++++++++++++++---------------- glymur/jp2k.py | 4 +- glymur/test/test_jp2box_uuid.py | 5 +- glymur/test/test_jp2k.py | 12 ++--- setup.py | 2 +- 9 files changed, 67 insertions(+), 195 deletions(-) delete mode 100644 glymur/_uuid_io/XMP.py delete mode 100644 glymur/_uuid_io/generic.py diff --git a/glymur/_uuid_io/Exif.py b/glymur/_uuid_io/Exif.py index fb5e2a1..c1b30f0 100644 --- a/glymur/_uuid_io/Exif.py +++ b/glymur/_uuid_io/Exif.py @@ -13,76 +13,27 @@ if sys.hexversion < 0x02070000: else: from collections import OrderedDict -class UUIDExif(object): +def tiff_header(read_buffer): """ - Attributes - ---------- - read_buffer : bytes - Raw byte stream consisting of the UUID data. - endian : str - Either '<' for big-endian, or '>' for little-endian. """ + # Ignore the first six bytes. + # Next 8 should be (73, 73, 42, 8) or (77, 77, 42, 8) + data = struct.unpack('JP2': - self.data = _uuid_io.UUIDExif(raw_data) - self._type = 'Exif' - else: - self.data = _uuid_io.UUIDGeneric(raw_data) - self._type = 'unknown' - except Exception: - # In case of any exception, create the generic UUID. - self.data = _uuid_io.UUIDGeneric(raw_data) - self._type = 'unknown' - msg = "Error encountered during UUID processing, " - msg += "the UUID will be treated as generic.\n\n{0}" - warnings.warn(msg.format(traceback.format_exc())) - - self.raw_data = raw_data - self.length = length self.offset = offset + self.data = None + + try: + self._parse_raw_data() + except Exception as e: + warnings.warn(str(e)) + + def _parse_raw_data(self): + """ + Private function for parsing UUID payloads if possible. + """ + if self.uuid == uuid.UUID('be7acfcb-97a9-42e8-9c71-999491e3afac'): + xmp = XMPMeta() + xmp.parse_from_str(self.raw_data.decode('utf-8'), + xmpmeta_wrap=False) + self.data = xmp + elif self.uuid.bytes == b'JpgTiffExif->JP2': + self.data = _uuid_io.tiff_header(self.raw_data) + else: + self.data = self.raw_data def __repr__(self): msg = "glymur.jp2box.UUIDBox(the_uuid={0}, " msg += "raw_data=)" - return msg.format(repr(self.uuid), len(self.raw_data)) - + return msg.format(repr(self.uuid), len(self.data)) def __str__(self): msg = '{0}\n' - msg += ' UUID: {1} ({2})\n' - msg += ' UUID Data: {3}' + msg += ' UUID: {1}\n' + msg += ' UUID Data: {2}' - msg = msg.format(Jp2kBox.__str__(self), - self.uuid, - self._type, - str(self.data)) + msg = msg.format(Jp2kBox.__str__(self), self.uuid, str(self.data)) return msg - def write(self, fptr): - """Write a UUID box box to file. + """Write a UUID box to file. """ - if self._type != 'XMP': + if self.uuid != uuid.UUID('be7acfcb-97a9-42e8-9c71-999491e3afac'): msg = "Only XMP UUID boxes can currently be written." raise NotImplementedError(msg) - serialized = b'' - serialized += ET.tostring(self.data.packet.getroot(), encoding='utf-8') - serialized += b'' - if self.length == 0: - self.length = 24 + len(serialized) - read_buffer = struct.pack('>I4s', self.length, b'uuid') - fptr.write(read_buffer) + write_buffer = struct.pack('>I4s', self.length, b'uuid') + fptr.write(write_buffer) fptr.write(self.uuid.bytes) - fptr.write(serialized) + fptr.write(self.raw_data) @staticmethod def parse(fptr, offset, length): diff --git a/glymur/jp2k.py b/glymur/jp2k.py index 4d7071e..a337ae7 100644 --- a/glymur/jp2k.py +++ b/glymur/jp2k.py @@ -20,6 +20,7 @@ import ctypes import math import os import struct +from uuid import UUID import warnings import numpy as np @@ -526,7 +527,8 @@ class Jp2k(Jp2kBox): raise IOError(msg) if not ((box.box_id == 'xml ') or - (box.box_id == 'uuid' and box._type == 'XMP')): + (box.box_id == 'uuid' and + box.uuid == UUID('be7acfcb-97a9-42e8-9c71-999491e3afac'))): msg = "Only XML boxes and XMP UUID boxes can currently be appended." raise IOError(msg) diff --git a/glymur/test/test_jp2box_uuid.py b/glymur/test/test_jp2box_uuid.py index c17a6ab..8f24f74 100644 --- a/glymur/test/test_jp2box_uuid.py +++ b/glymur/test/test_jp2box_uuid.py @@ -35,6 +35,8 @@ if sys.hexversion <= 0x03030000: else: from unittest.mock import patch +from libxmp import XMPMeta + import glymur from glymur import Jp2k from .fixtures import OPJ_DATA_ROOT, opj_data_file, SimpleRDF @@ -66,8 +68,7 @@ class TestUUIDXMP(unittest.TestCase): # The data should be an XMP packet, which gets interpreted as # an ElementTree. - self.assertTrue(isinstance(jp2.box[-1].data.packet, - ET.ElementTree)) + self.assertTrue(isinstance(jp2.box[-1].data, XMPMeta)) class TestUUIDExif(unittest.TestCase): """Tests for UUIDs of Exif type.""" diff --git a/glymur/test/test_jp2k.py b/glymur/test/test_jp2k.py index c38cacd..c055aba 100644 --- a/glymur/test/test_jp2k.py +++ b/glymur/test/test_jp2k.py @@ -30,6 +30,8 @@ import warnings import numpy as np import pkg_resources +import libxmp + import glymur from glymur import Jp2k @@ -362,13 +364,9 @@ class TestJp2k(unittest.TestCase): def test_xmp_attribute(self): """Verify the XMP packet in the shipping example file can be read.""" j = Jp2k(self.jp2file) - xmp = j.box[3].data.packet - ns0 = '{http://www.w3.org/1999/02/22-rdf-syntax-ns#}' - ns2 = '{http://ns.adobe.com/xap/1.0/}' - name = '{0}RDF/{0}Description/{1}CreatorTool'.format(ns0, ns2) - elt = xmp.find(name) - self.assertEqual(elt.text, 'Google') - + xmp = j.box[3].data + creator_tool = xmp.get_property(libxmp.consts.XMP_NS_XMP, 'CreatorTool') + self.assertEqual(creator_tool, 'Google') @unittest.skipIf(re.match(r"""1\.[01234]""", glymur.version.openjpeg_version), "Requires at least version 1.5") diff --git a/setup.py b/setup.py index b780e4d..b4fdc2f 100644 --- a/setup.py +++ b/setup.py @@ -16,7 +16,7 @@ kwargs = {'name': 'Glymur', 'license': 'MIT', 'test_suite': 'glymur.test'} -instllrqrs = ['numpy>=1.4.1'] +instllrqrs = ['numpy>=1.4.1', 'python-xmp-toolkit>=2.0.0'] if sys.hexversion < 0x03030000: instllrqrs.append('contextlib2>=0.4') instllrqrs.append('mock>=1.0.1')