Releasing 0.5.11.
Updated to support OpenJPEG versions 1.5.2, 2.0.1, and 2.1. Updated to support Python 3.4. Cleaned up and refactored many tests. Dropped some tests that were always skipped.
This commit is contained in:
parent
b78009ebf2
commit
5936706f0e
25 changed files with 860 additions and 7037 deletions
|
|
@ -3,6 +3,7 @@ python:
|
|||
- "2.6"
|
||||
- "2.7"
|
||||
- "3.3"
|
||||
- "3.4"
|
||||
|
||||
before_install:
|
||||
- sudo apt-get update -qq
|
||||
|
|
@ -15,12 +16,14 @@ install:
|
|||
- if [[ $TRAVIS_PYTHON_VERSION == '2.6' ]]; then pip install --use-mirrors contextlib2 mock ordereddict unittest2; fi
|
||||
- if [[ $TRAVIS_PYTHON_VERSION == '2.7' ]]; then pip install --use-mirrors contextlib2 mock; fi
|
||||
- if [[ $TRAVIS_PYTHON_VERSION == '3.3' ]]; then pip install --use-mirrors numpy; fi
|
||||
- if [[ $TRAVIS_PYTHON_VERSION == '3.4' ]]; then pip install --use-mirrors numpy; fi
|
||||
|
||||
# command to run tests
|
||||
script:
|
||||
- if [[ $TRAVIS_PYTHON_VERSION == '2.6' ]]; then unit2 discover; fi
|
||||
- if [[ $TRAVIS_PYTHON_VERSION == '2.7' ]]; then python -m unittest discover; fi
|
||||
- if [[ $TRAVIS_PYTHON_VERSION == '3.3' ]]; then python -m unittest discover; fi
|
||||
- if [[ $TRAVIS_PYTHON_VERSION == '3.4' ]]; then python -m unittest discover; fi
|
||||
|
||||
notifications:
|
||||
email: "john.g.evans.ne@gmail.com"
|
||||
|
|
|
|||
|
|
@ -1,3 +1,6 @@
|
|||
May 09, 2014 - v0.5.11 Added support for Python 3.4, OpenJPEG 2.0.1, and
|
||||
OpenJPEG 2.1.0.
|
||||
|
||||
Jan 28, 2014 - v0.5.10 Fixed bad warning when reader requirements box mask
|
||||
length is unsupported.
|
||||
|
||||
|
|
|
|||
|
|
@ -3,7 +3,6 @@ glymur: a Python interface for JPEG 2000
|
|||
|
||||
**glymur** contains a Python interface to the OpenJPEG library which
|
||||
allows one to read and write JPEG 2000 files. **glymur** works on
|
||||
Python 2.6, 2.7 and 3.3. Python 3.3 is strongly
|
||||
recommended.
|
||||
Python 2.6, 2.7, 3.3, and 3.4.
|
||||
|
||||
Please read the docs, https://glymur.readthedocs.org/en/latest/
|
||||
|
|
|
|||
|
|
@ -78,7 +78,7 @@ copyright = u'2013, John Evans'
|
|||
# The short X.Y version.
|
||||
version = '0.5'
|
||||
# The full version, including alpha/beta/rc tags.
|
||||
release = '0.5.10'
|
||||
release = '0.5.11'
|
||||
|
||||
# The language for content autogenerated by Sphinx. Refer to documentation
|
||||
# for a list of supported languages.
|
||||
|
|
|
|||
|
|
@ -7,27 +7,18 @@ Most users won't need to read this! You've been warned...
|
|||
Glymur Configuration
|
||||
''''''''''''''''''''''
|
||||
|
||||
The default glymur installation process relies upon OpenJPEG
|
||||
being properly installed on your system. If you have version 1.5 you can
|
||||
both read and write JPEG 2000 files, but you may wish to install version 2.0
|
||||
or the 2.0+ version from OpenJPEG's development trunk for better performance.
|
||||
If you do that, you should compile it as a shared library (named *openjp2*
|
||||
instead of *openjpeg*) from the developmental source that you can retrieve
|
||||
via subversion. As of this time of writing, svn revision 2347 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. ::
|
||||
The default glymur installation process relies upon OpenJPEG being
|
||||
properly installed on your system as a shared library. You need
|
||||
at least version 1.5 in order to read and write JPEG 2000 files.
|
||||
|
||||
$ svn co http://openjpeg.googlecode.com/svn/data
|
||||
$ export OPJ_DATA_ROOT=`pwd`/data
|
||||
|
||||
Glymur uses ctypes to access the openjp2/openjpeg libraries,
|
||||
and because ctypes accesses libraries in a platform-dependent manner, it is
|
||||
recommended that you create a configuration file to help Glymur properly find
|
||||
the openjpeg or openjp2 libraries (linux users don't need to bother with this
|
||||
if you are using OpenJPEG as provided by your package manager). The
|
||||
configuration format is the same as used by Python's configparser module,
|
||||
Glymur uses ctypes to access the openjp2/openjpeg libraries, and
|
||||
because ctypes accesses libraries in a platform-dependent manner,
|
||||
it is recommended that if you compile and install OpenJPEG into a
|
||||
non-standard location, you should create a configuration file to
|
||||
help Glymur properly find the openjpeg or openjp2 libraries (linux
|
||||
users or macports users don't need to bother with this if you are
|
||||
using OpenJPEG as provided by your package manager). The configuration
|
||||
format is the same as used by Python's configparser module,
|
||||
i.e. ::
|
||||
|
||||
[library]
|
||||
|
|
@ -35,7 +26,7 @@ i.e. ::
|
|||
|
||||
This assumes, of course, that you've installed OpenJPEG into
|
||||
/opt/openjp2-svn on a linux system. The location of the configuration file
|
||||
can vary as well (of course). If you use either linux or mac, the path
|
||||
can vary as well. If you use either linux or mac, the path
|
||||
to the configuration file would normally be ::
|
||||
|
||||
$HOME/.config/glymur/glymurrc
|
||||
|
|
@ -58,78 +49,17 @@ installed in a non-standard place, i.e. ::
|
|||
[library]
|
||||
openjpeg: /not/the/usual/location/lib/libopenjpeg.so
|
||||
|
||||
''''''''''''''''''''''''''''''
|
||||
Package Management Suggestions
|
||||
''''''''''''''''''''''''''''''
|
||||
|
||||
You only need to read this section if you want detailed
|
||||
platform-specific instructions on running as many tests as possible or wish to
|
||||
use your system's package manager to install as many required
|
||||
packages/RPMs/ports/whatever without going through pip.
|
||||
|
||||
|
||||
Mac OS X
|
||||
--------
|
||||
All the necessary packages are available to use glymur with Python 2.6, 2.7,
|
||||
and 3.3 via MacPorts. For python 3.3, you should install the following set of
|
||||
ports:
|
||||
|
||||
* python33
|
||||
* py33-numpy
|
||||
* py33-distribute
|
||||
* py33-matplotlib (optional, for running certain tests)
|
||||
* py33-Pillow (optional, for running certain tests)
|
||||
|
||||
MacPorts supplies both OpenJPEG 1.5.0 and OpenJPEG 2.0.0.
|
||||
|
||||
Linux
|
||||
-----
|
||||
For the most part, you only need python and numpy to run glymur, so on
|
||||
just about all distributions you are already set to go (and you don't
|
||||
need to mess around with a configuration file, as the openjpeg shared
|
||||
libraries are found in the usual places thanks to your package manager).
|
||||
In order to run as many tests as possible, however, the following Python
|
||||
packages may also need to be installed. Consult your package manager
|
||||
documentation or use pip.
|
||||
|
||||
* setuptools
|
||||
* matplotlib
|
||||
* pillow
|
||||
* contextlib2 (python 2.6, 2.7 only)
|
||||
* mock (python 2.6, 2.7 only)
|
||||
* ordereddict (python 2.6 only)
|
||||
|
||||
Glymur's been tested on the following linux platforms without any unexpected
|
||||
difficulties:
|
||||
|
||||
* OpenSUSE 12.3
|
||||
* Fedora 17, 18, 19
|
||||
* Raspian
|
||||
* Travis CI (currently Ubuntu 12.04?)
|
||||
* CentOS 6.4
|
||||
|
||||
Windows
|
||||
-------
|
||||
32-bit WinPython 2.7.5 seemed to work with OpenJPEG 1.X, 2.0, and the
|
||||
development version, but still required contextlib2 and mock to be
|
||||
installed via pip. WinPython 3.3.2, however, seems to have trouble
|
||||
with OpenJPEG 2.0, so I would suggest using the development version with
|
||||
that configuration. I no longer have any access to a windows machine,
|
||||
so I cannot currently offer much guidance here.
|
||||
|
||||
|
||||
'''''''
|
||||
Testing
|
||||
'''''''
|
||||
It is not necessary, but you may wish to download OpenJPEG's test
|
||||
data for the purpose of configuring and running OpenJPEG's test
|
||||
suite. Check their instructions on how to do that. You can then
|
||||
set the **OPJ_DATA_ROOT** environment variable for the purpose of
|
||||
pointing Glymur to OpenJPEG's test suite. ::
|
||||
|
||||
There are two environment variables you may wish to set before running the
|
||||
tests.
|
||||
|
||||
* **OPJ_DATA_ROOT** - points to directory for OpenJPEG test data (see above)
|
||||
* **FORMAT_CORPUS_DATA_ROOT** - points to directory for format-corpus repository (see https://github.com/openplanets/format-corpus if you wish, but you really don't need to bother with this)
|
||||
|
||||
Setting these two environment variables is not required, as any tests using
|
||||
either of them will be skipped.
|
||||
$ svn co http://openjpeg.googlecode.com/svn/data
|
||||
$ export OPJ_DATA_ROOT=`pwd`/data
|
||||
|
||||
In order to run the tests, you can either run them from within
|
||||
python as follows ... ::
|
||||
|
|
@ -141,11 +71,3 @@ or from the command line. ::
|
|||
|
||||
$ cd /to/where/you/unpacked/glymur
|
||||
$ python -m unittest discover
|
||||
|
||||
Quite a few tests are currently skipped. These include tests whose
|
||||
OpenJPEG counterparts are already failing, and others which do pass but
|
||||
still produce heaps of output on stderr. Rather than let this swamp
|
||||
the signal (that most of those tests are actually passing), they've been
|
||||
filtered out for now. There are also more skipped tests on Python 2.7
|
||||
than on Python 3.3. The important part is whether or not any test
|
||||
errors are reported at the end.
|
||||
|
|
|
|||
|
|
@ -4,7 +4,7 @@ How do I...?
|
|||
|
||||
|
||||
... read the lowest resolution thumbnail?
|
||||
=====================================
|
||||
=========================================
|
||||
Printing the Jp2k object should reveal the number of resolutions (look in the
|
||||
COD segment section), but you can take a shortcut by supplying -1 as the
|
||||
resolution level. ::
|
||||
|
|
@ -15,7 +15,7 @@ resolution level. ::
|
|||
>>> thumbnail = j.read(rlevel=-1)
|
||||
|
||||
... display metadata?
|
||||
=================
|
||||
=====================
|
||||
There are two ways. From the unix command line, the script *jp2dump* is
|
||||
available. ::
|
||||
|
||||
|
|
@ -35,7 +35,7 @@ codestream box, only the main header is printed. It is possible to print
|
|||
>>> print(j.get_codestream())
|
||||
|
||||
... add XML metadata?
|
||||
=================
|
||||
=====================
|
||||
You can append any number of XML boxes to a JP2 file (not to a raw codestream).
|
||||
Consider the following XML file `data.xml` : ::
|
||||
|
||||
|
|
@ -67,7 +67,7 @@ The **append** method can add an XML box as shown below::
|
|||
>>> print(jp2)
|
||||
|
||||
... add metadata in a more general fashion?
|
||||
=======================================
|
||||
===========================================
|
||||
An existing raw codestream (or JP2 file) can be wrapped (re-wrapped) in a
|
||||
user-defined set of JP2 boxes. To get just a minimal JP2 jacket on the
|
||||
codestream provided by `goodstuff.j2k` (a file consisting of a raw codestream),
|
||||
|
|
@ -158,11 +158,11 @@ while **append** modifies an existing file and is currently limited to XML
|
|||
boxes.
|
||||
|
||||
... create an image with an alpha layer?
|
||||
====================================
|
||||
========================================
|
||||
|
||||
OpenJPEG can create JP2 files with more than 3 components (requires
|
||||
the development version of OpenJPEG), but by default, any extra components are
|
||||
not described as such. In order to do so, we need to rewrap such
|
||||
OpenJPEG can create JP2 files with more than 3 components (requires version
|
||||
2.1), but by default any extra components are not described as such by the JP2
|
||||
boxes created by OpenJPEG. In order to do so, we need to rewrap such
|
||||
an image in a set of boxes that includes a channel definition box.
|
||||
|
||||
This example is based on SciPy example code found at
|
||||
|
|
|
|||
|
|
@ -13,14 +13,13 @@ some very limited support for reading JPX metadata. For instance,
|
|||
**asoc** and **labl** boxes are recognized, so GMLJP2 metadata can
|
||||
be retrieved from such JPX files.
|
||||
|
||||
Glymur works on Python 2.6, 2.7, and 3.3.
|
||||
Glymur works on Python 2.6, 2.7, 3.3, and 3.4.
|
||||
|
||||
OpenJPEG Installation
|
||||
=====================
|
||||
Glymur will read JPEG 2000 images with versions 1.3, 1.4, 1.5, 2.0,
|
||||
and the trunk/development version of OpenJPEG. Writing images is
|
||||
only supported with the 1.5 or better, however, and the trunk/development
|
||||
version is strongly recommended. For more information about OpenJPEG,
|
||||
Glymur will read JPEG 2000 images with versions 1.3, 1.4, 1.5, 2.0, and 2.1 of
|
||||
OpenJPEG. Writing images is only supported with the 1.5 or better, however,
|
||||
and version 2.1 is strongly recommended. For more information about OpenJPEG,
|
||||
please consult http://www.openjpeg.org.
|
||||
|
||||
If you use MacPorts or if you have a sufficiently recent version of
|
||||
|
|
|
|||
|
|
@ -19,6 +19,7 @@ else:
|
|||
import ctypes
|
||||
import math
|
||||
import os
|
||||
import re
|
||||
import struct
|
||||
import warnings
|
||||
|
||||
|
|
@ -490,16 +491,16 @@ class Jp2k(Jp2kBox):
|
|||
|
||||
opj2.setup_encoder(codec, cparams, image)
|
||||
|
||||
if _OPENJP2_IS_OFFICIAL_V2:
|
||||
if re.match("2.0", version.openjpeg_version):
|
||||
fptr = libc.fopen(self.filename, 'wb')
|
||||
strm = opj2.stream_create_default_file_stream(fptr, False)
|
||||
stack.callback(opj2.stream_destroy, strm)
|
||||
stack.callback(libc.fclose, fptr)
|
||||
else:
|
||||
# This routine introduced in 2.0 devel series.
|
||||
strm = opj2.stream_create_default_file_stream_v3(self.filename,
|
||||
# This routine introduced in 2.1.
|
||||
strm = opj2.stream_create_default_file_stream(self.filename,
|
||||
False)
|
||||
stack.callback(opj2.stream_destroy_v3, strm)
|
||||
stack.callback(opj2.stream_destroy, strm)
|
||||
|
||||
opj2.start_compress(codec, image, strm)
|
||||
opj2.encode(codec, strm)
|
||||
|
|
@ -807,17 +808,16 @@ class Jp2k(Jp2kBox):
|
|||
dparam = self._populate_dparam(layer, rlevel, area, tile)
|
||||
|
||||
with ExitStack() as stack:
|
||||
if hasattr(opj2.OPENJP2,
|
||||
'opj_stream_create_default_file_stream_v3'):
|
||||
filename = self.filename
|
||||
stream = opj2.stream_create_default_file_stream_v3(filename,
|
||||
True)
|
||||
stack.callback(opj2.stream_destroy_v3, stream)
|
||||
else:
|
||||
if re.match("2.0", version.openjpeg_version):
|
||||
fptr = libc.fopen(self.filename, 'rb')
|
||||
stack.callback(libc.fclose, fptr)
|
||||
stream = opj2.stream_create_default_file_stream(fptr, True)
|
||||
stack.callback(opj2.stream_destroy, stream)
|
||||
else:
|
||||
filename = self.filename
|
||||
stream = opj2.stream_create_default_file_stream(filename, True)
|
||||
stack.callback(opj2.stream_destroy, stream)
|
||||
|
||||
codec = opj2.create_decompress(self._codec_format)
|
||||
stack.callback(opj2.destroy_codec, codec)
|
||||
|
||||
|
|
@ -952,17 +952,15 @@ class Jp2k(Jp2kBox):
|
|||
dparam = self._populate_dparam(layer, rlevel, area, tile)
|
||||
|
||||
with ExitStack() as stack:
|
||||
if hasattr(opj2.OPENJP2,
|
||||
'opj_stream_create_default_file_stream_v3'):
|
||||
filename = self.filename
|
||||
stream = opj2.stream_create_default_file_stream_v3(filename,
|
||||
True)
|
||||
stack.callback(opj2.stream_destroy_v3, stream)
|
||||
else:
|
||||
if re.match("2.0", version.openjpeg_version):
|
||||
fptr = libc.fopen(self.filename, 'rb')
|
||||
stack.callback(libc.fclose, fptr)
|
||||
stream = opj2.stream_create_default_file_stream(fptr, True)
|
||||
stack.callback(opj2.stream_destroy, stream)
|
||||
else:
|
||||
filename = self.filename
|
||||
stream = opj2.stream_create_default_file_stream(filename, True)
|
||||
stack.callback(opj2.stream_destroy, stream)
|
||||
codec = opj2.create_decompress(self._codec_format)
|
||||
stack.callback(opj2.destroy_codec, codec)
|
||||
|
||||
|
|
@ -1389,7 +1387,7 @@ def _validate_compression_params(img_array, cparams):
|
|||
msg = "{0}D imagery is not allowed.".format(img_array.ndim)
|
||||
raise IOError(msg)
|
||||
|
||||
if _OPENJP2_IS_OFFICIAL_V2:
|
||||
if re.match("2.0.0", version.openjpeg_version):
|
||||
if (((img_array.ndim != 2) and
|
||||
(img_array.shape[2] != 1 and img_array.shape[2] != 3))):
|
||||
msg = "Writing images is restricted to single-channel "
|
||||
|
|
@ -1402,14 +1400,6 @@ def _validate_compression_params(img_array, cparams):
|
|||
msg = "Only uint8 and uint16 images are currently supported."
|
||||
raise RuntimeError(msg)
|
||||
|
||||
# Need to known if openjp2 library is the officially release v2.0.0 or not.
|
||||
_OPENJP2_IS_OFFICIAL_V2 = False
|
||||
if opj2.OPENJP2 is not None:
|
||||
if opj2.version() == '2.0.0':
|
||||
if not hasattr(opj2.OPENJP2,
|
||||
'opj_stream_create_default_file_stream_v3'):
|
||||
_OPENJP2_IS_OFFICIAL_V2 = True
|
||||
|
||||
_COLORSPACE_MAP = {'rgb': opj2.CLRSPC_SRGB,
|
||||
'gray': opj2.CLRSPC_GRAY,
|
||||
'grey': opj2.CLRSPC_GRAY,
|
||||
|
|
|
|||
|
|
@ -5,11 +5,29 @@ Wraps individual functions in openjp2 library.
|
|||
# pylint: disable=C0302,R0903,W0201
|
||||
|
||||
import ctypes
|
||||
import re
|
||||
import sys
|
||||
|
||||
from .config import glymur_config
|
||||
OPENJP2, OPENJPEG = glymur_config()
|
||||
|
||||
def version():
|
||||
"""Wrapper for opj_version library routine."""
|
||||
try:
|
||||
OPENJP2.opj_version.restype = ctypes.c_char_p
|
||||
except AttributeError:
|
||||
# No library, so the version is zero.
|
||||
return "0.0.0"
|
||||
library_version = OPENJP2.opj_version()
|
||||
if sys.hexversion >= 0x03000000:
|
||||
return library_version.decode('utf-8')
|
||||
else:
|
||||
return library_version
|
||||
|
||||
if OPENJP2 is not None:
|
||||
_MAJOR, _MINOR, _PATH = version().split('.')
|
||||
else:
|
||||
_MINOR = 0
|
||||
ERROR_MSG_LST = []
|
||||
|
||||
# Map certain atomic OpenJPEG datatypes to the ctypes equivalents.
|
||||
|
|
@ -353,6 +371,16 @@ class CompressionParametersType(ctypes.Structure):
|
|||
# based encoding without offset concerning all the components.
|
||||
("mct_data", ctypes.c_void_p)]
|
||||
|
||||
if _MINOR == '1':
|
||||
# Maximum size (in bytes) for the whole codestream.
|
||||
# If == 0, codestream size limitation is not considered.
|
||||
# If it does not comply with tcp_rates, max_cs_size prevails and a
|
||||
# warning is issued.
|
||||
_fields_.append(("max_cs_size", ctypes.c_int32))
|
||||
|
||||
# To be used to combine OPJ_PROFILE_*, OPJ_EXTENSION_* and (sub)levels
|
||||
# values.
|
||||
_fields_.append(("rsiz", ctypes.c_uint16))
|
||||
|
||||
class ImageCompType(ctypes.Structure):
|
||||
"""Defines a single image component.
|
||||
|
|
@ -392,6 +420,9 @@ class ImageCompType(ctypes.Structure):
|
|||
# image component data
|
||||
("data", ctypes.POINTER(ctypes.c_int32))]
|
||||
|
||||
if _MINOR == '1':
|
||||
_fields_.append(("alpha", ctypes.c_uint16))
|
||||
|
||||
|
||||
class ImageType(ctypes.Structure):
|
||||
"""Defines image data and characteristics.
|
||||
|
|
@ -1261,11 +1292,10 @@ def start_compress(codec, image, stream):
|
|||
OPENJP2.opj_start_compress(codec, image, stream)
|
||||
|
||||
|
||||
def stream_create_default_file_stream(fptr, isa_read_stream):
|
||||
def _stream_create_default_file_stream_2p0(fptr, isa_read_stream):
|
||||
"""Wraps openjp2 library function opj_stream_create_default_vile_stream.
|
||||
|
||||
Sets the stream to be a file stream. This is valid only for version 2.0.0
|
||||
of OpenJPEG.
|
||||
Sets the stream to be a file stream.
|
||||
|
||||
Parameters
|
||||
----------
|
||||
|
|
@ -1287,11 +1317,10 @@ def stream_create_default_file_stream(fptr, isa_read_stream):
|
|||
return stream
|
||||
|
||||
|
||||
def stream_create_default_file_stream_v3(fname, isa_read_stream):
|
||||
"""Wraps openjp2 library function opj_stream_create_default_vile_stream_v3.
|
||||
def _stream_create_default_file_stream_2p1(fname, isa_read_stream):
|
||||
"""Wraps openjp2 library function opj_stream_create_default_vile_stream.
|
||||
|
||||
Sets the stream to be a file stream. This function is only valid for the
|
||||
trunk/development 2.0+ version of the openjp2 library.
|
||||
Sets the stream to be a file stream.
|
||||
|
||||
Parameters
|
||||
----------
|
||||
|
|
@ -1306,14 +1335,18 @@ def stream_create_default_file_stream_v3(fname, isa_read_stream):
|
|||
An OpenJPEG file stream.
|
||||
"""
|
||||
ARGTYPES = [ctypes.c_char_p, ctypes.c_int32]
|
||||
OPENJP2.opj_stream_create_default_file_stream_v3.argtypes = ARGTYPES
|
||||
OPENJP2.opj_stream_create_default_file_stream_v3.restype = STREAM_TYPE_P
|
||||
OPENJP2.opj_stream_create_default_file_stream.argtypes = ARGTYPES
|
||||
OPENJP2.opj_stream_create_default_file_stream.restype = STREAM_TYPE_P
|
||||
read_stream = 1 if isa_read_stream else 0
|
||||
file_argument = ctypes.c_char_p(fname.encode())
|
||||
stream = OPENJP2.opj_stream_create_default_file_stream_v3(file_argument,
|
||||
read_stream)
|
||||
stream = OPENJP2.opj_stream_create_default_file_stream(file_argument,
|
||||
read_stream)
|
||||
return stream
|
||||
|
||||
if re.match(r'''2.0''', version()):
|
||||
stream_create_default_file_stream = _stream_create_default_file_stream_2p0
|
||||
else:
|
||||
stream_create_default_file_stream = _stream_create_default_file_stream_2p1
|
||||
|
||||
def stream_destroy(stream):
|
||||
"""Wraps openjp2 library function opj_stream_destroy.
|
||||
|
|
@ -1330,21 +1363,6 @@ def stream_destroy(stream):
|
|||
OPENJP2.opj_stream_destroy(stream)
|
||||
|
||||
|
||||
def stream_destroy_v3(stream):
|
||||
"""Wraps openjp2 library function opj_stream_destroy_v3.
|
||||
|
||||
Destroys the stream created by create_stream_v3.
|
||||
|
||||
Parameters
|
||||
----------
|
||||
stream : STREAM_TYPE_P
|
||||
The file stream.
|
||||
"""
|
||||
OPENJP2.opj_stream_destroy_v3.argtypes = [STREAM_TYPE_P]
|
||||
OPENJP2.opj_stream_destroy_v3.restype = ctypes.c_void_p
|
||||
OPENJP2.opj_stream_destroy_v3(stream)
|
||||
|
||||
|
||||
def write_tile(codec, tile_index, data, data_size, stream):
|
||||
"""Wraps openjp2 library function opj_write_tile.
|
||||
|
||||
|
|
@ -1388,11 +1406,3 @@ def set_error_message(msg):
|
|||
ERROR_MSG_LST.append(msg)
|
||||
|
||||
|
||||
def version():
|
||||
"""Wrapper for opj_version library routine."""
|
||||
OPENJP2.opj_version.restype = ctypes.c_char_p
|
||||
library_version = OPENJP2.opj_version()
|
||||
if sys.hexversion >= 0x03000000:
|
||||
return library_version.decode('utf-8')
|
||||
else:
|
||||
return library_version
|
||||
|
|
|
|||
|
|
@ -9,6 +9,7 @@ Tests for libopenjp2 wrapping functions.
|
|||
# pylint: disable=F0401
|
||||
|
||||
import os
|
||||
import re
|
||||
import sys
|
||||
import tempfile
|
||||
|
||||
|
|
@ -22,17 +23,15 @@ import numpy as np
|
|||
import glymur
|
||||
from glymur.lib import openjp2
|
||||
|
||||
OPENJP2_IS_V2_OFFICIAL = False
|
||||
if openjp2.OPENJP2 is not None:
|
||||
if not hasattr(openjp2.OPENJP2,
|
||||
'opj_stream_create_default_file_stream_v3'):
|
||||
OPENJP2_IS_V2_OFFICIAL = True
|
||||
|
||||
if re.match("2.0", glymur.version.openjpeg_version):
|
||||
OPENJP2_IS_V2_OFFICIAL = True
|
||||
else:
|
||||
OPENJP2_IS_V2_OFFICIAL = False
|
||||
|
||||
@unittest.skipIf(os.name == "nt", "Temporary file issue on window.")
|
||||
@unittest.skipIf(openjp2.OPENJP2 is None,
|
||||
"Missing openjp2 library.")
|
||||
@unittest.skipIf(OPENJP2_IS_V2_OFFICIAL, "API followed here specific to V2.0+")
|
||||
@unittest.skipIf(OPENJP2_IS_V2_OFFICIAL, "API followed here specific to V2.1")
|
||||
class TestOpenJP2(unittest.TestCase):
|
||||
"""Test openjp2 library functionality.
|
||||
|
||||
|
|
@ -89,7 +88,7 @@ class TestOpenJP2(unittest.TestCase):
|
|||
openjp2.set_warning_handler(codec, None)
|
||||
openjp2.set_error_handler(codec, None)
|
||||
|
||||
stream = openjp2.stream_create_default_file_stream_v3(filename, True)
|
||||
stream = openjp2.stream_create_default_file_stream(filename, True)
|
||||
|
||||
openjp2.setup_decoder(codec, dparam)
|
||||
image = openjp2.read_header(stream, codec)
|
||||
|
|
@ -110,7 +109,7 @@ class TestOpenJP2(unittest.TestCase):
|
|||
|
||||
openjp2.end_decompress(codec, stream)
|
||||
openjp2.destroy_codec(codec)
|
||||
openjp2.stream_destroy_v3(stream)
|
||||
openjp2.stream_destroy(stream)
|
||||
openjp2.image_destroy(image)
|
||||
|
||||
def test_tte0(self):
|
||||
|
|
@ -318,15 +317,15 @@ def tile_encoder(**kwargs):
|
|||
|
||||
openjp2.setup_encoder(codec, l_param, l_image)
|
||||
|
||||
stream = openjp2.stream_create_default_file_stream_v3(kwargs['filename'],
|
||||
False)
|
||||
stream = openjp2.stream_create_default_file_stream(kwargs['filename'],
|
||||
False)
|
||||
openjp2.start_compress(codec, l_image, stream)
|
||||
|
||||
for j in np.arange(num_tiles):
|
||||
openjp2.write_tile(codec, j, data, tile_size, stream)
|
||||
|
||||
openjp2.end_compress(codec, stream)
|
||||
openjp2.stream_destroy_v3(stream)
|
||||
openjp2.stream_destroy(stream)
|
||||
openjp2.destroy_codec(codec)
|
||||
openjp2.image_destroy(l_image)
|
||||
|
||||
|
|
@ -335,8 +334,8 @@ def tile_decoder(**kwargs):
|
|||
|
||||
Reads a tile. That's all it does.
|
||||
"""
|
||||
stream = openjp2.stream_create_default_file_stream_v3(kwargs['filename'],
|
||||
True)
|
||||
stream = openjp2.stream_create_default_file_stream(kwargs['filename'],
|
||||
True)
|
||||
dparam = openjp2.set_default_decoder_parameters()
|
||||
|
||||
dparam.decod_format = kwargs['codec_format']
|
||||
|
|
@ -371,7 +370,7 @@ def tile_decoder(**kwargs):
|
|||
|
||||
openjp2.end_decompress(codec, stream)
|
||||
openjp2.destroy_codec(codec)
|
||||
openjp2.stream_destroy_v3(stream)
|
||||
openjp2.stream_destroy(stream)
|
||||
openjp2.image_destroy(image)
|
||||
|
||||
def ttx0_setup(filename):
|
||||
|
|
|
|||
|
|
@ -167,3 +167,252 @@ def read_pgx_header(pgx_file):
|
|||
|
||||
header = header.rstrip()
|
||||
return header, pos
|
||||
|
||||
text_gbr_27 = """Colour Specification Box (colr) @ (179, 1339)
|
||||
Method: any ICC profile
|
||||
Precedence: 2
|
||||
Approximation: accurately represents correct colorspace definition
|
||||
ICC Profile:
|
||||
{'Color Space': 'RGB',
|
||||
'Connection Space': 'XYZ',
|
||||
'Creator': u'appl',
|
||||
'Datetime': datetime.datetime(2009, 2, 25, 11, 26, 11),
|
||||
'Device Attributes': 'reflective, glossy, positive media polarity, color media',
|
||||
'Device Class': 'display device profile',
|
||||
'Device Manufacturer': u'appl',
|
||||
'Device Model': '',
|
||||
'File Signature': u'acsp',
|
||||
'Flags': 'not embedded, can be used independently',
|
||||
'Illuminant': array([ 0.96420288, 1. , 0.8249054 ]),
|
||||
'Platform': u'APPL',
|
||||
'Preferred CMM Type': 1634758764,
|
||||
'Rendering Intent': 'perceptual',
|
||||
'Size': 1328,
|
||||
'Version': '2.2.0'}"""
|
||||
|
||||
text_gbr_33 = """Colour Specification Box (colr) @ (179, 1339)
|
||||
Method: any ICC profile
|
||||
Precedence: 2
|
||||
Approximation: accurately represents correct colorspace definition
|
||||
ICC Profile:
|
||||
{'Size': 1328,
|
||||
'Preferred CMM Type': 1634758764,
|
||||
'Version': '2.2.0',
|
||||
'Device Class': 'display device profile',
|
||||
'Color Space': 'RGB',
|
||||
'Connection Space': 'XYZ',
|
||||
'Datetime': datetime.datetime(2009, 2, 25, 11, 26, 11),
|
||||
'File Signature': 'acsp',
|
||||
'Platform': 'APPL',
|
||||
'Flags': 'not embedded, can be used independently',
|
||||
'Device Manufacturer': 'appl',
|
||||
'Device Model': '',
|
||||
'Device Attributes': 'reflective, glossy, positive media polarity, color media',
|
||||
'Rendering Intent': 'perceptual',
|
||||
'Illuminant': array([ 0.96420288, 1. , 0.8249054 ]),
|
||||
'Creator': 'appl'}"""
|
||||
|
||||
text_gbr_34 = """Colour Specification Box (colr) @ (179, 1339)
|
||||
Method: any ICC profile
|
||||
Precedence: 2
|
||||
Approximation: accurately represents correct colorspace definition
|
||||
ICC Profile:
|
||||
{'Size': 1328,
|
||||
'Preferred CMM Type': 1634758764,
|
||||
'Version': '2.2.0',
|
||||
'Device Class': 'display device profile',
|
||||
'Color Space': 'RGB',
|
||||
'Connection Space': 'XYZ',
|
||||
'Datetime': datetime.datetime(2009, 2, 25, 11, 26, 11),
|
||||
'File Signature': 'acsp',
|
||||
'Platform': 'APPL',
|
||||
'Flags': 'not embedded, can be used independently',
|
||||
'Device Manufacturer': 'appl',
|
||||
'Device Model': '',
|
||||
'Device Attributes': 'reflective, glossy, positive media polarity, color '
|
||||
'media',
|
||||
'Rendering Intent': 'perceptual',
|
||||
'Illuminant': array([ 0.96420288, 1. , 0.8249054 ]),
|
||||
'Creator': 'appl'}"""
|
||||
|
||||
|
||||
# Metadata dump of nemo.
|
||||
nemo_dump_full_opj2 = r'''JPEG 2000 Signature Box (jP ) @ (0, 12)
|
||||
Signature: 0d0a870a
|
||||
File Type Box (ftyp) @ (12, 20)
|
||||
Brand: jp2
|
||||
Compatibility: ['jp2 ']
|
||||
JP2 Header Box (jp2h) @ (32, 45)
|
||||
Image Header Box (ihdr) @ (40, 22)
|
||||
Size: [1456 2592 3]
|
||||
Bitdepth: 8
|
||||
Signed: False
|
||||
Compression: wavelet
|
||||
Colorspace Unknown: False
|
||||
Colour Specification Box (colr) @ (62, 15)
|
||||
Method: enumerated colorspace
|
||||
Precedence: 0
|
||||
Colorspace: sRGB
|
||||
UUID Box (uuid) @ (77, 638)
|
||||
UUID: 4a706754-6966-6645-7869-662d3e4a5032 (Exif)
|
||||
UUID Data:
|
||||
{'Image': {'Make': 'HTC',
|
||||
'Model': 'HTC Glacier',
|
||||
'XResolution': 72.0,
|
||||
'YResolution': 72.0,
|
||||
'ResolutionUnit': 2,
|
||||
'YCbCrPositioning': 1,
|
||||
'ExifTag': 138,
|
||||
'GPSTag': 354},
|
||||
'Photo': {'ISOSpeedRatings': 76,
|
||||
'ExifVersion': (48, 50, 50, 48),
|
||||
'DateTimeOriginal': '2013:02:09 14:47:53',
|
||||
'DateTimeDigitized': '2013:02:09 14:47:53',
|
||||
'ComponentsConfiguration': (1, 2, 3, 0),
|
||||
'FocalLength': 3.53,
|
||||
'FlashpixVersion': (48, 49, 48, 48),
|
||||
'ColorSpace': 1,
|
||||
'PixelXDimension': 2528,
|
||||
'PixelYDimension': 1424,
|
||||
'InteroperabilityTag': 324},
|
||||
'GPSInfo': {'GPSVersionID': (2, 2, 0),
|
||||
'GPSLatitudeRef': 'N',
|
||||
'GPSLatitude': [42.0, 20.0, 33.61],
|
||||
'GPSLongitudeRef': 'W',
|
||||
'GPSLongitude': [71.0, 5.0, 17.32],
|
||||
'GPSAltitudeRef': 0,
|
||||
'GPSAltitude': 0.0,
|
||||
'GPSTimeStamp': [19.0, 47.0, 53.0],
|
||||
'GPSMapDatum': 'WGS-84',
|
||||
'GPSProcessingMethod': (65,
|
||||
83,
|
||||
67,
|
||||
73,
|
||||
73,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
78,
|
||||
69,
|
||||
84,
|
||||
87,
|
||||
79,
|
||||
82,
|
||||
75),
|
||||
'GPSDateStamp': '2013:02:09'},
|
||||
'Iop': None}
|
||||
UUID Box (uuid) @ (715, 2412)
|
||||
UUID: be7acfcb-97a9-42e8-9c71-999491e3afac (XMP)
|
||||
UUID Data:
|
||||
<ns0:xmpmeta xmlns:ns0="adobe:ns:meta/" xmlns:ns2="http://ns.adobe.com/xap/1.0/" xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" ns0:xmptk="XMP Core 4.4.0-Exiv2">
|
||||
<rdf:RDF>
|
||||
<rdf:Description ns2:CreatorTool="glymur" rdf:about="" />
|
||||
</rdf:RDF>
|
||||
</ns0:xmpmeta>
|
||||
|
||||
Contiguous Codestream Box (jp2c) @ (3127, 1132296)
|
||||
Main header:
|
||||
SOC marker segment @ (3135, 0)
|
||||
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: (1456 x 2592)
|
||||
Vertical, Horizontal Reference Tile Offset: (0 x 0)
|
||||
Bitdepth: (8, 8, 8)
|
||||
Signed: (False, False, False)
|
||||
Vertical, Horizontal Subsampling: ((1, 1), (1, 1), (1, 1))
|
||||
COD marker segment @ (3186, 12)
|
||||
Coding style:
|
||||
Entropy coder, without partitions
|
||||
SOP marker segments: False
|
||||
EPH marker segments: False
|
||||
Coding style parameters:
|
||||
Progression order: LRCP
|
||||
Number of layers: 2
|
||||
Multiple component transformation usage: reversible
|
||||
Number of resolutions: 2
|
||||
Code block height, width: (64 x 64)
|
||||
Wavelet transform: 5-3 reversible
|
||||
Precinct size: default, 2^15 x 2^15
|
||||
Code block context:
|
||||
Selective arithmetic coding bypass: False
|
||||
Reset context probabilities on coding pass boundaries: False
|
||||
Termination on each coding pass: False
|
||||
Vertically stripe causal context: False
|
||||
Predictable termination: False
|
||||
Segmentation symbols: False
|
||||
QCD marker segment @ (3200, 7)
|
||||
Quantization style: no quantization, 2 guard bits
|
||||
Step size: [(0, 8), (0, 9), (0, 9), (0, 10)]
|
||||
CME marker segment @ (3209, 37)
|
||||
"Created by OpenJPEG version 2.0.0"'''
|
||||
nemo_dump_full_p27 = r'''JPEG 2000 Signature Box (jP ) @ (0, 12)
|
||||
Signature: 0d0a870a
|
||||
File Type Box (ftyp) @ (12, 20)
|
||||
Brand: jp2
|
||||
Compatibility: ['jp2 ']
|
||||
JP2 Header Box (jp2h) @ (32, 45)
|
||||
Image Header Box (ihdr) @ (40, 22)
|
||||
Size: [1456 2592 3]
|
||||
Bitdepth: 8
|
||||
Signed: False
|
||||
Compression: wavelet
|
||||
Colorspace Unknown: False
|
||||
Colour Specification Box (colr) @ (62, 15)
|
||||
Method: enumerated colorspace
|
||||
Precedence: 0
|
||||
Colorspace: sRGB
|
||||
UUID Box (uuid) @ (77, 638)
|
||||
UUID: 4a706754-6966-6645-7869-662d3e4a5032 (Exif)
|
||||
UUID Data:
|
||||
{'GPSInfo': OrderedDict([('GPSVersionID', (2, 2, 0)), ('GPSLatitudeRef', 'N'), ('GPSLatitude', [42.0, 20.0, 33.61]), ('GPSLongitudeRef', 'W'), ('GPSLongitude', [71.0, 5.0, 17.32]), ('GPSAltitudeRef', 0), ('GPSAltitude', 0.0), ('GPSTimeStamp', [19.0, 47.0, 53.0]), ('GPSMapDatum', 'WGS-84'), ('GPSProcessingMethod', (65, 83, 67, 73, 73, 0, 0, 0, 78, 69, 84, 87, 79, 82, 75)), ('GPSDateStamp', '2013:02:09')]),
|
||||
'Image': OrderedDict([('Make', 'HTC'), ('Model', 'HTC Glacier'), ('XResolution', 72.0), ('YResolution', 72.0), ('ResolutionUnit', 2), ('YCbCrPositioning', 1), ('ExifTag', 138), ('GPSTag', 354)]),
|
||||
'Iop': None,
|
||||
'Photo': OrderedDict([('ISOSpeedRatings', 76), ('ExifVersion', (48, 50, 50, 48)), ('DateTimeOriginal', '2013:02:09 14:47:53'), ('DateTimeDigitized', '2013:02:09 14:47:53'), ('ComponentsConfiguration', (1, 2, 3, 0)), ('FocalLength', 3.53), ('FlashpixVersion', (48, 49, 48, 48)), ('ColorSpace', 1), ('PixelXDimension', 2528), ('PixelYDimension', 1424), ('InteroperabilityTag', 324)])}
|
||||
UUID Box (uuid) @ (715, 2412)
|
||||
UUID: be7acfcb-97a9-42e8-9c71-999491e3afac (XMP)
|
||||
UUID Data:
|
||||
<ns0:xmpmeta xmlns:ns0="adobe:ns:meta/" xmlns:ns2="http://ns.adobe.com/xap/1.0/" xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" ns0:xmptk="XMP Core 4.4.0-Exiv2">
|
||||
<rdf:RDF>
|
||||
<rdf:Description ns2:CreatorTool="glymur" rdf:about="" />
|
||||
</rdf:RDF>
|
||||
</ns0:xmpmeta>
|
||||
|
||||
Contiguous Codestream Box (jp2c) @ (3127, 1132296)
|
||||
Main header:
|
||||
SOC marker segment @ (3135, 0)
|
||||
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: (1456 x 2592)
|
||||
Vertical, Horizontal Reference Tile Offset: (0 x 0)
|
||||
Bitdepth: (8, 8, 8)
|
||||
Signed: (False, False, False)
|
||||
Vertical, Horizontal Subsampling: ((1, 1), (1, 1), (1, 1))
|
||||
COD marker segment @ (3186, 12)
|
||||
Coding style:
|
||||
Entropy coder, without partitions
|
||||
SOP marker segments: False
|
||||
EPH marker segments: False
|
||||
Coding style parameters:
|
||||
Progression order: LRCP
|
||||
Number of layers: 2
|
||||
Multiple component transformation usage: reversible
|
||||
Number of resolutions: 2
|
||||
Code block height, width: (64 x 64)
|
||||
Wavelet transform: 5-3 reversible
|
||||
Precinct size: default, 2^15 x 2^15
|
||||
Code block context:
|
||||
Selective arithmetic coding bypass: False
|
||||
Reset context probabilities on coding pass boundaries: False
|
||||
Termination on each coding pass: False
|
||||
Vertically stripe causal context: False
|
||||
Predictable termination: False
|
||||
Segmentation symbols: False
|
||||
QCD marker segment @ (3200, 7)
|
||||
Quantization style: no quantization, 2 guard bits
|
||||
Step size: [(0, 8), (0, 9), (0, 9), (0, 10)]
|
||||
CME marker segment @ (3209, 37)
|
||||
"Created by OpenJPEG version 2.0.0"'''
|
||||
|
|
|
|||
|
|
@ -15,6 +15,7 @@ import os
|
|||
import struct
|
||||
import sys
|
||||
import tempfile
|
||||
import warnings
|
||||
|
||||
if sys.hexversion < 0x02070000:
|
||||
import unittest2 as unittest
|
||||
|
|
@ -98,8 +99,10 @@ class TestCodestream(unittest.TestCase):
|
|||
tfile.write(read_buffer)
|
||||
tfile.flush()
|
||||
|
||||
with self.assertWarns(UserWarning):
|
||||
with warnings.catch_warnings(record=True) as w:
|
||||
warnings.simplefilter("always")
|
||||
codestream = Jp2k(tfile.name).get_codestream()
|
||||
self.assertEqual(len(w), 1)
|
||||
|
||||
self.assertEqual(codestream.segment[2].marker_id, '0xff79')
|
||||
self.assertEqual(codestream.segment[2].length, 3)
|
||||
|
|
|
|||
|
|
@ -15,6 +15,7 @@ import imp
|
|||
import os
|
||||
import sys
|
||||
import tempfile
|
||||
import warnings
|
||||
|
||||
if sys.hexversion < 0x02070000:
|
||||
import unittest2 as unittest
|
||||
|
|
@ -87,8 +88,10 @@ class TestSuite(unittest.TestCase):
|
|||
with patch.dict('os.environ', {'XDG_CONFIG_HOME': tdir}):
|
||||
# Misconfigured new configuration file should
|
||||
# be rejected.
|
||||
with self.assertWarns(UserWarning):
|
||||
with warnings.catch_warnings(record=True) as w:
|
||||
warnings.simplefilter("always")
|
||||
imp.reload(glymur.lib.openjp2)
|
||||
self.assertEqual(len(w), 1)
|
||||
|
||||
|
||||
@unittest.skipIf(glymur.lib.openjp2.OPENJP2 is None and
|
||||
|
|
|
|||
|
|
@ -14,6 +14,7 @@ import os
|
|||
from os.path import join
|
||||
import re
|
||||
import sys
|
||||
import warnings
|
||||
|
||||
if sys.hexversion < 0x02070000:
|
||||
import unittest2 as unittest
|
||||
|
|
@ -36,8 +37,6 @@ except KeyError:
|
|||
|
||||
@unittest.skipIf(FORMAT_CORPUS_DATA_ROOT is None,
|
||||
"FORMAT_CORPUS_DATA_ROOT environment variable not set")
|
||||
@unittest.skipIf(sys.hexversion < 0x03020000,
|
||||
"Requires features introduced in 3.2 (assertWarns)")
|
||||
class TestSuiteFormatCorpus(unittest.TestCase):
|
||||
"""Test suite for files in format corpus repository."""
|
||||
|
||||
|
|
@ -49,32 +48,16 @@ class TestSuiteFormatCorpus(unittest.TestCase):
|
|||
jfile = os.path.join(FORMAT_CORPUS_DATA_ROOT,
|
||||
'jp2k-test/byteCorruption/balloon_trunc1.jp2')
|
||||
j2k = Jp2k(jfile)
|
||||
with self.assertWarns(UserWarning):
|
||||
with warnings.catch_warnings(record=True) as w:
|
||||
warnings.simplefilter("always")
|
||||
codestream = j2k.get_codestream(header_only=False)
|
||||
self.assertEqual(len(w), 1)
|
||||
|
||||
# The last segment is truncated, so there should not be an EOC marker.
|
||||
self.assertNotEqual(codestream.segment[-1].marker_id, 'EOC')
|
||||
|
||||
# The codestream is not as long as claimed.
|
||||
with self.assertRaises(OSError):
|
||||
j2k.read(rlevel=-1)
|
||||
|
||||
@unittest.skipIf(re.match(r"""1\.[01234]""",
|
||||
glymur.version.openjpeg_version) is not None,
|
||||
"Needs 1.4+ to catch this.")
|
||||
def test_balloon_trunc2(self):
|
||||
"""Shortened by 5000 bytes."""
|
||||
jfile = os.path.join(FORMAT_CORPUS_DATA_ROOT,
|
||||
'jp2k-test/byteCorruption/balloon_trunc2.jp2')
|
||||
j2k = Jp2k(jfile)
|
||||
with self.assertWarns(UserWarning):
|
||||
codestream = j2k.get_codestream(header_only=False)
|
||||
|
||||
# The last segment is truncated, so there should not be an EOC marker.
|
||||
self.assertNotEqual(codestream.segment[-1].marker_id, 'EOC')
|
||||
|
||||
# The codestream is not as long as claimed.
|
||||
with self.assertRaises(OSError):
|
||||
with self.assertRaises((OSError, IOError)):
|
||||
j2k.read(rlevel=-1)
|
||||
|
||||
def test_balloon_trunc3(self):
|
||||
|
|
@ -82,8 +65,10 @@ class TestSuiteFormatCorpus(unittest.TestCase):
|
|||
jfile = os.path.join(FORMAT_CORPUS_DATA_ROOT,
|
||||
'jp2k-test/byteCorruption/balloon_trunc3.jp2')
|
||||
j2k = Jp2k(jfile)
|
||||
with self.assertWarns(UserWarning):
|
||||
with warnings.catch_warnings(record=True) as w:
|
||||
warnings.simplefilter("always")
|
||||
codestream = j2k.get_codestream(header_only=False)
|
||||
self.assertEqual(len(w), 1)
|
||||
|
||||
# The last segment is truncated, so there should not be an EOC marker.
|
||||
self.assertNotEqual(codestream.segment[-1].marker_id, 'EOC')
|
||||
|
|
@ -97,8 +82,10 @@ class TestSuiteFormatCorpus(unittest.TestCase):
|
|||
jfile = os.path.join(FORMAT_CORPUS_DATA_ROOT,
|
||||
'jp2k-test', 'icc',
|
||||
'balloon_eciRGBv2_ps_adobeplugin.jpf')
|
||||
with self.assertWarns(UserWarning):
|
||||
with warnings.catch_warnings(record=True) as w:
|
||||
warnings.simplefilter("always")
|
||||
Jp2k(jfile)
|
||||
self.assertEqual(len(w), 1)
|
||||
|
||||
def test_jp2_brand_iccpr_mult_colr(self):
|
||||
"""Has colr box, one that conforms, one that does not."""
|
||||
|
|
@ -109,14 +96,14 @@ class TestSuiteFormatCorpus(unittest.TestCase):
|
|||
# ("Input Device") changed relative to original profile.
|
||||
jfile = join(FORMAT_CORPUS_DATA_ROOT, 'jp2k-test', 'icc',
|
||||
'balloon_eciRGBv2_ps_adobeplugin_jp2compatible.jpf')
|
||||
with self.assertWarns(UserWarning):
|
||||
with warnings.catch_warnings(record=True) as w:
|
||||
warnings.simplefilter("always")
|
||||
Jp2k(jfile)
|
||||
self.assertEqual(len(w), 1)
|
||||
|
||||
|
||||
@unittest.skipIf(OPJ_DATA_ROOT is None,
|
||||
"OPJ_DATA_ROOT environment variable not set")
|
||||
@unittest.skipIf(sys.hexversion < 0x03020000,
|
||||
"Requires features introduced in 3.2 (assertWarns)")
|
||||
class TestSuiteOpj(unittest.TestCase):
|
||||
"""Test suite for files in openjpeg repository."""
|
||||
|
||||
|
|
@ -130,8 +117,10 @@ class TestSuiteOpj(unittest.TestCase):
|
|||
"""If 'jp2 ', then the method cannot be any icc profile."""
|
||||
filename = os.path.join(OPJ_DATA_ROOT,
|
||||
'input/nonregression/text_GBR.jp2')
|
||||
with self.assertWarns(UserWarning):
|
||||
with warnings.catch_warnings(record=True) as w:
|
||||
warnings.simplefilter("always")
|
||||
Jp2k(filename)
|
||||
self.assertEqual(len(w), 1)
|
||||
|
||||
if __name__ == "__main__":
|
||||
unittest.main()
|
||||
|
|
|
|||
|
|
@ -11,6 +11,7 @@ ICC profile tests.
|
|||
import datetime
|
||||
import os
|
||||
import sys
|
||||
import warnings
|
||||
|
||||
if sys.hexversion < 0x02070000:
|
||||
import unittest2 as unittest
|
||||
|
|
@ -65,16 +66,16 @@ class TestICC(unittest.TestCase):
|
|||
|
||||
self.assertEqual(profile['Creator'], 'JPEG')
|
||||
|
||||
@unittest.skipIf(sys.hexversion < 0x03020000,
|
||||
"Uses features introduced in 3.2.")
|
||||
def test_invalid_profile_header(self):
|
||||
"""invalid ICC header data should cause UserWarning"""
|
||||
jfile = opj_data_file('input/nonregression/orb-blue10-lin-jp2.jp2')
|
||||
|
||||
# assertWarns in Python 3.3 (python2.7/pylint issue)
|
||||
# pylint: disable=E1101
|
||||
with self.assertWarns(UserWarning):
|
||||
with warnings.catch_warnings(record=True) as w:
|
||||
warnings.simplefilter("always")
|
||||
Jp2k(jfile)
|
||||
self.assertEqual(len(w), 1)
|
||||
|
||||
if __name__ == "__main__":
|
||||
unittest.main()
|
||||
|
|
|
|||
|
|
@ -18,6 +18,7 @@ Test suite specifically targeting JP2 box layout.
|
|||
|
||||
import doctest
|
||||
import os
|
||||
import re
|
||||
import shutil
|
||||
import struct
|
||||
import sys
|
||||
|
|
@ -57,7 +58,7 @@ def load_tests(loader, tests, ignore):
|
|||
return tests
|
||||
|
||||
@unittest.skipIf(glymur.version.openjpeg_version_tuple[0] < 2 or
|
||||
OPENJP2_IS_V2_OFFICIAL,
|
||||
re.match(r'''2.0.0''', glymur.version.openjpeg_version),
|
||||
"Not supported until 2.0+.")
|
||||
@unittest.skipIf(os.name == "nt", "Temporary file issue on window.")
|
||||
class TestChannelDefinition(unittest.TestCase):
|
||||
|
|
|
|||
|
|
@ -53,8 +53,10 @@ class TestReaderRequirements(unittest.TestCase):
|
|||
tfile.write(nemof.read())
|
||||
tfile.flush()
|
||||
|
||||
with self.assertWarns(UserWarning):
|
||||
with warnings.catch_warnings(record=True) as w:
|
||||
warnings.simplefilter("always")
|
||||
j = Jp2k(tfile.name)
|
||||
self.assertEqual(len(w), 1)
|
||||
self.assertEqual(j.box[2].box_id, 'rreq')
|
||||
self.assertEqual(type(j.box[2]),
|
||||
glymur.jp2box.ReaderRequirementsBox)
|
||||
|
|
|
|||
|
|
@ -23,6 +23,7 @@ import sys
|
|||
import tempfile
|
||||
import warnings
|
||||
import xml.etree.cElementTree as ET
|
||||
import warnings
|
||||
|
||||
if sys.hexversion < 0x03000000:
|
||||
from StringIO import StringIO
|
||||
|
|
@ -212,18 +213,12 @@ class TestJp2kBadXmlFile(unittest.TestCase):
|
|||
def tearDown(self):
|
||||
pass
|
||||
|
||||
@unittest.skipIf(sys.hexversion < 0x03020000,
|
||||
"Uses features introduced in 3.2.")
|
||||
def test_invalid_xml_box_warning(self):
|
||||
"""Should warn in case of bad XML"""
|
||||
with self.assertWarns(UserWarning):
|
||||
Jp2k(self._bad_xml_file)
|
||||
|
||||
def test_invalid_xml_box(self):
|
||||
"""Should be able to recover info from xml box with bad xml."""
|
||||
with warnings.catch_warnings():
|
||||
warnings.simplefilter("ignore")
|
||||
with warnings.catch_warnings(record=True) as w:
|
||||
warnings.simplefilter("always")
|
||||
jp2k = Jp2k(self._bad_xml_file)
|
||||
self.assertEqual(len(w), 1)
|
||||
|
||||
self.assertEqual(jp2k.box[3].box_id, 'xml ')
|
||||
self.assertEqual(jp2k.box[3].offset, 77)
|
||||
|
|
@ -276,8 +271,10 @@ class TestBadButRecoverableXmlFile(unittest.TestCase):
|
|||
"Uses features introduced in 3.2.")
|
||||
def test_bad_xml_box_warning(self):
|
||||
"""Should warn in case of bad XML"""
|
||||
with self.assertWarns(UserWarning):
|
||||
with warnings.catch_warnings(record=True) as w:
|
||||
warnings.simplefilter("always")
|
||||
Jp2k(self._bad_xml_file)
|
||||
self.assertEqual(len(w), 1)
|
||||
|
||||
def test_recover_from_bad_xml(self):
|
||||
"""Should be able to recover info from xml box with bad xml."""
|
||||
|
|
|
|||
|
|
@ -1,9 +1,6 @@
|
|||
"""
|
||||
Tests for general glymur functionality.
|
||||
"""
|
||||
# E1101: assertWarns introduced in python 3.2
|
||||
# pylint: disable=E1101
|
||||
|
||||
# R0904: Not too many methods in unittest.
|
||||
# pylint: disable=R0904
|
||||
|
||||
|
|
@ -384,13 +381,9 @@ class TestJp2k(unittest.TestCase):
|
|||
|
||||
# Verify that a warning is issued, but only on python3.
|
||||
# On python2, just suppress the warning.
|
||||
if sys.hexversion < 0x03030000:
|
||||
with warnings.catch_warnings():
|
||||
warnings.simplefilter("ignore")
|
||||
j = Jp2k(tfile.name)
|
||||
else:
|
||||
with self.assertWarns(UserWarning):
|
||||
j = Jp2k(tfile.name)
|
||||
with warnings.catch_warnings():
|
||||
warnings.simplefilter("ignore")
|
||||
j = Jp2k(tfile.name)
|
||||
|
||||
exif = j.box[3].data
|
||||
# Were the tag == 271, 'Make' would be in the keys instead.
|
||||
|
|
@ -590,8 +583,8 @@ class TestJp2k_1_x(unittest.TestCase):
|
|||
j2k.read(layer=1)
|
||||
|
||||
|
||||
@unittest.skipIf(not OPENJP2_IS_V2_OFFICIAL,
|
||||
"Tests only to be run on 2.0 official.")
|
||||
@unittest.skipIf(re.match("2.0.0", glymur.version.openjpeg_version) is None,
|
||||
"Tests only to be run on 2.0.0.")
|
||||
class TestJp2k_2_0_official(unittest.TestCase):
|
||||
"""Test suite to only be run on v2.0 official."""
|
||||
|
||||
|
|
|
|||
File diff suppressed because it is too large
Load diff
407
glymur/test/test_opj_suite_2p1.py
Normal file
407
glymur/test/test_opj_suite_2p1.py
Normal file
|
|
@ -0,0 +1,407 @@
|
|||
"""
|
||||
The tests defined here roughly correspond to what is in the OpenJPEG test
|
||||
suite.
|
||||
"""
|
||||
|
||||
# Some test names correspond with openjpeg tests. Long names are ok in this
|
||||
# case.
|
||||
# pylint: disable=C0103
|
||||
|
||||
# All of these tests correspond to tests in openjpeg, so no docstring is really
|
||||
# needed.
|
||||
# pylint: disable=C0111
|
||||
|
||||
# This module is very long, cannot be helped.
|
||||
# pylint: disable=C0302
|
||||
|
||||
# unittest fools pylint with "too many public methods"
|
||||
# pylint: disable=R0904
|
||||
|
||||
# Some tests use numpy test infrastructure, which means the tests never
|
||||
# reference "self", so pylint claims it should be a function. No, no, no.
|
||||
# pylint: disable=R0201
|
||||
|
||||
# Many tests are pretty long and that can't be helped.
|
||||
# pylint: disable=R0915
|
||||
|
||||
# asserWarns introduced in python 3.2 (python2.7/pylint issue)
|
||||
# pylint: disable=E1101
|
||||
|
||||
# unittest2 is python2.6 only (pylint/python-2.7)
|
||||
# pylint: disable=F0401
|
||||
|
||||
import re
|
||||
import sys
|
||||
|
||||
if sys.hexversion < 0x02070000:
|
||||
import unittest2 as unittest
|
||||
else:
|
||||
import unittest
|
||||
|
||||
import warnings
|
||||
|
||||
import numpy as np
|
||||
|
||||
from glymur import Jp2k
|
||||
import glymur
|
||||
|
||||
from .fixtures import OPENJP2_IS_V2_OFFICIAL, OPJ_DATA_ROOT
|
||||
from .fixtures import mse, peak_tolerance, read_pgx, opj_data_file
|
||||
|
||||
|
||||
@unittest.skipIf(OPJ_DATA_ROOT is None,
|
||||
"OPJ_DATA_ROOT environment variable not set")
|
||||
@unittest.skipIf(re.match(r'''2.0.0''', glymur.version.openjpeg_version),
|
||||
"Tests not introduced until 2.0.1")
|
||||
@unittest.skipIf(glymur.version.openjpeg_version_tuple[0] == 1,
|
||||
"Tests not introduced until 2.1")
|
||||
class TestSuite2point1(unittest.TestCase):
|
||||
"""Runs tests introduced in version 2.0+ or that pass only in 2.0+"""
|
||||
|
||||
def setUp(self):
|
||||
pass
|
||||
|
||||
def tearDown(self):
|
||||
pass
|
||||
|
||||
def test_NR_DEC_text_GBR_jp2_29_decode(self):
|
||||
jfile = opj_data_file('input/nonregression/text_GBR.jp2')
|
||||
with warnings.catch_warnings():
|
||||
# brand is 'jp2 ', but has any icc profile.
|
||||
warnings.simplefilter("ignore")
|
||||
jp2 = Jp2k(jfile)
|
||||
jp2.read()
|
||||
self.assertTrue(True)
|
||||
|
||||
def test_NR_DEC_kodak_2layers_lrcp_j2c_31_decode(self):
|
||||
jfile = opj_data_file('input/nonregression/kodak_2layers_lrcp.j2c')
|
||||
Jp2k(jfile).read()
|
||||
self.assertTrue(True)
|
||||
|
||||
def test_NR_DEC_kodak_2layers_lrcp_j2c_32_decode(self):
|
||||
jfile = opj_data_file('input/nonregression/kodak_2layers_lrcp.j2c')
|
||||
Jp2k(jfile).read(layer=2)
|
||||
self.assertTrue(True)
|
||||
|
||||
def test_NR_DEC_issue104_jpxstream_jp2_33_decode(self):
|
||||
jfile = opj_data_file('input/nonregression/issue104_jpxstream.jp2')
|
||||
Jp2k(jfile).read()
|
||||
self.assertTrue(True)
|
||||
|
||||
def test_NR_DEC_mem_b2b86b74_2753_jp2_35_decode(self):
|
||||
jfile = opj_data_file('input/nonregression/mem-b2b86b74-2753.jp2')
|
||||
Jp2k(jfile).read()
|
||||
self.assertTrue(True)
|
||||
|
||||
def test_NR_DEC_gdal_fuzzer_unchecked_num_resolutions_jp2_36_decode(self):
|
||||
f = 'input/nonregression/gdal_fuzzer_unchecked_numresolutions.jp2'
|
||||
jfile = opj_data_file(f)
|
||||
with warnings.catch_warnings():
|
||||
# Invalid number of resolutions.
|
||||
warnings.simplefilter("ignore")
|
||||
j = Jp2k(jfile)
|
||||
with self.assertRaises(IOError):
|
||||
j.read()
|
||||
|
||||
def test_NR_DEC_gdal_fuzzer_check_number_of_tiles_jp2_38_decode(self):
|
||||
relpath = 'input/nonregression/gdal_fuzzer_check_number_of_tiles.jp2'
|
||||
jfile = opj_data_file(relpath)
|
||||
with warnings.catch_warnings():
|
||||
# Invalid number of tiles.
|
||||
warnings.simplefilter("ignore")
|
||||
j = Jp2k(jfile)
|
||||
with self.assertRaises(IOError):
|
||||
j.read()
|
||||
|
||||
def test_NR_DEC_gdal_fuzzer_check_comp_dx_dy_jp2_39_decode(self):
|
||||
relpath = 'input/nonregression/gdal_fuzzer_check_comp_dx_dy.jp2'
|
||||
jfile = opj_data_file(relpath)
|
||||
with warnings.catch_warnings():
|
||||
# Invalid subsampling value
|
||||
warnings.simplefilter("ignore")
|
||||
with self.assertRaises(IOError):
|
||||
Jp2k(jfile).read()
|
||||
|
||||
def test_NR_DEC_file_409752_jp2_40_decode(self):
|
||||
jfile = opj_data_file('input/nonregression/file409752.jp2')
|
||||
with self.assertRaises(RuntimeError):
|
||||
Jp2k(jfile).read()
|
||||
|
||||
def test_NR_DEC_issue188_beach_64bitsbox_jp2_41_decode(self):
|
||||
# Has an 'XML ' box instead of 'xml '. Yes that is pedantic, but it
|
||||
# really does deserve a warning.
|
||||
relpath = 'input/nonregression/issue188_beach_64bitsbox.jp2'
|
||||
jfile = opj_data_file(relpath)
|
||||
with warnings.catch_warnings(record=True) as w:
|
||||
warnings.simplefilter("always")
|
||||
Jp2k(jfile).read()
|
||||
self.assertEqual(len(w), 1)
|
||||
|
||||
def test_NR_DEC_issue206_image_000_jp2_42_decode(self):
|
||||
jfile = opj_data_file('input/nonregression/issue206_image-000.jp2')
|
||||
Jp2k(jfile).read()
|
||||
self.assertTrue(True)
|
||||
|
||||
def test_NR_DEC_p1_04_j2k_43_decode(self):
|
||||
jfile = opj_data_file('input/conformance/p1_04.j2k')
|
||||
jp2k = Jp2k(jfile)
|
||||
ssdata = jp2k.read(area=(0, 0, 1024, 1024))
|
||||
odata = jp2k.read()
|
||||
np.testing.assert_array_equal(ssdata, odata)
|
||||
|
||||
def test_NR_DEC_p1_04_j2k_44_decode(self):
|
||||
jfile = opj_data_file('input/conformance/p1_04.j2k')
|
||||
jp2k = Jp2k(jfile)
|
||||
ssdata = jp2k.read(area=(640, 512, 768, 640))
|
||||
odata = jp2k.read()
|
||||
np.testing.assert_array_equal(ssdata, odata[640:768, 512:640])
|
||||
|
||||
def test_NR_DEC_p1_04_j2k_45_decode(self):
|
||||
jfile = opj_data_file('input/conformance/p1_04.j2k')
|
||||
jp2k = Jp2k(jfile)
|
||||
ssdata = jp2k.read(area=(896, 896, 1024, 1024))
|
||||
odata = jp2k.read()
|
||||
np.testing.assert_array_equal(ssdata, odata[896:1024, 896:1024])
|
||||
|
||||
def test_NR_DEC_p1_04_j2k_46_decode(self):
|
||||
jfile = opj_data_file('input/conformance/p1_04.j2k')
|
||||
jp2k = Jp2k(jfile)
|
||||
ssdata = jp2k.read(area=(500, 100, 800, 300))
|
||||
odata = jp2k.read()
|
||||
np.testing.assert_array_equal(ssdata, odata[500:800, 100:300])
|
||||
|
||||
def test_NR_DEC_p1_04_j2k_47_decode(self):
|
||||
jfile = opj_data_file('input/conformance/p1_04.j2k')
|
||||
jp2k = Jp2k(jfile)
|
||||
ssdata = jp2k.read(area=(520, 260, 600, 360))
|
||||
odata = jp2k.read()
|
||||
np.testing.assert_array_equal(ssdata, odata[520:600, 260:360])
|
||||
|
||||
def test_NR_DEC_p1_04_j2k_48_decode(self):
|
||||
jfile = opj_data_file('input/conformance/p1_04.j2k')
|
||||
jp2k = Jp2k(jfile)
|
||||
ssdata = jp2k.read(area=(520, 260, 660, 360))
|
||||
odata = jp2k.read()
|
||||
np.testing.assert_array_equal(ssdata, odata[520:660, 260:360])
|
||||
|
||||
def test_NR_DEC_p1_04_j2k_49_decode(self):
|
||||
jfile = opj_data_file('input/conformance/p1_04.j2k')
|
||||
jp2k = Jp2k(jfile)
|
||||
ssdata = jp2k.read(area=(520, 360, 600, 400))
|
||||
odata = jp2k.read()
|
||||
np.testing.assert_array_equal(ssdata, odata[520:600, 360:400])
|
||||
|
||||
def test_NR_DEC_p1_04_j2k_50_decode(self):
|
||||
jfile = opj_data_file('input/conformance/p1_04.j2k')
|
||||
jp2k = Jp2k(jfile)
|
||||
ssdata = jp2k.read(area=(0, 0, 1024, 1024), rlevel=2)
|
||||
odata = jp2k.read(rlevel=2)
|
||||
|
||||
np.testing.assert_array_equal(ssdata, odata[0:256, 0:256])
|
||||
|
||||
def test_NR_DEC_p1_04_j2k_51_decode(self):
|
||||
jfile = opj_data_file('input/conformance/p1_04.j2k')
|
||||
jp2k = Jp2k(jfile)
|
||||
ssdata = jp2k.read(area=(640, 512, 768, 640), rlevel=2)
|
||||
odata = jp2k.read(rlevel=2)
|
||||
np.testing.assert_array_equal(ssdata, odata[160:192, 128:160])
|
||||
|
||||
def test_NR_DEC_p1_04_j2k_52_decode(self):
|
||||
jfile = opj_data_file('input/conformance/p1_04.j2k')
|
||||
jp2k = Jp2k(jfile)
|
||||
ssdata = jp2k.read(area=(896, 896, 1024, 1024), rlevel=2)
|
||||
odata = jp2k.read(rlevel=2)
|
||||
np.testing.assert_array_equal(ssdata, odata[224:352, 224:352])
|
||||
|
||||
def test_NR_DEC_p1_04_j2k_53_decode(self):
|
||||
jfile = opj_data_file('input/conformance/p1_04.j2k')
|
||||
jp2k = Jp2k(jfile)
|
||||
ssdata = jp2k.read(area=(500, 100, 800, 300), rlevel=2)
|
||||
odata = jp2k.read(rlevel=2)
|
||||
np.testing.assert_array_equal(ssdata, odata[125:200, 25:75])
|
||||
|
||||
def test_NR_DEC_p1_04_j2k_54_decode(self):
|
||||
jfile = opj_data_file('input/conformance/p1_04.j2k')
|
||||
jp2k = Jp2k(jfile)
|
||||
ssdata = jp2k.read(area=(520, 260, 600, 360), rlevel=2)
|
||||
odata = jp2k.read(rlevel=2)
|
||||
np.testing.assert_array_equal(ssdata, odata[130:150, 65:90])
|
||||
|
||||
def test_NR_DEC_p1_04_j2k_55_decode(self):
|
||||
jfile = opj_data_file('input/conformance/p1_04.j2k')
|
||||
jp2k = Jp2k(jfile)
|
||||
ssdata = jp2k.read(area=(520, 260, 660, 360), rlevel=2)
|
||||
odata = jp2k.read(rlevel=2)
|
||||
np.testing.assert_array_equal(ssdata, odata[130:165, 65:90])
|
||||
|
||||
def test_NR_DEC_p1_04_j2k_56_decode(self):
|
||||
jfile = opj_data_file('input/conformance/p1_04.j2k')
|
||||
jp2k = Jp2k(jfile)
|
||||
ssdata = jp2k.read(area=(520, 360, 600, 400), rlevel=2)
|
||||
odata = jp2k.read(rlevel=2)
|
||||
np.testing.assert_array_equal(ssdata, odata[130:150, 90:100])
|
||||
|
||||
def test_NR_DEC_p1_04_j2k_57_decode(self):
|
||||
jfile = opj_data_file('input/conformance/p1_04.j2k')
|
||||
jp2k = Jp2k(jfile)
|
||||
tdata = jp2k.read(tile=63) # last tile
|
||||
odata = jp2k.read()
|
||||
np.testing.assert_array_equal(tdata, odata[896:1024, 896:1024])
|
||||
|
||||
def test_NR_DEC_p1_04_j2k_58_decode(self):
|
||||
jfile = opj_data_file('input/conformance/p1_04.j2k')
|
||||
jp2k = Jp2k(jfile)
|
||||
tdata = jp2k.read(tile=63, rlevel=2) # last tile
|
||||
odata = jp2k.read(rlevel=2)
|
||||
np.testing.assert_array_equal(tdata, odata[224:256, 224:256])
|
||||
|
||||
def test_NR_DEC_p1_04_j2k_59_decode(self):
|
||||
jfile = opj_data_file('input/conformance/p1_04.j2k')
|
||||
jp2k = Jp2k(jfile)
|
||||
tdata = jp2k.read(tile=12) # 2nd row, 5th column
|
||||
odata = jp2k.read()
|
||||
np.testing.assert_array_equal(tdata, odata[128:256, 512:640])
|
||||
|
||||
def test_NR_DEC_p1_04_j2k_60_decode(self):
|
||||
jfile = opj_data_file('input/conformance/p1_04.j2k')
|
||||
jp2k = Jp2k(jfile)
|
||||
tdata = jp2k.read(tile=12, rlevel=1) # 2nd row, 5th column
|
||||
odata = jp2k.read(rlevel=1)
|
||||
np.testing.assert_array_equal(tdata, odata[64:128, 256:320])
|
||||
|
||||
def test_NR_DEC_jp2_36_decode(self):
|
||||
lst = ('input',
|
||||
'nonregression',
|
||||
'gdal_fuzzer_assert_in_opj_j2k_read_SQcd_SQcc.patch.jp2')
|
||||
jfile = opj_data_file('/'.join(lst))
|
||||
with warnings.catch_warnings():
|
||||
# Invalid component number.
|
||||
warnings.simplefilter("ignore")
|
||||
j = Jp2k(jfile)
|
||||
with self.assertRaises(IOError):
|
||||
j.read()
|
||||
|
||||
def test_NR_DEC_p1_06_j2k_70_decode(self):
|
||||
jfile = opj_data_file('input/conformance/p1_06.j2k')
|
||||
jp2k = Jp2k(jfile)
|
||||
ssdata = jp2k.read(area=(9, 9, 12, 12), rlevel=1)
|
||||
self.assertEqual(ssdata.shape, (1, 1, 3))
|
||||
|
||||
def test_NR_DEC_p1_06_j2k_71_decode(self):
|
||||
jfile = opj_data_file('input/conformance/p1_06.j2k')
|
||||
jp2k = Jp2k(jfile)
|
||||
ssdata = jp2k.read(area=(10, 4, 12, 10), rlevel=1)
|
||||
self.assertEqual(ssdata.shape, (1, 3, 3))
|
||||
|
||||
def test_NR_DEC_p1_06_j2k_72_decode(self):
|
||||
jfile = opj_data_file('input/conformance/p1_06.j2k')
|
||||
jp2k = Jp2k(jfile)
|
||||
ssdata = jp2k.read(area=(3, 3, 9, 9), rlevel=1)
|
||||
self.assertEqual(ssdata.shape, (3, 3, 3))
|
||||
|
||||
def test_NR_DEC_p1_06_j2k_73_decode(self):
|
||||
jfile = opj_data_file('input/conformance/p1_06.j2k')
|
||||
jp2k = Jp2k(jfile)
|
||||
ssdata = jp2k.read(area=(4, 4, 7, 7), rlevel=1)
|
||||
self.assertEqual(ssdata.shape, (2, 2, 3))
|
||||
|
||||
def test_NR_DEC_p1_06_j2k_74_decode(self):
|
||||
jfile = opj_data_file('input/conformance/p1_06.j2k')
|
||||
jp2k = Jp2k(jfile)
|
||||
ssdata = jp2k.read(area=(4, 4, 5, 5), rlevel=1)
|
||||
self.assertEqual(ssdata.shape, (1, 1, 3))
|
||||
|
||||
def test_NR_DEC_p1_06_j2k_75_decode(self):
|
||||
# Image size would be 0 x 0.
|
||||
jfile = opj_data_file('input/conformance/p1_06.j2k')
|
||||
jp2k = Jp2k(jfile)
|
||||
with self.assertRaises((IOError, OSError)):
|
||||
jp2k.read(area=(9, 9, 12, 12), rlevel=2)
|
||||
|
||||
def test_NR_DEC_p0_04_j2k_85_decode(self):
|
||||
jfile = opj_data_file('input/conformance/p0_04.j2k')
|
||||
jp2k = Jp2k(jfile)
|
||||
ssdata = jp2k.read(area=(0, 0, 256, 256))
|
||||
fulldata = jp2k.read()
|
||||
np.testing.assert_array_equal(fulldata[0:256, 0:256], ssdata)
|
||||
|
||||
def test_NR_DEC_p0_04_j2k_86_decode(self):
|
||||
jfile = opj_data_file('input/conformance/p0_04.j2k')
|
||||
jp2k = Jp2k(jfile)
|
||||
ssdata = jp2k.read(area=(0, 128, 128, 256))
|
||||
fulldata = jp2k.read()
|
||||
np.testing.assert_array_equal(fulldata[0:128, 128:256], ssdata)
|
||||
|
||||
def test_NR_DEC_p0_04_j2k_87_decode(self):
|
||||
jfile = opj_data_file('input/conformance/p0_04.j2k')
|
||||
jp2k = Jp2k(jfile)
|
||||
ssdata = jp2k.read(area=(10, 50, 200, 120))
|
||||
fulldata = jp2k.read()
|
||||
np.testing.assert_array_equal(fulldata[10:200, 50:120], ssdata)
|
||||
|
||||
def test_NR_DEC_p0_04_j2k_88_decode(self):
|
||||
jfile = opj_data_file('input/conformance/p0_04.j2k')
|
||||
jp2k = Jp2k(jfile)
|
||||
ssdata = jp2k.read(area=(150, 10, 210, 190))
|
||||
fulldata = jp2k.read()
|
||||
np.testing.assert_array_equal(fulldata[150:210, 10:190], ssdata)
|
||||
|
||||
def test_NR_DEC_p0_04_j2k_89_decode(self):
|
||||
jfile = opj_data_file('input/conformance/p0_04.j2k')
|
||||
jp2k = Jp2k(jfile)
|
||||
ssdata = jp2k.read(area=(80, 100, 150, 200))
|
||||
fulldata = jp2k.read()
|
||||
np.testing.assert_array_equal(fulldata[80:150, 100:200], ssdata)
|
||||
|
||||
def test_NR_DEC_p0_04_j2k_90_decode(self):
|
||||
jfile = opj_data_file('input/conformance/p0_04.j2k')
|
||||
jp2k = Jp2k(jfile)
|
||||
ssdata = jp2k.read(area=(20, 150, 50, 200))
|
||||
fulldata = jp2k.read()
|
||||
np.testing.assert_array_equal(fulldata[20:50, 150:200], ssdata)
|
||||
|
||||
def test_NR_DEC_p0_04_j2k_91_decode(self):
|
||||
jfile = opj_data_file('input/conformance/p0_04.j2k')
|
||||
jp2k = Jp2k(jfile)
|
||||
ssdata = jp2k.read(area=(0, 0, 256, 256), rlevel=2)
|
||||
fulldata = jp2k.read(rlevel=2)
|
||||
np.testing.assert_array_equal(fulldata[0:64, 0:64], ssdata)
|
||||
|
||||
def test_NR_DEC_p0_04_j2k_92_decode(self):
|
||||
jfile = opj_data_file('input/conformance/p0_04.j2k')
|
||||
jp2k = Jp2k(jfile)
|
||||
ssdata = jp2k.read(area=(0, 128, 128, 256), rlevel=2)
|
||||
fulldata = jp2k.read(rlevel=2)
|
||||
np.testing.assert_array_equal(fulldata[0:32, 32:64], ssdata)
|
||||
|
||||
def test_NR_DEC_p0_04_j2k_93_decode(self):
|
||||
jfile = opj_data_file('input/conformance/p0_04.j2k')
|
||||
jp2k = Jp2k(jfile)
|
||||
ssdata = jp2k.read(area=(10, 50, 200, 120), rlevel=2)
|
||||
fulldata = jp2k.read(rlevel=2)
|
||||
np.testing.assert_array_equal(fulldata[3:50, 13:30], ssdata)
|
||||
|
||||
def test_NR_DEC_p0_04_j2k_94_decode(self):
|
||||
jfile = opj_data_file('input/conformance/p0_04.j2k')
|
||||
jp2k = Jp2k(jfile)
|
||||
ssdata = jp2k.read(area=(150, 10, 210, 190), rlevel=2)
|
||||
fulldata = jp2k.read(rlevel=2)
|
||||
np.testing.assert_array_equal(fulldata[38:53, 3:48], ssdata)
|
||||
|
||||
def test_NR_DEC_p0_04_j2k_95_decode(self):
|
||||
jfile = opj_data_file('input/conformance/p0_04.j2k')
|
||||
jp2k = Jp2k(jfile)
|
||||
ssdata = jp2k.read(area=(80, 100, 150, 200), rlevel=2)
|
||||
fulldata = jp2k.read(rlevel=2)
|
||||
np.testing.assert_array_equal(fulldata[20:38, 25:50], ssdata)
|
||||
|
||||
def test_NR_DEC_p0_04_j2k_96_decode(self):
|
||||
jfile = opj_data_file('input/conformance/p0_04.j2k')
|
||||
jp2k = Jp2k(jfile)
|
||||
ssdata = jp2k.read(area=(20, 150, 50, 200), rlevel=2)
|
||||
fulldata = jp2k.read(rlevel=2)
|
||||
np.testing.assert_array_equal(fulldata[5:13, 38:50], ssdata)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
unittest.main()
|
||||
|
|
@ -2,9 +2,6 @@
|
|||
The tests here do not correspond directly to the OpenJPEG test suite, but
|
||||
seem like logical negative tests to add.
|
||||
"""
|
||||
# E1101: assertWarns introduced in python 3.2
|
||||
# pylint: disable=E1101
|
||||
|
||||
# R0904: Not too many methods in unittest.
|
||||
# pylint: disable=R0904
|
||||
|
||||
|
|
@ -15,6 +12,7 @@ import os
|
|||
import re
|
||||
import sys
|
||||
import tempfile
|
||||
import warnings
|
||||
|
||||
if sys.hexversion < 0x02070000:
|
||||
import unittest2 as unittest
|
||||
|
|
@ -64,15 +62,15 @@ class TestSuiteNegative(unittest.TestCase):
|
|||
jp2k.get_codestream(header_only=False)
|
||||
self.assertTrue(True)
|
||||
|
||||
@unittest.skipIf(sys.hexversion < 0x03020000,
|
||||
"Uses features introduced in 3.2.")
|
||||
def test_nr_illegalclrtransform(self):
|
||||
"""EOC marker is bad"""
|
||||
relpath = 'input/nonregression/illegalcolortransform.j2k'
|
||||
jfile = opj_data_file(relpath)
|
||||
jp2k = Jp2k(jfile)
|
||||
with self.assertWarns(UserWarning):
|
||||
with warnings.catch_warnings(record=True) as w:
|
||||
warnings.simplefilter("always")
|
||||
codestream = jp2k.get_codestream(header_only=False)
|
||||
self.assertEqual(len(w), 1)
|
||||
|
||||
# Verify that the last segment returned in the codestream is SOD,
|
||||
# not EOC. Codestream parsing should stop when we try to jump to
|
||||
|
|
@ -106,8 +104,6 @@ class TestSuiteNegative(unittest.TestCase):
|
|||
with self.assertRaises(IOError):
|
||||
j.write(data, cbsize=(2, 2048))
|
||||
|
||||
@unittest.skipIf(sys.hexversion < 0x03020000,
|
||||
"Uses features introduced in 3.2.")
|
||||
def test_exceeded_box(self):
|
||||
"""should warn if reading past end of a box"""
|
||||
# Verify that a warning is issued if we read past the end of a box
|
||||
|
|
@ -115,7 +111,8 @@ class TestSuiteNegative(unittest.TestCase):
|
|||
# short.
|
||||
infile = os.path.join(OPJ_DATA_ROOT,
|
||||
'input/nonregression/mem-b2ace68c-1381.jp2')
|
||||
with self.assertWarns(UserWarning):
|
||||
with warnings.catch_warnings(record=True) as w:
|
||||
warnings.simplefilter("ignore")
|
||||
Jp2k(infile)
|
||||
|
||||
@unittest.skipIf(os.name == "nt", "Temporary file issue on window.")
|
||||
|
|
|
|||
|
|
@ -794,7 +794,6 @@ class TestSuiteWrite(unittest.TestCase):
|
|||
glymur.core.WAVELET_XFORM_5X3_REVERSIBLE)
|
||||
self.assertEqual(len(codestream.segment[2].spcod), 9)
|
||||
|
||||
@unittest.skip("Known failure in openjpeg test suite.")
|
||||
def test_NR_ENC_random_issue_0005_tif_12_encode(self):
|
||||
"""NR-ENC-random-issue-0005.tif-12-encode"""
|
||||
# opj_decompress has trouble reading it, but that is not an issue here.
|
||||
|
|
|
|||
|
|
@ -35,7 +35,9 @@ else:
|
|||
|
||||
import glymur
|
||||
from glymur import Jp2k
|
||||
from . import fixtures
|
||||
from .fixtures import OPJ_DATA_ROOT, opj_data_file
|
||||
from .fixtures import text_gbr_27, text_gbr_33, text_gbr_34
|
||||
|
||||
|
||||
@unittest.skipIf(os.name == "nt", "Temporary file issue on window.")
|
||||
|
|
@ -185,31 +187,23 @@ class TestPrintingNeedsLib(unittest.TestCase):
|
|||
expected = '\n'.join(lines)
|
||||
self.assertEqual(actual, expected)
|
||||
|
||||
@unittest.skipIf(sys.hexversion < 0x02070000, "Do not bother with 2.6")
|
||||
def test_jp2dump(self):
|
||||
"""basic jp2dump test"""
|
||||
with patch('sys.stdout', new=StringIO()) as fake_out:
|
||||
glymur.jp2dump(self._plain_nemo_file)
|
||||
glymur.jp2dump(glymur.data.nemo())
|
||||
actual = fake_out.getvalue().strip()
|
||||
|
||||
# Get rid of the filename line, as it is not set in stone.
|
||||
lst = actual.split('\n')
|
||||
lst = lst[1:]
|
||||
actual = '\n'.join(lst)
|
||||
self.assertEqual(actual, self.expected_plain)
|
||||
|
||||
def test_entire_file(self):
|
||||
"""verify output from printing entire file"""
|
||||
j = glymur.Jp2k(self._plain_nemo_file)
|
||||
with patch('sys.stdout', new=StringIO()) as fake_out:
|
||||
print(j)
|
||||
actual = fake_out.getvalue().strip()
|
||||
|
||||
# Get rid of the filename line, as it is not set in stone.
|
||||
lst = actual.split('\n')
|
||||
lst = lst[1:]
|
||||
actual = '\n'.join(lst)
|
||||
|
||||
self.assertEqual(actual, self.expected_plain)
|
||||
self.maxDiff = None
|
||||
if sys.hexversion < 0x02080000:
|
||||
# Ordered dicts are different in 2.7
|
||||
self.assertEqual(actual, fixtures.nemo_dump_full_p27)
|
||||
else:
|
||||
self.assertEqual(actual, fixtures.nemo_dump_full_opj2)
|
||||
|
||||
|
||||
class TestPrinting(unittest.TestCase):
|
||||
|
|
@ -287,70 +281,25 @@ class TestPrinting(unittest.TestCase):
|
|||
@unittest.skipIf(OPJ_DATA_ROOT is None,
|
||||
"OPJ_DATA_ROOT environment variable not set")
|
||||
def test_icc_profile(self):
|
||||
"""verify printing of colr box with ICC profile"""
|
||||
"""verify icc profile printing with a jpx"""
|
||||
# ICC profiles may be used in JP2, but the approximation field should
|
||||
# be zero unless we have jpx. This file does both.
|
||||
filename = opj_data_file('input/nonregression/text_GBR.jp2')
|
||||
with warnings.catch_warnings():
|
||||
# brand is 'jp2 ', but has any icc profile.
|
||||
warnings.simplefilter("ignore")
|
||||
jp2 = Jp2k(filename)
|
||||
|
||||
with patch('sys.stdout', new=StringIO()) as fake_out:
|
||||
print(jp2.box[3].box[1])
|
||||
actual = fake_out.getvalue().strip()
|
||||
lin27 = ["Colour Specification Box (colr) @ (179, 1339)",
|
||||
" Method: any ICC profile",
|
||||
" Precedence: 2",
|
||||
" Approximation: accurately represents correct "
|
||||
+ "colorspace definition",
|
||||
" ICC Profile:",
|
||||
" {'Color Space': 'RGB',",
|
||||
" 'Connection Space': 'XYZ',",
|
||||
" 'Creator': u'appl',",
|
||||
" 'Datetime': "
|
||||
+ "datetime.datetime(2009, 2, 25, 11, 26, 11),",
|
||||
" 'Device Attributes': 'reflective, glossy, "
|
||||
+ "positive media polarity, color media',",
|
||||
" 'Device Class': 'display device profile',",
|
||||
" 'Device Manufacturer': u'appl',",
|
||||
" 'Device Model': '',",
|
||||
" 'File Signature': u'acsp',",
|
||||
" 'Flags': "
|
||||
+ "'not embedded, can be used independently',",
|
||||
" 'Illuminant': "
|
||||
+ "array([ 0.96420288, 1. , 0.8249054 ]),",
|
||||
" 'Platform': u'APPL',",
|
||||
" 'Preferred CMM Type': 1634758764,",
|
||||
" 'Rendering Intent': 'perceptual',",
|
||||
" 'Size': 1328,",
|
||||
" 'Version': '2.2.0'}"]
|
||||
lin33 = ["Colour Specification Box (colr) @ (179, 1339)",
|
||||
" Method: any ICC profile",
|
||||
" Precedence: 2",
|
||||
" Approximation: accurately represents correct "
|
||||
+ "colorspace definition",
|
||||
" ICC Profile:",
|
||||
" {'Size': 1328,",
|
||||
" 'Preferred CMM Type': 1634758764,",
|
||||
" 'Version': '2.2.0',",
|
||||
" 'Device Class': 'display device profile',",
|
||||
" 'Color Space': 'RGB',",
|
||||
" 'Connection Space': 'XYZ',",
|
||||
" 'Datetime': "
|
||||
+ "datetime.datetime(2009, 2, 25, 11, 26, 11),",
|
||||
" 'File Signature': 'acsp',",
|
||||
" 'Platform': 'APPL',",
|
||||
" 'Flags': 'not embedded, can be used "
|
||||
+ "independently',",
|
||||
" 'Device Manufacturer': 'appl',",
|
||||
" 'Device Model': '',",
|
||||
" 'Device Attributes': 'reflective, glossy, "
|
||||
+ "positive media polarity, color media',",
|
||||
" 'Rendering Intent': 'perceptual',",
|
||||
" 'Illuminant': "
|
||||
+ "array([ 0.96420288, 1. , 0.8249054 ]),",
|
||||
" 'Creator': 'appl'}"]
|
||||
if sys.hexversion < 0x03000000:
|
||||
expected = text_gbr_27
|
||||
elif sys.hexversion < 0x03040000:
|
||||
expected = text_gbr_33
|
||||
else:
|
||||
expected = text_gbr_34
|
||||
|
||||
lines = lin27 if sys.hexversion < 0x03000000 else lin33
|
||||
expected = '\n'.join(lines)
|
||||
self.assertEqual(actual, expected)
|
||||
|
||||
@unittest.skipIf(OPJ_DATA_ROOT is None,
|
||||
|
|
@ -980,7 +929,7 @@ class TestPrinting(unittest.TestCase):
|
|||
@unittest.skipIf(OPJ_DATA_ROOT is None,
|
||||
"OPJ_DATA_ROOT environment variable not set")
|
||||
def test_jpx_approx_icc_profile(self):
|
||||
"""verify jpx with approx field equal to zero"""
|
||||
"""verify icc profile printing with a jpx"""
|
||||
# ICC profiles may be used in JP2, but the approximation field should
|
||||
# be zero unless we have jpx. This file does both.
|
||||
filename = opj_data_file('input/nonregression/text_GBR.jp2')
|
||||
|
|
@ -992,34 +941,13 @@ class TestPrinting(unittest.TestCase):
|
|||
with patch('sys.stdout', new=StringIO()) as fake_out:
|
||||
print(jp2.box[3].box[1])
|
||||
actual = fake_out.getvalue().strip()
|
||||
lines = ["Colour Specification Box (colr) @ (179, 1339)",
|
||||
" Method: any ICC profile",
|
||||
" Precedence: 2",
|
||||
" Approximation: accurately represents "
|
||||
+ "correct colorspace definition",
|
||||
" ICC Profile:",
|
||||
" {'Size': 1328,",
|
||||
" 'Preferred CMM Type': 1634758764,",
|
||||
" 'Version': '2.2.0',",
|
||||
" 'Device Class': 'display device profile',",
|
||||
" 'Color Space': 'RGB',",
|
||||
" 'Connection Space': 'XYZ',",
|
||||
" 'Datetime': "
|
||||
+ "datetime.datetime(2009, 2, 25, 11, 26, 11),",
|
||||
" 'File Signature': 'acsp',",
|
||||
" 'Platform': 'APPL',",
|
||||
" 'Flags': 'not embedded, "
|
||||
+ "can be used independently',",
|
||||
" 'Device Manufacturer': 'appl',",
|
||||
" 'Device Model': '',",
|
||||
" 'Device Attributes': 'reflective, glossy, "
|
||||
+ "positive media polarity, color media',",
|
||||
" 'Rendering Intent': 'perceptual',",
|
||||
" 'Illuminant': array([ 0.96420288, 1. ,"
|
||||
+ " 0.8249054 ]),",
|
||||
" 'Creator': 'appl'}"]
|
||||
if sys.hexversion < 0x03000000:
|
||||
expected = text_gbr_27
|
||||
elif sys.hexversion < 0x03040000:
|
||||
expected = text_gbr_33
|
||||
else:
|
||||
expected = text_gbr_34
|
||||
|
||||
expected = '\n'.join(lines)
|
||||
self.assertEqual(actual, expected)
|
||||
|
||||
@unittest.skipIf(OPJ_DATA_ROOT is None,
|
||||
|
|
|
|||
|
|
@ -15,7 +15,7 @@ from .lib import openjp2 as opj2
|
|||
|
||||
# Do not change the format of this next line! Doing so risks breaking
|
||||
# setup.py
|
||||
version = "0.5.10"
|
||||
version = "0.5.11"
|
||||
_sv = LooseVersion(version)
|
||||
version_tuple = _sv.version
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue