Merge branch 'release-0.5.0'

This commit is contained in:
jevans 2013-09-16 19:45:11 -04:00
commit 17dcd6ec18
21 changed files with 2145 additions and 2634 deletions

View file

@ -12,6 +12,11 @@ before_install:
# command to install dependencies # command to install dependencies
install: install:
- pip install . --use-mirrors - pip install . --use-mirrors
# command to run tests # command to run tests
script: script:
- "python -m unittest discover" - "python -m unittest discover"
notifications:
email:
- john.g.evans.ne@gmail.com

View file

@ -1,3 +1,5 @@
Sep 16, 2013 - v0.5.0 Added write support for 1.5.x. Added version module.
Aug 21, 2013 - v0.4.1 Fixed segfault with openjpeg 1.x when rlevel=-1 Aug 21, 2013 - v0.4.1 Fixed segfault with openjpeg 1.x when rlevel=-1
Aug 18, 2013 - v0.4.0 Added append method. Aug 18, 2013 - v0.4.0 Added append method.

View file

@ -76,9 +76,9 @@ copyright = u'2013, John Evans'
# built documents. # built documents.
# #
# The short X.Y version. # The short X.Y version.
version = '0.4' version = '0.5'
# The full version, including alpha/beta/rc tags. # The full version, including alpha/beta/rc tags.
release = '0.4.1' release = '0.5.0'
# 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

@ -1,31 +1,33 @@
---------------------------------- ----------------------------------
Advanced Installation Instructions Advanced Installation Instructions
---------------------------------- ----------------------------------
Most users won't need to read this! You've been warned...
'''''''''''''''''''''' ''''''''''''''''''''''
Glymur Configuration Glymur Configuration
'''''''''''''''''''''' ''''''''''''''''''''''
The default glymur installation process relies upon OpenJPEG version The default glymur installation process relies upon OpenJPEG version
1.X being properly installed on your system. This will, however, only 1.X being properly installed on your system. If you have version 1.5 you can
give you you basic read capabilities, so if you wish to take advantage both read and write JPEG 2000 files, but you may wish to install version 2.0
of more of glymur's features, you should install version 2.0 or or the 2.0+ version from OpenJPEG's development trunk for better performance.
compile OpenJPEG as a shared library (named *openjp2* instead of If you do that, you should compile it as a shared library (named *openjp2*
*openjpeg*) from the developmental source that you can retrieve via instead of *openjpeg*) from the developmental source that you can retrieve
subversion. As of this time of writing, svn revision 2345 works. via subversion. As of this time of writing, svn revision 2345 works.
You should also download the test data for the purpose of configuring You should also download the test data for the purpose of configuring
and running OpenJPEG's test suite, check their instructions for all and running OpenJPEG's test suite, check their instructions for all this.
this. You should set the **OPJ_DATA_ROOT** environment variable You should set the **OPJ_DATA_ROOT** environment variable for the purpose
for the purpose of running Glymur's test suite. :: of running Glymur's test suite. ::
$ svn co http://openjpeg.googlecode.com/svn/data $ svn co http://openjpeg.googlecode.com/svn/data
$ export OPJ_DATA_ROOT=`pwd`/data $ export OPJ_DATA_ROOT=`pwd`/data
Glymur uses ctypes (for the moment) to access the openjp2 library, and Glymur uses ctypes to access the openjp2/openjpeg libraries,
because ctypes access libraries in a platform-dependent manner, it is and because ctypes accesses 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. The configuration format is the same as used by Python's the openjpeg or openjp2 libraries (linux users don't need to bother if you are
configparser module, i.e. :: using OpenJPEG as provided by your package manager). The configuration
format is the same as used by Python's configparser module, i.e. ::
[library] [library]
openjp2: /opt/openjp2-svn/lib/libopenjp2.so openjp2: /opt/openjp2-svn/lib/libopenjp2.so
@ -37,7 +39,8 @@ to the configuration file would normally be ::
$HOME/.config/glymur/glymurrc $HOME/.config/glymur/glymurrc
but if you have **$XDG_CONFIG_HOME** defined, the path will be :: but if you have the **XDG_CONFIG_HOME** environment variable defined,
the path will be ::
$XDG_CONFIG_HOME/glymur/glymurrc $XDG_CONFIG_HOME/glymur/glymurrc
@ -52,12 +55,11 @@ You may also include a line for the version 1.x openjpeg library if you have it
installed in a non-standard place, i.e. :: installed in a non-standard place, i.e. ::
[library] [library]
openjp2: /opt/openjp2-svn/lib/libopenjp2.so
openjpeg: /not/the/usual/location/lib/libopenjpeg.so openjpeg: /not/the/usual/location/lib/libopenjpeg.so
''''''''''''''''''''''''''''''''''''''''''' ''''''''''''''''''''''''''''''
Package Management Suggestions for Testing Package Management Suggestions
''''''''''''''''''''''''''''''''''''''''''' ''''''''''''''''''''''''''''''
You only need to read this section if you want detailed You only need to read this section if you want detailed
platform-specific instructions on running as many tests as possible or wish to platform-specific instructions on running as many tests as possible or wish to
@ -67,8 +69,8 @@ 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 2.6, 2.7,
MacPorts. You should install the following set of ports: and 3.3 via MacPorts. You should install the following set of ports:
* python33 * python33
* py33-numpy * py33-numpy
@ -80,72 +82,38 @@ MacPorts supplies both OpenJPEG 1.5.0 and OpenJPEG 2.0.0.
Linux Linux
----- -----
For the most part, you only need python and numpy to run glymur, so on
just about all distributions you are already set to go (and you don't
need to mess around with a configuration file, as the openjpeg shared
libraries are found in the usual places thanks to your package manager).
In order to run as many tests as possible, however, the following Python
packages may also need to be installed. Consult your package manager
documentation or use pip.
Fedora 19 * setuptools
''''''''' * matplotlib
Fedora 18 ships with Python 3.3 and all the necessary RPMs are available to * pillow
run the maximum number of tests. * contextlib2 (python 2.6, 2.7 only)
* mock (python 2.6, 2.7 only)
* ordereddict (python 2.6 only)
* python3 Glymur's been tested on the following linux platforms without any unexpected
* python3-numpy difficulties:
* python3-setuptools
* python3-matplotlib (for running tests)
* python3-matplotlib-tk (or whichever matplotlib backend you prefer)
* python3-pillow (for running tests)
Fedora 18 * OpenSUSE 12.3
''''''''' * Fedora 17, 18, 19
Fedora 18 ships with Python 3.3 and the following RPMs are available to * Raspian
meet the minimal set of requirements for running glymur. * Travis CI (currently Ubuntu 12.04?)
* CentOS 6.4
* python3
* python3-numpy
* python3-setuptools
For running the maximal number of tests, you also need
* python3-matplotlib
* python3-matplotlib-tk (or whichever matplotlib backend you prefer)
Pillow is also needed in order to run the maximum number of tests, so
go ahead and install Pillow via pip since Pillow is not 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 2.7 and OpenJPEG 1.4. You should have the
following RPMs installed.
* python
* python-mock
* python-pip
* python-setuptools
* numpy
* matplotlib (optional)
In addition, you must install contextlib2 and Pillow via pip. ::
$ yum install python-devel # pip needs this in order to compile Pillow
$ pip-python install Pillow --user
$ pip-python install contextlib2 --user
$ export PYTHONPATH=$HOME/.local/lib/python2.7/site-packages:$PYTHONPATH
Windows Windows
------- -------
32-bit WinPython 2.7.5 seemed to work with OpenJPEG 1.X, 2.0, and the 32-bit WinPython 2.7.5 seemed to work with OpenJPEG 1.X, 2.0, and the
development version, but still required contextlib2 and mock to be development version, but still required contextlib2 and mock to be
installed via pip. WinPython 3.3.2, however, seems to have trouble installed via pip. WinPython 3.3.2, however, seems to have trouble
with OpenJPEG 2.0, so I would suggest using the development version with OpenJPEG 2.0, so I would suggest using the development version with
there (I'm unwilling to spend ANY more time trying to figure out what that configuration. I no longer have any access to a windows machine,
the problem is there). so I cannot currently offer much guidance here.
At the moment I do not have access to a win32 machine, and
64-bit windows is completely untested.
''''''' '''''''
@ -155,8 +123,8 @@ Testing
There are two environment variables you may wish to set before running the There are two environment variables you may wish to set before running the
tests. tests.
* **OPJ_DATA_ROOT** - points to directory for OpenJPEG test data * **OPJ_DATA_ROOT** - points to directory for OpenJPEG test data (see above)
* **FORMAT_CORPUS_ROOT** - points to directory for format-corpus repository (see https://github.com/openplanets/format-corpus if you wish, but you really don't need to bother with this) * **FORMAT_CORPUS_DATA_ROOT** - points to directory for format-corpus repository (see https://github.com/openplanets/format-corpus if you wish, but you really don't need to bother with this)
Setting these two environment variables is not required, as any tests using Setting these two environment variables is not required, as any tests using
either of them will be skipped. either of them will be skipped.
@ -175,7 +143,7 @@ or from the command line. ::
Quite a few tests are currently skipped. These include tests whose Quite a few tests are currently skipped. These include tests whose
OpenJPEG counterparts are already failing, and others which do pass but OpenJPEG counterparts are already failing, and others which do pass but
still produce heaps of output on stderr. Rather than let this swamp 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 the signal (that most of those tests are actually passing), they've been
filtered out for now. There are also more skipped tests on Python 2.7 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 than on Python 3.3. The important part is whether or not any test
errors are reported at the end. errors are reported at the end.

View file

@ -20,7 +20,7 @@ OpenJPEG Installation
===================== =====================
Glymur will read JPEG 2000 images with versions 1.3, 1.4, 1.5, 2.0, Glymur will read JPEG 2000 images with versions 1.3, 1.4, 1.5, 2.0,
and the trunk/development version of OpenJPEG. Writing images is and the trunk/development version of OpenJPEG. Writing images is
only supported with the 2.0 series, however, and the trunk/development only supported with the 1.5 or better, however, and the trunk/development
version is strongly recommended. For more information about OpenJPEG, version is strongly recommended. For more information about OpenJPEG,
please consult http://www.openjpeg.org. please consult http://www.openjpeg.org.
@ -55,6 +55,5 @@ You can run the tests from within python as follows::
>>> import glymur >>> import glymur
>>> glymur.runtests() >>> glymur.runtests()
Many tests are currently skipped; in fact most of them are skipped if you Many tests are currently skipped, but the The important thing is whether or
are relying on OpenJPEG 1.X. The important thing, though, is whether or
not any tests fail. not any tests fail.

View file

@ -1,9 +1,3 @@
------------
Known Issues
------------
* WinPython 3.3.2 and OpenJPEG 2.0 don't seem to want to play well together. If you do not need write support, just use OpenJPEG 1.5 instead. If you do need write support, try the development version of OpenJPEG.
------- -------
Roadmap Roadmap
------- -------

View file

@ -2,6 +2,9 @@
""" """
import sys import sys
from glymur import version
__version__ = version.version
from .jp2k import Jp2k from .jp2k import Jp2k
from .jp2dump import jp2dump from .jp2dump import jp2dump

View file

@ -1,4 +1,8 @@
"""Access to JPEG2000 files. """This file is part of glymur, a Python interface for accessing JPEG 2000.
http://glymur.readthedocs.org
Copyright 2013 John Evans
License: MIT License: MIT
""" """
@ -21,8 +25,7 @@ import warnings
import numpy as np import numpy as np
from .codestream import Codestream from .codestream import Codestream
from .core import SRGB from .core import SRGB, GREYSCALE
from .core import GREYSCALE
from .core import PROGRESSION_ORDER from .core import PROGRESSION_ORDER
from .core import ENUMERATED_COLORSPACE, RESTRICTED_ICC_PROFILE from .core import ENUMERATED_COLORSPACE, RESTRICTED_ICC_PROFILE
from .jp2box import Jp2kBox from .jp2box import Jp2kBox
@ -31,6 +34,7 @@ from .jp2box import ColourSpecificationBox, ContiguousCodestreamBox
from .jp2box import ImageHeaderBox from .jp2box import ImageHeaderBox
from .lib import openjpeg as opj from .lib import openjpeg as opj
from .lib import openjp2 as opj2 from .lib import openjp2 as opj2
from . import version
from .lib import c as libc from .lib import c as libc
@ -185,6 +189,9 @@ class Jp2k(Jp2kBox):
cparams : CompressionParametersType(ctypes.Structure) cparams : CompressionParametersType(ctypes.Structure)
Corresponds to cparameters_t type in openjp2 headers. Corresponds to cparameters_t type in openjp2 headers.
""" """
if version.openjpeg_version_tuple[0] == 1:
cparams = opj.set_default_encoder_parameters()
else:
cparams = opj2.set_default_encoder_parameters() cparams = opj2.set_default_encoder_parameters()
outfile = self.filename.encode() outfile = self.filename.encode()
@ -280,9 +287,6 @@ class Jp2k(Jp2kBox):
Corresponds to cparameters_t type in openjp2 headers. Corresponds to cparameters_t type in openjp2 headers.
colorspace : int colorspace : int
Either CLRSPC_SRGB or CLRSPC_GRAY Either CLRSPC_SRGB or CLRSPC_GRAY
mct : bool, optional
Specifies usage of the multi component transform. If not
specified, defaults to True if the colorspace is RGB.
""" """
if 'cratios' in kwargs and 'psnr' in kwargs: if 'cratios' in kwargs and 'psnr' in kwargs:
@ -380,11 +384,87 @@ class Jp2k(Jp2kBox):
glymur.LibraryNotFoundError glymur.LibraryNotFoundError
If glymur is unable to load the openjp2 library. If glymur is unable to load the openjp2 library.
""" """
if opj2.OPENJP2 is None: if opj2.OPENJP2 is not None:
raise LibraryNotFoundError("You must have the openjp2 library " self._write_openjp2(img_array, verbose=verbose, **kwargs)
"installed before using this " elif opj.OPENJPEG is not None:
self._write_openjpeg(img_array, verbose=verbose, **kwargs)
else:
raise LibraryNotFoundError("You must have at least version 1.5 of "
"OpenJPEG before using this "
"functionality.") "functionality.")
def _write_openjpeg(self, img_array, verbose=False, **kwargs):
"""
Write JPEG 2000 file using OpenJPEG 1.5 interface.
"""
cparams, colorspace = self._process_write_inputs(img_array, **kwargs)
if img_array.ndim == 2:
# Force the image to be 3D. Just makes things easier later on.
img_array = img_array.reshape(img_array.shape[0],
img_array.shape[1],
1)
comptparms = _populate_comptparms(img_array, cparams)
with ExitStack() as stack:
image = opj.image_create(comptparms, colorspace)
stack.callback(opj.image_destroy, image)
numrows, numcols, numlayers = img_array.shape
# set image offset and reference grid
image.contents.x0 = cparams.image_offset_x0
image.contents.y0 = cparams.image_offset_y0
image.contents.x1 = image.contents.x0 \
+ (numcols - 1) * cparams.subsampling_dx + 1
image.contents.y1 = image.contents.y0 \
+ (numrows - 1) * cparams.subsampling_dy + 1
# Stage the image data to the openjpeg data structure.
for k in range(0, numlayers):
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)
cinfo = opj.create_compress(cparams.codec_fmt)
stack.callback(opj.destroy_compress, cinfo)
# Setup the info, warning, and error handlers.
# Always use the warning and error handler. Use of an info
# handler is optional.
event_mgr = opj.EventMgrType()
_info_handler = _INFO_CALLBACK if verbose else None
event_mgr.info_handler = _info_handler
event_mgr.warning_handler = ctypes.cast(_WARNING_CALLBACK,
ctypes.c_void_p)
event_mgr.error_handler = ctypes.cast(_ERROR_CALLBACK,
ctypes.c_void_p)
opj.setup_encoder(cinfo, ctypes.byref(cparams), image)
cio = opj.cio_open(cinfo)
stack.callback(opj.cio_close, cio)
if not opj.encode(cinfo, cio, image):
raise IOError("Encode error.")
pos = opj.cio_tell(cio)
blob = ctypes.string_at(cio.contents.buffer, pos)
fptr = open(self.filename, 'wb')
stack.callback(fptr.close)
fptr.write(blob)
self.parse()
def _write_openjp2(self, img_array, verbose=False, **kwargs):
"""
Write JPEG 2000 file using OpenJPEG 1.5 interface.
"""
cparams, colorspace = self._process_write_inputs(img_array, **kwargs) cparams, colorspace = self._process_write_inputs(img_array, **kwargs)
if img_array.ndim == 2: if img_array.ndim == 2:
@ -650,6 +730,7 @@ class Jp2k(Jp2kBox):
raise IOError(msg) raise IOError(msg)
with ExitStack() as stack: with ExitStack() as stack:
try:
# Set decoding parameters. # Set decoding parameters.
dparameters = opj.DecompressionParametersType() dparameters = opj.DecompressionParametersType()
opj.set_default_decoder_parameters(ctypes.byref(dparameters)) opj.set_default_decoder_parameters(ctypes.byref(dparameters))
@ -686,6 +767,9 @@ class Jp2k(Jp2kBox):
data = extract_image_cube(image) data = extract_image_cube(image)
except ValueError:
opj2.check_error(0)
if data.shape[2] == 1: if data.shape[2] == 1:
# The third dimension has just a single layer. Make the image # The third dimension has just a single layer. Make the image
# data 2D instead of 3D. # data 2D instead of 3D.
@ -864,8 +948,8 @@ class Jp2k(Jp2kBox):
glymur.LibraryNotFoundError glymur.LibraryNotFoundError
If glymur is unable to load the openjp2 library. If glymur is unable to load the openjp2 library.
""" """
if opj2.OPENJP2 is None: if version.openjpeg_version_tuple[0] < 2:
raise LibraryNotFoundError("You must have the development version " raise LibraryNotFoundError("You must have at least version 2.0.0 "
"of OpenJP2 installed before using " "of OpenJP2 installed before using "
"this functionality.") "this functionality.")
@ -1207,6 +1291,9 @@ def _populate_comptparms(img_array, cparams):
comp_prec = 16 comp_prec = 16
numrows, numcols, num_comps = img_array.shape numrows, numcols, num_comps = img_array.shape
if version.openjpeg_version_tuple[0] == 1:
comptparms = (opj.ImageComptParmType * num_comps)()
else:
comptparms = (opj2.ImageComptParmType * num_comps)() comptparms = (opj2.ImageComptParmType * num_comps)()
for j in range(num_comps): for j in range(num_comps):
comptparms[j].dx = cparams.subsampling_dx comptparms[j].dx = cparams.subsampling_dx
@ -1339,18 +1426,18 @@ _CMPFUNC = ctypes.CFUNCTYPE(ctypes.c_void_p, ctypes.c_char_p, ctypes.c_void_p)
def _default_error_handler(msg, _): def _default_error_handler(msg, _):
"""Default error handler callback for openjpeg library.""" """Default error handler callback for libopenjp2."""
msg = "OpenJPEG library error: {0}".format(msg.decode('utf-8').rstrip()) msg = "OpenJPEG library error: {0}".format(msg.decode('utf-8').rstrip())
opj2.set_error_message(msg) opj2.set_error_message(msg)
def _default_info_handler(msg, _): def _default_info_handler(msg, _):
"""Default info handler callback for openjpeg library.""" """Default info handler callback."""
print("[INFO] {0}".format(msg.decode('utf-8').rstrip())) print("[INFO] {0}".format(msg.decode('utf-8').rstrip()))
def _default_warning_handler(library_msg, _): def _default_warning_handler(library_msg, _):
"""Default warning handler callback for openjpeg library.""" """Default warning handler callback."""
library_msg = library_msg.decode('utf-8').rstrip() library_msg = library_msg.decode('utf-8').rstrip()
msg = "OpenJPEG library warning: {0}".format(library_msg) msg = "OpenJPEG library warning: {0}".format(library_msg)
warnings.warn(msg) warnings.warn(msg)

View file

@ -685,7 +685,7 @@ def check_error(status):
raise IOError("OpenJPEG function failure.") raise IOError("OpenJPEG function failure.")
# These library functions all return an error status. Circumvent that and # These library functions all return an error status. Circumvent that and
# force # them to raise an exception. # force them to raise an exception.
FCNS = ['opj_decode', 'opj_decode_tile_data', 'opj_end_compress', FCNS = ['opj_decode', 'opj_decode_tile_data', 'opj_end_compress',
'opj_encode', 'opj_end_decompress', 'opj_get_decoded_tile', 'opj_encode', 'opj_end_decompress', 'opj_get_decoded_tile',
'opj_read_header', 'opj_read_tile_header', 'opj_set_decode_area', 'opj_read_header', 'opj_read_tile_header', 'opj_set_decode_area',

View file

@ -6,9 +6,15 @@
import ctypes import ctypes
import sys import sys
import numpy as np
from .config import glymur_config from .config import glymur_config
_, OPENJPEG = glymur_config() _, OPENJPEG = glymur_config()
# Maximum number of tile parts expected by JPWL: increase at your will
JPWL_MAX_NO_TILESPECS = 16
J2K_MAXRLVLS = 33 # Number of maximum resolution level authorized
PATH_LEN = 4096 # maximum allowed size for filenames PATH_LEN = 4096 # maximum allowed size for filenames
@ -52,14 +58,8 @@ class CommonStructType(ctypes.Structure):
("mj2_handle", ctypes.c_void_p)] ("mj2_handle", ctypes.c_void_p)]
class DecompressionInfoType(ctypes.Structure): STREAM_READ = 0x0001 # The stream was opened for reading.
"""This is for decompression contexts. STREAM_WRITE = 0x0002 # The stream was opened for writing.
Corresponds to dinfo_t type in openjpeg headers.
"""
pass
class CioType(ctypes.Structure): class CioType(ctypes.Structure):
"""Byte input-output stream (CIO) """Byte input-output stream (CIO)
@ -80,6 +80,266 @@ class CioType(ctypes.Structure):
("bp", ctypes.c_char_p)] ("bp", ctypes.c_char_p)]
class CompressionInfoType(CommonStructType):
"""Common fields between JPEG-2000 compression and decompression contexts.
This is for compression contexts. Corresponds to common_struct_t.
"""
pass
class PocType(ctypes.Structure):
"""Progression order changes."""
_fields_ = [("resno", ctypes.c_int),
# Resolution num start, Component num start, given by POC
("compno0", ctypes.c_int),
# Layer num end,Resolution num end, Component num end, given by POC
("layno1", ctypes.c_int),
("resno1", ctypes.c_int),
("compno1", ctypes.c_int),
# Layer num start,Precinct num start, Precinct num end
("layno0", ctypes.c_int),
("precno0", ctypes.c_int),
("precno1", ctypes.c_int),
# Progression order enum
# OPJ_PROG_ORDER prg1,prg;
("prg1", ctypes.c_int),
("prg", ctypes.c_int),
# Progression order string
# char progorder[5];
("progorder", ctypes.c_char * 5),
# Tile number
# int tile;
("tile", ctypes.c_int),
# /** Start and end values for Tile width and height*/
# int tx0,tx1,ty0,ty1;
("tx0", ctypes.c_int),
("tx1", ctypes.c_int),
("ty0", ctypes.c_int),
("ty1", ctypes.c_int),
# /** Start value, initialised in pi_initialise_encode*/
# int layS, resS, compS, prcS;
("layS", ctypes.c_int),
("resS", ctypes.c_int),
("compS", ctypes.c_int),
("prcS", ctypes.c_int),
# /** End value, initialised in pi_initialise_encode */
# int layE, resE, compE, prcE;
("layE", ctypes.c_int),
("resE", ctypes.c_int),
("compE", ctypes.c_int),
("prcE", ctypes.c_int),
# Start and end values of Tile width and height, initialised in
# pi_initialise_encode int txS,txE,tyS,tyE,dx,dy;
("txS", ctypes.c_int),
("txE", ctypes.c_int),
("tyS", ctypes.c_int),
("tyE", ctypes.c_int),
("dx", ctypes.c_int),
("dy", ctypes.c_int),
# Temporary values for Tile parts, initialised in pi_create_encode
# int lay_t, res_t, comp_t, prc_t,tx0_t,ty0_t;
("lay_t", ctypes.c_int),
("res_t", ctypes.c_int),
("comp_t", ctypes.c_int),
("prc_t", ctypes.c_int),
("tx0_t", ctypes.c_int),
("ty0_t", ctypes.c_int)]
class CompressionParametersType(ctypes.Structure):
"""Compression parameters.
Corresponds to cparameters_t type in openjp2 headers.
"""
_fields_ = [
# size of tile:
# tile_size_on = false (not in argument) or
# = true (in argument)
("tile_size_on", ctypes.c_int),
# XTOsiz, YTOsiz
("cp_tx0", ctypes.c_int),
("cp_ty0", ctypes.c_int),
# XTsiz, YTsiz
("cp_tdx", ctypes.c_int),
("cp_tdy", ctypes.c_int),
# allocation by rate/distortion
("cp_disto_alloc", ctypes.c_int),
# allocation by fixed layer
("cp_fixed_alloc", ctypes.c_int),
# add fixed_quality
("cp_fixed_quality", ctypes.c_int),
# fixed layer
("cp_matrice", ctypes.c_void_p),
# comment for coding
("cp_comment", ctypes.c_char_p),
# csty : coding style
("csty", ctypes.c_int),
# progression order (default OPJ_LRCP)
("prog_order", ctypes.c_int),
# progression order changes
("poc", PocType * 32),
# number of progression order changes (POC), default to 0
("numpocs", ctypes.c_uint),
# number of layers
("tcp_numlayers", ctypes.c_int),
# rates of layers
("tcp_rates", ctypes.c_float * 100),
# different psnr for successive layers
("tcp_distoratio", ctypes.c_float * 100),
# number of resolutions
("numresolution", ctypes.c_int),
# initial code block width, default to 64
("cblockw_init", ctypes.c_int),
# initial code block height, default to 64
("cblockh_init", ctypes.c_int),
# mode switch (cblk_style)
("mode", ctypes.c_int),
# 1 : use the irreversible DWT 9-7
# 0 : use lossless compression (default)
("irreversible", ctypes.c_int),
# region of interest: affected component in [0..3], -1 means no ROI
("roi_compno", ctypes.c_int),
# region of interest: upshift value
("roi_shift", ctypes.c_int),
# number of precinct size specifications
("res_spec", ctypes.c_int),
# initial precinct width
("prcw_init", ctypes.c_int * J2K_MAXRLVLS),
# initial precinct height
("prch_init", ctypes.c_int * J2K_MAXRLVLS),
# input file name
("infile", ctypes.c_char * PATH_LEN),
# output file name
("outfile", ctypes.c_char * PATH_LEN),
# DEPRECATED.
("index_on", ctypes.c_int),
# DEPRECATED.
("index", ctypes.c_char * PATH_LEN),
# subimage encoding: origin image offset in x direction
# subimage encoding: origin image offset in y direction
("image_offset_x0", ctypes.c_int),
("image_offset_y0", ctypes.c_int),
# subsampling value for dx
# subsampling value for dy
("subsampling_dx", ctypes.c_int),
("subsampling_dy", ctypes.c_int),
# input file format 0: PGX, 1: PxM, 2: BMP 3:TIF
# output file format 0: J2K, 1: JP2, 2: JPT
("decod_format", ctypes.c_int),
("cod_format", ctypes.c_int),
# JPWL encoding parameters
# enables writing of EPC in MH, thus activating JPWL
("jpwl_epc_on", ctypes.c_int),
# error protection method for MH (0,1,16,32,37-128)
("jpwl_hprot_mh", ctypes.c_int),
# tile number of header protection specification (>=0)
("jpwl_hprot_tph_tileno", ctypes.c_int * JPWL_MAX_NO_TILESPECS),
# error protection methods for TPHs (0,1,16,32,37-128)
("jpwl_hprot_tph", ctypes.c_int * JPWL_MAX_NO_TILESPECS),
# tile number of packet protection specification (>=0)
("jpwl_pprot_tileno", ctypes.c_int * JPWL_MAX_NO_TILESPECS),
# packet number of packet protection specification (>=0)
("jpwl_pprot_packno", ctypes.c_int * JPWL_MAX_NO_TILESPECS),
# error protection methods for packets (0,1,16,32,37-128)
("jpwl_pprot", ctypes.c_int * JPWL_MAX_NO_TILESPECS),
# enables writing of ESD, (0=no/1/2 bytes)
("jpwl_sens_size", ctypes.c_int),
# sensitivity addressing size (0=auto/2/4 bytes)
("jpwl_sens_addr", ctypes.c_int),
# sensitivity range (0-3)
("jpwl_sens_range", ctypes.c_int),
# sensitivity method for MH (-1=no,0-7)
("jpwl_sens_mh", ctypes.c_int),
# tile number of sensitivity specification (>=0)
("jpwl_sens_tph_tileno", ctypes.c_int * JPWL_MAX_NO_TILESPECS),
# sensitivity methods for TPHs (-1=no,0-7)
("jpwl_sens_tph", ctypes.c_int * JPWL_MAX_NO_TILESPECS),
# Digital Cinema compliance 0-not compliant, 1-compliant
("cp_cinema", ctypes.c_int),
# Maximum rate for each component.
# If == 0, component size limitation is not considered
("max_comp_size", ctypes.c_int),
# Profile name
("cp_rsiz", ctypes.c_int),
# Tile part generation
("tp_on", ctypes.c_uint8),
# Flag for Tile part generation
("tp_flag", ctypes.c_uint8),
# MCT (multiple component transform)
("tcp_mct", ctypes.c_uint8),
# Enable JPIP indexing
("jpip_on", ctypes.c_int)]
class DecompressionInfoType(ctypes.Structure):
"""This is for decompression contexts.
Corresponds to dinfo_t type in openjpeg headers.
"""
pass
class DecompressionParametersType(ctypes.Structure): class DecompressionParametersType(ctypes.Structure):
"""Decompression parameters. """Decompression parameters.
@ -111,11 +371,39 @@ class DecompressionParametersType(ctypes.Structure):
_fields_.append(("flags", ctypes.c_uint)) _fields_.append(("flags", ctypes.c_uint))
class ImageCompType(ctypes.Structure): class ImageComptParmType(ctypes.Structure):
"""Defines a single image component. """Component parameters structure used by the opj_image_create function.
Corresponds to image_comp_t type in openjpeg.
""" """
_fields_ = [
# XRsiz: horizontal separation of a sample of ith component with
# respect to the reference grid
("dx", ctypes.c_int),
# YRsiz: vertical separation of a sample of ith component with
# respect to the reference grid */
("dy", ctypes.c_int),
# data width, height
("w", ctypes.c_int),
("h", ctypes.c_int),
# x component offset compared to the whole image
# y component offset compared to the whole image
("x0", ctypes.c_int),
("y0", ctypes.c_int),
# precision
('prec', ctypes.c_int),
# image depth in bits
('bpp', ctypes.c_int),
# signed (1) / unsigned (0)
('sgnd', ctypes.c_int)]
class ImageCompType(ctypes.Structure):
"""Defines a single image component. """
_fields_ = [("dx", ctypes.c_int), _fields_ = [("dx", ctypes.c_int),
("dy", ctypes.c_int), ("dy", ctypes.c_int),
("w", ctypes.c_int), ("w", ctypes.c_int),
@ -146,16 +434,22 @@ class ImageType(ctypes.Structure):
("icc_profile_len", ctypes.c_int)] ("icc_profile_len", ctypes.c_int)]
def cio_open(cinfo, src): def cio_open(cinfo, src=None):
"""Wrapper for openjpeg library function opj_cio_open.""" """Wrapper for openjpeg library function opj_cio_open."""
argtypes = [ctypes.POINTER(CommonStructType), ctypes.c_char_p, argtypes = [ctypes.POINTER(CommonStructType), ctypes.c_char_p,
ctypes.c_int] ctypes.c_int]
OPENJPEG.opj_cio_open.argtypes = argtypes OPENJPEG.opj_cio_open.argtypes = argtypes
OPENJPEG.opj_cio_open.restype = ctypes.POINTER(CioType) OPENJPEG.opj_cio_open.restype = ctypes.POINTER(CioType)
if src is None:
length = 0
else:
length = len(src)
cio = OPENJPEG.opj_cio_open(ctypes.cast(cinfo, cio = OPENJPEG.opj_cio_open(ctypes.cast(cinfo,
ctypes.POINTER(CommonStructType)), ctypes.POINTER(CommonStructType)),
src, len(src)) src,
length)
return cio return cio
@ -166,6 +460,24 @@ def cio_close(cio):
OPENJPEG.opj_cio_close(cio) OPENJPEG.opj_cio_close(cio)
def cio_tell(cio):
"""Get position in byte stream."""
OPENJPEG.cio_tell.argtypes = [ctypes.POINTER(CioType)]
OPENJPEG.cio_tell.restype = ctypes.c_int
pos = OPENJPEG.cio_tell(cio)
return pos
def create_compress(fmt):
"""Wrapper for openjpeg library function opj_create_compress.
Creates a J2K/JPT/JP2 compression structure.
"""
OPENJPEG.opj_create_compress.argtypes = [ctypes.c_int]
OPENJPEG.opj_create_compress.restype = ctypes.POINTER(CompressionInfoType)
cinfo = OPENJPEG.opj_create_compress(fmt)
return cinfo
def create_decompress(fmt): def create_decompress(fmt):
"""Wraps openjpeg library function opj_create_decompress. """Wraps openjpeg library function opj_create_decompress.
""" """
@ -186,6 +498,38 @@ def decode(dinfo, cio):
return image return image
def destroy_compress(cinfo):
"""Wrapper for openjpeg library function opj_destroy_compress.
Release resources for a compressor handle.
"""
argtypes = [ctypes.POINTER(CompressionInfoType)]
OPENJPEG.opj_destroy_compress.argtypes = argtypes
OPENJPEG.opj_destroy_compress(cinfo)
def encode(cinfo, cio, image):
"""Wrapper for openjpeg library function opj_encode.
Encodes an image into a JPEG-2000 codestream.
Parameters
----------
cinfo : compression handle
cio : output buffer stream
image : image to encode
"""
argtypes = [ctypes.POINTER(CompressionInfoType),
ctypes.POINTER(CioType),
ctypes.POINTER(ImageType)]
OPENJPEG.opj_encode.argtypes = argtypes
OPENJPEG.opj_encode.restype = ctypes.c_int
status = OPENJPEG.opj_encode(cinfo, cio, image)
return status
def destroy_decompress(dinfo): def destroy_decompress(dinfo):
"""Wraps openjpeg library function opj_destroy_decompress.""" """Wraps openjpeg library function opj_destroy_decompress."""
argtypes = [ctypes.POINTER(DecompressionInfoType)] argtypes = [ctypes.POINTER(DecompressionInfoType)]
@ -193,12 +537,78 @@ def destroy_decompress(dinfo):
OPENJPEG.opj_destroy_decompress(dinfo) OPENJPEG.opj_destroy_decompress(dinfo)
def image_cmptparm_t_from_np(np_image):
"""Return appropriate image_cmptparm_t based on given numpy array.
"""
try:
num_comps = np_image.shape[2]
except IndexError:
num_comps = 1
cmpt_parm_array_t = ImageCmptparmType * num_comps
tarr = cmpt_parm_array_t()
if np_image.dtype == np.uint8:
prec = 8
bpp = 8
sgnd = 0
elif np_image.dtype == np.int8:
prec = 8
bpp = 8
sgnd = 1
elif np_image.dtype == np.uint16:
prec = 16
bpp = 16
sgnd = 0
elif np_image.dtype == np.int16:
prec = 16
bpp = 16
sgnd = 1
else:
raise(TypeError("unhandled"))
for j in range(0, num_comps):
tarr[j].dx = 1
tarr[j].dy = 1
tarr[j].w = np_image.shape[1]
tarr[j].h = np_image.shape[0]
tarr[j].x0 = 0
tarr[j].y0 = 0
tarr[j].prec = prec
tarr[j].bpp = bpp
tarr[j].sgnd = sgnd
return(tarr)
def image_create(cmptparms, cspace):
"""Wrapper for openjpeg library function opj_image_create.
"""
OPENJPEG.opj_image_create.argtypes = [ctypes.c_int,
ctypes.POINTER(ImageComptParmType),
ctypes.c_int]
OPENJPEG.opj_image_create.restype = ctypes.POINTER(ImageType)
image = OPENJPEG.opj_image_create(len(cmptparms), cmptparms, cspace)
return(image)
def image_destroy(image): def image_destroy(image):
"""Wraps openjpeg library function opj_image_destroy.""" """Wraps openjpeg library function opj_image_destroy."""
OPENJPEG.opj_image_destroy.argtypes = [ctypes.POINTER(ImageType)] OPENJPEG.opj_image_destroy.argtypes = [ctypes.POINTER(ImageType)]
OPENJPEG.opj_image_destroy(image) OPENJPEG.opj_image_destroy(image)
def set_default_encoder_parameters():
"""Wrapper for openjpeg library function opj_set_default_encoder_parameters.
"""
cparams = CompressionParametersType()
argtypes = [ctypes.POINTER(CompressionParametersType)]
OPENJPEG.opj_set_default_encoder_parameters.argtypes = argtypes
OPENJPEG.opj_set_default_encoder_parameters(ctypes.byref(cparams))
return cparams
def set_default_decoder_parameters(dparams_p): def set_default_decoder_parameters(dparams_p):
"""Wrapper for opj_set_default_decoder_parameters. """Wrapper for opj_set_default_decoder_parameters.
""" """
@ -219,6 +629,15 @@ def set_event_mgr(dinfo, event_mgr, context=None):
event_mgr, context) event_mgr, context)
def setup_encoder(cinfo, cparameters, image):
"""Wrapper for openjpeg library function opj_setup_decoder."""
argtypes = [ctypes.POINTER(CompressionInfoType),
ctypes.POINTER(CompressionParametersType),
ctypes.POINTER(ImageType)]
OPENJPEG.opj_setup_encoder.argtypes = argtypes
OPENJPEG.opj_setup_encoder(cinfo, cparameters, image)
def setup_decoder(dinfo, dparams): def setup_decoder(dinfo, dparams):
"""Wrapper for openjpeg library function opj_setup_decoder.""" """Wrapper for openjpeg library function opj_setup_decoder."""
argtypes = [ctypes.POINTER(DecompressionInfoType), argtypes = [ctypes.POINTER(DecompressionInfoType),

View file

@ -1,6 +1,7 @@
""" """
Test fixtures common to more than one test point. Test fixtures common to more than one test point.
""" """
import os
import re import re
import sys import sys
import warnings import warnings
@ -9,11 +10,6 @@ import numpy as np
import glymur import glymur
# Need to know the openjpeg version. If openjpeg is not installed, we use
# '0.0.0'
OPENJPEG_VERSION = '0.0.0'
if glymur.lib.openjpeg.OPENJPEG is not None:
OPENJPEG_VERSION = glymur.lib.openjpeg.version()
# Need to know of the libopenjp2 version is the official 2.0.0 release and NOT # Need to know of the libopenjp2 version is the official 2.0.0 release and NOT
# the 2.0+ development version. # the 2.0+ development version.
@ -27,6 +23,19 @@ if glymur.lib.openjp2.OPENJP2 is not None:
NO_READ_BACKEND_MSG = "Matplotlib with the PIL backend must be available in " NO_READ_BACKEND_MSG = "Matplotlib with the PIL backend must be available in "
NO_READ_BACKEND_MSG += "order to run the tests in this suite." NO_READ_BACKEND_MSG += "order to run the tests in this suite."
try:
OPJ_DATA_ROOT = os.environ['OPJ_DATA_ROOT']
except KeyError:
OPJ_DATA_ROOT = None
except:
raise
def opj_data_file(relative_file_name):
"""Compact way of forming a full filename from OpenJPEG's test suite."""
jfile = os.path.join(OPJ_DATA_ROOT, relative_file_name)
return jfile
try: try:
from matplotlib.pyplot import imread from matplotlib.pyplot import imread

View file

@ -117,6 +117,8 @@ class TestConfig(unittest.TestCase):
""" """
with patch('glymur.lib.openjp2.OPENJP2', new=None): with patch('glymur.lib.openjp2.OPENJP2', new=None):
with patch('glymur.lib.openjpeg.OPENJPEG', new=None): with patch('glymur.lib.openjpeg.OPENJPEG', new=None):
with patch('glymur.version.openjpeg_version_tuple',
new=(0, 0, 0)):
with self.assertRaises(glymur.jp2k.LibraryNotFoundError): with self.assertRaises(glymur.jp2k.LibraryNotFoundError):
glymur.Jp2k(self.jp2file).read_bands() glymur.Jp2k(self.jp2file).read_bands()

View file

@ -12,6 +12,7 @@ These tests deal with JPX/JP2/J2K images in the format-corpus repository.
import os import os
from os.path import join from os.path import join
import re
import sys import sys
if sys.hexversion < 0x02070000: if sys.hexversion < 0x02070000:
@ -19,6 +20,7 @@ if sys.hexversion < 0x02070000:
else: else:
import unittest import unittest
import glymur
from glymur import Jp2k from glymur import Jp2k
try: try:
@ -39,6 +41,9 @@ except KeyError:
class TestSuiteFormatCorpus(unittest.TestCase): class TestSuiteFormatCorpus(unittest.TestCase):
"""Test suite for files in format corpus repository.""" """Test suite for files in format corpus repository."""
@unittest.skipIf(re.match(r"""1\.[0123]""",
glymur.version.openjpeg_version) is not None,
"Needs 1.3+ to catch this.")
def test_balloon_trunc1(self): def test_balloon_trunc1(self):
"""Has one byte shaved off of EOC marker.""" """Has one byte shaved off of EOC marker."""
jfile = os.path.join(FORMAT_CORPUS_DATA_ROOT, jfile = os.path.join(FORMAT_CORPUS_DATA_ROOT,
@ -54,6 +59,9 @@ class TestSuiteFormatCorpus(unittest.TestCase):
with self.assertRaises(OSError): with self.assertRaises(OSError):
j2k.read(rlevel=-1) j2k.read(rlevel=-1)
@unittest.skipIf(re.match(r"""1\.[01234]""",
glymur.version.openjpeg_version) is not None,
"Needs 1.4+ to catch this.")
def test_balloon_trunc2(self): def test_balloon_trunc2(self):
"""Shortened by 5000 bytes.""" """Shortened by 5000 bytes."""
jfile = os.path.join(FORMAT_CORPUS_DATA_ROOT, jfile = os.path.join(FORMAT_CORPUS_DATA_ROOT,

View file

@ -20,16 +20,10 @@ else:
import numpy as np import numpy as np
from glymur import Jp2k from glymur import Jp2k
from .fixtures import OPJ_DATA_ROOT, opj_data_file
try:
DATA_ROOT = os.environ['OPJ_DATA_ROOT']
except KeyError:
DATA_ROOT = None
except:
raise
@unittest.skipIf(DATA_ROOT is None, @unittest.skipIf(OPJ_DATA_ROOT is None,
"OPJ_DATA_ROOT environment variable not set") "OPJ_DATA_ROOT environment variable not set")
class TestICC(unittest.TestCase): class TestICC(unittest.TestCase):
"""ICC profile tests""" """ICC profile tests"""
@ -42,7 +36,7 @@ class TestICC(unittest.TestCase):
def test_file5(self): def test_file5(self):
"""basic ICC profile""" """basic ICC profile"""
filename = os.path.join(DATA_ROOT, 'input/conformance/file5.jp2') filename = opj_data_file('input/conformance/file5.jp2')
j = Jp2k(filename) j = Jp2k(filename)
profile = j.box[3].box[1].icc_profile profile = j.box[3].box[1].icc_profile
self.assertEqual(profile['Size'], 546) self.assertEqual(profile['Size'], 546)
@ -75,8 +69,7 @@ class TestICC(unittest.TestCase):
"Uses features introduced in 3.2.") "Uses features introduced in 3.2.")
def test_invalid_profile_header(self): def test_invalid_profile_header(self):
"""invalid ICC header data should cause UserWarning""" """invalid ICC header data should cause UserWarning"""
jfile = os.path.join(DATA_ROOT, jfile = opj_data_file('input/nonregression/orb-blue10-lin-jp2.jp2')
'input/nonregression/orb-blue10-lin-jp2.jp2')
# assertWarns in Python 3.3 (python2.7/pylint issue) # assertWarns in Python 3.3 (python2.7/pylint issue)
# pylint: disable=E1101 # pylint: disable=E1101

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

View file

@ -23,23 +23,17 @@ else:
import numpy as np import numpy as np
from .fixtures import read_image, NO_READ_BACKEND, NO_READ_BACKEND_MSG from .fixtures import read_image, NO_READ_BACKEND, NO_READ_BACKEND_MSG
from .fixtures import OPJ_DATA_ROOT, opj_data_file
from glymur import Jp2k from glymur import Jp2k
import glymur 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, @unittest.skipIf(glymur.lib.openjp2.OPENJP2 is None,
"Missing openjp2 library.") "Missing openjp2 library.")
@unittest.skipIf(NO_READ_BACKEND, NO_READ_BACKEND_MSG) @unittest.skipIf(NO_READ_BACKEND, NO_READ_BACKEND_MSG)
@unittest.skipIf(DATA_ROOT is None, @unittest.skipIf(OPJ_DATA_ROOT is None,
"OPJ_DATA_ROOT environment variable not set") "OPJ_OPJ_DATA_ROOT environment variable not set")
class TestSuiteNegative(unittest.TestCase): class TestSuiteNegative(unittest.TestCase):
"""Test suite for certain negative tests from openjpeg suite.""" """Test suite for certain negative tests from openjpeg suite."""
@ -54,7 +48,7 @@ class TestSuiteNegative(unittest.TestCase):
def test_psnr_with_cratios(self): def test_psnr_with_cratios(self):
"""Using psnr with cratios options is not allowed.""" """Using psnr with cratios options is not allowed."""
# Not an OpenJPEG test, but close. # Not an OpenJPEG test, but close.
infile = os.path.join(DATA_ROOT, 'input/nonregression/Bretagne1.ppm') infile = opj_data_file('input/nonregression/Bretagne1.ppm')
data = read_image(infile) data = read_image(infile)
with tempfile.NamedTemporaryFile(suffix='.j2k') as tfile: with tempfile.NamedTemporaryFile(suffix='.j2k') as tfile:
j = Jp2k(tfile.name, 'wb') j = Jp2k(tfile.name, 'wb')
@ -64,7 +58,7 @@ class TestSuiteNegative(unittest.TestCase):
def test_nr_marker_not_compliant(self): def test_nr_marker_not_compliant(self):
"""non-compliant marker, should still be able to read""" """non-compliant marker, should still be able to read"""
relpath = 'input/nonregression/MarkerIsNotCompliant.j2k' relpath = 'input/nonregression/MarkerIsNotCompliant.j2k'
jfile = os.path.join(DATA_ROOT, relpath) jfile = opj_data_file(relpath)
jp2k = Jp2k(jfile) jp2k = Jp2k(jfile)
jp2k.get_codestream(header_only=False) jp2k.get_codestream(header_only=False)
self.assertTrue(True) self.assertTrue(True)
@ -74,7 +68,7 @@ class TestSuiteNegative(unittest.TestCase):
def test_nr_illegalclrtransform(self): def test_nr_illegalclrtransform(self):
"""EOC marker is bad""" """EOC marker is bad"""
relpath = 'input/nonregression/illegalcolortransform.j2k' relpath = 'input/nonregression/illegalcolortransform.j2k'
jfile = os.path.join(DATA_ROOT, relpath) jfile = opj_data_file(relpath)
jp2k = Jp2k(jfile) jp2k = Jp2k(jfile)
with self.assertWarns(UserWarning): with self.assertWarns(UserWarning):
codestream = jp2k.get_codestream(header_only=False) codestream = jp2k.get_codestream(header_only=False)
@ -87,7 +81,7 @@ class TestSuiteNegative(unittest.TestCase):
def test_nr_cannotreadwnosizeknown(self): def test_nr_cannotreadwnosizeknown(self):
"""not sure exactly what is wrong with this file""" """not sure exactly what is wrong with this file"""
relpath = 'input/nonregression/Cannotreaddatawithnosizeknown.j2k' relpath = 'input/nonregression/Cannotreaddatawithnosizeknown.j2k'
jfile = os.path.join(DATA_ROOT, relpath) jfile = opj_data_file(relpath)
jp2k = Jp2k(jfile) jp2k = Jp2k(jfile)
jp2k.get_codestream(header_only=False) jp2k.get_codestream(header_only=False)
self.assertTrue(True) self.assertTrue(True)
@ -118,7 +112,7 @@ class TestSuiteNegative(unittest.TestCase):
# Verify that a warning is issued if we read past the end of a box # Verify that a warning is issued if we read past the end of a box
# This file has a palette (pclr) box whose length is impossibly # This file has a palette (pclr) box whose length is impossibly
# short. # short.
infile = os.path.join(DATA_ROOT, infile = os.path.join(OPJ_DATA_ROOT,
'input/nonregression/mem-b2ace68c-1381.jp2') 'input/nonregression/mem-b2ace68c-1381.jp2')
with self.assertWarns(UserWarning): with self.assertWarns(UserWarning):
Jp2k(infile) Jp2k(infile)

View file

@ -10,6 +10,7 @@ suite.
# pylint: disable=F0401 # pylint: disable=F0401
import os import os
import re
import sys import sys
import tempfile import tempfile
@ -19,23 +20,18 @@ else:
import unittest import unittest
from .fixtures import read_image, NO_READ_BACKEND, NO_READ_BACKEND_MSG from .fixtures import read_image, NO_READ_BACKEND, NO_READ_BACKEND_MSG
from .fixtures import OPJ_DATA_ROOT, opj_data_file
from glymur import Jp2k from glymur import Jp2k
import glymur import glymur
try:
data_root = os.environ['OPJ_DATA_ROOT']
except KeyError:
data_root = None
except:
raise
@unittest.skipIf(os.name == "nt", "no write support on windows, period") @unittest.skipIf(os.name == "nt", "no write support on windows, period")
@unittest.skipIf(glymur.lib.openjp2.OPENJP2 is None, @unittest.skipIf(re.match(r"""1\.[01234]\.\d""",
"Missing openjp2 library.") glymur.version.openjpeg_version) is not None,
"Writing only supported with openjpeg version 1.5+.")
@unittest.skipIf(NO_READ_BACKEND, NO_READ_BACKEND_MSG) @unittest.skipIf(NO_READ_BACKEND, NO_READ_BACKEND_MSG)
@unittest.skipIf(data_root is None, @unittest.skipIf(OPJ_DATA_ROOT is None,
"OPJ_DATA_ROOT environment variable not set") "OPJ_DATA_ROOT environment variable not set")
class TestSuiteWrite(unittest.TestCase): class TestSuiteWrite(unittest.TestCase):
"""Tests for writing with openjp2 backend. """Tests for writing with openjp2 backend.
@ -51,7 +47,7 @@ class TestSuiteWrite(unittest.TestCase):
def test_NR_ENC_Bretagne1_ppm_1_encode(self): def test_NR_ENC_Bretagne1_ppm_1_encode(self):
"""NR-ENC-Bretagne1.ppm-1-encode""" """NR-ENC-Bretagne1.ppm-1-encode"""
infile = os.path.join(data_root, 'input/nonregression/Bretagne1.ppm') infile = opj_data_file('input/nonregression/Bretagne1.ppm')
data = read_image(infile) data = read_image(infile)
with tempfile.NamedTemporaryFile(suffix='.j2k') as tfile: with tempfile.NamedTemporaryFile(suffix='.j2k') as tfile:
j = Jp2k(tfile.name, 'wb') j = Jp2k(tfile.name, 'wb')
@ -115,7 +111,7 @@ class TestSuiteWrite(unittest.TestCase):
def test_NR_ENC_Bretagne1_ppm_2_encode(self): def test_NR_ENC_Bretagne1_ppm_2_encode(self):
"""NR-ENC-Bretagne1.ppm-2-encode""" """NR-ENC-Bretagne1.ppm-2-encode"""
infile = os.path.join(data_root, 'input/nonregression/Bretagne1.ppm') infile = opj_data_file('input/nonregression/Bretagne1.ppm')
data = read_image(infile) data = read_image(infile)
with tempfile.NamedTemporaryFile(suffix='.j2k') as tfile: with tempfile.NamedTemporaryFile(suffix='.j2k') as tfile:
j = Jp2k(tfile.name, 'wb') j = Jp2k(tfile.name, 'wb')
@ -180,7 +176,7 @@ class TestSuiteWrite(unittest.TestCase):
def test_NR_ENC_Bretagne1_ppm_3_encode(self): def test_NR_ENC_Bretagne1_ppm_3_encode(self):
"""NR-ENC-Bretagne1.ppm-3-encode""" """NR-ENC-Bretagne1.ppm-3-encode"""
infile = os.path.join(data_root, 'input/nonregression/Bretagne1.ppm') infile = opj_data_file('input/nonregression/Bretagne1.ppm')
data = read_image(infile) data = read_image(infile)
with tempfile.NamedTemporaryFile(suffix='.j2k') as tfile: with tempfile.NamedTemporaryFile(suffix='.j2k') as tfile:
j = Jp2k(tfile.name, 'wb') j = Jp2k(tfile.name, 'wb')
@ -247,7 +243,7 @@ class TestSuiteWrite(unittest.TestCase):
def test_NR_ENC_Bretagne2_ppm_4_encode(self): def test_NR_ENC_Bretagne2_ppm_4_encode(self):
"""NR-ENC-Bretagne2.ppm-4-encode""" """NR-ENC-Bretagne2.ppm-4-encode"""
infile = os.path.join(data_root, 'input/nonregression/Bretagne2.ppm') infile = opj_data_file('input/nonregression/Bretagne2.ppm')
data = read_image(infile) data = read_image(infile)
with tempfile.NamedTemporaryFile(suffix='.j2k') as tfile: with tempfile.NamedTemporaryFile(suffix='.j2k') as tfile:
j = Jp2k(tfile.name, 'wb') j = Jp2k(tfile.name, 'wb')
@ -316,7 +312,7 @@ class TestSuiteWrite(unittest.TestCase):
def test_NR_ENC_Bretagne2_ppm_5_encode(self): def test_NR_ENC_Bretagne2_ppm_5_encode(self):
"""NR-ENC-Bretagne2.ppm-5-encode""" """NR-ENC-Bretagne2.ppm-5-encode"""
infile = os.path.join(data_root, 'input/nonregression/Bretagne2.ppm') infile = opj_data_file('input/nonregression/Bretagne2.ppm')
data = read_image(infile) data = read_image(infile)
with tempfile.NamedTemporaryFile(suffix='.j2k') as tfile: with tempfile.NamedTemporaryFile(suffix='.j2k') as tfile:
j = Jp2k(tfile.name, 'wb') j = Jp2k(tfile.name, 'wb')
@ -379,7 +375,7 @@ class TestSuiteWrite(unittest.TestCase):
def test_NR_ENC_Bretagne2_ppm_6_encode(self): def test_NR_ENC_Bretagne2_ppm_6_encode(self):
"""NR-ENC-Bretagne2.ppm-6-encode""" """NR-ENC-Bretagne2.ppm-6-encode"""
infile = os.path.join(data_root, 'input/nonregression/Bretagne2.ppm') infile = opj_data_file('input/nonregression/Bretagne2.ppm')
data = read_image(infile) data = read_image(infile)
with tempfile.NamedTemporaryFile(suffix='.j2k') as tfile: with tempfile.NamedTemporaryFile(suffix='.j2k') as tfile:
j = Jp2k(tfile.name, 'wb') j = Jp2k(tfile.name, 'wb')
@ -447,7 +443,7 @@ class TestSuiteWrite(unittest.TestCase):
def test_NR_ENC_Bretagne2_ppm_7_encode(self): def test_NR_ENC_Bretagne2_ppm_7_encode(self):
"""NR-ENC-Bretagne2.ppm-7-encode""" """NR-ENC-Bretagne2.ppm-7-encode"""
infile = os.path.join(data_root, 'input/nonregression/Bretagne2.ppm') infile = opj_data_file('input/nonregression/Bretagne2.ppm')
data = read_image(infile) data = read_image(infile)
with tempfile.NamedTemporaryFile(suffix='.j2k') as tfile: with tempfile.NamedTemporaryFile(suffix='.j2k') as tfile:
j = Jp2k(tfile.name, 'wb') j = Jp2k(tfile.name, 'wb')
@ -514,7 +510,7 @@ class TestSuiteWrite(unittest.TestCase):
def test_NR_ENC_Bretagne2_ppm_8_encode(self): def test_NR_ENC_Bretagne2_ppm_8_encode(self):
"""NR-ENC-Bretagne2.ppm-8-encode""" """NR-ENC-Bretagne2.ppm-8-encode"""
infile = os.path.join(data_root, 'input/nonregression/Bretagne2.ppm') infile = opj_data_file('input/nonregression/Bretagne2.ppm')
data = read_image(infile) data = read_image(infile)
with tempfile.NamedTemporaryFile(suffix='.j2k') as tfile: with tempfile.NamedTemporaryFile(suffix='.j2k') as tfile:
j = Jp2k(tfile.name, 'wb') j = Jp2k(tfile.name, 'wb')
@ -578,7 +574,7 @@ class TestSuiteWrite(unittest.TestCase):
def test_NR_ENC_Cevennes1_bmp_9_encode(self): def test_NR_ENC_Cevennes1_bmp_9_encode(self):
"""NR-ENC-Cevennes1.bmp-9-encode""" """NR-ENC-Cevennes1.bmp-9-encode"""
infile = os.path.join(data_root, 'input/nonregression/Cevennes1.bmp') infile = opj_data_file('input/nonregression/Cevennes1.bmp')
data = read_image(infile) data = read_image(infile)
with tempfile.NamedTemporaryFile(suffix='.j2k') as tfile: with tempfile.NamedTemporaryFile(suffix='.j2k') as tfile:
j = Jp2k(tfile.name, 'wb') j = Jp2k(tfile.name, 'wb')
@ -641,7 +637,7 @@ class TestSuiteWrite(unittest.TestCase):
def test_NR_ENC_Cevennes2_ppm_10_encode(self): def test_NR_ENC_Cevennes2_ppm_10_encode(self):
"""NR-ENC-Cevennes2.ppm-10-encode""" """NR-ENC-Cevennes2.ppm-10-encode"""
infile = os.path.join(data_root, 'input/nonregression/Cevennes2.ppm') infile = opj_data_file('input/nonregression/Cevennes2.ppm')
data = read_image(infile) data = read_image(infile)
with tempfile.NamedTemporaryFile(suffix='.j2k') as tfile: with tempfile.NamedTemporaryFile(suffix='.j2k') as tfile:
j = Jp2k(tfile.name, 'wb') j = Jp2k(tfile.name, 'wb')
@ -704,8 +700,7 @@ class TestSuiteWrite(unittest.TestCase):
def test_NR_ENC_Rome_bmp_11_encode(self): def test_NR_ENC_Rome_bmp_11_encode(self):
"""NR-ENC-Rome.bmp-11-encode""" """NR-ENC-Rome.bmp-11-encode"""
data = read_image(os.path.join(data_root, data = read_image(opj_data_file('input/nonregression/Rome.bmp'))
'input/nonregression/Rome.bmp'))
with tempfile.NamedTemporaryFile(suffix='.jp2') as tfile: with tempfile.NamedTemporaryFile(suffix='.jp2') as tfile:
jp2 = Jp2k(tfile.name, 'wb') jp2 = Jp2k(tfile.name, 'wb')
jp2.write(data, psnr=[30, 35, 50], prog='LRCP', numres=3) jp2.write(data, psnr=[30, 35, 50], prog='LRCP', numres=3)
@ -804,8 +799,7 @@ class TestSuiteWrite(unittest.TestCase):
"""NR-ENC-random-issue-0005.tif-12-encode""" """NR-ENC-random-issue-0005.tif-12-encode"""
# opj_decompress has trouble reading it, but that is not an issue here. # opj_decompress has trouble reading it, but that is not an issue here.
# The nature of the image itself seems to give the compressor trouble. # The nature of the image itself seems to give the compressor trouble.
infile = os.path.join(data_root, infile = opj_data_file('input/nonregression/random-issue-0005.tif')
'input/nonregression/random-issue-0005.tif')
data = read_image(infile) data = read_image(infile)
with tempfile.NamedTemporaryFile(suffix='.j2k') as tfile: with tempfile.NamedTemporaryFile(suffix='.j2k') as tfile:
j = Jp2k(tfile.name, 'wb') j = Jp2k(tfile.name, 'wb')

View file

@ -32,13 +32,7 @@ else:
import glymur import glymur
from glymur import Jp2k from glymur import Jp2k
from .fixtures import OPJ_DATA_ROOT, opj_data_file
try:
DATA_ROOT = os.environ['OPJ_DATA_ROOT']
except KeyError:
DATA_ROOT = None
except:
raise
@unittest.skipIf(os.name == "nt", "Temporary file issue on window.") @unittest.skipIf(os.name == "nt", "Temporary file issue on window.")
@ -287,11 +281,11 @@ class TestPrinting(unittest.TestCase):
expected = '\n'.join(lines) expected = '\n'.join(lines)
self.assertEqual(actual, expected) self.assertEqual(actual, expected)
@unittest.skipIf(DATA_ROOT is None, @unittest.skipIf(OPJ_DATA_ROOT is None,
"OPJ_DATA_ROOT environment variable not set") "OPJ_DATA_ROOT environment variable not set")
def test_icc_profile(self): def test_icc_profile(self):
"""verify printing of colr box with ICC profile""" """verify printing of colr box with ICC profile"""
filename = os.path.join(DATA_ROOT, 'input/nonregression/text_GBR.jp2') filename = opj_data_file('input/nonregression/text_GBR.jp2')
with warnings.catch_warnings(): with warnings.catch_warnings():
# brand is 'jp2 ', but has any icc profile. # brand is 'jp2 ', but has any icc profile.
warnings.simplefilter("ignore") warnings.simplefilter("ignore")
@ -356,11 +350,11 @@ class TestPrinting(unittest.TestCase):
expected = '\n'.join(lines) expected = '\n'.join(lines)
self.assertEqual(actual, expected) self.assertEqual(actual, expected)
@unittest.skipIf(DATA_ROOT is None, @unittest.skipIf(OPJ_DATA_ROOT is None,
"OPJ_DATA_ROOT environment variable not set") "OPJ_DATA_ROOT environment variable not set")
def test_crg(self): def test_crg(self):
"""verify printing of CRG segment""" """verify printing of CRG segment"""
filename = os.path.join(DATA_ROOT, 'input/conformance/p0_03.j2k') filename = opj_data_file('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: with patch('sys.stdout', new=StringIO()) as fake_out:
@ -371,11 +365,11 @@ class TestPrinting(unittest.TestCase):
expected = '\n'.join(lines) expected = '\n'.join(lines)
self.assertEqual(actual, expected) self.assertEqual(actual, expected)
@unittest.skipIf(DATA_ROOT is None, @unittest.skipIf(OPJ_DATA_ROOT is None,
"OPJ_DATA_ROOT environment variable not set") "OPJ_DATA_ROOT environment variable not set")
def test_rgn(self): def test_rgn(self):
"""verify printing of RGN segment""" """verify printing of RGN segment"""
filename = os.path.join(DATA_ROOT, 'input/conformance/p0_03.j2k') filename = opj_data_file('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: with patch('sys.stdout', new=StringIO()) as fake_out:
@ -388,11 +382,11 @@ class TestPrinting(unittest.TestCase):
expected = '\n'.join(lines) expected = '\n'.join(lines)
self.assertEqual(actual, expected) self.assertEqual(actual, expected)
@unittest.skipIf(DATA_ROOT is None, @unittest.skipIf(OPJ_DATA_ROOT is None,
"OPJ_DATA_ROOT environment variable not set") "OPJ_DATA_ROOT environment variable not set")
def test_sop(self): def test_sop(self):
"""verify printing of SOP segment""" """verify printing of SOP segment"""
filename = os.path.join(DATA_ROOT, 'input/conformance/p0_03.j2k') filename = opj_data_file('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: with patch('sys.stdout', new=StringIO()) as fake_out:
@ -403,11 +397,11 @@ class TestPrinting(unittest.TestCase):
expected = '\n'.join(lines) expected = '\n'.join(lines)
self.assertEqual(actual, expected) self.assertEqual(actual, expected)
@unittest.skipIf(DATA_ROOT is None, @unittest.skipIf(OPJ_DATA_ROOT is None,
"OPJ_DATA_ROOT environment variable not set") "OPJ_DATA_ROOT environment variable not set")
def test_cme(self): def test_cme(self):
"""Test printing a CME or comment marker segment.""" """Test printing a CME or comment marker segment."""
filename = os.path.join(DATA_ROOT, 'input/conformance/p0_02.j2k') filename = opj_data_file('input/conformance/p0_02.j2k')
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
@ -431,11 +425,11 @@ class TestPrinting(unittest.TestCase):
expected = '\n'.join(lines) expected = '\n'.join(lines)
self.assertEqual(actual, expected) self.assertEqual(actual, expected)
@unittest.skipIf(DATA_ROOT is None, @unittest.skipIf(OPJ_DATA_ROOT is None,
"OPJ_DATA_ROOT environment variable not set") "OPJ_DATA_ROOT environment variable not set")
def test_plt_segment(self): def test_plt_segment(self):
"""verify printing of PLT segment""" """verify printing of PLT segment"""
filename = os.path.join(DATA_ROOT, 'input/conformance/p0_07.j2k') filename = opj_data_file('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: with patch('sys.stdout', new=StringIO()) as fake_out:
@ -450,11 +444,11 @@ class TestPrinting(unittest.TestCase):
expected = '\n'.join(lines) expected = '\n'.join(lines)
self.assertEqual(actual, expected) self.assertEqual(actual, expected)
@unittest.skipIf(DATA_ROOT is None, @unittest.skipIf(OPJ_DATA_ROOT is None,
"OPJ_DATA_ROOT environment variable not set") "OPJ_DATA_ROOT environment variable not set")
def test_pod_segment(self): def test_pod_segment(self):
"""verify printing of POD segment""" """verify printing of POD segment"""
filename = os.path.join(DATA_ROOT, 'input/conformance/p0_13.j2k') filename = opj_data_file('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: with patch('sys.stdout', new=StringIO()) as fake_out:
@ -480,11 +474,11 @@ class TestPrinting(unittest.TestCase):
expected = '\n'.join(lines) expected = '\n'.join(lines)
self.assertEqual(actual, expected) self.assertEqual(actual, expected)
@unittest.skipIf(DATA_ROOT is None, @unittest.skipIf(OPJ_DATA_ROOT is None,
"OPJ_DATA_ROOT environment variable not set") "OPJ_DATA_ROOT environment variable not set")
def test_ppm_segment(self): def test_ppm_segment(self):
"""verify printing of PPM segment""" """verify printing of PPM segment"""
filename = os.path.join(DATA_ROOT, 'input/conformance/p1_03.j2k') filename = opj_data_file('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: with patch('sys.stdout', new=StringIO()) as fake_out:
@ -498,11 +492,11 @@ class TestPrinting(unittest.TestCase):
expected = '\n'.join(lines) expected = '\n'.join(lines)
self.assertEqual(actual, expected) self.assertEqual(actual, expected)
@unittest.skipIf(DATA_ROOT is None, @unittest.skipIf(OPJ_DATA_ROOT is None,
"OPJ_DATA_ROOT environment variable not set") "OPJ_DATA_ROOT environment variable not set")
def test_ppt_segment(self): def test_ppt_segment(self):
"""verify printing of ppt segment""" """verify printing of ppt segment"""
filename = os.path.join(DATA_ROOT, 'input/conformance/p1_06.j2k') filename = opj_data_file('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: with patch('sys.stdout', new=StringIO()) as fake_out:
@ -610,11 +604,11 @@ class TestPrinting(unittest.TestCase):
expected = '\n'.join(lines) expected = '\n'.join(lines)
self.assertEqual(actual, expected) self.assertEqual(actual, expected)
@unittest.skipIf(DATA_ROOT is None, @unittest.skipIf(OPJ_DATA_ROOT is None,
"OPJ_DATA_ROOT environment variable not set") "OPJ_DATA_ROOT environment variable not set")
def test_tlm_segment(self): def test_tlm_segment(self):
"""verify printing of TLM segment""" """verify printing of TLM segment"""
filename = os.path.join(DATA_ROOT, 'input/conformance/p0_15.j2k') filename = opj_data_file('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: with patch('sys.stdout', new=StringIO()) as fake_out:
@ -704,11 +698,11 @@ class TestPrinting(unittest.TestCase):
@unittest.skipIf(sys.hexversion < 0x02070000, @unittest.skipIf(sys.hexversion < 0x02070000,
"Differences in XML printing between 2.6 and 2.7") "Differences in XML printing between 2.6 and 2.7")
@unittest.skipIf(DATA_ROOT is None, @unittest.skipIf(OPJ_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):
"""verify printing of XML box""" """verify printing of XML box"""
filename = os.path.join(DATA_ROOT, 'input/conformance/file1.jp2') filename = opj_data_file('input/conformance/file1.jp2')
j = glymur.Jp2k(filename) j = glymur.Jp2k(filename)
with patch('sys.stdout', new=StringIO()) as fake_out: with patch('sys.stdout', new=StringIO()) as fake_out:
print(j.box[2]) print(j.box[2])
@ -735,11 +729,11 @@ class TestPrinting(unittest.TestCase):
expected = '\n'.join(lines) expected = '\n'.join(lines)
self.assertEqual(actual, expected) self.assertEqual(actual, expected)
@unittest.skipIf(DATA_ROOT is None, @unittest.skipIf(OPJ_DATA_ROOT is None,
"OPJ_DATA_ROOT environment variable not set") "OPJ_DATA_ROOT environment variable not set")
def test_channel_definition(self): def test_channel_definition(self):
"""verify printing of cdef box""" """verify printing of cdef box"""
filename = os.path.join(DATA_ROOT, 'input/conformance/file2.jp2') filename = opj_data_file('input/conformance/file2.jp2')
j = glymur.Jp2k(filename) j = glymur.Jp2k(filename)
with patch('sys.stdout', new=StringIO()) as fake_out: with patch('sys.stdout', new=StringIO()) as fake_out:
print(j.box[2].box[2]) print(j.box[2].box[2])
@ -751,11 +745,11 @@ class TestPrinting(unittest.TestCase):
expected = '\n'.join(lines) expected = '\n'.join(lines)
self.assertEqual(actual, expected) self.assertEqual(actual, expected)
@unittest.skipIf(DATA_ROOT is None, @unittest.skipIf(OPJ_DATA_ROOT is None,
"OPJ_DATA_ROOT environment variable not set") "OPJ_DATA_ROOT environment variable not set")
def test_component_mapping(self): def test_component_mapping(self):
"""verify printing of cmap box""" """verify printing of cmap box"""
filename = os.path.join(DATA_ROOT, 'input/conformance/file9.jp2') filename = opj_data_file('input/conformance/file9.jp2')
j = glymur.Jp2k(filename) j = glymur.Jp2k(filename)
with patch('sys.stdout', new=StringIO()) as fake_out: with patch('sys.stdout', new=StringIO()) as fake_out:
print(j.box[2].box[2]) print(j.box[2].box[2])
@ -767,11 +761,11 @@ class TestPrinting(unittest.TestCase):
expected = '\n'.join(lines) expected = '\n'.join(lines)
self.assertEqual(actual, expected) self.assertEqual(actual, expected)
@unittest.skipIf(DATA_ROOT is None, @unittest.skipIf(OPJ_DATA_ROOT is None,
"OPJ_DATA_ROOT environment variable not set") "OPJ_DATA_ROOT environment variable not set")
def test_palette7(self): def test_palette7(self):
"""verify printing of pclr box""" """verify printing of pclr box"""
filename = os.path.join(DATA_ROOT, 'input/conformance/file9.jp2') filename = opj_data_file('input/conformance/file9.jp2')
j = glymur.Jp2k(filename) j = glymur.Jp2k(filename)
with patch('sys.stdout', new=StringIO()) as fake_out: with patch('sys.stdout', new=StringIO()) as fake_out:
print(j.box[2].box[1]) print(j.box[2].box[1])
@ -781,11 +775,11 @@ class TestPrinting(unittest.TestCase):
expected = '\n'.join(lines) expected = '\n'.join(lines)
self.assertEqual(actual, expected) self.assertEqual(actual, expected)
@unittest.skipIf(DATA_ROOT is None, @unittest.skipIf(OPJ_DATA_ROOT is None,
"OPJ_DATA_ROOT environment variable not set") "OPJ_DATA_ROOT environment variable not set")
def test_rreq(self): def test_rreq(self):
"""verify printing of reader requirements box""" """verify printing of reader requirements box"""
filename = os.path.join(DATA_ROOT, 'input/conformance/file7.jp2') filename = opj_data_file('input/conformance/file7.jp2')
j = glymur.Jp2k(filename) j = glymur.Jp2k(filename)
with patch('sys.stdout', new=StringIO()) as fake_out: with patch('sys.stdout', new=StringIO()) as fake_out:
print(j.box[2]) print(j.box[2])
@ -805,11 +799,11 @@ class TestPrinting(unittest.TestCase):
expected = '\n'.join(lines) expected = '\n'.join(lines)
self.assertEqual(actual, expected) self.assertEqual(actual, expected)
@unittest.skipIf(DATA_ROOT is None, @unittest.skipIf(OPJ_DATA_ROOT is None,
"OPJ_DATA_ROOT environment variable not set") "OPJ_DATA_ROOT environment variable not set")
def test_differing_subsamples(self): def test_differing_subsamples(self):
"""verify printing of SIZ with different subsampling... Issue 86.""" """verify printing of SIZ with different subsampling... Issue 86."""
filename = os.path.join(DATA_ROOT, 'input/conformance/p0_05.j2k') filename = opj_data_file('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: with patch('sys.stdout', new=StringIO()) as fake_out:
@ -828,11 +822,11 @@ class TestPrinting(unittest.TestCase):
expected = '\n'.join(lines) expected = '\n'.join(lines)
self.assertEqual(actual, expected) self.assertEqual(actual, expected)
@unittest.skipIf(DATA_ROOT is None, @unittest.skipIf(OPJ_DATA_ROOT is None,
"OPJ_DATA_ROOT environment variable not set") "OPJ_DATA_ROOT environment variable not set")
def test_palette_box(self): def test_palette_box(self):
"""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 = opj_data_file('input/conformance/file9.jp2')
j = glymur.Jp2k(filename) j = glymur.Jp2k(filename)
with patch('sys.stdout', new=StringIO()) as fake_out: with patch('sys.stdout', new=StringIO()) as fake_out:
print(j.box[2].box[1]) print(j.box[2].box[1])
@ -921,13 +915,13 @@ class TestPrinting(unittest.TestCase):
@unittest.skipIf(sys.hexversion < 0x03000000, @unittest.skipIf(sys.hexversion < 0x03000000,
"Ordered dicts not printing well in 2.7") "Ordered dicts not printing well in 2.7")
@unittest.skipIf(DATA_ROOT is None, @unittest.skipIf(OPJ_DATA_ROOT is None,
"OPJ_DATA_ROOT environment variable not set") "OPJ_DATA_ROOT environment variable not set")
def test_jpx_approx_icc_profile(self): def test_jpx_approx_icc_profile(self):
"""verify jpx with approx field equal to zero""" """verify jpx with approx field equal to zero"""
# ICC profiles may be used in JP2, but the approximation field should # ICC profiles may be used in JP2, but the approximation field should
# be zero unless we have jpx. This file does both. # be zero unless we have jpx. This file does both.
filename = os.path.join(DATA_ROOT, 'input/nonregression/text_GBR.jp2') filename = opj_data_file('input/nonregression/text_GBR.jp2')
with warnings.catch_warnings(): with warnings.catch_warnings():
# brand is 'jp2 ', but has any icc profile. # brand is 'jp2 ', but has any icc profile.
warnings.simplefilter("ignore") warnings.simplefilter("ignore")
@ -966,11 +960,11 @@ class TestPrinting(unittest.TestCase):
expected = '\n'.join(lines) expected = '\n'.join(lines)
self.assertEqual(actual, expected) self.assertEqual(actual, expected)
@unittest.skipIf(DATA_ROOT is None, @unittest.skipIf(OPJ_DATA_ROOT is None,
"OPJ_DATA_ROOT environment variable not set") "OPJ_DATA_ROOT environment variable not set")
def test_uuid(self): def test_uuid(self):
"""verify printing of UUID box""" """verify printing of UUID box"""
filename = os.path.join(DATA_ROOT, 'input/nonregression/text_GBR.jp2') filename = opj_data_file('input/nonregression/text_GBR.jp2')
with warnings.catch_warnings(): with warnings.catch_warnings():
# brand is 'jp2 ', but has any icc profile. # brand is 'jp2 ', but has any icc profile.
warnings.simplefilter("ignore") warnings.simplefilter("ignore")

53
glymur/version.py Normal file
View file

@ -0,0 +1,53 @@
# This file is part of glymur, a Python interface for accessing JPEG 2000.
#
# http://glymur.readthedocs.org
#
# Copyright 2013 John Evans
#
# License: MIT
import sys
import numpy as np
from distutils.version import LooseVersion
from .lib import openjpeg as opj
from .lib import openjp2 as opj2
version = "0.5.0"
_sv = LooseVersion(version)
version_tuple = _sv.version
if opj.OPENJPEG is None and opj2.OPENJP2 is None:
openjpeg_version = '0.0.0'
elif opj2.OPENJP2 is None:
openjpeg_version = opj.version()
else:
openjpeg_version = opj2.version()
_sv = LooseVersion(openjpeg_version)
openjpeg_version_tuple = _sv.version
__doc__ = """\
This is glymur **{glymur_version}**
* OPENJPEG version: **{openjpeg}**
""".format(glymur_version=version,
openjpeg=openjpeg_version)
info = """\
Summary of glymur configuration
-------------------------------
glymur {glymur}
OPENJPEG {openjpeg}
Python {python}
sys.platform {platform}
sys.maxsize {maxsize}
numpy {numpy}
""".format(glymur=version,
openjpeg=openjpeg_version,
python=sys.version,
platform=sys.platform,
maxsize=sys.maxsize,
numpy=np.__version__)

View file

@ -2,7 +2,6 @@ from setuptools import setup, find_packages
import sys import sys
kwargs = {'name': 'Glymur', kwargs = {'name': 'Glymur',
'version': '0.4.1',
'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',
@ -13,8 +12,7 @@ kwargs = {'name': 'Glymur',
'package_data': {'glymur': ['data/*.jp2', 'data/*.j2k']}, 'package_data': {'glymur': ['data/*.jp2', 'data/*.j2k']},
'scripts': ['bin/jp2dump'], 'scripts': ['bin/jp2dump'],
'license': 'MIT', 'license': 'MIT',
'test_suite': 'glymur.test', 'test_suite': 'glymur.test'}
'platforms': ['darwin']}
instllrqrs = ['numpy>=1.4.1'] instllrqrs = ['numpy>=1.4.1']
if sys.hexversion < 0x03030000: if sys.hexversion < 0x03030000:
@ -39,4 +37,8 @@ clssfrs = ["Programming Language :: Python",
"Intended Audience :: Information Technology", "Intended Audience :: Information Technology",
"Topic :: Software Development :: Libraries :: Python Modules"] "Topic :: Software Development :: Libraries :: Python Modules"]
kwargs['classifiers'] = clssfrs kwargs['classifiers'] = clssfrs
import glymur
kwargs['version'] = glymur.version.version
setup(**kwargs) setup(**kwargs)