Merge branch 'issue67' into devel
This commit is contained in:
commit
162e6372c9
20 changed files with 1461 additions and 244 deletions
|
|
@ -1,3 +1,4 @@
|
||||||
include *.txt *.md
|
include *.txt *.md
|
||||||
prune build
|
prune build
|
||||||
exclude readthedocs-pip-requirements.txt
|
exclude readthedocs-pip-requirements.txt
|
||||||
|
exclude release.txt
|
||||||
|
|
|
||||||
|
|
@ -1,16 +1,54 @@
|
||||||
-----------------------------------------------------
|
----------------------------------
|
||||||
Detailed Instructions for Package Management, Testing
|
Detailed Installation Instructions
|
||||||
-----------------------------------------------------
|
----------------------------------
|
||||||
|
|
||||||
You only need to read this page if you want detailed
|
''''''''''''''''''''''
|
||||||
|
Glymur Configuration
|
||||||
|
''''''''''''''''''''''
|
||||||
|
|
||||||
|
The default glymur installation process relies upon OpenJPEG version
|
||||||
|
1.5.1 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 compile OpenJPEG as
|
||||||
|
a shared library 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. ::
|
||||||
|
|
||||||
|
$ 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
|
||||||
|
recommended that you create a configuration file to help Glymur properly find
|
||||||
|
the openjp2 library. You may create the configuration file as follows::
|
||||||
|
|
||||||
|
$ mkdir -p ~/.config/glymur
|
||||||
|
$ cd ~/.config/glymur
|
||||||
|
$ cat > glymurrc << EOF
|
||||||
|
> [library]
|
||||||
|
> openjp2: /opt/openjp2-svn/lib/libopenjp2.so
|
||||||
|
> EOF
|
||||||
|
|
||||||
|
That assumes, of course, that you've installed OpenJPEG into
|
||||||
|
/opt/openjp2-svn on a linux system. You may also substitute
|
||||||
|
**$XDG_CONFIG_HOME** for **$HOME/.config**.
|
||||||
|
|
||||||
|
Again, though, the configuration file is not required if you only wish to
|
||||||
|
read JPEG 2000 files using OpenJPEG version 1.5.1.
|
||||||
|
|
||||||
|
|
||||||
|
'''''''''''''''''''''''''''''''''''''''''''
|
||||||
|
Package Management Suggestions for Testing
|
||||||
|
'''''''''''''''''''''''''''''''''''''''''''
|
||||||
|
|
||||||
|
You only need to read this section if you want detailed
|
||||||
platform-specific instructions on running as many tests as possible or wish to
|
platform-specific instructions on running as many tests as possible or wish to
|
||||||
use your system's package manager to install as many required
|
use your system's package manager to install as many required
|
||||||
packages/RPMs/ports/whatever without going through pip. Otherwise go on to
|
packages/RPMs/ports/whatever without going through pip.
|
||||||
the next page.
|
|
||||||
|
|
||||||
''''''''
|
|
||||||
Platform
|
|
||||||
''''''''
|
|
||||||
|
|
||||||
Mac OS X
|
Mac OS X
|
||||||
--------
|
--------
|
||||||
|
|
@ -58,8 +96,9 @@ repositories::
|
||||||
|
|
||||||
Raspbian
|
Raspbian
|
||||||
''''''''
|
''''''''
|
||||||
Yeah, this was the first thing I tried after getting my new Raspberry Pi hooked
|
Yeah, this was the first thing I tried after getting my new Raspberry
|
||||||
up (couldn't help myself :-) Raspbian ships with Python 3.2 and 2.7, so these steps detail working with 2.7.
|
Pi hooked up (couldn't help myself :-) Raspbian ships with Python
|
||||||
|
3.2 and 2.7, so these steps detail working with 2.7.
|
||||||
|
|
||||||
Additional required OS packages include::
|
Additional required OS packages include::
|
||||||
|
|
||||||
|
|
@ -79,8 +118,8 @@ one unexpected failure as of the time of writing.
|
||||||
|
|
||||||
Fedora 17
|
Fedora 17
|
||||||
'''''''''
|
'''''''''
|
||||||
Fedora 17 ships with Python 3.2 and 2.7, so these steps detail working with
|
Fedora 17 ships with Python 3.2 and 2.7, but OpenJPEG is only at version 1.4,
|
||||||
2.7.
|
so these steps detail working with Python 2.7 and the svn version of OpenJPEG.
|
||||||
|
|
||||||
Required RPMs include::
|
Required RPMs include::
|
||||||
|
|
||||||
|
|
@ -111,7 +150,10 @@ it was installable via pip::
|
||||||
|
|
||||||
Windows
|
Windows
|
||||||
-------
|
-------
|
||||||
Not currently supported.
|
The only configuration I've tested is Python(xy), which uses Python 2.7.
|
||||||
|
Python(xy) already comes with numpy, but you will have to install pip and then
|
||||||
|
contextlib2 as well. This configuration assumes you've installed OpenJPEG
|
||||||
|
1.5.1.
|
||||||
|
|
||||||
'''''''
|
'''''''
|
||||||
Testing
|
Testing
|
||||||
|
|
|
||||||
|
|
@ -2,14 +2,9 @@
|
||||||
Glymur: a Python interface for JPEG 2000
|
Glymur: a Python interface for JPEG 2000
|
||||||
----------------------------------------
|
----------------------------------------
|
||||||
|
|
||||||
**Glymur** contains a Python interface to the OpenJPEG library
|
**Glymur** is an interface to the OpenJPEG library
|
||||||
which allows linux and mac users to read and write JPEG 2000 files. For more
|
which allows one to read and write JPEG 2000 files from within Python.
|
||||||
information about OpenJPEG, please consult http://www.openjpeg.org. Glymur
|
Glymur supports both reading and writing of JPEG 2000 images. Writing
|
||||||
currently relies upon a development version of the OpenJPEG library, and so,
|
|
||||||
while useable, it is totally at the mercy of any upstream changes
|
|
||||||
made to the development version of OpenJPEG.
|
|
||||||
|
|
||||||
Glymur supports both reading and writing of JPEG 2000 images (part 1). Writing
|
|
||||||
JPEG 2000 images is currently limited to images that can fit in memory,
|
JPEG 2000 images is currently limited to images that can fit in memory,
|
||||||
however.
|
however.
|
||||||
|
|
||||||
|
|
@ -23,34 +18,18 @@ Glymur works on Python 2.7 and 3.3. Python 3.3 is strongly recommended.
|
||||||
|
|
||||||
OpenJPEG Installation
|
OpenJPEG Installation
|
||||||
=====================
|
=====================
|
||||||
OpenJPEG must be built as a shared library. In addition, you
|
The OpenJPEG library version must be either 1.5.1 or the trunk/development
|
||||||
currently must compile OpenJPEG from the developmental source that
|
version of OpenJPEG. Version 2.0.0 or versions earlier than 1.5.0
|
||||||
you can retrieve via subversion. As of this time of writing, svn
|
are not supported. Furthermore, the 1.5.x version of OpenJPEG is
|
||||||
revision 2345 works. You should download the test data for the purpose
|
currently only utilized for read-only purposes. For more information
|
||||||
of configuring and running OpenJPEG's test suite, check their instructions for
|
about OpenJPEG, please consult http://www.openjpeg.org.
|
||||||
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
|
If you use MacPorts on the mac or if you have a sufficiently recent version of
|
||||||
$ export OPJ_DATA_ROOT=`pwd`/data
|
Linux, your package manager should already provide you with at least version
|
||||||
|
1.5.1 of OpenJPEG, which means that glymur can be installed ready to read JPEG
|
||||||
Earlier versions of OpenJPEG through the 2.0 official release will **NOT**
|
2000 images. If you use windows, I suggest using the 1.5.1 windows installer provided
|
||||||
work and are not supported.
|
to you by the OpenJPEG folks at
|
||||||
|
https://code.google.com/p/openjpeg/downloads/list .
|
||||||
Glymur uses ctypes (for the moment) to access the openjp2 library, and
|
|
||||||
because ctypes access libraries in a platform-dependent manner, it is
|
|
||||||
recommended that you create a configuration file to help Glymur properly find
|
|
||||||
the openjp2 library. You may create the configuration file as follows::
|
|
||||||
|
|
||||||
$ mkdir -p ~/.config/glymur
|
|
||||||
$ cd ~/.config/glymur
|
|
||||||
$ cat > glymurrc << EOF
|
|
||||||
> [library]
|
|
||||||
> openjp2: /opt/openjp2-svn/lib/libopenjp2.so
|
|
||||||
> EOF
|
|
||||||
|
|
||||||
That assumes, of course, that you've installed OpenJPEG into /opt/openjp2-svn.
|
|
||||||
You may also substitute **$XDG_CONFIG_HOME** for **$HOME/.config**.
|
|
||||||
|
|
||||||
Glymur Installation
|
Glymur Installation
|
||||||
===================
|
===================
|
||||||
|
|
@ -76,5 +55,6 @@ You can run the tests from within python as follows::
|
||||||
>>> import glymur
|
>>> import glymur
|
||||||
>>> glymur.runtests()
|
>>> glymur.runtests()
|
||||||
|
|
||||||
Many tests are currently skipped; the important thing is whether or not any
|
Many tests are currently skipped; in fact most of them are skipped if you
|
||||||
|
are relying on OpenJPEG 1.5.1. But the important thing is whether or not any
|
||||||
tests fail.
|
tests fail.
|
||||||
|
|
|
||||||
|
|
@ -186,4 +186,3 @@ _reader_requirements_display = {
|
||||||
+ 'requirements in M.9.2.3',
|
+ 'requirements in M.9.2.3',
|
||||||
73: 'YPbPr(1125/60) enumerated colourspace',
|
73: 'YPbPr(1125/60) enumerated colourspace',
|
||||||
74: 'YPbPr(1250/50) enumerated colourspace'}
|
74: 'YPbPr(1250/50) enumerated colourspace'}
|
||||||
|
|
||||||
|
|
|
||||||
Binary file not shown.
180
glymur/jp2k.py
180
glymur/jp2k.py
|
|
@ -18,6 +18,7 @@ import numpy as np
|
||||||
from .codestream import Codestream
|
from .codestream import Codestream
|
||||||
from .core import *
|
from .core import *
|
||||||
from .jp2box import *
|
from .jp2box import *
|
||||||
|
from .lib import openjpeg as opj
|
||||||
from .lib import openjp2 as opj2
|
from .lib import openjp2 as opj2
|
||||||
|
|
||||||
_cspace_map = {'rgb': opj2._CLRSPC_SRGB,
|
_cspace_map = {'rgb': opj2._CLRSPC_SRGB,
|
||||||
|
|
@ -202,7 +203,7 @@ class Jp2k(Jp2kBox):
|
||||||
>>> import glymur
|
>>> import glymur
|
||||||
>>> jfile = glymur.data.nemo()
|
>>> jfile = glymur.data.nemo()
|
||||||
>>> jp2 = glymur.Jp2k(jfile)
|
>>> jp2 = glymur.Jp2k(jfile)
|
||||||
>>> data = jp2.read(reduce=3)
|
>>> data = jp2.read(reduce=1)
|
||||||
>>> from tempfile import NamedTemporaryFile
|
>>> from tempfile import NamedTemporaryFile
|
||||||
>>> tfile = NamedTemporaryFile(suffix='.jp2', delete=False)
|
>>> tfile = NamedTemporaryFile(suffix='.jp2', delete=False)
|
||||||
>>> j = Jp2k(tfile.name, mode='wb')
|
>>> j = Jp2k(tfile.name, mode='wb')
|
||||||
|
|
@ -544,16 +545,17 @@ class Jp2k(Jp2kBox):
|
||||||
jp2 = Jp2k(filename)
|
jp2 = Jp2k(filename)
|
||||||
return jp2
|
return jp2
|
||||||
|
|
||||||
def read(self, reduce=0, layer=0, area=None, tile=None, verbose=False):
|
def read(self, **kwargs):
|
||||||
"""Read a JPEG 2000 image.
|
"""Read a JPEG 2000 image.
|
||||||
|
|
||||||
Parameters
|
Parameters
|
||||||
----------
|
----------
|
||||||
layer : int, optional
|
|
||||||
Number of quality layer to decode.
|
|
||||||
reduce : int, optional
|
reduce : int, optional
|
||||||
Factor by which to reduce output resolution. Use -1 to get the
|
Factor by which to reduce output resolution. Use -1 to get the
|
||||||
lowest resolution thumbnail.
|
lowest resolution thumbnail. This is the only keyword option
|
||||||
|
available to use when only OpenJPEG version 1.5.1 is present.
|
||||||
|
layer : int, optional
|
||||||
|
Number of quality layer to decode.
|
||||||
area : tuple, optional
|
area : tuple, optional
|
||||||
Specifies decoding image area,
|
Specifies decoding image area,
|
||||||
(first_row, first_col, last_row, last_col)
|
(first_row, first_col, last_row, last_col)
|
||||||
|
|
@ -585,7 +587,156 @@ class Jp2k(Jp2kBox):
|
||||||
|
|
||||||
>>> thumbnail = jp.read(reduce=-1)
|
>>> thumbnail = jp.read(reduce=-1)
|
||||||
>>> thumbnail.shape
|
>>> thumbnail.shape
|
||||||
(46, 81, 3)
|
(728, 1296, 3)
|
||||||
|
"""
|
||||||
|
if opj2._OPENJP2 is not None:
|
||||||
|
img = self._read_openjp2(**kwargs)
|
||||||
|
else:
|
||||||
|
img = self._read_openjpeg(**kwargs)
|
||||||
|
return img
|
||||||
|
|
||||||
|
def _read_openjpeg(self, reduce=0, verbose=False):
|
||||||
|
"""Read a JPEG 2000 image using libopenjpeg.
|
||||||
|
|
||||||
|
Parameters
|
||||||
|
----------
|
||||||
|
reduce : int, optional
|
||||||
|
Factor by which to reduce output resolution. Use -1 to get the
|
||||||
|
lowest resolution thumbnail.
|
||||||
|
verbose : bool, optional
|
||||||
|
Print informational messages produced by the OpenJPEG library.
|
||||||
|
|
||||||
|
Returns
|
||||||
|
-------
|
||||||
|
img_array : ndarray
|
||||||
|
The image data.
|
||||||
|
|
||||||
|
Raises
|
||||||
|
------
|
||||||
|
RuntimeError
|
||||||
|
If the image has differing subsample factors.
|
||||||
|
"""
|
||||||
|
# Check for differing subsample factors.
|
||||||
|
codestream = self.get_codestream(header_only=True)
|
||||||
|
dxs = np.array(codestream.segment[1].XRsiz)
|
||||||
|
dys = np.array(codestream.segment[1].YRsiz)
|
||||||
|
if np.any(dxs - dxs[0]) or np.any(dys - dys[0]):
|
||||||
|
msg = "Components must all have the same subsampling factors "
|
||||||
|
msg += "to use this method with OpenJPEG 1.5.1. Please consider "
|
||||||
|
msg += "using OPENJP2 instead."
|
||||||
|
raise RuntimeError(msg)
|
||||||
|
|
||||||
|
|
||||||
|
with ExitStack() as stack:
|
||||||
|
# Set decoding parameters.
|
||||||
|
dparameters = opj.dparameters_t()
|
||||||
|
opj._set_default_decoder_parameters(ctypes.byref(dparameters))
|
||||||
|
dparameters.cp_reduce = reduce
|
||||||
|
dparameters.decod_format = self._codec_format
|
||||||
|
|
||||||
|
infile = self.filename.encode()
|
||||||
|
nelts = opj._PATH_LEN - len(infile)
|
||||||
|
infile += b'0' * nelts
|
||||||
|
dparameters.infile = infile
|
||||||
|
|
||||||
|
dinfo = opj._create_decompress(dparameters.decod_format)
|
||||||
|
|
||||||
|
event_mgr = opj.event_mgr_t()
|
||||||
|
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)
|
||||||
|
|
||||||
|
with open(self.filename, 'rb') as fp:
|
||||||
|
src = fp.read()
|
||||||
|
cio = opj._cio_open(dinfo, src)
|
||||||
|
|
||||||
|
image = opj._decode(dinfo, cio)
|
||||||
|
|
||||||
|
stack.callback(opj._image_destroy, image)
|
||||||
|
stack.callback(opj._destroy_decompress, dinfo)
|
||||||
|
stack.callback(opj._cio_close, cio)
|
||||||
|
|
||||||
|
ncomps = image.contents.numcomps
|
||||||
|
component = image.contents.comps[0]
|
||||||
|
if component.sgnd:
|
||||||
|
if component.prec <= 8:
|
||||||
|
dtype = np.int8
|
||||||
|
elif component.prec <= 16:
|
||||||
|
dtype = np.int16
|
||||||
|
else:
|
||||||
|
raise RuntimeError("Unhandled precision, datatype")
|
||||||
|
else:
|
||||||
|
if component.prec <= 8:
|
||||||
|
dtype = np.uint8
|
||||||
|
elif component.prec <= 16:
|
||||||
|
dtype = np.uint16
|
||||||
|
else:
|
||||||
|
raise RuntimeError("Unhandled precision, datatype")
|
||||||
|
|
||||||
|
nrows = image.contents.comps[0].h
|
||||||
|
ncols = image.contents.comps[0].w
|
||||||
|
ncomps = image.contents.numcomps
|
||||||
|
data = np.zeros((nrows, ncols, ncomps), dtype)
|
||||||
|
|
||||||
|
for k in range(image.contents.numcomps):
|
||||||
|
component = image.contents.comps[k]
|
||||||
|
nrows = component.h
|
||||||
|
ncols = component.w
|
||||||
|
|
||||||
|
if nrows == 0 or ncols == 0:
|
||||||
|
# Letting this situation continue would segfault
|
||||||
|
# Python.
|
||||||
|
msg = "Component {0} has dimensions {1} x {2}"
|
||||||
|
msg = msg.format(k, nrows, ncols)
|
||||||
|
raise IOError(msg)
|
||||||
|
|
||||||
|
addr = ctypes.addressof(component.data.contents)
|
||||||
|
with warnings.catch_warnings():
|
||||||
|
warnings.simplefilter("ignore")
|
||||||
|
nelts = nrows * ncols
|
||||||
|
x = np.ctypeslib.as_array((ctypes.c_int32 * nelts).from_address(addr))
|
||||||
|
data[:, :, k] = np.reshape(x.astype(dtype), (nrows, ncols))
|
||||||
|
|
||||||
|
if data.shape[2] == 1:
|
||||||
|
data = data.view()
|
||||||
|
data.shape = data.shape[0:2]
|
||||||
|
|
||||||
|
return data
|
||||||
|
|
||||||
|
def _read_openjp2(self, reduce=0, layer=0, area=None, tile=None,
|
||||||
|
verbose=False):
|
||||||
|
"""Read a JPEG 2000 image using libopenjp2.
|
||||||
|
|
||||||
|
Parameters
|
||||||
|
----------
|
||||||
|
layer : int, optional
|
||||||
|
Number of quality layer to decode.
|
||||||
|
reduce : int, optional
|
||||||
|
Factor by which to reduce output resolution. Use -1 to get the
|
||||||
|
lowest resolution thumbnail.
|
||||||
|
area : tuple, optional
|
||||||
|
Specifies decoding image area,
|
||||||
|
(first_row, first_col, last_row, last_col)
|
||||||
|
tile : int, optional
|
||||||
|
Number of tile to decode.
|
||||||
|
verbose : bool, optional
|
||||||
|
Print informational messages produced by the OpenJPEG library.
|
||||||
|
|
||||||
|
Returns
|
||||||
|
-------
|
||||||
|
img_array : ndarray
|
||||||
|
The image data.
|
||||||
|
|
||||||
|
Raises
|
||||||
|
------
|
||||||
|
RuntimeError
|
||||||
|
If the image has differing subsample factors.
|
||||||
"""
|
"""
|
||||||
# Check for differing subsample factors.
|
# Check for differing subsample factors.
|
||||||
codestream = self.get_codestream(header_only=True)
|
codestream = self.get_codestream(header_only=True)
|
||||||
|
|
@ -593,7 +744,7 @@ class Jp2k(Jp2kBox):
|
||||||
dys = np.array(codestream.segment[1].YRsiz)
|
dys = np.array(codestream.segment[1].YRsiz)
|
||||||
if np.any(dxs - dxs[0]) or np.any(dys - dys[0]):
|
if np.any(dxs - dxs[0]) or np.any(dys - dys[0]):
|
||||||
msg = "Components must all have the same subsampling factors."
|
msg = "Components must all have the same subsampling factors."
|
||||||
raise IOError(msg)
|
raise RuntimeError(msg)
|
||||||
|
|
||||||
img_array = self._read_common(reduce=reduce,
|
img_array = self._read_common(reduce=reduce,
|
||||||
layer=layer,
|
layer=layer,
|
||||||
|
|
@ -780,7 +931,16 @@ class Jp2k(Jp2kBox):
|
||||||
>>> jfile = glymur.data.nemo()
|
>>> jfile = glymur.data.nemo()
|
||||||
>>> jp = glymur.Jp2k(jfile)
|
>>> jp = glymur.Jp2k(jfile)
|
||||||
>>> components_lst = jp.read_bands(reduce=1)
|
>>> components_lst = jp.read_bands(reduce=1)
|
||||||
|
|
||||||
|
Raises
|
||||||
|
------
|
||||||
|
NotImplementedError
|
||||||
|
If the openjp2 library is not available.
|
||||||
"""
|
"""
|
||||||
|
if opj2._OPENJP2 is None:
|
||||||
|
msg = "Requires openjp2 library."
|
||||||
|
raise NotImplementedError(msg)
|
||||||
|
|
||||||
lst = self._read_common(reduce=reduce,
|
lst = self._read_common(reduce=reduce,
|
||||||
layer=layer,
|
layer=layer,
|
||||||
area=area,
|
area=area,
|
||||||
|
|
@ -807,14 +967,14 @@ class Jp2k(Jp2kBox):
|
||||||
--------
|
--------
|
||||||
>>> import glymur
|
>>> import glymur
|
||||||
>>> jfile = glymur.data.nemo()
|
>>> jfile = glymur.data.nemo()
|
||||||
>>> jp = glymur.Jp2k(jfile)
|
>>> jp2 = glymur.Jp2k(jfile)
|
||||||
>>> codestream = jp.get_codestream()
|
>>> codestream = jp2.get_codestream()
|
||||||
>>> print(codestream.segment[1])
|
>>> print(codestream.segment[1])
|
||||||
SIZ marker segment @ (3137, 47)
|
SIZ marker segment @ (3137, 47)
|
||||||
Profile: 2
|
Profile: 2
|
||||||
Reference Grid Height, Width: (1456 x 2592)
|
Reference Grid Height, Width: (1456 x 2592)
|
||||||
Vertical, Horizontal Reference Grid Offset: (0 x 0)
|
Vertical, Horizontal Reference Grid Offset: (0 x 0)
|
||||||
Reference Tile Height, Width: (512 x 512)
|
Reference Tile Height, Width: (1456 x 2592)
|
||||||
Vertical, Horizontal Reference Tile Offset: (0 x 0)
|
Vertical, Horizontal Reference Tile Offset: (0 x 0)
|
||||||
Bitdepth: (8, 8, 8)
|
Bitdepth: (8, 8, 8)
|
||||||
Signed: (False, False, False)
|
Signed: (False, False, False)
|
||||||
|
|
|
||||||
|
|
@ -1,3 +1,4 @@
|
||||||
"""This package organizes individual libraries employed by glymur."""
|
"""This package organizes individual libraries employed by glymur."""
|
||||||
from . import openjp2
|
from . import openjp2
|
||||||
from . import test
|
from . import openjpeg
|
||||||
|
#from . import test
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,9 @@
|
||||||
"""
|
"""
|
||||||
Wraps individual functions in openjp2 library.
|
Wraps individual functions in openjp2 library.
|
||||||
"""
|
"""
|
||||||
|
import ctypes
|
||||||
|
import platform
|
||||||
|
from ctypes.util import find_library
|
||||||
|
|
||||||
|
|
||||||
def _glymurrc_fname():
|
def _glymurrc_fname():
|
||||||
|
|
@ -23,19 +26,46 @@ def _glymurrc_fname():
|
||||||
fname = os.path.join(confdir, 'glymurrc')
|
fname = os.path.join(confdir, 'glymurrc')
|
||||||
if os.path.exists(fname):
|
if os.path.exists(fname):
|
||||||
return fname
|
return fname
|
||||||
else:
|
|
||||||
msg = "Configuration file '{0}' does not exist.".format(confdir)
|
|
||||||
warnings.warn(msg, UserWarning)
|
|
||||||
|
|
||||||
# didn't find a configuration file.
|
# didn't find a configuration file.
|
||||||
return None
|
return None
|
||||||
|
|
||||||
|
|
||||||
def _config():
|
def _get_openjpeg_config():
|
||||||
"""Read configuration file.
|
libopenjpeg_path = find_library('openjpeg')
|
||||||
|
|
||||||
|
# If we could not find it, then look in some likely locations.
|
||||||
|
if libopenjpeg_path is None:
|
||||||
|
if platform.system() == 'Darwin':
|
||||||
|
path = '/opt/local/lib/libopenjpeg.dylib'
|
||||||
|
if os.path.exists(path):
|
||||||
|
libopenjpeg_path = path
|
||||||
|
elif os.name == 'nt':
|
||||||
|
path = os.path.join('C:\\', 'Program files', 'OpenJPEG 1.5',
|
||||||
|
'bin', 'openjpeg.dll')
|
||||||
|
if os.path.exists(path):
|
||||||
|
libopenjpeg_path = path
|
||||||
|
|
||||||
Based on matplotlib.
|
try:
|
||||||
"""
|
if os.name == "nt":
|
||||||
|
_OPENJPEG = ctypes.windll.LoadLibrary(libopenjpeg_path)
|
||||||
|
else:
|
||||||
|
_OPENJPEG = ctypes.CDLL(libopenjpeg_path)
|
||||||
|
except OSError:
|
||||||
|
_OPENJPEG = None
|
||||||
|
|
||||||
|
if _OPENJPEG is not None:
|
||||||
|
# Must be at least 1.5.0
|
||||||
|
_OPENJPEG.opj_version.restype = ctypes.c_char_p
|
||||||
|
v = _OPENJPEG.opj_version()
|
||||||
|
v = v.decode('utf-8')
|
||||||
|
major, minor, patch = v.split('.')
|
||||||
|
if minor != '5':
|
||||||
|
_OPENJPEG = None
|
||||||
|
return _OPENJPEG
|
||||||
|
|
||||||
|
|
||||||
|
def _get_openjp2_config():
|
||||||
filename = _glymurrc_fname()
|
filename = _glymurrc_fname()
|
||||||
if filename is not None:
|
if filename is not None:
|
||||||
# Read the configuration file for the library location.
|
# Read the configuration file for the library location.
|
||||||
|
|
@ -44,14 +74,16 @@ def _config():
|
||||||
libopenjp2_path = parser.get('library', 'openjp2')
|
libopenjp2_path = parser.get('library', 'openjp2')
|
||||||
else:
|
else:
|
||||||
# No help from the config file, try to find it ourselves.
|
# No help from the config file, try to find it ourselves.
|
||||||
from ctypes.util import find_library
|
|
||||||
libopenjp2_path = find_library('openjp2')
|
libopenjp2_path = find_library('openjp2')
|
||||||
|
|
||||||
if libopenjp2_path is None:
|
if libopenjp2_path is None:
|
||||||
return None
|
return None
|
||||||
|
|
||||||
try:
|
try:
|
||||||
_OPENJP2 = ctypes.CDLL(libopenjp2_path)
|
if os.name == "nt":
|
||||||
|
_OPENJP2 = ctypes.windll.LoadLibrary(libopenjp2_path)
|
||||||
|
else:
|
||||||
|
_OPENJP2 = ctypes.CDLL(libopenjp2_path)
|
||||||
except OSError:
|
except OSError:
|
||||||
msg = '"Library {0}" could not be loaded. Operating in degraded mode.'
|
msg = '"Library {0}" could not be loaded. Operating in degraded mode.'
|
||||||
msg = msg.format(libopenjp2_path)
|
msg = msg.format(libopenjp2_path)
|
||||||
|
|
@ -60,6 +92,13 @@ def _config():
|
||||||
return _OPENJP2
|
return _OPENJP2
|
||||||
|
|
||||||
|
|
||||||
|
def _config():
|
||||||
|
"""Read configuration file.
|
||||||
|
"""
|
||||||
|
_OPENJP2 = _get_openjp2_config()
|
||||||
|
_OPENJPEG = _get_openjpeg_config()
|
||||||
|
return _OPENJP2, _OPENJPEG
|
||||||
|
|
||||||
def _get_configdir():
|
def _get_configdir():
|
||||||
"""Return string representing the configuration directory.
|
"""Return string representing the configuration directory.
|
||||||
|
|
||||||
|
|
@ -73,7 +112,9 @@ def _get_configdir():
|
||||||
if 'HOME' in os.environ:
|
if 'HOME' in os.environ:
|
||||||
return os.path.join(os.environ['HOME'], '.config', 'glymur')
|
return os.path.join(os.environ['HOME'], '.config', 'glymur')
|
||||||
|
|
||||||
import ctypes
|
if 'USERPROFILE' in os.environ:
|
||||||
|
return os.path.join(os.environ['USERPROFILE'], 'Application Data', 'glymur')
|
||||||
|
|
||||||
import os
|
import os
|
||||||
import warnings
|
import warnings
|
||||||
|
|
||||||
|
|
@ -85,7 +126,12 @@ else:
|
||||||
from configparser import ConfigParser
|
from configparser import ConfigParser
|
||||||
from configparser import NoOptionError
|
from configparser import NoOptionError
|
||||||
|
|
||||||
_OPENJP2 = _config()
|
_OPENJP2, _OPENJPEG = _config()
|
||||||
|
if _OPENJP2 is None and _OPENJPEG is None:
|
||||||
|
msg = "Neither the glymur configuration file could not be located "
|
||||||
|
msg += "nor could openjpeg 1.5.1 be located. Glymur can only "
|
||||||
|
msg += "operate under extremely degraded conditions."
|
||||||
|
warnings.warn(msg, UserWarning)
|
||||||
|
|
||||||
import numpy as np
|
import numpy as np
|
||||||
|
|
||||||
|
|
@ -616,8 +662,8 @@ class _codestream_info_v2_t(ctypes.Structure):
|
||||||
# Restrict the input and output argument types for each function used in the
|
# Restrict the input and output argument types for each function used in the
|
||||||
# API.
|
# API.
|
||||||
if _OPENJP2 is not None:
|
if _OPENJP2 is not None:
|
||||||
_OPENJP2.opj_create_compress.argtypes = [_codec_format_t]
|
|
||||||
_OPENJP2.opj_create_compress.restype = _codec_t_p
|
_OPENJP2.opj_create_compress.restype = _codec_t_p
|
||||||
|
_OPENJP2.opj_create_compress.argtypes = [_codec_format_t]
|
||||||
|
|
||||||
_OPENJP2.opj_create_decompress.argtypes = [_codec_format_t]
|
_OPENJP2.opj_create_decompress.argtypes = [_codec_format_t]
|
||||||
_OPENJP2.opj_create_decompress.restype = _codec_t_p
|
_OPENJP2.opj_create_decompress.restype = _codec_t_p
|
||||||
|
|
|
||||||
189
glymur/lib/openjpeg.py
Normal file
189
glymur/lib/openjpeg.py
Normal file
|
|
@ -0,0 +1,189 @@
|
||||||
|
"""Wraps library calls to openjpeg.
|
||||||
|
"""
|
||||||
|
|
||||||
|
import ctypes
|
||||||
|
from ctypes.util import find_library
|
||||||
|
import platform
|
||||||
|
import os
|
||||||
|
|
||||||
|
if os.name == "nt":
|
||||||
|
path = os.path.join('C:\\', 'Program files', 'OpenJPEG 1.5',
|
||||||
|
'bin', 'openjpeg.dll')
|
||||||
|
_OPENJPEG = ctypes.windll.LoadLibrary(path)
|
||||||
|
else:
|
||||||
|
if platform.system() == 'Darwin':
|
||||||
|
_OPENJPEG = ctypes.CDLL('/opt/local/lib/libopenjpeg.dylib')
|
||||||
|
elif platform.system() == 'Linux':
|
||||||
|
_OPENJPEG = ctypes.CDLL(find_library('openjpeg'))
|
||||||
|
|
||||||
|
_PATH_LEN = 4096 # maximum allowed size for filenames
|
||||||
|
|
||||||
|
|
||||||
|
class event_mgr_t(ctypes.Structure):
|
||||||
|
"""Message handler object.
|
||||||
|
"""
|
||||||
|
_fields_ = [("error_handler", ctypes.c_void_p),
|
||||||
|
("warning_handler", ctypes.c_void_p),
|
||||||
|
("info_handler", ctypes.c_void_p)]
|
||||||
|
|
||||||
|
class common_struct_t(ctypes.Structure):
|
||||||
|
"""Common fields between JPEG 2000 compression and decompression contextx.
|
||||||
|
"""
|
||||||
|
_fields_ = [("event_mgr", ctypes.POINTER(event_mgr_t)),
|
||||||
|
("client_data", ctypes.c_void_p),
|
||||||
|
("is_decompressor", ctypes.c_bool),
|
||||||
|
("codec_format", ctypes.c_int),
|
||||||
|
("j2k_handle", ctypes.c_void_p),
|
||||||
|
("jp2_handle", ctypes.c_void_p),
|
||||||
|
("mj2_handle", ctypes.c_void_p)]
|
||||||
|
|
||||||
|
|
||||||
|
class dinfo_t(ctypes.Structure):
|
||||||
|
"""Common fields between JPEG 2000 compression and decompression contextx.
|
||||||
|
This is for decompression contexts.
|
||||||
|
"""
|
||||||
|
pass
|
||||||
|
|
||||||
|
|
||||||
|
class cio_t(ctypes.Structure):
|
||||||
|
_fields_ = [# codec context
|
||||||
|
("cinfo", ctypes.POINTER(common_struct_t)),
|
||||||
|
# STREAM_READ or STREAM_WRITE
|
||||||
|
("openmode", ctypes.c_int),
|
||||||
|
# pointer to start of buffer
|
||||||
|
("buffer", ctypes.POINTER(ctypes.c_char)),
|
||||||
|
# buffer size in bytes
|
||||||
|
("length", ctypes.c_int),
|
||||||
|
# pointer to start of stream
|
||||||
|
("start", ctypes.c_char_p),
|
||||||
|
# pointer to end of stream
|
||||||
|
("end", ctypes.c_char_p),
|
||||||
|
# pointer to current position
|
||||||
|
("bp", ctypes.c_char_p)]
|
||||||
|
|
||||||
|
|
||||||
|
class dparameters_t(ctypes.Structure):
|
||||||
|
# cp_reduce: the number of highest resolution levels to be discarded
|
||||||
|
_fields_ = [("cp_reduce", ctypes.c_int),
|
||||||
|
# cp_layer: the maximum number of quality layers to decode
|
||||||
|
("cp_layer", ctypes.c_int),
|
||||||
|
# infile: input file name
|
||||||
|
("infile", ctypes.c_char * _PATH_LEN),
|
||||||
|
# outfile: output file name
|
||||||
|
("outfile", ctypes.c_char * _PATH_LEN),
|
||||||
|
# decod_format: input file format 0: J2K, 1: JP2, 2: JPT
|
||||||
|
("decod_format", ctypes.c_int),
|
||||||
|
# cod_format: output file format 0: PGX, 1: PxM, 2: BMP
|
||||||
|
("cod_format", ctypes.c_int),
|
||||||
|
# jpwl_correct: activates the JPWL correction capabilities
|
||||||
|
("jpwl_correct", ctypes.c_bool),
|
||||||
|
# jpwl_exp_comps: expected number of components
|
||||||
|
("jpwl_exp_comps", ctypes.c_int),
|
||||||
|
# jpwl_max_tiles: maximum number of tiles
|
||||||
|
("jpwl_max_tiles", ctypes.c_int),
|
||||||
|
# cp_limit_decoding: whether decoding should be done on the
|
||||||
|
# entire codestream or be limited to the main header
|
||||||
|
("cp_limit_decoding", ctypes.c_int),
|
||||||
|
("flags", ctypes.c_uint)]
|
||||||
|
|
||||||
|
|
||||||
|
class image_comp_t(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 image_t(ctypes.Structure):
|
||||||
|
"""Defines image data and characteristics."""
|
||||||
|
_fields_ = [("x0", ctypes.c_int),
|
||||||
|
("y0", ctypes.c_int),
|
||||||
|
("x1", ctypes.c_int),
|
||||||
|
("y1", ctypes.c_int),
|
||||||
|
("numcomps", ctypes.c_int),
|
||||||
|
("color_space", ctypes.c_int),
|
||||||
|
("comps", ctypes.POINTER(image_comp_t)),
|
||||||
|
("icc_profile_buf", ctypes.c_char_p),
|
||||||
|
("icc_profile_len", ctypes.c_int)]
|
||||||
|
|
||||||
|
def _cio_open(cinfo, src):
|
||||||
|
"""Wrapper for openjpeg library function opj_cio_open."""
|
||||||
|
argtypes = [ctypes.POINTER(common_struct_t), ctypes.c_char_p, ctypes.c_int]
|
||||||
|
_OPENJPEG.opj_cio_open.argtypes = argtypes
|
||||||
|
_OPENJPEG.opj_cio_open.restype = ctypes.POINTER(cio_t)
|
||||||
|
|
||||||
|
cio = _OPENJPEG.opj_cio_open(ctypes.cast(cinfo, ctypes.POINTER(common_struct_t)),
|
||||||
|
src, len(src))
|
||||||
|
return cio
|
||||||
|
|
||||||
|
def _cio_close(cio):
|
||||||
|
"""Wraps openjpeg library function cio_close.
|
||||||
|
"""
|
||||||
|
_OPENJPEG.opj_cio_close.argtypes = [ctypes.POINTER(cio_t)]
|
||||||
|
_OPENJPEG.opj_cio_close(cio)
|
||||||
|
|
||||||
|
def _create_decompress(fmt):
|
||||||
|
"""Wraps openjpeg library function opj_create_decompress.
|
||||||
|
"""
|
||||||
|
_OPENJPEG.opj_create_decompress.argtypes = [ctypes.c_int]
|
||||||
|
_OPENJPEG.opj_create_decompress.restype = ctypes.POINTER(dinfo_t)
|
||||||
|
dinfo = _OPENJPEG.opj_create_decompress(fmt)
|
||||||
|
return dinfo
|
||||||
|
|
||||||
|
def _decode(dinfo, cio):
|
||||||
|
"""Wrapper for opj_decode.
|
||||||
|
"""
|
||||||
|
argtypes = [ctypes.POINTER(dinfo_t), ctypes.POINTER(cio_t)]
|
||||||
|
_OPENJPEG.opj_decode.argtypes = argtypes
|
||||||
|
_OPENJPEG.opj_decode.restype = ctypes.POINTER(image_t)
|
||||||
|
image = _OPENJPEG.opj_decode(dinfo, cio)
|
||||||
|
return image
|
||||||
|
|
||||||
|
def _destroy_decompress(dinfo):
|
||||||
|
"""Wraps openjpeg library function opj_destroy_decompress."""
|
||||||
|
_OPENJPEG.opj_destroy_decompress.argtypes = [ctypes.POINTER(dinfo_t)]
|
||||||
|
_OPENJPEG.opj_destroy_decompress(dinfo)
|
||||||
|
|
||||||
|
def _image_destroy(image):
|
||||||
|
"""Wraps openjpeg library function opj_image_destroy."""
|
||||||
|
_OPENJPEG.opj_image_destroy.argtypes = [ctypes.POINTER(image_t)]
|
||||||
|
_OPENJPEG.opj_image_destroy(image)
|
||||||
|
|
||||||
|
def _set_default_decoder_parameters(dparams_p):
|
||||||
|
"""Wrapper for opj_set_default_decoder_parameters.
|
||||||
|
"""
|
||||||
|
argtypes = [ctypes.POINTER(dparameters_t)]
|
||||||
|
_OPENJPEG.opj_set_default_decoder_parameters.argtypes = argtypes
|
||||||
|
_OPENJPEG.opj_set_default_decoder_parameters(dparams_p)
|
||||||
|
|
||||||
|
|
||||||
|
def _set_event_mgr(dinfo, event_mgr, context=None):
|
||||||
|
"""Wrapper for openjpeg library function opj_set_event_mgr.
|
||||||
|
"""
|
||||||
|
argtypes = [ctypes.POINTER(common_struct_t),
|
||||||
|
ctypes.POINTER(event_mgr_t),
|
||||||
|
ctypes.c_void_p]
|
||||||
|
_OPENJPEG.opj_set_event_mgr(ctypes.cast(dinfo,
|
||||||
|
ctypes.POINTER(common_struct_t)),
|
||||||
|
event_mgr, context)
|
||||||
|
|
||||||
|
def _setup_decoder(dinfo, dparams):
|
||||||
|
"""Wrapper for openjpeg library function opj_setup_decoder."""
|
||||||
|
argtypes = [ctypes.POINTER(dinfo_t), ctypes.POINTER(dparameters_t)]
|
||||||
|
_OPENJPEG.opj_setup_decoder.argtypes = argtypes
|
||||||
|
_OPENJPEG.opj_setup_decoder(dinfo, dparams)
|
||||||
|
|
||||||
|
def _version():
|
||||||
|
"""Wrapper for opj_version library routine."""
|
||||||
|
_OPENJPEG.opj_version.restype = ctypes.c_char_p
|
||||||
|
v = _OPENJPEG.opj_version()
|
||||||
|
return v.decode('utf-8')
|
||||||
38
glymur/lib/test/test_openjpeg.py
Normal file
38
glymur/lib/test/test_openjpeg.py
Normal file
|
|
@ -0,0 +1,38 @@
|
||||||
|
import ctypes
|
||||||
|
import unittest
|
||||||
|
|
||||||
|
import glymur
|
||||||
|
|
||||||
|
@unittest.skipIf(glymur.lib.openjpeg._OPENJPEG is None,
|
||||||
|
"Missing openjpeg library.")
|
||||||
|
class TestOpenJPEG(unittest.TestCase):
|
||||||
|
|
||||||
|
def setUp(self):
|
||||||
|
pass
|
||||||
|
|
||||||
|
def tearDown(self):
|
||||||
|
pass
|
||||||
|
|
||||||
|
def test_version(self):
|
||||||
|
v = glymur.lib.openjpeg._version()
|
||||||
|
parts = v.split('.')
|
||||||
|
self.assertEqual(parts[0], '1')
|
||||||
|
self.assertEqual(parts[1], '5')
|
||||||
|
|
||||||
|
def test_set_default_decoder_parameters(self):
|
||||||
|
# Verify that we properly set the default decode parameters.
|
||||||
|
dp = glymur.lib.openjpeg.dparameters_t()
|
||||||
|
glymur.lib.openjpeg._set_default_decoder_parameters(ctypes.byref(dp))
|
||||||
|
|
||||||
|
self.assertEqual(dp.cp_reduce, 0)
|
||||||
|
self.assertEqual(dp.cp_layer, 0)
|
||||||
|
self.assertEqual(dp.infile, b'')
|
||||||
|
self.assertEqual(dp.outfile, b'')
|
||||||
|
self.assertEqual(dp.decod_format, -1)
|
||||||
|
self.assertEqual(dp.cod_format, -1)
|
||||||
|
self.assertEqual(dp.jpwl_correct, 0)
|
||||||
|
self.assertEqual(dp.jpwl_exp_comps, 0)
|
||||||
|
self.assertEqual(dp.jpwl_max_tiles, 0)
|
||||||
|
self.assertEqual(dp.cp_limit_decoding, 0)
|
||||||
|
self.assertEqual(dp.flags, 0)
|
||||||
|
|
||||||
|
|
@ -1,5 +1,6 @@
|
||||||
from .test_callbacks import TestCallbacks as callbacks
|
from .test_callbacks import TestCallbacks as callbacks
|
||||||
from .test_codestream import TestCodestream as codestream
|
from .test_codestream import TestCodestream as codestream
|
||||||
|
from .test_config import TestSuite as config
|
||||||
from .test_jp2k import TestJp2k as jp2k
|
from .test_jp2k import TestJp2k as jp2k
|
||||||
from .test_icc import TestICC as icc
|
from .test_icc import TestICC as icc
|
||||||
from .test_printing import TestPrinting as printing
|
from .test_printing import TestPrinting as printing
|
||||||
|
|
|
||||||
93
glymur/test/fixtures.py
Normal file
93
glymur/test/fixtures.py
Normal file
|
|
@ -0,0 +1,93 @@
|
||||||
|
import re
|
||||||
|
import sys
|
||||||
|
|
||||||
|
import numpy as np
|
||||||
|
|
||||||
|
def mse(A, B):
|
||||||
|
"""Mean Square Error"""
|
||||||
|
diff = A.astype(np.double) - B.astype(np.double)
|
||||||
|
#e = np.sqrt(np.mean(diff**2))
|
||||||
|
e = np.mean(diff**2)
|
||||||
|
return e
|
||||||
|
|
||||||
|
|
||||||
|
def peak_tolerance(A, B):
|
||||||
|
"""Peak Tolerance"""
|
||||||
|
diff = np.abs(A.astype(np.double) - B.astype(np.double))
|
||||||
|
p = diff.max()
|
||||||
|
return p
|
||||||
|
|
||||||
|
|
||||||
|
def read_pgx(pgx_file):
|
||||||
|
"""Helper function for reading the PGX comparison files.
|
||||||
|
|
||||||
|
Open the file in ascii mode and read the header line.
|
||||||
|
Will look something like
|
||||||
|
|
||||||
|
PG ML + 8 128 128
|
||||||
|
PG%[ \t]%c%c%[ \t+-]%d%[ \t]%d%[ \t]%d"
|
||||||
|
"""
|
||||||
|
header = ''
|
||||||
|
with open(pgx_file, 'rb') as fp:
|
||||||
|
while True:
|
||||||
|
x = fp.read(1)
|
||||||
|
if x[0] == 10 or x == '\n':
|
||||||
|
pos = fp.tell()
|
||||||
|
break
|
||||||
|
else:
|
||||||
|
if sys.hexversion < 0x03000000:
|
||||||
|
header += x
|
||||||
|
else:
|
||||||
|
header += chr(x[0])
|
||||||
|
|
||||||
|
header = header.rstrip()
|
||||||
|
n = re.split('\s', header)
|
||||||
|
|
||||||
|
if (n[1][0] == 'M') and (sys.byteorder == 'little'):
|
||||||
|
swapbytes = True
|
||||||
|
elif (n[1][0] == 'L') and (sys.byteorder == 'big'):
|
||||||
|
swapbytes = True
|
||||||
|
else:
|
||||||
|
swapbytes = False
|
||||||
|
|
||||||
|
if (len(n) == 6):
|
||||||
|
bitdepth = int(n[3])
|
||||||
|
signed = bitdepth < 0
|
||||||
|
if signed:
|
||||||
|
bitdepth = -1 * bitdepth
|
||||||
|
nrows = int(n[5])
|
||||||
|
ncols = int(n[4])
|
||||||
|
else:
|
||||||
|
bitdepth = int(n[2])
|
||||||
|
signed = bitdepth < 0
|
||||||
|
if signed:
|
||||||
|
bitdepth = -1 * bitdepth
|
||||||
|
nrows = int(n[4])
|
||||||
|
ncols = int(n[3])
|
||||||
|
|
||||||
|
if signed:
|
||||||
|
if bitdepth <= 8:
|
||||||
|
dtype = np.int8
|
||||||
|
elif bitdepth <= 16:
|
||||||
|
dtype = np.int16
|
||||||
|
else:
|
||||||
|
raise RuntimeError("unhandled bitdepth")
|
||||||
|
else:
|
||||||
|
if bitdepth <= 8:
|
||||||
|
dtype = np.uint8
|
||||||
|
elif bitdepth <= 16:
|
||||||
|
dtype = np.uint16
|
||||||
|
else:
|
||||||
|
raise RuntimeError("unhandled bitdepth")
|
||||||
|
|
||||||
|
shape = [nrows, ncols]
|
||||||
|
|
||||||
|
# Reopen the file in binary mode and seek to the start of the binary
|
||||||
|
# data
|
||||||
|
with open(pgx_file, 'rb') as fp:
|
||||||
|
fp.seek(pos)
|
||||||
|
data = np.fromfile(file=fp, dtype=dtype).reshape(shape)
|
||||||
|
|
||||||
|
return(data.byteswap(swapbytes))
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -1,5 +1,6 @@
|
||||||
import os
|
import os
|
||||||
import pkg_resources
|
import pkg_resources
|
||||||
|
import re
|
||||||
import sys
|
import sys
|
||||||
import tempfile
|
import tempfile
|
||||||
import unittest
|
import unittest
|
||||||
|
|
@ -21,8 +22,8 @@ class TestCallbacks(unittest.TestCase):
|
||||||
# Save sys.stdout.
|
# Save sys.stdout.
|
||||||
self.stdout = sys.stdout
|
self.stdout = sys.stdout
|
||||||
sys.stdout = StringIO()
|
sys.stdout = StringIO()
|
||||||
self.jp2file = pkg_resources.resource_filename(glymur.__name__,
|
self.jp2file = glymur.data.nemo()
|
||||||
"data/nemo.jp2")
|
self.j2kfile = glymur.data.goodstuff()
|
||||||
|
|
||||||
def tearDown(self):
|
def tearDown(self):
|
||||||
# Restore stdout.
|
# Restore stdout.
|
||||||
|
|
@ -44,24 +45,67 @@ class TestCallbacks(unittest.TestCase):
|
||||||
def test_info_warning_callbacks_on_read(self):
|
def test_info_warning_callbacks_on_read(self):
|
||||||
# Verify that we get the expected stdio output when our internal info
|
# Verify that we get the expected stdio output when our internal info
|
||||||
# callback handler is enabled.
|
# callback handler is enabled.
|
||||||
j = glymur.Jp2k(self.jp2file)
|
j = glymur.Jp2k(self.j2kfile)
|
||||||
d = j.read(reduce=3, verbose=True, area=(0, 0, 512, 1024))
|
d = j.read(reduce=1, verbose=True, area=(0, 0, 200, 150))
|
||||||
actual = sys.stdout.getvalue().strip()
|
actual = sys.stdout.getvalue().strip()
|
||||||
|
|
||||||
lines = ['[INFO] Start to read j2k main header (3135).',
|
lines = ['[INFO] Start to read j2k main header (0).',
|
||||||
'[INFO] Main header has been correctly decoded.',
|
'[INFO] Main header has been correctly decoded.',
|
||||||
'[INFO] Setting decoding area to 0,0,1024,512',
|
'[INFO] Setting decoding area to 0,0,150,200',
|
||||||
'[INFO] Header of tile 0 / 17 has been read.',
|
'[INFO] Header of tile 0 / 0 has been read.',
|
||||||
'[INFO] Tile 1/18 has been decoded.',
|
'[INFO] Tile 1/1 has been decoded.',
|
||||||
'[INFO] Image data has been updated with tile 1.',
|
'[INFO] Image data has been updated with tile 1.']
|
||||||
'[INFO] Header of tile 1 / 17 has been read.',
|
|
||||||
'[INFO] Tile 2/18 has been decoded.',
|
|
||||||
'[INFO] Image data has been updated with tile 2.',
|
|
||||||
'[INFO] Stream reached its end !']
|
|
||||||
|
|
||||||
expected = '\n'.join(lines)
|
expected = '\n'.join(lines)
|
||||||
self.assertEqual(actual, expected)
|
self.assertEqual(actual, expected)
|
||||||
|
|
||||||
|
|
||||||
|
@unittest.skipIf(glymur.lib.openjp2._OPENJPEG is None,
|
||||||
|
"Missing openjpeg library.")
|
||||||
|
class TestCallbacks15(unittest.TestCase):
|
||||||
|
"""This test suite is for OpenJPEG 1.5.1 properties.
|
||||||
|
"""
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def setUpClass(cls):
|
||||||
|
# Monkey patch the package so as to use OPENJPEG instead of OPENJP2
|
||||||
|
cls.openjp2 = glymur.lib.openjp2._OPENJP2
|
||||||
|
glymur.lib.openjp2._OPENJP2 = None
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def tearDownClass(cls):
|
||||||
|
# Restore OPENJP2
|
||||||
|
glymur.lib.openjp2._OPENJP2 = cls.openjp2
|
||||||
|
|
||||||
|
def setUp(self):
|
||||||
|
# Save sys.stdout.
|
||||||
|
self.stdout = sys.stdout
|
||||||
|
sys.stdout = StringIO()
|
||||||
|
self.jp2file = glymur.data.nemo()
|
||||||
|
self.j2kfile = glymur.data.goodstuff()
|
||||||
|
|
||||||
|
def tearDown(self):
|
||||||
|
# Restore stdout.
|
||||||
|
sys.stdout = self.stdout
|
||||||
|
|
||||||
|
def test_info_callbacks_on_read(self):
|
||||||
|
# Verify that we get the expected stdio output when our internal info
|
||||||
|
# callback handler is enabled.
|
||||||
|
j = glymur.Jp2k(self.j2kfile)
|
||||||
|
d = j.read(reduce=1, verbose=True)
|
||||||
|
actual = sys.stdout.getvalue().strip()
|
||||||
|
|
||||||
|
regex = re.compile(r"""\[INFO\]\stile\s1\sof\s1\s+
|
||||||
|
\[INFO\]\s-\stiers-1\stook\s[0-9]+\.[0-9]+\ss\s+
|
||||||
|
\[INFO\]\s-\sdwt\stook\s[0-9]+\.[0-9]+\ss\s+
|
||||||
|
\[INFO\]\s-\stile\sdecoded\sin\s[0-9]+\.[0-9]+\ss""",
|
||||||
|
re.VERBOSE)
|
||||||
|
if sys.hexversion <= 0x03020000:
|
||||||
|
self.assertRegexpMatches(actual, regex)
|
||||||
|
else:
|
||||||
|
self.assertRegex(actual, regex)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
if __name__ == "__main__":
|
if __name__ == "__main__":
|
||||||
unittest.main()
|
unittest.main()
|
||||||
|
|
|
||||||
|
|
@ -1,3 +1,7 @@
|
||||||
|
"""These tests are for edge cases where OPENJPEG does not exist, but
|
||||||
|
OPENJP2 may be present in some form or other.
|
||||||
|
"""
|
||||||
|
|
||||||
import imp
|
import imp
|
||||||
import os
|
import os
|
||||||
import sys
|
import sys
|
||||||
|
|
@ -16,14 +20,28 @@ from glymur import Jp2k
|
||||||
from glymur.lib import openjp2 as opj2
|
from glymur.lib import openjp2 as opj2
|
||||||
|
|
||||||
|
|
||||||
|
@unittest.skip("Cannot work when both OPENJPEG and OPENJP2 are both present.")
|
||||||
|
@unittest.skipIf(glymur.lib.openjp2._OPENJP2 is None,
|
||||||
|
"Needs openjp2 library first before these tests make sense.")
|
||||||
@unittest.skipIf(sys.hexversion < 0x03020000,
|
@unittest.skipIf(sys.hexversion < 0x03020000,
|
||||||
"Uses features introduced in 3.2.")
|
"Uses features introduced in 3.2.")
|
||||||
class TestJp2k(unittest.TestCase):
|
class TestSuite(unittest.TestCase):
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def setUpClass(cls):
|
||||||
|
# Monkey patch the package so as to ignore OPENJPEG if it exists.
|
||||||
|
cls.openjpeg = glymur.lib.openjpeg._OPENJPEG
|
||||||
|
glymur.lib.openjp2._OPENJPEG = None
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def tearDownClass(cls):
|
||||||
|
# Restore OPENJPEG
|
||||||
|
glymur.lib.openjpeg._OPENJPEG = cls.openjpeg
|
||||||
|
|
||||||
def setUp(self):
|
def setUp(self):
|
||||||
self.jp2file = pkg_resources.resource_filename(glymur.__name__,
|
|
||||||
"data/nemo.jp2")
|
|
||||||
imp.reload(glymur)
|
imp.reload(glymur)
|
||||||
imp.reload(glymur.lib.openjp2)
|
imp.reload(glymur.lib.openjp2)
|
||||||
|
self.jp2file = glymur.data.nemo()
|
||||||
|
|
||||||
def tearDown(self):
|
def tearDown(self):
|
||||||
imp.reload(glymur)
|
imp.reload(glymur)
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,5 @@
|
||||||
import doctest
|
import doctest
|
||||||
|
import os
|
||||||
import tempfile
|
import tempfile
|
||||||
import xml.etree.cElementTree as ET
|
import xml.etree.cElementTree as ET
|
||||||
import unittest
|
import unittest
|
||||||
|
|
@ -17,6 +18,8 @@ def load_tests(loader, tests, ignore):
|
||||||
return tests
|
return tests
|
||||||
|
|
||||||
|
|
||||||
|
@unittest.skipIf(glymur.lib.openjp2._OPENJP2 is None,
|
||||||
|
"Missing openjp2 library.")
|
||||||
class TestChannelDefinition(unittest.TestCase):
|
class TestChannelDefinition(unittest.TestCase):
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
|
|
@ -288,6 +291,8 @@ class TestXML(unittest.TestCase):
|
||||||
with self.assertRaises((IOError, OSError)) as ce:
|
with self.assertRaises((IOError, OSError)) as ce:
|
||||||
xmlb = glymur.jp2box.XMLBox(filename=self.xmlfile, xml=xml_object)
|
xmlb = glymur.jp2box.XMLBox(filename=self.xmlfile, xml=xml_object)
|
||||||
|
|
||||||
|
@unittest.skipIf(os.name == "nt",
|
||||||
|
"Problems using NamedTemporaryFile on windows.")
|
||||||
def test_basic_xml(self):
|
def test_basic_xml(self):
|
||||||
# Should be able to write an XMLBox.
|
# Should be able to write an XMLBox.
|
||||||
j2k = Jp2k(self.j2kfile)
|
j2k = Jp2k(self.j2kfile)
|
||||||
|
|
@ -308,6 +313,8 @@ class TestXML(unittest.TestCase):
|
||||||
self.assertEqual(ET.tostring(jp2.box[3].xml),
|
self.assertEqual(ET.tostring(jp2.box[3].xml),
|
||||||
b'<data>0</data>')
|
b'<data>0</data>')
|
||||||
|
|
||||||
|
@unittest.skipIf(os.name == "nt",
|
||||||
|
"Problems using NamedTemporaryFile on windows.")
|
||||||
def test_xml_from_file(self):
|
def test_xml_from_file(self):
|
||||||
j2k = Jp2k(self.j2kfile)
|
j2k = Jp2k(self.j2kfile)
|
||||||
|
|
||||||
|
|
@ -352,6 +359,8 @@ class TestColourSpecificationBox(unittest.TestCase):
|
||||||
def tearDown(self):
|
def tearDown(self):
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
@unittest.skipIf(os.name == "nt",
|
||||||
|
"Problems using NamedTemporaryFile on windows.")
|
||||||
def test_color_specification_box_with_out_enumerated_colorspace(self):
|
def test_color_specification_box_with_out_enumerated_colorspace(self):
|
||||||
j2k = Jp2k(self.j2kfile)
|
j2k = Jp2k(self.j2kfile)
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -74,10 +74,8 @@ class TestJp2k(unittest.TestCase):
|
||||||
os.unlink(cls._bad_xml_file)
|
os.unlink(cls._bad_xml_file)
|
||||||
|
|
||||||
def setUp(self):
|
def setUp(self):
|
||||||
self.jp2file = pkg_resources.resource_filename(glymur.__name__,
|
self.jp2file = glymur.data.nemo()
|
||||||
"data/nemo.jp2")
|
self.j2kfile = glymur.data.goodstuff()
|
||||||
self.j2kfile = pkg_resources.resource_filename(glymur.__name__,
|
|
||||||
"data/goodstuff.j2k")
|
|
||||||
|
|
||||||
def tearDown(self):
|
def tearDown(self):
|
||||||
pass
|
pass
|
||||||
|
|
@ -92,11 +90,11 @@ class TestJp2k(unittest.TestCase):
|
||||||
|
|
||||||
def test_reduce_max(self):
|
def test_reduce_max(self):
|
||||||
# Verify that reduce=-1 gets us the lowest resolution image
|
# Verify that reduce=-1 gets us the lowest resolution image
|
||||||
j = Jp2k(self.jp2file)
|
j = Jp2k(self.j2kfile)
|
||||||
thumbnail1 = j.read(reduce=-1)
|
thumbnail1 = j.read(reduce=-1)
|
||||||
thumbnail2 = j.read(reduce=5)
|
thumbnail2 = j.read(reduce=5)
|
||||||
np.testing.assert_array_equal(thumbnail1, thumbnail2)
|
np.testing.assert_array_equal(thumbnail1, thumbnail2)
|
||||||
self.assertEqual(thumbnail1.shape, (46, 81, 3))
|
self.assertEqual(thumbnail1.shape, (25, 15, 3))
|
||||||
|
|
||||||
def test_invalid_xml_box(self):
|
def test_invalid_xml_box(self):
|
||||||
# Should be able to recover from xml box with bad xml.
|
# Should be able to recover from xml box with bad xml.
|
||||||
|
|
@ -145,15 +143,6 @@ class TestJp2k(unittest.TestCase):
|
||||||
filename = 'this file does not actually exist on the file system.'
|
filename = 'this file does not actually exist on the file system.'
|
||||||
jp2k = Jp2k(filename)
|
jp2k = Jp2k(filename)
|
||||||
|
|
||||||
def test_nemo_tile(self):
|
|
||||||
# Issue 134, trouble reading first nemo tile.
|
|
||||||
j = Jp2k(self.jp2file)
|
|
||||||
with warnings.catch_warnings():
|
|
||||||
warnings.simplefilter("ignore")
|
|
||||||
tiledata = j.read(tile=0)
|
|
||||||
subsetdata = j.read(area=(0, 0, 512, 512))
|
|
||||||
np.testing.assert_array_equal(tiledata, subsetdata)
|
|
||||||
|
|
||||||
def test_write_srgb_without_mct(self):
|
def test_write_srgb_without_mct(self):
|
||||||
j2k = Jp2k(self.j2kfile)
|
j2k = Jp2k(self.j2kfile)
|
||||||
expdata = j2k.read()
|
expdata = j2k.read()
|
||||||
|
|
@ -178,7 +167,7 @@ class TestJp2k(unittest.TestCase):
|
||||||
def test_write_cprl(self):
|
def test_write_cprl(self):
|
||||||
# Issue 17
|
# Issue 17
|
||||||
j = Jp2k(self.jp2file)
|
j = Jp2k(self.jp2file)
|
||||||
expdata = j.read(reduce=2)
|
expdata = j.read(reduce=1)
|
||||||
with tempfile.NamedTemporaryFile(suffix='.jp2') as tfile:
|
with tempfile.NamedTemporaryFile(suffix='.jp2') as tfile:
|
||||||
ofile = Jp2k(tfile.name, 'wb')
|
ofile = Jp2k(tfile.name, 'wb')
|
||||||
ofile.write(expdata, prog='CPRL')
|
ofile.write(expdata, prog='CPRL')
|
||||||
|
|
@ -220,7 +209,7 @@ class TestJp2k(unittest.TestCase):
|
||||||
|
|
||||||
self.assertEqual(jp2k.box[5].id, 'jp2c')
|
self.assertEqual(jp2k.box[5].id, 'jp2c')
|
||||||
self.assertEqual(jp2k.box[5].offset, 3127)
|
self.assertEqual(jp2k.box[5].offset, 3127)
|
||||||
self.assertEqual(jp2k.box[5].length, 1133427)
|
self.assertEqual(jp2k.box[5].length, 1132296)
|
||||||
|
|
||||||
# jp2h super box
|
# jp2h super box
|
||||||
self.assertEqual(len(jp2k.box[2].box), 2)
|
self.assertEqual(len(jp2k.box[2].box), 2)
|
||||||
|
|
@ -330,7 +319,7 @@ class TestJp2k(unittest.TestCase):
|
||||||
# Issue 86.
|
# Issue 86.
|
||||||
filename = os.path.join(data_root, 'input/conformance/p0_05.j2k')
|
filename = os.path.join(data_root, 'input/conformance/p0_05.j2k')
|
||||||
j = Jp2k(filename)
|
j = Jp2k(filename)
|
||||||
with self.assertRaises(IOError):
|
with self.assertRaises(RuntimeError):
|
||||||
j.read()
|
j.read()
|
||||||
|
|
||||||
@unittest.skipIf(data_root is None,
|
@unittest.skipIf(data_root is None,
|
||||||
|
|
@ -540,7 +529,7 @@ class TestJp2k(unittest.TestCase):
|
||||||
def test_asoc_label_box(self):
|
def test_asoc_label_box(self):
|
||||||
# Construct a fake file with an asoc and a label box, as
|
# Construct a fake file with an asoc and a label box, as
|
||||||
# OpenJPEG doesn't have such a file.
|
# OpenJPEG doesn't have such a file.
|
||||||
data = Jp2k(self.jp2file).read(reduce=3)
|
data = Jp2k(self.jp2file).read(reduce=1)
|
||||||
with tempfile.NamedTemporaryFile(suffix='.jp2') as tfile:
|
with tempfile.NamedTemporaryFile(suffix='.jp2') as tfile:
|
||||||
j = Jp2k(tfile.name, 'wb')
|
j = Jp2k(tfile.name, 'wb')
|
||||||
j.write(data)
|
j.write(data)
|
||||||
|
|
@ -659,5 +648,66 @@ class TestJp2k(unittest.TestCase):
|
||||||
self.assertFalse('Make' in exif['Image'].keys())
|
self.assertFalse('Make' in exif['Image'].keys())
|
||||||
|
|
||||||
|
|
||||||
|
@unittest.skipIf(glymur.lib.openjpeg._OPENJPEG is None,
|
||||||
|
"Missing openjpeg library.")
|
||||||
|
class TestJp2k15(unittest.TestCase):
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def setUpClass(cls):
|
||||||
|
# Monkey patch the package so as to use OPENJPEG instead of OPENJP2
|
||||||
|
cls.openjp2 = glymur.lib.openjp2._OPENJP2
|
||||||
|
glymur.lib.openjp2._OPENJP2 = None
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def tearDownClass(cls):
|
||||||
|
# Restore OPENJP2
|
||||||
|
glymur.lib.openjp2._OPENJP2 = cls.openjp2
|
||||||
|
|
||||||
|
def setUp(self):
|
||||||
|
self.jp2file = glymur.data.nemo()
|
||||||
|
self.j2kfile = glymur.data.goodstuff()
|
||||||
|
|
||||||
|
def tearDown(self):
|
||||||
|
pass
|
||||||
|
|
||||||
|
def test_bands(self):
|
||||||
|
# Reading individual bands is an advanced maneuver.
|
||||||
|
jp2k = Jp2k(self.j2kfile)
|
||||||
|
with self.assertRaises(NotImplementedError) as ce:
|
||||||
|
jpdata = jp2k.read_bands()
|
||||||
|
|
||||||
|
def test_area(self):
|
||||||
|
# Area option not allowed for 1.5.1.
|
||||||
|
j2k = Jp2k(self.j2kfile)
|
||||||
|
with self.assertRaises(TypeError) as ce:
|
||||||
|
d = j2k.read(area=(0, 0, 100, 100))
|
||||||
|
|
||||||
|
def test_tile(self):
|
||||||
|
# tile option not allowed for 1.5.1.
|
||||||
|
j2k = Jp2k(self.j2kfile)
|
||||||
|
with self.assertRaises(TypeError) as ce:
|
||||||
|
d = j2k.read(tile=0)
|
||||||
|
|
||||||
|
def test_layer(self):
|
||||||
|
# layer option not allowed for 1.5.1.
|
||||||
|
j2k = Jp2k(self.j2kfile)
|
||||||
|
with self.assertRaises(TypeError) as ce:
|
||||||
|
d = j2k.read(layer=1)
|
||||||
|
|
||||||
|
def test_basic_jp2(self):
|
||||||
|
# This test is only useful when openjp2 is not available
|
||||||
|
# and OPJ_DATA_ROOT is not set. We need at least one
|
||||||
|
# working JP2 test.
|
||||||
|
j2k = Jp2k(self.jp2file)
|
||||||
|
d = j2k.read(reduce=1)
|
||||||
|
|
||||||
|
def test_basic_j2k(self):
|
||||||
|
# This test is only useful when openjp2 is not available
|
||||||
|
# and OPJ_DATA_ROOT is not set. We need at least one
|
||||||
|
# working J2K test.
|
||||||
|
j2k = Jp2k(self.j2kfile)
|
||||||
|
d = j2k.read()
|
||||||
|
|
||||||
|
|
||||||
if __name__ == "__main__":
|
if __name__ == "__main__":
|
||||||
unittest.main()
|
unittest.main()
|
||||||
|
|
|
||||||
|
|
@ -24,6 +24,8 @@ import numpy as np
|
||||||
from glymur import Jp2k
|
from glymur import Jp2k
|
||||||
import glymur
|
import glymur
|
||||||
|
|
||||||
|
from .fixtures import *
|
||||||
|
|
||||||
try:
|
try:
|
||||||
data_root = os.environ['OPJ_DATA_ROOT']
|
data_root = os.environ['OPJ_DATA_ROOT']
|
||||||
except KeyError:
|
except KeyError:
|
||||||
|
|
@ -32,94 +34,6 @@ except:
|
||||||
raise
|
raise
|
||||||
|
|
||||||
|
|
||||||
def mse(A, B):
|
|
||||||
"""Mean Square Error"""
|
|
||||||
diff = A.astype(np.double) - B.astype(np.double)
|
|
||||||
#e = np.sqrt(np.mean(diff**2))
|
|
||||||
e = np.mean(diff**2)
|
|
||||||
return e
|
|
||||||
|
|
||||||
|
|
||||||
def peak_tolerance(A, B):
|
|
||||||
"""Peak Tolerance"""
|
|
||||||
diff = np.abs(A.astype(np.double) - B.astype(np.double))
|
|
||||||
p = diff.max()
|
|
||||||
return p
|
|
||||||
|
|
||||||
|
|
||||||
def read_pgx(pgx_file):
|
|
||||||
"""Helper function for reading the PGX comparison files.
|
|
||||||
|
|
||||||
Open the file in ascii mode and read the header line.
|
|
||||||
Will look something like
|
|
||||||
|
|
||||||
PG ML + 8 128 128
|
|
||||||
PG%[ \t]%c%c%[ \t+-]%d%[ \t]%d%[ \t]%d"
|
|
||||||
"""
|
|
||||||
header = ''
|
|
||||||
with open(pgx_file, 'rb') as fp:
|
|
||||||
while True:
|
|
||||||
x = fp.read(1)
|
|
||||||
if x[0] == 10 or x == '\n':
|
|
||||||
pos = fp.tell()
|
|
||||||
break
|
|
||||||
else:
|
|
||||||
if sys.hexversion < 0x03000000:
|
|
||||||
header += x
|
|
||||||
else:
|
|
||||||
header += chr(x[0])
|
|
||||||
|
|
||||||
header = header.rstrip()
|
|
||||||
n = re.split('\s', header)
|
|
||||||
|
|
||||||
if (n[1][0] == 'M') and (sys.byteorder == 'little'):
|
|
||||||
swapbytes = True
|
|
||||||
elif (n[1][0] == 'L') and (sys.byteorder == 'big'):
|
|
||||||
swapbytes = True
|
|
||||||
else:
|
|
||||||
swapbytes = False
|
|
||||||
|
|
||||||
if (len(n) == 6):
|
|
||||||
bitdepth = int(n[3])
|
|
||||||
signed = bitdepth < 0
|
|
||||||
if signed:
|
|
||||||
bitdepth = -1 * bitdepth
|
|
||||||
nrows = int(n[5])
|
|
||||||
ncols = int(n[4])
|
|
||||||
else:
|
|
||||||
bitdepth = int(n[2])
|
|
||||||
signed = bitdepth < 0
|
|
||||||
if signed:
|
|
||||||
bitdepth = -1 * bitdepth
|
|
||||||
nrows = int(n[4])
|
|
||||||
ncols = int(n[3])
|
|
||||||
|
|
||||||
if signed:
|
|
||||||
if bitdepth <= 8:
|
|
||||||
dtype = np.int8
|
|
||||||
elif bitdepth <= 16:
|
|
||||||
dtype = np.int16
|
|
||||||
else:
|
|
||||||
raise RuntimeError("unhandled bitdepth")
|
|
||||||
else:
|
|
||||||
if bitdepth <= 8:
|
|
||||||
dtype = np.uint8
|
|
||||||
elif bitdepth <= 16:
|
|
||||||
dtype = np.uint16
|
|
||||||
else:
|
|
||||||
raise RuntimeError("unhandled bitdepth")
|
|
||||||
|
|
||||||
shape = [nrows, ncols]
|
|
||||||
|
|
||||||
# Reopen the file in binary mode and seek to the start of the binary
|
|
||||||
# data
|
|
||||||
with open(pgx_file, 'rb') as fp:
|
|
||||||
fp.seek(pos)
|
|
||||||
data = np.fromfile(file=fp, dtype=dtype).reshape(shape)
|
|
||||||
|
|
||||||
return(data.byteswap(swapbytes))
|
|
||||||
|
|
||||||
|
|
||||||
@unittest.skipIf(glymur.lib.openjp2._OPENJP2 is None,
|
@unittest.skipIf(glymur.lib.openjp2._OPENJP2 is None,
|
||||||
"Missing openjp2 library.")
|
"Missing openjp2 library.")
|
||||||
@unittest.skipIf(data_root is None,
|
@unittest.skipIf(data_root is None,
|
||||||
|
|
@ -1155,7 +1069,7 @@ class TestSuite(unittest.TestCase):
|
||||||
def test_NR_DEC_file_409752_jp2_40_decode(self):
|
def test_NR_DEC_file_409752_jp2_40_decode(self):
|
||||||
jfile = os.path.join(data_root,
|
jfile = os.path.join(data_root,
|
||||||
'input/nonregression/file409752.jp2')
|
'input/nonregression/file409752.jp2')
|
||||||
with self.assertRaises(IOError):
|
with self.assertRaises(RuntimeError):
|
||||||
data = Jp2k(jfile).read()
|
data = Jp2k(jfile).read()
|
||||||
|
|
||||||
@unittest.skipIf(sys.hexversion < 0x03020000,
|
@unittest.skipIf(sys.hexversion < 0x03020000,
|
||||||
|
|
@ -7418,5 +7332,615 @@ class TestSuiteDump(unittest.TestCase):
|
||||||
self.assertEqual(c.segment[3]._exponent,
|
self.assertEqual(c.segment[3]._exponent,
|
||||||
[8, 9, 9, 10, 9, 9, 10, 9, 9, 10, 9, 9, 10, 9, 9, 10])
|
[8, 9, 9, 10, 9, 9, 10, 9, 9, 10, 9, 9, 10, 9, 9, 10])
|
||||||
|
|
||||||
|
|
||||||
|
@unittest.skipIf(glymur.lib.openjpeg._OPENJPEG is None,
|
||||||
|
"Missing openjpeg library.")
|
||||||
|
@unittest.skipIf(data_root is None,
|
||||||
|
"OPJ_DATA_ROOT environment variable not set")
|
||||||
|
class TestSuite15(unittest.TestCase):
|
||||||
|
"""Suite of tests for libopenjpeg 1.5.1"""
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def setUpClass(cls):
|
||||||
|
# Monkey patch the package so as to use OPENJPEG instead of OPENJP2
|
||||||
|
cls.openjp2 = glymur.lib.openjp2._OPENJP2
|
||||||
|
glymur.lib.openjp2._OPENJP2 = None
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def tearDownClass(cls):
|
||||||
|
# Restore OPENJP2
|
||||||
|
glymur.lib.openjp2._OPENJP2 = cls.openjp2
|
||||||
|
|
||||||
|
def setUp(self):
|
||||||
|
pass
|
||||||
|
|
||||||
|
def tearDown(self):
|
||||||
|
pass
|
||||||
|
|
||||||
|
def test_ETS_C0P0_p0_01_j2k(self):
|
||||||
|
jfile = os.path.join(data_root, 'input/conformance/p0_01.j2k')
|
||||||
|
jp2k = Jp2k(jfile)
|
||||||
|
jpdata = jp2k.read(reduce=0)
|
||||||
|
|
||||||
|
pgxfile = os.path.join(data_root, 'baseline/conformance/c0p0_01.pgx')
|
||||||
|
pgxdata = read_pgx(pgxfile)
|
||||||
|
np.testing.assert_array_equal(jpdata, pgxdata)
|
||||||
|
|
||||||
|
def test_ETS_C0P0_p0_02_j2k(self):
|
||||||
|
jfile = os.path.join(data_root, 'input/conformance/p0_02.j2k')
|
||||||
|
with warnings.catch_warnings():
|
||||||
|
# There's a 0xff30 marker segment. Not illegal, but we don't
|
||||||
|
# really know what to do with it. Just ignore.
|
||||||
|
warnings.simplefilter("ignore")
|
||||||
|
jp2k = Jp2k(jfile)
|
||||||
|
jpdata = jp2k.read(reduce=0)
|
||||||
|
|
||||||
|
pgxfile = os.path.join(data_root, 'baseline/conformance/c0p0_02.pgx')
|
||||||
|
pgxdata = read_pgx(pgxfile)
|
||||||
|
np.testing.assert_array_equal(jpdata, pgxdata)
|
||||||
|
|
||||||
|
def test_ETS_C0P0_p0_09_j2k(self):
|
||||||
|
jfile = os.path.join(data_root, 'input/conformance/p0_09.j2k')
|
||||||
|
jp2k = Jp2k(jfile)
|
||||||
|
jpdata = jp2k.read(reduce=2)
|
||||||
|
|
||||||
|
pgxfile = os.path.join(data_root,
|
||||||
|
'baseline/conformance/c0p0_09.pgx')
|
||||||
|
pgxdata = read_pgx(pgxfile)
|
||||||
|
|
||||||
|
self.assertTrue(peak_tolerance(jpdata, pgxdata) < 4)
|
||||||
|
self.assertTrue(mse(jpdata, pgxdata) < 1.47)
|
||||||
|
|
||||||
|
def test_ETS_C0P0_p0_11_j2k(self):
|
||||||
|
jfile = os.path.join(data_root, 'input/conformance/p0_11.j2k')
|
||||||
|
jp2k = Jp2k(jfile)
|
||||||
|
jpdata = jp2k.read(reduce=0)
|
||||||
|
|
||||||
|
pgxfile = os.path.join(data_root,
|
||||||
|
'baseline/conformance/c0p0_11.pgx')
|
||||||
|
pgxdata = read_pgx(pgxfile)
|
||||||
|
|
||||||
|
np.testing.assert_array_equal(jpdata, pgxdata)
|
||||||
|
|
||||||
|
@unittest.skip("fprintf stderr output in r2343.")
|
||||||
|
def test_ETS_C0P0_p0_12_j2k(self):
|
||||||
|
jfile = os.path.join(data_root, 'input/conformance/p0_12.j2k')
|
||||||
|
jp2k = Jp2k(jfile)
|
||||||
|
jpdata = jp2k.read(reduce=0)
|
||||||
|
|
||||||
|
pgxfile = os.path.join(data_root,
|
||||||
|
'baseline/conformance/c0p0_12.pgx')
|
||||||
|
pgxdata = read_pgx(pgxfile)
|
||||||
|
|
||||||
|
np.testing.assert_array_equal(jpdata, pgxdata)
|
||||||
|
|
||||||
|
def test_ETS_C0P0_p0_16_j2k(self):
|
||||||
|
jfile = os.path.join(data_root, 'input/conformance/p0_16.j2k')
|
||||||
|
jp2k = Jp2k(jfile)
|
||||||
|
jpdata = jp2k.read(reduce=0)
|
||||||
|
|
||||||
|
pgxfile = os.path.join(data_root,
|
||||||
|
'baseline/conformance/c0p0_16.pgx')
|
||||||
|
pgxdata = read_pgx(pgxfile)
|
||||||
|
|
||||||
|
np.testing.assert_array_equal(jpdata, pgxdata)
|
||||||
|
|
||||||
|
def test_ETS_C0P1_p1_01_j2k(self):
|
||||||
|
jfile = os.path.join(data_root, 'input/conformance/p1_01.j2k')
|
||||||
|
jp2k = Jp2k(jfile)
|
||||||
|
jpdata = jp2k.read(reduce=0)
|
||||||
|
|
||||||
|
pgxfile = os.path.join(data_root,
|
||||||
|
'baseline/conformance/c0p1_01.pgx')
|
||||||
|
pgxdata = read_pgx(pgxfile)
|
||||||
|
|
||||||
|
np.testing.assert_array_equal(jpdata, pgxdata)
|
||||||
|
|
||||||
|
def test_ETS_C1P0_p0_01_j2k(self):
|
||||||
|
jfile = os.path.join(data_root, 'input/conformance/p0_01.j2k')
|
||||||
|
jp2k = Jp2k(jfile)
|
||||||
|
jpdata = jp2k.read(reduce=0)
|
||||||
|
|
||||||
|
pgxfile = os.path.join(data_root, 'baseline/conformance/c1p0_01_0.pgx')
|
||||||
|
pgxdata = read_pgx(pgxfile)
|
||||||
|
|
||||||
|
np.testing.assert_array_equal(jpdata, pgxdata)
|
||||||
|
|
||||||
|
def test_ETS_C1P0_p0_02_j2k(self):
|
||||||
|
jfile = os.path.join(data_root, 'input/conformance/p0_02.j2k')
|
||||||
|
with warnings.catch_warnings():
|
||||||
|
# There's a 0xff30 marker segment. Not illegal, but we don't
|
||||||
|
# really know what to do with it. Just ignore.
|
||||||
|
warnings.simplefilter("ignore")
|
||||||
|
jp2k = Jp2k(jfile)
|
||||||
|
jpdata = jp2k.read(reduce=0)
|
||||||
|
|
||||||
|
pgxfile = os.path.join(data_root, 'baseline/conformance/c1p0_02_0.pgx')
|
||||||
|
pgxdata = read_pgx(pgxfile)
|
||||||
|
|
||||||
|
np.testing.assert_array_equal(jpdata, pgxdata)
|
||||||
|
|
||||||
|
def test_ETS_C1P0_p0_03_j2k(self):
|
||||||
|
jfile = os.path.join(data_root, 'input/conformance/p0_03.j2k')
|
||||||
|
jp2k = Jp2k(jfile)
|
||||||
|
jpdata = jp2k.read(reduce=0)
|
||||||
|
|
||||||
|
pgxfile = os.path.join(data_root, 'baseline/conformance/c1p0_03_0.pgx')
|
||||||
|
pgxdata = read_pgx(pgxfile)
|
||||||
|
|
||||||
|
np.testing.assert_array_equal(jpdata, pgxdata)
|
||||||
|
|
||||||
|
def test_ETS_C1P0_p0_04_j2k(self):
|
||||||
|
jfile = os.path.join(data_root, 'input/conformance/p0_04.j2k')
|
||||||
|
jp2k = Jp2k(jfile)
|
||||||
|
jpdata = jp2k.read(reduce=0)
|
||||||
|
|
||||||
|
pgxfile = os.path.join(data_root, 'baseline/conformance/c1p0_04_0.pgx')
|
||||||
|
pgxdata = read_pgx(pgxfile)
|
||||||
|
self.assertTrue(peak_tolerance(jpdata[:, :, 0], pgxdata) < 5)
|
||||||
|
self.assertTrue(mse(jpdata[:, :, 0], pgxdata) < 0.776)
|
||||||
|
|
||||||
|
pgxfile = os.path.join(data_root, 'baseline/conformance/c1p0_04_1.pgx')
|
||||||
|
pgxdata = read_pgx(pgxfile)
|
||||||
|
self.assertTrue(peak_tolerance(jpdata[:, :, 1], pgxdata) < 4)
|
||||||
|
self.assertTrue(mse(jpdata[:, :, 1], pgxdata) < 0.626)
|
||||||
|
|
||||||
|
pgxfile = os.path.join(data_root, 'baseline/conformance/c1p0_04_2.pgx')
|
||||||
|
pgxdata = read_pgx(pgxfile)
|
||||||
|
self.assertTrue(peak_tolerance(jpdata[:, :, 2], pgxdata) < 6)
|
||||||
|
self.assertTrue(mse(jpdata[:, :, 2], pgxdata) < 1.07)
|
||||||
|
|
||||||
|
def test_ETS_C1P0_p0_08_j2k(self):
|
||||||
|
jfile = os.path.join(data_root, 'input/conformance/p0_08.j2k')
|
||||||
|
jp2k = Jp2k(jfile)
|
||||||
|
jpdata = jp2k.read(reduce=1)
|
||||||
|
|
||||||
|
pgxfile = os.path.join(data_root, 'baseline/conformance/c1p0_08_0.pgx')
|
||||||
|
pgxdata = read_pgx(pgxfile)
|
||||||
|
np.testing.assert_array_equal(jpdata[:, :, 0], pgxdata)
|
||||||
|
|
||||||
|
pgxfile = os.path.join(data_root, 'baseline/conformance/c1p0_08_1.pgx')
|
||||||
|
pgxdata = read_pgx(pgxfile)
|
||||||
|
np.testing.assert_array_equal(jpdata[:, :, 1], pgxdata)
|
||||||
|
|
||||||
|
pgxfile = os.path.join(data_root, 'baseline/conformance/c1p0_08_2.pgx')
|
||||||
|
pgxdata = read_pgx(pgxfile)
|
||||||
|
np.testing.assert_array_equal(jpdata[:, :, 2], pgxdata)
|
||||||
|
|
||||||
|
def test_ETS_C1P0_p0_09_j2k(self):
|
||||||
|
jfile = os.path.join(data_root, 'input/conformance/p0_09.j2k')
|
||||||
|
jp2k = Jp2k(jfile)
|
||||||
|
jpdata = jp2k.read(reduce=0)
|
||||||
|
|
||||||
|
pgxfile = os.path.join(data_root, 'baseline/conformance/c1p0_09_0.pgx')
|
||||||
|
pgxdata = read_pgx(pgxfile)
|
||||||
|
np.testing.assert_array_equal(jpdata, pgxdata)
|
||||||
|
|
||||||
|
def test_ETS_C1P0_p0_10_j2k(self):
|
||||||
|
jfile = os.path.join(data_root, 'input/conformance/p0_10.j2k')
|
||||||
|
jp2k = Jp2k(jfile)
|
||||||
|
with warnings.catch_warnings():
|
||||||
|
# This file has an invalid ICC profile
|
||||||
|
warnings.simplefilter("ignore")
|
||||||
|
jpdata = jp2k.read(reduce=0)
|
||||||
|
|
||||||
|
pgxfile = os.path.join(data_root, 'baseline/conformance/c1p0_10_0.pgx')
|
||||||
|
pgxdata = read_pgx(pgxfile)
|
||||||
|
np.testing.assert_array_equal(jpdata[:, :, 0], pgxdata)
|
||||||
|
|
||||||
|
pgxfile = os.path.join(data_root, 'baseline/conformance/c1p0_10_1.pgx')
|
||||||
|
pgxdata = read_pgx(pgxfile)
|
||||||
|
np.testing.assert_array_equal(jpdata[:, :, 1], pgxdata)
|
||||||
|
|
||||||
|
pgxfile = os.path.join(data_root, 'baseline/conformance/c1p0_10_2.pgx')
|
||||||
|
pgxdata = read_pgx(pgxfile)
|
||||||
|
np.testing.assert_array_equal(jpdata[:, :, 2], pgxdata)
|
||||||
|
|
||||||
|
def test_ETS_C1P0_p0_11_j2k(self):
|
||||||
|
jfile = os.path.join(data_root, 'input/conformance/p0_11.j2k')
|
||||||
|
jp2k = Jp2k(jfile)
|
||||||
|
jpdata = jp2k.read(reduce=0)
|
||||||
|
|
||||||
|
pgxfile = os.path.join(data_root, 'baseline/conformance/c1p0_11_0.pgx')
|
||||||
|
pgxdata = read_pgx(pgxfile)
|
||||||
|
np.testing.assert_array_equal(jpdata, pgxdata)
|
||||||
|
|
||||||
|
@unittest.skip("fprintf stderr output in r2343.")
|
||||||
|
def test_ETS_C1P0_p0_12_j2k(self):
|
||||||
|
jfile = os.path.join(data_root, 'input/conformance/p0_12.j2k')
|
||||||
|
jp2k = Jp2k(jfile)
|
||||||
|
jpdata = jp2k.read(reduce=0)
|
||||||
|
|
||||||
|
pgxfile = os.path.join(data_root, 'baseline/conformance/c1p0_12_0.pgx')
|
||||||
|
pgxdata = read_pgx(pgxfile)
|
||||||
|
np.testing.assert_array_equal(jpdata, pgxdata)
|
||||||
|
|
||||||
|
@unittest.skip("fprintf stderr output in r2343.")
|
||||||
|
def test_ETS_C1P0_p0_13_j2k(self):
|
||||||
|
jfile = os.path.join(data_root, 'input/conformance/p0_13.j2k')
|
||||||
|
jp2k = Jp2k(jfile)
|
||||||
|
jpdata = jp2k.read(reduce=0)
|
||||||
|
|
||||||
|
pgxfile = os.path.join(data_root, 'baseline/conformance/c1p0_13_0.pgx')
|
||||||
|
pgxdata = read_pgx(pgxfile)
|
||||||
|
np.testing.assert_array_equal(jpdata[:, :, 0], pgxdata)
|
||||||
|
|
||||||
|
pgxfile = os.path.join(data_root, 'baseline/conformance/c1p0_13_1.pgx')
|
||||||
|
pgxdata = read_pgx(pgxfile)
|
||||||
|
np.testing.assert_array_equal(jpdata[:, :, 1], pgxdata)
|
||||||
|
|
||||||
|
pgxfile = os.path.join(data_root, 'baseline/conformance/c1p0_13_2.pgx')
|
||||||
|
pgxdata = read_pgx(pgxfile)
|
||||||
|
np.testing.assert_array_equal(jpdata[:, :, 2], pgxdata)
|
||||||
|
|
||||||
|
pgxfile = os.path.join(data_root, 'baseline/conformance/c1p0_13_3.pgx')
|
||||||
|
pgxdata = read_pgx(pgxfile)
|
||||||
|
np.testing.assert_array_equal(jpdata[:, :, 3], pgxdata)
|
||||||
|
|
||||||
|
def test_ETS_C1P0_p0_14_j2k(self):
|
||||||
|
jfile = os.path.join(data_root, 'input/conformance/p0_14.j2k')
|
||||||
|
jp2k = Jp2k(jfile)
|
||||||
|
jpdata = jp2k.read(reduce=0)
|
||||||
|
|
||||||
|
pgxfile = os.path.join(data_root, 'baseline/conformance/c1p0_14_0.pgx')
|
||||||
|
pgxdata = read_pgx(pgxfile)
|
||||||
|
np.testing.assert_array_equal(jpdata[:, :, 0], pgxdata)
|
||||||
|
|
||||||
|
pgxfile = os.path.join(data_root, 'baseline/conformance/c1p0_14_1.pgx')
|
||||||
|
pgxdata = read_pgx(pgxfile)
|
||||||
|
np.testing.assert_array_equal(jpdata[:, :, 1], pgxdata)
|
||||||
|
|
||||||
|
pgxfile = os.path.join(data_root, 'baseline/conformance/c1p0_14_2.pgx')
|
||||||
|
pgxdata = read_pgx(pgxfile)
|
||||||
|
np.testing.assert_array_equal(jpdata[:, :, 2], pgxdata)
|
||||||
|
|
||||||
|
def test_ETS_C1P0_p0_15_j2k(self):
|
||||||
|
jfile = os.path.join(data_root, 'input/conformance/p0_15.j2k')
|
||||||
|
jp2k = Jp2k(jfile)
|
||||||
|
jpdata = jp2k.read(reduce=0)
|
||||||
|
|
||||||
|
pgxfile = os.path.join(data_root, 'baseline/conformance/c1p0_15_0.pgx')
|
||||||
|
pgxdata = read_pgx(pgxfile)
|
||||||
|
np.testing.assert_array_equal(jpdata, pgxdata)
|
||||||
|
|
||||||
|
def test_ETS_C1P0_p0_16_j2k(self):
|
||||||
|
jfile = os.path.join(data_root, 'input/conformance/p0_16.j2k')
|
||||||
|
jp2k = Jp2k(jfile)
|
||||||
|
jpdata = jp2k.read(reduce=0)
|
||||||
|
|
||||||
|
pgxfile = os.path.join(data_root, 'baseline/conformance/c1p0_16_0.pgx')
|
||||||
|
pgxdata = read_pgx(pgxfile)
|
||||||
|
np.testing.assert_array_equal(jpdata, pgxdata)
|
||||||
|
|
||||||
|
def test_ETS_C1P1_p1_01_j2k(self):
|
||||||
|
jfile = os.path.join(data_root, 'input/conformance/p1_01.j2k')
|
||||||
|
jp2k = Jp2k(jfile)
|
||||||
|
jpdata = jp2k.read(reduce=0)
|
||||||
|
|
||||||
|
pgxfile = os.path.join(data_root, 'baseline/conformance/c1p1_01_0.pgx')
|
||||||
|
pgxdata = read_pgx(pgxfile)
|
||||||
|
np.testing.assert_array_equal(jpdata, pgxdata)
|
||||||
|
|
||||||
|
def test_ETS_C1P1_p1_02_j2k(self):
|
||||||
|
jfile = os.path.join(data_root, 'input/conformance/p1_02.j2k')
|
||||||
|
jp2k = Jp2k(jfile)
|
||||||
|
jpdata = jp2k.read(reduce=0)
|
||||||
|
|
||||||
|
pgxfile = os.path.join(data_root, 'baseline/conformance/c1p1_02_0.pgx')
|
||||||
|
pgxdata = read_pgx(pgxfile)
|
||||||
|
self.assertTrue(peak_tolerance(jpdata[:, :, 0], pgxdata) < 5)
|
||||||
|
self.assertTrue(mse(jpdata[:, :, 0], pgxdata) < 0.765)
|
||||||
|
|
||||||
|
pgxfile = os.path.join(data_root, 'baseline/conformance/c1p1_02_1.pgx')
|
||||||
|
pgxdata = read_pgx(pgxfile)
|
||||||
|
self.assertTrue(peak_tolerance(jpdata[:, :, 1], pgxdata) < 4)
|
||||||
|
self.assertTrue(mse(jpdata[:, :, 1], pgxdata) < 0.616)
|
||||||
|
|
||||||
|
pgxfile = os.path.join(data_root, 'baseline/conformance/c1p1_02_2.pgx')
|
||||||
|
pgxdata = read_pgx(pgxfile)
|
||||||
|
self.assertTrue(peak_tolerance(jpdata[:, :, 2], pgxdata) < 6)
|
||||||
|
self.assertTrue(mse(jpdata[:, :, 2], pgxdata) < 1.051)
|
||||||
|
|
||||||
|
def test_ETS_C1P1_p1_04_j2k(self):
|
||||||
|
jfile = os.path.join(data_root, 'input/conformance/p1_04.j2k')
|
||||||
|
jp2k = Jp2k(jfile)
|
||||||
|
jpdata = jp2k.read()
|
||||||
|
|
||||||
|
pgxfile = os.path.join(data_root, 'baseline/conformance/c1p1_04_0.pgx')
|
||||||
|
pgxdata = read_pgx(pgxfile)
|
||||||
|
self.assertTrue(peak_tolerance(jpdata, pgxdata) < 624)
|
||||||
|
self.assertTrue(mse(jpdata, pgxdata) < 3080)
|
||||||
|
|
||||||
|
@unittest.skip("fprintf stderr output in r2343.")
|
||||||
|
def test_ETS_C1P1_p1_05_j2k(self):
|
||||||
|
jfile = os.path.join(data_root, 'input/conformance/p1_05.j2k')
|
||||||
|
jp2k = Jp2k(jfile)
|
||||||
|
jpdata = jp2k.read()
|
||||||
|
|
||||||
|
pgxfile = os.path.join(data_root, 'baseline/conformance/c1p1_05_0.pgx')
|
||||||
|
pgxdata = read_pgx(pgxfile)
|
||||||
|
self.assertTrue(peak_tolerance(jpdata[:, :, 0], pgxdata) < 40)
|
||||||
|
self.assertTrue(mse(jpdata[:, :, 0], pgxdata) < 8.458)
|
||||||
|
|
||||||
|
pgxfile = os.path.join(data_root, 'baseline/conformance/c1p1_05_1.pgx')
|
||||||
|
pgxdata = read_pgx(pgxfile)
|
||||||
|
self.assertTrue(peak_tolerance(jpdata[:, :, 1], pgxdata) < 40)
|
||||||
|
self.assertTrue(mse(jpdata[:, :, 1], pgxdata) < 9.816)
|
||||||
|
|
||||||
|
pgxfile = os.path.join(data_root, 'baseline/conformance/c1p1_05_2.pgx')
|
||||||
|
pgxdata = read_pgx(pgxfile)
|
||||||
|
self.assertTrue(peak_tolerance(jpdata[:, :, 2], pgxdata) < 40)
|
||||||
|
self.assertTrue(mse(jpdata[:, :, 2], pgxdata) < 10.154)
|
||||||
|
|
||||||
|
@unittest.skip("fprintf stderr output in r2343.")
|
||||||
|
def test_ETS_C1P1_p1_06_j2k(self):
|
||||||
|
jfile = os.path.join(data_root, 'input/conformance/p1_06.j2k')
|
||||||
|
jp2k = Jp2k(jfile)
|
||||||
|
jpdata = jp2k.read()
|
||||||
|
|
||||||
|
pgxfile = os.path.join(data_root, 'baseline/conformance/c1p1_06_0.pgx')
|
||||||
|
pgxdata = read_pgx(pgxfile)
|
||||||
|
self.assertTrue(peak_tolerance(jpdata[:, :, 0], pgxdata) < 2)
|
||||||
|
self.assertTrue(mse(jpdata[:, :, 0], pgxdata) < 0.6)
|
||||||
|
|
||||||
|
pgxfile = os.path.join(data_root, 'baseline/conformance/c1p1_06_1.pgx')
|
||||||
|
pgxdata = read_pgx(pgxfile)
|
||||||
|
self.assertTrue(peak_tolerance(jpdata[:, :, 1], pgxdata) < 2)
|
||||||
|
self.assertTrue(mse(jpdata[:, :, 1], pgxdata) < 0.6)
|
||||||
|
|
||||||
|
pgxfile = os.path.join(data_root, 'baseline/conformance/c1p1_06_2.pgx')
|
||||||
|
pgxdata = read_pgx(pgxfile)
|
||||||
|
self.assertTrue(peak_tolerance(jpdata[:, :, 2], pgxdata) < 2)
|
||||||
|
self.assertTrue(mse(jpdata[:, :, 2], pgxdata) < 0.6)
|
||||||
|
|
||||||
|
def test_ETS_JP2_file1(self):
|
||||||
|
jfile = os.path.join(data_root, 'input/conformance/file1.jp2')
|
||||||
|
jp2k = Jp2k(jfile)
|
||||||
|
jpdata = jp2k.read()
|
||||||
|
self.assertEqual(jpdata.shape, (512, 768, 3))
|
||||||
|
|
||||||
|
def test_ETS_JP2_file2(self):
|
||||||
|
jfile = os.path.join(data_root, 'input/conformance/file2.jp2')
|
||||||
|
jp2k = Jp2k(jfile)
|
||||||
|
jpdata = jp2k.read()
|
||||||
|
self.assertEqual(jpdata.shape, (640, 480, 3))
|
||||||
|
|
||||||
|
def test_ETS_JP2_file4(self):
|
||||||
|
jfile = os.path.join(data_root, 'input/conformance/file4.jp2')
|
||||||
|
jp2k = Jp2k(jfile)
|
||||||
|
jpdata = jp2k.read()
|
||||||
|
self.assertEqual(jpdata.shape, (512, 768))
|
||||||
|
|
||||||
|
def test_ETS_JP2_file5(self):
|
||||||
|
jfile = os.path.join(data_root, 'input/conformance/file5.jp2')
|
||||||
|
jp2k = Jp2k(jfile)
|
||||||
|
jpdata = jp2k.read()
|
||||||
|
self.assertEqual(jpdata.shape, (512, 768, 3))
|
||||||
|
|
||||||
|
def test_ETS_JP2_file6(self):
|
||||||
|
jfile = os.path.join(data_root, 'input/conformance/file6.jp2')
|
||||||
|
jp2k = Jp2k(jfile)
|
||||||
|
jpdata = jp2k.read()
|
||||||
|
self.assertEqual(jpdata.shape, (512, 768))
|
||||||
|
|
||||||
|
def test_ETS_JP2_file7(self):
|
||||||
|
jfile = os.path.join(data_root, 'input/conformance/file7.jp2')
|
||||||
|
jp2k = Jp2k(jfile)
|
||||||
|
jpdata = jp2k.read()
|
||||||
|
self.assertEqual(jpdata.shape, (640, 480, 3))
|
||||||
|
|
||||||
|
def test_ETS_JP2_file8(self):
|
||||||
|
jfile = os.path.join(data_root, 'input/conformance/file8.jp2')
|
||||||
|
jp2k = Jp2k(jfile)
|
||||||
|
jpdata = jp2k.read()
|
||||||
|
self.assertEqual(jpdata.shape, (400, 700))
|
||||||
|
|
||||||
|
def test_ETS_JP2_file9(self):
|
||||||
|
jfile = os.path.join(data_root, 'input/conformance/file9.jp2')
|
||||||
|
jp2k = Jp2k(jfile)
|
||||||
|
jpdata = jp2k.read()
|
||||||
|
self.assertEqual(jpdata.shape, (512, 768, 3))
|
||||||
|
|
||||||
|
def test_NR_DEC_Bretagne2_j2k_1_decode(self):
|
||||||
|
jfile = os.path.join(data_root,
|
||||||
|
'input/nonregression/Bretagne2.j2k')
|
||||||
|
jp2 = Jp2k(jfile)
|
||||||
|
data = jp2.read()
|
||||||
|
self.assertTrue(True)
|
||||||
|
|
||||||
|
def test_NR_DEC__00042_j2k_2_decode(self):
|
||||||
|
jfile = os.path.join(data_root,
|
||||||
|
'input/nonregression/_00042.j2k')
|
||||||
|
jp2 = Jp2k(jfile)
|
||||||
|
data = jp2.read()
|
||||||
|
self.assertTrue(True)
|
||||||
|
|
||||||
|
@unittest.skip("fprintf stderr output in r2343.")
|
||||||
|
def test_NR_DEC_123_j2c_3_decode(self):
|
||||||
|
jfile = os.path.join(data_root,
|
||||||
|
'input/nonregression/123.j2c')
|
||||||
|
jp2 = Jp2k(jfile)
|
||||||
|
data = jp2.read()
|
||||||
|
self.assertTrue(True)
|
||||||
|
|
||||||
|
@unittest.skipIf(sys.hexversion < 0x03020000,
|
||||||
|
"Uses features introduced in 3.2.")
|
||||||
|
def test_NR_DEC_broken_jp2_4_decode(self):
|
||||||
|
jfile = os.path.join(data_root,
|
||||||
|
'input/nonregression/broken.jp2')
|
||||||
|
with self.assertWarns(UserWarning) as cw:
|
||||||
|
# colr box has bad length.
|
||||||
|
jp2 = Jp2k(jfile)
|
||||||
|
with self.assertRaises(ValueError):
|
||||||
|
data = jp2.read()
|
||||||
|
self.assertTrue(True)
|
||||||
|
|
||||||
|
def test_NR_DEC_broken2_jp2_5_decode(self):
|
||||||
|
jfile = os.path.join(data_root,
|
||||||
|
'input/nonregression/broken2.jp2')
|
||||||
|
with self.assertRaises(IOError):
|
||||||
|
data = Jp2k(jfile).read()
|
||||||
|
self.assertTrue(True)
|
||||||
|
|
||||||
|
@unittest.skipIf(sys.hexversion < 0x03020000,
|
||||||
|
"Uses features introduced in 3.2.")
|
||||||
|
def test_NR_DEC_broken3_jp2_6_decode(self):
|
||||||
|
jfile = os.path.join(data_root,
|
||||||
|
'input/nonregression/broken3.jp2')
|
||||||
|
with self.assertWarns(UserWarning) as cw:
|
||||||
|
# colr box has bad length.
|
||||||
|
j = Jp2k(jfile)
|
||||||
|
|
||||||
|
with self.assertRaises(ValueError) as ce:
|
||||||
|
d = j.read()
|
||||||
|
|
||||||
|
def test_NR_DEC_broken4_jp2_7_decode(self):
|
||||||
|
jfile = os.path.join(data_root,
|
||||||
|
'input/nonregression/broken4.jp2')
|
||||||
|
with self.assertRaises(IOError):
|
||||||
|
data = Jp2k(jfile).read()
|
||||||
|
self.assertTrue(True)
|
||||||
|
|
||||||
|
@unittest.skip("fprintf stderr output in r2343.")
|
||||||
|
def test_NR_DEC_bug_j2c_8_decode(self):
|
||||||
|
jfile = os.path.join(data_root,
|
||||||
|
'input/nonregression/bug.j2c')
|
||||||
|
data = Jp2k(jfile).read()
|
||||||
|
self.assertTrue(True)
|
||||||
|
|
||||||
|
def test_NR_DEC_buxI_j2k_9_decode(self):
|
||||||
|
jfile = os.path.join(data_root,
|
||||||
|
'input/nonregression/buxI.j2k')
|
||||||
|
data = Jp2k(jfile).read()
|
||||||
|
self.assertTrue(True)
|
||||||
|
|
||||||
|
def test_NR_DEC_buxR_j2k_10_decode(self):
|
||||||
|
jfile = os.path.join(data_root,
|
||||||
|
'input/nonregression/buxR.j2k')
|
||||||
|
data = Jp2k(jfile).read()
|
||||||
|
self.assertTrue(True)
|
||||||
|
|
||||||
|
def test_NR_DEC_Cannotreaddatawithnosizeknown_j2k_11_decode(self):
|
||||||
|
relpath = 'input/nonregression/Cannotreaddatawithnosizeknown.j2k'
|
||||||
|
jfile = os.path.join(data_root, relpath)
|
||||||
|
data = Jp2k(jfile).read()
|
||||||
|
self.assertTrue(True)
|
||||||
|
|
||||||
|
def test_NR_DEC_cthead1_j2k_12_decode(self):
|
||||||
|
jfile = os.path.join(data_root,
|
||||||
|
'input/nonregression/cthead1.j2k')
|
||||||
|
data = Jp2k(jfile).read()
|
||||||
|
self.assertTrue(True)
|
||||||
|
|
||||||
|
def test_NR_DEC_CT_Phillips_JPEG2K_Decompr_Problem_j2k_13_decode(self):
|
||||||
|
relpath = 'input/nonregression/CT_Phillips_JPEG2K_Decompr_Problem.j2k'
|
||||||
|
jfile = os.path.join(data_root, relpath)
|
||||||
|
data = Jp2k(jfile).read()
|
||||||
|
self.assertTrue(True)
|
||||||
|
|
||||||
|
@unittest.skip("fprintf stderr output in r2343.")
|
||||||
|
def test_NR_DEC_illegalcolortransform_j2k_14_decode(self):
|
||||||
|
# Stream too short, expected SOT.
|
||||||
|
jfile = os.path.join(data_root,
|
||||||
|
'input/nonregression/illegalcolortransform.j2k')
|
||||||
|
data = Jp2k(jfile).read()
|
||||||
|
self.assertTrue(True)
|
||||||
|
|
||||||
|
def test_NR_DEC_j2k32_j2k_15_decode(self):
|
||||||
|
jfile = os.path.join(data_root,
|
||||||
|
'input/nonregression/j2k32.j2k')
|
||||||
|
data = Jp2k(jfile).read()
|
||||||
|
self.assertTrue(True)
|
||||||
|
|
||||||
|
def test_NR_DEC_kakadu_v4_4_openjpegv2_broken_j2k_16_decode(self):
|
||||||
|
relpath = 'input/nonregression/kakadu_v4-4_openjpegv2_broken.j2k'
|
||||||
|
jfile = os.path.join(data_root, relpath)
|
||||||
|
with warnings.catch_warnings():
|
||||||
|
# This file has an invalid ICC profile
|
||||||
|
warnings.simplefilter("ignore")
|
||||||
|
data = Jp2k(jfile).read()
|
||||||
|
self.assertTrue(True)
|
||||||
|
|
||||||
|
def test_NR_DEC_MarkerIsNotCompliant_j2k_17_decode(self):
|
||||||
|
jfile = os.path.join(data_root,
|
||||||
|
'input/nonregression/MarkerIsNotCompliant.j2k')
|
||||||
|
data = Jp2k(jfile).read()
|
||||||
|
self.assertTrue(True)
|
||||||
|
|
||||||
|
def test_NR_DEC_Marrin_jp2_18_decode(self):
|
||||||
|
jfile = os.path.join(data_root,
|
||||||
|
'input/nonregression/Marrin.jp2')
|
||||||
|
data = Jp2k(jfile).read()
|
||||||
|
self.assertTrue(True)
|
||||||
|
|
||||||
|
def test_NR_DEC_movie_00000_j2k_20_decode(self):
|
||||||
|
jfile = os.path.join(data_root,
|
||||||
|
'input/nonregression/movie_00000.j2k')
|
||||||
|
data = Jp2k(jfile).read()
|
||||||
|
self.assertTrue(True)
|
||||||
|
|
||||||
|
def test_NR_DEC_movie_00001_j2k_21_decode(self):
|
||||||
|
jfile = os.path.join(data_root,
|
||||||
|
'input/nonregression/movie_00001.j2k')
|
||||||
|
data = Jp2k(jfile).read()
|
||||||
|
self.assertTrue(True)
|
||||||
|
|
||||||
|
def test_NR_DEC_movie_00002_j2k_22_decode(self):
|
||||||
|
jfile = os.path.join(data_root,
|
||||||
|
'input/nonregression/movie_00002.j2k')
|
||||||
|
data = Jp2k(jfile).read()
|
||||||
|
self.assertTrue(True)
|
||||||
|
|
||||||
|
def test_NR_DEC_orb_blue_lin_j2k_j2k_23_decode(self):
|
||||||
|
jfile = os.path.join(data_root,
|
||||||
|
'input/nonregression/orb-blue10-lin-j2k.j2k')
|
||||||
|
data = Jp2k(jfile).read()
|
||||||
|
self.assertTrue(True)
|
||||||
|
|
||||||
|
def test_NR_DEC_orb_blue_win_j2k_j2k_24_decode(self):
|
||||||
|
jfile = os.path.join(data_root,
|
||||||
|
'input/nonregression/orb-blue10-win-j2k.j2k')
|
||||||
|
data = Jp2k(jfile).read()
|
||||||
|
self.assertTrue(True)
|
||||||
|
|
||||||
|
def test_NR_DEC_orb_blue_lin_jp2_25_decode(self):
|
||||||
|
jfile = os.path.join(data_root,
|
||||||
|
'input/nonregression/orb-blue10-lin-jp2.jp2')
|
||||||
|
with warnings.catch_warnings():
|
||||||
|
# This file has an invalid ICC profile
|
||||||
|
warnings.simplefilter("ignore")
|
||||||
|
data = Jp2k(jfile).read()
|
||||||
|
self.assertTrue(True)
|
||||||
|
|
||||||
|
def test_NR_DEC_orb_blue_win_jp2_26_decode(self):
|
||||||
|
jfile = os.path.join(data_root,
|
||||||
|
'input/nonregression/orb-blue10-win-jp2.jp2')
|
||||||
|
data = Jp2k(jfile).read()
|
||||||
|
self.assertTrue(True)
|
||||||
|
|
||||||
|
def test_NR_DEC_relax_jp2_27_decode(self):
|
||||||
|
jfile = os.path.join(data_root,
|
||||||
|
'input/nonregression/relax.jp2')
|
||||||
|
data = Jp2k(jfile).read()
|
||||||
|
self.assertTrue(True)
|
||||||
|
|
||||||
|
def test_NR_DEC_test_lossless_j2k_28_decode(self):
|
||||||
|
jfile = os.path.join(data_root,
|
||||||
|
'input/nonregression/test_lossless.j2k')
|
||||||
|
data = Jp2k(jfile).read()
|
||||||
|
self.assertTrue(True)
|
||||||
|
|
||||||
|
def test_NR_DEC_issue104_jpxstream_jp2_33_decode(self):
|
||||||
|
jfile = os.path.join(data_root,
|
||||||
|
'input/nonregression/issue104_jpxstream.jp2')
|
||||||
|
data = Jp2k(jfile).read()
|
||||||
|
self.assertTrue(True)
|
||||||
|
|
||||||
|
def test_NR_DEC_file_409752_jp2_40_decode(self):
|
||||||
|
jfile = os.path.join(data_root, 'input/nonregression/file409752.jp2')
|
||||||
|
j = Jp2k(jfile)
|
||||||
|
with self.assertRaises(RuntimeError) as ce:
|
||||||
|
data = j.read()
|
||||||
|
|
||||||
if __name__ == "__main__":
|
if __name__ == "__main__":
|
||||||
unittest.main()
|
unittest.main()
|
||||||
|
|
|
||||||
|
|
@ -65,8 +65,8 @@ def read_image(infile):
|
||||||
class TestSuiteNegative(unittest.TestCase):
|
class TestSuiteNegative(unittest.TestCase):
|
||||||
|
|
||||||
def setUp(self):
|
def setUp(self):
|
||||||
self.jp2file = pkg_resources.resource_filename(glymur.__name__,
|
self.jp2file = glymur.data.nemo()
|
||||||
"data/nemo.jp2")
|
self.j2kfile = glymur.data.goodstuff()
|
||||||
|
|
||||||
def tearDown(self):
|
def tearDown(self):
|
||||||
pass
|
pass
|
||||||
|
|
@ -156,8 +156,8 @@ class TestSuiteNegative(unittest.TestCase):
|
||||||
|
|
||||||
def test_precinct_size_not_multiple_of_two(self):
|
def test_precinct_size_not_multiple_of_two(self):
|
||||||
# Seems like precinct sizes should be powers of two.
|
# Seems like precinct sizes should be powers of two.
|
||||||
ifile = Jp2k(self.jp2file)
|
ifile = Jp2k(self.j2kfile)
|
||||||
data = ifile.read(reduce=3)
|
data = ifile.read(reduce=2)
|
||||||
with tempfile.NamedTemporaryFile(suffix='.jp2') as tfile:
|
with tempfile.NamedTemporaryFile(suffix='.jp2') as tfile:
|
||||||
ofile = Jp2k(tfile.name, 'wb')
|
ofile = Jp2k(tfile.name, 'wb')
|
||||||
with self.assertRaises(IOError) as ce:
|
with self.assertRaises(IOError) as ce:
|
||||||
|
|
@ -165,8 +165,8 @@ class TestSuiteNegative(unittest.TestCase):
|
||||||
|
|
||||||
def test_codeblock_size_not_multiple_of_two(self):
|
def test_codeblock_size_not_multiple_of_two(self):
|
||||||
# Seems like code block sizes should be powers of two.
|
# Seems like code block sizes should be powers of two.
|
||||||
ifile = Jp2k(self.jp2file)
|
ifile = Jp2k(self.j2kfile)
|
||||||
data = ifile.read(reduce=3)
|
data = ifile.read(reduce=2)
|
||||||
with tempfile.NamedTemporaryFile(suffix='.jp2') as tfile:
|
with tempfile.NamedTemporaryFile(suffix='.jp2') as tfile:
|
||||||
ofile = Jp2k(tfile.name, 'wb')
|
ofile = Jp2k(tfile.name, 'wb')
|
||||||
with self.assertRaises(IOError) as ce:
|
with self.assertRaises(IOError) as ce:
|
||||||
|
|
@ -175,8 +175,8 @@ class TestSuiteNegative(unittest.TestCase):
|
||||||
def test_codeblock_size_with_precinct_size(self):
|
def test_codeblock_size_with_precinct_size(self):
|
||||||
# Seems like code block sizes should never exceed half that of
|
# Seems like code block sizes should never exceed half that of
|
||||||
# precinct size.
|
# precinct size.
|
||||||
ifile = Jp2k(self.jp2file)
|
ifile = Jp2k(self.j2kfile)
|
||||||
data = ifile.read(reduce=3)
|
data = ifile.read(reduce=2)
|
||||||
with tempfile.NamedTemporaryFile(suffix='.jp2') as tfile:
|
with tempfile.NamedTemporaryFile(suffix='.jp2') as tfile:
|
||||||
ofile = Jp2k(tfile.name, 'wb')
|
ofile = Jp2k(tfile.name, 'wb')
|
||||||
with self.assertRaises(IOError) as ce:
|
with self.assertRaises(IOError) as ce:
|
||||||
|
|
|
||||||
|
|
@ -34,7 +34,7 @@ class TestPrintingNeedsLib(unittest.TestCase):
|
||||||
with tempfile.NamedTemporaryFile(suffix='.jp2', delete=False) as tfile:
|
with tempfile.NamedTemporaryFile(suffix='.jp2', delete=False) as tfile:
|
||||||
cls._plain_nemo_file = tfile.name
|
cls._plain_nemo_file = tfile.name
|
||||||
ijfile = Jp2k(jp2file)
|
ijfile = Jp2k(jp2file)
|
||||||
data = ijfile.read(reduce=3)
|
data = ijfile.read(reduce=1)
|
||||||
ojfile = Jp2k(cls._plain_nemo_file, 'wb')
|
ojfile = Jp2k(cls._plain_nemo_file, 'wb')
|
||||||
ojfile.write(data)
|
ojfile.write(data)
|
||||||
|
|
||||||
|
|
@ -43,8 +43,9 @@ class TestPrintingNeedsLib(unittest.TestCase):
|
||||||
os.unlink(cls._plain_nemo_file)
|
os.unlink(cls._plain_nemo_file)
|
||||||
|
|
||||||
def setUp(self):
|
def setUp(self):
|
||||||
self.jp2file = pkg_resources.resource_filename(glymur.__name__,
|
self.jp2file = glymur.data.nemo()
|
||||||
"data/nemo.jp2")
|
self.j2kfile = glymur.data.goodstuff()
|
||||||
|
|
||||||
# Save sys.stdout.
|
# Save sys.stdout.
|
||||||
self.stdout = sys.stdout
|
self.stdout = sys.stdout
|
||||||
sys.stdout = StringIO()
|
sys.stdout = StringIO()
|
||||||
|
|
@ -57,7 +58,7 @@ class TestPrintingNeedsLib(unittest.TestCase):
|
||||||
" Compatibility: ['jp2 ']",
|
" Compatibility: ['jp2 ']",
|
||||||
'JP2 Header Box (jp2h) @ (32, 45)',
|
'JP2 Header Box (jp2h) @ (32, 45)',
|
||||||
' Image Header Box (ihdr) @ (40, 22)',
|
' Image Header Box (ihdr) @ (40, 22)',
|
||||||
' Size: [182 324 3]',
|
' Size: [728 1296 3]',
|
||||||
' Bitdepth: 8',
|
' Bitdepth: 8',
|
||||||
' Signed: False',
|
' Signed: False',
|
||||||
' Compression: wavelet',
|
' Compression: wavelet',
|
||||||
|
|
@ -66,15 +67,15 @@ class TestPrintingNeedsLib(unittest.TestCase):
|
||||||
' Method: enumerated colorspace',
|
' Method: enumerated colorspace',
|
||||||
' Precedence: 0',
|
' Precedence: 0',
|
||||||
' Colorspace: sRGB',
|
' Colorspace: sRGB',
|
||||||
'Contiguous Codestream Box (jp2c) @ (77, 112814)',
|
'Contiguous Codestream Box (jp2c) @ (77, 1632355)',
|
||||||
' Main header:',
|
' Main header:',
|
||||||
' SOC marker segment @ (85, 0)',
|
' SOC marker segment @ (85, 0)',
|
||||||
' SIZ marker segment @ (87, 47)',
|
' SIZ marker segment @ (87, 47)',
|
||||||
' Profile: 2',
|
' Profile: 2',
|
||||||
' Reference Grid Height, Width: (182 x 324)',
|
' Reference Grid Height, Width: (728 x 1296)',
|
||||||
' Vertical, Horizontal Reference Grid Offset: '
|
' Vertical, Horizontal Reference Grid Offset: '
|
||||||
+ '(0 x 0)',
|
+ '(0 x 0)',
|
||||||
' Reference Tile Height, Width: (182 x 324)',
|
' Reference Tile Height, Width: (728 x 1296)',
|
||||||
' Vertical, Horizontal Reference Tile Offset: '
|
' Vertical, Horizontal Reference Tile Offset: '
|
||||||
+ '(0 x 0)',
|
+ '(0 x 0)',
|
||||||
' Bitdepth: (8, 8, 8)',
|
' Bitdepth: (8, 8, 8)',
|
||||||
|
|
@ -121,7 +122,7 @@ class TestPrintingNeedsLib(unittest.TestCase):
|
||||||
def test_asoc_label_box(self):
|
def test_asoc_label_box(self):
|
||||||
# Construct a fake file with an asoc and a label box, as
|
# Construct a fake file with an asoc and a label box, as
|
||||||
# OpenJPEG doesn't have such a file.
|
# OpenJPEG doesn't have such a file.
|
||||||
data = glymur.Jp2k(self.jp2file).read(reduce=3)
|
data = glymur.Jp2k(self.jp2file).read(reduce=1)
|
||||||
with tempfile.NamedTemporaryFile(suffix='.jp2') as tfile:
|
with tempfile.NamedTemporaryFile(suffix='.jp2') as tfile:
|
||||||
j = glymur.Jp2k(tfile.name, 'wb')
|
j = glymur.Jp2k(tfile.name, 'wb')
|
||||||
j.write(data)
|
j.write(data)
|
||||||
|
|
@ -177,7 +178,7 @@ class TestPrintingNeedsLib(unittest.TestCase):
|
||||||
lst = actual.split('\n')
|
lst = actual.split('\n')
|
||||||
lst = lst[1:]
|
lst = lst[1:]
|
||||||
actual = '\n'.join(lst)
|
actual = '\n'.join(lst)
|
||||||
|
self.maxDiff = None
|
||||||
self.assertEqual(actual, self.expectedPlain)
|
self.assertEqual(actual, self.expectedPlain)
|
||||||
|
|
||||||
def test_entire_file(self):
|
def test_entire_file(self):
|
||||||
|
|
@ -209,15 +210,15 @@ class TestPrinting(unittest.TestCase):
|
||||||
def test_COC_segment(self):
|
def test_COC_segment(self):
|
||||||
j = glymur.Jp2k(self.jp2file)
|
j = glymur.Jp2k(self.jp2file)
|
||||||
codestream = j.get_codestream(header_only=False)
|
codestream = j.get_codestream(header_only=False)
|
||||||
print(codestream.segment[5])
|
print(codestream.segment[6])
|
||||||
actual = sys.stdout.getvalue().strip()
|
actual = sys.stdout.getvalue().strip()
|
||||||
|
|
||||||
lines = ['COC marker segment @ (3233, 9)',
|
lines = ['COC marker segment @ (3260, 9)',
|
||||||
' Associated component: 1',
|
' Associated component: 1',
|
||||||
' Coding style for this component: '
|
' Coding style for this component: '
|
||||||
+ 'Entropy coder, PARTITION = 0',
|
+ 'Entropy coder, PARTITION = 0',
|
||||||
' Coding style parameters:',
|
' Coding style parameters:',
|
||||||
' Number of resolutions: 6',
|
' Number of resolutions: 2',
|
||||||
' Code block height, width: (64 x 64)',
|
' Code block height, width: (64 x 64)',
|
||||||
' Wavelet transform: 5-3 reversible',
|
' Wavelet transform: 5-3 reversible',
|
||||||
' Code block context:',
|
' Code block context:',
|
||||||
|
|
@ -230,6 +231,7 @@ class TestPrinting(unittest.TestCase):
|
||||||
' Segmentation symbols: False']
|
' Segmentation symbols: False']
|
||||||
|
|
||||||
expected = '\n'.join(lines)
|
expected = '\n'.join(lines)
|
||||||
|
self.maxDiff = None
|
||||||
self.assertEqual(actual, expected)
|
self.assertEqual(actual, expected)
|
||||||
|
|
||||||
def test_COD_segment(self):
|
def test_COD_segment(self):
|
||||||
|
|
@ -245,10 +247,10 @@ class TestPrinting(unittest.TestCase):
|
||||||
' EPH marker segments: False',
|
' EPH marker segments: False',
|
||||||
' Coding style parameters:',
|
' Coding style parameters:',
|
||||||
' Progression order: LRCP',
|
' Progression order: LRCP',
|
||||||
' Number of layers: 3',
|
' Number of layers: 2',
|
||||||
' Multiple component transformation usage: '
|
' Multiple component transformation usage: '
|
||||||
+ 'reversible',
|
+ 'reversible',
|
||||||
' Number of resolutions: 6',
|
' Number of resolutions: 2',
|
||||||
' Code block height, width: (64 x 64)',
|
' Code block height, width: (64 x 64)',
|
||||||
' Wavelet transform: 5-3 reversible',
|
' Wavelet transform: 5-3 reversible',
|
||||||
' Precinct size: default, 2^15 x 2^15',
|
' Precinct size: default, 2^15 x 2^15',
|
||||||
|
|
@ -392,7 +394,7 @@ class TestPrinting(unittest.TestCase):
|
||||||
print(codestream.segment[-1])
|
print(codestream.segment[-1])
|
||||||
actual = sys.stdout.getvalue().strip()
|
actual = sys.stdout.getvalue().strip()
|
||||||
|
|
||||||
lines = ['EOC marker segment @ (1136552, 0)']
|
lines = ['EOC marker segment @ (1135421, 0)']
|
||||||
expected = '\n'.join(lines)
|
expected = '\n'.join(lines)
|
||||||
self.assertEqual(actual, expected)
|
self.assertEqual(actual, expected)
|
||||||
|
|
||||||
|
|
@ -476,15 +478,13 @@ class TestPrinting(unittest.TestCase):
|
||||||
def test_QCC_segment(self):
|
def test_QCC_segment(self):
|
||||||
j = glymur.Jp2k(self.jp2file)
|
j = glymur.Jp2k(self.jp2file)
|
||||||
codestream = j.get_codestream(header_only=False)
|
codestream = j.get_codestream(header_only=False)
|
||||||
print(codestream.segment[6])
|
print(codestream.segment[7])
|
||||||
actual = sys.stdout.getvalue().strip()
|
actual = sys.stdout.getvalue().strip()
|
||||||
|
|
||||||
lines = ['QCC marker segment @ (3244, 20)',
|
lines = ['QCC marker segment @ (3271, 8)',
|
||||||
' Associated Component: 1',
|
' Associated Component: 1',
|
||||||
' Quantization style: no quantization, 2 guard bits',
|
' Quantization style: no quantization, 2 guard bits',
|
||||||
' Step size: [(0, 8), (0, 9), (0, 9), (0, 10), (0, 9), '
|
' Step size: [(0, 8), (0, 9), (0, 9), (0, 10)]']
|
||||||
+ '(0, 9), (0, 10), (0, 9), (0, 9), (0, 10), (0, 9), (0, 9), '
|
|
||||||
+ '(0, 10), (0, 9), (0, 9), (0, 10)]']
|
|
||||||
|
|
||||||
expected = '\n'.join(lines)
|
expected = '\n'.join(lines)
|
||||||
self.assertEqual(actual, expected)
|
self.assertEqual(actual, expected)
|
||||||
|
|
@ -495,11 +495,9 @@ class TestPrinting(unittest.TestCase):
|
||||||
print(codestream.segment[3])
|
print(codestream.segment[3])
|
||||||
actual = sys.stdout.getvalue().strip()
|
actual = sys.stdout.getvalue().strip()
|
||||||
|
|
||||||
lines = ['QCD marker segment @ (3200, 19)',
|
lines = ['QCD marker segment @ (3200, 7)',
|
||||||
' Quantization style: no quantization, 2 guard bits',
|
' Quantization style: no quantization, 2 guard bits',
|
||||||
' Step size: [(0, 8), (0, 9), (0, 9), (0, 10), (0, 9), '
|
' Step size: [(0, 8), (0, 9), (0, 9), (0, 10)]']
|
||||||
+ '(0, 9), (0, 10), (0, 9), (0, 9), (0, 10), (0, 9), '
|
|
||||||
+ '(0, 9), (0, 10), (0, 9), (0, 9), (0, 10)]']
|
|
||||||
|
|
||||||
expected = '\n'.join(lines)
|
expected = '\n'.join(lines)
|
||||||
self.assertEqual(actual, expected)
|
self.assertEqual(actual, expected)
|
||||||
|
|
@ -514,7 +512,7 @@ class TestPrinting(unittest.TestCase):
|
||||||
' Profile: 2',
|
' Profile: 2',
|
||||||
' Reference Grid Height, Width: (1456 x 2592)',
|
' Reference Grid Height, Width: (1456 x 2592)',
|
||||||
' Vertical, Horizontal Reference Grid Offset: (0 x 0)',
|
' Vertical, Horizontal Reference Grid Offset: (0 x 0)',
|
||||||
' Reference Tile Height, Width: (512 x 512)',
|
' Reference Tile Height, Width: (1456 x 2592)',
|
||||||
' Vertical, Horizontal Reference Tile Offset: (0 x 0)',
|
' Vertical, Horizontal Reference Tile Offset: (0 x 0)',
|
||||||
' Bitdepth: (8, 8, 8)',
|
' Bitdepth: (8, 8, 8)',
|
||||||
' Signed: (False, False, False)',
|
' Signed: (False, False, False)',
|
||||||
|
|
@ -537,26 +535,27 @@ class TestPrinting(unittest.TestCase):
|
||||||
def test_SOD_segment(self):
|
def test_SOD_segment(self):
|
||||||
j = glymur.Jp2k(self.jp2file)
|
j = glymur.Jp2k(self.jp2file)
|
||||||
codestream = j.get_codestream(header_only=False)
|
codestream = j.get_codestream(header_only=False)
|
||||||
print(codestream.segment[9])
|
print(codestream.segment[10])
|
||||||
actual = sys.stdout.getvalue().strip()
|
actual = sys.stdout.getvalue().strip()
|
||||||
|
|
||||||
lines = ['SOD marker segment @ (3299, 0)']
|
lines = ['SOD marker segment @ (3302, 0)']
|
||||||
expected = '\n'.join(lines)
|
expected = '\n'.join(lines)
|
||||||
self.assertEqual(actual, expected)
|
self.assertEqual(actual, expected)
|
||||||
|
|
||||||
def test_SOT_segment(self):
|
def test_SOT_segment(self):
|
||||||
j = glymur.Jp2k(self.jp2file)
|
j = glymur.Jp2k(self.jp2file)
|
||||||
codestream = j.get_codestream(header_only=False)
|
codestream = j.get_codestream(header_only=False)
|
||||||
print(codestream.segment[4])
|
print(codestream.segment[5])
|
||||||
actual = sys.stdout.getvalue().strip()
|
actual = sys.stdout.getvalue().strip()
|
||||||
|
|
||||||
lines = ['SOT marker segment @ (3221, 10)',
|
lines = ['SOT marker segment @ (3248, 10)',
|
||||||
' Tile part index: 0',
|
' Tile part index: 0',
|
||||||
' Tile part length: 78629',
|
' Tile part length: 1132173',
|
||||||
' Tile part instance: 0',
|
' Tile part instance: 0',
|
||||||
' Number of tile parts: 1']
|
' Number of tile parts: 1']
|
||||||
|
|
||||||
expected = '\n'.join(lines)
|
expected = '\n'.join(lines)
|
||||||
|
self.maxDiff = None
|
||||||
self.assertEqual(actual, expected)
|
self.assertEqual(actual, expected)
|
||||||
|
|
||||||
@unittest.skipIf(data_root is None,
|
@unittest.skipIf(data_root is None,
|
||||||
|
|
@ -606,7 +605,7 @@ class TestPrinting(unittest.TestCase):
|
||||||
' Profile: 2',
|
' Profile: 2',
|
||||||
' Reference Grid Height, Width: (1456 x 2592)',
|
' Reference Grid Height, Width: (1456 x 2592)',
|
||||||
' Vertical, Horizontal Reference Grid Offset: (0 x 0)',
|
' Vertical, Horizontal Reference Grid Offset: (0 x 0)',
|
||||||
' Reference Tile Height, Width: (512 x 512)',
|
' Reference Tile Height, Width: (1456 x 2592)',
|
||||||
' Vertical, Horizontal Reference Tile Offset: (0 x 0)',
|
' Vertical, Horizontal Reference Tile Offset: (0 x 0)',
|
||||||
' Bitdepth: (8, 8, 8)',
|
' Bitdepth: (8, 8, 8)',
|
||||||
' Signed: (False, False, False)',
|
' Signed: (False, False, False)',
|
||||||
|
|
@ -619,10 +618,10 @@ class TestPrinting(unittest.TestCase):
|
||||||
' EPH marker segments: False',
|
' EPH marker segments: False',
|
||||||
' Coding style parameters:',
|
' Coding style parameters:',
|
||||||
' Progression order: LRCP',
|
' Progression order: LRCP',
|
||||||
' Number of layers: 3',
|
' Number of layers: 2',
|
||||||
' Multiple component transformation usage: '
|
' Multiple component transformation usage: '
|
||||||
+ 'reversible',
|
+ 'reversible',
|
||||||
' Number of resolutions: 6',
|
' Number of resolutions: 2',
|
||||||
' Code block height, width: (64 x 64)',
|
' Code block height, width: (64 x 64)',
|
||||||
' Wavelet transform: 5-3 reversible',
|
' Wavelet transform: 5-3 reversible',
|
||||||
' Precinct size: default, 2^15 x 2^15',
|
' Precinct size: default, 2^15 x 2^15',
|
||||||
|
|
@ -634,13 +633,12 @@ class TestPrinting(unittest.TestCase):
|
||||||
' Vertically stripe causal context: False',
|
' Vertically stripe causal context: False',
|
||||||
' Predictable termination: False',
|
' Predictable termination: False',
|
||||||
' Segmentation symbols: False',
|
' Segmentation symbols: False',
|
||||||
' QCD marker segment @ (3200, 19)',
|
' QCD marker segment @ (3200, 7)',
|
||||||
' Quantization style: no quantization, '
|
' Quantization style: no quantization, '
|
||||||
+ '2 guard bits',
|
+ '2 guard bits',
|
||||||
' Step size: [(0, 8), (0, 9), (0, 9), '
|
' Step size: [(0, 8), (0, 9), (0, 9), (0, 10)]',
|
||||||
+ '(0, 10), (0, 9), (0, 9), (0, 10), (0, 9), (0, 9), '
|
' CME marker segment @ (3209, 37)',
|
||||||
+ '(0, 10), (0, 9), (0, 9), (0, 10), (0, 9), (0, 9), '
|
' "Created by OpenJPEG version 2.0.0"']
|
||||||
+ '(0, 10)]']
|
|
||||||
expected = '\n'.join(lst)
|
expected = '\n'.join(lst)
|
||||||
self.assertEqual(actual, expected)
|
self.assertEqual(actual, expected)
|
||||||
|
|
||||||
|
|
@ -783,6 +781,8 @@ class TestPrinting(unittest.TestCase):
|
||||||
expected = '\n'.join(lines)
|
expected = '\n'.join(lines)
|
||||||
self.assertEqual(actual, expected)
|
self.assertEqual(actual, expected)
|
||||||
|
|
||||||
|
@unittest.skipIf(os.name == "nt",
|
||||||
|
"Problems using NamedTemporaryFile on windows.")
|
||||||
def test_less_common_boxes(self):
|
def test_less_common_boxes(self):
|
||||||
with tempfile.NamedTemporaryFile(suffix='.jp2') as tfile:
|
with tempfile.NamedTemporaryFile(suffix='.jp2') as tfile:
|
||||||
with open(self.jp2file, 'rb') as ifile:
|
with open(self.jp2file, 'rb') as ifile:
|
||||||
|
|
|
||||||
22
release.txt
Normal file
22
release.txt
Normal file
|
|
@ -0,0 +1,22 @@
|
||||||
|
| OS | Python 2.7 | Python 3.3 | Notes |
|
||||||
|
+------------+------------+------------+----------------------------------+
|
||||||
|
| Windows | X | | Python(xy) with OpenJPEG 1.5.1. |
|
||||||
|
| | | | At least 25 tests should pass |
|
||||||
|
+------------+------------+------------+----------------------------------+
|
||||||
|
| Mac | X | | MacPorts with both OpenJPEG 1.5.1|
|
||||||
|
| | | | and OpenJPEG svn. Maximum number|
|
||||||
|
| | | | of tests should pass. |
|
||||||
|
+------------+------------+------------+----------------------------------+
|
||||||
|
| Mac | | X | MacPorts with both OpenJPEG 1.5.1|
|
||||||
|
| | | | and OpenJPEG svn. Maximum number|
|
||||||
|
| | | | of tests should pass. |
|
||||||
|
+------------+------------+------------+----------------------------------+
|
||||||
|
| Raspberry | X | | Ships with only 1.3. Should |
|
||||||
|
| | | | error out gracefully. |
|
||||||
|
+------------+------------+------------+----------------------------------+
|
||||||
|
| Fedora 17 | X | | Ships with 1.4. Should error out|
|
||||||
|
| | | | gracefully. |
|
||||||
|
+------------+------------+------------+----------------------------------+
|
||||||
|
| Fedora 18 | | X | Ships with 1.5.1. Some tests |
|
||||||
|
| | | | should pass. |
|
||||||
|
+------------+------------+------------+----------------------------------+
|
||||||
Loading…
Add table
Add a link
Reference in a new issue