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
install:
- pip install . --use-mirrors
# command to run tests
script:
- "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 18, 2013 - v0.4.0 Added append method.

View file

@ -76,9 +76,9 @@ copyright = u'2013, John Evans'
# built documents.
#
# The short X.Y version.
version = '0.4'
version = '0.5'
# 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
# for a list of supported languages.

View file

@ -1,31 +1,33 @@
----------------------------------
Advanced Installation Instructions
----------------------------------
Most users won't need to read this! You've been warned...
''''''''''''''''''''''
Glymur Configuration
''''''''''''''''''''''
The default glymur installation process relies upon OpenJPEG version
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
of more of glymur's features, you should install version 2.0 or
compile OpenJPEG as a shared library (named *openjp2* instead of
*openjpeg*) from the developmental source that you can retrieve via
subversion. As of this time of writing, svn revision 2345 works.
1.X being properly installed on your system. If you have version 1.5 you can
both read and write JPEG 2000 files, but you may wish to install version 2.0
or the 2.0+ version from OpenJPEG's development trunk for better performance.
If you do that, you should compile it as a shared library (named *openjp2*
instead of *openjpeg*) from the developmental source that you can retrieve
via subversion. As of this time of writing, svn revision 2345 works.
You should also download the test data for the purpose of configuring
and running OpenJPEG's test suite, check their instructions for all
this. You should set the **OPJ_DATA_ROOT** environment variable
for the purpose of running Glymur's test suite. ::
and running OpenJPEG's test suite, check their instructions for all this.
You should set the **OPJ_DATA_ROOT** environment variable for the purpose
of running Glymur's test suite. ::
$ svn co http://openjpeg.googlecode.com/svn/data
$ export OPJ_DATA_ROOT=`pwd`/data
Glymur uses ctypes (for the moment) to access the openjp2 library, and
because ctypes access libraries in a platform-dependent manner, it is
Glymur uses ctypes to access the openjp2/openjpeg libraries,
and because ctypes accesses libraries in a platform-dependent manner, it is
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
configparser module, i.e. ::
the openjpeg or openjp2 libraries (linux users don't need to bother if you are
using OpenJPEG as provided by your package manager). The configuration
format is the same as used by Python's configparser module, i.e. ::
[library]
openjp2: /opt/openjp2-svn/lib/libopenjp2.so
@ -37,7 +39,8 @@ to the configuration file would normally be ::
$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
@ -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. ::
[library]
openjp2: /opt/openjp2-svn/lib/libopenjp2.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
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
--------
All the necessary packages are available to use glymur with Python 3.3 via
MacPorts. You should install the following set of ports:
All the necessary packages are available to use glymur with Python 2.6, 2.7,
and 3.3 via MacPorts. You should install the following set of ports:
* python33
* py33-numpy
@ -80,72 +82,38 @@ MacPorts supplies both OpenJPEG 1.5.0 and OpenJPEG 2.0.0.
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
'''''''''
Fedora 18 ships with Python 3.3 and all the necessary RPMs are available to
run the maximum number of tests.
* setuptools
* matplotlib
* pillow
* contextlib2 (python 2.6, 2.7 only)
* mock (python 2.6, 2.7 only)
* ordereddict (python 2.6 only)
* python3
* python3-numpy
* python3-setuptools
* python3-matplotlib (for running tests)
* python3-matplotlib-tk (or whichever matplotlib backend you prefer)
* python3-pillow (for running tests)
Fedora 18
'''''''''
Fedora 18 ships with Python 3.3 and the following RPMs are available to
meet the minimal set of requirements for running glymur.
* 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
Glymur's been tested on the following linux platforms without any unexpected
difficulties:
* OpenSUSE 12.3
* Fedora 17, 18, 19
* Raspian
* Travis CI (currently Ubuntu 12.04?)
* CentOS 6.4
Windows
-------
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
installed via pip. WinPython 3.3.2, however, seems to have trouble
with OpenJPEG 2.0, so I would suggest using the development version
there (I'm unwilling to spend ANY more time trying to figure out what
the problem is there).
At the moment I do not have access to a win32 machine, and
64-bit windows is completely untested.
with OpenJPEG 2.0, so I would suggest using the development version with
that configuration. I no longer have any access to a windows machine,
so I cannot currently offer much guidance here.
'''''''
@ -155,8 +123,8 @@ Testing
There are two environment variables you may wish to set before running the
tests.
* **OPJ_DATA_ROOT** - points to directory for OpenJPEG test data
* **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)
* **OPJ_DATA_ROOT** - points to directory for OpenJPEG test data (see above)
* **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
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
OpenJPEG counterparts are already failing, and others which do pass but
still produce heaps of output on stderr. Rather than let this swamp
the signal (that most of the tests are actually passing), they've been
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
than on Python 3.3. The important part is whether or not any test
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,
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,
please consult http://www.openjpeg.org.
@ -55,6 +55,5 @@ You can run the tests from within python as follows::
>>> import glymur
>>> glymur.runtests()
Many tests are currently skipped; in fact most of them are skipped if you
are relying on OpenJPEG 1.X. The important thing, though, is whether or
Many tests are currently skipped, but the The important thing is whether or
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
-------

View file

@ -2,6 +2,9 @@
"""
import sys
from glymur import version
__version__ = version.version
from .jp2k import Jp2k
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
"""
@ -21,8 +25,7 @@ import warnings
import numpy as np
from .codestream import Codestream
from .core import SRGB
from .core import GREYSCALE
from .core import SRGB, GREYSCALE
from .core import PROGRESSION_ORDER
from .core import ENUMERATED_COLORSPACE, RESTRICTED_ICC_PROFILE
from .jp2box import Jp2kBox
@ -31,6 +34,7 @@ from .jp2box import ColourSpecificationBox, ContiguousCodestreamBox
from .jp2box import ImageHeaderBox
from .lib import openjpeg as opj
from .lib import openjp2 as opj2
from . import version
from .lib import c as libc
@ -185,7 +189,10 @@ class Jp2k(Jp2kBox):
cparams : CompressionParametersType(ctypes.Structure)
Corresponds to cparameters_t type in openjp2 headers.
"""
cparams = opj2.set_default_encoder_parameters()
if version.openjpeg_version_tuple[0] == 1:
cparams = opj.set_default_encoder_parameters()
else:
cparams = opj2.set_default_encoder_parameters()
outfile = self.filename.encode()
num_pad_bytes = opj2.PATH_LEN - len(outfile)
@ -280,9 +287,6 @@ class Jp2k(Jp2kBox):
Corresponds to cparameters_t type in openjp2 headers.
colorspace : int
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:
@ -380,11 +384,87 @@ class Jp2k(Jp2kBox):
glymur.LibraryNotFoundError
If glymur is unable to load the openjp2 library.
"""
if opj2.OPENJP2 is None:
raise LibraryNotFoundError("You must have the openjp2 library "
"installed before using this "
if opj2.OPENJP2 is not None:
self._write_openjp2(img_array, verbose=verbose, **kwargs)
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.")
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)
if img_array.ndim == 2:
@ -650,41 +730,45 @@ class Jp2k(Jp2kBox):
raise IOError(msg)
with ExitStack() as stack:
# Set decoding parameters.
dparameters = opj.DecompressionParametersType()
opj.set_default_decoder_parameters(ctypes.byref(dparameters))
dparameters.cp_reduce = rlevel
dparameters.decod_format = self._codec_format
try:
# Set decoding parameters.
dparameters = opj.DecompressionParametersType()
opj.set_default_decoder_parameters(ctypes.byref(dparameters))
dparameters.cp_reduce = rlevel
dparameters.decod_format = self._codec_format
infile = self.filename.encode()
nelts = opj.PATH_LEN - len(infile)
infile += b'0' * nelts
dparameters.infile = infile
infile = self.filename.encode()
nelts = opj.PATH_LEN - len(infile)
infile += b'0' * nelts
dparameters.infile = infile
dinfo = opj.create_decompress(dparameters.decod_format)
dinfo = opj.create_decompress(dparameters.decod_format)
event_mgr = opj.EventMgrType()
info_handler = ctypes.cast(_INFO_CALLBACK, ctypes.c_void_p)
event_mgr.info_handler = info_handler if verbose else None
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.set_event_mgr(dinfo, ctypes.byref(event_mgr))
event_mgr = opj.EventMgrType()
info_handler = ctypes.cast(_INFO_CALLBACK, ctypes.c_void_p)
event_mgr.info_handler = info_handler if verbose else None
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.set_event_mgr(dinfo, ctypes.byref(event_mgr))
opj.setup_decoder(dinfo, dparameters)
opj.setup_decoder(dinfo, dparameters)
with open(self.filename, 'rb') as fptr:
src = fptr.read()
cio = opj.cio_open(dinfo, src)
with open(self.filename, 'rb') as fptr:
src = fptr.read()
cio = opj.cio_open(dinfo, src)
image = opj.decode(dinfo, cio)
image = opj.decode(dinfo, cio)
stack.callback(opj.image_destroy, image)
stack.callback(opj.destroy_decompress, dinfo)
stack.callback(opj.cio_close, cio)
stack.callback(opj.image_destroy, image)
stack.callback(opj.destroy_decompress, dinfo)
stack.callback(opj.cio_close, cio)
data = extract_image_cube(image)
data = extract_image_cube(image)
except ValueError:
opj2.check_error(0)
if data.shape[2] == 1:
# The third dimension has just a single layer. Make the image
@ -864,8 +948,8 @@ class Jp2k(Jp2kBox):
glymur.LibraryNotFoundError
If glymur is unable to load the openjp2 library.
"""
if opj2.OPENJP2 is None:
raise LibraryNotFoundError("You must have the development version "
if version.openjpeg_version_tuple[0] < 2:
raise LibraryNotFoundError("You must have at least version 2.0.0 "
"of OpenJP2 installed before using "
"this functionality.")
@ -1207,7 +1291,10 @@ def _populate_comptparms(img_array, cparams):
comp_prec = 16
numrows, numcols, num_comps = img_array.shape
comptparms = (opj2.ImageComptParmType * num_comps)()
if version.openjpeg_version_tuple[0] == 1:
comptparms = (opj.ImageComptParmType * num_comps)()
else:
comptparms = (opj2.ImageComptParmType * num_comps)()
for j in range(num_comps):
comptparms[j].dx = cparams.subsampling_dx
comptparms[j].dy = cparams.subsampling_dy
@ -1339,18 +1426,18 @@ _CMPFUNC = ctypes.CFUNCTYPE(ctypes.c_void_p, ctypes.c_char_p, ctypes.c_void_p)
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())
opj2.set_error_message(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()))
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()
msg = "OpenJPEG library warning: {0}".format(library_msg)
warnings.warn(msg)

View file

@ -685,7 +685,7 @@ def check_error(status):
raise IOError("OpenJPEG function failure.")
# 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',
'opj_encode', 'opj_end_decompress', 'opj_get_decoded_tile',
'opj_read_header', 'opj_read_tile_header', 'opj_set_decode_area',

View file

@ -6,10 +6,16 @@
import ctypes
import sys
import numpy as np
from .config import glymur_config
_, OPENJPEG = glymur_config()
PATH_LEN = 4096 # maximum allowed size for filenames
# 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
def version():
@ -52,14 +58,8 @@ class CommonStructType(ctypes.Structure):
("mj2_handle", ctypes.c_void_p)]
class DecompressionInfoType(ctypes.Structure):
"""This is for decompression contexts.
Corresponds to dinfo_t type in openjpeg headers.
"""
pass
STREAM_READ = 0x0001 # The stream was opened for reading.
STREAM_WRITE = 0x0002 # The stream was opened for writing.
class CioType(ctypes.Structure):
"""Byte input-output stream (CIO)
@ -80,6 +80,266 @@ class CioType(ctypes.Structure):
("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):
"""Decompression parameters.
@ -111,23 +371,51 @@ class DecompressionParametersType(ctypes.Structure):
_fields_.append(("flags", ctypes.c_uint))
class ImageCompType(ctypes.Structure):
"""Defines a single image component.
Corresponds to image_comp_t type in openjpeg.
class ImageComptParmType(ctypes.Structure):
"""Component parameters structure used by the opj_image_create function.
"""
_fields_ = [("dx", ctypes.c_int),
("dy", ctypes.c_int),
("w", ctypes.c_int),
("h", ctypes.c_int),
("x0", ctypes.c_int),
("y0", ctypes.c_int),
("prec", ctypes.c_int),
("bpp", ctypes.c_int),
("sgnd", ctypes.c_int),
("resno_decoded", ctypes.c_int),
("factor", ctypes.c_int),
("data", ctypes.POINTER(ctypes.c_int))]
_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),
("dy", ctypes.c_int),
("w", ctypes.c_int),
("h", ctypes.c_int),
("x0", ctypes.c_int),
("y0", ctypes.c_int),
("prec", ctypes.c_int),
("bpp", ctypes.c_int),
("sgnd", ctypes.c_int),
("resno_decoded", ctypes.c_int),
("factor", ctypes.c_int),
("data", ctypes.POINTER(ctypes.c_int))]
class ImageType(ctypes.Structure):
@ -146,16 +434,22 @@ class ImageType(ctypes.Structure):
("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."""
argtypes = [ctypes.POINTER(CommonStructType), ctypes.c_char_p,
ctypes.c_int]
OPENJPEG.opj_cio_open.argtypes = argtypes
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,
ctypes.POINTER(CommonStructType)),
src, len(src))
src,
length)
return cio
@ -166,6 +460,24 @@ def 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):
"""Wraps openjpeg library function opj_create_decompress.
"""
@ -186,6 +498,38 @@ def decode(dinfo, cio):
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):
"""Wraps openjpeg library function opj_destroy_decompress."""
argtypes = [ctypes.POINTER(DecompressionInfoType)]
@ -193,12 +537,78 @@ def 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):
"""Wraps openjpeg library function opj_image_destroy."""
OPENJPEG.opj_image_destroy.argtypes = [ctypes.POINTER(ImageType)]
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):
"""Wrapper for opj_set_default_decoder_parameters.
"""
@ -219,6 +629,15 @@ def set_event_mgr(dinfo, event_mgr, context=None):
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):
"""Wrapper for openjpeg library function opj_setup_decoder."""
argtypes = [ctypes.POINTER(DecompressionInfoType),

View file

@ -1,6 +1,7 @@
"""
Test fixtures common to more than one test point.
"""
import os
import re
import sys
import warnings
@ -9,11 +10,6 @@ import numpy as np
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
# 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 += "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:
from matplotlib.pyplot import imread

View file

@ -117,8 +117,10 @@ class TestConfig(unittest.TestCase):
"""
with patch('glymur.lib.openjp2.OPENJP2', new=None):
with patch('glymur.lib.openjpeg.OPENJPEG', new=None):
with self.assertRaises(glymur.jp2k.LibraryNotFoundError):
glymur.Jp2k(self.jp2file).read_bands()
with patch('glymur.version.openjpeg_version_tuple',
new=(0, 0, 0)):
with self.assertRaises(glymur.jp2k.LibraryNotFoundError):
glymur.Jp2k(self.jp2file).read_bands()
@unittest.skipIf(os.name == "nt", "NamedTemporaryFile issue on windows")
def test_write_without_library(self):

View file

@ -12,6 +12,7 @@ These tests deal with JPX/JP2/J2K images in the format-corpus repository.
import os
from os.path import join
import re
import sys
if sys.hexversion < 0x02070000:
@ -19,6 +20,7 @@ if sys.hexversion < 0x02070000:
else:
import unittest
import glymur
from glymur import Jp2k
try:
@ -39,6 +41,9 @@ except KeyError:
class TestSuiteFormatCorpus(unittest.TestCase):
"""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):
"""Has one byte shaved off of EOC marker."""
jfile = os.path.join(FORMAT_CORPUS_DATA_ROOT,
@ -54,6 +59,9 @@ class TestSuiteFormatCorpus(unittest.TestCase):
with self.assertRaises(OSError):
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):
"""Shortened by 5000 bytes."""
jfile = os.path.join(FORMAT_CORPUS_DATA_ROOT,

View file

@ -20,16 +20,10 @@ else:
import numpy as np
from glymur import Jp2k
try:
DATA_ROOT = os.environ['OPJ_DATA_ROOT']
except KeyError:
DATA_ROOT = None
except:
raise
from .fixtures import OPJ_DATA_ROOT, opj_data_file
@unittest.skipIf(DATA_ROOT is None,
@unittest.skipIf(OPJ_DATA_ROOT is None,
"OPJ_DATA_ROOT environment variable not set")
class TestICC(unittest.TestCase):
"""ICC profile tests"""
@ -42,7 +36,7 @@ class TestICC(unittest.TestCase):
def test_file5(self):
"""basic ICC profile"""
filename = os.path.join(DATA_ROOT, 'input/conformance/file5.jp2')
filename = opj_data_file('input/conformance/file5.jp2')
j = Jp2k(filename)
profile = j.box[3].box[1].icc_profile
self.assertEqual(profile['Size'], 546)
@ -75,8 +69,7 @@ class TestICC(unittest.TestCase):
"Uses features introduced in 3.2.")
def test_invalid_profile_header(self):
"""invalid ICC header data should cause UserWarning"""
jfile = os.path.join(DATA_ROOT,
'input/nonregression/orb-blue10-lin-jp2.jp2')
jfile = opj_data_file('input/nonregression/orb-blue10-lin-jp2.jp2')
# assertWarns in Python 3.3 (python2.7/pylint issue)
# 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
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
import glymur
try:
DATA_ROOT = os.environ['OPJ_DATA_ROOT']
except KeyError:
DATA_ROOT = None
except:
raise
@unittest.skipIf(glymur.lib.openjp2.OPENJP2 is None,
"Missing openjp2 library.")
@unittest.skipIf(NO_READ_BACKEND, NO_READ_BACKEND_MSG)
@unittest.skipIf(DATA_ROOT is None,
"OPJ_DATA_ROOT environment variable not set")
@unittest.skipIf(OPJ_DATA_ROOT is None,
"OPJ_OPJ_DATA_ROOT environment variable not set")
class TestSuiteNegative(unittest.TestCase):
"""Test suite for certain negative tests from openjpeg suite."""
@ -54,7 +48,7 @@ class TestSuiteNegative(unittest.TestCase):
def test_psnr_with_cratios(self):
"""Using psnr with cratios options is not allowed."""
# 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)
with tempfile.NamedTemporaryFile(suffix='.j2k') as tfile:
j = Jp2k(tfile.name, 'wb')
@ -64,7 +58,7 @@ class TestSuiteNegative(unittest.TestCase):
def test_nr_marker_not_compliant(self):
"""non-compliant marker, should still be able to read"""
relpath = 'input/nonregression/MarkerIsNotCompliant.j2k'
jfile = os.path.join(DATA_ROOT, relpath)
jfile = opj_data_file(relpath)
jp2k = Jp2k(jfile)
jp2k.get_codestream(header_only=False)
self.assertTrue(True)
@ -74,7 +68,7 @@ class TestSuiteNegative(unittest.TestCase):
def test_nr_illegalclrtransform(self):
"""EOC marker is bad"""
relpath = 'input/nonregression/illegalcolortransform.j2k'
jfile = os.path.join(DATA_ROOT, relpath)
jfile = opj_data_file(relpath)
jp2k = Jp2k(jfile)
with self.assertWarns(UserWarning):
codestream = jp2k.get_codestream(header_only=False)
@ -87,7 +81,7 @@ class TestSuiteNegative(unittest.TestCase):
def test_nr_cannotreadwnosizeknown(self):
"""not sure exactly what is wrong with this file"""
relpath = 'input/nonregression/Cannotreaddatawithnosizeknown.j2k'
jfile = os.path.join(DATA_ROOT, relpath)
jfile = opj_data_file(relpath)
jp2k = Jp2k(jfile)
jp2k.get_codestream(header_only=False)
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
# This file has a palette (pclr) box whose length is impossibly
# short.
infile = os.path.join(DATA_ROOT,
infile = os.path.join(OPJ_DATA_ROOT,
'input/nonregression/mem-b2ace68c-1381.jp2')
with self.assertWarns(UserWarning):
Jp2k(infile)

View file

@ -10,6 +10,7 @@ suite.
# pylint: disable=F0401
import os
import re
import sys
import tempfile
@ -19,23 +20,18 @@ else:
import unittest
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
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(glymur.lib.openjp2.OPENJP2 is None,
"Missing openjp2 library.")
@unittest.skipIf(re.match(r"""1\.[01234]\.\d""",
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(data_root is None,
@unittest.skipIf(OPJ_DATA_ROOT is None,
"OPJ_DATA_ROOT environment variable not set")
class TestSuiteWrite(unittest.TestCase):
"""Tests for writing with openjp2 backend.
@ -51,7 +47,7 @@ class TestSuiteWrite(unittest.TestCase):
def test_NR_ENC_Bretagne1_ppm_1_encode(self):
"""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)
with tempfile.NamedTemporaryFile(suffix='.j2k') as tfile:
j = Jp2k(tfile.name, 'wb')
@ -115,7 +111,7 @@ class TestSuiteWrite(unittest.TestCase):
def test_NR_ENC_Bretagne1_ppm_2_encode(self):
"""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)
with tempfile.NamedTemporaryFile(suffix='.j2k') as tfile:
j = Jp2k(tfile.name, 'wb')
@ -180,7 +176,7 @@ class TestSuiteWrite(unittest.TestCase):
def test_NR_ENC_Bretagne1_ppm_3_encode(self):
"""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)
with tempfile.NamedTemporaryFile(suffix='.j2k') as tfile:
j = Jp2k(tfile.name, 'wb')
@ -247,7 +243,7 @@ class TestSuiteWrite(unittest.TestCase):
def test_NR_ENC_Bretagne2_ppm_4_encode(self):
"""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)
with tempfile.NamedTemporaryFile(suffix='.j2k') as tfile:
j = Jp2k(tfile.name, 'wb')
@ -316,7 +312,7 @@ class TestSuiteWrite(unittest.TestCase):
def test_NR_ENC_Bretagne2_ppm_5_encode(self):
"""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)
with tempfile.NamedTemporaryFile(suffix='.j2k') as tfile:
j = Jp2k(tfile.name, 'wb')
@ -379,7 +375,7 @@ class TestSuiteWrite(unittest.TestCase):
def test_NR_ENC_Bretagne2_ppm_6_encode(self):
"""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)
with tempfile.NamedTemporaryFile(suffix='.j2k') as tfile:
j = Jp2k(tfile.name, 'wb')
@ -447,7 +443,7 @@ class TestSuiteWrite(unittest.TestCase):
def test_NR_ENC_Bretagne2_ppm_7_encode(self):
"""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)
with tempfile.NamedTemporaryFile(suffix='.j2k') as tfile:
j = Jp2k(tfile.name, 'wb')
@ -514,7 +510,7 @@ class TestSuiteWrite(unittest.TestCase):
def test_NR_ENC_Bretagne2_ppm_8_encode(self):
"""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)
with tempfile.NamedTemporaryFile(suffix='.j2k') as tfile:
j = Jp2k(tfile.name, 'wb')
@ -578,7 +574,7 @@ class TestSuiteWrite(unittest.TestCase):
def test_NR_ENC_Cevennes1_bmp_9_encode(self):
"""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)
with tempfile.NamedTemporaryFile(suffix='.j2k') as tfile:
j = Jp2k(tfile.name, 'wb')
@ -641,7 +637,7 @@ class TestSuiteWrite(unittest.TestCase):
def test_NR_ENC_Cevennes2_ppm_10_encode(self):
"""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)
with tempfile.NamedTemporaryFile(suffix='.j2k') as tfile:
j = Jp2k(tfile.name, 'wb')
@ -704,8 +700,7 @@ class TestSuiteWrite(unittest.TestCase):
def test_NR_ENC_Rome_bmp_11_encode(self):
"""NR-ENC-Rome.bmp-11-encode"""
data = read_image(os.path.join(data_root,
'input/nonregression/Rome.bmp'))
data = read_image(opj_data_file('input/nonregression/Rome.bmp'))
with tempfile.NamedTemporaryFile(suffix='.jp2') as tfile:
jp2 = Jp2k(tfile.name, 'wb')
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"""
# 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.
infile = os.path.join(data_root,
'input/nonregression/random-issue-0005.tif')
infile = opj_data_file('input/nonregression/random-issue-0005.tif')
data = read_image(infile)
with tempfile.NamedTemporaryFile(suffix='.j2k') as tfile:
j = Jp2k(tfile.name, 'wb')

View file

@ -32,13 +32,7 @@ else:
import glymur
from glymur import Jp2k
try:
DATA_ROOT = os.environ['OPJ_DATA_ROOT']
except KeyError:
DATA_ROOT = None
except:
raise
from .fixtures import OPJ_DATA_ROOT, opj_data_file
@unittest.skipIf(os.name == "nt", "Temporary file issue on window.")
@ -287,11 +281,11 @@ class TestPrinting(unittest.TestCase):
expected = '\n'.join(lines)
self.assertEqual(actual, expected)
@unittest.skipIf(DATA_ROOT is None,
@unittest.skipIf(OPJ_DATA_ROOT is None,
"OPJ_DATA_ROOT environment variable not set")
def test_icc_profile(self):
"""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():
# brand is 'jp2 ', but has any icc profile.
warnings.simplefilter("ignore")
@ -356,11 +350,11 @@ class TestPrinting(unittest.TestCase):
expected = '\n'.join(lines)
self.assertEqual(actual, expected)
@unittest.skipIf(DATA_ROOT is None,
@unittest.skipIf(OPJ_DATA_ROOT is None,
"OPJ_DATA_ROOT environment variable not set")
def test_crg(self):
"""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)
codestream = j.get_codestream()
with patch('sys.stdout', new=StringIO()) as fake_out:
@ -371,11 +365,11 @@ class TestPrinting(unittest.TestCase):
expected = '\n'.join(lines)
self.assertEqual(actual, expected)
@unittest.skipIf(DATA_ROOT is None,
@unittest.skipIf(OPJ_DATA_ROOT is None,
"OPJ_DATA_ROOT environment variable not set")
def test_rgn(self):
"""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)
codestream = j.get_codestream(header_only=False)
with patch('sys.stdout', new=StringIO()) as fake_out:
@ -388,11 +382,11 @@ class TestPrinting(unittest.TestCase):
expected = '\n'.join(lines)
self.assertEqual(actual, expected)
@unittest.skipIf(DATA_ROOT is None,
@unittest.skipIf(OPJ_DATA_ROOT is None,
"OPJ_DATA_ROOT environment variable not set")
def test_sop(self):
"""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)
codestream = j.get_codestream(header_only=False)
with patch('sys.stdout', new=StringIO()) as fake_out:
@ -403,11 +397,11 @@ class TestPrinting(unittest.TestCase):
expected = '\n'.join(lines)
self.assertEqual(actual, expected)
@unittest.skipIf(DATA_ROOT is None,
@unittest.skipIf(OPJ_DATA_ROOT is None,
"OPJ_DATA_ROOT environment variable not set")
def test_cme(self):
"""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)
codestream = j.get_codestream()
# 2nd to last segment in the main header
@ -431,11 +425,11 @@ class TestPrinting(unittest.TestCase):
expected = '\n'.join(lines)
self.assertEqual(actual, expected)
@unittest.skipIf(DATA_ROOT is None,
@unittest.skipIf(OPJ_DATA_ROOT is None,
"OPJ_DATA_ROOT environment variable not set")
def test_plt_segment(self):
"""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)
codestream = j.get_codestream(header_only=False)
with patch('sys.stdout', new=StringIO()) as fake_out:
@ -450,11 +444,11 @@ class TestPrinting(unittest.TestCase):
expected = '\n'.join(lines)
self.assertEqual(actual, expected)
@unittest.skipIf(DATA_ROOT is None,
@unittest.skipIf(OPJ_DATA_ROOT is None,
"OPJ_DATA_ROOT environment variable not set")
def test_pod_segment(self):
"""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)
codestream = j.get_codestream()
with patch('sys.stdout', new=StringIO()) as fake_out:
@ -480,11 +474,11 @@ class TestPrinting(unittest.TestCase):
expected = '\n'.join(lines)
self.assertEqual(actual, expected)
@unittest.skipIf(DATA_ROOT is None,
@unittest.skipIf(OPJ_DATA_ROOT is None,
"OPJ_DATA_ROOT environment variable not set")
def test_ppm_segment(self):
"""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)
codestream = j.get_codestream()
with patch('sys.stdout', new=StringIO()) as fake_out:
@ -498,11 +492,11 @@ class TestPrinting(unittest.TestCase):
expected = '\n'.join(lines)
self.assertEqual(actual, expected)
@unittest.skipIf(DATA_ROOT is None,
@unittest.skipIf(OPJ_DATA_ROOT is None,
"OPJ_DATA_ROOT environment variable not set")
def test_ppt_segment(self):
"""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)
codestream = j.get_codestream(header_only=False)
with patch('sys.stdout', new=StringIO()) as fake_out:
@ -610,11 +604,11 @@ class TestPrinting(unittest.TestCase):
expected = '\n'.join(lines)
self.assertEqual(actual, expected)
@unittest.skipIf(DATA_ROOT is None,
@unittest.skipIf(OPJ_DATA_ROOT is None,
"OPJ_DATA_ROOT environment variable not set")
def test_tlm_segment(self):
"""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)
codestream = j.get_codestream()
with patch('sys.stdout', new=StringIO()) as fake_out:
@ -704,11 +698,11 @@ class TestPrinting(unittest.TestCase):
@unittest.skipIf(sys.hexversion < 0x02070000,
"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")
def test_xml(self):
"""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)
with patch('sys.stdout', new=StringIO()) as fake_out:
print(j.box[2])
@ -735,11 +729,11 @@ class TestPrinting(unittest.TestCase):
expected = '\n'.join(lines)
self.assertEqual(actual, expected)
@unittest.skipIf(DATA_ROOT is None,
@unittest.skipIf(OPJ_DATA_ROOT is None,
"OPJ_DATA_ROOT environment variable not set")
def test_channel_definition(self):
"""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)
with patch('sys.stdout', new=StringIO()) as fake_out:
print(j.box[2].box[2])
@ -751,11 +745,11 @@ class TestPrinting(unittest.TestCase):
expected = '\n'.join(lines)
self.assertEqual(actual, expected)
@unittest.skipIf(DATA_ROOT is None,
@unittest.skipIf(OPJ_DATA_ROOT is None,
"OPJ_DATA_ROOT environment variable not set")
def test_component_mapping(self):
"""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)
with patch('sys.stdout', new=StringIO()) as fake_out:
print(j.box[2].box[2])
@ -767,11 +761,11 @@ class TestPrinting(unittest.TestCase):
expected = '\n'.join(lines)
self.assertEqual(actual, expected)
@unittest.skipIf(DATA_ROOT is None,
@unittest.skipIf(OPJ_DATA_ROOT is None,
"OPJ_DATA_ROOT environment variable not set")
def test_palette7(self):
"""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)
with patch('sys.stdout', new=StringIO()) as fake_out:
print(j.box[2].box[1])
@ -781,11 +775,11 @@ class TestPrinting(unittest.TestCase):
expected = '\n'.join(lines)
self.assertEqual(actual, expected)
@unittest.skipIf(DATA_ROOT is None,
@unittest.skipIf(OPJ_DATA_ROOT is None,
"OPJ_DATA_ROOT environment variable not set")
def test_rreq(self):
"""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)
with patch('sys.stdout', new=StringIO()) as fake_out:
print(j.box[2])
@ -805,11 +799,11 @@ class TestPrinting(unittest.TestCase):
expected = '\n'.join(lines)
self.assertEqual(actual, expected)
@unittest.skipIf(DATA_ROOT is None,
@unittest.skipIf(OPJ_DATA_ROOT is None,
"OPJ_DATA_ROOT environment variable not set")
def test_differing_subsamples(self):
"""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)
codestream = j.get_codestream()
with patch('sys.stdout', new=StringIO()) as fake_out:
@ -828,11 +822,11 @@ class TestPrinting(unittest.TestCase):
expected = '\n'.join(lines)
self.assertEqual(actual, expected)
@unittest.skipIf(DATA_ROOT is None,
@unittest.skipIf(OPJ_DATA_ROOT is None,
"OPJ_DATA_ROOT environment variable not set")
def test_palette_box(self):
"""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)
with patch('sys.stdout', new=StringIO()) as fake_out:
print(j.box[2].box[1])
@ -921,13 +915,13 @@ class TestPrinting(unittest.TestCase):
@unittest.skipIf(sys.hexversion < 0x03000000,
"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")
def test_jpx_approx_icc_profile(self):
"""verify jpx with approx field equal to zero"""
# ICC profiles may be used in JP2, but the approximation field should
# 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():
# brand is 'jp2 ', but has any icc profile.
warnings.simplefilter("ignore")
@ -966,11 +960,11 @@ class TestPrinting(unittest.TestCase):
expected = '\n'.join(lines)
self.assertEqual(actual, expected)
@unittest.skipIf(DATA_ROOT is None,
@unittest.skipIf(OPJ_DATA_ROOT is None,
"OPJ_DATA_ROOT environment variable not set")
def test_uuid(self):
"""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():
# brand is 'jp2 ', but has any icc profile.
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
kwargs = {'name': 'Glymur',
'version': '0.4.1',
'description': 'Tools for accessing JPEG2000 files',
'long_description': open('README.md').read(),
'author': 'John Evans',
@ -13,8 +12,7 @@ kwargs = {'name': 'Glymur',
'package_data': {'glymur': ['data/*.jp2', 'data/*.j2k']},
'scripts': ['bin/jp2dump'],
'license': 'MIT',
'test_suite': 'glymur.test',
'platforms': ['darwin']}
'test_suite': 'glymur.test'}
instllrqrs = ['numpy>=1.4.1']
if sys.hexversion < 0x03030000:
@ -39,4 +37,8 @@ clssfrs = ["Programming Language :: Python",
"Intended Audience :: Information Technology",
"Topic :: Software Development :: Libraries :: Python Modules"]
kwargs['classifiers'] = clssfrs
import glymur
kwargs['version'] = glymur.version.version
setup(**kwargs)