Merge branch 'release-0.5.0'
This commit is contained in:
commit
17dcd6ec18
21 changed files with 2145 additions and 2634 deletions
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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.
|
||||
|
|
|
|||
|
|
@ -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.
|
||||
|
|
|
|||
|
|
@ -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.
|
||||
|
|
|
|||
|
|
@ -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.
|
||||
|
|
|
|||
|
|
@ -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
|
||||
-------
|
||||
|
|
|
|||
|
|
@ -2,6 +2,9 @@
|
|||
"""
|
||||
import sys
|
||||
|
||||
from glymur import version
|
||||
__version__ = version.version
|
||||
|
||||
from .jp2k import Jp2k
|
||||
from .jp2dump import jp2dump
|
||||
|
||||
|
|
|
|||
173
glymur/jp2k.py
173
glymur/jp2k.py
|
|
@ -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)
|
||||
|
|
|
|||
|
|
@ -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',
|
||||
|
|
|
|||
|
|
@ -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),
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
||||
|
|
|
|||
|
|
@ -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):
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
|
|
|
|||
|
|
@ -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
|
|
@ -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)
|
||||
|
|
|
|||
|
|
@ -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')
|
||||
|
|
|
|||
|
|
@ -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
53
glymur/version.py
Normal 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__)
|
||||
8
setup.py
8
setup.py
|
|
@ -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)
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue