diff --git a/CHANGES.txt b/CHANGES.txt index 2cb6883..ef8ef6c 100644 --- a/CHANGES.txt +++ b/CHANGES.txt @@ -1,3 +1,10 @@ +Jun 16, 2013 - v0.1.9 Reading ICC profile headers as ordered dicts. Exif + dictionaries changed to ordered dicts. Honoring XDG_CONFIG_HOME + environment variable. + +Jun 14, 2013 - v0.1.8 Added reduce=-1 option to get lowest resolution + thumbnail. + Jun 07, 2013 - v0.1.7 Changed Exif dictionary names from ['Exif', 'Photo', 'Iop', 'GPSInfo'] to ['Image', 'Photo', 'Iop', 'GPSInfo']. diff --git a/MANIFEST.in b/MANIFEST.in index 160d333..86279d7 100644 --- a/MANIFEST.in +++ b/MANIFEST.in @@ -1,4 +1,3 @@ include *.txt *.md -recursive-include *.txt *.py prune build exclude readthedocs-pip-requirements.txt diff --git a/docs/source/conf.py b/docs/source/conf.py index 262e5d8..0e3563a 100644 --- a/docs/source/conf.py +++ b/docs/source/conf.py @@ -78,7 +78,7 @@ copyright = u'2013, John Evans' # The short X.Y version. version = '0.1' # The full version, including alpha/beta/rc tags. -release = '0.1.7' +release = '0.1.9' # The language for content autogenerated by Sphinx. Refer to documentation # for a list of supported languages. diff --git a/docs/source/detailed_installation.rst b/docs/source/detailed_installation.rst new file mode 100644 index 0000000..1771722 --- /dev/null +++ b/docs/source/detailed_installation.rst @@ -0,0 +1,110 @@ +----------------------------------------------------- +Detailed Instructions for Package Management, Testing +----------------------------------------------------- + +You only need to read this page if you want detailed +platform-specific instructions on running as many tests as possible or wish to +use your system's package manager to install as many required +packages/RPMs/ports/whatever without going through pip. Otherwise go on to +the next page. + +'''''''' +Platform +'''''''' + +Mac OS X +-------- +All the necessary packages are available to use glymur with Python 3.3 via +MacPorts. A minimal set of ports includes + + * python33 + * py33-numpy + * py33-distribute + +To run all the testing, one of the following combinations of ports must +additionally be installed: + + * py33-scikit-image and either py33-Pillow or freeimage + * py33-matplotlib and py33-Pillow + +Linux +----- + +Fedora 18 +''''''''' +Fedora 18 ships with Python 3.3, so all the necessary RPMs are available to +meet the minimal set of requirements. + + * python3 + * python3-numpy + * python3-setuptools + * python3-matplotlib (for running tests) + * python3-matplotlib-tk (or whichever matplotlib backend you prefer) + +A few tests still will not run, however, unless one of the following +combinations of RPMs / Python packages is installed. + + * scikit-image and either Pillow or freeimage + * matplotlib and Pillow + +The 2nd route is probably the easiest, so go ahead and install Pillow +via pip since Pillow is not yet available in Fedora 18 default +repositories:: + + $ yum install python3-devel # pip needs this in order to compile Pillow + $ yum install python3-pip + $ pip-python3 install Pillow --user + $ export PYTHONPATH=$HOME/.local/lib/python3.3/site-packages:$PYTHONPATH + +Fedora 17 +''''''''' +Fedora 17 ships with Python 3.2 and 2.7, so these steps detail working with +2.7. + +Required RPMs include:: + + * python + * python-mock + * python-pip + * python-setuptools + * numpy + +In addition, you must install contextlib2 via pip. + +A few tests still will not run, however, unless one of the following +combinations of RPMs / Python packages is installed. + + * scikit-image and either Pillow or freeimage + * matplotlib and Pillow + +scikit-image is not available in the Fedora 17 default repositories, but +it may be installed via pip:: + + $ yum install Cython # pip needs this in order to compile scikit-image + $ yum install python-devel # pip needs this in order to compile scikit-image + $ yum install freeimage # scikit-image uses this as a backend + $ yum install scipy # needed by scikit-image + $ pip-python install scikit-image --user + $ pip-python install contextlib2 --user + $ export PYTHONPATH=$HOME/.local/lib/python2.7/site-packages:$PYTHONPATH + +Windows +------- +Not currently supported. + +''''''' +Testing +''''''' + +If you wish to run the tests (strongly suggested :-), try the following + + $ cd /to/where/you/unpacked/glymur + $ python -m unittest discover + +Quite a few tests are currently skipped. These include tests whose +OpenJPEG counterparts are already failing, and others which do pass but +still produce heaps of output on stderr. Rather than let this swamp +the signal (that most of the tests are actually passing), they've been +filtered out for now. There are also more skipped tests on Python 2.7 +than on Python 3.3. The important part is whether or not any test +errors are reported at the end. diff --git a/docs/source/how_do_i.rst b/docs/source/how_do_i.rst index 82f03bd..355ff14 100644 --- a/docs/source/how_do_i.rst +++ b/docs/source/how_do_i.rst @@ -3,6 +3,17 @@ How do I...? ------------ +Read the lowest resolution thumbnail? +===================================== +Printing the Jp2k object should reveal the number of resolutions (look in the +COD segment section), but you can take a shortcut by supplying -1 as the reduce +level. :: + + >>> import glymur + >>> file = glymur.data.nemo() + >>> j = glymur.Jp2k(file) + >>> thumbnail = j.read(reduce=-1) + Display metadata? ================= There are two ways. From the unix command line, the script *jp2dump* is @@ -12,9 +23,8 @@ available. :: From within Python, it is as simple as printing the Jp2k object, i.e. :: - >>> import pkg_resources >>> from glymur import Jp2k - >>> file = pkg_resources.resource_filename(glymur.__name__, "data/nemo.jp2") + >>> file = glymur.data.nemo() >>> j = Jp2k(file) >>> print(j) @@ -26,11 +36,10 @@ codestream box, only the main header is printed. It is possible to print Work with XMP UUIDs? ==================== -The example JP2 file shipped with glymur has an XMP UUID:: +The example JP2 file shipped with glymur has an XMP UUID. :: - >>> import pkg_resources >>> from glymur import Jp2k - >>> file = pkg_resources.resource_filename(glymur.__name__, "data/nemo.jp2") + >>> file = glymur.data.nemo() >>> j = Jp2k(file) >>> print(j.box[4]) UUID Box (uuid) @ (715, 2412) diff --git a/docs/source/index.rst b/docs/source/index.rst index bcc2d75..8536be8 100644 --- a/docs/source/index.rst +++ b/docs/source/index.rst @@ -13,6 +13,7 @@ Contents: :maxdepth: 2 introduction + detailed_installation how_do_i roadmap api diff --git a/docs/source/introduction.rst b/docs/source/introduction.rst index 27beed2..d21d7eb 100644 --- a/docs/source/introduction.rst +++ b/docs/source/introduction.rst @@ -19,189 +19,54 @@ some very limited support for reading JPX metadata. For instance, **asoc** and **labl** boxes are recognized, so GMLJP2 metadata can be retrieved from such JPX files. -'''''''''''' -Requirements -'''''''''''' -glymur works on Python 2.7 and 3.3. Python 3.3 is strongly recommended. +Glymur works on Python 2.7 and 3.3. Python 3.3 is strongly recommended. -OpenJPEG -======== +OpenJPEG Installation +===================== OpenJPEG must be built as a shared library. In addition, you currently must compile OpenJPEG from the developmental source that you can retrieve via subversion. As of this time of writing, svn -revision 2345 works. In addition, you should also retrieve their test data, as -you will need it when running glymur's test suite. +revision 2345 works. You should download the test data for the purpose +of configuring and running OpenJPEG's test suite, check their instructions for +all this. You should set the **OPJ_DATA_ROOT** environment variable for the +purpose of running Glymur's test suite. :: + + $ svn co http://openjpeg.googlecode.com/svn/data + $ export OPJ_DATA_ROOT=`pwd`/data Earlier versions of OpenJPEG through the 2.0 official release will **NOT** work and are not supported. -Be sure to have the following ports/RPMs/debs installed. - - * gcc - * gcc-c++ - * cmake - -You should build OpenJPEG with testing turned on. Consult the OpenJPEG -documentation on how to do this. If you use linux, make sure that you -have the following development packages installed - - * zlib-devel - * png-devel - * libtiff-devel - * lcms2-devel - -OS -== - -Mac OS X --------- -All the necessary packages are available to use glymur with Python 3.3 via -MacPorts. A minimal set of ports includes - - * python33 - * py33-numpy - * py33-distribute - -To run all the testing, one of the following combinations of ports must -additionally be installed: - - * py33-scikit-image and either py33-Pillow or freeimage - * py33-matplotlib and py33-Pillow - -Linux ------ - -Fedora 18 -''''''''' -Fedora 18 ships with Python 3.3, so all the necessary RPMs are available to -meet the minimal set of requirements. - - * python3 - * python3-numpy - * python3-setuptools - * python3-matplotlib (for running tests) - * python3-matplotlib-tk (or whichever matplotlib backend you prefer) - -A few tests still will not run, however, unless one of the following -combinations of RPMs / Python packages is installed. - - * scikit-image and either Pillow or freeimage - * matplotlib and Pillow - -The 2nd route is probably the easiest, so go ahead and install Pillow -via pip since Pillow is not yet available in Fedora 18 default -repositories:: - - $ yum install python3-devel # pip needs this in order to compile Pillow - $ yum install python3-pip - $ pip-python3 install Pillow --user - $ export PYTHONPATH=$HOME/.local/lib/python3.3/site-packages:$PYTHONPATH - -Fedora 17 -''''''''' -Fedora 17 ships with Python 3.2 and 2.7, so these steps detail working with -2.7. - -Required RPMs include:: - - * python - * python-mock - * python-pip - * python-setuptools - * numpy - -In addition, you must install contextlib2 via pip. - -A few tests still will not run, however, unless one of the following -combinations of RPMs / Python packages is installed. - - * scikit-image and either Pillow or freeimage - * matplotlib and Pillow - -scikit-image is not available in the Fedora 17 default repositories, but -it may be installed via pip:: - - $ yum install Cython # pip needs this in order to compile scikit-image - $ yum install python-devel # pip needs this in order to compile scikit-image - $ yum install freeimage # scikit-image uses this as a backend - $ yum install scipy # needed by scikit-image - $ pip-python install scikit-image --user - $ pip-python install contextlib2 --user - $ export PYTHONPATH=$HOME/.local/lib/python2.7/site-packages:$PYTHONPATH - -Windows -------- -Not currently supported. - -'''''''''''''''''''''''''''''''''''' -Installation, Testing, Configuration -'''''''''''''''''''''''''''''''''''' - -From this point forward, python3 will be referred to as just "python". - -Installation -============ - -You can install glymur via pip from the command line:: - - $ pip install glymur - -or manually retrieve the code from either of GitHub or PyPI - - * https://pypi.python.org/pypi/Glymur/ (stable releases) - * http://github.com/quintusdias/glymur (bleeding edge) - -and then unpack and install with:: - - $ python setup.py install --prefix=/install/path - -In addition to merely installing glymur, you should adjust your **$PATH** -environment variable in order to be able to use the *jp2dump* script from -the unix command line. - -:: - - $ export PYTHONPATH=/install/path/lib/python3.3/site-packages - $ export PATH=/install/path/bin:$PATH - - -Configuration -============= -glymur uses ctypes (for the moment) to access the openjp2 library, and +Glymur uses ctypes (for the moment) to access the openjp2 library, and because ctypes access libraries in a platform-dependent manner, it is -recommended that you create a configuration file to help glymur properly find +recommended that you create a configuration file to help Glymur properly find the openjp2 library. You may create the configuration file as follows:: - $ mkdir ~/.glymur - $ cd ~/.glymur + $ mkdir -p ~/.config/glymur + $ cd ~/.config/glymur $ cat > glymurrc << EOF > [library] > openjp2: /opt/openjp2-svn/lib/libopenjp2.so > EOF That assumes, of course, that you've installed OpenJPEG into /opt/openjp2-svn. +You may also replace **$HOME/.config** with **$XDG_CONFIG_HOME**. +Glymur Installation +=================== +You can retrieve the source for Glymur from either of -Testing -======= -In order to run all of the test suite, you will first need the OpenJPEG test -data that you previously retrieved. -Then you should set the **OPJ_DATA_ROOT** environment variable to -point to this directory, e.g. :: + * https://pypi.python.org/pypi/Glymur/ (stable releases) + * http://github.com/quintusdias/glymur (bleeding edge) - $ cd /somewhere/outside/the/glymur/unpacking/directory - $ svn co http://openjpeg.googlecode.com/svn/data - $ export OPJ_DATA_ROOT=`pwd`/data +but you should now be able to get a functional installation of Glymur via +pip :: -The test suite may then be run with:: + $ pip install glymur - $ cd /back/to/glymur/unpacking/directory - $ python -m unittest discover +This will install the **jp2dump** script, so you should adjust your **$PATH** +to take advantage of it. For example, if you install with pip's +`--user` option on linux :: -Quite a few tests are currently skipped. These include tests whose -OpenJPEG counterparts are already failing, and others which do pass but -still produce heaps of output on stderr. Rather than let this swamp -the signal (that most of the tests are actually passing), they've been -filtered out for now. There are also more skipped tests on Python 2.7 -than on Python 3.3. The important part is whether or not any test -errors are reported at the end. + $ export PYTHONPATH=$HOME/.local/lib/python3.3/site-packages + $ export PATH=$HOME/.local/bin:$PATH diff --git a/glymur/__init__.py b/glymur/__init__.py index 3525b6a..473bb65 100644 --- a/glymur/__init__.py +++ b/glymur/__init__.py @@ -7,8 +7,8 @@ def _glymurrc_fname(): Search order: 1) current working directory - 2) environ var GLYMURCONFIGDIR - 3) HOME/.glymur/glymurrc + 2) environ var XDG_CONFIG_HOME + 3) $HOME/.config/glymur/glymurrc """ # Current directory. @@ -62,15 +62,15 @@ def _config(): def _get_configdir(): """Return string representing the configuration directory. - Default is HOME/.glymur. You can override this with the GLYMURCONFIGDIR - environment variable. + Default is $HOME/.config/glymur. You can override this with the + XDG_CONFIG_HOME environment variable. """ - if 'GLYMURCONFIGDIR' in os.environ: - return os.environ['GLYMURCONFIGDIR'] + if 'XDG_CONFIG_HOME' in os.environ: + return os.path.join(os.environ['XDG_CONFIG_HOME'], 'glymur') if 'HOME' in os.environ: - return os.path.join(os.environ['HOME'], '.glymur') + return os.path.join(os.environ['HOME'], '.config', 'glymur') import warnings import sys @@ -88,4 +88,5 @@ _OPENJP2 = _config() from .jp2k import Jp2k from .jp2dump import jp2dump +from . import data from . import test diff --git a/glymur/codestream.py b/glymur/codestream.py index f433eca..04c208f 100644 --- a/glymur/codestream.py +++ b/glymur/codestream.py @@ -29,7 +29,7 @@ for _marker in range(0xff90, 0xff94): _valid_markers.append(_marker) -class Codestream: +class Codestream(object): """Container for codestream information. Attributes @@ -226,7 +226,7 @@ class Codestream: def __str__(self): msg = 'Codestream:\n' for segment in self.segment: - strs = segment.__str__() + strs = str(segment) # Add indentation strs = [(' ' + x + '\n') for x in strs.split('\n')] @@ -869,7 +869,7 @@ class Codestream: return TLMsegment(**kwargs) -class Segment: +class Segment(object): """Segment information. Attributes diff --git a/glymur/data/__init__.py b/glymur/data/__init__.py new file mode 100644 index 0000000..ff39c0e --- /dev/null +++ b/glymur/data/__init__.py @@ -0,0 +1,19 @@ +"""Shipping JPEG 2000 files. + +There is only one JP2 file at the moment, "nemo.jp2", converted from the +original JPEG photo of the aftermath of NEMO, the nor'easter that shutdown +Boston in February of 2013. +""" +import pkg_resources + + +def nemo(): + """Shortcut for specifying path to nemo.jp2. + + Returns + ------- + file : str + Platform-independent path to nemo.jp2. + """ + file = pkg_resources.resource_filename(__name__, "nemo.jp2") + return file diff --git a/glymur/jp2box.py b/glymur/jp2box.py index e8e7678..d4a44e9 100644 --- a/glymur/jp2box.py +++ b/glymur/jp2box.py @@ -4,14 +4,16 @@ References ---------- .. [JP2K15444-1i] International Organization for Standardication. ISO/IEC 15444-1:2004 - Information technology -- JPEG 2000 image coding system: - Core coding system" + Core coding system .. [JP2K15444-2m] International Organization for Standardication. ISO/IEC 15444-2:2004 - Information technology -- JPEG 2000 image coding system: Extensions """ +import collections import copy +import datetime import math import os import pprint @@ -31,7 +33,7 @@ from .core import _method_display from .core import _reader_requirements_display -class Jp2kBox: +class Jp2kBox(object): """Superclass for JPEG 2000 boxes. Attributes @@ -153,9 +155,9 @@ class ColourSpecificationBox(Jp2kBox): colorspace : int or None Enumerated colorspace, corresponds to one of 'sRGB', 'greyscale', or 'YCC'. If not None, then icc_profile must be None. - icc_profile : byte array or None - ICC profile according to ICC profile specification. If not None, then - color_space must be None. + icc_profile : dict + ICC profile header according to ICC profile specification. If + colorspace is not None, then icc_profile must be empty. """ def __init__(self, **kwargs): Jp2kBox.__init__(self, id='', longname='Colour Specification') @@ -174,8 +176,15 @@ class ColourSpecificationBox(Jp2kBox): x = _colorspace_map_display[self.colorspace] msg += '\n Colorspace: {0}'.format(x) else: - x = len(self.icc_profile) - msg += '\n ICC Profile: {0} bytes'.format(x) + # 2.7 has trouble pretty-printing ordered dicts so we just have + # to print as a regular dict in this case. + if sys.hexversion < 0x03000000: + icc_profile = dict(self.icc_profile) + else: + icc_profile = self.icc_profile + x = pprint.pformat(icc_profile) + lines = [' ' * 8 + y for y in x.split('\n')] + msg += '\n ICC Profile:\n{0}'.format('\n'.join(lines)) return msg @@ -221,12 +230,130 @@ class ColourSpecificationBox(Jp2kBox): # ICC profile kwargs['colorspace'] = None n = offset + length - f.tell() - kwargs['icc_profile'] = f.read(n) + if n < 128: + msg = "ICC profile header is corrupt, length is " + msg += "only {0} instead of 128." + warnings.warn(msg.format(n), UserWarning) + kwargs['icc_profile'] = None + else: + icc_profile = _ICCProfile(f.read(n)) + kwargs['icc_profile'] = icc_profile.header box = ColourSpecificationBox(**kwargs) return box +class _ICCProfile(object): + """ + """ + profile_class = {b'scnr': 'input device profile', + b'mntr': 'display device profile', + b'prtr': 'output device profile', + b'link': 'devicelink profile', + b'spac': 'colorspace conversion profile', + b'abst': 'abstract profile', + b'nmcl': 'name colour profile'} + + colour_space_dict = {b'XYZ ': 'XYZ', + b'Lab ': 'Lab', + b'Luv ': 'Luv', + b'YCbr': 'YCbCr', + b'Yxy ': 'Yxy', + b'RGB ': 'RGB', + b'GRAY': 'gray', + b'HSV ': 'hsv', + b'HLS ': 'hls', + b'CMYK': 'CMYK', + b'CMY ': 'cmy', + b'2CLR': '2colour', + b'3CLR': '3colour', + b'4CLR': '4colour', + b'5CLR': '5colour', + b'6CLR': '6colour', + b'7CLR': '7colour', + b'8CLR': '8colour', + b'9CLR': '9colour', + b'ACLR': '10colour', + b'BCLR': '11colour', + b'CCLR': '12colour', + b'DCLR': '13colour', + b'ECLR': '14colour', + b'FCLR': '15colour'} + + rendering_intent_dict = {0: 'perceptual', + 1: 'media-relative colorimetric', + 2: 'saturation', + 3: 'ICC-absolute colorimetric'} + + def __init__(self, buffer): + self._raw_buffer = buffer + header = collections.OrderedDict() + + data = struct.unpack('>IIBB', self._raw_buffer[0:10]) + header['Size'] = data[0] + header['Preferred CMM Type'] = data[1] + major = data[2] + minor = (data[3] & 0xf0) >> 4 + bugfix = (data[3] & 0x0f) + header['Version'] = '{0}.{1}.{2}'.format(major, minor, bugfix) + + header['Device Class'] = self.profile_class[self._raw_buffer[12:16]] + header['Color Space'] = self.colour_space_dict[self._raw_buffer[16:20]] + data = self.colour_space_dict[self._raw_buffer[20:24]] + header['Connection Space'] = data + + data = struct.unpack('>HHHHHH', self._raw_buffer[24:36]) + header['Datetime'] = datetime.datetime(*data) + header['File Signature'] = buffer[36:40].decode('utf-8') + if buffer[40:44] == b'\x00\x00\x00\x00': + header['Platform'] = 'unrecognized' + else: + header['Platform'] = buffer[40:44].decode('utf-8') + + x, = struct.unpack('>I', buffer[44:48]) + y = 'embedded, ' if x & 0x01 else 'not embedded, ' + y += 'cannot ' if x & 0x02 else 'can ' + y += 'be used independently' + header['Flags'] = y + + header['Device Manufacturer'] = buffer[48:52].decode('utf-8') + if buffer[52:56] == b'\x00\x00\x00\x00': + device_model = '' + else: + device_model = buffer[52:56].decode('utf-8') + header['Device Model'] = device_model + + x, = struct.unpack('>Q', buffer[56:64]) + y = 'transparency, ' if x & 0x01 else 'reflective, ' + y += 'matte, ' if x & 0x02 else 'glossy, ' + y += 'negative ' if x & 0x04 else 'positive ' + y += 'media polarity, ' + y += 'black and white media' if x & 0x08 else 'color media' + header['Device Attributes'] = y + + x, = struct.unpack('>I', buffer[64:68]) + try: + header['Rendering Intent'] = self.rendering_intent_dict[x] + except KeyError: + header['Rendering Intent'] = 'unknown' + + data = struct.unpack('>iii', buffer[68:80]) + header['Illuminant'] = np.array(data, dtype=np.float64) / 65536 + + if buffer[80:84] == b'\x00\x00\x00\x00': + creator = 'unrecognized' + else: + creator = buffer[80:84].decode('utf-8') + header['Creator'] = creator + + if header['Version'][0] == '4': + header['Profile Id'] = buffer[84:100] + + # Final 27 bytes are reserved. + + self.header = header + + class ComponentDefinitionBox(Jp2kBox): """Container for component definition box information. @@ -405,7 +532,7 @@ class ContiguousCodestreamBox(Jp2kBox): msg = Jp2kBox.__str__(self) msg += '\n Main header:' for segment in self.main_header.segment: - segstr = segment.__str__() + segstr = str(segment) # Add indentation. strs = [('\n ' + x) for x in segstr.split('\n')] @@ -633,7 +760,7 @@ class AssociationBox(Jp2kBox): def __str__(self): msg = Jp2kBox.__str__(self) for box in self.box: - boxstr = box.__str__() + boxstr = str(box) # Add indentation. strs = [('\n ' + x) for x in boxstr.split('\n')] @@ -697,7 +824,7 @@ class JP2HeaderBox(Jp2kBox): def __str__(self): msg = Jp2kBox.__str__(self) for box in self.box: - boxstr = box.__str__() + boxstr = str(box) # Add indentation. strs = [('\n ' + x) for x in boxstr.split('\n')] @@ -1050,7 +1177,7 @@ class ResolutionBox(Jp2kBox): def __str__(self): msg = Jp2kBox.__str__(self) for box in self.box: - boxstr = box.__str__() + boxstr = str(box) # Add indentation. strs = [('\n ' + x) for x in boxstr.split('\n')] @@ -1427,7 +1554,7 @@ class UUIDInfoBox(Jp2kBox): msg = Jp2kBox.__str__(self) for box in self.box: - box_str = box.__str__() + box_str = str(box) # Add indentation. lst = [('\n ' + x) for x in box_str.split('\n')] @@ -1556,9 +1683,15 @@ class UUIDBox(Jp2kBox): more verbose description of the box. uuid : uuid.UUID 16-byte UUID - data : bytes or dictionary or ElementTree.Element - Vendor-specific UUID data. Exif UUIDs are interpreted as dictionaries. + data : bytes or dict or ElementTree.Element + Vendor-specific data. Exif UUIDs are interpreted as dictionaries. XMP UUIDs are interpreted as standard XML. + + References + ---------- + .. [XMP] International Organization for Standardication. ISO/IEC + 16684-1:2012 - Graphic technology -- Extensible metadata platform (XMP) + specification -- Part 1: Data model, serialization and core properties """ def __init__(self, **kwargs): Jp2kBox.__init__(self, id='', longname='UUID') @@ -1574,7 +1707,10 @@ class UUIDBox(Jp2kBox): uuid_data = _pretty_print_xml(self.data) elif self.uuid.bytes == b'JpgTiffExif->JP2': uuid_type = ' (Exif)' - uuid_data = '\n' + pprint.pformat(self.data) + # 2.7 has trouble pretty-printing ordered dicts, so print them + # as regular dicts. Not ideal, but at least it's good on 3.3+. + x = self.data if sys.hexversion >= 0x03000000 else dict(self.data) + uuid_data = '\n' + pprint.pformat(x) else: uuid_type = '' uuid_data = '{0} bytes'.format(len(self.data)) @@ -1625,7 +1761,7 @@ class UUIDBox(Jp2kBox): kwargs['data'] = ET.fromstring(text) elif kwargs['uuid'].bytes == b'JpgTiffExif->JP2': e = Exif(buffer) - d = {} + d = collections.OrderedDict() d['Image'] = e.exif_image d['Photo'] = e.exif_photo d['GPSInfo'] = e.exif_gpsinfo @@ -1637,7 +1773,7 @@ class UUIDBox(Jp2kBox): return box -class Exif: +class Exif(object): """ Attributes ---------- @@ -1690,7 +1826,7 @@ class Exif: self.exif_gpsinfo = gps.processed_ifd -class _Ifd: +class _Ifd(object): """ Attributes ---------- @@ -1720,7 +1856,7 @@ class _Ifd: def __init__(self, endian, buffer, offset): self.endian = endian self.buffer = buffer - self.processed_ifd = {} + self.processed_ifd = collections.OrderedDict() self.num_tags, = struct.unpack(endian + 'H', buffer[offset:offset + 2]) @@ -1728,7 +1864,7 @@ class _Ifd: fmt = self.endian + 'HHII' * self.num_tags ifd_buffer = buffer[offset + 2:offset + 2 + self.num_tags * 12] data = struct.unpack(fmt, ifd_buffer) - self.raw_ifd = {} + self.raw_ifd = collections.OrderedDict() for j, tag in enumerate(data[0::4]): # The offset to the tag offset/payload is the offset to the IFD # plus 2 bytes for the number of tags plus 12 bytes for each diff --git a/glymur/jp2k.py b/glymur/jp2k.py index a42e291..b09271e 100644 --- a/glymur/jp2k.py +++ b/glymur/jp2k.py @@ -87,10 +87,10 @@ class Jp2k(Jp2kBox): metadata = ['File: ' + os.path.basename(self.filename)] if len(self.box) > 0: for box in self.box: - metadata.append(box.__str__()) + metadata.append(str(box)) else: c = self.get_codestream() - metadata.append(c.__str__()) + metadata.append(str(c)) return '\n'.join(metadata) def _parse(self): @@ -138,7 +138,7 @@ class Jp2k(Jp2kBox): f.seek(0) self.box = self._parse_superbox(f) - def write(self, data, cratios=None, eph=False, psnr=None, numres=None, + def write(self, img_array, cratios=None, eph=False, psnr=None, numres=None, cbsize=None, psizes=None, grid_offset=None, sop=False, subsam=None, tilesize=None, prog=None, modesw=None, colorspace=None, verbose=False): @@ -150,7 +150,7 @@ class Jp2k(Jp2kBox): Parameters ---------- - data : array + img_array : ndarray Image data to be written to file. callbacks : bool, optional If true, enable default info handler such that INFO messages @@ -197,8 +197,7 @@ class Jp2k(Jp2kBox): Examples -------- >>> import glymur - >>> import pkg_resources as pkg - >>> jfile = pkg.resource_filename(glymur.__name__, "data/nemo.jp2") + >>> jfile = glymur.data.nemo() >>> jp2 = glymur.Jp2k(jfile) >>> data = jp2.read(reduce=3) >>> from tempfile import NamedTemporaryFile @@ -307,19 +306,19 @@ class Jp2k(Jp2kBox): msg = "Cannot specify cratios and psnr together." raise RuntimeError(msg) - if data.ndim == 2: - numrows, numcols = data.shape - data = data.reshape(numrows, numcols, 1) - elif data.ndim == 3: + if img_array.ndim == 2: + numrows, numcols = img_array.shape + img_array = img_array.reshape(numrows, numcols, 1) + elif img_array.ndim == 3: pass else: - msg = "{0}D imagery is not allowed.".format(data.ndim) + msg = "{0}D imagery is not allowed.".format(img_array.ndim) raise IOError(msg) - numrows, numcols, num_comps = data.shape + numrows, numcols, num_comps = img_array.shape if colorspace is None: - if data.shape[2] == 1 or data.shape[2] == 2: + if img_array.shape[2] == 1 or img_array.shape[2] == 2: colorspace = opj2._CLRSPC_GRAY else: # No YCC unless specifically told to do so. @@ -331,15 +330,15 @@ class Jp2k(Jp2kBox): if colorspace not in ('rgb', 'grey', 'gray'): msg = 'Invalid colorspace "{0}"'.format(colorspace) raise IOError(msg) - elif colorspace == 'rgb' and data.shape[2] < 3: + elif colorspace == 'rgb' and img_array.shape[2] < 3: msg = 'RGB colorspace requires at least 3 components.' raise IOError(msg) else: colorspace = _cspace_map[colorspace] - if data.dtype == np.uint8: + if img_array.dtype == np.uint8: comp_prec = 8 - elif data.dtype == np.uint16: + elif img_array.dtype == np.uint16: comp_prec = 16 else: raise RuntimeError("unhandled datatype") @@ -368,7 +367,7 @@ class Jp2k(Jp2kBox): # Stage the image data to the openjpeg data structure. for k in range(0, num_comps): - layer = np.ascontiguousarray(data[:, :, k], dtype=np.int32) + layer = np.ascontiguousarray(img_array[:, :, k], dtype=np.int32) dest = image.contents.comps[k].data src = layer.ctypes.data ctypes.memmove(dest, src, layer.nbytes) @@ -407,7 +406,8 @@ class Jp2k(Jp2kBox): layer : int, optional Number of quality layer to decode. reduce : int, optional - Factor by which to reduce output resolution. + Factor by which to reduce output resolution. Use -1 to get the + lowest resolution thumbnail. area : tuple, optional Specifies decoding image area, (first_row, first_col, last_row, last_col) @@ -418,7 +418,7 @@ class Jp2k(Jp2kBox): Returns ------- - result : array + img_array : ndarray The image data. Raises @@ -429,10 +429,17 @@ class Jp2k(Jp2kBox): Examples -------- >>> import glymur - >>> import pkg_resources as pkg - >>> jfile = pkg.resource_filename(glymur.__name__, "data/nemo.jp2") + >>> jfile = glymur.data.nemo() >>> jp = glymur.Jp2k(jfile) - >>> data = jp.read(reduce=1) + >>> image = jp.read() + >>> image.shape + (1456, 2592, 3) + + Read the lowest resolution thumbnail. + + >>> thumbnail = jp.read(reduce=-1) + >>> thumbnail.shape + (46, 81, 3) """ # Check for differing subsample factors. codestream = self.get_codestream(header_only=True) @@ -442,18 +449,18 @@ class Jp2k(Jp2kBox): msg = "Components must all have the same subsampling factors." raise IOError(msg) - data = self._read_common(reduce=reduce, - layer=layer, - area=area, - tile=tile, - verbose=verbose, - as_bands=False) + img_array = self._read_common(reduce=reduce, + layer=layer, + area=area, + tile=tile, + verbose=verbose, + as_bands=False) - if data.shape[2] == 1: - data = data.view() - data.shape = data.shape[0:2] + if img_array.shape[2] == 1: + img_array = img_array.view() + img_array.shape = img_array.shape[0:2] - return data + return img_array def _read_common(self, reduce=0, layer=0, area=None, tile=None, verbose=False, as_bands=False): @@ -477,7 +484,7 @@ class Jp2k(Jp2kBox): Returns ------- - data : list or array + img_array : ndarray The individual image components or a single array. """ dparam = opj2._set_default_decoder_parameters() @@ -490,6 +497,12 @@ class Jp2k(Jp2kBox): dparam.decod_format = self._codec_format dparam.cp_layer = layer + + if reduce == -1: + # Get the lowest resolution thumbnail. + codestream = self.get_codestream() + reduce = codestream.segment[2].SPcod[4] + dparam.cp_reduce = reduce if area is not None: if area[0] < 0 or area[1] < 0: @@ -618,8 +631,7 @@ class Jp2k(Jp2kBox): Examples -------- >>> import glymur - >>> import pkg_resources as pkg - >>> jfile = pkg.resource_filename(glymur.__name__, "data/nemo.jp2") + >>> jfile = glymur.data.nemo() >>> jp = glymur.Jp2k(jfile) >>> components_lst = jp.read_bands(reduce=1) """ @@ -648,8 +660,7 @@ class Jp2k(Jp2kBox): Examples -------- >>> import glymur - >>> import pkg_resources as pkg - >>> jfile = pkg.resource_filename(glymur.__name__, "data/nemo.jp2") + >>> jfile = glymur.data.nemo() >>> jp = glymur.Jp2k(jfile) >>> codestream = jp.get_codestream() >>> print(codestream.segment[1]) diff --git a/glymur/lib/test/__init__.py b/glymur/lib/test/__init__.py index 9f68aec..5aea3ab 100644 --- a/glymur/lib/test/__init__.py +++ b/glymur/lib/test/__init__.py @@ -1 +1 @@ -from .test_openjp2 import TestOpenJP2 as openjp2 +#from .test_openjp2 import TestOpenJP2 as openjp2 diff --git a/glymur/lib/test/test_openjp2.py b/glymur/lib/test/test_openjp2.py index 0bee92f..90a5f08 100644 --- a/glymur/lib/test/test_openjp2.py +++ b/glymur/lib/test/test_openjp2.py @@ -12,12 +12,14 @@ import numpy as np import glymur -# Doc tests should be run as well. def load_tests(loader, tests, ignore): - tests.addTests(doctest.DocTestSuite('glymur.lib.openjp2')) + if glymur.lib.openjp2._OPENJP2 is not None: + tests.addTests(doctest.DocTestSuite('glymur.lib.openjp2')) return tests +@unittest.skipIf(glymur.lib.openjp2._OPENJP2 is None, + "Missing openjp2 library.") class TestOpenJP2(unittest.TestCase): def setUp(self): diff --git a/glymur/test/__init__.py b/glymur/test/__init__.py index 9677af5..1e19d88 100644 --- a/glymur/test/__init__.py +++ b/glymur/test/__init__.py @@ -1,6 +1,7 @@ from .test_callbacks import TestCallbacks as callbacks from .test_codestream import TestCodestream as codestream from .test_jp2k import TestJp2k as jp2k +from .test_icc import TestICC as icc from .test_printing import TestPrinting as printing from .test_opj_suite import TestSuite as suite from .test_opj_suite_write import TestSuiteWrite as suitew diff --git a/glymur/test/test_callbacks.py b/glymur/test/test_callbacks.py index aae4ddc..9a1250b 100644 --- a/glymur/test/test_callbacks.py +++ b/glymur/test/test_callbacks.py @@ -12,14 +12,9 @@ else: import glymur -try: - data_root = os.environ['OPJ_DATA_ROOT'] -except KeyError: - data_root = None -except: - raise - +@unittest.skipIf(glymur.lib.openjp2._OPENJP2 is None, + "Missing openjp2 library.") class TestCallbacks(unittest.TestCase): def setUp(self): diff --git a/glymur/test/test_icc.py b/glymur/test/test_icc.py new file mode 100644 index 0000000..b989bbe --- /dev/null +++ b/glymur/test/test_icc.py @@ -0,0 +1,73 @@ +import datetime +import os +import struct +import sys +import tempfile +import unittest +import warnings +from xml.etree import cElementTree as ET + +import numpy as np +import pkg_resources + +from glymur import Jp2k +import glymur + +try: + data_root = os.environ['OPJ_DATA_ROOT'] +except KeyError: + data_root = None +except: + raise + + +@unittest.skipIf(data_root is None, + "OPJ_DATA_ROOT environment variable not set") +class TestICC(unittest.TestCase): + + def setUp(self): + pass + + def tearDown(self): + pass + + def test_file5(self): + filename = os.path.join(data_root, 'input/conformance/file5.jp2') + j = Jp2k(filename) + profile = j.box[3].box[1].icc_profile + self.assertEqual(profile['Size'], 546) + self.assertEqual(profile['Preferred CMM Type'], 0) + self.assertEqual(profile['Version'], '2.2.0') + self.assertEqual(profile['Device Class'], 'input device profile') + self.assertEqual(profile['Color Space'], 'RGB') + self.assertEqual(profile['Datetime'], + datetime.datetime(2001, 8, 30, 13, 32, 37)) + self.assertEqual(profile['File Signature'], 'acsp') + self.assertEqual(profile['Platform'], 'unrecognized') + self.assertEqual(profile['Flags'], + 'embedded, can be used independently') + + self.assertEqual(profile['Device Manufacturer'], 'KODA') + self.assertEqual(profile['Device Model'], 'ROMM') + + self.assertEqual(profile['Device Attributes'], + 'reflective, glossy, positive media polarity, ' + + 'color media') + self.assertEqual(profile['Rendering Intent'], 'perceptual') + + np.testing.assert_almost_equal(profile['Illuminant'], + (0.964203, 1.000000, 0.824905), + decimal=6) + + self.assertEqual(profile['Creator'], 'JPEG') + + @unittest.skipIf(sys.hexversion < 0x03020000, + "Uses features introduced in 3.2.") + def test_invalid_profile_header(self): + jfile = os.path.join(data_root, + 'input/nonregression/orb-blue10-lin-jp2.jp2') + with self.assertWarns(UserWarning) as cw: + j = Jp2k(jfile) + +if __name__ == "__main__": + unittest.main() diff --git a/glymur/test/test_jp2k.py b/glymur/test/test_jp2k.py index 5e9ab9b..3c25cca 100644 --- a/glymur/test/test_jp2k.py +++ b/glymur/test/test_jp2k.py @@ -34,26 +34,19 @@ except: # Doc tests should be run as well. def load_tests(loader, tests, ignore): - tests.addTests(doctest.DocTestSuite('glymur.jp2k')) + if glymur.lib.openjp2._OPENJP2 is not None: + tests.addTests(doctest.DocTestSuite('glymur.jp2k')) return tests -@contextlib.contextmanager -def chdir(dirname=None): - curdir = os.getcwd() - try: - if dirname is not None: - os.chdir(dirname) - yield - finally: - os.chdir(curdir) - - +@unittest.skipIf(glymur.lib.openjp2._OPENJP2 is None, + "Missing openjp2 library.") class TestJp2k(unittest.TestCase): @classmethod def setUpClass(cls): - # Setup a JP2 file with a bad XML box. + # Setup a JP2 file with a bad XML box. We only need to do this once + # per class rather than once per test. jp2file = pkg_resources.resource_filename(glymur.__name__, "data/nemo.jp2") with tempfile.NamedTemporaryFile(suffix='.jp2', delete=False) as tfile: @@ -92,10 +85,18 @@ class TestJp2k(unittest.TestCase): "Uses features introduced in 3.2.") def test_invalid_xml_box_warning(self): # Should be able to recover from xml box with bad xml. - # Just verify that a warning is issued on 3.2+ + # Just verify that a warning is issued on 3.3+ with self.assertWarns(UserWarning) as cw: jp2k = Jp2k(self._bad_xml_file) + def test_reduce_max(self): + # Verify that reduce=-1 gets us the lowest resolution image + j = Jp2k(self.jp2file) + thumbnail1 = j.read(reduce=-1) + thumbnail2 = j.read(reduce=5) + np.testing.assert_array_equal(thumbnail1, thumbnail2) + self.assertEqual(thumbnail1.shape, (46, 81, 3)) + def test_invalid_xml_box(self): # Should be able to recover from xml box with bad xml. with warnings.catch_warnings(): @@ -598,13 +599,15 @@ class TestJp2k(unittest.TestCase): def test_config_file_via_environ(self): """Verify that we can read a configuration file set via environ var.""" with tempfile.TemporaryDirectory() as tdir: - filename = os.path.join(tdir, 'glymurrc') + configdir = os.path.join(tdir, 'glymur') + os.mkdir(configdir) + filename = os.path.join(configdir, 'glymurrc') with open(filename, 'wb') as tfile: tfile.write('[library]\n'.encode()) line = 'openjp2: {0}\n'.format(glymur._OPENJP2._name) tfile.write(line.encode()) tfile.flush() - with patch.dict('os.environ', {'GLYMURCONFIGDIR': tdir}): + with patch.dict('os.environ', {'XDG_CONFIG_HOME': tdir}): imp.reload(glymur) j = Jp2k(self.jp2file) @@ -613,13 +616,15 @@ class TestJp2k(unittest.TestCase): def test_config_file_via_environ_is_wrong(self): # A non-existant library location should be rejected. with tempfile.TemporaryDirectory() as tdir: - fname = os.path.join(tdir, 'glymurrc') + configdir = os.path.join(tdir, 'glymur') + os.mkdir(configdir) + fname = os.path.join(configdir, 'glymurrc') with open(fname, 'w') as fp: with tempfile.NamedTemporaryFile(suffix='.dylib') as tfile: fp.write('[library]\n') fp.write('openjp2: {0}.not.there\n'.format(tfile.name)) fp.flush() - with patch.dict('os.environ', {'GLYMURCONFIGDIR': tdir}): + with patch.dict('os.environ', {'XDG_CONFIG_HOME': tdir}): # Misconfigured new configuration file should # be rejected. with self.assertWarns(UserWarning) as cw: @@ -631,7 +636,7 @@ class TestJp2k(unittest.TestCase): # Verify that we error out properly if the configuration file # specified via environment variable is not found. with tempfile.TemporaryDirectory() as tdir: - with patch.dict('os.environ', {'GLYMURCONFIGDIR': tdir}): + with patch.dict('os.environ', {'XDG_CONFIG_HOME': tdir}): # Misconfigured new configuration file should # be rejected. with self.assertWarns(UserWarning) as cw: @@ -640,7 +645,7 @@ class TestJp2k(unittest.TestCase): @unittest.skipIf(sys.hexversion < 0x03020000, "Uses features introduced in 3.2.") def test_home_dir_missing_config_dir(self): - # Verify no exception is raised if $HOME is missing .glymur directory. + # Verify no exception is raised if $HOME is missing .config directory. with tempfile.TemporaryDirectory() as tdir: with patch.dict('os.environ', {'HOME': tdir}): # Misconfigured new configuration file should @@ -648,6 +653,24 @@ class TestJp2k(unittest.TestCase): with self.assertWarns(UserWarning) as cw: imp.reload(glymur) + @unittest.skipIf(sys.hexversion < 0x03020000, + "Uses features introduced in 3.2.") + def test_home_dir_missing_glymur_rc_dir(self): + # Should warn but not error if $HOME/.config but no glymurrc dir. + with tempfile.TemporaryDirectory() as tdir: + # We need the subdirectory to be specifically named as ".config" + # in order for this test to work. A specifically-named temporary + # directory does not seem to be possible, so try to symlink it. + # Supposedly the symlink gets cleaned up with tdir gets cleaned up. + with tempfile.TemporaryDirectory(suffix=".config", dir=tdir) \ + as tdir_config: + os.symlink(tdir_config, os.path.join(tdir, '.config')) + with patch.dict('os.environ', {'HOME': tdir}): + # Misconfigured new configuration file should + # be rejected. + with self.assertWarns(UserWarning) as cw: + imp.reload(glymur) + def test_xmp_attribute(self): # Verify that we can read the XMP packet in our shipping example file. j = Jp2k(self.jp2file) diff --git a/glymur/test/test_opj_suite.py b/glymur/test/test_opj_suite.py index 15913e2..9a7efde 100644 --- a/glymur/test/test_opj_suite.py +++ b/glymur/test/test_opj_suite.py @@ -120,6 +120,8 @@ def read_pgx(pgx_file): return(data.byteswap(swapbytes)) +@unittest.skipIf(glymur.lib.openjp2._OPENJP2 is None, + "Missing openjp2 library.") @unittest.skipIf(data_root is None, "OPJ_DATA_ROOT environment variable not set") class TestSuite(unittest.TestCase): @@ -875,6 +877,725 @@ class TestSuite(unittest.TestCase): jpdata = jp2k.read() self.assertEqual(jpdata.shape, (512, 768, 3)) + def test_NR_DEC_Bretagne2_j2k_1_decode(self): + jfile = os.path.join(data_root, + 'input/nonregression/Bretagne2.j2k') + jp2 = Jp2k(jfile) + data = jp2.read() + self.assertTrue(True) + + def test_NR_DEC__00042_j2k_2_decode(self): + jfile = os.path.join(data_root, + 'input/nonregression/_00042.j2k') + jp2 = Jp2k(jfile) + data = jp2.read() + self.assertTrue(True) + + @unittest.skip("fprintf stderr output in r2343.") + def test_NR_DEC_123_j2c_3_decode(self): + jfile = os.path.join(data_root, + 'input/nonregression/123.j2c') + jp2 = Jp2k(jfile) + data = jp2.read() + self.assertTrue(True) + + @unittest.skipIf(sys.hexversion < 0x03020000, + "Uses features introduced in 3.2.") + def test_NR_DEC_broken_jp2_4_decode(self): + jfile = os.path.join(data_root, + 'input/nonregression/broken.jp2') + with self.assertWarns(UserWarning) as cw: + # colr box has bad length. + jp2 = Jp2k(jfile) + with self.assertRaises(IOError): + data = jp2.read() + self.assertTrue(True) + + def test_NR_DEC_broken2_jp2_5_decode(self): + jfile = os.path.join(data_root, + 'input/nonregression/broken2.jp2') + with self.assertRaises(IOError): + data = Jp2k(jfile).read() + self.assertTrue(True) + + @unittest.skipIf(sys.hexversion < 0x03020000, + "Uses features introduced in 3.2.") + def test_NR_DEC_broken3_jp2_6_decode(self): + jfile = os.path.join(data_root, + 'input/nonregression/broken3.jp2') + with self.assertWarns(UserWarning) as cw: + # colr box has bad length. + j = Jp2k(jfile) + + with self.assertRaises(IOError) as ce: + d = j.read() + + def test_NR_DEC_broken4_jp2_7_decode(self): + jfile = os.path.join(data_root, + 'input/nonregression/broken4.jp2') + with self.assertRaises(IOError): + data = Jp2k(jfile).read() + self.assertTrue(True) + + @unittest.skip("fprintf stderr output in r2343.") + def test_NR_DEC_bug_j2c_8_decode(self): + jfile = os.path.join(data_root, + 'input/nonregression/bug.j2c') + data = Jp2k(jfile).read() + self.assertTrue(True) + + def test_NR_DEC_buxI_j2k_9_decode(self): + jfile = os.path.join(data_root, + 'input/nonregression/buxI.j2k') + data = Jp2k(jfile).read() + self.assertTrue(True) + + def test_NR_DEC_buxR_j2k_10_decode(self): + jfile = os.path.join(data_root, + 'input/nonregression/buxR.j2k') + data = Jp2k(jfile).read() + self.assertTrue(True) + + def test_NR_DEC_Cannotreaddatawithnosizeknown_j2k_11_decode(self): + relpath = 'input/nonregression/Cannotreaddatawithnosizeknown.j2k' + jfile = os.path.join(data_root, relpath) + data = Jp2k(jfile).read() + self.assertTrue(True) + + def test_NR_DEC_cthead1_j2k_12_decode(self): + jfile = os.path.join(data_root, + 'input/nonregression/cthead1.j2k') + data = Jp2k(jfile).read() + self.assertTrue(True) + + def test_NR_DEC_CT_Phillips_JPEG2K_Decompr_Problem_j2k_13_decode(self): + relpath = 'input/nonregression/CT_Phillips_JPEG2K_Decompr_Problem.j2k' + jfile = os.path.join(data_root, relpath) + data = Jp2k(jfile).read() + self.assertTrue(True) + + @unittest.skip("fprintf stderr output in r2343.") + def test_NR_DEC_illegalcolortransform_j2k_14_decode(self): + # Stream too short, expected SOT. + jfile = os.path.join(data_root, + 'input/nonregression/illegalcolortransform.j2k') + data = Jp2k(jfile).read() + self.assertTrue(True) + + def test_NR_DEC_j2k32_j2k_15_decode(self): + jfile = os.path.join(data_root, + 'input/nonregression/j2k32.j2k') + data = Jp2k(jfile).read() + self.assertTrue(True) + + def test_NR_DEC_kakadu_v4_4_openjpegv2_broken_j2k_16_decode(self): + relpath = 'input/nonregression/kakadu_v4-4_openjpegv2_broken.j2k' + jfile = os.path.join(data_root, relpath) + data = Jp2k(jfile).read() + self.assertTrue(True) + + def test_NR_DEC_MarkerIsNotCompliant_j2k_17_decode(self): + jfile = os.path.join(data_root, + 'input/nonregression/MarkerIsNotCompliant.j2k') + data = Jp2k(jfile).read() + self.assertTrue(True) + + def test_NR_DEC_Marrin_jp2_18_decode(self): + jfile = os.path.join(data_root, + 'input/nonregression/Marrin.jp2') + data = Jp2k(jfile).read() + self.assertTrue(True) + + def test_NR_DEC_merged_jp2_19_decode(self): + jfile = os.path.join(data_root, + 'input/nonregression/merged.jp2') + data = Jp2k(jfile).read_bands() + self.assertTrue(True) + + def test_NR_DEC_movie_00000_j2k_20_decode(self): + jfile = os.path.join(data_root, + 'input/nonregression/movie_00000.j2k') + data = Jp2k(jfile).read() + self.assertTrue(True) + + def test_NR_DEC_movie_00001_j2k_21_decode(self): + jfile = os.path.join(data_root, + 'input/nonregression/movie_00001.j2k') + data = Jp2k(jfile).read() + self.assertTrue(True) + + def test_NR_DEC_movie_00002_j2k_22_decode(self): + jfile = os.path.join(data_root, + 'input/nonregression/movie_00002.j2k') + data = Jp2k(jfile).read() + self.assertTrue(True) + + def test_NR_DEC_orb_blue_lin_j2k_j2k_23_decode(self): + jfile = os.path.join(data_root, + 'input/nonregression/orb-blue10-lin-j2k.j2k') + data = Jp2k(jfile).read() + self.assertTrue(True) + + def test_NR_DEC_orb_blue_win_j2k_j2k_24_decode(self): + jfile = os.path.join(data_root, + 'input/nonregression/orb-blue10-win-j2k.j2k') + data = Jp2k(jfile).read() + self.assertTrue(True) + + def test_NR_DEC_orb_blue_lin_jp2_25_decode(self): + jfile = os.path.join(data_root, + 'input/nonregression/orb-blue10-lin-jp2.jp2') + with warnings.catch_warnings(): + # This file has an invalid ICC profile + warnings.simplefilter("ignore") + data = Jp2k(jfile).read() + self.assertTrue(True) + + def test_NR_DEC_orb_blue_win_jp2_26_decode(self): + jfile = os.path.join(data_root, + 'input/nonregression/orb-blue10-win-jp2.jp2') + data = Jp2k(jfile).read() + self.assertTrue(True) + + def test_NR_DEC_relax_jp2_27_decode(self): + jfile = os.path.join(data_root, + 'input/nonregression/relax.jp2') + data = Jp2k(jfile).read() + self.assertTrue(True) + + def test_NR_DEC_test_lossless_j2k_28_decode(self): + jfile = os.path.join(data_root, + 'input/nonregression/test_lossless.j2k') + data = Jp2k(jfile).read() + self.assertTrue(True) + + def test_NR_DEC_text_GBR_jp2_29_decode(self): + jfile = os.path.join(data_root, + 'input/nonregression/text_GBR.jp2') + data = Jp2k(jfile).read() + self.assertTrue(True) + + def test_NR_DEC_pacs_ge_j2k_30_decode(self): + jfile = os.path.join(data_root, + 'input/nonregression/pacs.ge.j2k') + data = Jp2k(jfile).read() + self.assertTrue(True) + + def test_NR_DEC_kodak_2layers_lrcp_j2c_31_decode(self): + jfile = os.path.join(data_root, + 'input/nonregression/kodak_2layers_lrcp.j2c') + data = Jp2k(jfile).read() + self.assertTrue(True) + + def test_NR_DEC_kodak_2layers_lrcp_j2c_32_decode(self): + jfile = os.path.join(data_root, + 'input/nonregression/kodak_2layers_lrcp.j2c') + data = Jp2k(jfile).read(layer=2) + self.assertTrue(True) + + def test_NR_DEC_issue104_jpxstream_jp2_33_decode(self): + jfile = os.path.join(data_root, + 'input/nonregression/issue104_jpxstream.jp2') + data = Jp2k(jfile).read() + self.assertTrue(True) + + def test_NR_DEC_mem_b2ace68c_1381_jp2_34_decode(self): + jfile = os.path.join(data_root, + 'input/nonregression/mem-b2ace68c-1381.jp2') + with warnings.catch_warnings(): + # This file has a bad pclr box, we test for this elsewhere. + warnings.simplefilter("ignore") + j = Jp2k(jfile) + data = j.read() + self.assertTrue(True) + + def test_NR_DEC_mem_b2b86b74_2753_jp2_35_decode(self): + jfile = os.path.join(data_root, + 'input/nonregression/mem-b2b86b74-2753.jp2') + data = Jp2k(jfile).read() + self.assertTrue(True) + + def test_NR_DEC_gdal_fuzzer_unchecked_num_resolutions_jp2_36_decode(self): + f = 'input/nonregression/gdal_fuzzer_unchecked_numresolutions.jp2' + jfile = os.path.join(data_root, f) + with warnings.catch_warnings(): + warnings.simplefilter("ignore") + j = Jp2k(jfile) + with self.assertRaises(IOError): + data = j.read() + + def test_NR_DEC_jp2_36_decode(self): + lst = ('input', + 'nonregression', + 'gdal_fuzzer_assert_in_opj_j2k_read_SQcd_SQcc.patch.jp2') + jfile = os.path.join(data_root, '/'.join(lst)) + with warnings.catch_warnings(): + warnings.simplefilter("ignore") + j = Jp2k(jfile) + with self.assertRaises(IOError): + data = j.read() + + def test_NR_DEC_gdal_fuzzer_check_number_of_tiles_jp2_38_decode(self): + relpath = 'input/nonregression/gdal_fuzzer_check_number_of_tiles.jp2' + jfile = os.path.join(data_root, relpath) + with warnings.catch_warnings(): + warnings.simplefilter("ignore") + j = Jp2k(jfile) + with self.assertRaises(IOError): + data = j.read() + + def test_NR_DEC_gdal_fuzzer_check_comp_dx_dy_jp2_39_decode(self): + relpath = 'input/nonregression/gdal_fuzzer_check_comp_dx_dy.jp2' + jfile = os.path.join(data_root, relpath) + with warnings.catch_warnings(): + warnings.simplefilter("ignore") + with self.assertRaises(IOError): + j = Jp2k(jfile).read() + + def test_NR_DEC_file_409752_jp2_40_decode(self): + jfile = os.path.join(data_root, + 'input/nonregression/file409752.jp2') + with self.assertRaises(IOError): + data = Jp2k(jfile).read() + + @unittest.skipIf(sys.hexversion < 0x03020000, + "Uses features introduced in 3.2.") + def test_NR_DEC_issue188_beach_64bitsbox_jp2_41_decode(self): + # Has an 'XML ' box instead of 'xml '. Yes that is pedantic, but it + # really does deserve a warning. + relpath = 'input/nonregression/issue188_beach_64bitsbox.jp2' + jfile = os.path.join(data_root, relpath) + with self.assertWarns(UserWarning) as cw: + data = Jp2k(jfile).read() + + def test_NR_DEC_issue206_image_000_jp2_42_decode(self): + jfile = os.path.join(data_root, + 'input/nonregression/issue206_image-000.jp2') + data = Jp2k(jfile).read() + self.assertTrue(True) + + def test_NR_DEC_p1_04_j2k_43_decode(self): + jfile = os.path.join(data_root, 'input/conformance/p1_04.j2k') + jp2k = Jp2k(jfile) + ssdata = jp2k.read(area=(0, 0, 1024, 1024)) + odata = jp2k.read() + np.testing.assert_array_equal(ssdata, odata) + + def test_NR_DEC_p1_04_j2k_44_decode(self): + jfile = os.path.join(data_root, 'input/conformance/p1_04.j2k') + jp2k = Jp2k(jfile) + ssdata = jp2k.read(area=(640, 512, 768, 640)) + odata = jp2k.read() + np.testing.assert_array_equal(ssdata, odata[640:768, 512:640]) + + def test_NR_DEC_p1_04_j2k_45_decode(self): + jfile = os.path.join(data_root, 'input/conformance/p1_04.j2k') + jp2k = Jp2k(jfile) + ssdata = jp2k.read(area=(896, 896, 1024, 1024)) + odata = jp2k.read() + np.testing.assert_array_equal(ssdata, odata[896:1024, 896:1024]) + + def test_NR_DEC_p1_04_j2k_46_decode(self): + jfile = os.path.join(data_root, 'input/conformance/p1_04.j2k') + jp2k = Jp2k(jfile) + ssdata = jp2k.read(area=(500, 100, 800, 300)) + odata = jp2k.read() + np.testing.assert_array_equal(ssdata, odata[500:800, 100:300]) + + def test_NR_DEC_p1_04_j2k_47_decode(self): + jfile = os.path.join(data_root, 'input/conformance/p1_04.j2k') + jp2k = Jp2k(jfile) + ssdata = jp2k.read(area=(520, 260, 600, 360)) + odata = jp2k.read() + np.testing.assert_array_equal(ssdata, odata[520:600, 260:360]) + + def test_NR_DEC_p1_04_j2k_48_decode(self): + jfile = os.path.join(data_root, 'input/conformance/p1_04.j2k') + jp2k = Jp2k(jfile) + ssdata = jp2k.read(area=(520, 260, 660, 360)) + odata = jp2k.read() + np.testing.assert_array_equal(ssdata, odata[520:660, 260:360]) + + def test_NR_DEC_p1_04_j2k_49_decode(self): + jfile = os.path.join(data_root, 'input/conformance/p1_04.j2k') + jp2k = Jp2k(jfile) + ssdata = jp2k.read(area=(520, 360, 600, 400)) + odata = jp2k.read() + np.testing.assert_array_equal(ssdata, odata[520:600, 360:400]) + + def test_NR_DEC_p1_04_j2k_50_decode(self): + jfile = os.path.join(data_root, 'input/conformance/p1_04.j2k') + jp2k = Jp2k(jfile) + ssdata = jp2k.read(area=(0, 0, 1024, 1024), reduce=2) + odata = jp2k.read(reduce=2) + + np.testing.assert_array_equal(ssdata, odata[0:256, 0:256]) + + def test_NR_DEC_p1_04_j2k_51_decode(self): + jfile = os.path.join(data_root, 'input/conformance/p1_04.j2k') + jp2k = Jp2k(jfile) + ssdata = jp2k.read(area=(640, 512, 768, 640), reduce=2) + odata = jp2k.read(reduce=2) + np.testing.assert_array_equal(ssdata, odata[160:192, 128:160]) + + def test_NR_DEC_p1_04_j2k_52_decode(self): + jfile = os.path.join(data_root, 'input/conformance/p1_04.j2k') + jp2k = Jp2k(jfile) + ssdata = jp2k.read(area=(896, 896, 1024, 1024), reduce=2) + odata = jp2k.read(reduce=2) + np.testing.assert_array_equal(ssdata, odata[224:352, 224:352]) + + def test_NR_DEC_p1_04_j2k_53_decode(self): + jfile = os.path.join(data_root, 'input/conformance/p1_04.j2k') + jp2k = Jp2k(jfile) + ssdata = jp2k.read(area=(500, 100, 800, 300), reduce=2) + odata = jp2k.read(reduce=2) + np.testing.assert_array_equal(ssdata, odata[125:200, 25:75]) + + def test_NR_DEC_p1_04_j2k_54_decode(self): + jfile = os.path.join(data_root, 'input/conformance/p1_04.j2k') + jp2k = Jp2k(jfile) + ssdata = jp2k.read(area=(520, 260, 600, 360), reduce=2) + odata = jp2k.read(reduce=2) + np.testing.assert_array_equal(ssdata, odata[130:150, 65:90]) + + def test_NR_DEC_p1_04_j2k_55_decode(self): + jfile = os.path.join(data_root, 'input/conformance/p1_04.j2k') + jp2k = Jp2k(jfile) + ssdata = jp2k.read(area=(520, 260, 660, 360), reduce=2) + odata = jp2k.read(reduce=2) + np.testing.assert_array_equal(ssdata, odata[130:165, 65:90]) + + def test_NR_DEC_p1_04_j2k_56_decode(self): + jfile = os.path.join(data_root, 'input/conformance/p1_04.j2k') + jp2k = Jp2k(jfile) + ssdata = jp2k.read(area=(520, 360, 600, 400), reduce=2) + odata = jp2k.read(reduce=2) + np.testing.assert_array_equal(ssdata, odata[130:150, 90:100]) + + def test_NR_DEC_p1_04_j2k_57_decode(self): + jfile = os.path.join(data_root, 'input/conformance/p1_04.j2k') + jp2k = Jp2k(jfile) + with warnings.catch_warnings(): + warnings.simplefilter("ignore") + tdata = jp2k.read(tile=63) # last tile + odata = jp2k.read() + np.testing.assert_array_equal(tdata, odata[896:1024, 896:1024]) + + def test_NR_DEC_p1_04_j2k_58_decode(self): + jfile = os.path.join(data_root, 'input/conformance/p1_04.j2k') + jp2k = Jp2k(jfile) + with warnings.catch_warnings(): + warnings.simplefilter("ignore") + tdata = jp2k.read(tile=63, reduce=2) # last tile + odata = jp2k.read(reduce=2) + np.testing.assert_array_equal(tdata, odata[224:256, 224:256]) + + def test_NR_DEC_p1_04_j2k_59_decode(self): + jfile = os.path.join(data_root, 'input/conformance/p1_04.j2k') + jp2k = Jp2k(jfile) + with warnings.catch_warnings(): + warnings.simplefilter("ignore") + tdata = jp2k.read(tile=12) # 2nd row, 5th column + odata = jp2k.read() + np.testing.assert_array_equal(tdata, odata[128:256, 512:640]) + + def test_NR_DEC_p1_04_j2k_60_decode(self): + jfile = os.path.join(data_root, 'input/conformance/p1_04.j2k') + jp2k = Jp2k(jfile) + with warnings.catch_warnings(): + warnings.simplefilter("ignore") + tdata = jp2k.read(tile=12, reduce=1) # 2nd row, 5th column + odata = jp2k.read(reduce=1) + np.testing.assert_array_equal(tdata, odata[64:128, 256:320]) + + @unittest.skip("fprintf stderr output in r2343.") + def test_NR_DEC_p1_06_j2k_61_decode(self): + jfile = os.path.join(data_root, 'input/conformance/p1_06.j2k') + jp2k = Jp2k(jfile) + ssdata = jp2k.read(area=(0, 0, 12, 12)) + odata = jp2k.read() + np.testing.assert_array_equal(ssdata, odata[0:12, 0:12]) + + @unittest.skip("fprintf stderr output in r2343.") + def test_NR_DEC_p1_06_j2k_62_decode(self): + jfile = os.path.join(data_root, 'input/conformance/p1_06.j2k') + jp2k = Jp2k(jfile) + ssdata = jp2k.read(area=(1, 8, 8, 11)) + odata = jp2k.read() + np.testing.assert_array_equal(ssdata, odata[1:8, 8:11]) + + @unittest.skip("fprintf stderr output in r2343.") + def test_NR_DEC_p1_06_j2k_63_decode(self): + jfile = os.path.join(data_root, 'input/conformance/p1_06.j2k') + jp2k = Jp2k(jfile) + ssdata = jp2k.read(area=(9, 9, 12, 12)) + odata = jp2k.read() + np.testing.assert_array_equal(ssdata, odata[9:12, 9:12]) + + @unittest.skip("fprintf stderr output in r2343.") + def test_NR_DEC_p1_06_j2k_64_decode(self): + jfile = os.path.join(data_root, 'input/conformance/p1_06.j2k') + jp2k = Jp2k(jfile) + ssdata = jp2k.read(area=(10, 4, 12, 10)) + odata = jp2k.read() + np.testing.assert_array_equal(ssdata, odata[10:12, 4:10]) + + @unittest.skip("fprintf stderr output in r2343.") + def test_NR_DEC_p1_06_j2k_65_decode(self): + jfile = os.path.join(data_root, 'input/conformance/p1_06.j2k') + jp2k = Jp2k(jfile) + ssdata = jp2k.read(area=(3, 3, 9, 9)) + odata = jp2k.read() + np.testing.assert_array_equal(ssdata, odata[3:9, 3:9]) + + @unittest.skip("fprintf stderr output in r2343.") + def test_NR_DEC_p1_06_j2k_66_decode(self): + jfile = os.path.join(data_root, 'input/conformance/p1_06.j2k') + jp2k = Jp2k(jfile) + ssdata = jp2k.read(area=(4, 4, 7, 7)) + odata = jp2k.read() + np.testing.assert_array_equal(ssdata, odata[4:7, 4:7]) + + @unittest.skip("fprintf stderr output in r2343.") + def test_NR_DEC_p1_06_j2k_67_decode(self): + jfile = os.path.join(data_root, 'input/conformance/p1_06.j2k') + jp2k = Jp2k(jfile) + ssdata = jp2k.read(area=(4, 4, 5, 5)) + odata = jp2k.read() + np.testing.assert_array_equal(ssdata, odata[4:5, 4: 5]) + + @unittest.skip("fprintf stderr output in r2343.") + def test_NR_DEC_p1_06_j2k_68_decode(self): + jfile = os.path.join(data_root, 'input/conformance/p1_06.j2k') + jp2k = Jp2k(jfile) + ssdata = jp2k.read(area=(0, 0, 12, 12), reduce=1) + odata = jp2k.read(reduce=1) + np.testing.assert_array_equal(ssdata, odata[0:6, 0:6]) + + @unittest.skip("fprintf stderr output in r2343.") + def test_NR_DEC_p1_06_j2k_69_decode(self): + jfile = os.path.join(data_root, 'input/conformance/p1_06.j2k') + jp2k = Jp2k(jfile) + ssdata = jp2k.read(area=(1, 8, 8, 11), reduce=1) + self.assertEqual(ssdata.shape, (3, 2, 3)) + + def test_NR_DEC_p1_06_j2k_70_decode(self): + jfile = os.path.join(data_root, 'input/conformance/p1_06.j2k') + jp2k = Jp2k(jfile) + ssdata = jp2k.read(area=(9, 9, 12, 12), reduce=1) + self.assertEqual(ssdata.shape, (1, 1, 3)) + + def test_NR_DEC_p1_06_j2k_71_decode(self): + jfile = os.path.join(data_root, 'input/conformance/p1_06.j2k') + jp2k = Jp2k(jfile) + ssdata = jp2k.read(area=(10, 4, 12, 10), reduce=1) + self.assertEqual(ssdata.shape, (1, 3, 3)) + + def test_NR_DEC_p1_06_j2k_72_decode(self): + jfile = os.path.join(data_root, 'input/conformance/p1_06.j2k') + jp2k = Jp2k(jfile) + ssdata = jp2k.read(area=(3, 3, 9, 9), reduce=1) + self.assertEqual(ssdata.shape, (3, 3, 3)) + + def test_NR_DEC_p1_06_j2k_73_decode(self): + jfile = os.path.join(data_root, 'input/conformance/p1_06.j2k') + jp2k = Jp2k(jfile) + ssdata = jp2k.read(area=(4, 4, 7, 7), reduce=1) + self.assertEqual(ssdata.shape, (2, 2, 3)) + + def test_NR_DEC_p1_06_j2k_74_decode(self): + jfile = os.path.join(data_root, 'input/conformance/p1_06.j2k') + jp2k = Jp2k(jfile) + ssdata = jp2k.read(area=(4, 4, 5, 5), reduce=1) + self.assertEqual(ssdata.shape, (1, 1, 3)) + + def test_NR_DEC_p1_06_j2k_75_decode(self): + # Image size would be 0 x 0. + jfile = os.path.join(data_root, 'input/conformance/p1_06.j2k') + jp2k = Jp2k(jfile) + with self.assertRaises((IOError, OSError)) as ce: + ssdata = jp2k.read(area=(9, 9, 12, 12), reduce=2) + + @unittest.skip("fprintf stderr output in r2343.") + def test_NR_DEC_p1_06_j2k_76_decode(self): + jfile = os.path.join(data_root, 'input/conformance/p1_06.j2k') + jp2k = Jp2k(jfile) + fulldata = jp2k.read() + with warnings.catch_warnings(): + warnings.simplefilter("ignore") + tiledata = jp2k.read(tile=0) + np.testing.assert_array_equal(tiledata, fulldata[0:3, 0:3]) + + @unittest.skip("fprintf stderr output in r2343.") + def test_NR_DEC_p1_06_j2k_77_decode(self): + jfile = os.path.join(data_root, 'input/conformance/p1_06.j2k') + jp2k = Jp2k(jfile) + fulldata = jp2k.read() + with warnings.catch_warnings(): + warnings.simplefilter("ignore") + tiledata = jp2k.read(tile=5) + np.testing.assert_array_equal(tiledata, fulldata[3:6, 3:6]) + + @unittest.skip("fprintf stderr output in r2343.") + def test_NR_DEC_p1_06_j2k_78_decode(self): + jfile = os.path.join(data_root, 'input/conformance/p1_06.j2k') + jp2k = Jp2k(jfile) + fulldata = jp2k.read() + with warnings.catch_warnings(): + warnings.simplefilter("ignore") + tiledata = jp2k.read(tile=9) + np.testing.assert_array_equal(tiledata, fulldata[6:9, 3:6]) + + @unittest.skip("fprintf stderr output in r2343.") + def test_NR_DEC_p1_06_j2k_79_decode(self): + jfile = os.path.join(data_root, 'input/conformance/p1_06.j2k') + jp2k = Jp2k(jfile) + fulldata = jp2k.read() + with warnings.catch_warnings(): + warnings.simplefilter("ignore") + tiledata = jp2k.read(tile=15) + np.testing.assert_array_equal(tiledata, fulldata[9:12, 9:12]) + + @unittest.skip("fprintf stderr output in r2343.") + def test_NR_DEC_p1_06_j2k_80_decode(self): + # Just read the data, don't bother verifying. + jfile = os.path.join(data_root, 'input/conformance/p1_06.j2k') + jp2k = Jp2k(jfile) + with warnings.catch_warnings(): + warnings.simplefilter("ignore") + tiledata = jp2k.read(tile=0, reduce=2) + + @unittest.skip("fprintf stderr output in r2343.") + def test_NR_DEC_p1_06_j2k_81_decode(self): + # Just read the data, don't bother verifying. + jfile = os.path.join(data_root, 'input/conformance/p1_06.j2k') + jp2k = Jp2k(jfile) + with warnings.catch_warnings(): + warnings.simplefilter("ignore") + tiledata = jp2k.read(tile=5, reduce=2) + + @unittest.skip("fprintf stderr output in r2343.") + def test_NR_DEC_p1_06_j2k_82_decode(self): + # Just read the data, don't bother verifying. + jfile = os.path.join(data_root, 'input/conformance/p1_06.j2k') + jp2k = Jp2k(jfile) + with warnings.catch_warnings(): + warnings.simplefilter("ignore") + tiledata = jp2k.read(tile=9, reduce=2) + + @unittest.skip("fprintf stderr output in r2343.") + def test_NR_DEC_p1_06_j2k_83_decode(self): + # tile size is 3x3. Reducing two levels results in no data. + jfile = os.path.join(data_root, 'input/conformance/p1_06.j2k') + jp2k = Jp2k(jfile) + with warnings.catch_warnings(): + warnings.simplefilter("ignore") + with self.assertRaises((IOError, OSError)) as ce: + tiledata = jp2k.read(tile=15, reduce=2) + + @unittest.skip("fprintf stderr output in r2343.") + def test_NR_DEC_p1_06_j2k_84_decode(self): + # Just read the data, don't bother verifying. + jfile = os.path.join(data_root, 'input/conformance/p1_06.j2k') + jp2k = Jp2k(jfile) + data = jp2k.read(reduce=4) + + def test_NR_DEC_p0_04_j2k_85_decode(self): + jfile = os.path.join(data_root, 'input/conformance/p0_04.j2k') + jp2k = Jp2k(jfile) + ssdata = jp2k.read(area=(0, 0, 256, 256)) + fulldata = jp2k.read() + np.testing.assert_array_equal(fulldata[0:256, 0:256], ssdata) + + def test_NR_DEC_p0_04_j2k_86_decode(self): + jfile = os.path.join(data_root, 'input/conformance/p0_04.j2k') + jp2k = Jp2k(jfile) + ssdata = jp2k.read(area=(0, 128, 128, 256)) + fulldata = jp2k.read() + np.testing.assert_array_equal(fulldata[0:128, 128:256], ssdata) + + def test_NR_DEC_p0_04_j2k_87_decode(self): + jfile = os.path.join(data_root, 'input/conformance/p0_04.j2k') + jp2k = Jp2k(jfile) + ssdata = jp2k.read(area=(10, 50, 200, 120)) + fulldata = jp2k.read() + np.testing.assert_array_equal(fulldata[10:200, 50:120], ssdata) + + def test_NR_DEC_p0_04_j2k_88_decode(self): + jfile = os.path.join(data_root, 'input/conformance/p0_04.j2k') + jp2k = Jp2k(jfile) + ssdata = jp2k.read(area=(150, 10, 210, 190)) + fulldata = jp2k.read() + np.testing.assert_array_equal(fulldata[150:210, 10:190], ssdata) + + def test_NR_DEC_p0_04_j2k_89_decode(self): + jfile = os.path.join(data_root, 'input/conformance/p0_04.j2k') + jp2k = Jp2k(jfile) + ssdata = jp2k.read(area=(80, 100, 150, 200)) + fulldata = jp2k.read() + np.testing.assert_array_equal(fulldata[80:150, 100:200], ssdata) + + def test_NR_DEC_p0_04_j2k_90_decode(self): + jfile = os.path.join(data_root, 'input/conformance/p0_04.j2k') + jp2k = Jp2k(jfile) + ssdata = jp2k.read(area=(20, 150, 50, 200)) + fulldata = jp2k.read() + np.testing.assert_array_equal(fulldata[20:50, 150:200], ssdata) + + def test_NR_DEC_p0_04_j2k_91_decode(self): + jfile = os.path.join(data_root, 'input/conformance/p0_04.j2k') + jp2k = Jp2k(jfile) + ssdata = jp2k.read(area=(0, 0, 256, 256), reduce=2) + fulldata = jp2k.read(reduce=2) + np.testing.assert_array_equal(fulldata[0:64, 0:64], ssdata) + + def test_NR_DEC_p0_04_j2k_92_decode(self): + jfile = os.path.join(data_root, 'input/conformance/p0_04.j2k') + jp2k = Jp2k(jfile) + ssdata = jp2k.read(area=(0, 128, 128, 256), reduce=2) + fulldata = jp2k.read(reduce=2) + np.testing.assert_array_equal(fulldata[0:32, 32:64], ssdata) + + def test_NR_DEC_p0_04_j2k_93_decode(self): + jfile = os.path.join(data_root, 'input/conformance/p0_04.j2k') + jp2k = Jp2k(jfile) + ssdata = jp2k.read(area=(10, 50, 200, 120), reduce=2) + fulldata = jp2k.read(reduce=2) + np.testing.assert_array_equal(fulldata[3:50, 13:30], ssdata) + + def test_NR_DEC_p0_04_j2k_94_decode(self): + jfile = os.path.join(data_root, 'input/conformance/p0_04.j2k') + jp2k = Jp2k(jfile) + ssdata = jp2k.read(area=(150, 10, 210, 190), reduce=2) + fulldata = jp2k.read(reduce=2) + np.testing.assert_array_equal(fulldata[38:53, 3:48], ssdata) + + def test_NR_DEC_p0_04_j2k_95_decode(self): + jfile = os.path.join(data_root, 'input/conformance/p0_04.j2k') + jp2k = Jp2k(jfile) + ssdata = jp2k.read(area=(80, 100, 150, 200), reduce=2) + fulldata = jp2k.read(reduce=2) + np.testing.assert_array_equal(fulldata[20:38, 25:50], ssdata) + + def test_NR_DEC_p0_04_j2k_96_decode(self): + jfile = os.path.join(data_root, 'input/conformance/p0_04.j2k') + jp2k = Jp2k(jfile) + ssdata = jp2k.read(area=(20, 150, 50, 200), reduce=2) + fulldata = jp2k.read(reduce=2) + np.testing.assert_array_equal(fulldata[5:13, 38:50], ssdata) + + +@unittest.skipIf(data_root is None, + "OPJ_DATA_ROOT environment variable not set") +class TestSuiteDump(unittest.TestCase): + + def setUp(self): + pass + + def tearDown(self): + pass + def test_NR_p0_01_dump(self): jfile = os.path.join(data_root, 'input/conformance/p0_01.j2k') c = Jp2k(jfile).get_codestream(header_only=False) @@ -3579,7 +4300,7 @@ class TestSuite(unittest.TestCase): self.assertEqual(jp2.box[3].box[1].method, 2) # enumerated self.assertEqual(jp2.box[3].box[1].precedence, 0) self.assertEqual(jp2.box[3].box[1].approximation, 1) # JPX exact - self.assertEqual(len(jp2.box[3].box[1].icc_profile), 546) + self.assertEqual(jp2.box[3].box[1].icc_profile['Size'], 546) self.assertIsNone(jp2.box[3].box[1].colorspace) # Jp2 Header @@ -3674,7 +4395,7 @@ class TestSuite(unittest.TestCase): self.assertEqual(jp2.box[3].box[1].method, 2) self.assertEqual(jp2.box[3].box[1].precedence, 0) self.assertEqual(jp2.box[3].box[1].approximation, 1) # JPX exact - self.assertEqual(len(jp2.box[3].box[1].icc_profile), 13332) + self.assertEqual(jp2.box[3].box[1].icc_profile['Size'], 13332) self.assertIsNone(jp2.box[3].box[1].colorspace) # Jp2 Header @@ -3723,7 +4444,7 @@ class TestSuite(unittest.TestCase): self.assertEqual(jp2.box[2].box[1].method, 2) # enumerated self.assertEqual(jp2.box[2].box[1].precedence, 0) self.assertEqual(jp2.box[2].box[1].approximation, 1) # JPX exact - self.assertEqual(len(jp2.box[2].box[1].icc_profile), 414) + self.assertEqual(jp2.box[2].box[1].icc_profile['Size'], 414) self.assertIsNone(jp2.box[2].box[1].colorspace) # XML box @@ -6394,7 +7115,10 @@ class TestSuite(unittest.TestCase): def test_NR_orb_blue10_lin_jp2_dump(self): jfile = os.path.join(data_root, 'input/nonregression/orb-blue10-lin-jp2.jp2') - jp2 = Jp2k(jfile) + with warnings.catch_warnings(): + # This file has an invalid ICC profile + warnings.simplefilter("ignore") + jp2 = Jp2k(jfile) ids = [box.id for box in jp2.box] self.assertEqual(ids, ['jP ', 'ftyp', 'jp2h', 'jp2c']) @@ -6426,7 +7150,7 @@ class TestSuite(unittest.TestCase): self.assertEqual(jp2.box[2].box[1].method, 2) # res icc self.assertEqual(jp2.box[2].box[1].precedence, 0) self.assertEqual(jp2.box[2].box[1].approximation, 0) # JP2 - self.assertEqual(len(jp2.box[2].box[1].icc_profile), 1) + self.assertIsNone(jp2.box[2].box[1].icc_profile) self.assertIsNone(jp2.box[2].box[1].colorspace) c = jp2.box[3].main_header @@ -6490,7 +7214,10 @@ class TestSuite(unittest.TestCase): def test_NR_orb_blue10_win_jp2_dump(self): jfile = os.path.join(data_root, 'input/nonregression/orb-blue10-win-jp2.jp2') - jp2 = Jp2k(jfile) + with warnings.catch_warnings(): + # This file has an invalid ICC profile + warnings.simplefilter("ignore") + jp2 = Jp2k(jfile) ids = [box.id for box in jp2.box] self.assertEqual(ids, ['jP ', 'ftyp', 'jp2h', 'jp2c']) @@ -6522,7 +7249,7 @@ class TestSuite(unittest.TestCase): self.assertEqual(jp2.box[2].box[1].method, 2) # restricted icc self.assertEqual(jp2.box[2].box[1].precedence, 0) self.assertEqual(jp2.box[2].box[1].approximation, 0) # JP2 - self.assertEqual(len(jp2.box[2].box[1].icc_profile), 1) + self.assertIsNone(jp2.box[2].box[1].icc_profile) self.assertIsNone(jp2.box[2].box[1].colorspace) c = jp2.box[3].main_header @@ -6624,7 +7351,7 @@ class TestSuite(unittest.TestCase): self.assertEqual(jp2.box[3].box[1].method, 3) # any icc self.assertEqual(jp2.box[3].box[1].precedence, 2) self.assertEqual(jp2.box[3].box[1].approximation, 1) # JPX exact - self.assertEqual(len(jp2.box[3].box[1].icc_profile), 1328) + self.assertEqual(jp2.box[3].box[1].icc_profile['Size'], 1328) self.assertIsNone(jp2.box[3].box[1].colorspace) # UUID boxes. All mentioned in the RREQ box. @@ -6691,710 +7418,5 @@ class TestSuite(unittest.TestCase): self.assertEqual(c.segment[3]._exponent, [8, 9, 9, 10, 9, 9, 10, 9, 9, 10, 9, 9, 10, 9, 9, 10]) - def test_NR_DEC_Bretagne2_j2k_1_decode(self): - jfile = os.path.join(data_root, - 'input/nonregression/Bretagne2.j2k') - jp2 = Jp2k(jfile) - data = jp2.read() - self.assertTrue(True) - - def test_NR_DEC__00042_j2k_2_decode(self): - jfile = os.path.join(data_root, - 'input/nonregression/_00042.j2k') - jp2 = Jp2k(jfile) - data = jp2.read() - self.assertTrue(True) - - @unittest.skip("fprintf stderr output in r2343.") - def test_NR_DEC_123_j2c_3_decode(self): - jfile = os.path.join(data_root, - 'input/nonregression/123.j2c') - jp2 = Jp2k(jfile) - data = jp2.read() - self.assertTrue(True) - - @unittest.skipIf(sys.hexversion < 0x03020000, - "Uses features introduced in 3.2.") - def test_NR_DEC_broken_jp2_4_decode(self): - jfile = os.path.join(data_root, - 'input/nonregression/broken.jp2') - with self.assertWarns(UserWarning) as cw: - # colr box has bad length. - jp2 = Jp2k(jfile) - with self.assertRaises(IOError): - data = jp2.read() - self.assertTrue(True) - - def test_NR_DEC_broken2_jp2_5_decode(self): - jfile = os.path.join(data_root, - 'input/nonregression/broken2.jp2') - with self.assertRaises(IOError): - data = Jp2k(jfile).read() - self.assertTrue(True) - - @unittest.skipIf(sys.hexversion < 0x03020000, - "Uses features introduced in 3.2.") - def test_NR_DEC_broken3_jp2_6_decode(self): - jfile = os.path.join(data_root, - 'input/nonregression/broken3.jp2') - with self.assertWarns(UserWarning) as cw: - # colr box has bad length. - j = Jp2k(jfile) - - with self.assertRaises(IOError) as ce: - d = j.read() - - def test_NR_DEC_broken4_jp2_7_decode(self): - jfile = os.path.join(data_root, - 'input/nonregression/broken4.jp2') - with self.assertRaises(IOError): - data = Jp2k(jfile).read() - self.assertTrue(True) - - @unittest.skip("fprintf stderr output in r2343.") - def test_NR_DEC_bug_j2c_8_decode(self): - jfile = os.path.join(data_root, - 'input/nonregression/bug.j2c') - data = Jp2k(jfile).read() - self.assertTrue(True) - - def test_NR_DEC_buxI_j2k_9_decode(self): - jfile = os.path.join(data_root, - 'input/nonregression/buxI.j2k') - data = Jp2k(jfile).read() - self.assertTrue(True) - - def test_NR_DEC_buxR_j2k_10_decode(self): - jfile = os.path.join(data_root, - 'input/nonregression/buxR.j2k') - data = Jp2k(jfile).read() - self.assertTrue(True) - - def test_NR_DEC_Cannotreaddatawithnosizeknown_j2k_11_decode(self): - relpath = 'input/nonregression/Cannotreaddatawithnosizeknown.j2k' - jfile = os.path.join(data_root, relpath) - data = Jp2k(jfile).read() - self.assertTrue(True) - - def test_NR_DEC_cthead1_j2k_12_decode(self): - jfile = os.path.join(data_root, - 'input/nonregression/cthead1.j2k') - data = Jp2k(jfile).read() - self.assertTrue(True) - - def test_NR_DEC_CT_Phillips_JPEG2K_Decompr_Problem_j2k_13_decode(self): - relpath = 'input/nonregression/CT_Phillips_JPEG2K_Decompr_Problem.j2k' - jfile = os.path.join(data_root, relpath) - data = Jp2k(jfile).read() - self.assertTrue(True) - - @unittest.skip("fprintf stderr output in r2343.") - def test_NR_DEC_illegalcolortransform_j2k_14_decode(self): - # Stream too short, expected SOT. - jfile = os.path.join(data_root, - 'input/nonregression/illegalcolortransform.j2k') - data = Jp2k(jfile).read() - self.assertTrue(True) - - def test_NR_DEC_j2k32_j2k_15_decode(self): - jfile = os.path.join(data_root, - 'input/nonregression/j2k32.j2k') - data = Jp2k(jfile).read() - self.assertTrue(True) - - def test_NR_DEC_kakadu_v4_4_openjpegv2_broken_j2k_16_decode(self): - relpath = 'input/nonregression/kakadu_v4-4_openjpegv2_broken.j2k' - jfile = os.path.join(data_root, relpath) - data = Jp2k(jfile).read() - self.assertTrue(True) - - def test_NR_DEC_MarkerIsNotCompliant_j2k_17_decode(self): - jfile = os.path.join(data_root, - 'input/nonregression/MarkerIsNotCompliant.j2k') - data = Jp2k(jfile).read() - self.assertTrue(True) - - def test_NR_DEC_Marrin_jp2_18_decode(self): - jfile = os.path.join(data_root, - 'input/nonregression/Marrin.jp2') - data = Jp2k(jfile).read() - self.assertTrue(True) - - def test_NR_DEC_merged_jp2_19_decode(self): - jfile = os.path.join(data_root, - 'input/nonregression/merged.jp2') - data = Jp2k(jfile).read_bands() - self.assertTrue(True) - - def test_NR_DEC_movie_00000_j2k_20_decode(self): - jfile = os.path.join(data_root, - 'input/nonregression/movie_00000.j2k') - data = Jp2k(jfile).read() - self.assertTrue(True) - - def test_NR_DEC_movie_00001_j2k_21_decode(self): - jfile = os.path.join(data_root, - 'input/nonregression/movie_00001.j2k') - data = Jp2k(jfile).read() - self.assertTrue(True) - - def test_NR_DEC_movie_00002_j2k_22_decode(self): - jfile = os.path.join(data_root, - 'input/nonregression/movie_00002.j2k') - data = Jp2k(jfile).read() - self.assertTrue(True) - - def test_NR_DEC_orb_blue_lin_j2k_j2k_23_decode(self): - jfile = os.path.join(data_root, - 'input/nonregression/orb-blue10-lin-j2k.j2k') - data = Jp2k(jfile).read() - self.assertTrue(True) - - def test_NR_DEC_orb_blue_win_j2k_j2k_24_decode(self): - jfile = os.path.join(data_root, - 'input/nonregression/orb-blue10-win-j2k.j2k') - data = Jp2k(jfile).read() - self.assertTrue(True) - - def test_NR_DEC_orb_blue_lin_jp2_25_decode(self): - jfile = os.path.join(data_root, - 'input/nonregression/orb-blue10-lin-jp2.jp2') - data = Jp2k(jfile).read() - self.assertTrue(True) - - def test_NR_DEC_orb_blue_win_jp2_26_decode(self): - jfile = os.path.join(data_root, - 'input/nonregression/orb-blue10-win-jp2.jp2') - data = Jp2k(jfile).read() - self.assertTrue(True) - - def test_NR_DEC_relax_jp2_27_decode(self): - jfile = os.path.join(data_root, - 'input/nonregression/relax.jp2') - data = Jp2k(jfile).read() - self.assertTrue(True) - - def test_NR_DEC_test_lossless_j2k_28_decode(self): - jfile = os.path.join(data_root, - 'input/nonregression/test_lossless.j2k') - data = Jp2k(jfile).read() - self.assertTrue(True) - - def test_NR_DEC_text_GBR_jp2_29_decode(self): - jfile = os.path.join(data_root, - 'input/nonregression/text_GBR.jp2') - data = Jp2k(jfile).read() - self.assertTrue(True) - - def test_NR_DEC_pacs_ge_j2k_30_decode(self): - jfile = os.path.join(data_root, - 'input/nonregression/pacs.ge.j2k') - data = Jp2k(jfile).read() - self.assertTrue(True) - - def test_NR_DEC_kodak_2layers_lrcp_j2c_31_decode(self): - jfile = os.path.join(data_root, - 'input/nonregression/kodak_2layers_lrcp.j2c') - data = Jp2k(jfile).read() - self.assertTrue(True) - - def test_NR_DEC_kodak_2layers_lrcp_j2c_32_decode(self): - jfile = os.path.join(data_root, - 'input/nonregression/kodak_2layers_lrcp.j2c') - data = Jp2k(jfile).read(layer=2) - self.assertTrue(True) - - def test_NR_DEC_issue104_jpxstream_jp2_33_decode(self): - jfile = os.path.join(data_root, - 'input/nonregression/issue104_jpxstream.jp2') - data = Jp2k(jfile).read() - self.assertTrue(True) - - def test_NR_DEC_mem_b2ace68c_1381_jp2_34_decode(self): - jfile = os.path.join(data_root, - 'input/nonregression/mem-b2ace68c-1381.jp2') - with warnings.catch_warnings(): - # This file has a bad pclr box, we test for this elsewhere. - warnings.simplefilter("ignore") - j = Jp2k(jfile) - data = j.read() - self.assertTrue(True) - - def test_NR_DEC_mem_b2b86b74_2753_jp2_35_decode(self): - jfile = os.path.join(data_root, - 'input/nonregression/mem-b2b86b74-2753.jp2') - data = Jp2k(jfile).read() - self.assertTrue(True) - - def test_NR_DEC_gdal_fuzzer_unchecked_num_resolutions_jp2_36_decode(self): - f = 'input/nonregression/gdal_fuzzer_unchecked_numresolutions.jp2' - jfile = os.path.join(data_root, f) - with warnings.catch_warnings(): - warnings.simplefilter("ignore") - j = Jp2k(jfile) - with self.assertRaises(IOError): - data = j.read() - - def test_NR_DEC_jp2_36_decode(self): - lst = ('input', - 'nonregression', - 'gdal_fuzzer_assert_in_opj_j2k_read_SQcd_SQcc.patch.jp2') - jfile = os.path.join(data_root, '/'.join(lst)) - with warnings.catch_warnings(): - warnings.simplefilter("ignore") - j = Jp2k(jfile) - with self.assertRaises(IOError): - data = j.read() - - def test_NR_DEC_gdal_fuzzer_check_number_of_tiles_jp2_38_decode(self): - relpath = 'input/nonregression/gdal_fuzzer_check_number_of_tiles.jp2' - jfile = os.path.join(data_root, relpath) - with warnings.catch_warnings(): - warnings.simplefilter("ignore") - j = Jp2k(jfile) - with self.assertRaises(IOError): - data = j.read() - - def test_NR_DEC_gdal_fuzzer_check_comp_dx_dy_jp2_39_decode(self): - relpath = 'input/nonregression/gdal_fuzzer_check_comp_dx_dy.jp2' - jfile = os.path.join(data_root, relpath) - with warnings.catch_warnings(): - warnings.simplefilter("ignore") - with self.assertRaises(IOError): - j = Jp2k(jfile).read() - - def test_NR_DEC_file_409752_jp2_40_decode(self): - jfile = os.path.join(data_root, - 'input/nonregression/file409752.jp2') - with self.assertRaises(IOError): - data = Jp2k(jfile).read() - - @unittest.skipIf(sys.hexversion < 0x03020000, - "Uses features introduced in 3.2.") - def test_NR_DEC_issue188_beach_64bitsbox_jp2_41_decode(self): - # Has an 'XML ' box instead of 'xml '. Yes that is pedantic, but it - # really does deserve a warning. - relpath = 'input/nonregression/issue188_beach_64bitsbox.jp2' - jfile = os.path.join(data_root, relpath) - with self.assertWarns(UserWarning) as cw: - data = Jp2k(jfile).read() - - def test_NR_DEC_issue206_image_000_jp2_42_decode(self): - jfile = os.path.join(data_root, - 'input/nonregression/issue206_image-000.jp2') - data = Jp2k(jfile).read() - self.assertTrue(True) - - def test_NR_DEC_p1_04_j2k_43_decode(self): - jfile = os.path.join(data_root, 'input/conformance/p1_04.j2k') - jp2k = Jp2k(jfile) - ssdata = jp2k.read(area=(0, 0, 1024, 1024)) - odata = jp2k.read() - np.testing.assert_array_equal(ssdata, odata) - - def test_NR_DEC_p1_04_j2k_44_decode(self): - jfile = os.path.join(data_root, 'input/conformance/p1_04.j2k') - jp2k = Jp2k(jfile) - ssdata = jp2k.read(area=(640, 512, 768, 640)) - odata = jp2k.read() - np.testing.assert_array_equal(ssdata, odata[640:768, 512:640]) - - def test_NR_DEC_p1_04_j2k_45_decode(self): - jfile = os.path.join(data_root, 'input/conformance/p1_04.j2k') - jp2k = Jp2k(jfile) - ssdata = jp2k.read(area=(896, 896, 1024, 1024)) - odata = jp2k.read() - np.testing.assert_array_equal(ssdata, odata[896:1024, 896:1024]) - - def test_NR_DEC_p1_04_j2k_46_decode(self): - jfile = os.path.join(data_root, 'input/conformance/p1_04.j2k') - jp2k = Jp2k(jfile) - ssdata = jp2k.read(area=(500, 100, 800, 300)) - odata = jp2k.read() - np.testing.assert_array_equal(ssdata, odata[500:800, 100:300]) - - def test_NR_DEC_p1_04_j2k_47_decode(self): - jfile = os.path.join(data_root, 'input/conformance/p1_04.j2k') - jp2k = Jp2k(jfile) - ssdata = jp2k.read(area=(520, 260, 600, 360)) - odata = jp2k.read() - np.testing.assert_array_equal(ssdata, odata[520:600, 260:360]) - - def test_NR_DEC_p1_04_j2k_48_decode(self): - jfile = os.path.join(data_root, 'input/conformance/p1_04.j2k') - jp2k = Jp2k(jfile) - ssdata = jp2k.read(area=(520, 260, 660, 360)) - odata = jp2k.read() - np.testing.assert_array_equal(ssdata, odata[520:660, 260:360]) - - def test_NR_DEC_p1_04_j2k_49_decode(self): - jfile = os.path.join(data_root, 'input/conformance/p1_04.j2k') - jp2k = Jp2k(jfile) - ssdata = jp2k.read(area=(520, 360, 600, 400)) - odata = jp2k.read() - np.testing.assert_array_equal(ssdata, odata[520:600, 360:400]) - - def test_NR_DEC_p1_04_j2k_50_decode(self): - jfile = os.path.join(data_root, 'input/conformance/p1_04.j2k') - jp2k = Jp2k(jfile) - ssdata = jp2k.read(area=(0, 0, 1024, 1024), reduce=2) - odata = jp2k.read(reduce=2) - - np.testing.assert_array_equal(ssdata, odata[0:256, 0:256]) - - def test_NR_DEC_p1_04_j2k_51_decode(self): - jfile = os.path.join(data_root, 'input/conformance/p1_04.j2k') - jp2k = Jp2k(jfile) - ssdata = jp2k.read(area=(640, 512, 768, 640), reduce=2) - odata = jp2k.read(reduce=2) - np.testing.assert_array_equal(ssdata, odata[160:192, 128:160]) - - def test_NR_DEC_p1_04_j2k_52_decode(self): - jfile = os.path.join(data_root, 'input/conformance/p1_04.j2k') - jp2k = Jp2k(jfile) - ssdata = jp2k.read(area=(896, 896, 1024, 1024), reduce=2) - odata = jp2k.read(reduce=2) - np.testing.assert_array_equal(ssdata, odata[224:352, 224:352]) - - def test_NR_DEC_p1_04_j2k_53_decode(self): - jfile = os.path.join(data_root, 'input/conformance/p1_04.j2k') - jp2k = Jp2k(jfile) - ssdata = jp2k.read(area=(500, 100, 800, 300), reduce=2) - odata = jp2k.read(reduce=2) - np.testing.assert_array_equal(ssdata, odata[125:200, 25:75]) - - def test_NR_DEC_p1_04_j2k_54_decode(self): - jfile = os.path.join(data_root, 'input/conformance/p1_04.j2k') - jp2k = Jp2k(jfile) - ssdata = jp2k.read(area=(520, 260, 600, 360), reduce=2) - odata = jp2k.read(reduce=2) - np.testing.assert_array_equal(ssdata, odata[130:150, 65:90]) - - def test_NR_DEC_p1_04_j2k_55_decode(self): - jfile = os.path.join(data_root, 'input/conformance/p1_04.j2k') - jp2k = Jp2k(jfile) - ssdata = jp2k.read(area=(520, 260, 660, 360), reduce=2) - odata = jp2k.read(reduce=2) - np.testing.assert_array_equal(ssdata, odata[130:165, 65:90]) - - def test_NR_DEC_p1_04_j2k_56_decode(self): - jfile = os.path.join(data_root, 'input/conformance/p1_04.j2k') - jp2k = Jp2k(jfile) - ssdata = jp2k.read(area=(520, 360, 600, 400), reduce=2) - odata = jp2k.read(reduce=2) - np.testing.assert_array_equal(ssdata, odata[130:150, 90:100]) - - def test_NR_DEC_p1_04_j2k_57_decode(self): - jfile = os.path.join(data_root, 'input/conformance/p1_04.j2k') - jp2k = Jp2k(jfile) - with warnings.catch_warnings(): - warnings.simplefilter("ignore") - tdata = jp2k.read(tile=63) # last tile - odata = jp2k.read() - np.testing.assert_array_equal(tdata, odata[896:1024, 896:1024]) - - def test_NR_DEC_p1_04_j2k_58_decode(self): - jfile = os.path.join(data_root, 'input/conformance/p1_04.j2k') - jp2k = Jp2k(jfile) - with warnings.catch_warnings(): - warnings.simplefilter("ignore") - tdata = jp2k.read(tile=63, reduce=2) # last tile - odata = jp2k.read(reduce=2) - np.testing.assert_array_equal(tdata, odata[224:256, 224:256]) - - def test_NR_DEC_p1_04_j2k_59_decode(self): - jfile = os.path.join(data_root, 'input/conformance/p1_04.j2k') - jp2k = Jp2k(jfile) - with warnings.catch_warnings(): - warnings.simplefilter("ignore") - tdata = jp2k.read(tile=12) # 2nd row, 5th column - odata = jp2k.read() - np.testing.assert_array_equal(tdata, odata[128:256, 512:640]) - - def test_NR_DEC_p1_04_j2k_60_decode(self): - jfile = os.path.join(data_root, 'input/conformance/p1_04.j2k') - jp2k = Jp2k(jfile) - with warnings.catch_warnings(): - warnings.simplefilter("ignore") - tdata = jp2k.read(tile=12, reduce=1) # 2nd row, 5th column - odata = jp2k.read(reduce=1) - np.testing.assert_array_equal(tdata, odata[64:128, 256:320]) - - @unittest.skip("fprintf stderr output in r2343.") - def test_NR_DEC_p1_06_j2k_61_decode(self): - jfile = os.path.join(data_root, 'input/conformance/p1_06.j2k') - jp2k = Jp2k(jfile) - ssdata = jp2k.read(area=(0, 0, 12, 12)) - odata = jp2k.read() - np.testing.assert_array_equal(ssdata, odata[0:12, 0:12]) - - @unittest.skip("fprintf stderr output in r2343.") - def test_NR_DEC_p1_06_j2k_62_decode(self): - jfile = os.path.join(data_root, 'input/conformance/p1_06.j2k') - jp2k = Jp2k(jfile) - ssdata = jp2k.read(area=(1, 8, 8, 11)) - odata = jp2k.read() - np.testing.assert_array_equal(ssdata, odata[1:8, 8:11]) - - @unittest.skip("fprintf stderr output in r2343.") - def test_NR_DEC_p1_06_j2k_63_decode(self): - jfile = os.path.join(data_root, 'input/conformance/p1_06.j2k') - jp2k = Jp2k(jfile) - ssdata = jp2k.read(area=(9, 9, 12, 12)) - odata = jp2k.read() - np.testing.assert_array_equal(ssdata, odata[9:12, 9:12]) - - @unittest.skip("fprintf stderr output in r2343.") - def test_NR_DEC_p1_06_j2k_64_decode(self): - jfile = os.path.join(data_root, 'input/conformance/p1_06.j2k') - jp2k = Jp2k(jfile) - ssdata = jp2k.read(area=(10, 4, 12, 10)) - odata = jp2k.read() - np.testing.assert_array_equal(ssdata, odata[10:12, 4:10]) - - @unittest.skip("fprintf stderr output in r2343.") - def test_NR_DEC_p1_06_j2k_65_decode(self): - jfile = os.path.join(data_root, 'input/conformance/p1_06.j2k') - jp2k = Jp2k(jfile) - ssdata = jp2k.read(area=(3, 3, 9, 9)) - odata = jp2k.read() - np.testing.assert_array_equal(ssdata, odata[3:9, 3:9]) - - @unittest.skip("fprintf stderr output in r2343.") - def test_NR_DEC_p1_06_j2k_66_decode(self): - jfile = os.path.join(data_root, 'input/conformance/p1_06.j2k') - jp2k = Jp2k(jfile) - ssdata = jp2k.read(area=(4, 4, 7, 7)) - odata = jp2k.read() - np.testing.assert_array_equal(ssdata, odata[4:7, 4:7]) - - @unittest.skip("fprintf stderr output in r2343.") - def test_NR_DEC_p1_06_j2k_67_decode(self): - jfile = os.path.join(data_root, 'input/conformance/p1_06.j2k') - jp2k = Jp2k(jfile) - ssdata = jp2k.read(area=(4, 4, 5, 5)) - odata = jp2k.read() - np.testing.assert_array_equal(ssdata, odata[4:5, 4: 5]) - - @unittest.skip("fprintf stderr output in r2343.") - def test_NR_DEC_p1_06_j2k_68_decode(self): - jfile = os.path.join(data_root, 'input/conformance/p1_06.j2k') - jp2k = Jp2k(jfile) - ssdata = jp2k.read(area=(0, 0, 12, 12), reduce=1) - odata = jp2k.read(reduce=1) - np.testing.assert_array_equal(ssdata, odata[0:6, 0:6]) - - @unittest.skip("fprintf stderr output in r2343.") - def test_NR_DEC_p1_06_j2k_69_decode(self): - jfile = os.path.join(data_root, 'input/conformance/p1_06.j2k') - jp2k = Jp2k(jfile) - ssdata = jp2k.read(area=(1, 8, 8, 11), reduce=1) - self.assertEqual(ssdata.shape, (3, 2, 3)) - - def test_NR_DEC_p1_06_j2k_70_decode(self): - jfile = os.path.join(data_root, 'input/conformance/p1_06.j2k') - jp2k = Jp2k(jfile) - ssdata = jp2k.read(area=(9, 9, 12, 12), reduce=1) - self.assertEqual(ssdata.shape, (1, 1, 3)) - - def test_NR_DEC_p1_06_j2k_71_decode(self): - jfile = os.path.join(data_root, 'input/conformance/p1_06.j2k') - jp2k = Jp2k(jfile) - ssdata = jp2k.read(area=(10, 4, 12, 10), reduce=1) - self.assertEqual(ssdata.shape, (1, 3, 3)) - - def test_NR_DEC_p1_06_j2k_72_decode(self): - jfile = os.path.join(data_root, 'input/conformance/p1_06.j2k') - jp2k = Jp2k(jfile) - ssdata = jp2k.read(area=(3, 3, 9, 9), reduce=1) - self.assertEqual(ssdata.shape, (3, 3, 3)) - - def test_NR_DEC_p1_06_j2k_73_decode(self): - jfile = os.path.join(data_root, 'input/conformance/p1_06.j2k') - jp2k = Jp2k(jfile) - ssdata = jp2k.read(area=(4, 4, 7, 7), reduce=1) - self.assertEqual(ssdata.shape, (2, 2, 3)) - - def test_NR_DEC_p1_06_j2k_74_decode(self): - jfile = os.path.join(data_root, 'input/conformance/p1_06.j2k') - jp2k = Jp2k(jfile) - ssdata = jp2k.read(area=(4, 4, 5, 5), reduce=1) - self.assertEqual(ssdata.shape, (1, 1, 3)) - - def test_NR_DEC_p1_06_j2k_75_decode(self): - # Image size would be 0 x 0. - jfile = os.path.join(data_root, 'input/conformance/p1_06.j2k') - jp2k = Jp2k(jfile) - with self.assertRaises((IOError, OSError)) as ce: - ssdata = jp2k.read(area=(9, 9, 12, 12), reduce=2) - - @unittest.skip("fprintf stderr output in r2343.") - def test_NR_DEC_p1_06_j2k_76_decode(self): - jfile = os.path.join(data_root, 'input/conformance/p1_06.j2k') - jp2k = Jp2k(jfile) - fulldata = jp2k.read() - with warnings.catch_warnings(): - warnings.simplefilter("ignore") - tiledata = jp2k.read(tile=0) - np.testing.assert_array_equal(tiledata, fulldata[0:3, 0:3]) - - @unittest.skip("fprintf stderr output in r2343.") - def test_NR_DEC_p1_06_j2k_77_decode(self): - jfile = os.path.join(data_root, 'input/conformance/p1_06.j2k') - jp2k = Jp2k(jfile) - fulldata = jp2k.read() - with warnings.catch_warnings(): - warnings.simplefilter("ignore") - tiledata = jp2k.read(tile=5) - np.testing.assert_array_equal(tiledata, fulldata[3:6, 3:6]) - - @unittest.skip("fprintf stderr output in r2343.") - def test_NR_DEC_p1_06_j2k_78_decode(self): - jfile = os.path.join(data_root, 'input/conformance/p1_06.j2k') - jp2k = Jp2k(jfile) - fulldata = jp2k.read() - with warnings.catch_warnings(): - warnings.simplefilter("ignore") - tiledata = jp2k.read(tile=9) - np.testing.assert_array_equal(tiledata, fulldata[6:9, 3:6]) - - @unittest.skip("fprintf stderr output in r2343.") - def test_NR_DEC_p1_06_j2k_79_decode(self): - jfile = os.path.join(data_root, 'input/conformance/p1_06.j2k') - jp2k = Jp2k(jfile) - fulldata = jp2k.read() - with warnings.catch_warnings(): - warnings.simplefilter("ignore") - tiledata = jp2k.read(tile=15) - np.testing.assert_array_equal(tiledata, fulldata[9:12, 9:12]) - - @unittest.skip("fprintf stderr output in r2343.") - def test_NR_DEC_p1_06_j2k_80_decode(self): - # Just read the data, don't bother verifying. - jfile = os.path.join(data_root, 'input/conformance/p1_06.j2k') - jp2k = Jp2k(jfile) - with warnings.catch_warnings(): - warnings.simplefilter("ignore") - tiledata = jp2k.read(tile=0, reduce=2) - - @unittest.skip("fprintf stderr output in r2343.") - def test_NR_DEC_p1_06_j2k_81_decode(self): - # Just read the data, don't bother verifying. - jfile = os.path.join(data_root, 'input/conformance/p1_06.j2k') - jp2k = Jp2k(jfile) - with warnings.catch_warnings(): - warnings.simplefilter("ignore") - tiledata = jp2k.read(tile=5, reduce=2) - - @unittest.skip("fprintf stderr output in r2343.") - def test_NR_DEC_p1_06_j2k_82_decode(self): - # Just read the data, don't bother verifying. - jfile = os.path.join(data_root, 'input/conformance/p1_06.j2k') - jp2k = Jp2k(jfile) - with warnings.catch_warnings(): - warnings.simplefilter("ignore") - tiledata = jp2k.read(tile=9, reduce=2) - - @unittest.skip("fprintf stderr output in r2343.") - def test_NR_DEC_p1_06_j2k_83_decode(self): - # tile size is 3x3. Reducing two levels results in no data. - jfile = os.path.join(data_root, 'input/conformance/p1_06.j2k') - jp2k = Jp2k(jfile) - with warnings.catch_warnings(): - warnings.simplefilter("ignore") - with self.assertRaises((IOError, OSError)) as ce: - tiledata = jp2k.read(tile=15, reduce=2) - - @unittest.skip("fprintf stderr output in r2343.") - def test_NR_DEC_p1_06_j2k_84_decode(self): - # Just read the data, don't bother verifying. - jfile = os.path.join(data_root, 'input/conformance/p1_06.j2k') - jp2k = Jp2k(jfile) - data = jp2k.read(reduce=4) - - def test_NR_DEC_p0_04_j2k_85_decode(self): - jfile = os.path.join(data_root, 'input/conformance/p0_04.j2k') - jp2k = Jp2k(jfile) - ssdata = jp2k.read(area=(0, 0, 256, 256)) - fulldata = jp2k.read() - np.testing.assert_array_equal(fulldata[0:256, 0:256], ssdata) - - def test_NR_DEC_p0_04_j2k_86_decode(self): - jfile = os.path.join(data_root, 'input/conformance/p0_04.j2k') - jp2k = Jp2k(jfile) - ssdata = jp2k.read(area=(0, 128, 128, 256)) - fulldata = jp2k.read() - np.testing.assert_array_equal(fulldata[0:128, 128:256], ssdata) - - def test_NR_DEC_p0_04_j2k_87_decode(self): - jfile = os.path.join(data_root, 'input/conformance/p0_04.j2k') - jp2k = Jp2k(jfile) - ssdata = jp2k.read(area=(10, 50, 200, 120)) - fulldata = jp2k.read() - np.testing.assert_array_equal(fulldata[10:200, 50:120], ssdata) - - def test_NR_DEC_p0_04_j2k_88_decode(self): - jfile = os.path.join(data_root, 'input/conformance/p0_04.j2k') - jp2k = Jp2k(jfile) - ssdata = jp2k.read(area=(150, 10, 210, 190)) - fulldata = jp2k.read() - np.testing.assert_array_equal(fulldata[150:210, 10:190], ssdata) - - def test_NR_DEC_p0_04_j2k_89_decode(self): - jfile = os.path.join(data_root, 'input/conformance/p0_04.j2k') - jp2k = Jp2k(jfile) - ssdata = jp2k.read(area=(80, 100, 150, 200)) - fulldata = jp2k.read() - np.testing.assert_array_equal(fulldata[80:150, 100:200], ssdata) - - def test_NR_DEC_p0_04_j2k_90_decode(self): - jfile = os.path.join(data_root, 'input/conformance/p0_04.j2k') - jp2k = Jp2k(jfile) - ssdata = jp2k.read(area=(20, 150, 50, 200)) - fulldata = jp2k.read() - np.testing.assert_array_equal(fulldata[20:50, 150:200], ssdata) - - def test_NR_DEC_p0_04_j2k_91_decode(self): - jfile = os.path.join(data_root, 'input/conformance/p0_04.j2k') - jp2k = Jp2k(jfile) - ssdata = jp2k.read(area=(0, 0, 256, 256), reduce=2) - fulldata = jp2k.read(reduce=2) - np.testing.assert_array_equal(fulldata[0:64, 0:64], ssdata) - - def test_NR_DEC_p0_04_j2k_92_decode(self): - jfile = os.path.join(data_root, 'input/conformance/p0_04.j2k') - jp2k = Jp2k(jfile) - ssdata = jp2k.read(area=(0, 128, 128, 256), reduce=2) - fulldata = jp2k.read(reduce=2) - np.testing.assert_array_equal(fulldata[0:32, 32:64], ssdata) - - def test_NR_DEC_p0_04_j2k_93_decode(self): - jfile = os.path.join(data_root, 'input/conformance/p0_04.j2k') - jp2k = Jp2k(jfile) - ssdata = jp2k.read(area=(10, 50, 200, 120), reduce=2) - fulldata = jp2k.read(reduce=2) - np.testing.assert_array_equal(fulldata[3:50, 13:30], ssdata) - - def test_NR_DEC_p0_04_j2k_94_decode(self): - jfile = os.path.join(data_root, 'input/conformance/p0_04.j2k') - jp2k = Jp2k(jfile) - ssdata = jp2k.read(area=(150, 10, 210, 190), reduce=2) - fulldata = jp2k.read(reduce=2) - np.testing.assert_array_equal(fulldata[38:53, 3:48], ssdata) - - def test_NR_DEC_p0_04_j2k_95_decode(self): - jfile = os.path.join(data_root, 'input/conformance/p0_04.j2k') - jp2k = Jp2k(jfile) - ssdata = jp2k.read(area=(80, 100, 150, 200), reduce=2) - fulldata = jp2k.read(reduce=2) - np.testing.assert_array_equal(fulldata[20:38, 25:50], ssdata) - - def test_NR_DEC_p0_04_j2k_96_decode(self): - jfile = os.path.join(data_root, 'input/conformance/p0_04.j2k') - jp2k = Jp2k(jfile) - ssdata = jp2k.read(area=(20, 150, 50, 200), reduce=2) - fulldata = jp2k.read(reduce=2) - np.testing.assert_array_equal(fulldata[5:13, 38:50], ssdata) - if __name__ == "__main__": unittest.main() diff --git a/glymur/test/test_opj_suite_neg.py b/glymur/test/test_opj_suite_neg.py index 75c9c6f..03cb437 100644 --- a/glymur/test/test_opj_suite_neg.py +++ b/glymur/test/test_opj_suite_neg.py @@ -57,6 +57,8 @@ def read_image(infile): return data +@unittest.skipIf(glymur.lib.openjp2._OPENJP2 is None, + "Missing openjp2 library.") @unittest.skipIf(no_read_backend, no_read_backend_msg) @unittest.skipIf(data_root is None, "OPJ_DATA_ROOT environment variable not set") diff --git a/glymur/test/test_opj_suite_write.py b/glymur/test/test_opj_suite_write.py index d511768..0526fc3 100644 --- a/glymur/test/test_opj_suite_write.py +++ b/glymur/test/test_opj_suite_write.py @@ -57,6 +57,8 @@ def read_image(infile): return data +@unittest.skipIf(glymur.lib.openjp2._OPENJP2 is None, + "Missing openjp2 library.") @unittest.skipIf(no_read_backend, no_read_backend_msg) @unittest.skipIf(data_root is None, "OPJ_DATA_ROOT environment variable not set") diff --git a/glymur/test/test_printing.py b/glymur/test/test_printing.py index 9ba259d..f948c3e 100644 --- a/glymur/test/test_printing.py +++ b/glymur/test/test_printing.py @@ -21,7 +21,11 @@ except: raise -class TestPrinting(unittest.TestCase): +@unittest.skipIf(glymur.lib.openjp2._OPENJP2 is None, + "Missing openjp2 library.") +class TestPrintingNeedsLib(unittest.TestCase): + """These tests require the library, mostly in order to just setup the test. + """ @classmethod def setUpClass(cls): @@ -40,11 +44,11 @@ class TestPrinting(unittest.TestCase): os.unlink(cls._plain_nemo_file) def setUp(self): + self.jp2file = pkg_resources.resource_filename(glymur.__name__, + "data/nemo.jp2") # Save sys.stdout. self.stdout = sys.stdout sys.stdout = StringIO() - self.jp2file = pkg_resources.resource_filename(glymur.__name__, - "data/nemo.jp2") # Save the output of dumping nemo.jp2 for more than one test. lines = ['JPEG 2000 Signature Box (jP ) @ (0, 12)', @@ -115,6 +119,57 @@ class TestPrinting(unittest.TestCase): # Restore stdout. sys.stdout = self.stdout + def test_asoc_label_box(self): + # Construct a fake file with an asoc and a label box, as + # OpenJPEG doesn't have such a file. + data = glymur.Jp2k(self.jp2file).read(reduce=3) + with tempfile.NamedTemporaryFile(suffix='.jp2') as tfile: + j = glymur.Jp2k(tfile.name, 'wb') + j.write(data) + + with tempfile.NamedTemporaryFile(suffix='.jp2') as tfile2: + + # Offset of the codestream is where we start. + buffer = tfile.read(77) + tfile2.write(buffer) + + # read the rest of the file, it's the codestream. + codestream = tfile.read() + + # Write the asoc superbox. + # Length = 36, id is 'asoc'. + buffer = struct.pack('>I4s', int(56), b'asoc') + tfile2.write(buffer) + + # Write the contained label box + buffer = struct.pack('>I4s', int(13), b'lbl ') + tfile2.write(buffer) + tfile2.write('label'.encode()) + + # Write the xml box + # Length = 36, id is 'xml '. + buffer = struct.pack('>I4s', int(35), b'xml ') + tfile2.write(buffer) + + buffer = 'this is a test' + buffer = buffer.encode() + tfile2.write(buffer) + + # Now append the codestream. + tfile2.write(codestream) + tfile2.flush() + + jasoc = glymur.Jp2k(tfile2.name) + print(jasoc.box[3]) + actual = sys.stdout.getvalue().strip() + lines = ['Association Box (asoc) @ (77, 56)', + ' Label Box (lbl ) @ (85, 13)', + ' Label: label', + ' XML Box (xml ) @ (98, 35)', + ' this is a test'] + expected = '\n'.join(lines) + self.assertEqual(actual, expected) + def test_jp2dump(self): glymur.jp2dump(self._plain_nemo_file) actual = sys.stdout.getvalue().strip() @@ -126,6 +181,32 @@ class TestPrinting(unittest.TestCase): self.assertEqual(actual, self.expectedPlain) + def test_entire_file(self): + j = glymur.Jp2k(self._plain_nemo_file) + print(j) + actual = sys.stdout.getvalue().strip() + + # Get rid of the filename line, as it is not set in stone. + lst = actual.split('\n') + lst = lst[1:] + actual = '\n'.join(lst) + + self.assertEqual(actual, self.expectedPlain) + + +class TestPrinting(unittest.TestCase): + + def setUp(self): + # Save sys.stdout. + self.stdout = sys.stdout + sys.stdout = StringIO() + self.jp2file = pkg_resources.resource_filename(glymur.__name__, + "data/nemo.jp2") + + def tearDown(self): + # Restore stdout. + sys.stdout = self.stdout + def test_COC_segment(self): j = glymur.Jp2k(self.jp2file) codestream = j.get_codestream(header_only=False) @@ -186,6 +267,70 @@ class TestPrinting(unittest.TestCase): self.expected = expected self.assertEqual(actual, expected) + @unittest.skipIf(data_root is None, + "OPJ_DATA_ROOT environment variable not set") + def test_icc_profile(self): + filename = os.path.join(data_root, 'input/nonregression/text_GBR.jp2') + j = glymur.Jp2k(filename) + print(j.box[3].box[1]) + actual = sys.stdout.getvalue().strip() + lin27 = ["Colour Specification Box (colr) @ (179, 1339)", + " Method: any ICC profile", + " Precedence: 2", + " Approximation: accurately represents correct " + + "colorspace definition", + " ICC Profile:", + " {'Color Space': 'RGB',", + " 'Connection Space': 'XYZ',", + " 'Creator': u'appl',", + " 'Datetime': " + + "datetime.datetime(2009, 2, 25, 11, 26, 11),", + " 'Device Attributes': 'reflective, glossy, " + + "positive media polarity, color media',", + " 'Device Class': 'display device profile',", + " 'Device Manufacturer': u'appl',", + " 'Device Model': '',", + " 'File Signature': u'acsp',", + " 'Flags': " + + "'not embedded, can be used independently',", + " 'Illuminant': " + + "array([ 0.96420288, 1. , 0.8249054 ]),", + " 'Platform': u'APPL',", + " 'Preferred CMM Type': 1634758764,", + " 'Rendering Intent': 'perceptual',", + " 'Size': 1328,", + " 'Version': '2.2.0'}"] + lin33 = ["Colour Specification Box (colr) @ (179, 1339)", + " Method: any ICC profile", + " Precedence: 2", + " Approximation: accurately represents correct " + + "colorspace definition", + " ICC Profile:", + " {'Size': 1328,", + " 'Preferred CMM Type': 1634758764,", + " 'Version': '2.2.0',", + " 'Device Class': 'display device profile',", + " 'Color Space': 'RGB',", + " 'Connection Space': 'XYZ',", + " 'Datetime': " + + "datetime.datetime(2009, 2, 25, 11, 26, 11),", + " 'File Signature': 'acsp',", + " 'Platform': 'APPL',", + " 'Flags': 'not embedded, can be used " + + "independently',", + " 'Device Manufacturer': 'appl',", + " 'Device Model': '',", + " 'Device Attributes': 'reflective, glossy, " + + "positive media polarity, color media',", + " 'Rendering Intent': 'perceptual',", + " 'Illuminant': " + + "array([ 0.96420288, 1. , 0.8249054 ]),", + " 'Creator': 'appl'}"] + + lines = lin27 if sys.hexversion < 0x03000000 else lin33 + expected = '\n'.join(lines) + self.assertEqual(actual, expected) + @unittest.skipIf(data_root is None, "OPJ_DATA_ROOT environment variable not set") def test_CRG(self): @@ -452,18 +597,6 @@ class TestPrinting(unittest.TestCase): expected = '\n'.join(lst) self.assertEqual(actual, expected) - def test_entire_file(self): - j = glymur.Jp2k(self._plain_nemo_file) - print(j) - actual = sys.stdout.getvalue().strip() - - # Get rid of the filename line, as it is not set in stone. - lst = actual.split('\n') - lst = lst[1:] - actual = '\n'.join(lst) - - self.assertEqual(actual, self.expectedPlain) - def test_codestream(self): j = glymur.Jp2k(self.jp2file) print(j.get_codestream()) @@ -651,57 +784,6 @@ class TestPrinting(unittest.TestCase): expected = '\n'.join(lines) self.assertEqual(actual, expected) - def test_asoc_label_box(self): - # Construct a fake file with an asoc and a label box, as - # OpenJPEG doesn't have such a file. - data = glymur.Jp2k(self.jp2file).read(reduce=3) - with tempfile.NamedTemporaryFile(suffix='.jp2') as tfile: - j = glymur.Jp2k(tfile.name, 'wb') - j.write(data) - - with tempfile.NamedTemporaryFile(suffix='.jp2') as tfile2: - - # Offset of the codestream is where we start. - buffer = tfile.read(77) - tfile2.write(buffer) - - # read the rest of the file, it's the codestream. - codestream = tfile.read() - - # Write the asoc superbox. - # Length = 36, id is 'asoc'. - buffer = struct.pack('>I4s', int(56), b'asoc') - tfile2.write(buffer) - - # Write the contained label box - buffer = struct.pack('>I4s', int(13), b'lbl ') - tfile2.write(buffer) - tfile2.write('label'.encode()) - - # Write the xml box - # Length = 36, id is 'xml '. - buffer = struct.pack('>I4s', int(35), b'xml ') - tfile2.write(buffer) - - buffer = 'this is a test' - buffer = buffer.encode() - tfile2.write(buffer) - - # Now append the codestream. - tfile2.write(codestream) - tfile2.flush() - - jasoc = glymur.Jp2k(tfile2.name) - print(jasoc.box[3]) - actual = sys.stdout.getvalue().strip() - lines = ['Association Box (asoc) @ (77, 56)', - ' Label Box (lbl ) @ (85, 13)', - ' Label: label', - ' XML Box (xml ) @ (98, 35)', - ' this is a test'] - expected = '\n'.join(lines) - self.assertEqual(actual, expected) - def test_less_common_boxes(self): with tempfile.NamedTemporaryFile(suffix='.jp2') as tfile: with open(self.jp2file, 'rb') as ifile: @@ -775,6 +857,8 @@ class TestPrinting(unittest.TestCase): expected = '\n'.join(lines) self.assertEqual(actual, expected) + @unittest.skipIf(sys.hexversion < 0x03000000, + "Ordered dicts not printing well in 2.7") @unittest.skipIf(data_root is None, "OPJ_DATA_ROOT environment variable not set") def test_jpx_approximation_with_icc_profile(self): @@ -785,12 +869,32 @@ class TestPrinting(unittest.TestCase): print(j.box[3].box[1]) actual = sys.stdout.getvalue().strip() - lines = ['Colour Specification Box (colr) @ (179, 1339)', - ' Method: any ICC profile', - ' Precedence: 2', - ' Approximation: accurately represents ' - + 'correct colorspace definition', - ' ICC Profile: 1328 bytes'] + lines = ["Colour Specification Box (colr) @ (179, 1339)", + " Method: any ICC profile", + " Precedence: 2", + " Approximation: accurately represents " + + "correct colorspace definition", + " ICC Profile:", + " {'Size': 1328,", + " 'Preferred CMM Type': 1634758764,", + " 'Version': '2.2.0',", + " 'Device Class': 'display device profile',", + " 'Color Space': 'RGB',", + " 'Connection Space': 'XYZ',", + " 'Datetime': " + + "datetime.datetime(2009, 2, 25, 11, 26, 11),", + " 'File Signature': 'acsp',", + " 'Platform': 'APPL',", + " 'Flags': 'not embedded, " + + "can be used independently',", + " 'Device Manufacturer': 'appl',", + " 'Device Model': '',", + " 'Device Attributes': 'reflective, glossy, " + + "positive media polarity, color media',", + " 'Rendering Intent': 'perceptual',", + " 'Illuminant': array([ 0.96420288, 1. ," + + " 0.8249054 ]),", + " 'Creator': 'appl'}"] expected = '\n'.join(lines) self.assertEqual(actual, expected) @@ -811,6 +915,8 @@ class TestPrinting(unittest.TestCase): expected = '\n'.join(lines) self.assertEqual(actual, expected) + @unittest.skipIf(sys.hexversion < 0x03000000, + "Ordered dicts not printing well in 2.7") def test_exif_uuid(self): j = glymur.Jp2k(self.jp2file) @@ -820,13 +926,33 @@ class TestPrinting(unittest.TestCase): lines = ["UUID Box (uuid) @ (77, 638)", " UUID: 4a706754-6966-6645-7869-662d3e4a5032 (Exif)", " UUID Data: ", - "{'GPSInfo': {'GPSAltitude': 0.0,", - " 'GPSAltitudeRef': 0,", - " 'GPSDateStamp': '2013:02:09',", - " 'GPSLatitude': [42.0, 20.0, 33.61],", + "{'Image': {'Make': 'HTC',", + " 'Model': 'HTC Glacier',", + " 'XResolution': 72.0,", + " 'YResolution': 72.0,", + " 'ResolutionUnit': 2,", + " 'YCbCrPositioning': 1,", + " 'ExifTag': 138,", + " 'GPSTag': 354},", + " 'Photo': {'ISOSpeedRatings': 76,", + " 'ExifVersion': (48, 50, 50, 48),", + " 'DateTimeOriginal': '2013:02:09 14:47:53',", + " 'DateTimeDigitized': '2013:02:09 14:47:53',", + " 'ComponentsConfiguration': (1, 2, 3, 0),", + " 'FocalLength': 3.53,", + " 'FlashpixVersion': (48, 49, 48, 48),", + " 'ColorSpace': 1,", + " 'PixelXDimension': 2528,", + " 'PixelYDimension': 1424,", + " 'InteroperabilityTag': 324},", + " 'GPSInfo': {'GPSVersionID': (2, 2, 0),", " 'GPSLatitudeRef': 'N',", - " 'GPSLongitude': [71.0, 5.0, 17.32],", + " 'GPSLatitude': [42.0, 20.0, 33.61],", " 'GPSLongitudeRef': 'W',", + " 'GPSLongitude': [71.0, 5.0, 17.32],", + " 'GPSAltitudeRef': 0,", + " 'GPSAltitude': 0.0,", + " 'GPSTimeStamp': [19.0, 47.0, 53.0],", " 'GPSMapDatum': 'WGS-84',", " 'GPSProcessingMethod': (65,", " 83,", @@ -843,28 +969,8 @@ class TestPrinting(unittest.TestCase): " 79,", " 82,", " 75),", - " 'GPSTimeStamp': [19.0, 47.0, 53.0],", - " 'GPSVersionID': (2, 2, 0)},", - " 'Image': {'ExifTag': 138,", - " 'GPSTag': 354,", - " 'Make': 'HTC',", - " 'Model': 'HTC Glacier',", - " 'ResolutionUnit': 2,", - " 'XResolution': 72.0,", - " 'YCbCrPositioning': 1,", - " 'YResolution': 72.0},", - " 'Iop': None,", - " 'Photo': {'ColorSpace': 1,", - " 'ComponentsConfiguration': (1, 2, 3, 0),", - " 'DateTimeDigitized': '2013:02:09 14:47:53',", - " 'DateTimeOriginal': '2013:02:09 14:47:53',", - " 'ExifVersion': (48, 50, 50, 48),", - " 'FlashpixVersion': (48, 49, 48, 48),", - " 'FocalLength': 3.53,", - " 'ISOSpeedRatings': 76,", - " 'InteroperabilityTag': 324,", - " 'PixelXDimension': 2528,", - " 'PixelYDimension': 1424}}"] + " 'GPSDateStamp': '2013:02:09'},", + " 'Iop': None}"] expected = '\n'.join(lines) diff --git a/setup.py b/setup.py index 6e968ae..0566e21 100644 --- a/setup.py +++ b/setup.py @@ -1,18 +1,26 @@ -from distutils.core import setup +from setuptools import setup, find_packages +import sys kwargs = {'name': 'Glymur', - 'version': '0.1.7', + 'version': '0.1.9', 'description': 'Tools for accessing JPEG2000 files', 'long_description': open('README.md').read(), 'author': 'John Evans', 'author_email': 'johnevans938 at gmail dot com', 'url': 'https://github.com/quintusdias/glymur', - 'packages': ['glymur', 'glymur.test', 'glymur.lib', + 'packages': ['glymur', 'glymur.data', 'glymur.test', 'glymur.lib', 'glymur.lib.test'], 'package_data': {'glymur': ['data/*.jp2']}, 'scripts': ['bin/jp2dump'], 'license': 'LICENSE.txt', 'platforms': ['darwin']} + +instllrqrs = ['numpy>1.6.2'] +if sys.hexversion < 0x03030000: + instllrqrs.append('contextlib2>=0.4') + instllrqrs.append('mock>=1.0.1') +kwargs['install_requires'] = instllrqrs + clssfrs = ["Programming Language :: Python", "Programming Language :: Python :: 2.7", "Programming Language :: Python :: 3.3",