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
|
||||
prune build
|
||||
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
|
||||
use your system's package manager to install as many required
|
||||
packages/RPMs/ports/whatever without going through pip. Otherwise go on to
|
||||
the next page.
|
||||
packages/RPMs/ports/whatever without going through pip.
|
||||
|
||||
''''''''
|
||||
Platform
|
||||
''''''''
|
||||
|
||||
Mac OS X
|
||||
--------
|
||||
|
|
@ -58,8 +96,9 @@ repositories::
|
|||
|
||||
Raspbian
|
||||
''''''''
|
||||
Yeah, this was the first thing I tried after getting my new Raspberry Pi hooked
|
||||
up (couldn't help myself :-) Raspbian ships with Python 3.2 and 2.7, so these steps detail working with 2.7.
|
||||
Yeah, this was the first thing I tried after getting my new Raspberry
|
||||
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::
|
||||
|
||||
|
|
@ -79,8 +118,8 @@ one unexpected failure as of the time of writing.
|
|||
|
||||
Fedora 17
|
||||
'''''''''
|
||||
Fedora 17 ships with Python 3.2 and 2.7, so these steps detail working with
|
||||
2.7.
|
||||
Fedora 17 ships with Python 3.2 and 2.7, but OpenJPEG is only at version 1.4,
|
||||
so these steps detail working with Python 2.7 and the svn version of OpenJPEG.
|
||||
|
||||
Required RPMs include::
|
||||
|
||||
|
|
@ -111,7 +150,10 @@ it was installable via pip::
|
|||
|
||||
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
|
||||
|
|
|
|||
|
|
@ -2,14 +2,9 @@
|
|||
Glymur: a Python interface for JPEG 2000
|
||||
----------------------------------------
|
||||
|
||||
**Glymur** contains a Python interface to the OpenJPEG library
|
||||
which allows linux and mac users to read and write JPEG 2000 files. For more
|
||||
information about OpenJPEG, please consult http://www.openjpeg.org. Glymur
|
||||
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
|
||||
**Glymur** is an interface to the OpenJPEG library
|
||||
which allows one to read and write JPEG 2000 files from within Python.
|
||||
Glymur supports both reading and writing of JPEG 2000 images. Writing
|
||||
JPEG 2000 images is currently limited to images that can fit in memory,
|
||||
however.
|
||||
|
||||
|
|
@ -23,34 +18,18 @@ Glymur works on Python 2.7 and 3.3. Python 3.3 is strongly recommended.
|
|||
|
||||
OpenJPEG Installation
|
||||
=====================
|
||||
OpenJPEG must be built as a shared library. In addition, you
|
||||
currently must compile OpenJPEG from the developmental source that
|
||||
you can retrieve via subversion. As of this time of writing, svn
|
||||
revision 2345 works. You should 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. ::
|
||||
The OpenJPEG library version must be either 1.5.1 or the trunk/development
|
||||
version of OpenJPEG. Version 2.0.0 or versions earlier than 1.5.0
|
||||
are not supported. Furthermore, the 1.5.x version of OpenJPEG is
|
||||
currently only utilized for read-only purposes. For more information
|
||||
about OpenJPEG, please consult http://www.openjpeg.org.
|
||||
|
||||
$ svn co http://openjpeg.googlecode.com/svn/data
|
||||
$ export OPJ_DATA_ROOT=`pwd`/data
|
||||
|
||||
Earlier versions of OpenJPEG through the 2.0 official release will **NOT**
|
||||
work and are not supported.
|
||||
|
||||
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**.
|
||||
If you use MacPorts on the mac or if you have a sufficiently recent version of
|
||||
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
|
||||
2000 images. If you use windows, I suggest using the 1.5.1 windows installer provided
|
||||
to you by the OpenJPEG folks at
|
||||
https://code.google.com/p/openjpeg/downloads/list .
|
||||
|
||||
Glymur Installation
|
||||
===================
|
||||
|
|
@ -76,5 +55,6 @@ You can run the tests from within python as follows::
|
|||
>>> import glymur
|
||||
>>> 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.
|
||||
|
|
|
|||
|
|
@ -186,4 +186,3 @@ _reader_requirements_display = {
|
|||
+ 'requirements in M.9.2.3',
|
||||
73: 'YPbPr(1125/60) 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 .core import *
|
||||
from .jp2box import *
|
||||
from .lib import openjpeg as opj
|
||||
from .lib import openjp2 as opj2
|
||||
|
||||
_cspace_map = {'rgb': opj2._CLRSPC_SRGB,
|
||||
|
|
@ -202,7 +203,7 @@ class Jp2k(Jp2kBox):
|
|||
>>> import glymur
|
||||
>>> jfile = glymur.data.nemo()
|
||||
>>> jp2 = glymur.Jp2k(jfile)
|
||||
>>> data = jp2.read(reduce=3)
|
||||
>>> data = jp2.read(reduce=1)
|
||||
>>> from tempfile import NamedTemporaryFile
|
||||
>>> tfile = NamedTemporaryFile(suffix='.jp2', delete=False)
|
||||
>>> j = Jp2k(tfile.name, mode='wb')
|
||||
|
|
@ -544,16 +545,17 @@ class Jp2k(Jp2kBox):
|
|||
jp2 = Jp2k(filename)
|
||||
return jp2
|
||||
|
||||
def read(self, reduce=0, layer=0, area=None, tile=None, verbose=False):
|
||||
def read(self, **kwargs):
|
||||
"""Read a JPEG 2000 image.
|
||||
|
||||
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.
|
||||
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
|
||||
Specifies decoding image area,
|
||||
(first_row, first_col, last_row, last_col)
|
||||
|
|
@ -585,7 +587,156 @@ class Jp2k(Jp2kBox):
|
|||
|
||||
>>> thumbnail = jp.read(reduce=-1)
|
||||
>>> 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.
|
||||
codestream = self.get_codestream(header_only=True)
|
||||
|
|
@ -593,7 +744,7 @@ class Jp2k(Jp2kBox):
|
|||
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."
|
||||
raise IOError(msg)
|
||||
raise RuntimeError(msg)
|
||||
|
||||
img_array = self._read_common(reduce=reduce,
|
||||
layer=layer,
|
||||
|
|
@ -780,7 +931,16 @@ class Jp2k(Jp2kBox):
|
|||
>>> jfile = glymur.data.nemo()
|
||||
>>> jp = glymur.Jp2k(jfile)
|
||||
>>> 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,
|
||||
layer=layer,
|
||||
area=area,
|
||||
|
|
@ -807,14 +967,14 @@ class Jp2k(Jp2kBox):
|
|||
--------
|
||||
>>> import glymur
|
||||
>>> jfile = glymur.data.nemo()
|
||||
>>> jp = glymur.Jp2k(jfile)
|
||||
>>> codestream = jp.get_codestream()
|
||||
>>> jp2 = glymur.Jp2k(jfile)
|
||||
>>> codestream = jp2.get_codestream()
|
||||
>>> print(codestream.segment[1])
|
||||
SIZ marker segment @ (3137, 47)
|
||||
Profile: 2
|
||||
Reference Grid Height, Width: (1456 x 2592)
|
||||
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)
|
||||
Bitdepth: (8, 8, 8)
|
||||
Signed: (False, False, False)
|
||||
|
|
|
|||
|
|
@ -1,3 +1,4 @@
|
|||
"""This package organizes individual libraries employed by glymur."""
|
||||
from . import openjp2
|
||||
from . import test
|
||||
from . import openjpeg
|
||||
#from . import test
|
||||
|
|
|
|||
|
|
@ -1,6 +1,9 @@
|
|||
"""
|
||||
Wraps individual functions in openjp2 library.
|
||||
"""
|
||||
import ctypes
|
||||
import platform
|
||||
from ctypes.util import find_library
|
||||
|
||||
|
||||
def _glymurrc_fname():
|
||||
|
|
@ -23,19 +26,46 @@ def _glymurrc_fname():
|
|||
fname = os.path.join(confdir, 'glymurrc')
|
||||
if os.path.exists(fname):
|
||||
return fname
|
||||
else:
|
||||
msg = "Configuration file '{0}' does not exist.".format(confdir)
|
||||
warnings.warn(msg, UserWarning)
|
||||
|
||||
# didn't find a configuration file.
|
||||
return None
|
||||
|
||||
|
||||
def _config():
|
||||
"""Read configuration file.
|
||||
def _get_openjpeg_config():
|
||||
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()
|
||||
if filename is not None:
|
||||
# Read the configuration file for the library location.
|
||||
|
|
@ -44,14 +74,16 @@ def _config():
|
|||
libopenjp2_path = parser.get('library', 'openjp2')
|
||||
else:
|
||||
# No help from the config file, try to find it ourselves.
|
||||
from ctypes.util import find_library
|
||||
libopenjp2_path = find_library('openjp2')
|
||||
|
||||
if libopenjp2_path is None:
|
||||
return None
|
||||
|
||||
try:
|
||||
_OPENJP2 = ctypes.CDLL(libopenjp2_path)
|
||||
if os.name == "nt":
|
||||
_OPENJP2 = ctypes.windll.LoadLibrary(libopenjp2_path)
|
||||
else:
|
||||
_OPENJP2 = ctypes.CDLL(libopenjp2_path)
|
||||
except OSError:
|
||||
msg = '"Library {0}" could not be loaded. Operating in degraded mode.'
|
||||
msg = msg.format(libopenjp2_path)
|
||||
|
|
@ -60,6 +92,13 @@ def _config():
|
|||
return _OPENJP2
|
||||
|
||||
|
||||
def _config():
|
||||
"""Read configuration file.
|
||||
"""
|
||||
_OPENJP2 = _get_openjp2_config()
|
||||
_OPENJPEG = _get_openjpeg_config()
|
||||
return _OPENJP2, _OPENJPEG
|
||||
|
||||
def _get_configdir():
|
||||
"""Return string representing the configuration directory.
|
||||
|
||||
|
|
@ -73,7 +112,9 @@ def _get_configdir():
|
|||
if 'HOME' in os.environ:
|
||||
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 warnings
|
||||
|
||||
|
|
@ -85,7 +126,12 @@ else:
|
|||
from configparser import ConfigParser
|
||||
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
|
||||
|
||||
|
|
@ -616,8 +662,8 @@ class _codestream_info_v2_t(ctypes.Structure):
|
|||
# Restrict the input and output argument types for each function used in the
|
||||
# API.
|
||||
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.argtypes = [_codec_format_t]
|
||||
|
||||
_OPENJP2.opj_create_decompress.argtypes = [_codec_format_t]
|
||||
_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_codestream import TestCodestream as codestream
|
||||
from .test_config import TestSuite as config
|
||||
from .test_jp2k import TestJp2k as jp2k
|
||||
from .test_icc import TestICC as icc
|
||||
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 pkg_resources
|
||||
import re
|
||||
import sys
|
||||
import tempfile
|
||||
import unittest
|
||||
|
|
@ -21,8 +22,8 @@ class TestCallbacks(unittest.TestCase):
|
|||
# Save sys.stdout.
|
||||
self.stdout = sys.stdout
|
||||
sys.stdout = StringIO()
|
||||
self.jp2file = pkg_resources.resource_filename(glymur.__name__,
|
||||
"data/nemo.jp2")
|
||||
self.jp2file = glymur.data.nemo()
|
||||
self.j2kfile = glymur.data.goodstuff()
|
||||
|
||||
def tearDown(self):
|
||||
# Restore stdout.
|
||||
|
|
@ -44,24 +45,67 @@ class TestCallbacks(unittest.TestCase):
|
|||
def test_info_warning_callbacks_on_read(self):
|
||||
# Verify that we get the expected stdio output when our internal info
|
||||
# callback handler is enabled.
|
||||
j = glymur.Jp2k(self.jp2file)
|
||||
d = j.read(reduce=3, verbose=True, area=(0, 0, 512, 1024))
|
||||
j = glymur.Jp2k(self.j2kfile)
|
||||
d = j.read(reduce=1, verbose=True, area=(0, 0, 200, 150))
|
||||
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] Setting decoding area to 0,0,1024,512',
|
||||
'[INFO] Header of tile 0 / 17 has been read.',
|
||||
'[INFO] Tile 1/18 has been decoded.',
|
||||
'[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 !']
|
||||
'[INFO] Setting decoding area to 0,0,150,200',
|
||||
'[INFO] Header of tile 0 / 0 has been read.',
|
||||
'[INFO] Tile 1/1 has been decoded.',
|
||||
'[INFO] Image data has been updated with tile 1.']
|
||||
|
||||
expected = '\n'.join(lines)
|
||||
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__":
|
||||
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 os
|
||||
import sys
|
||||
|
|
@ -16,14 +20,28 @@ from glymur import Jp2k
|
|||
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,
|
||||
"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):
|
||||
self.jp2file = pkg_resources.resource_filename(glymur.__name__,
|
||||
"data/nemo.jp2")
|
||||
imp.reload(glymur)
|
||||
imp.reload(glymur.lib.openjp2)
|
||||
self.jp2file = glymur.data.nemo()
|
||||
|
||||
def tearDown(self):
|
||||
imp.reload(glymur)
|
||||
|
|
|
|||
|
|
@ -1,4 +1,5 @@
|
|||
import doctest
|
||||
import os
|
||||
import tempfile
|
||||
import xml.etree.cElementTree as ET
|
||||
import unittest
|
||||
|
|
@ -17,6 +18,8 @@ def load_tests(loader, tests, ignore):
|
|||
return tests
|
||||
|
||||
|
||||
@unittest.skipIf(glymur.lib.openjp2._OPENJP2 is None,
|
||||
"Missing openjp2 library.")
|
||||
class TestChannelDefinition(unittest.TestCase):
|
||||
|
||||
@classmethod
|
||||
|
|
@ -288,6 +291,8 @@ class TestXML(unittest.TestCase):
|
|||
with self.assertRaises((IOError, OSError)) as ce:
|
||||
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):
|
||||
# Should be able to write an XMLBox.
|
||||
j2k = Jp2k(self.j2kfile)
|
||||
|
|
@ -308,6 +313,8 @@ class TestXML(unittest.TestCase):
|
|||
self.assertEqual(ET.tostring(jp2.box[3].xml),
|
||||
b'<data>0</data>')
|
||||
|
||||
@unittest.skipIf(os.name == "nt",
|
||||
"Problems using NamedTemporaryFile on windows.")
|
||||
def test_xml_from_file(self):
|
||||
j2k = Jp2k(self.j2kfile)
|
||||
|
||||
|
|
@ -352,6 +359,8 @@ class TestColourSpecificationBox(unittest.TestCase):
|
|||
def tearDown(self):
|
||||
pass
|
||||
|
||||
@unittest.skipIf(os.name == "nt",
|
||||
"Problems using NamedTemporaryFile on windows.")
|
||||
def test_color_specification_box_with_out_enumerated_colorspace(self):
|
||||
j2k = Jp2k(self.j2kfile)
|
||||
|
||||
|
|
|
|||
|
|
@ -74,10 +74,8 @@ class TestJp2k(unittest.TestCase):
|
|||
os.unlink(cls._bad_xml_file)
|
||||
|
||||
def setUp(self):
|
||||
self.jp2file = pkg_resources.resource_filename(glymur.__name__,
|
||||
"data/nemo.jp2")
|
||||
self.j2kfile = pkg_resources.resource_filename(glymur.__name__,
|
||||
"data/goodstuff.j2k")
|
||||
self.jp2file = glymur.data.nemo()
|
||||
self.j2kfile = glymur.data.goodstuff()
|
||||
|
||||
def tearDown(self):
|
||||
pass
|
||||
|
|
@ -92,11 +90,11 @@ class TestJp2k(unittest.TestCase):
|
|||
|
||||
def test_reduce_max(self):
|
||||
# Verify that reduce=-1 gets us the lowest resolution image
|
||||
j = Jp2k(self.jp2file)
|
||||
j = Jp2k(self.j2kfile)
|
||||
thumbnail1 = j.read(reduce=-1)
|
||||
thumbnail2 = j.read(reduce=5)
|
||||
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):
|
||||
# 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.'
|
||||
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):
|
||||
j2k = Jp2k(self.j2kfile)
|
||||
expdata = j2k.read()
|
||||
|
|
@ -178,7 +167,7 @@ class TestJp2k(unittest.TestCase):
|
|||
def test_write_cprl(self):
|
||||
# Issue 17
|
||||
j = Jp2k(self.jp2file)
|
||||
expdata = j.read(reduce=2)
|
||||
expdata = j.read(reduce=1)
|
||||
with tempfile.NamedTemporaryFile(suffix='.jp2') as tfile:
|
||||
ofile = Jp2k(tfile.name, 'wb')
|
||||
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].offset, 3127)
|
||||
self.assertEqual(jp2k.box[5].length, 1133427)
|
||||
self.assertEqual(jp2k.box[5].length, 1132296)
|
||||
|
||||
# jp2h super box
|
||||
self.assertEqual(len(jp2k.box[2].box), 2)
|
||||
|
|
@ -330,7 +319,7 @@ class TestJp2k(unittest.TestCase):
|
|||
# Issue 86.
|
||||
filename = os.path.join(data_root, 'input/conformance/p0_05.j2k')
|
||||
j = Jp2k(filename)
|
||||
with self.assertRaises(IOError):
|
||||
with self.assertRaises(RuntimeError):
|
||||
j.read()
|
||||
|
||||
@unittest.skipIf(data_root is None,
|
||||
|
|
@ -540,7 +529,7 @@ class TestJp2k(unittest.TestCase):
|
|||
def test_asoc_label_box(self):
|
||||
# Construct a fake file with an asoc and a label box, as
|
||||
# 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:
|
||||
j = Jp2k(tfile.name, 'wb')
|
||||
j.write(data)
|
||||
|
|
@ -659,5 +648,66 @@ class TestJp2k(unittest.TestCase):
|
|||
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__":
|
||||
unittest.main()
|
||||
|
|
|
|||
|
|
@ -24,6 +24,8 @@ import numpy as np
|
|||
from glymur import Jp2k
|
||||
import glymur
|
||||
|
||||
from .fixtures import *
|
||||
|
||||
try:
|
||||
data_root = os.environ['OPJ_DATA_ROOT']
|
||||
except KeyError:
|
||||
|
|
@ -32,94 +34,6 @@ except:
|
|||
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,
|
||||
"Missing openjp2 library.")
|
||||
@unittest.skipIf(data_root is None,
|
||||
|
|
@ -1155,7 +1069,7 @@ class TestSuite(unittest.TestCase):
|
|||
def test_NR_DEC_file_409752_jp2_40_decode(self):
|
||||
jfile = os.path.join(data_root,
|
||||
'input/nonregression/file409752.jp2')
|
||||
with self.assertRaises(IOError):
|
||||
with self.assertRaises(RuntimeError):
|
||||
data = Jp2k(jfile).read()
|
||||
|
||||
@unittest.skipIf(sys.hexversion < 0x03020000,
|
||||
|
|
@ -7418,5 +7332,615 @@ class TestSuiteDump(unittest.TestCase):
|
|||
self.assertEqual(c.segment[3]._exponent,
|
||||
[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__":
|
||||
unittest.main()
|
||||
|
|
|
|||
|
|
@ -65,8 +65,8 @@ def read_image(infile):
|
|||
class TestSuiteNegative(unittest.TestCase):
|
||||
|
||||
def setUp(self):
|
||||
self.jp2file = pkg_resources.resource_filename(glymur.__name__,
|
||||
"data/nemo.jp2")
|
||||
self.jp2file = glymur.data.nemo()
|
||||
self.j2kfile = glymur.data.goodstuff()
|
||||
|
||||
def tearDown(self):
|
||||
pass
|
||||
|
|
@ -156,8 +156,8 @@ class TestSuiteNegative(unittest.TestCase):
|
|||
|
||||
def test_precinct_size_not_multiple_of_two(self):
|
||||
# Seems like precinct sizes should be powers of two.
|
||||
ifile = Jp2k(self.jp2file)
|
||||
data = ifile.read(reduce=3)
|
||||
ifile = Jp2k(self.j2kfile)
|
||||
data = ifile.read(reduce=2)
|
||||
with tempfile.NamedTemporaryFile(suffix='.jp2') as tfile:
|
||||
ofile = Jp2k(tfile.name, 'wb')
|
||||
with self.assertRaises(IOError) as ce:
|
||||
|
|
@ -165,8 +165,8 @@ class TestSuiteNegative(unittest.TestCase):
|
|||
|
||||
def test_codeblock_size_not_multiple_of_two(self):
|
||||
# Seems like code block sizes should be powers of two.
|
||||
ifile = Jp2k(self.jp2file)
|
||||
data = ifile.read(reduce=3)
|
||||
ifile = Jp2k(self.j2kfile)
|
||||
data = ifile.read(reduce=2)
|
||||
with tempfile.NamedTemporaryFile(suffix='.jp2') as tfile:
|
||||
ofile = Jp2k(tfile.name, 'wb')
|
||||
with self.assertRaises(IOError) as ce:
|
||||
|
|
@ -175,8 +175,8 @@ class TestSuiteNegative(unittest.TestCase):
|
|||
def test_codeblock_size_with_precinct_size(self):
|
||||
# Seems like code block sizes should never exceed half that of
|
||||
# precinct size.
|
||||
ifile = Jp2k(self.jp2file)
|
||||
data = ifile.read(reduce=3)
|
||||
ifile = Jp2k(self.j2kfile)
|
||||
data = ifile.read(reduce=2)
|
||||
with tempfile.NamedTemporaryFile(suffix='.jp2') as tfile:
|
||||
ofile = Jp2k(tfile.name, 'wb')
|
||||
with self.assertRaises(IOError) as ce:
|
||||
|
|
|
|||
|
|
@ -34,7 +34,7 @@ class TestPrintingNeedsLib(unittest.TestCase):
|
|||
with tempfile.NamedTemporaryFile(suffix='.jp2', delete=False) as tfile:
|
||||
cls._plain_nemo_file = tfile.name
|
||||
ijfile = Jp2k(jp2file)
|
||||
data = ijfile.read(reduce=3)
|
||||
data = ijfile.read(reduce=1)
|
||||
ojfile = Jp2k(cls._plain_nemo_file, 'wb')
|
||||
ojfile.write(data)
|
||||
|
||||
|
|
@ -43,8 +43,9 @@ class TestPrintingNeedsLib(unittest.TestCase):
|
|||
os.unlink(cls._plain_nemo_file)
|
||||
|
||||
def setUp(self):
|
||||
self.jp2file = pkg_resources.resource_filename(glymur.__name__,
|
||||
"data/nemo.jp2")
|
||||
self.jp2file = glymur.data.nemo()
|
||||
self.j2kfile = glymur.data.goodstuff()
|
||||
|
||||
# Save sys.stdout.
|
||||
self.stdout = sys.stdout
|
||||
sys.stdout = StringIO()
|
||||
|
|
@ -57,7 +58,7 @@ class TestPrintingNeedsLib(unittest.TestCase):
|
|||
" Compatibility: ['jp2 ']",
|
||||
'JP2 Header Box (jp2h) @ (32, 45)',
|
||||
' Image Header Box (ihdr) @ (40, 22)',
|
||||
' Size: [182 324 3]',
|
||||
' Size: [728 1296 3]',
|
||||
' Bitdepth: 8',
|
||||
' Signed: False',
|
||||
' Compression: wavelet',
|
||||
|
|
@ -66,15 +67,15 @@ class TestPrintingNeedsLib(unittest.TestCase):
|
|||
' Method: enumerated colorspace',
|
||||
' Precedence: 0',
|
||||
' Colorspace: sRGB',
|
||||
'Contiguous Codestream Box (jp2c) @ (77, 112814)',
|
||||
'Contiguous Codestream Box (jp2c) @ (77, 1632355)',
|
||||
' Main header:',
|
||||
' SOC marker segment @ (85, 0)',
|
||||
' SIZ marker segment @ (87, 47)',
|
||||
' Profile: 2',
|
||||
' Reference Grid Height, Width: (182 x 324)',
|
||||
' Reference Grid Height, Width: (728 x 1296)',
|
||||
' Vertical, Horizontal Reference Grid Offset: '
|
||||
+ '(0 x 0)',
|
||||
' Reference Tile Height, Width: (182 x 324)',
|
||||
' Reference Tile Height, Width: (728 x 1296)',
|
||||
' Vertical, Horizontal Reference Tile Offset: '
|
||||
+ '(0 x 0)',
|
||||
' Bitdepth: (8, 8, 8)',
|
||||
|
|
@ -121,7 +122,7 @@ class TestPrintingNeedsLib(unittest.TestCase):
|
|||
def test_asoc_label_box(self):
|
||||
# Construct a fake file with an asoc and a label box, as
|
||||
# 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:
|
||||
j = glymur.Jp2k(tfile.name, 'wb')
|
||||
j.write(data)
|
||||
|
|
@ -177,7 +178,7 @@ class TestPrintingNeedsLib(unittest.TestCase):
|
|||
lst = actual.split('\n')
|
||||
lst = lst[1:]
|
||||
actual = '\n'.join(lst)
|
||||
|
||||
self.maxDiff = None
|
||||
self.assertEqual(actual, self.expectedPlain)
|
||||
|
||||
def test_entire_file(self):
|
||||
|
|
@ -209,15 +210,15 @@ class TestPrinting(unittest.TestCase):
|
|||
def test_COC_segment(self):
|
||||
j = glymur.Jp2k(self.jp2file)
|
||||
codestream = j.get_codestream(header_only=False)
|
||||
print(codestream.segment[5])
|
||||
print(codestream.segment[6])
|
||||
actual = sys.stdout.getvalue().strip()
|
||||
|
||||
lines = ['COC marker segment @ (3233, 9)',
|
||||
lines = ['COC marker segment @ (3260, 9)',
|
||||
' Associated component: 1',
|
||||
' Coding style for this component: '
|
||||
+ 'Entropy coder, PARTITION = 0',
|
||||
' Coding style parameters:',
|
||||
' Number of resolutions: 6',
|
||||
' Number of resolutions: 2',
|
||||
' Code block height, width: (64 x 64)',
|
||||
' Wavelet transform: 5-3 reversible',
|
||||
' Code block context:',
|
||||
|
|
@ -230,6 +231,7 @@ class TestPrinting(unittest.TestCase):
|
|||
' Segmentation symbols: False']
|
||||
|
||||
expected = '\n'.join(lines)
|
||||
self.maxDiff = None
|
||||
self.assertEqual(actual, expected)
|
||||
|
||||
def test_COD_segment(self):
|
||||
|
|
@ -245,10 +247,10 @@ class TestPrinting(unittest.TestCase):
|
|||
' EPH marker segments: False',
|
||||
' Coding style parameters:',
|
||||
' Progression order: LRCP',
|
||||
' Number of layers: 3',
|
||||
' Number of layers: 2',
|
||||
' Multiple component transformation usage: '
|
||||
+ 'reversible',
|
||||
' Number of resolutions: 6',
|
||||
' Number of resolutions: 2',
|
||||
' Code block height, width: (64 x 64)',
|
||||
' Wavelet transform: 5-3 reversible',
|
||||
' Precinct size: default, 2^15 x 2^15',
|
||||
|
|
@ -392,7 +394,7 @@ class TestPrinting(unittest.TestCase):
|
|||
print(codestream.segment[-1])
|
||||
actual = sys.stdout.getvalue().strip()
|
||||
|
||||
lines = ['EOC marker segment @ (1136552, 0)']
|
||||
lines = ['EOC marker segment @ (1135421, 0)']
|
||||
expected = '\n'.join(lines)
|
||||
self.assertEqual(actual, expected)
|
||||
|
||||
|
|
@ -476,15 +478,13 @@ class TestPrinting(unittest.TestCase):
|
|||
def test_QCC_segment(self):
|
||||
j = glymur.Jp2k(self.jp2file)
|
||||
codestream = j.get_codestream(header_only=False)
|
||||
print(codestream.segment[6])
|
||||
print(codestream.segment[7])
|
||||
actual = sys.stdout.getvalue().strip()
|
||||
|
||||
lines = ['QCC marker segment @ (3244, 20)',
|
||||
lines = ['QCC marker segment @ (3271, 8)',
|
||||
' Associated Component: 1',
|
||||
' Quantization style: no quantization, 2 guard bits',
|
||||
' Step size: [(0, 8), (0, 9), (0, 9), (0, 10), (0, 9), '
|
||||
+ '(0, 9), (0, 10), (0, 9), (0, 9), (0, 10), (0, 9), (0, 9), '
|
||||
+ '(0, 10), (0, 9), (0, 9), (0, 10)]']
|
||||
' Step size: [(0, 8), (0, 9), (0, 9), (0, 10)]']
|
||||
|
||||
expected = '\n'.join(lines)
|
||||
self.assertEqual(actual, expected)
|
||||
|
|
@ -495,11 +495,9 @@ class TestPrinting(unittest.TestCase):
|
|||
print(codestream.segment[3])
|
||||
actual = sys.stdout.getvalue().strip()
|
||||
|
||||
lines = ['QCD marker segment @ (3200, 19)',
|
||||
lines = ['QCD marker segment @ (3200, 7)',
|
||||
' Quantization style: no quantization, 2 guard bits',
|
||||
' Step size: [(0, 8), (0, 9), (0, 9), (0, 10), (0, 9), '
|
||||
+ '(0, 9), (0, 10), (0, 9), (0, 9), (0, 10), (0, 9), '
|
||||
+ '(0, 9), (0, 10), (0, 9), (0, 9), (0, 10)]']
|
||||
' Step size: [(0, 8), (0, 9), (0, 9), (0, 10)]']
|
||||
|
||||
expected = '\n'.join(lines)
|
||||
self.assertEqual(actual, expected)
|
||||
|
|
@ -514,7 +512,7 @@ class TestPrinting(unittest.TestCase):
|
|||
' Profile: 2',
|
||||
' Reference Grid Height, Width: (1456 x 2592)',
|
||||
' 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)',
|
||||
' Bitdepth: (8, 8, 8)',
|
||||
' Signed: (False, False, False)',
|
||||
|
|
@ -537,26 +535,27 @@ class TestPrinting(unittest.TestCase):
|
|||
def test_SOD_segment(self):
|
||||
j = glymur.Jp2k(self.jp2file)
|
||||
codestream = j.get_codestream(header_only=False)
|
||||
print(codestream.segment[9])
|
||||
print(codestream.segment[10])
|
||||
actual = sys.stdout.getvalue().strip()
|
||||
|
||||
lines = ['SOD marker segment @ (3299, 0)']
|
||||
lines = ['SOD marker segment @ (3302, 0)']
|
||||
expected = '\n'.join(lines)
|
||||
self.assertEqual(actual, expected)
|
||||
|
||||
def test_SOT_segment(self):
|
||||
j = glymur.Jp2k(self.jp2file)
|
||||
codestream = j.get_codestream(header_only=False)
|
||||
print(codestream.segment[4])
|
||||
print(codestream.segment[5])
|
||||
actual = sys.stdout.getvalue().strip()
|
||||
|
||||
lines = ['SOT marker segment @ (3221, 10)',
|
||||
lines = ['SOT marker segment @ (3248, 10)',
|
||||
' Tile part index: 0',
|
||||
' Tile part length: 78629',
|
||||
' Tile part length: 1132173',
|
||||
' Tile part instance: 0',
|
||||
' Number of tile parts: 1']
|
||||
|
||||
expected = '\n'.join(lines)
|
||||
self.maxDiff = None
|
||||
self.assertEqual(actual, expected)
|
||||
|
||||
@unittest.skipIf(data_root is None,
|
||||
|
|
@ -606,7 +605,7 @@ class TestPrinting(unittest.TestCase):
|
|||
' Profile: 2',
|
||||
' Reference Grid Height, Width: (1456 x 2592)',
|
||||
' 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)',
|
||||
' Bitdepth: (8, 8, 8)',
|
||||
' Signed: (False, False, False)',
|
||||
|
|
@ -619,10 +618,10 @@ class TestPrinting(unittest.TestCase):
|
|||
' EPH marker segments: False',
|
||||
' Coding style parameters:',
|
||||
' Progression order: LRCP',
|
||||
' Number of layers: 3',
|
||||
' Number of layers: 2',
|
||||
' Multiple component transformation usage: '
|
||||
+ 'reversible',
|
||||
' Number of resolutions: 6',
|
||||
' Number of resolutions: 2',
|
||||
' Code block height, width: (64 x 64)',
|
||||
' Wavelet transform: 5-3 reversible',
|
||||
' Precinct size: default, 2^15 x 2^15',
|
||||
|
|
@ -634,13 +633,12 @@ class TestPrinting(unittest.TestCase):
|
|||
' Vertically stripe causal context: False',
|
||||
' Predictable termination: False',
|
||||
' Segmentation symbols: False',
|
||||
' QCD marker segment @ (3200, 19)',
|
||||
' QCD marker segment @ (3200, 7)',
|
||||
' Quantization style: no quantization, '
|
||||
+ '2 guard bits',
|
||||
' Step size: [(0, 8), (0, 9), (0, 9), '
|
||||
+ '(0, 10), (0, 9), (0, 9), (0, 10), (0, 9), (0, 9), '
|
||||
+ '(0, 10), (0, 9), (0, 9), (0, 10), (0, 9), (0, 9), '
|
||||
+ '(0, 10)]']
|
||||
' Step size: [(0, 8), (0, 9), (0, 9), (0, 10)]',
|
||||
' CME marker segment @ (3209, 37)',
|
||||
' "Created by OpenJPEG version 2.0.0"']
|
||||
expected = '\n'.join(lst)
|
||||
self.assertEqual(actual, expected)
|
||||
|
||||
|
|
@ -783,6 +781,8 @@ class TestPrinting(unittest.TestCase):
|
|||
expected = '\n'.join(lines)
|
||||
self.assertEqual(actual, expected)
|
||||
|
||||
@unittest.skipIf(os.name == "nt",
|
||||
"Problems using NamedTemporaryFile on windows.")
|
||||
def test_less_common_boxes(self):
|
||||
with tempfile.NamedTemporaryFile(suffix='.jp2') as tfile:
|
||||
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