Merge branch 'release-0.2.3'

This commit is contained in:
jevans 2013-07-18 19:52:40 -04:00
commit 85df7f615d
27 changed files with 623 additions and 378 deletions

View file

@ -1,3 +1,6 @@
Jul 18, 2013 - v0.2.3 Support for Python 2.6, OpenJPEG 1.4. Incompatible
change to ChannelDefinitionBox constructor. Added RGBA example.
Jul 11, 2013 - v0.2.2 Fixed mistakes with trove classifier, pypi releases. Jul 11, 2013 - v0.2.2 Fixed mistakes with trove classifier, pypi releases.
Jul 11, 2013 - v0.2.0 Support for Python 2.7 on windows, OpenJPEG 1.5.1. Jul 11, 2013 - v0.2.0 Support for Python 2.7 on windows, OpenJPEG 1.5.1.

View file

@ -3,6 +3,7 @@ glymur: a Python interface for JPEG 2000
**glymur** contains a Python interface to the OpenJPEG library **glymur** contains a Python interface to the OpenJPEG library
which allows linux and mac users to read and write JPEG 2000 files. which allows linux and mac users to read and write JPEG 2000 files.
**glymur** works on Python 2.7 and 3.3. Python 3.3 is strongly recommended. **glymur** works on Python 2.6, 2.7 and 3.3. Python 3.3 is strongly
recommended.
Please read the docs, https://glymur.readthedocs.org/en/latest/ Please read the docs, https://glymur.readthedocs.org/en/latest/

View file

@ -78,7 +78,7 @@ copyright = u'2013, John Evans'
# The short X.Y version. # The short X.Y version.
version = '0.1' version = '0.1'
# The full version, including alpha/beta/rc tags. # The full version, including alpha/beta/rc tags.
release = '0.2.2' release = '0.2.3'
# The language for content autogenerated by Sphinx. Refer to documentation # The language for content autogenerated by Sphinx. Refer to documentation
# for a list of supported languages. # for a list of supported languages.

View file

@ -7,7 +7,7 @@ Glymur Configuration
'''''''''''''''''''''' ''''''''''''''''''''''
The default glymur installation process relies upon OpenJPEG version The default glymur installation process relies upon OpenJPEG version
1.5.1 being properly installed on your system. This will, however, only 1.X being properly installed on your system. This will, however, only
give you you basic read capabilities, so if you wish to take advantage give you you basic read capabilities, so if you wish to take advantage
of more of glymur's features, you should compile OpenJPEG as a shared of more of glymur's features, you should compile OpenJPEG as a shared
library (named *openjp2* instead of *openjpeg*) from the developmental library (named *openjp2* instead of *openjpeg*) from the developmental
@ -23,21 +23,18 @@ environment variable for the purpose of running Glymur's test suite. ::
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 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:: the openjp2 library. The configuration format is the same as used by Python's
configparser module, i.e. ::
$ mkdir -p ~/.config/glymur [library]
$ cd ~/.config/glymur openjp2: /opt/openjp2-svn/lib/libopenjp2.so
$ cat > glymurrc << EOF
> [library]
> openjp2: /opt/openjp2-svn/lib/libopenjp2.so
> EOF
This assumes, of course, that you've installed OpenJPEG into This assumes, of course, that you've installed OpenJPEG into
/opt/openjp2-svn on a linux system. You may also substitute /opt/openjp2-svn on a linux system. You may also substitute
**$XDG_CONFIG_HOME** for **$HOME/.config**. **$XDG_CONFIG_HOME** for **$HOME/.config**.
You may also include a line for the version 1.5.1 library if you have it installed You may also include a line for the version 1.x openjpeg library if you have it
in a non-standard place, i.e. :: installed in a non-standard place, i.e. ::
[library] [library]
openjp2: /opt/openjp2-svn/lib/libopenjp2.so openjp2: /opt/openjp2-svn/lib/libopenjp2.so
@ -56,17 +53,13 @@ packages/RPMs/ports/whatever without going through pip.
Mac OS X Mac OS X
-------- --------
All the necessary packages are available to use glymur with Python 3.3 via All the necessary packages are available to use glymur with Python 3.3 via
MacPorts. A minimal set of ports includes MacPorts. You should install the following set of ports:
* python33 * python33
* py33-numpy * py33-numpy
* py33-distribute * py33-distribute
* py33-matplotlib (optional, for running certain tests)
To run all the testing, one of the following combinations of ports must * py33-Pillow (optional, for running certain tests)
additionally be installed:
* py33-scikit-image and either py33-Pillow or freeimage
* py33-matplotlib and py33-Pillow
MacPorts supplies both OpenJPEG 1.5.0 and OpenJPEG 2.0.0. As previously MacPorts supplies both OpenJPEG 1.5.0 and OpenJPEG 2.0.0. As previously
mentioned, the 2.0.0 official release is not supported (although the 2.0+ mentioned, the 2.0.0 official release is not supported (although the 2.0+
@ -95,18 +88,15 @@ meet the minimal set of requirements for running glymur.
* python3 * python3
* python3-numpy * python3-numpy
* python3-setuptools * python3-setuptools
* python3-matplotlib (for running tests)
For running the maximal number of tests, you also need
* python3-matplotlib
* python3-matplotlib-tk (or whichever matplotlib backend you prefer) * python3-matplotlib-tk (or whichever matplotlib backend you prefer)
A few tests still will not run, however, unless one of the following Pillow is also needed in order to run the maximum number of tests, so
combinations of RPMs / Python packages is installed. go ahead and install Pillow via pip since Pillow is not available
in Fedora 18 default repositories::
* 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-devel # pip needs this in order to compile Pillow
$ yum install python3-pip $ yum install python3-pip
@ -115,33 +105,20 @@ repositories::
Fedora 17 Fedora 17
''''''''' '''''''''
Fedora 17 ships with Python 3.2 and 2.7, but OpenJPEG is only at version 1.4, Fedora 17 ships with Python 2.7 and OpenJPEG 1.4. You should have the
so these steps detail working with Python 2.7 and the svn version of OpenJPEG. following RPMs installed.
Required RPMs include::
* python * python
* python-mock * python-mock
* python-pip * python-pip
* python-setuptools * python-setuptools
* numpy * numpy
* matplotlib (optional)
In addition, you must install contextlib2 via pip. In addition, you must install contextlib2 and Pillow via pip.
A few tests still will not run, however, unless one of the following $ yum install python-devel # pip needs this in order to compile Pillow
combinations of RPMs / Python packages is installed. $ pip-python install Pillow --user
* scikit-image and either Pillow or freeimage
* matplotlib and Pillow
scikit-image was not available in the Fedora 17 default repositories, but
it was installable 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 $ pip-python install contextlib2 --user
$ export PYTHONPATH=$HOME/.local/lib/python2.7/site-packages:$PYTHONPATH $ export PYTHONPATH=$HOME/.local/lib/python2.7/site-packages:$PYTHONPATH

Binary file not shown.

After

Width:  |  Height:  |  Size: 480 KiB

View file

@ -38,8 +38,8 @@ Add XML Metadata?
================= =================
An existing raw codestream (or JP2 file) can be wrapped (re-wrapped) in a An existing raw codestream (or JP2 file) can be wrapped (re-wrapped) in a
user-defined set of JP2 boxes. To get just a minimal JP2 jacket on the user-defined set of JP2 boxes. To get just a minimal JP2 jacket on the
codestream provided by `goodstuff.j2k`, you can use the **wrap** method with codestream provided by `goodstuff.j2k` (a file consisting of a raw codestream),
no box argument: :: you can use the **wrap** method with no box argument: ::
>>> import glymur >>> import glymur
>>> jfile = glymur.data.goodstuff() >>> jfile = glymur.data.goodstuff()
@ -119,6 +119,68 @@ and add it after the JP2 header box, but before the codestream box ::
. (truncated) . (truncated)
. .
Create an image with an alpha layer?
====================================
OpenJPEG can create JP2 files with more than 3 components, but by default, any
extra components are not described as such. In order to do so,
we need to rewrap such an image in a set of boxes that includes a channel
definition box.
This example is based on SciPy example code found at
http://scipy-lectures.github.io/advanced/image_processing/#basic-manipulations .
Instead of a circular mask, however, we'll make it an ellipse since the source
image isn't square.
>>> import numpy as np
>>> import glymur
>>> from glymur import Jp2k
>>> rgb = Jp2k(glymur.data.goodstuff()).read()
>>> lx, ly = rgb.shape[0:2]
>>> X, Y = np.ogrid[0:lx, 0:ly]
>>> mask = ly**2*(X - lx / 2) ** 2 + lx**2*(Y - ly / 2) ** 2 > (lx * ly / 2)**2
>>> alpha = 255 * np.ones((lx, ly, 1), dtype=np.uint8)
>>> alpha[mask] = 0
>>> rgba = np.concatenate((rgb, alpha), axis=2)
>>> jp2 = Jp2k('tmp.jp2', 'wb')
>>> jp2.write(rgba)
Next we need to specify what types of channels we have.
The first three channels are color channels, but we identify the fourth as
an alpha channel::
>>> from glymur.core import COLOR, OPACITY
>>> ctype = [COLOR, COLOR, COLOR, OPACITY]
And finally we have to specify just exactly how each channel is to be
interpreted. The color channels are straightforward, they correspond to R-G-B,
but the alpha (or opacity) channel in this case is to be applied against the
entire image (it is possible to apply an alpha channel to a single color
channel, but we aren't doing that). ::
>>> from glymur.core import RED, GREEN, BLUE, WHOLE_IMAGE
>>> asoc = [RED, GREEN, BLUE, WHOLE_IMAGE]
>>> cdef = glymur.jp2box.ChannelDefinitionBox(channel_type=ctype, association=asoc)
>>> print(cdef)
Channel Definition Box (cdef) @ (0, 0)
Channel 0 (color) ==> (1)
Channel 1 (color) ==> (2)
Channel 2 (color) ==> (3)
Channel 3 (opacity) ==> (whole image)
It's easiest to take the existing jp2 jacket and just add the channel
definition box in the appropriate spot. The channel definition box **must**
go into the jp2 header box, and then we can rewrap the image. ::
>>> boxes = jp2.box # The box attribute is the list of JP2 boxes
>>> boxes[2].box.append(cdef)
>>> jp2_rgba = jp2.wrap("goodstuff_rgba.jp2", boxes=boxes)
Here's how the Preview application on the mac shows the RGBA image.
.. image:: goodstuff_alpha.png
Work with XMP UUIDs? 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. ::

View file

@ -14,22 +14,23 @@ some very limited support for reading JPX metadata. For instance,
**asoc** and **labl** boxes are recognized, so GMLJP2 metadata can **asoc** and **labl** boxes are recognized, so GMLJP2 metadata can
be retrieved from such JPX files. be retrieved from such JPX files.
Glymur works on Python 2.7 and 3.3. Python 3.3 is strongly recommended. Glymur works on Python 2.6, 2.7, and 3.3. Python 3.3 is strongly recommended.
OpenJPEG Installation OpenJPEG Installation
===================== =====================
The OpenJPEG library version must be either 1.5.1 or the trunk/development OpenJPEG should be version 1.4, 1.5, or the trunk/development
version of OpenJPEG. Version 2.0.0 or versions earlier than 1.5.0 version of OpenJPEG. The official 2.0.0 release or versions earlier than 1.3.0
are not supported. Furthermore, the 1.5.x version of OpenJPEG is are not supported. Furthermore, the 1.X versions of OpenJPEG are
currently only utilized for read-only purposes. For more information currently only utilized for read-only purposes. In order to write JPEG 2000
images, you must compile the the trunk/development version. For more information
about OpenJPEG, please consult http://www.openjpeg.org. about OpenJPEG, please consult http://www.openjpeg.org.
If you use MacPorts on the mac or if you have a sufficiently recent version of If you use MacPorts on the mac or if you have a sufficiently recent
Linux, your package manager should already provide you with at least version version of Linux, your package manager should already provide you
1.5.1 of OpenJPEG, which means that glymur can be installed ready to read JPEG with a version of OpenJPEG 1.X with which glymur can already use
2000 images. If you use windows, I suggest using the 1.5.1 windows installer for read-only purposes. If your platform is windows, I suggest
provided to you by the OpenJPEG folks at using the 1.5.1 windows installer provided to you by the OpenJPEG
https://code.google.com/p/openjpeg/downloads/list . folks at https://code.google.com/p/openjpeg/downloads/list .
Glymur Installation Glymur Installation
=================== ===================
@ -56,5 +57,5 @@ You can run the tests from within python as follows::
>>> glymur.runtests() >>> glymur.runtests()
Many tests are currently skipped; in fact most of them are skipped if you Many tests are currently skipped; in fact most of them are skipped if you
are relying on OpenJPEG 1.5.1. But the important thing, though, is whether or are relying on OpenJPEG 1.4 or 1.5. The important thing, though, is whether or
not any tests fail. not any tests fail.

View file

@ -1,16 +1,20 @@
"""glymur - read, write, and interrogate JPEG 2000 files """glymur - read, write, and interrogate JPEG 2000 files
""" """
import sys
from .jp2k import Jp2k from .jp2k import Jp2k
from .jp2dump import jp2dump from .jp2dump import jp2dump
from . import data from . import data
from . import test #from . import test
def runtests(): def runtests():
"""Discover and run all tests for the glymur package. """Discover and run all tests for the glymur package.
""" """
if sys.hexversion <= 0x02070000:
import unittest2 as unittest
else:
import unittest import unittest
suite = unittest.defaultTestLoader.discover(__path__[0]) suite = unittest.defaultTestLoader.discover(__path__[0])
unittest.TextTestRunner(verbosity=2).run(suite) unittest.TextTestRunner(verbosity=2).run(suite)

View file

@ -43,14 +43,14 @@ _COLORSPACE_MAP_DISPLAY = {
ROMM_RGB: 'ROMM-RGB'} ROMM_RGB: 'ROMM-RGB'}
# enumerated color channel types # enumerated color channel types
_COLOR = 0 COLOR = 0
_OPACITY = 1 OPACITY = 1
_PRE_MULTIPLIED_OPACITY = 2 PRE_MULTIPLIED_OPACITY = 2
_UNSPECIFIED = 65535 _UNSPECIFIED = 65535
_COLOR_TYPE_MAP_DISPLAY = { _COLOR_TYPE_MAP_DISPLAY = {
_COLOR: 'color', COLOR: 'color',
_OPACITY: 'opacity', OPACITY: 'opacity',
_PRE_MULTIPLIED_OPACITY: 'pre-multiplied opacity', PRE_MULTIPLIED_OPACITY: 'pre-multiplied opacity',
_UNSPECIFIED: 'unspecified'} _UNSPECIFIED: 'unspecified'}
# color channel definitions. # color channel definitions.
@ -58,6 +58,7 @@ RED = 1
GREEN = 2 GREEN = 2
BLUE = 3 BLUE = 3
GREY = 1 GREY = 1
WHOLE_IMAGE = 0
# enumerated color channel associations # enumerated color channel associations
_COLORSPACE = {SRGB: {"R": 1, "G": 2, "B": 3}, _COLORSPACE = {SRGB: {"R": 1, "G": 2, "B": 3},

View file

@ -13,16 +13,22 @@ References
# pylint: disable=C0302,R0903,R0913 # pylint: disable=C0302,R0903,R0913
import collections
import copy import copy
import datetime import datetime
import math import math
import os
import pprint import pprint
import struct import struct
import sys import sys
import uuid import uuid
import warnings import warnings
import xml.etree.cElementTree as ET import xml.etree.cElementTree as ET
if sys.hexversion < 0x02070000:
from ordereddict import OrderedDict
from xml.etree.cElementTree import XMLParserError as ParseError
else:
from xml.etree.cElementTree import ParseError
from collections import OrderedDict
import numpy as np import numpy as np
@ -68,9 +74,6 @@ class Jp2kBox(object):
self.offset = offset self.offset = offset
self.longname = longname self.longname = longname
# should never be used except for last box in file.
self._file_size = -1
def __str__(self): def __str__(self):
msg = "{0} Box ({1})".format(self.longname, self.box_id) msg = "{0} Box ({1})".format(self.longname, self.box_id)
msg += " @ ({0}, {1})".format(self.offset, self.length) msg += " @ ({0}, {1})".format(self.offset, self.length)
@ -113,7 +116,7 @@ class Jp2kBox(object):
if box_length == 0: if box_length == 0:
# The length of the box is presumed to last until the end of # The length of the box is presumed to last until the end of
# the file. Compute the effective length of the box. # the file. Compute the effective length of the box.
num_bytes = self._file_size - fptr.tell() + 8 num_bytes = os.path.getsize(fptr.name) - fptr.tell() + 8
elif box_length == 1: elif box_length == 1:
# The length of the box is in the XL field, a 64-bit value. # The length of the box is in the XL field, a 64-bit value.
@ -342,7 +345,7 @@ class _ICCProfile(object):
def __init__(self, read_buffer): def __init__(self, read_buffer):
self._raw_buffer = read_buffer self._raw_buffer = read_buffer
header = collections.OrderedDict() header = OrderedDict()
data = struct.unpack('>IIBB', self._raw_buffer[0:10]) data = struct.unpack('>IIBB', self._raw_buffer[0:10])
header['Size'] = data[0] header['Size'] = data[0]
@ -423,14 +426,24 @@ class ChannelDefinitionBox(Jp2kBox):
longname : str longname : str
more verbose description of the box. more verbose description of the box.
index : int index : int
number of the channel number of the channel. Defaults to monotonically increasing sequence,
i.e. [0, 1, 2, ...]
channel_type : int channel_type : int
type of the channel type of the channel
association : int association : int
index of the associated color index of the associated color
""" """
def __init__(self, index, channel_type, association, **kwargs): def __init__(self, index=None, channel_type=None, association=None,
**kwargs):
Jp2kBox.__init__(self, box_id='cdef', longname='Channel Definition') Jp2kBox.__init__(self, box_id='cdef', longname='Channel Definition')
# channel type and association must be specified.
if channel_type is None or association is None:
raise IOError("channel_type and association must be specified.")
if index is None:
index = list(range(len(channel_type)))
if len(index) != len(channel_type) or len(index) != len(association): if len(index) != len(channel_type) or len(index) != len(association):
msg = "Length of channel definition box inputs must be the same." msg = "Length of channel definition box inputs must be the same."
raise IOError(msg) raise IOError(msg)
@ -501,8 +514,9 @@ class ChannelDefinitionBox(Jp2kBox):
channel_type = data[1:num_components * 6:3] channel_type = data[1:num_components * 6:3]
association = data[2:num_components * 6:3] association = data[2:num_components * 6:3]
box = ChannelDefinitionBox(index, channel_type, association, box = ChannelDefinitionBox(index=index, channel_type=channel_type,
length=length, offset=offset) association=association, length=length,
offset=offset)
return box return box
@ -1012,8 +1026,9 @@ class JPEG2000SignatureBox(Jp2kBox):
def __str__(self): def __str__(self):
msg = Jp2kBox.__str__(self) msg = Jp2kBox.__str__(self)
msg += '\n Signature: {:02x}{:02x}{:02x}{:02x}' msg += '\n Signature: {0:02x}{1:02x}{2:02x}{3:02x}'
msg = msg.format(*self.signature) msg = msg.format(self.signature[0], self.signature[1],
self.signature[2], self.signature[3])
return msg return msg
def write(self, fptr): def write(self, fptr):
@ -1634,7 +1649,8 @@ class XMLBox(Jp2kBox):
""" """
try: try:
read_buffer = ET.tostring(self.xml, encoding='utf-8') read_buffer = ET.tostring(self.xml, encoding='utf-8')
except AttributeError: except (AttributeError, AssertionError):
# AssertionError on 2.6
read_buffer = ET.tostring(self.xml.getroot(), encoding='utf-8') read_buffer = ET.tostring(self.xml.getroot(), encoding='utf-8')
fptr.write(struct.pack('>I', len(read_buffer) + 8)) fptr.write(struct.pack('>I', len(read_buffer) + 8))
@ -1667,7 +1683,7 @@ class XMLBox(Jp2kBox):
try: try:
xml = ET.fromstring(text) xml = ET.fromstring(text)
except ET.ParseError as parse_error: except ParseError as parse_error:
msg = 'A problem was encountered while parsing an XML box: "{0}"' msg = 'A problem was encountered while parsing an XML box: "{0}"'
msg = msg.format(str(parse_error)) msg = msg.format(str(parse_error))
warnings.warn(msg, UserWarning) warnings.warn(msg, UserWarning)
@ -1910,14 +1926,16 @@ class UUIDBox(Jp2kBox):
# XMP data. Parse as XML. Seems to be a difference between # XMP data. Parse as XML. Seems to be a difference between
# ElementTree in version 2.7 and 3.3. # ElementTree in version 2.7 and 3.3.
if sys.hexversion < 0x03000000: if sys.hexversion < 0x03000000:
parser = ET.XMLParser(encoding='utf-8') #parser = ET.XMLParser(encoding='utf-8')
self.data = ET.fromstringlist(raw_data, parser=parser) #import pdb; pdb.set_trace()
#self.data = ET.fromstringlist(raw_data, parser=parser)
self.data = ET.fromstring(raw_data)
else: else:
text = raw_data.decode('utf-8') text = raw_data.decode('utf-8')
self.data = ET.fromstring(text) self.data = ET.fromstring(text)
elif the_uuid.bytes == b'JpgTiffExif->JP2': elif the_uuid.bytes == b'JpgTiffExif->JP2':
exif_obj = Exif(raw_data) exif_obj = Exif(raw_data)
ifds = collections.OrderedDict() ifds = OrderedDict()
ifds['Image'] = exif_obj.exif_image ifds['Image'] = exif_obj.exif_image
ifds['Photo'] = exif_obj.exif_photo ifds['Photo'] = exif_obj.exif_photo
ifds['GPSInfo'] = exif_obj.exif_gpsinfo ifds['GPSInfo'] = exif_obj.exif_gpsinfo
@ -2067,7 +2085,7 @@ class _Ifd(object):
def __init__(self, endian, read_buffer, offset): def __init__(self, endian, read_buffer, offset):
self.endian = endian self.endian = endian
self.read_buffer = read_buffer self.read_buffer = read_buffer
self.processed_ifd = collections.OrderedDict() self.processed_ifd = OrderedDict()
self.num_tags, = struct.unpack(endian + 'H', self.num_tags, = struct.unpack(endian + 'H',
read_buffer[offset:offset + 2]) read_buffer[offset:offset + 2])
@ -2075,7 +2093,7 @@ class _Ifd(object):
fmt = self.endian + 'HHII' * self.num_tags fmt = self.endian + 'HHII' * self.num_tags
ifd_buffer = read_buffer[offset + 2:offset + 2 + self.num_tags * 12] ifd_buffer = read_buffer[offset + 2:offset + 2 + self.num_tags * 12]
data = struct.unpack(fmt, ifd_buffer) data = struct.unpack(fmt, ifd_buffer)
self.raw_ifd = collections.OrderedDict() self.raw_ifd = OrderedDict()
for j, tag in enumerate(data[0::4]): for j, tag in enumerate(data[0::4]):
# The offset to the tag offset/payload is the offset to the IFD # 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 # plus 2 bytes for the number of tags plus 12 bytes for each

View file

@ -65,6 +65,13 @@ _INFO_CALLBACK = _CMPFUNC(_default_info_handler)
_WARNING_CALLBACK = _CMPFUNC(_default_warning_handler) _WARNING_CALLBACK = _CMPFUNC(_default_warning_handler)
class LibraryNotFoundError(IOError):
"""Raised if functionality is requested without the necessary library.
"""
def __init__(self, msg):
IOError.__init__(self, msg)
class Jp2k(Jp2kBox): class Jp2k(Jp2kBox):
"""JPEG 2000 file. """JPEG 2000 file.
@ -94,7 +101,6 @@ class Jp2k(Jp2kBox):
self.mode = mode self.mode = mode
self.box = [] self.box = []
self._codec_format = None self._codec_format = None
self._file_size = 0
# Parse the file for JP2/JPX contents only if we are reading it. # Parse the file for JP2/JPX contents only if we are reading it.
if mode == 'rb': if mode == 'rb':
@ -118,9 +124,7 @@ class Jp2k(Jp2kBox):
IOError IOError
The file was not JPEG 2000. The file was not JPEG 2000.
""" """
stat = os.stat(self.filename) self.length = os.path.getsize(self.filename)
self.length = stat.st_size
self._file_size = stat.st_size
with open(self.filename, 'rb') as fptr: with open(self.filename, 'rb') as fptr:
@ -226,7 +230,16 @@ class Jp2k(Jp2kBox):
>>> tfile = NamedTemporaryFile(suffix='.jp2', delete=False) >>> tfile = NamedTemporaryFile(suffix='.jp2', delete=False)
>>> j = Jp2k(tfile.name, mode='wb') >>> j = Jp2k(tfile.name, mode='wb')
>>> j.write(data.astype(np.uint8)) >>> j.write(data.astype(np.uint8))
Raises
------
glymur.LibraryNotFoundError
If glymur is unable to load the openjp2 library.
""" """
if _opj2.OPENJP2 is None:
raise LibraryNotFoundError("You must have the development version "
"of OpenJP2 installed before using "
"this functionality.")
cparams = _opj2.set_default_encoder_parameters() cparams = _opj2.set_default_encoder_parameters()
@ -575,7 +588,7 @@ class Jp2k(Jp2kBox):
rlevel : int, optional rlevel : int, optional
Factor by which to rlevel output resolution. Use -1 to get the Factor by which to rlevel output resolution. Use -1 to get the
lowest resolution thumbnail. This is the only keyword option lowest resolution thumbnail. This is the only keyword option
available to use when only OpenJPEG version 1.5.1 is present. available to use when only the OpenJPEG version 1.5.1 is present.
layer : int, optional layer : int, optional
Number of quality layer to decode. Number of quality layer to decode.
area : tuple, optional area : tuple, optional
@ -593,6 +606,9 @@ class Jp2k(Jp2kBox):
Raises Raises
------ ------
glymur.LibraryNotFoundError
If glymur is unable to load either the openjpeg or openjp2
libraries.
IOError IOError
If the image has differing subsample factors. If the image has differing subsample factors.
@ -613,8 +629,13 @@ class Jp2k(Jp2kBox):
""" """
if _opj2.OPENJP2 is not None: if _opj2.OPENJP2 is not None:
img = self._read_openjp2(**kwargs) img = self._read_openjp2(**kwargs)
else: elif _opj.OPENJPEG is not None:
img = self._read_openjpeg(**kwargs) img = self._read_openjpeg(**kwargs)
else:
raise LibraryNotFoundError("You must have either a recent version "
"of OpenJPEG or the development "
"version of OpenJP2 installed before "
"using this functionality.")
return img return img
def _read_openjpeg(self, rlevel=0, verbose=False): def _read_openjpeg(self, rlevel=0, verbose=False):
@ -958,12 +979,13 @@ class Jp2k(Jp2kBox):
Raises Raises
------ ------
NotImplementedError glymur.LibraryNotFoundError
If the openjp2 library is not available. If glymur is unable to load the openjp2 library.
""" """
if _opj2.OPENJP2 is None: if _opj2.OPENJP2 is None:
msg = "Requires openjp2 library." raise LibraryNotFoundError("You must have the development version "
raise NotImplementedError(msg) "of OpenJP2 installed before using "
"this functionality.")
lst = self._read_common(rlevel=rlevel, lst = self._read_common(rlevel=rlevel,
layer=layer, layer=layer,

View file

@ -35,6 +35,9 @@ def glymurrc_fname():
fname = os.path.join(confdir, 'glymurrc') fname = os.path.join(confdir, 'glymurrc')
if os.path.exists(fname): if os.path.exists(fname):
return fname return fname
else:
msg = "Configuration directory '{0}' does not exist.".format(fname)
warnings.warn(msg)
# didn't find a configuration file. # didn't find a configuration file.
return None return None
@ -67,13 +70,6 @@ def load_openjpeg(libopenjpeg_path):
except OSError: except OSError:
openjpeg_lib = None openjpeg_lib = None
if openjpeg_lib is not None:
# Must be at least 1.5.0
openjpeg_lib.opj_version.restype = ctypes.c_char_p
version = openjpeg_lib.opj_version().decode('utf-8')
_, minor, _ = version.split('.')
if minor != '5':
openjpeg_lib = None
return openjpeg_lib return openjpeg_lib
@ -140,7 +136,6 @@ def get_configdir():
Default is $HOME/.config/glymur. You can override this with the Default is $HOME/.config/glymur. You can override this with the
XDG_CONFIG_HOME environment variable. XDG_CONFIG_HOME environment variable.
""" """
if 'XDG_CONFIG_HOME' in os.environ: if 'XDG_CONFIG_HOME' in os.environ:
return os.path.join(os.environ['XDG_CONFIG_HOME'], 'glymur') return os.path.join(os.environ['XDG_CONFIG_HOME'], 'glymur')

View file

@ -4,6 +4,7 @@
# pylint: disable=R0903 # pylint: disable=R0903
import ctypes import ctypes
import sys
from .config import glymur_config from .config import glymur_config
_, OPENJPEG = glymur_config() _, OPENJPEG = glymur_config()
@ -11,6 +12,20 @@ _, OPENJPEG = glymur_config()
PATH_LEN = 4096 # maximum allowed size for filenames PATH_LEN = 4096 # maximum allowed size for filenames
def version():
"""Wrapper for opj_version library routine."""
OPENJPEG.opj_version.restype = ctypes.c_char_p
library_version = OPENJPEG.opj_version()
if sys.hexversion >= 0x03000000:
return library_version.decode('utf-8')
else:
return library_version
# Need to get the minor version, make sure we are at least at 1.4.x
#import pdb; pdb.set_trace()
_MINOR = version().split('.')[1]
class EventMgrType(ctypes.Structure): class EventMgrType(ctypes.Structure):
"""Message handler object. """Message handler object.
@ -86,8 +101,10 @@ class DecompressionParametersType(ctypes.Structure):
("jpwl_max_tiles", ctypes.c_int), ("jpwl_max_tiles", ctypes.c_int),
# cp_limit_decoding: whether decoding should be done on the # cp_limit_decoding: whether decoding should be done on the
# entire codestream or be limited to the main header # entire codestream or be limited to the main header
("cp_limit_decoding", ctypes.c_int), ("cp_limit_decoding", ctypes.c_int)]
("flags", ctypes.c_uint)]
if _MINOR == '5':
_fields_.append(("flags", ctypes.c_uint))
class ImageCompType(ctypes.Structure): class ImageCompType(ctypes.Structure):
@ -204,10 +221,3 @@ def setup_decoder(dinfo, dparams):
ctypes.POINTER(DecompressionParametersType)] ctypes.POINTER(DecompressionParametersType)]
OPENJPEG.opj_setup_decoder.argtypes = argtypes OPENJPEG.opj_setup_decoder.argtypes = argtypes
OPENJPEG.opj_setup_decoder(dinfo, dparams) OPENJPEG.opj_setup_decoder(dinfo, dparams)
def version():
"""Wrapper for opj_version library routine."""
OPENJPEG.opj_version.restype = ctypes.c_char_p
library_version = OPENJPEG.opj_version()
return library_version.decode('utf-8')

View file

@ -6,7 +6,11 @@ import shutil
import struct import struct
import sys import sys
import tempfile import tempfile
import unittest
if sys.hexversion < 0x02070000:
import unittest2 as unittest
else:
import unittest
import numpy as np import numpy as np

View file

@ -1,6 +1,12 @@
#pylint: disable-all #pylint: disable-all
import ctypes import ctypes
import unittest import re
import sys
if sys.hexversion < 0x02070000:
import unittest2 as unittest
else:
import unittest
import glymur import glymur
@ -16,13 +22,18 @@ class TestOpenJPEG(unittest.TestCase):
pass pass
def test_version(self): def test_version(self):
v = glymur.lib._openjpeg.version() version = glymur.lib._openjpeg.version()
parts = v.split('.') regex = re.compile('1.[345].[0-9]')
self.assertEqual(parts[0], '1') if sys.hexversion <= 0x03020000:
self.assertEqual(parts[1], '5') self.assertRegexpMatches(version, regex)
else:
self.assertRegex(version, regex)
def test_set_default_decoder_parameters(self): def test_set_default_decoder_parameters(self):
# Verify that we properly set the default decode parameters. # Verify that we properly set the default decode parameters.
version = glymur.lib._openjpeg.version()
minor = int(version.split('.')[1])
dp = glymur.lib._openjpeg.DecompressionParametersType() dp = glymur.lib._openjpeg.DecompressionParametersType()
glymur.lib._openjpeg.set_default_decoder_parameters(ctypes.byref(dp)) glymur.lib._openjpeg.set_default_decoder_parameters(ctypes.byref(dp))
@ -36,4 +47,6 @@ class TestOpenJPEG(unittest.TestCase):
self.assertEqual(dp.jpwl_exp_comps, 0) self.assertEqual(dp.jpwl_exp_comps, 0)
self.assertEqual(dp.jpwl_max_tiles, 0) self.assertEqual(dp.jpwl_max_tiles, 0)
self.assertEqual(dp.cp_limit_decoding, 0) self.assertEqual(dp.cp_limit_decoding, 0)
if minor > 4:
# Introduced in 1.5.x
self.assertEqual(dp.flags, 0) self.assertEqual(dp.flags, 0)

View file

@ -4,7 +4,6 @@ import pkg_resources
import re import re
import sys import sys
import tempfile import tempfile
import unittest
import warnings import warnings
if sys.hexversion < 0x03000000: if sys.hexversion < 0x03000000:
@ -12,6 +11,11 @@ if sys.hexversion < 0x03000000:
else: else:
from io import StringIO from io import StringIO
if sys.hexversion < 0x02070000:
import unittest2 as unittest
else:
import unittest
import glymur import glymur

View file

@ -3,7 +3,11 @@ import os
import struct import struct
import sys import sys
import tempfile import tempfile
import unittest
if sys.hexversion < 0x02070000:
import unittest2 as unittest
else:
import unittest
import numpy as np import numpy as np
import pkg_resources import pkg_resources

View file

@ -7,7 +7,12 @@ import imp
import os import os
import sys import sys
import tempfile import tempfile
import unittest
if sys.hexversion < 0x02070000:
import unittest2 as unittest
else:
import unittest
if sys.hexversion <= 0x03030000: if sys.hexversion <= 0x03030000:
from mock import patch from mock import patch
else: else:
@ -21,32 +26,27 @@ from glymur import Jp2k
from glymur.lib import openjp2 as opj2 from glymur.lib import openjp2 as opj2
@unittest.skip("Cannot work when both OPENJPEG and OPENJP2 are both present.") @unittest.skipIf(sys.hexversion < 0x03020000,
"TemporaryDirectory introduced in 3.2.")
@unittest.skipIf(glymur.lib.openjp2.OPENJP2 is None, @unittest.skipIf(glymur.lib.openjp2.OPENJP2 is None,
"Needs openjp2 library first before these tests make sense.") "Needs openjp2 library first before these tests make sense.")
@unittest.skipIf(sys.hexversion < 0x03020000,
"Uses features introduced in 3.2.")
class TestSuite(unittest.TestCase): class TestSuite(unittest.TestCase):
@classmethod @classmethod
def setUpClass(cls): def setUpClass(cls):
# Monkey patch the package so as to ignore OPENJPEG if it exists. imp.reload(glymur)
cls.openjpeg = glymur.lib.openjpeg._OPENJPEG imp.reload(glymur.lib.openjp2)
glymur.lib.openjp2._OPENJPEG = None
@classmethod @classmethod
def tearDownClass(cls): def tearDownClass(cls):
# Restore OPENJPEG
glymur.lib.openjpeg._OPENJPEG = cls.openjpeg
def setUp(self):
imp.reload(glymur) imp.reload(glymur)
imp.reload(glymur.lib.openjp2) imp.reload(glymur.lib.openjp2)
def setUp(self):
self.jp2file = glymur.data.nemo() self.jp2file = glymur.data.nemo()
def tearDown(self): def tearDown(self):
imp.reload(glymur) pass
imp.reload(glymur.lib.openjp2)
def test_config_file_via_environ(self): def test_config_file_via_environ(self):
"""Verify that we can read a configuration file set via environ var.""" """Verify that we can read a configuration file set via environ var."""
@ -54,11 +54,11 @@ class TestSuite(unittest.TestCase):
configdir = os.path.join(tdir, 'glymur') configdir = os.path.join(tdir, 'glymur')
os.mkdir(configdir) os.mkdir(configdir)
filename = os.path.join(configdir, 'glymurrc') filename = os.path.join(configdir, 'glymurrc')
with open(filename, 'wb') as tfile: with open(filename, 'wt') as tfile:
tfile.write('[library]\n'.encode()) tfile.write('[library]\n')
libloc = glymur.lib.openjp2.OPENJP2._name libloc = glymur.lib.openjp2.OPENJP2._name
line = 'openjp2: {0}\n'.format(libloc) line = 'openjp2: {0}\n'.format(libloc)
tfile.write(line.encode()) tfile.write(line)
tfile.flush() tfile.flush()
with patch.dict('os.environ', {'XDG_CONFIG_HOME': tdir}): with patch.dict('os.environ', {'XDG_CONFIG_HOME': tdir}):
imp.reload(glymur.lib.openjp2) imp.reload(glymur.lib.openjp2)

View file

@ -4,7 +4,12 @@ import os
import struct import struct
import sys import sys
import tempfile import tempfile
import unittest
if sys.hexversion < 0x02070000:
import unittest2 as unittest
else:
import unittest
import warnings import warnings
from xml.etree import cElementTree as ET from xml.etree import cElementTree as ET

View file

@ -1,9 +1,14 @@
#pylint: disable-all #pylint: disable-all
import doctest import doctest
import os import os
import sys
import tempfile import tempfile
import xml.etree.cElementTree as ET import xml.etree.cElementTree as ET
import unittest
if sys.hexversion < 0x02070000:
import unittest2 as unittest
else:
import unittest
import numpy as np import numpy as np
import pkg_resources import pkg_resources
@ -11,6 +16,8 @@ import pkg_resources
import glymur import glymur
from glymur import Jp2k from glymur import Jp2k
from glymur.jp2box import * from glymur.jp2box import *
from glymur.core import COLOR, OPACITY
from glymur.core import RED, GREEN, BLUE, GREY, WHOLE_IMAGE
# Doc tests should be run as well. # Doc tests should be run as well.
@ -79,12 +86,19 @@ class TestChannelDefinition(unittest.TestCase):
def tearDown(self): def tearDown(self):
pass pass
def test_rgb(self): def test_cdef_no_inputs(self):
"""channel_type and association are required inputs."""
with self.assertRaises(IOError):
glymur.jp2box.ChannelDefinitionBox()
def test_rgb_with_index(self):
"""Just regular RGB.""" """Just regular RGB."""
j2k = Jp2k(self.j2kfile) j2k = Jp2k(self.j2kfile)
channel_type = [COLOR, COLOR, COLOR]
association = [RED, GREEN, BLUE]
cdef = glymur.jp2box.ChannelDefinitionBox(index=[0, 1, 2], cdef = glymur.jp2box.ChannelDefinitionBox(index=[0, 1, 2],
channel_type=[0, 0, 0], channel_type=channel_type,
association=[1, 2, 3]) association=association)
boxes = [self.ihdr, self.colr_rgb, cdef] boxes = [self.ihdr, self.colr_rgb, cdef]
self.jp2h.box = boxes self.jp2h.box = boxes
boxes = [self.jP, self.ftyp, self.jp2h, self.jp2c] boxes = [self.jP, self.ftyp, self.jp2h, self.jp2c]
@ -96,15 +110,41 @@ class TestChannelDefinition(unittest.TestCase):
boxes = [box.box_id for box in jp2h.box] boxes = [box.box_id for box in jp2h.box]
self.assertEqual(boxes, ['ihdr', 'colr', 'cdef']) self.assertEqual(boxes, ['ihdr', 'colr', 'cdef'])
self.assertEqual(jp2h.box[2].index, (0, 1, 2)) self.assertEqual(jp2h.box[2].index, (0, 1, 2))
self.assertEqual(jp2h.box[2].channel_type, (0, 0, 0)) self.assertEqual(jp2h.box[2].channel_type,
self.assertEqual(jp2h.box[2].association, (1, 2, 3)) (COLOR, COLOR, COLOR))
self.assertEqual(jp2h.box[2].association,
(RED, GREEN, BLUE))
def test_rgb(self):
"""Just regular RGB, but don't supply the optional index."""
j2k = Jp2k(self.j2kfile)
channel_type = [COLOR, COLOR, COLOR]
association = [RED, GREEN, BLUE]
cdef = glymur.jp2box.ChannelDefinitionBox(channel_type=channel_type,
association=association)
boxes = [self.ihdr, self.colr_rgb, cdef]
self.jp2h.box = boxes
boxes = [self.jP, self.ftyp, self.jp2h, self.jp2c]
with tempfile.NamedTemporaryFile(suffix=".jp2") as tfile:
j2k.wrap(tfile.name, boxes=boxes)
jp2 = Jp2k(tfile.name)
jp2h = jp2.box[2]
boxes = [box.box_id for box in jp2h.box]
self.assertEqual(boxes, ['ihdr', 'colr', 'cdef'])
self.assertEqual(jp2h.box[2].index, (0, 1, 2))
self.assertEqual(jp2h.box[2].channel_type,
(COLOR, COLOR, COLOR))
self.assertEqual(jp2h.box[2].association,
(RED, GREEN, BLUE))
def test_rgba(self): def test_rgba(self):
"""Just regular RGBA.""" """Just regular RGBA."""
j2k = Jp2k(self.four_planes) j2k = Jp2k(self.four_planes)
cdef = glymur.jp2box.ChannelDefinitionBox(index=[0, 1, 2, 3], channel_type = (COLOR, COLOR, COLOR, OPACITY)
channel_type=[0, 0, 0, 1], association = (RED, GREEN, BLUE, WHOLE_IMAGE)
association=[1, 2, 3, 0]) cdef = glymur.jp2box.ChannelDefinitionBox(channel_type=channel_type,
association=association)
boxes = [self.ihdr, self.colr_rgb, cdef] boxes = [self.ihdr, self.colr_rgb, cdef]
self.jp2h.box = boxes self.jp2h.box = boxes
boxes = [self.jP, self.ftyp, self.jp2h, self.jp2c] boxes = [self.jP, self.ftyp, self.jp2h, self.jp2c]
@ -116,15 +156,16 @@ class TestChannelDefinition(unittest.TestCase):
boxes = [box.box_id for box in jp2h.box] boxes = [box.box_id for box in jp2h.box]
self.assertEqual(boxes, ['ihdr', 'colr', 'cdef']) self.assertEqual(boxes, ['ihdr', 'colr', 'cdef'])
self.assertEqual(jp2h.box[2].index, (0, 1, 2, 3)) self.assertEqual(jp2h.box[2].index, (0, 1, 2, 3))
self.assertEqual(jp2h.box[2].channel_type, (0, 0, 0, 1)) self.assertEqual(jp2h.box[2].channel_type, channel_type)
self.assertEqual(jp2h.box[2].association, (1, 2, 3, 0)) self.assertEqual(jp2h.box[2].association, association)
def test_bad_rgba(self): def test_bad_rgba(self):
"""R, G, and B must be specified.""" """R, G, and B must be specified."""
j2k = Jp2k(self.four_planes) j2k = Jp2k(self.four_planes)
cdef = glymur.jp2box.ChannelDefinitionBox(index=[0, 1, 2, 3], channel_type = (COLOR, COLOR, OPACITY, OPACITY)
channel_type=[0, 0, 1, 1], association = (RED, GREEN, BLUE, WHOLE_IMAGE)
association=[1, 2, 3, 0]) cdef = glymur.jp2box.ChannelDefinitionBox(channel_type=channel_type,
association=association)
boxes = [self.ihdr, self.colr_rgb, cdef] boxes = [self.ihdr, self.colr_rgb, cdef]
self.jp2h.box = boxes self.jp2h.box = boxes
boxes = [self.jP, self.ftyp, self.jp2h, self.jp2c] boxes = [self.jP, self.ftyp, self.jp2h, self.jp2c]
@ -135,9 +176,10 @@ class TestChannelDefinition(unittest.TestCase):
def test_grey(self): def test_grey(self):
"""Just regular greyscale.""" """Just regular greyscale."""
j2k = Jp2k(self.one_plane) j2k = Jp2k(self.one_plane)
cdef = glymur.jp2box.ChannelDefinitionBox(index=[0], channel_type = (COLOR,)
channel_type=[0], association = (GREY,)
association=[1]) cdef = glymur.jp2box.ChannelDefinitionBox(channel_type=channel_type,
association=association)
boxes = [self.ihdr, self.colr_gr, cdef] boxes = [self.ihdr, self.colr_gr, cdef]
self.jp2h.box = boxes self.jp2h.box = boxes
boxes = [self.jP, self.ftyp, self.jp2h, self.jp2c] boxes = [self.jP, self.ftyp, self.jp2h, self.jp2c]
@ -149,15 +191,16 @@ class TestChannelDefinition(unittest.TestCase):
boxes = [box.box_id for box in jp2h.box] boxes = [box.box_id for box in jp2h.box]
self.assertEqual(boxes, ['ihdr', 'colr', 'cdef']) self.assertEqual(boxes, ['ihdr', 'colr', 'cdef'])
self.assertEqual(jp2h.box[2].index, (0,)) self.assertEqual(jp2h.box[2].index, (0,))
self.assertEqual(jp2h.box[2].channel_type, (0,)) self.assertEqual(jp2h.box[2].channel_type, channel_type)
self.assertEqual(jp2h.box[2].association, (1,)) self.assertEqual(jp2h.box[2].association, association)
def test_grey_alpha(self): def test_grey_alpha(self):
"""Just regular greyscale plus alpha.""" """Just regular greyscale plus alpha."""
j2k = Jp2k(self.two_planes) j2k = Jp2k(self.two_planes)
cdef = glymur.jp2box.ChannelDefinitionBox(index=[0, 1], channel_type = (COLOR, OPACITY)
channel_type=[0, 1], association = (GREY, WHOLE_IMAGE)
association=[1, 0]) cdef = glymur.jp2box.ChannelDefinitionBox(channel_type=channel_type,
association=association)
boxes = [self.ihdr, self.colr_gr, cdef] boxes = [self.ihdr, self.colr_gr, cdef]
self.jp2h.box = boxes self.jp2h.box = boxes
boxes = [self.jP, self.ftyp, self.jp2h, self.jp2c] boxes = [self.jP, self.ftyp, self.jp2h, self.jp2c]
@ -169,17 +212,19 @@ class TestChannelDefinition(unittest.TestCase):
boxes = [box.box_id for box in jp2h.box] boxes = [box.box_id for box in jp2h.box]
self.assertEqual(boxes, ['ihdr', 'colr', 'cdef']) self.assertEqual(boxes, ['ihdr', 'colr', 'cdef'])
self.assertEqual(jp2h.box[2].index, (0, 1)) self.assertEqual(jp2h.box[2].index, (0, 1))
self.assertEqual(jp2h.box[2].channel_type, (0, 1)) self.assertEqual(jp2h.box[2].channel_type, channel_type)
self.assertEqual(jp2h.box[2].association, (1, 0)) self.assertEqual(jp2h.box[2].association, association)
def test_bad_grey_alpha(self): def test_bad_grey_alpha(self):
"""A greyscale image with alpha layer must specify Y""" """A greyscale image with alpha layer must specify a color channel"""
j2k = Jp2k(self.two_planes) j2k = Jp2k(self.two_planes)
channel_type = (OPACITY, OPACITY)
association = (GREY, WHOLE_IMAGE)
# This cdef box # This cdef box
cdef = glymur.jp2box.ChannelDefinitionBox(index=[0, 1], cdef = glymur.jp2box.ChannelDefinitionBox(channel_type=channel_type,
channel_type=[1, 1], association=association)
association=[0, 1])
boxes = [self.ihdr, self.colr_gr, cdef] boxes = [self.ihdr, self.colr_gr, cdef]
self.jp2h.box = boxes self.jp2h.box = boxes
boxes = [self.jP, self.ftyp, self.jp2h, self.jp2c] boxes = [self.jP, self.ftyp, self.jp2h, self.jp2c]
@ -191,9 +236,10 @@ class TestChannelDefinition(unittest.TestCase):
"""There can only be one channel definition box in the jp2 header.""" """There can only be one channel definition box in the jp2 header."""
j2k = Jp2k(self.j2kfile) j2k = Jp2k(self.j2kfile)
cdef = glymur.jp2box.ChannelDefinitionBox(index=[0, 1, 2], channel_type = (COLOR, COLOR, COLOR)
channel_type=[0, 0, 0], association = (RED, GREEN, BLUE)
association=[1, 2, 3]) cdef = glymur.jp2box.ChannelDefinitionBox(channel_type=channel_type,
association=association)
boxes = [self.ihdr, cdef, self.colr_rgb, cdef] boxes = [self.ihdr, cdef, self.colr_rgb, cdef]
self.jp2h.box = boxes self.jp2h.box = boxes
@ -209,9 +255,10 @@ class TestChannelDefinition(unittest.TestCase):
boxes = [self.ihdr, self.colr_rgb] boxes = [self.ihdr, self.colr_rgb]
self.jp2h.box = boxes self.jp2h.box = boxes
cdef = glymur.jp2box.ChannelDefinitionBox(index=[0, 1, 2], channel_type = (COLOR, COLOR, COLOR)
channel_type=[0, 0, 0], association = (RED, GREEN, BLUE)
association=[1, 2, 3]) cdef = glymur.jp2box.ChannelDefinitionBox(channel_type=channel_type,
association=association)
boxes = [self.jP, self.ftyp, self.jp2h, cdef, self.jp2c] boxes = [self.jP, self.ftyp, self.jp2h, cdef, self.jp2c]
@ -223,18 +270,20 @@ class TestChannelDefinition(unittest.TestCase):
# Channel types are limited to 0, 1, 2, 65535 # Channel types are limited to 0, 1, 2, 65535
# Should reject if not all of index, channel_type, association the # Should reject if not all of index, channel_type, association the
# same length. # same length.
channel_type = (COLOR, COLOR, 3)
association = (RED, GREEN, BLUE)
with self.assertRaises(IOError): with self.assertRaises(IOError):
box = glymur.jp2box.ChannelDefinitionBox(index=[0, 1, 2], box = glymur.jp2box.ChannelDefinitionBox(channel_type=channel_type,
channel_type=[0, 0, 3], association=association)
association=[1, 2, 3])
def test_wrong_lengths(self): def test_wrong_lengths(self):
# Should reject if not all of index, channel_type, association the # Should reject if not all of index, channel_type, association the
# same length. # same length.
channel_type = (COLOR, COLOR)
association = (RED, GREEN, BLUE)
with self.assertRaises(IOError): with self.assertRaises(IOError):
box = glymur.jp2box.ChannelDefinitionBox(index=[0, 1, 2], box = glymur.jp2box.ChannelDefinitionBox(channel_type=channel_type,
channel_type=[0, 0], association=association)
association=[1, 2, 3])
@unittest.skipIf(os.name == "nt", "Temporary file issue on window.") @unittest.skipIf(os.name == "nt", "Temporary file issue on window.")
@ -422,6 +471,7 @@ class TestJp2Boxes(unittest.TestCase):
def setUp(self): def setUp(self):
self.j2kfile = glymur.data.goodstuff() self.j2kfile = glymur.data.goodstuff()
self.jp2file = glymur.data.nemo()
def tearDown(self): def tearDown(self):
pass pass
@ -517,7 +567,7 @@ class TestJp2Boxes(unittest.TestCase):
@unittest.skipIf(os.name == "nt", "Temporary file issue on window.") @unittest.skipIf(os.name == "nt", "Temporary file issue on window.")
def test_wrap_jp2(self): def test_wrap_jp2(self):
j2k = Jp2k(self.j2kfile) j2k = Jp2k(self.jp2file)
with tempfile.NamedTemporaryFile(suffix=".jp2") as tfile: with tempfile.NamedTemporaryFile(suffix=".jp2") as tfile:
jp2 = j2k.wrap(tfile.name) jp2 = j2k.wrap(tfile.name)
boxes = [box.box_id for box in jp2.box] boxes = [box.box_id for box in jp2.box]

View file

@ -7,7 +7,12 @@ import struct
import sys import sys
import tempfile import tempfile
import uuid import uuid
import unittest
if sys.hexversion < 0x02070000:
import unittest2 as unittest
else:
import unittest
if sys.hexversion <= 0x03030000: if sys.hexversion <= 0x03030000:
from mock import patch from mock import patch
else: else:
@ -34,11 +39,52 @@ def load_tests(loader, tests, ignore):
if os.name == "nt": if os.name == "nt":
# Can't do it on windows, temporary file issue. # Can't do it on windows, temporary file issue.
return tests return tests
if sys.hexversion < 0x02070000:
# Don't bother with doctests on 2.6 for the time being.
return tests
if glymur.lib.openjp2.OPENJP2 is not None: if glymur.lib.openjp2.OPENJP2 is not None:
tests.addTests(doctest.DocTestSuite('glymur.jp2k')) tests.addTests(doctest.DocTestSuite('glymur.jp2k'))
return tests return tests
class TestConfig(unittest.TestCase):
def setUp(self):
self.jp2file = glymur.data.nemo()
self.j2kfile = glymur.data.goodstuff()
def tearDown(self):
pass
def test_read_without_library_backing_us_up(self):
"""Don't have either openjp2 or openjpeg libraries? Must error out.
"""
with patch('glymur.lib.openjp2.OPENJP2', new=None):
with patch('glymur.lib.openjpeg.OPENJPEG', new=None):
with self.assertRaises(glymur.jp2k.LibraryNotFoundError):
d = glymur.Jp2k(self.jp2file).read()
def test_read_bands_without_library_backing_us_up(self):
"""Don't have openjp2 library? Must error out.
"""
with patch('glymur.lib.openjp2.OPENJP2', new=None):
with patch('glymur.lib.openjpeg.OPENJPEG', new=None):
with self.assertRaises(glymur.jp2k.LibraryNotFoundError):
d = glymur.Jp2k(self.jp2file).read_bands()
@unittest.skipIf(os.name == "nt", "NamedTemporaryFile issue on windows")
def test_write_without_library_backing_us_up(self):
"""Don't have openjp2 library? Must error out.
"""
data = glymur.Jp2k(self.j2kfile).read()
with patch('glymur.lib.openjp2.OPENJP2', new=None):
with patch('glymur.lib.openjpeg.OPENJPEG', new=None):
with self.assertRaises(glymur.jp2k.LibraryNotFoundError):
with tempfile.NamedTemporaryFile(suffix='.jp2') as tfile:
ofile = Jp2k(tfile.name, 'wb')
ofile.write(data)
@unittest.skipIf(os.name == "nt", "NamedTemporaryFile issue on windows") @unittest.skipIf(os.name == "nt", "NamedTemporaryFile issue on windows")
@unittest.skipIf(glymur.lib.openjp2.OPENJP2 is None, @unittest.skipIf(glymur.lib.openjp2.OPENJP2 is None,
"Missing openjp2 library.") "Missing openjp2 library.")
@ -705,13 +751,6 @@ class TestJp2k15(unittest.TestCase):
def tearDown(self): def tearDown(self):
pass pass
def test_bands(self):
"""Reading individual bands is an advanced maneuver.
"""
jp2k = Jp2k(self.j2kfile)
with self.assertRaises(NotImplementedError):
jp2k.read_bands()
def test_area(self): def test_area(self):
"""Area option not allowed for 1.5.1. """Area option not allowed for 1.5.1.
""" """

View file

@ -10,7 +10,12 @@ import platform
import re import re
import sys import sys
from xml.etree import cElementTree as ET from xml.etree import cElementTree as ET
import unittest
if sys.hexversion < 0x02070000:
import unittest2 as unittest
else:
import unittest
import warnings import warnings
if sys.hexversion <= 0x03030000: if sys.hexversion <= 0x03030000:
@ -102,7 +107,6 @@ class TestSuite(unittest.TestCase):
self.assertTrue(peak_tolerance(jpdata[:, :, 2], pgxdata) < 33) self.assertTrue(peak_tolerance(jpdata[:, :, 2], pgxdata) < 33)
self.assertTrue(mse(jpdata[:, :, 2], pgxdata) < 55.8) self.assertTrue(mse(jpdata[:, :, 2], pgxdata) < 55.8)
@unittest.skip("Known failure in OPENJPEG test suite.")
def test_ETS_C0P0_p0_05_j2k(self): def test_ETS_C0P0_p0_05_j2k(self):
jfile = os.path.join(data_root, 'input/conformance/p0_05.j2k') jfile = os.path.join(data_root, 'input/conformance/p0_05.j2k')
jp2k = Jp2k(jfile) jp2k = Jp2k(jfile)
@ -114,17 +118,19 @@ class TestSuite(unittest.TestCase):
self.assertTrue(peak_tolerance(jpdata[0], pgxdata) < 54) self.assertTrue(peak_tolerance(jpdata[0], pgxdata) < 54)
self.assertTrue(mse(jpdata[0], pgxdata) < 68) self.assertTrue(mse(jpdata[0], pgxdata) < 68)
@unittest.skip("Known failure in OPENJPEG test suite.") @unittest.skip("8-bit pgx data vs 12-bit j2k data")
def test_ETS_C0P0_p0_06_j2k(self): def test_ETS_C0P0_p0_06_j2k(self):
jfile = os.path.join(data_root, 'input/conformance/p0_06.j2k') jfile = os.path.join(data_root, 'input/conformance/p0_06.j2k')
jp2k = Jp2k(jfile) jp2k = Jp2k(jfile)
jpdata = jp2k.read(rlevel=3) jpdata = jp2k.read_bands(rlevel=3)
pgxfile = os.path.join(data_root, pgxfile = os.path.join(data_root,
'baseline/conformance/c0p0_06.pgx') 'baseline/conformance/c0p0_06.pgx')
pgxdata = read_pgx(pgxfile) pgxdata = read_pgx(pgxfile)
self.assertTrue(peak_tolerance(jpdata[:, :, 0], pgxdata) < 109) tol = peak_tolerance(jpdata[0], pgxdata)
self.assertTrue(mse(jpdata[:, :, 0], pgxdata) < 743) self.assertTrue(tol < 109)
m = mse(jpdata[0], pgxdata)
self.assertTrue(m < 743)
@unittest.skip("Known failure in OPENJPEG test suite.") @unittest.skip("Known failure in OPENJPEG test suite.")
def test_ETS_C0P0_p0_07_j2k(self): def test_ETS_C0P0_p0_07_j2k(self):
@ -139,7 +145,7 @@ class TestSuite(unittest.TestCase):
self.assertTrue(peak_tolerance(jpdata[:, :, 0], pgxdata) < 10) self.assertTrue(peak_tolerance(jpdata[:, :, 0], pgxdata) < 10)
self.assertTrue(mse(jpdata[:, :, 0], pgxdata) < 0.34) self.assertTrue(mse(jpdata[:, :, 0], pgxdata) < 0.34)
@unittest.skip("Known failure in OPENJPEG test suite.") @unittest.skip("8-bit pgx data vs 12-bit j2k data")
def test_ETS_C0P0_p0_08_j2k(self): def test_ETS_C0P0_p0_08_j2k(self):
jfile = os.path.join(data_root, 'input/conformance/p0_08.j2k') jfile = os.path.join(data_root, 'input/conformance/p0_08.j2k')
jp2k = Jp2k(jfile) jp2k = Jp2k(jfile)
@ -210,7 +216,7 @@ class TestSuite(unittest.TestCase):
'baseline/conformance/c0p0_13.pgx') 'baseline/conformance/c0p0_13.pgx')
pgxdata = read_pgx(pgxfile) pgxdata = read_pgx(pgxfile)
np.testing.assert_array_equal(jpdata, pgxdata) np.testing.assert_array_equal(jpdata[:, :, 0], pgxdata)
@unittest.skip("Known failure in OPENJPEG test suite.") @unittest.skip("Known failure in OPENJPEG test suite.")
def test_ETS_C0P0_p0_14_j2k(self): def test_ETS_C0P0_p0_14_j2k(self):
@ -279,27 +285,20 @@ class TestSuite(unittest.TestCase):
'baseline/conformance/c0p1_02.pgx') 'baseline/conformance/c0p1_02.pgx')
pgxdata = read_pgx(pgxfile) pgxdata = read_pgx(pgxfile)
print(peak_tolerance(jpdata[:, :, 0], pgxdata))
print(peak_tolerance(jpdata[:, :, 1], pgxdata))
print(peak_tolerance(jpdata[:, :, 2], pgxdata))
self.assertTrue(peak_tolerance(jpdata[:, :, 0], pgxdata) < 35) self.assertTrue(peak_tolerance(jpdata[:, :, 0], pgxdata) < 35)
self.assertTrue(mse(jpdata[:, :, 0], pgxdata) < 74) self.assertTrue(mse(jpdata[:, :, 0], pgxdata) < 74)
@unittest.skip("Known failure in OPENJPEG test suite operation.")
def test_ETS_C0P1_p1_03_j2k(self): def test_ETS_C0P1_p1_03_j2k(self):
jfile = os.path.join(data_root, 'input/conformance/p1_03.j2k') jfile = os.path.join(data_root, 'input/conformance/p1_03.j2k')
jp2k = Jp2k(jfile) jp2k = Jp2k(jfile)
jpdata = jp2k.read(rlevel=3) jpdata = jp2k.read_bands(rlevel=3)
pgxfile = os.path.join(data_root, pgxfile = os.path.join(data_root,
'baseline/conformance/c0p1_03.pgx') 'baseline/conformance/c0p1_03.pgx')
pgxdata = read_pgx(pgxfile) pgxdata = read_pgx(pgxfile)
print(peak_tolerance(jpdata[:, :, 0], pgxdata)) self.assertTrue(peak_tolerance(jpdata[0], pgxdata) < 28)
print(peak_tolerance(jpdata[:, :, 1], pgxdata)) self.assertTrue(mse(jpdata[0], pgxdata) < 18.8)
print(peak_tolerance(jpdata[:, :, 2], pgxdata))
self.assertTrue(peak_tolerance(jpdata[:, :, 0], pgxdata) < 28)
self.assertTrue(mse(jpdata[:, :, 0], pgxdata) < 18.8)
@unittest.skip("Known failure in OPENJPEG test suite operation.") @unittest.skip("Known failure in OPENJPEG test suite operation.")
def test_ETS_C0P1_p1_04_j2k(self): def test_ETS_C0P1_p1_04_j2k(self):
@ -359,20 +358,17 @@ class TestSuite(unittest.TestCase):
self.assertTrue(peak_tolerance(jpdata[:, :, 0], pgxdata) < 128) self.assertTrue(peak_tolerance(jpdata[:, :, 0], pgxdata) < 128)
self.assertTrue(mse(jpdata[:, :, 0], pgxdata) < 16384) self.assertTrue(mse(jpdata[:, :, 0], pgxdata) < 16384)
@unittest.skip("Known failure in OPENJPEG test suite operation.") @unittest.skip("fprintf stderr output in r2345.")
def test_ETS_C0P1_p1_07_j2k(self): def test_ETS_C0P1_p1_07_j2k(self):
jfile = os.path.join(data_root, 'input/conformance/p1_07.j2k') jfile = os.path.join(data_root, 'input/conformance/p1_07.j2k')
jp2k = Jp2k(jfile) jp2k = Jp2k(jfile)
jpdata = jp2k.read(rlevel=0) jpdata = jp2k.read_bands(rlevel=0)
pgxfile = os.path.join(data_root, pgxfile = os.path.join(data_root,
'baseline/conformance/c0p1_07.pgx') 'baseline/conformance/c0p1_07.pgx')
pgxdata = read_pgx(pgxfile) pgxdata = read_pgx(pgxfile)
# This one works. np.testing.assert_array_equal(jpdata[0], pgxdata)
np.testing.assert_array_equal(jpdata[:, :, 0], pgxdata)
# This one does not.
np.testing.assert_array_equal(jpdata[:, :, 1], pgxdata)
def test_ETS_C1P0_p0_01_j2k(self): def test_ETS_C1P0_p0_01_j2k(self):
jfile = os.path.join(data_root, 'input/conformance/p0_01.j2k') jfile = os.path.join(data_root, 'input/conformance/p0_01.j2k')
@ -7764,6 +7760,9 @@ class TestSuite15(unittest.TestCase):
jfile = os.path.join(data_root, 'input/conformance/file9.jp2') jfile = os.path.join(data_root, 'input/conformance/file9.jp2')
jp2k = Jp2k(jfile) jp2k = Jp2k(jfile)
jpdata = jp2k.read() jpdata = jp2k.read()
if glymur.lib.openjpeg.version().startswith('1.3'):
self.assertEqual(jpdata.shape, (512, 768))
else:
self.assertEqual(jpdata.shape, (512, 768, 3)) self.assertEqual(jpdata.shape, (512, 768, 3))
def test_NR_DEC_Bretagne2_j2k_1_decode(self): def test_NR_DEC_Bretagne2_j2k_1_decode(self):

View file

@ -6,7 +6,12 @@ seem like logical negative tests to add.
import os import os
import sys import sys
import tempfile import tempfile
import unittest
if sys.hexversion < 0x02070000:
import unittest2 as unittest
else:
import unittest
import warnings import warnings
import numpy as np import numpy as np
@ -14,29 +19,14 @@ import pkg_resources
from glymur.lib import openjp2 as opj2 from glymur.lib import openjp2 as opj2
# Need some combination of matplotlib, PIL, or scikits-image for reading msg = "Matplotlib with the PIL backend must be available in order to run the "
# other image formats.
no_read_backend = False
msg = "Either scikit-image with the freeimage backend or matplotlib "
msg += "with the PIL backend must be available in order to run the "
msg += "tests in this suite." msg += "tests in this suite."
no_read_backend_msg = msg no_read_backend_msg = msg
try: try:
import skimage.io
try:
skimage.io.use_plugin('freeimage')
from skimage.io import imread
except ImportError:
try:
skimage.io.use_plugin('PIL')
from skimage.io import imread
except ImportError:
raise
except ImportError:
try:
from PIL import Image from PIL import Image
from matplotlib.pyplot import imread from matplotlib.pyplot import imread
except ImportError: no_read_backend = False
except:
no_read_backend = True no_read_backend = True
from glymur import Jp2k from glymur import Jp2k

View file

@ -7,36 +7,26 @@ import os
import platform import platform
import sys import sys
import tempfile import tempfile
import unittest
if sys.hexversion < 0x02070000:
import unittest2 as unittest
else:
import unittest
import warnings import warnings
import numpy as np import numpy as np
from glymur.lib import openjp2 as opj2 from glymur.lib import openjp2 as opj2
# Need some combination of matplotlib, PIL, or scikits-image for reading msg = "Matplotlib with the PIL backend must be available in order to run the "
# other image formats.
no_read_backend = False
msg = "Either scikit-image with the freeimage backend or matplotlib "
msg += "with the PIL backend must be available in order to run the "
msg += "tests in this suite." msg += "tests in this suite."
no_read_backend_msg = msg no_read_backend_msg = msg
try: try:
import skimage.io
try:
skimage.io.use_plugin('freeimage')
from skimage.io import imread
except ImportError:
try:
skimage.io.use_plugin('PIL')
from skimage.io import imread
except ImportError:
raise
except ImportError:
try:
from PIL import Image from PIL import Image
from matplotlib.pyplot import imread from matplotlib.pyplot import imread
except ImportError: no_read_backend = False
except:
no_read_backend = True no_read_backend = True
from glymur import Jp2k from glymur import Jp2k

View file

@ -4,13 +4,22 @@ import pkg_resources
import struct import struct
import sys import sys
import tempfile import tempfile
import unittest
if sys.hexversion < 0x02070000:
import unittest2 as unittest
else:
import unittest
if sys.hexversion < 0x03000000: if sys.hexversion < 0x03000000:
from StringIO import StringIO from StringIO import StringIO
else: else:
from io import StringIO from io import StringIO
if sys.hexversion <= 0x03030000:
from mock import patch
else:
from unittest.mock import patch
import glymur import glymur
from glymur import Jp2k from glymur import Jp2k
@ -48,10 +57,6 @@ class TestPrintingNeedsLib(unittest.TestCase):
self.jp2file = glymur.data.nemo() self.jp2file = glymur.data.nemo()
self.j2kfile = glymur.data.goodstuff() self.j2kfile = glymur.data.goodstuff()
# Save sys.stdout.
self.stdout = sys.stdout
sys.stdout = StringIO()
# Save the output of dumping nemo.jp2 for more than one test. # Save the output of dumping nemo.jp2 for more than one test.
lines = ['JPEG 2000 Signature Box (jP ) @ (0, 12)', lines = ['JPEG 2000 Signature Box (jP ) @ (0, 12)',
' Signature: 0d0a870a', ' Signature: 0d0a870a',
@ -118,8 +123,7 @@ class TestPrintingNeedsLib(unittest.TestCase):
self.expectedPlain = '\n'.join(lines) self.expectedPlain = '\n'.join(lines)
def tearDown(self): def tearDown(self):
# Restore stdout. pass
sys.stdout = self.stdout
def test_asoc_label_box(self): def test_asoc_label_box(self):
# Construct a fake file with an asoc and a label box, as # Construct a fake file with an asoc and a label box, as
@ -162,8 +166,9 @@ class TestPrintingNeedsLib(unittest.TestCase):
tfile2.flush() tfile2.flush()
jasoc = glymur.Jp2k(tfile2.name) jasoc = glymur.Jp2k(tfile2.name)
with patch('sys.stdout', new=StringIO()) as fake_out:
print(jasoc.box[3]) print(jasoc.box[3])
actual = sys.stdout.getvalue().strip() actual = fake_out.getvalue().strip()
lines = ['Association Box (asoc) @ (77, 56)', lines = ['Association Box (asoc) @ (77, 56)',
' Label Box (lbl ) @ (85, 13)', ' Label Box (lbl ) @ (85, 13)',
' Label: label', ' Label: label',
@ -173,20 +178,21 @@ class TestPrintingNeedsLib(unittest.TestCase):
self.assertEqual(actual, expected) self.assertEqual(actual, expected)
def test_jp2dump(self): def test_jp2dump(self):
with patch('sys.stdout', new=StringIO()) as fake_out:
glymur.jp2dump(self._plain_nemo_file) glymur.jp2dump(self._plain_nemo_file)
actual = sys.stdout.getvalue().strip() actual = fake_out.getvalue().strip()
# Get rid of the filename line, as it is not set in stone. # Get rid of the filename line, as it is not set in stone.
lst = actual.split('\n') lst = actual.split('\n')
lst = lst[1:] lst = lst[1:]
actual = '\n'.join(lst) actual = '\n'.join(lst)
self.maxDiff = None
self.assertEqual(actual, self.expectedPlain) self.assertEqual(actual, self.expectedPlain)
def test_entire_file(self): def test_entire_file(self):
j = glymur.Jp2k(self._plain_nemo_file) j = glymur.Jp2k(self._plain_nemo_file)
with patch('sys.stdout', new=StringIO()) as fake_out:
print(j) print(j)
actual = sys.stdout.getvalue().strip() actual = fake_out.getvalue().strip()
# Get rid of the filename line, as it is not set in stone. # Get rid of the filename line, as it is not set in stone.
lst = actual.split('\n') lst = actual.split('\n')
@ -200,20 +206,17 @@ class TestPrinting(unittest.TestCase):
def setUp(self): def setUp(self):
# Save sys.stdout. # Save sys.stdout.
self.stdout = sys.stdout self.jp2file = glymur.data.nemo()
sys.stdout = StringIO()
self.jp2file = pkg_resources.resource_filename(glymur.__name__,
"data/nemo.jp2")
def tearDown(self): def tearDown(self):
# Restore stdout. pass
sys.stdout = self.stdout
def test_COC_segment(self): def test_COC_segment(self):
j = glymur.Jp2k(self.jp2file) j = glymur.Jp2k(self.jp2file)
codestream = j.get_codestream(header_only=False) codestream = j.get_codestream(header_only=False)
with patch('sys.stdout', new=StringIO()) as fake_out:
print(codestream.segment[6]) print(codestream.segment[6])
actual = sys.stdout.getvalue().strip() actual = fake_out.getvalue().strip()
lines = ['COC marker segment @ (3260, 9)', lines = ['COC marker segment @ (3260, 9)',
' Associated component: 1', ' Associated component: 1',
@ -233,14 +236,14 @@ class TestPrinting(unittest.TestCase):
' Segmentation symbols: False'] ' Segmentation symbols: False']
expected = '\n'.join(lines) expected = '\n'.join(lines)
self.maxDiff = None
self.assertEqual(actual, expected) self.assertEqual(actual, expected)
def test_COD_segment(self): def test_COD_segment(self):
j = glymur.Jp2k(self.jp2file) j = glymur.Jp2k(self.jp2file)
codestream = j.get_codestream() codestream = j.get_codestream()
with patch('sys.stdout', new=StringIO()) as fake_out:
print(codestream.segment[2]) print(codestream.segment[2])
actual = sys.stdout.getvalue().strip() actual = fake_out.getvalue().strip()
lines = ['COD marker segment @ (3186, 12)', lines = ['COD marker segment @ (3186, 12)',
' Coding style:', ' Coding style:',
@ -275,8 +278,9 @@ class TestPrinting(unittest.TestCase):
def test_icc_profile(self): def test_icc_profile(self):
filename = os.path.join(data_root, 'input/nonregression/text_GBR.jp2') filename = os.path.join(data_root, 'input/nonregression/text_GBR.jp2')
j = glymur.Jp2k(filename) j = glymur.Jp2k(filename)
with patch('sys.stdout', new=StringIO()) as fake_out:
print(j.box[3].box[1]) print(j.box[3].box[1])
actual = sys.stdout.getvalue().strip() actual = fake_out.getvalue().strip()
lin27 = ["Colour Specification Box (colr) @ (179, 1339)", lin27 = ["Colour Specification Box (colr) @ (179, 1339)",
" Method: any ICC profile", " Method: any ICC profile",
" Precedence: 2", " Precedence: 2",
@ -340,8 +344,9 @@ class TestPrinting(unittest.TestCase):
filename = os.path.join(data_root, 'input/conformance/p0_03.j2k') filename = os.path.join(data_root, 'input/conformance/p0_03.j2k')
j = glymur.Jp2k(filename) j = glymur.Jp2k(filename)
codestream = j.get_codestream() codestream = j.get_codestream()
with patch('sys.stdout', new=StringIO()) as fake_out:
print(codestream.segment[-5]) print(codestream.segment[-5])
actual = sys.stdout.getvalue().strip() actual = fake_out.getvalue().strip()
lines = ['CRG marker segment at (87, 6)', lines = ['CRG marker segment at (87, 6)',
' Vertical, Horizontal offset: (0.50, 1.00)'] ' Vertical, Horizontal offset: (0.50, 1.00)']
expected = '\n'.join(lines) expected = '\n'.join(lines)
@ -353,8 +358,9 @@ class TestPrinting(unittest.TestCase):
filename = os.path.join(data_root, 'input/conformance/p0_03.j2k') filename = os.path.join(data_root, 'input/conformance/p0_03.j2k')
j = glymur.Jp2k(filename) j = glymur.Jp2k(filename)
codestream = j.get_codestream(header_only=False) codestream = j.get_codestream(header_only=False)
with patch('sys.stdout', new=StringIO()) as fake_out:
print(codestream.segment[12]) print(codestream.segment[12])
actual = sys.stdout.getvalue().strip() actual = fake_out.getvalue().strip()
lines = ['RGN marker segment @ (310, 5)', lines = ['RGN marker segment @ (310, 5)',
' Associated component: 0', ' Associated component: 0',
' ROI style: 0', ' ROI style: 0',
@ -368,8 +374,9 @@ class TestPrinting(unittest.TestCase):
filename = os.path.join(data_root, 'input/conformance/p0_03.j2k') filename = os.path.join(data_root, 'input/conformance/p0_03.j2k')
j = glymur.Jp2k(filename) j = glymur.Jp2k(filename)
codestream = j.get_codestream(header_only=False) codestream = j.get_codestream(header_only=False)
with patch('sys.stdout', new=StringIO()) as fake_out:
print(codestream.segment[-2]) print(codestream.segment[-2])
actual = sys.stdout.getvalue().strip() actual = fake_out.getvalue().strip()
lines = ['SOP marker segment @ (12836, 4)', lines = ['SOP marker segment @ (12836, 4)',
' Nsop: 15'] ' Nsop: 15']
expected = '\n'.join(lines) expected = '\n'.join(lines)
@ -383,8 +390,9 @@ class TestPrinting(unittest.TestCase):
j = glymur.Jp2k(filename) j = glymur.Jp2k(filename)
codestream = j.get_codestream() codestream = j.get_codestream()
# 2nd to last segment in the main header # 2nd to last segment in the main header
with patch('sys.stdout', new=StringIO()) as fake_out:
print(codestream.segment[-2]) print(codestream.segment[-2])
actual = sys.stdout.getvalue().strip() actual = fake_out.getvalue().strip()
lines = ['CME marker segment @ (85, 45)', lines = ['CME marker segment @ (85, 45)',
' "Creator: AV-J2K (c) 2000,2001 Algo Vision"'] ' "Creator: AV-J2K (c) 2000,2001 Algo Vision"']
expected = '\n'.join(lines) expected = '\n'.join(lines)
@ -393,8 +401,9 @@ class TestPrinting(unittest.TestCase):
def test_EOC_segment(self): def test_EOC_segment(self):
j = glymur.Jp2k(self.jp2file) j = glymur.Jp2k(self.jp2file)
codestream = j.get_codestream(header_only=False) codestream = j.get_codestream(header_only=False)
with patch('sys.stdout', new=StringIO()) as fake_out:
print(codestream.segment[-1]) print(codestream.segment[-1])
actual = sys.stdout.getvalue().strip() actual = fake_out.getvalue().strip()
lines = ['EOC marker segment @ (1135421, 0)'] lines = ['EOC marker segment @ (1135421, 0)']
expected = '\n'.join(lines) expected = '\n'.join(lines)
@ -406,8 +415,9 @@ class TestPrinting(unittest.TestCase):
filename = os.path.join(data_root, 'input/conformance/p0_07.j2k') filename = os.path.join(data_root, 'input/conformance/p0_07.j2k')
j = glymur.Jp2k(filename) j = glymur.Jp2k(filename)
codestream = j.get_codestream(header_only=False) codestream = j.get_codestream(header_only=False)
with patch('sys.stdout', new=StringIO()) as fake_out:
print(codestream.segment[49935]) print(codestream.segment[49935])
actual = sys.stdout.getvalue().strip() actual = fake_out.getvalue().strip()
lines = ['PLT marker segment @ (7871146, 38)', lines = ['PLT marker segment @ (7871146, 38)',
' Index: 0', ' Index: 0',
@ -423,8 +433,9 @@ class TestPrinting(unittest.TestCase):
filename = os.path.join(data_root, 'input/conformance/p0_13.j2k') filename = os.path.join(data_root, 'input/conformance/p0_13.j2k')
j = glymur.Jp2k(filename) j = glymur.Jp2k(filename)
codestream = j.get_codestream() codestream = j.get_codestream()
with patch('sys.stdout', new=StringIO()) as fake_out:
print(codestream.segment[8]) print(codestream.segment[8])
actual = sys.stdout.getvalue().strip() actual = fake_out.getvalue().strip()
lines = ['POD marker segment @ (878, 20)', lines = ['POD marker segment @ (878, 20)',
' Progression change 0:', ' Progression change 0:',
@ -451,8 +462,9 @@ class TestPrinting(unittest.TestCase):
filename = os.path.join(data_root, 'input/conformance/p1_03.j2k') filename = os.path.join(data_root, 'input/conformance/p1_03.j2k')
j = glymur.Jp2k(filename) j = glymur.Jp2k(filename)
codestream = j.get_codestream() codestream = j.get_codestream()
with patch('sys.stdout', new=StringIO()) as fake_out:
print(codestream.segment[9]) print(codestream.segment[9])
actual = sys.stdout.getvalue().strip() actual = fake_out.getvalue().strip()
lines = ['PPM marker segment @ (213, 43712)', lines = ['PPM marker segment @ (213, 43712)',
' Index: 0', ' Index: 0',
@ -467,8 +479,9 @@ class TestPrinting(unittest.TestCase):
filename = os.path.join(data_root, 'input/conformance/p1_06.j2k') filename = os.path.join(data_root, 'input/conformance/p1_06.j2k')
j = glymur.Jp2k(filename) j = glymur.Jp2k(filename)
codestream = j.get_codestream(header_only=False) codestream = j.get_codestream(header_only=False)
with patch('sys.stdout', new=StringIO()) as fake_out:
print(codestream.segment[6]) print(codestream.segment[6])
actual = sys.stdout.getvalue().strip() actual = fake_out.getvalue().strip()
lines = ['PPT marker segment @ (155, 109)', lines = ['PPT marker segment @ (155, 109)',
' Index: 0', ' Index: 0',
@ -480,8 +493,9 @@ class TestPrinting(unittest.TestCase):
def test_QCC_segment(self): def test_QCC_segment(self):
j = glymur.Jp2k(self.jp2file) j = glymur.Jp2k(self.jp2file)
codestream = j.get_codestream(header_only=False) codestream = j.get_codestream(header_only=False)
with patch('sys.stdout', new=StringIO()) as fake_out:
print(codestream.segment[7]) print(codestream.segment[7])
actual = sys.stdout.getvalue().strip() actual = fake_out.getvalue().strip()
lines = ['QCC marker segment @ (3271, 8)', lines = ['QCC marker segment @ (3271, 8)',
' Associated Component: 1', ' Associated Component: 1',
@ -494,8 +508,9 @@ class TestPrinting(unittest.TestCase):
def test_QCD_segment_5x3_transform(self): def test_QCD_segment_5x3_transform(self):
j = glymur.Jp2k(self.jp2file) j = glymur.Jp2k(self.jp2file)
codestream = j.get_codestream() codestream = j.get_codestream()
with patch('sys.stdout', new=StringIO()) as fake_out:
print(codestream.segment[3]) print(codestream.segment[3])
actual = sys.stdout.getvalue().strip() actual = fake_out.getvalue().strip()
lines = ['QCD marker segment @ (3200, 7)', lines = ['QCD marker segment @ (3200, 7)',
' Quantization style: no quantization, 2 guard bits', ' Quantization style: no quantization, 2 guard bits',
@ -507,8 +522,9 @@ class TestPrinting(unittest.TestCase):
def test_SIZ_segment(self): def test_SIZ_segment(self):
j = glymur.Jp2k(self.jp2file) j = glymur.Jp2k(self.jp2file)
codestream = j.get_codestream() codestream = j.get_codestream()
with patch('sys.stdout', new=StringIO()) as fake_out:
print(codestream.segment[1]) print(codestream.segment[1])
actual = sys.stdout.getvalue().strip() actual = fake_out.getvalue().strip()
lines = ['SIZ marker segment @ (3137, 47)', lines = ['SIZ marker segment @ (3137, 47)',
' Profile: 2', ' Profile: 2',
@ -527,8 +543,9 @@ class TestPrinting(unittest.TestCase):
def test_SOC_segment(self): def test_SOC_segment(self):
j = glymur.Jp2k(self.jp2file) j = glymur.Jp2k(self.jp2file)
codestream = j.get_codestream() codestream = j.get_codestream()
with patch('sys.stdout', new=StringIO()) as fake_out:
print(codestream.segment[0]) print(codestream.segment[0])
actual = sys.stdout.getvalue().strip() actual = fake_out.getvalue().strip()
lines = ['SOC marker segment @ (3135, 0)'] lines = ['SOC marker segment @ (3135, 0)']
expected = '\n'.join(lines) expected = '\n'.join(lines)
@ -537,8 +554,9 @@ class TestPrinting(unittest.TestCase):
def test_SOD_segment(self): def test_SOD_segment(self):
j = glymur.Jp2k(self.jp2file) j = glymur.Jp2k(self.jp2file)
codestream = j.get_codestream(header_only=False) codestream = j.get_codestream(header_only=False)
with patch('sys.stdout', new=StringIO()) as fake_out:
print(codestream.segment[10]) print(codestream.segment[10])
actual = sys.stdout.getvalue().strip() actual = fake_out.getvalue().strip()
lines = ['SOD marker segment @ (3302, 0)'] lines = ['SOD marker segment @ (3302, 0)']
expected = '\n'.join(lines) expected = '\n'.join(lines)
@ -547,8 +565,9 @@ class TestPrinting(unittest.TestCase):
def test_SOT_segment(self): def test_SOT_segment(self):
j = glymur.Jp2k(self.jp2file) j = glymur.Jp2k(self.jp2file)
codestream = j.get_codestream(header_only=False) codestream = j.get_codestream(header_only=False)
with patch('sys.stdout', new=StringIO()) as fake_out:
print(codestream.segment[5]) print(codestream.segment[5])
actual = sys.stdout.getvalue().strip() actual = fake_out.getvalue().strip()
lines = ['SOT marker segment @ (3248, 10)', lines = ['SOT marker segment @ (3248, 10)',
' Tile part index: 0', ' Tile part index: 0',
@ -566,8 +585,9 @@ class TestPrinting(unittest.TestCase):
filename = os.path.join(data_root, 'input/conformance/p0_15.j2k') filename = os.path.join(data_root, 'input/conformance/p0_15.j2k')
j = glymur.Jp2k(filename) j = glymur.Jp2k(filename)
codestream = j.get_codestream() codestream = j.get_codestream()
with patch('sys.stdout', new=StringIO()) as fake_out:
print(codestream.segment[10]) print(codestream.segment[10])
actual = sys.stdout.getvalue().strip() actual = fake_out.getvalue().strip()
lines = ['TLM marker segment @ (268, 28)', lines = ['TLM marker segment @ (268, 28)',
' Index: 0', ' Index: 0',
@ -577,11 +597,15 @@ class TestPrinting(unittest.TestCase):
expected = '\n'.join(lines) expected = '\n'.join(lines)
self.assertEqual(actual, expected) self.assertEqual(actual, expected)
@unittest.skipIf(sys.hexversion < 0x02070000,
"Differences in XML printing between 2.6 and 2.7")
def test_xmp(self): def test_xmp(self):
# Verify the printing of a UUID/XMP box. # Verify the printing of a UUID/XMP box.
j = glymur.Jp2k(self.jp2file) j = glymur.Jp2k(self.jp2file)
with patch('sys.stdout', new=StringIO()) as fake_out:
print(j.box[4]) print(j.box[4])
actual = sys.stdout.getvalue().strip() actual = fake_out.getvalue().strip()
lst = ['UUID Box (uuid) @ (715, 2412)', lst = ['UUID Box (uuid) @ (715, 2412)',
' UUID: be7acfcb-97a9-42e8-9c71-999491e3afac (XMP)', ' UUID: be7acfcb-97a9-42e8-9c71-999491e3afac (XMP)',
' UUID Data: ', ' UUID Data: ',
@ -599,8 +623,9 @@ class TestPrinting(unittest.TestCase):
def test_codestream(self): def test_codestream(self):
j = glymur.Jp2k(self.jp2file) j = glymur.Jp2k(self.jp2file)
with patch('sys.stdout', new=StringIO()) as fake_out:
print(j.get_codestream()) print(j.get_codestream())
actual = sys.stdout.getvalue().strip() actual = fake_out.getvalue().strip()
lst = ['Codestream:', lst = ['Codestream:',
' SOC marker segment @ (3135, 0)', ' SOC marker segment @ (3135, 0)',
' SIZ marker segment @ (3137, 47)', ' SIZ marker segment @ (3137, 47)',
@ -645,13 +670,16 @@ class TestPrinting(unittest.TestCase):
self.maxDiff = None self.maxDiff = None
self.assertEqual(actual, expected) self.assertEqual(actual, expected)
@unittest.skipIf(sys.hexversion < 0x02070000,
"Differences in XML printing between 2.6 and 2.7")
@unittest.skipIf(data_root is None, @unittest.skipIf(data_root is None,
"OPJ_DATA_ROOT environment variable not set") "OPJ_DATA_ROOT environment variable not set")
def test_xml(self): def test_xml(self):
filename = os.path.join(data_root, 'input/conformance/file1.jp2') filename = os.path.join(data_root, 'input/conformance/file1.jp2')
j = glymur.Jp2k(filename) j = glymur.Jp2k(filename)
with patch('sys.stdout', new=StringIO()) as fake_out:
print(j.box[2]) print(j.box[2])
actual = sys.stdout.getvalue().strip() actual = fake_out.getvalue().strip()
lines = ['XML Box (xml ) @ (36, 439)', lines = ['XML Box (xml ) @ (36, 439)',
' <ns0:IMAGE_CREATION ' ' <ns0:IMAGE_CREATION '
@ -679,8 +707,9 @@ class TestPrinting(unittest.TestCase):
def test_channel_definition(self): def test_channel_definition(self):
filename = os.path.join(data_root, 'input/conformance/file2.jp2') filename = os.path.join(data_root, 'input/conformance/file2.jp2')
j = glymur.Jp2k(filename) j = glymur.Jp2k(filename)
with patch('sys.stdout', new=StringIO()) as fake_out:
print(j.box[2].box[2]) print(j.box[2].box[2])
actual = sys.stdout.getvalue().strip() actual = fake_out.getvalue().strip()
lines = ['Channel Definition Box (cdef) @ (81, 28)', lines = ['Channel Definition Box (cdef) @ (81, 28)',
' Channel 0 (color) ==> (3)', ' Channel 0 (color) ==> (3)',
' Channel 1 (color) ==> (2)', ' Channel 1 (color) ==> (2)',
@ -693,8 +722,9 @@ class TestPrinting(unittest.TestCase):
def test_component_mapping(self): def test_component_mapping(self):
filename = os.path.join(data_root, 'input/conformance/file9.jp2') filename = os.path.join(data_root, 'input/conformance/file9.jp2')
j = glymur.Jp2k(filename) j = glymur.Jp2k(filename)
with patch('sys.stdout', new=StringIO()) as fake_out:
print(j.box[2].box[2]) print(j.box[2].box[2])
actual = sys.stdout.getvalue().strip() actual = fake_out.getvalue().strip()
lines = ['Component Mapping Box (cmap) @ (848, 20)', lines = ['Component Mapping Box (cmap) @ (848, 20)',
' Component 0 ==> palette column 0', ' Component 0 ==> palette column 0',
' Component 0 ==> palette column 1', ' Component 0 ==> palette column 1',
@ -707,8 +737,9 @@ class TestPrinting(unittest.TestCase):
def test_palette(self): def test_palette(self):
filename = os.path.join(data_root, 'input/conformance/file9.jp2') filename = os.path.join(data_root, 'input/conformance/file9.jp2')
j = glymur.Jp2k(filename) j = glymur.Jp2k(filename)
with patch('sys.stdout', new=StringIO()) as fake_out:
print(j.box[2].box[1]) print(j.box[2].box[1])
actual = sys.stdout.getvalue().strip() actual = fake_out.getvalue().strip()
lines = ['Palette Box (pclr) @ (66, 782)', lines = ['Palette Box (pclr) @ (66, 782)',
' Size: (256 x 3)'] ' Size: (256 x 3)']
expected = '\n'.join(lines) expected = '\n'.join(lines)
@ -719,8 +750,9 @@ class TestPrinting(unittest.TestCase):
def test_palette(self): def test_palette(self):
filename = os.path.join(data_root, 'input/conformance/file7.jp2') filename = os.path.join(data_root, 'input/conformance/file7.jp2')
j = glymur.Jp2k(filename) j = glymur.Jp2k(filename)
with patch('sys.stdout', new=StringIO()) as fake_out:
print(j.box[2]) print(j.box[2])
actual = sys.stdout.getvalue().strip() actual = fake_out.getvalue().strip()
lines = ['Reader Requirements Box (rreq) @ (44, 24)', lines = ['Reader Requirements Box (rreq) @ (44, 24)',
' Standard Features:', ' Standard Features:',
' Feature 005: ' ' Feature 005: '
@ -742,8 +774,9 @@ class TestPrinting(unittest.TestCase):
filename = os.path.join(data_root, 'input/conformance/p0_03.j2k') filename = os.path.join(data_root, 'input/conformance/p0_03.j2k')
j = glymur.Jp2k(filename) j = glymur.Jp2k(filename)
codestream = j.get_codestream() codestream = j.get_codestream()
with patch('sys.stdout', new=StringIO()) as fake_out:
print(codestream.segment[6]) print(codestream.segment[6])
actual = sys.stdout.getvalue().strip() actual = fake_out.getvalue().strip()
lines = ['CRG marker segment @ (87, 6)', lines = ['CRG marker segment @ (87, 6)',
' Vertical, Horizontal offset: (0.50, 1.00)'] ' Vertical, Horizontal offset: (0.50, 1.00)']
expected = '\n'.join(lines) expected = '\n'.join(lines)
@ -756,8 +789,9 @@ class TestPrinting(unittest.TestCase):
filename = os.path.join(data_root, 'input/conformance/p0_05.j2k') filename = os.path.join(data_root, 'input/conformance/p0_05.j2k')
j = glymur.Jp2k(filename) j = glymur.Jp2k(filename)
codestream = j.get_codestream() codestream = j.get_codestream()
with patch('sys.stdout', new=StringIO()) as fake_out:
print(codestream.segment[1]) print(codestream.segment[1])
actual = sys.stdout.getvalue().strip() actual = fake_out.getvalue().strip()
lines = ['SIZ marker segment @ (2, 50)', lines = ['SIZ marker segment @ (2, 50)',
' Profile: 0', ' Profile: 0',
' Reference Grid Height, Width: (1024 x 1024)', ' Reference Grid Height, Width: (1024 x 1024)',
@ -777,8 +811,9 @@ class TestPrinting(unittest.TestCase):
# Verify that palette (pclr) boxes are printed without error. # Verify that palette (pclr) boxes are printed without error.
filename = os.path.join(data_root, 'input/conformance/file9.jp2') filename = os.path.join(data_root, 'input/conformance/file9.jp2')
j = glymur.Jp2k(filename) j = glymur.Jp2k(filename)
with patch('sys.stdout', new=StringIO()) as fake_out:
print(j.box[2].box[1]) print(j.box[2].box[1])
actual = sys.stdout.getvalue().strip() actual = fake_out.getvalue().strip()
lines = ['Palette Box (pclr) @ (66, 782)', lines = ['Palette Box (pclr) @ (66, 782)',
' Size: (256 x 3)'] ' Size: (256 x 3)']
expected = '\n'.join(lines) expected = '\n'.join(lines)
@ -837,9 +872,10 @@ class TestPrinting(unittest.TestCase):
tfile.flush() tfile.flush()
jp2k = glymur.Jp2k(tfile.name) jp2k = glymur.Jp2k(tfile.name)
with patch('sys.stdout', new=StringIO()) as fake_out:
print(jp2k.box[3]) print(jp2k.box[3])
print(jp2k.box[4]) print(jp2k.box[4])
actual = sys.stdout.getvalue().strip() actual = fake_out.getvalue().strip()
lines = ['UUIDInfo Box (uinf) @ (77, 50)', lines = ['UUIDInfo Box (uinf) @ (77, 50)',
' UUID List Box (ulst) @ (85, 26)', ' UUID List Box (ulst) @ (85, 26)',
' UUID[0]: 00000000-0000-0000-0000-000000000000', ' UUID[0]: 00000000-0000-0000-0000-000000000000',
@ -868,8 +904,9 @@ class TestPrinting(unittest.TestCase):
filename = os.path.join(data_root, 'input/nonregression/text_GBR.jp2') filename = os.path.join(data_root, 'input/nonregression/text_GBR.jp2')
j = glymur.Jp2k(filename) j = glymur.Jp2k(filename)
with patch('sys.stdout', new=StringIO()) as fake_out:
print(j.box[3].box[1]) print(j.box[3].box[1])
actual = sys.stdout.getvalue().strip() actual = fake_out.getvalue().strip()
lines = ["Colour Specification Box (colr) @ (179, 1339)", lines = ["Colour Specification Box (colr) @ (179, 1339)",
" Method: any ICC profile", " Method: any ICC profile",
" Precedence: 2", " Precedence: 2",
@ -907,8 +944,9 @@ class TestPrinting(unittest.TestCase):
filename = os.path.join(data_root, 'input/nonregression/text_GBR.jp2') filename = os.path.join(data_root, 'input/nonregression/text_GBR.jp2')
j = glymur.Jp2k(filename) j = glymur.Jp2k(filename)
with patch('sys.stdout', new=StringIO()) as fake_out:
print(j.box[4]) print(j.box[4])
actual = sys.stdout.getvalue().strip() actual = fake_out.getvalue().strip()
lines = ['UUID Box (uuid) @ (1544, 25)', lines = ['UUID Box (uuid) @ (1544, 25)',
' UUID: 3a0d0218-0ae9-4115-b376-4bca41ce0e71', ' UUID: 3a0d0218-0ae9-4115-b376-4bca41ce0e71',
' UUID Data: 1 bytes'] ' UUID Data: 1 bytes']
@ -921,8 +959,9 @@ class TestPrinting(unittest.TestCase):
def test_exif_uuid(self): def test_exif_uuid(self):
j = glymur.Jp2k(self.jp2file) j = glymur.Jp2k(self.jp2file)
with patch('sys.stdout', new=StringIO()) as fake_out:
print(j.box[3]) print(j.box[3])
actual = sys.stdout.getvalue().strip() actual = fake_out.getvalue().strip()
lines = ["UUID Box (uuid) @ (77, 638)", lines = ["UUID Box (uuid) @ (77, 638)",
" UUID: 4a706754-6966-6645-7869-662d3e4a5032 (Exif)", " UUID: 4a706754-6966-6645-7869-662d3e4a5032 (Exif)",

View file

@ -1,30 +1,39 @@
| OS | Python 2.7 | Python 3.3 | Notes | | OS | Python | Python | Python | Notes |
+------------+------------+------------+--------------------------------------+ | | 2.6 | 2.7 | 3.3 | |
| Windows | X | | Python(xy) with OpenJPEG 1.5.1. At | +-----------+--------+--------+--------+--------------------------------------+
| | | | least 155 of 444 tests should pass. | | Windows | | X | | Python(xy) with OpenJPEG 1.5.1 and |
+------------+------------+------------+--------------------------------------+ | | | | | OpenJPEG svn. 285 of 448 tests |
| Windows | X | | Python(xy) with OpenJPEG 1.5.1 and | | | | | | pass. |
| | | | OpenJPEG svn. At least 282 of 444 | +-----------+--------+--------+--------+--------------------------------------+
| | | | tests should pass. | | Mac | X | | | MacPorts with both OpenJPEG 1.5.1 |
+------------+------------+------------+--------------------------------------+ | 10.6.8 | | | | and OpenJPEG svn. 353 of 449 tests |
| Mac | X | | MacPorts with both OpenJPEG 1.5.1 | | | | | | should pass. |
| | | | and OpenJPEG svn. 370 of 450 tests | +-----------+--------+--------+--------+--------------------------------------+
| | | | should pass. | | Mac | | X | | MacPorts with both OpenJPEG 1.5.1 |
+------------+------------+------------+--------------------------------------+ | 10.6.8 | | | | and OpenJPEG svn. 376 of 454 tests |
| Mac | | X | MacPorts with both OpenJPEG 1.5.1 | | | | | | should pass. |
| | | | and OpenJPEG svn. 390 of 450 | +-----------+--------+--------+--------+--------------------------------------+
| | | | tests should pass. | | Mac | | | X | MacPorts with both OpenJPEG 1.5.1 |
+------------+------------+------------+--------------------------------------+ | 10.6.8 | | | | and OpenJPEG svn. 401 of 454 |
| Fedora 19 | | X | Ships with 1.5.1. 390 of 450 tests | | | | | | tests should pass. |
| | | | should pass. | +-----------+--------+--------+-----------------------------------------------+
+------------+------------+------------+--------------------------------------+ | Fedora 19 | | | X | Ships with 1.5.1, openjp2 built too. |
| Fedora 18 | | X | Ships with 1.5.1. 167 of 445 tests | | | | | | 401 of 454 tests should pass. |
| | | | should pass. | +-----------+--------+--------+--------+--------------------------------------+
+------------+------------+------------+--------------------------------------+ | Fedora 18 | | | X | Ships with 1.5.1. 169 of 449 tests |
| Fedora 17 | X | | Ships with 1.4. Should error out | | | | | | should pass. |
| | | | gracefully. | +-----------+--------+--------+--------+--------------------------------------+
+------------+------------+------------+--------------------------------------+ | Fedora 17 | | X | | Ships with 1.4.0. 169 of 449 tests |
| | | | | should pass. |
+-----------+--------+--------+--------+--------------------------------------+
| CentOS | X | | | Ships with 1.3.0. 167 of 449 tests |
| 6.3 | | | | should pass. |
+-----------+--------+--------+--------+--------------------------------------+
| Raspberry | | X | | Ships with 1.3.0. 169 of 449 tests |
| Pi | | | | should pass. |
| Debian 7 | | | | |
+-----------+--------+--------+--------+--------------------------------------+
Pylint on entire package should be at least 0.95. Pylint on entire package should exceed 0.95.
pep8 should be pass cleanly. pep8 should be pass cleanly.
Coverage should exceed 95%. Coverage should exceed 95%.

View file

@ -2,26 +2,31 @@ from setuptools import setup, find_packages
import sys import sys
kwargs = {'name': 'Glymur', kwargs = {'name': 'Glymur',
'version': '0.2.2', 'version': '0.2.3',
'description': 'Tools for accessing JPEG2000 files', 'description': 'Tools for accessing JPEG2000 files',
'long_description': open('README.md').read(), 'long_description': open('README.md').read(),
'author': 'John Evans', 'author': 'John Evans',
'author_email': 'johnevans938 at gmail dot com', 'author_email': 'john.g.evans.ne at gmail dot com',
'url': 'https://github.com/quintusdias/glymur', 'url': 'https://github.com/quintusdias/glymur',
'packages': ['glymur', 'glymur.data', 'glymur.test', 'glymur.lib', 'packages': ['glymur', 'glymur.data', 'glymur.test', 'glymur.lib',
'glymur.lib.test'], 'glymur.lib.test'],
'package_data': {'glymur': ['data/*.jp2', 'data/*.j2k']}, 'package_data': {'glymur': ['data/*.jp2', 'data/*.j2k']},
'scripts': ['bin/jp2dump'], 'scripts': ['bin/jp2dump'],
'license': 'LICENSE.txt', 'license': 'LICENSE.txt',
'test_suite': 'glymur.test',
'platforms': ['darwin']} 'platforms': ['darwin']}
instllrqrs = ['numpy>1.6.2'] instllrqrs = ['numpy>=1.4.1']
if sys.hexversion < 0x03030000: if sys.hexversion < 0x03030000:
instllrqrs.append('contextlib2>=0.4') instllrqrs.append('contextlib2>=0.4')
instllrqrs.append('mock>=1.0.1') instllrqrs.append('mock>=1.0.1')
if sys.hexversion < 0x02070000:
instllrqrs.append('ordereddict>=1.1')
instllrqrs.append('unittest2>=0.5.1')
kwargs['install_requires'] = instllrqrs kwargs['install_requires'] = instllrqrs
clssfrs = ["Programming Language :: Python", clssfrs = ["Programming Language :: Python",
"Programming Language :: Python :: 2.6",
"Programming Language :: Python :: 2.7", "Programming Language :: Python :: 2.7",
"Programming Language :: Python :: 3.3", "Programming Language :: Python :: 3.3",
"Programming Language :: Python :: Implementation :: CPython", "Programming Language :: Python :: Implementation :: CPython",