Compare commits
2 commits
master
...
release-0.
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
f37da173e3 | ||
|
|
5936706f0e |
29 changed files with 1419 additions and 7044 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,8 @@
|
|||
May 18, 2014 - v0.5.12 Restored _v3 functions removed in 0.5.11
|
||||
|
||||
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.12'
|
||||
|
||||
# The language for content autogenerated by Sphinx. Refer to documentation
|
||||
# for a list of supported languages.
|
||||
|
|
|
|||
|
|
@ -1,33 +1,25 @@
|
|||
----------------------------------
|
||||
Advanced Installation Instructions
|
||||
----------------------------------
|
||||
Most users won't need to read this! You've been warned...
|
||||
|
||||
''''''''''''''''''''''
|
||||
Glymur Configuration
|
||||
''''''''''''''''''''''
|
||||
|
||||
The default glymur installation process relies upon OpenJPEG
|
||||
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. If you have OpenJPEG
|
||||
installed through your system's package manager on linux or if you use MacPorts
|
||||
on the mac, you are probably already set to go. But if you have OpenJPEG
|
||||
installed into a non-standard place or if you use windows, then read on.
|
||||
|
||||
$ 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 then 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 +27,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 +50,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 +72,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,11 +67,12 @@ 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),
|
||||
you can use the **wrap** method with no box argument: ::
|
||||
===========================================
|
||||
An existing raw codestream or JP2 file can be wrapped (re-wrapped in the case
|
||||
of JP2) 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 just a raw codestream), you can use the **wrap** method
|
||||
with no box argument: ::
|
||||
|
||||
>>> import glymur
|
||||
>>> jfile = glymur.data.goodstuff()
|
||||
|
|
@ -106,10 +107,12 @@ layer (the signature, file type, JP2 header, and contiguous codestream), with
|
|||
two additional boxes (image header and color specification) contained in the
|
||||
JP2 header superbox.
|
||||
|
||||
XML boxes are not in the minimal set of box requirements for the JP2 format, so
|
||||
in order to add an XML box into the mix before the codestream box, we'll need to
|
||||
re-specify all of the boxes. If you already have a JP2 jacket in place, you can just reuse that,
|
||||
though. Take the following example content in an XML file `favorites.xml` : ::
|
||||
XML boxes are not in the minimal set of box requirements for the
|
||||
JP2 format, so in order to add an XML box into the mix before the
|
||||
codestream box, we'll need to re-specify all of the boxes. If you
|
||||
already have a JP2 jacket in place, you can just reuse that, though.
|
||||
Take the following example content in an XML file `favorites.xml`
|
||||
: ::
|
||||
|
||||
<?xml version="1.0"?>
|
||||
<favorite_things>
|
||||
|
|
@ -158,11 +161,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
|
||||
|
|
@ -219,8 +222,8 @@ Here's how the Preview application on the mac shows the RGBA image.
|
|||
.. image:: goodstuff_alpha.png
|
||||
|
||||
|
||||
work with XMP UUIDs?
|
||||
====================
|
||||
... work with XMP UUIDs?
|
||||
========================
|
||||
The example JP2 file shipped with glymur has an XMP UUID. ::
|
||||
|
||||
>>> import glymur
|
||||
|
|
|
|||
|
|
@ -15,8 +15,10 @@ Contents:
|
|||
introduction
|
||||
detailed_installation
|
||||
how_do_i
|
||||
roadmap
|
||||
api
|
||||
roadmap
|
||||
whatsnew/index
|
||||
|
||||
|
||||
------------------
|
||||
Indices and tables
|
||||
|
|
|
|||
|
|
@ -3,7 +3,7 @@ Glymur: a Python interface for JPEG 2000
|
|||
----------------------------------------
|
||||
|
||||
**Glymur** is an interface to the OpenJPEG library
|
||||
which allows one to read and write JPEG 2000 files from within Python.
|
||||
which allows one to read and write JPEG 2000 files from Python.
|
||||
Glymur supports both reading and writing of JPEG 2000 images, but writing
|
||||
JPEG 2000 images is currently limited to images that can fit in memory
|
||||
|
||||
|
|
@ -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 OpenJPEG 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
|
||||
|
|
|
|||
50
docs/source/whatsnew/0.5.rst
Normal file
50
docs/source/whatsnew/0.5.rst
Normal file
|
|
@ -0,0 +1,50 @@
|
|||
=====================
|
||||
Changes in glymur 0.5
|
||||
=====================
|
||||
|
||||
Changes in 0.5.12
|
||||
=================
|
||||
|
||||
* Minor documentation fixes for grammar and style.
|
||||
* The functions removed in 0.5.11 due to API changes in OpenJPEG 2.1.0 were
|
||||
restored for backwards compatibility. They are deprecated, though, and will
|
||||
be removed in 0.6.0.
|
||||
|
||||
* ``glymur.lib.openjp2.stream_create_default_file_stream_v3``
|
||||
* ``glymur.lib.openjp2.opj.stream_destroy_v3``
|
||||
|
||||
|
||||
Changes in 0.5.11
|
||||
=================
|
||||
|
||||
* Added support for Python 3.4.
|
||||
* OpenJPEG 1.5.2 and 2.0.1 are officially supported.
|
||||
* OpenJPEG 2.1.0 is officially supported, but the ABI changes introduced by
|
||||
OpenJPEG 2.1.0 required corresponding changes to glymur's ctypes interface.
|
||||
The functions
|
||||
|
||||
* ``glymur.lib.openjp2.stream_create_default_file_stream_v3``
|
||||
* ``glymur.lib.openjp2.opj.stream_destroy_v3``
|
||||
|
||||
functions were renamed to
|
||||
|
||||
* ``glymur.lib.openjp2.stream_create_default_file_stream``
|
||||
* ``glymur.lib.openjp2.opj.stream_destroy``
|
||||
|
||||
in order to follow OpenJPEG's upstream changes. Unless you were using the
|
||||
svn version of OpenJPEG, you should not be affected by this.
|
||||
|
||||
|
||||
Changes in 0.5.10
|
||||
=================
|
||||
|
||||
* Fixed bad warning issued when an unsupported reader requirement box mask
|
||||
length was encountered.
|
||||
|
||||
Changes in 0.5.9
|
||||
================
|
||||
|
||||
* Fixed bad library load on linux as a result of botched 0.5.8 release.
|
||||
This release was primarily aimed at supporting SunPy.
|
||||
|
||||
|
||||
11
docs/source/whatsnew/index.rst
Normal file
11
docs/source/whatsnew/index.rst
Normal file
|
|
@ -0,0 +1,11 @@
|
|||
.. _whatsnew:
|
||||
|
||||
**********************
|
||||
"What's new" documents
|
||||
**********************
|
||||
|
||||
These document the changes between minor (or major) versions of glymur.
|
||||
|
||||
.. toctree::
|
||||
|
||||
0.5
|
||||
|
|
@ -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):
|
||||
"""Wraps openjp2 library function opj_stream_create_default_vile_stream.
|
||||
def _stream_create_default_file_stream_2p0(fptr, isa_read_stream):
|
||||
"""Wraps openjp2 library function opj_stream_create_default_file_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_file_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,15 +1335,14 @@ 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
|
||||
|
||||
|
||||
def stream_destroy(stream):
|
||||
"""Wraps openjp2 library function opj_stream_destroy.
|
||||
|
||||
|
|
@ -1329,21 +1357,51 @@ def stream_destroy(stream):
|
|||
OPENJP2.opj_stream_destroy.restype = ctypes.c_void_p
|
||||
OPENJP2.opj_stream_destroy(stream)
|
||||
|
||||
if re.match(r'''2.0''', version()):
|
||||
# We must have the 2.0.x
|
||||
stream_create_default_file_stream = _stream_create_default_file_stream_2p0
|
||||
else:
|
||||
# We must have version 2.1.
|
||||
stream_create_default_file_stream = _stream_create_default_file_stream_2p1
|
||||
|
||||
def stream_destroy_v3(stream):
|
||||
"""Wraps openjp2 library function opj_stream_destroy_v3.
|
||||
# The _v3 functions existed only in the SVN version of OpenJPEG, before 2.1.0
|
||||
# was released
|
||||
stream_create_default_file_stream_v3 = _stream_create_default_file_stream_2p1
|
||||
stream_create_default_file_stream_v3.__doc__ = r"""
|
||||
Wraps openjp2 library function opj_stream_create_default_file_stream_v3.
|
||||
|
||||
Destroys the stream created by create_stream_v3.
|
||||
Sets the stream to be a file stream.
|
||||
|
||||
This function is deprecated and will be removed in the 0.6.0 version of
|
||||
glymur. Please use stream_create_default_file_stream instead.
|
||||
|
||||
Parameters
|
||||
----------
|
||||
fname : str
|
||||
Specifies a file.
|
||||
isa_read_stream: bool
|
||||
True (read) or False (write)
|
||||
|
||||
Returns
|
||||
-------
|
||||
stream : stream_t
|
||||
An OpenJPEG file stream.
|
||||
"""
|
||||
|
||||
stream_destroy_v3 = stream_destroy
|
||||
stream_destroy_v3.__doc__ = r"""
|
||||
Wraps openjp2 library function opj_stream_destroy.
|
||||
|
||||
Destroys the stream created by create_stream.
|
||||
|
||||
This function is deprecated and wil be removed in the 0.6.0 version of
|
||||
glymur. Please use stream_destroy instead.
|
||||
|
||||
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 +1446,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):
|
||||
|
|
|
|||
443
glymur/lib/test/test_openjp2_svn.py
Normal file
443
glymur/lib/test/test_openjp2_svn.py
Normal file
|
|
@ -0,0 +1,443 @@
|
|||
"""
|
||||
Tests for functions that wrap SVN version of libopenjp2 (before release of
|
||||
2.1.0)
|
||||
"""
|
||||
# R0904: Seems like pylint is fooled in this situation
|
||||
# W0142: using kwargs is ok in this context
|
||||
# pylint: disable=R0904,W0142
|
||||
|
||||
# unittest2 is python-2.6 only (pylint/python-2.7)
|
||||
# pylint: disable=F0401
|
||||
|
||||
import os
|
||||
import re
|
||||
import sys
|
||||
import tempfile
|
||||
|
||||
if sys.hexversion < 0x02070000:
|
||||
import unittest2 as unittest
|
||||
else:
|
||||
import unittest
|
||||
|
||||
import numpy as np
|
||||
|
||||
import glymur
|
||||
from glymur.lib import openjp2
|
||||
|
||||
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.1")
|
||||
class TestOpenJP2(unittest.TestCase):
|
||||
"""Test openjp2 library functionality.
|
||||
|
||||
Some tests correspond to those in the openjpeg test suite.
|
||||
"""
|
||||
|
||||
def test_default_encoder_parameters(self):
|
||||
"""Ensure that the encoder structure is clean upon init."""
|
||||
cparams = openjp2.set_default_encoder_parameters()
|
||||
|
||||
self.assertEqual(cparams.res_spec, 0)
|
||||
self.assertEqual(cparams.cblockw_init, 64)
|
||||
self.assertEqual(cparams.cblockh_init, 64)
|
||||
self.assertEqual(cparams.numresolution, 6)
|
||||
self.assertEqual(cparams.subsampling_dx, 1)
|
||||
self.assertEqual(cparams.subsampling_dy, 1)
|
||||
self.assertEqual(cparams.mode, 0)
|
||||
self.assertEqual(cparams.prog_order, glymur.core.LRCP)
|
||||
self.assertEqual(cparams.roi_shift, 0)
|
||||
self.assertEqual(cparams.cp_tx0, 0)
|
||||
self.assertEqual(cparams.cp_ty0, 0)
|
||||
|
||||
self.assertEqual(cparams.irreversible, 0)
|
||||
|
||||
def test_default_decoder_parameters(self):
|
||||
"""Tests that the structure is clean upon initialization"""
|
||||
dparams = openjp2.set_default_decoder_parameters()
|
||||
|
||||
self.assertEqual(dparams.DA_x0, 0)
|
||||
self.assertEqual(dparams.DA_y0, 0)
|
||||
self.assertEqual(dparams.DA_x1, 0)
|
||||
self.assertEqual(dparams.DA_y1, 0)
|
||||
|
||||
def tile_macro(self, codec, stream, imagep, tidx):
|
||||
"""called only by j2k_random_tile_access"""
|
||||
openjp2.get_decoded_tile(codec, stream, imagep, tidx)
|
||||
for j in range(imagep.contents.numcomps):
|
||||
self.assertIsNotNone(imagep.contents.comps[j].data)
|
||||
|
||||
def j2k_random_tile_access(self, filename, codec_format=None):
|
||||
"""fixture called by the test_rtaX methods"""
|
||||
dparam = openjp2.set_default_decoder_parameters()
|
||||
|
||||
infile = filename.encode()
|
||||
nelts = openjp2.PATH_LEN - len(infile)
|
||||
infile += b'0' * nelts
|
||||
dparam.infile = infile
|
||||
|
||||
dparam.decod_format = codec_format
|
||||
|
||||
codec = openjp2.create_decompress(codec_format)
|
||||
|
||||
openjp2.set_info_handler(codec, None)
|
||||
openjp2.set_warning_handler(codec, None)
|
||||
openjp2.set_error_handler(codec, None)
|
||||
|
||||
stream = openjp2.stream_create_default_file_stream_v3(filename, True)
|
||||
|
||||
openjp2.setup_decoder(codec, dparam)
|
||||
image = openjp2.read_header(stream, codec)
|
||||
|
||||
cstr_info = openjp2.get_cstr_info(codec)
|
||||
|
||||
tile_ul = 0
|
||||
tile_ur = cstr_info.contents.tw - 1
|
||||
tile_lr = cstr_info.contents.tw * cstr_info.contents.th - 1
|
||||
tile_ll = tile_lr - cstr_info.contents.tw
|
||||
|
||||
self.tile_macro(codec, stream, image, tile_ul)
|
||||
self.tile_macro(codec, stream, image, tile_ur)
|
||||
self.tile_macro(codec, stream, image, tile_lr)
|
||||
self.tile_macro(codec, stream, image, tile_ll)
|
||||
|
||||
openjp2.destroy_cstr_info(cstr_info)
|
||||
|
||||
openjp2.end_decompress(codec, stream)
|
||||
openjp2.destroy_codec(codec)
|
||||
openjp2.stream_destroy_v3(stream)
|
||||
openjp2.image_destroy(image)
|
||||
|
||||
def test_tte0(self):
|
||||
"""Runs test designated tte0 in OpenJPEG test suite."""
|
||||
with tempfile.NamedTemporaryFile(suffix=".j2k") as tfile:
|
||||
ttx0_setup(tfile.name)
|
||||
self.assertTrue(True)
|
||||
|
||||
def test_ttd0(self):
|
||||
"""Runs test designated ttd0 in OpenJPEG test suite."""
|
||||
with tempfile.NamedTemporaryFile(suffix=".j2k") as tfile:
|
||||
|
||||
# Produce the tte0 output file for ttd0 input.
|
||||
ttx0_setup(tfile.name)
|
||||
|
||||
kwargs = {'x0': 0,
|
||||
'y0': 0,
|
||||
'x1': 1000,
|
||||
'y1': 1000,
|
||||
'filename': tfile.name,
|
||||
'codec_format': openjp2.CODEC_J2K}
|
||||
tile_decoder(**kwargs)
|
||||
self.assertTrue(True)
|
||||
|
||||
def xtx1_setup(self, filename):
|
||||
"""Runs tests tte1, rta1."""
|
||||
kwargs = {'filename': filename,
|
||||
'codec': openjp2.CODEC_J2K,
|
||||
'comp_prec': 8,
|
||||
'irreversible': 1,
|
||||
'num_comps': 3,
|
||||
'image_height': 256,
|
||||
'image_width': 256,
|
||||
'tile_height': 128,
|
||||
'tile_width': 128}
|
||||
tile_encoder(**kwargs)
|
||||
self.assertTrue(True)
|
||||
|
||||
def test_tte1(self):
|
||||
"""Runs test designated tte1 in OpenJPEG test suite."""
|
||||
with tempfile.NamedTemporaryFile(suffix=".j2k") as tfile:
|
||||
self.xtx1_setup(tfile.name)
|
||||
|
||||
def test_ttd1(self):
|
||||
"""Runs test designated ttd1 in OpenJPEG test suite."""
|
||||
with tempfile.NamedTemporaryFile(suffix=".j2k") as tfile:
|
||||
|
||||
# Produce the tte0 output file for ttd0 input.
|
||||
self.xtx1_setup(tfile.name)
|
||||
|
||||
kwargs = {'x0': 0,
|
||||
'y0': 0,
|
||||
'x1': 128,
|
||||
'y1': 128,
|
||||
'filename': tfile.name,
|
||||
'codec_format': openjp2.CODEC_J2K}
|
||||
tile_decoder(**kwargs)
|
||||
self.assertTrue(True)
|
||||
|
||||
def test_rta1(self):
|
||||
"""Runs test designated rta1 in OpenJPEG test suite."""
|
||||
with tempfile.NamedTemporaryFile(suffix=".j2k") as tfile:
|
||||
self.xtx1_setup(tfile.name)
|
||||
|
||||
codec_format = openjp2.CODEC_J2K
|
||||
self.j2k_random_tile_access(tfile.name, codec_format)
|
||||
self.assertTrue(True)
|
||||
|
||||
def test_tte2(self):
|
||||
"""Runs test designated tte2 in OpenJPEG test suite."""
|
||||
with tempfile.NamedTemporaryFile(suffix=".jp2") as tfile:
|
||||
xtx2_setup(tfile.name)
|
||||
self.assertTrue(True)
|
||||
|
||||
def test_ttd2(self):
|
||||
"""Runs test designated ttd2 in OpenJPEG test suite."""
|
||||
with tempfile.NamedTemporaryFile(suffix=".jp2") as tfile:
|
||||
# Produce the tte0 output file for ttd0 input.
|
||||
xtx2_setup(tfile.name)
|
||||
|
||||
kwargs = {'x0': 0,
|
||||
'y0': 0,
|
||||
'x1': 128,
|
||||
'y1': 128,
|
||||
'filename': tfile.name,
|
||||
'codec_format': openjp2.CODEC_JP2}
|
||||
tile_decoder(**kwargs)
|
||||
self.assertTrue(True)
|
||||
|
||||
def test_rta2(self):
|
||||
"""Runs test designated rta2 in OpenJPEG test suite."""
|
||||
with tempfile.NamedTemporaryFile(suffix=".jp2") as tfile:
|
||||
xtx2_setup(tfile.name)
|
||||
|
||||
codec_format = openjp2.CODEC_JP2
|
||||
self.j2k_random_tile_access(tfile.name, codec_format)
|
||||
|
||||
def test_tte3(self):
|
||||
"""Runs test designated tte3 in OpenJPEG test suite."""
|
||||
with tempfile.NamedTemporaryFile(suffix=".j2k") as tfile:
|
||||
xtx3_setup(tfile.name)
|
||||
self.assertTrue(True)
|
||||
|
||||
def test_rta3(self):
|
||||
"""Runs test designated rta3 in OpenJPEG test suite."""
|
||||
with tempfile.NamedTemporaryFile(suffix=".j2k") as tfile:
|
||||
xtx3_setup(tfile.name)
|
||||
|
||||
codec_format = openjp2.CODEC_J2K
|
||||
self.j2k_random_tile_access(tfile.name, codec_format)
|
||||
self.assertTrue(True)
|
||||
|
||||
def test_tte4(self):
|
||||
"""Runs test designated tte4 in OpenJPEG test suite."""
|
||||
with tempfile.NamedTemporaryFile(suffix=".j2k") as tfile:
|
||||
xtx4_setup(tfile.name)
|
||||
self.assertTrue(True)
|
||||
|
||||
def test_rta4(self):
|
||||
"""Runs test designated rta4 in OpenJPEG test suite."""
|
||||
with tempfile.NamedTemporaryFile(suffix=".j2k") as tfile:
|
||||
xtx4_setup(tfile.name)
|
||||
|
||||
codec_format = openjp2.CODEC_J2K
|
||||
self.j2k_random_tile_access(tfile.name, codec_format)
|
||||
|
||||
def test_tte5(self):
|
||||
"""Runs test designated tte5 in OpenJPEG test suite."""
|
||||
with tempfile.NamedTemporaryFile(suffix=".j2k") as tfile:
|
||||
xtx5_setup(tfile.name)
|
||||
self.assertTrue(True)
|
||||
|
||||
def test_rta5(self):
|
||||
"""Runs test designated rta5 in OpenJPEG test suite."""
|
||||
with tempfile.NamedTemporaryFile(suffix=".j2k") as tfile:
|
||||
xtx5_setup(tfile.name)
|
||||
|
||||
codec_format = openjp2.CODEC_J2K
|
||||
self.j2k_random_tile_access(tfile.name, codec_format)
|
||||
|
||||
|
||||
#def tile_encoder(num_comps=None, tile_width=None, tile_height=None,
|
||||
# filename=None, codec=None, comp_prec=None,
|
||||
# image_width=None, image_height=None,
|
||||
# irreversible=None):
|
||||
def tile_encoder(**kwargs):
|
||||
"""Fixture used by many tests."""
|
||||
num_tiles = ((kwargs['image_width'] / kwargs['tile_width']) *
|
||||
(kwargs['image_height'] / kwargs['tile_height']))
|
||||
tile_size = ((kwargs['tile_width'] * kwargs['tile_height']) *
|
||||
(kwargs['num_comps'] * kwargs['comp_prec'] / 8))
|
||||
|
||||
data = np.random.random((kwargs['tile_height'],
|
||||
kwargs['tile_width'],
|
||||
kwargs['num_comps']))
|
||||
data = (data * 255).astype(np.uint8)
|
||||
|
||||
l_param = openjp2.set_default_encoder_parameters()
|
||||
|
||||
l_param.tcp_numlayers = 1
|
||||
l_param.cp_fixed_quality = 1
|
||||
l_param.tcp_distoratio[0] = 20
|
||||
|
||||
# position of the tile grid aligned with the image
|
||||
l_param.cp_tx0 = 0
|
||||
l_param.cp_ty0 = 0
|
||||
|
||||
# tile size, we are using tile based encoding
|
||||
l_param.tile_size_on = 1
|
||||
l_param.cp_tdx = kwargs['tile_width']
|
||||
l_param.cp_tdy = kwargs['tile_height']
|
||||
|
||||
# use irreversible encoding
|
||||
l_param.irreversible = kwargs['irreversible']
|
||||
|
||||
l_param.numresolution = 6
|
||||
|
||||
l_param.prog_order = glymur.core.LRCP
|
||||
|
||||
l_params = (openjp2.ImageComptParmType * kwargs['num_comps'])()
|
||||
for j in range(kwargs['num_comps']):
|
||||
l_params[j].dx = 1
|
||||
l_params[j].dy = 1
|
||||
l_params[j].h = kwargs['image_height']
|
||||
l_params[j].w = kwargs['image_width']
|
||||
l_params[j].sgnd = 0
|
||||
l_params[j].prec = kwargs['comp_prec']
|
||||
l_params[j].x0 = 0
|
||||
l_params[j].y0 = 0
|
||||
|
||||
codec = openjp2.create_compress(kwargs['codec'])
|
||||
|
||||
openjp2.set_info_handler(codec, None)
|
||||
openjp2.set_warning_handler(codec, None)
|
||||
openjp2.set_error_handler(codec, None)
|
||||
|
||||
cspace = openjp2.CLRSPC_SRGB
|
||||
l_image = openjp2.image_tile_create(l_params, cspace)
|
||||
|
||||
l_image.contents.x0 = 0
|
||||
l_image.contents.y0 = 0
|
||||
l_image.contents.x1 = kwargs['image_width']
|
||||
l_image.contents.y1 = kwargs['image_height']
|
||||
l_image.contents.color_space = openjp2.CLRSPC_SRGB
|
||||
|
||||
openjp2.setup_encoder(codec, l_param, l_image)
|
||||
|
||||
stream = openjp2.stream_create_default_file_stream_v3(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.destroy_codec(codec)
|
||||
openjp2.image_destroy(l_image)
|
||||
|
||||
def tile_decoder(**kwargs):
|
||||
"""Fixture called with various configurations by many tests.
|
||||
|
||||
Reads a tile. That's all it does.
|
||||
"""
|
||||
stream = openjp2.stream_create_default_file_stream_v3(kwargs['filename'],
|
||||
True)
|
||||
dparam = openjp2.set_default_decoder_parameters()
|
||||
|
||||
dparam.decod_format = kwargs['codec_format']
|
||||
|
||||
# Do not use layer decoding limitation.
|
||||
dparam.cp_layer = 0
|
||||
|
||||
# do not use resolution reductions.
|
||||
dparam.cp_reduce = 0
|
||||
|
||||
codec = openjp2.create_decompress(kwargs['codec_format'])
|
||||
|
||||
openjp2.set_info_handler(codec, None)
|
||||
openjp2.set_warning_handler(codec, None)
|
||||
openjp2.set_error_handler(codec, None)
|
||||
|
||||
openjp2.setup_decoder(codec, dparam)
|
||||
image = openjp2.read_header(stream, codec)
|
||||
openjp2.set_decode_area(codec, image,
|
||||
kwargs['x0'], kwargs['y0'],
|
||||
kwargs['x1'], kwargs['y1'])
|
||||
|
||||
data = np.zeros((1150, 2048, 3), dtype=np.uint8)
|
||||
while True:
|
||||
rargs = openjp2.read_tile_header(codec, stream)
|
||||
tidx = rargs[0]
|
||||
size = rargs[1]
|
||||
go_on = rargs[-1]
|
||||
if not go_on:
|
||||
break
|
||||
openjp2.decode_tile_data(codec, tidx, data, size, stream)
|
||||
|
||||
openjp2.end_decompress(codec, stream)
|
||||
openjp2.destroy_codec(codec)
|
||||
openjp2.stream_destroy_v3(stream)
|
||||
openjp2.image_destroy(image)
|
||||
|
||||
def ttx0_setup(filename):
|
||||
"""Runs tests tte0, tte0."""
|
||||
kwargs = {'filename': filename,
|
||||
'codec': openjp2.CODEC_J2K,
|
||||
'comp_prec': 8,
|
||||
'irreversible': 1,
|
||||
'num_comps': 3,
|
||||
'image_height': 200,
|
||||
'image_width': 200,
|
||||
'tile_height': 100,
|
||||
'tile_width': 100}
|
||||
tile_encoder(**kwargs)
|
||||
|
||||
def xtx2_setup(filename):
|
||||
"""Runs tests rta2, tte2, ttd2."""
|
||||
kwargs = {'filename': filename,
|
||||
'codec': openjp2.CODEC_JP2,
|
||||
'comp_prec': 8,
|
||||
'irreversible': 1,
|
||||
'num_comps': 3,
|
||||
'image_height': 256,
|
||||
'image_width': 256,
|
||||
'tile_height': 128,
|
||||
'tile_width': 128}
|
||||
tile_encoder(**kwargs)
|
||||
|
||||
def xtx3_setup(filename):
|
||||
"""Runs tests tte3, rta3."""
|
||||
kwargs = {'filename': filename,
|
||||
'codec': openjp2.CODEC_J2K,
|
||||
'comp_prec': 8,
|
||||
'irreversible': 1,
|
||||
'num_comps': 1,
|
||||
'image_height': 256,
|
||||
'image_width': 256,
|
||||
'tile_height': 128,
|
||||
'tile_width': 128}
|
||||
tile_encoder(**kwargs)
|
||||
|
||||
def xtx4_setup(filename):
|
||||
"""Runs tests rta4, tte4."""
|
||||
kwargs = {'filename': filename,
|
||||
'codec': openjp2.CODEC_J2K,
|
||||
'comp_prec': 8,
|
||||
'irreversible': 0,
|
||||
'num_comps': 1,
|
||||
'image_height': 256,
|
||||
'image_width': 256,
|
||||
'tile_height': 128,
|
||||
'tile_width': 128}
|
||||
tile_encoder(**kwargs)
|
||||
|
||||
def xtx5_setup(filename):
|
||||
"""Runs tests rta5, tte5."""
|
||||
kwargs = {'filename': filename,
|
||||
'codec': openjp2.CODEC_J2K,
|
||||
'comp_prec': 8,
|
||||
'irreversible': 0,
|
||||
'num_comps': 1,
|
||||
'image_height': 512,
|
||||
'image_width': 512,
|
||||
'tile_height': 256,
|
||||
'tile_width': 256}
|
||||
tile_encoder(**kwargs)
|
||||
|
||||
if __name__ == "__main__":
|
||||
unittest.main()
|
||||
|
|
@ -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.12"
|
||||
_sv = LooseVersion(version)
|
||||
version_tuple = _sv.version
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue