diff --git a/glymur/_uuid_io/Exif.py b/glymur/_uuid_io/Exif.py index c1b30f0..a7c04aa 100644 --- a/glymur/_uuid_io/Exif.py +++ b/glymur/_uuid_io/Exif.py @@ -3,6 +3,7 @@ Handlers for Exif UUIDs. Be nice if we would find a standard for this. """ import pprint +import re import struct import sys import warnings @@ -13,8 +14,39 @@ if sys.hexversion < 0x02070000: else: from collections import OrderedDict +# The Python XMP Toolkit may be used for XMP UUIDs, but only if available and +# if the version is at least 2.0.0. +try: + import libxmp + if hasattr(libxmp, 'version') and re.match('[2-9].\d*.\d*', libxmp.version.VERSION): + from libxmp import XMPMeta + _HAS_PYTHON_XMP_TOOLKIT = True + else: + _HAS_PYTHON_XMP_TOOLKIT = False +except ImportError: + _HAS_PYTHON_XMP_TOOLKIT = False + +def xmp(read_buffer): + """ + If libxmp 2.0+ is installed, use it to describe the XMP data. + """ + if not _HAS_PYTHON_XMP_TOOLKIT: + # If the python xmp toolkit is not available or is not advanced enough, + # then issue a warning and just make available the raw data. + msg = "An XMP UUID was detected, but the Python XMP Toolkit package " + msg += "is either not available or is too old (must be at least 2.0). " + msg += "The UUID data field will consist only of the raw uninterpreted " + msg += "bytes." + warnings.warn(msg, UserWarning) + return read_buffer + + xmp = XMPMeta() + xmp.parse_from_str(read_buffer.decode('utf-8'), xmpmeta_wrap=False) + return xmp + def tiff_header(read_buffer): """ + Interpret the UUID data as a TIFF header. """ # Ignore the first six bytes. # Next 8 should be (73, 73, 42, 8) or (77, 77, 42, 8) diff --git a/glymur/_uuid_io/__init__.py b/glymur/_uuid_io/__init__.py index d12d20c..89bbf21 100644 --- a/glymur/_uuid_io/__init__.py +++ b/glymur/_uuid_io/__init__.py @@ -1,4 +1,4 @@ """ Sub package for handling various types of UUIDs. """ -from .Exif import tiff_header +from .Exif import tiff_header, xmp diff --git a/glymur/jp2box.py b/glymur/jp2box.py index 300ac12..8b0f6f3 100644 --- a/glymur/jp2box.py +++ b/glymur/jp2box.py @@ -33,12 +33,6 @@ else: import numpy as np -try: - from libxmp import XMPMeta - _HAS_PYTHON_XMP_TOOLKIT = True -except ImportError: - _HAS_PYTHON_XMP_TOOLKIT = False - from .codestream import Codestream from .core import _COLORSPACE_MAP_DISPLAY from .core import _COLOR_TYPE_MAP_DISPLAY @@ -2228,10 +2222,7 @@ class UUIDBox(Jp2kBox): 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 + self.data = _uuid_io.xmp(self.raw_data) elif self.uuid.bytes == b'JpgTiffExif->JP2': self.data = _uuid_io.tiff_header(self.raw_data) else: @@ -2243,11 +2234,19 @@ class UUIDBox(Jp2kBox): return msg.format(repr(self.uuid), len(self.data)) def __str__(self): - msg = '{0}\n' - msg += ' UUID: {1}\n' - msg += ' UUID Data: {2}' - - msg = msg.format(Jp2kBox.__str__(self), self.uuid, str(self.data)) + if self.uuid == uuid.UUID('be7acfcb-97a9-42e8-9c71-999491e3afac'): + utype = "XMP" + elif self.uuid.bytes == b'JpgTiffExif->JP2': + utype = "EXIF" + else: + utype = "unknown" + msg = '{0}\n UUID: {1} ({2})\n'.format(Jp2kBox.__str__(self), + self.uuid, + utype) + if utype == 'unknown': + msg += ' UUID Data: {0} bytes'.format(len(self.raw_data)) + else: + msg += ' UUID Data: {0}'.format(str(self.data)) return msg diff --git a/glymur/test/fixtures.py b/glymur/test/fixtures.py index 9c543bf..a33d1d6 100644 --- a/glymur/test/fixtures.py +++ b/glymur/test/fixtures.py @@ -170,90 +170,96 @@ def read_pgx_header(pgx_file): nemo_xmp_box = """UUID Box (uuid) @ (77, 3146) UUID: be7acfcb-97a9-42e8-9c71-999491e3afac (XMP) - UUID Data: - - - - Google - 2013-02-09T14:47:53 - - - 1 - 72/1 - 72/1 - 2 - HTC - HTC Glacier - 2592 - 1456 - - - 8 - 8 - 8 - - - 2 - 3 - - - 1343036288/4294967295 - 1413044224/4294967295 - - - - - 2748779008/4294967295 - 1417339264/4294967295 - 1288490240/4294967295 - 2576980480/4294967295 - 644245120/4294967295 - 257698032/4294967295 - - - - - 1 - 2528 - 1424 - 353/100 - 0 - 0/1 - WGS-84 - 2013-02-09T14:47:53 - - - 76 - - - 0220 - 0100 - - - 1 - 2 - 3 - 0 - - - 42,20.56N - 71,5.29W - 2013-02-09T19:47:53Z - NETWORK - - - 2013-02-09T14:47:53 - - - - - Glymur - Python XMP Toolkit - - - - - """ + UUID Data: + + + + Google + 2013-02-09T14:47:53 + + + 1 + 72/1 + 72/1 + 2 + HTC + HTC Glacier + 2592 + 1456 + + + 8 + 8 + 8 + + + 2 + 3 + + + 1343036288/4294967295 + 1413044224/4294967295 + + + + + 2748779008/4294967295 + 1417339264/4294967295 + 1288490240/4294967295 + 2576980480/4294967295 + 644245120/4294967295 + 257698032/4294967295 + + + + + 1 + 2528 + 1424 + 353/100 + 0 + 0/1 + WGS-84 + 2013-02-09T14:47:53 + + + 76 + + + 0220 + 0100 + + + 1 + 2 + 3 + 0 + + + 42,20.56N + 71,5.29W + 2013-02-09T19:47:53Z + NETWORK + + + 2013-02-09T14:47:53 + + + + + Glymur + Python XMP Toolkit + + + + + +""" SimpleRDF = """