Merge branch 'master' into devel
This commit is contained in:
commit
a854123bca
32 changed files with 6558 additions and 6467 deletions
|
|
@ -2,6 +2,7 @@ language: python
|
||||||
python:
|
python:
|
||||||
- "2.7"
|
- "2.7"
|
||||||
- "3.3"
|
- "3.3"
|
||||||
|
- "3.4"
|
||||||
|
|
||||||
before_install:
|
before_install:
|
||||||
- sudo apt-get update -qq
|
- sudo apt-get update -qq
|
||||||
|
|
@ -13,6 +14,7 @@ before_install:
|
||||||
install:
|
install:
|
||||||
- if [[ $TRAVIS_PYTHON_VERSION == '2.7' ]]; then pip install lxml contextlib2 mock; fi
|
- if [[ $TRAVIS_PYTHON_VERSION == '2.7' ]]; then pip install lxml contextlib2 mock; fi
|
||||||
- if [[ $TRAVIS_PYTHON_VERSION == '3.3' ]]; then pip install lxml numpy; fi
|
- if [[ $TRAVIS_PYTHON_VERSION == '3.3' ]]; then pip install lxml numpy; fi
|
||||||
|
- if [[ $TRAVIS_PYTHON_VERSION == '3.4' ]]; then pip install lxml numpy; fi
|
||||||
|
|
||||||
# command to run tests
|
# command to run tests
|
||||||
script:
|
script:
|
||||||
|
|
|
||||||
|
|
@ -1,46 +0,0 @@
|
||||||
---------
|
|
||||||
ChangeLog
|
|
||||||
---------
|
|
||||||
|
|
||||||
0.6.0 (pending)
|
|
||||||
===============
|
|
||||||
|
|
||||||
* Added Cinema2K, Cinema4K write support.
|
|
||||||
* Added lxml requirement.
|
|
||||||
* added set_printoptions, get_printoptions function
|
|
||||||
* dropped support for Python 2.6, added support for Python 3.4
|
|
||||||
* dropped support for OpenJPEG versions 1.3 and 1.4
|
|
||||||
* dropped windows support (it might work, it might not, I don't much care)
|
|
||||||
* added write support for JP2 UUID, dataEntryURL, palette, and component mapping boxes
|
|
||||||
* added read/write support for JPX free, number list, and data reference boxes
|
|
||||||
* Added read support for JPX fragment list and fragment table boxes
|
|
||||||
* incompatible change to channel definition box constructor, channel_type and association are no longer keyword arguments
|
|
||||||
* incompatible change to palette box constructor, it now takes a 2D numpy array instead of a list of 1D arrays
|
|
||||||
|
|
||||||
0.5.0 (September 16, 2013)
|
|
||||||
==========================
|
|
||||||
|
|
||||||
* added write support when using OpenJPEG version 1.5
|
|
||||||
* added version module
|
|
||||||
|
|
||||||
0.4.0 (August 18, 2013)
|
|
||||||
==========================
|
|
||||||
|
|
||||||
* added append method
|
|
||||||
|
|
||||||
0.3.0 (July 31, 2013)
|
|
||||||
==========================
|
|
||||||
|
|
||||||
* added support for OpenJPEG library version 2.0.0
|
|
||||||
|
|
||||||
0.2.0 (July 11, 2013)
|
|
||||||
==========================
|
|
||||||
|
|
||||||
* added Python 2.6, Python 2.7 on windows
|
|
||||||
* read/write using OpenJPEG library version 2.0.0
|
|
||||||
* read using OpenJPEG 1.4
|
|
||||||
|
|
||||||
0.1.0 (May 27, 2013)
|
|
||||||
====================
|
|
||||||
|
|
||||||
* first release using development version (2.x) of OpenJPEG
|
|
||||||
|
|
@ -76,9 +76,9 @@ copyright = u'2013, John Evans'
|
||||||
# built documents.
|
# built documents.
|
||||||
#
|
#
|
||||||
# The short X.Y version.
|
# The short X.Y version.
|
||||||
version = '0.5'
|
version = '0.6'
|
||||||
# The full version, including alpha/beta/rc tags.
|
# The full version, including alpha/beta/rc tags.
|
||||||
release = '0.5.10'
|
release = '0.6.0'
|
||||||
|
|
||||||
# The language for content autogenerated by Sphinx. Refer to documentation
|
# The language for content autogenerated by Sphinx. Refer to documentation
|
||||||
# for a list of supported languages.
|
# for a list of supported languages.
|
||||||
|
|
|
||||||
|
|
@ -1,34 +1,27 @@
|
||||||
----------------------------------
|
----------------------------------
|
||||||
Advanced Installation Instructions
|
Advanced Installation Instructions
|
||||||
----------------------------------
|
----------------------------------
|
||||||
Most users won't need to read this! You've been warned...
|
|
||||||
|
|
||||||
''''''''''''''''''''''
|
''''''''''''''''''''''
|
||||||
Glymur Configuration
|
Glymur Configuration
|
||||||
''''''''''''''''''''''
|
''''''''''''''''''''''
|
||||||
|
|
||||||
The default glymur installation process relies upon OpenJPEG
|
The default glymur installation process relies upon OpenJPEG being
|
||||||
being properly installed on your system. If you have version 1.5 you can
|
properly installed on your system as a shared library. If you have
|
||||||
both read and write JPEG 2000 files, but you may wish to install version 2.0
|
OpenJPEG installed through your system’s package manager on linux
|
||||||
or the 2.0+ version from OpenJPEG's development trunk for better performance.
|
or if you use MacPorts on the mac, you are probably already set to
|
||||||
If you do that, you should compile it as a shared library (named *openjp2*
|
go. But if you have OpenJPEG installed into a non-standard place
|
||||||
instead of *openjpeg*) from the developmental source that you can retrieve
|
or if you use windows, then read on.
|
||||||
via subversion. As of this time of writing, svn revision r2691 works.
|
|
||||||
You should also download the test data for the purpose of configuring
|
|
||||||
and running OpenJPEG's test suite, check their instructions for all this.
|
|
||||||
You should set the **OPJ_DATA_ROOT** environment variable for the purpose
|
|
||||||
of running Glymur's test suite. ::
|
|
||||||
|
|
||||||
$ svn co http://openjpeg.googlecode.com/svn/data
|
Glymur uses ctypes to access the openjp2/openjpeg libraries, and
|
||||||
$ export OPJ_DATA_ROOT=`pwd`/data
|
because ctypes accesses libraries in a platform-dependent manner,
|
||||||
|
it is recommended that if you compile and install OpenJPEG into a
|
||||||
Glymur uses ctypes to access the openjp2/openjpeg libraries,
|
non-standard location, you should then create a configuration file
|
||||||
and because ctypes accesses libraries in a platform-dependent manner, it is
|
to help Glymur properly find the openjpeg or openjp2 libraries
|
||||||
recommended that you create a configuration file to help Glymur properly find
|
(linux users or macports users don’t need to bother with this if
|
||||||
the openjpeg or openjp2 libraries (linux users don't need to bother with this
|
you are using OpenJPEG as provided by your package manager). The
|
||||||
if you are using OpenJPEG as provided by your package manager). The
|
configuration format is the same as used by Python’s configparser
|
||||||
configuration format is the same as used by Python's configparser module,
|
module, i.e. ::
|
||||||
i.e. ::
|
|
||||||
|
|
||||||
[library]
|
[library]
|
||||||
openjp2: /opt/openjp2-svn/lib/libopenjp2.so
|
openjp2: /opt/openjp2-svn/lib/libopenjp2.so
|
||||||
|
|
@ -45,78 +38,30 @@ the path will be ::
|
||||||
|
|
||||||
$XDG_CONFIG_HOME/glymur/glymurrc
|
$XDG_CONFIG_HOME/glymur/glymurrc
|
||||||
|
|
||||||
|
On windows, the path to the configuration file can be determined by starting
|
||||||
|
up Python and typing ::
|
||||||
|
|
||||||
|
import os
|
||||||
|
os.path.join(os.path.expanduser('~', 'glymur', 'glymurrc')
|
||||||
|
|
||||||
You may also include a line for the version 1.x openjpeg library if you have it
|
You may also include a line for the version 1.x openjpeg library if you have it
|
||||||
installed in a non-standard place, i.e. ::
|
installed in a non-standard place, i.e. ::
|
||||||
|
|
||||||
[library]
|
[library]
|
||||||
openjpeg: /not/the/usual/location/lib/libopenjpeg.so
|
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 MacPorts.
|
|
||||||
For python 3.3, you should install the following set of ports:
|
|
||||||
|
|
||||||
* python33
|
|
||||||
* py33-numpy
|
|
||||||
* py33-lxml
|
|
||||||
* py33-distribute
|
|
||||||
* 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
|
|
||||||
* python-lxml
|
|
||||||
* matplotlib
|
|
||||||
* pillow
|
|
||||||
* contextlib2 (2.7 only)
|
|
||||||
* mock (2.7 only)
|
|
||||||
|
|
||||||
Glymur 0.6 been tested on the following linux platforms without any unexpected
|
|
||||||
difficulties:
|
|
||||||
|
|
||||||
* OpenSUSE 13.1
|
|
||||||
* Fedora 19
|
|
||||||
* Raspian
|
|
||||||
* Travis CI (currently Ubuntu 12.04?)
|
|
||||||
|
|
||||||
Windows
|
|
||||||
-------
|
|
||||||
The 0.6.x series of Glymur is untested on windows and I make no promises here.
|
|
||||||
I suggest that windows users check the 0.5.x series.
|
|
||||||
|
|
||||||
|
|
||||||
'''''''
|
'''''''
|
||||||
Testing
|
Testing
|
||||||
'''''''
|
'''''''
|
||||||
|
|
||||||
There are two environment variables you may wish to set before running the
|
It is not necessary, but you may wish to download OpenJPEG's test
|
||||||
tests.
|
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. ::
|
||||||
|
|
||||||
* **OPJ_DATA_ROOT** - points to directory for OpenJPEG test data (see above)
|
$ svn co http://openjpeg.googlecode.com/svn/data
|
||||||
* **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)
|
$ export OPJ_DATA_ROOT=`pwd`/data
|
||||||
|
|
||||||
Setting these two environment variables is not required, as any tests using
|
|
||||||
either of them will be skipped.
|
|
||||||
|
|
||||||
In order to run the tests, you can either run them from within
|
In order to run the tests, you can either run them from within
|
||||||
python as follows ... ::
|
python as follows ... ::
|
||||||
|
|
@ -128,11 +73,3 @@ or from the command line. ::
|
||||||
|
|
||||||
$ cd /to/where/you/unpacked/glymur
|
$ cd /to/where/you/unpacked/glymur
|
||||||
$ python -m unittest discover
|
$ 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 Python3. The important part is whether or not any test
|
|
||||||
errors are reported at the end.
|
|
||||||
|
|
|
||||||
|
|
@ -11,13 +11,13 @@ take a shortcut by supplying -1 as the
|
||||||
resolution level. ::
|
resolution level. ::
|
||||||
|
|
||||||
>>> import glymur
|
>>> import glymur
|
||||||
>>> file = glymur.data.nemo()
|
>>> jp2file = glymur.data.nemo()
|
||||||
>>> jp2 = glymur.Jp2k(file)
|
>>> jp2 = glymur.Jp2k(jp2file)
|
||||||
>>> thumbnail = jp2.read(rlevel=-1)
|
>>> thumbnail = jp2.read(rlevel=-1)
|
||||||
|
|
||||||
... display metadata?
|
... display metadata?
|
||||||
=====================
|
=====================
|
||||||
There are two ways. From the unix command line, the script *jp2dump* is
|
There are two ways. From the unix command line, the script **jp2dump** is
|
||||||
available. ::
|
available. ::
|
||||||
|
|
||||||
$ jp2dump /path/to/glymur/installation/data/nemo.jp2
|
$ jp2dump /path/to/glymur/installation/data/nemo.jp2
|
||||||
|
|
@ -25,8 +25,8 @@ available. ::
|
||||||
From within Python, it is as simple as printing the Jp2k object, i.e. ::
|
From within Python, it is as simple as printing the Jp2k object, i.e. ::
|
||||||
|
|
||||||
>>> import glymur
|
>>> import glymur
|
||||||
>>> file = glymur.data.nemo()
|
>>> jp2file = glymur.data.nemo()
|
||||||
>>> jp2 = glymur.Jp2k(file)
|
>>> jp2 = glymur.Jp2k(jp2file)
|
||||||
>>> print(jp2)
|
>>> print(jp2)
|
||||||
File: nemo.jp2
|
File: nemo.jp2
|
||||||
JPEG 2000 Signature Box (jP ) @ (0, 12)
|
JPEG 2000 Signature Box (jP ) @ (0, 12)
|
||||||
|
|
@ -241,8 +241,8 @@ you can use the :py:meth:`wrap` method with no box argument: ::
|
||||||
|
|
||||||
>>> import glymur
|
>>> import glymur
|
||||||
>>> glymur.set_printoptions(codestream=False)
|
>>> glymur.set_printoptions(codestream=False)
|
||||||
>>> jfile = glymur.data.goodstuff()
|
>>> jp2file = glymur.data.goodstuff()
|
||||||
>>> j2k = glymur.Jp2k(jfile)
|
>>> j2k = glymur.Jp2k(jp2file)
|
||||||
>>> jp2 = j2k.wrap("newfile.jp2")
|
>>> jp2 = j2k.wrap("newfile.jp2")
|
||||||
>>> print(jp2)
|
>>> print(jp2)
|
||||||
File: newfile.jp2
|
File: newfile.jp2
|
||||||
|
|
@ -524,8 +524,8 @@ You can also build up XMP metadata from scratch. For instance, if we try to
|
||||||
wrap `goodstuff.j2k` again::
|
wrap `goodstuff.j2k` again::
|
||||||
|
|
||||||
>>> import glymur
|
>>> import glymur
|
||||||
>>> jfile = glymur.data.goodstuff()
|
>>> j2kfile = glymur.data.goodstuff()
|
||||||
>>> j2k = glymur.Jp2k(jfile)
|
>>> j2k = glymur.Jp2k(j2kfile)
|
||||||
>>> jp2 = j2k.wrap("goodstuff.jp2")
|
>>> jp2 = j2k.wrap("goodstuff.jp2")
|
||||||
|
|
||||||
Now build up the metadata piece-by-piece. It would help to have the XMP
|
Now build up the metadata piece-by-piece. It would help to have the XMP
|
||||||
|
|
|
||||||
|
|
@ -15,9 +15,9 @@ Contents:
|
||||||
introduction
|
introduction
|
||||||
detailed_installation
|
detailed_installation
|
||||||
how_do_i
|
how_do_i
|
||||||
roadmap
|
|
||||||
changelog
|
|
||||||
api
|
api
|
||||||
|
whatsnew/index
|
||||||
|
roadmap
|
||||||
|
|
||||||
------------------
|
------------------
|
||||||
Indices and tables
|
Indices and tables
|
||||||
|
|
|
||||||
|
|
@ -3,13 +3,13 @@ Glymur: a Python interface for JPEG 2000
|
||||||
----------------------------------------
|
----------------------------------------
|
||||||
|
|
||||||
**Glymur** is an interface to the OpenJPEG library
|
**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
|
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
|
JPEG 2000 images is currently limited to images that can fit in memory
|
||||||
|
|
||||||
In regards to metadata, most JP2 boxes are properly interpreted.
|
In regards to metadata, most JP2 boxes are properly interpreted.
|
||||||
Certain optional JP2 boxes can also be written, including XML boxes and
|
Certain optional JP2 boxes can also be written, including XML boxes and
|
||||||
XMP UUIDs. There is some very limited support for reading JPX metadata.
|
XMP UUIDs. There is incomplete support for reading JPX metadata.
|
||||||
|
|
||||||
Glymur 0.6 works on Python versions 2.7, 3.3 and 3.4. If you have Python 2.6,
|
Glymur 0.6 works on Python versions 2.7, 3.3 and 3.4. If you have Python 2.6,
|
||||||
you should use the 0.5 series of Glymur.
|
you should use the 0.5 series of Glymur.
|
||||||
|
|
@ -21,16 +21,16 @@ Glymur Installation
|
||||||
You can retrieve the source for Glymur from either of
|
You can retrieve the source for Glymur from either of
|
||||||
|
|
||||||
* https://pypi.python.org/pypi/Glymur/ (stable releases)
|
* https://pypi.python.org/pypi/Glymur/ (stable releases)
|
||||||
* http://github.com/quintusdias/glymur (bleeding edge)
|
* http://github.com/quintusdias/glymur (bleeding edge, use the devel branch)
|
||||||
|
|
||||||
but you should also be able to install Glymur via pip ::
|
but you should also be able to install Glymur via pip ::
|
||||||
|
|
||||||
$ pip install glymur
|
$ pip install glymur
|
||||||
|
|
||||||
This will install the **jp2dump** script that can be used from the unix command
|
This will install a script **jp2dump** that can be used from the unix command
|
||||||
line, so you should adjust your **$PATH**
|
line for dumping JP2 metadata, so you should adjust your **$PATH**
|
||||||
to take advantage of it. For example, if you install with pip's
|
environment variable to take advantage of it. For example, if you install
|
||||||
`--user` option on linux ::
|
with pip's `--user` option on linux ::
|
||||||
|
|
||||||
$ export PATH=$HOME/.local/bin:$PATH
|
$ export PATH=$HOME/.local/bin:$PATH
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,3 +1,11 @@
|
||||||
|
------------
|
||||||
|
Known Issues
|
||||||
|
------------
|
||||||
|
|
||||||
|
* Creating a Jp2 file with the irreversible option does not work
|
||||||
|
on windows.
|
||||||
|
* Eval-ing a :py:meth:`repr` string does not work on windows.
|
||||||
|
|
||||||
-------
|
-------
|
||||||
Roadmap
|
Roadmap
|
||||||
-------
|
-------
|
||||||
|
|
|
||||||
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.
|
||||||
|
|
||||||
|
|
||||||
23
docs/source/whatsnew/0.6.rst
Normal file
23
docs/source/whatsnew/0.6.rst
Normal file
|
|
@ -0,0 +1,23 @@
|
||||||
|
=====================
|
||||||
|
Changes in glymur 0.6
|
||||||
|
=====================
|
||||||
|
|
||||||
|
Changes in 0.6.0
|
||||||
|
=================
|
||||||
|
|
||||||
|
* Added Cinema2K, Cinema4K write support.
|
||||||
|
* Added irreversible 9-7 transform write support.
|
||||||
|
* Added set_printoptions, get_printoptions functions.
|
||||||
|
* Added write support for JP2 UUID, data entry URL, palette, and component
|
||||||
|
mapping boxes.
|
||||||
|
* Added read/write support for JPX free, number list, and data reference boxes
|
||||||
|
* Added read support for JPX fragment list and fragment table boxes
|
||||||
|
* Incompatible change to channel definition box constructor, channel_type and
|
||||||
|
association are no longer keyword arguments
|
||||||
|
* Incompatible change to palette box constructor, it now takes a 2D numpy array
|
||||||
|
instead of a list of 1D arrays
|
||||||
|
* Dropped support for 1.3 and 1.4.
|
||||||
|
* Dropped support for Python 2.6.
|
||||||
|
* Dropped windows support. It might still work, I don't have access to a windows
|
||||||
|
box with which to test it.
|
||||||
|
* Added lxml as a package dependency, replacing ElementTree.
|
||||||
12
docs/source/whatsnew/index.rst
Normal file
12
docs/source/whatsnew/index.rst
Normal file
|
|
@ -0,0 +1,12 @@
|
||||||
|
.. _whatsnew:
|
||||||
|
|
||||||
|
**********************
|
||||||
|
"What's new" documents
|
||||||
|
**********************
|
||||||
|
|
||||||
|
These document the changes between minor (or major) versions of glymur.
|
||||||
|
|
||||||
|
.. toctree::
|
||||||
|
|
||||||
|
0.5
|
||||||
|
0.6
|
||||||
|
|
@ -37,7 +37,9 @@ def tiff_header(read_buffer):
|
||||||
# big endian
|
# big endian
|
||||||
endian = '>'
|
endian = '>'
|
||||||
else:
|
else:
|
||||||
msg = "Bad byte order indication: {0}".format(read_buffer[6:8])
|
msg = "The byte order indication in the TIFF header ({0}) is invalid. "
|
||||||
|
msg += "It should be either {1} or {2}."
|
||||||
|
msg = msg.format(read_buffer[6:8], bytes([73, 73]), bytes([77, 77]))
|
||||||
raise IOError(msg)
|
raise IOError(msg)
|
||||||
|
|
||||||
_, offset = struct.unpack(endian + 'HI', read_buffer[8:14])
|
_, offset = struct.unpack(endian + 'HI', read_buffer[8:14])
|
||||||
|
|
@ -99,8 +101,12 @@ class _Ifd(object):
|
||||||
def parse_tag(self, dtype, count, offset_buf):
|
def parse_tag(self, dtype, count, offset_buf):
|
||||||
"""Interpret an Exif image tag data payload.
|
"""Interpret an Exif image tag data payload.
|
||||||
"""
|
"""
|
||||||
|
try:
|
||||||
fmt = self.datatype2fmt[dtype][0] * count
|
fmt = self.datatype2fmt[dtype][0] * count
|
||||||
payload_size = self.datatype2fmt[dtype][1] * count
|
payload_size = self.datatype2fmt[dtype][1] * count
|
||||||
|
except KeyError:
|
||||||
|
msg = 'Invalid TIFF tag datatype ({0}).'.format(dtype)
|
||||||
|
raise IOError(msg)
|
||||||
|
|
||||||
if payload_size <= 4:
|
if payload_size <= 4:
|
||||||
# Interpret the payload from the 4 bytes in the tag entry.
|
# Interpret the payload from the 4 bytes in the tag entry.
|
||||||
|
|
|
||||||
|
|
@ -1241,8 +1241,10 @@ class FileTypeBox(Jp2kBox):
|
||||||
def _validate(self, writing=False):
|
def _validate(self, writing=False):
|
||||||
"""Validate the box before writing to file."""
|
"""Validate the box before writing to file."""
|
||||||
if self.brand not in ['jp2 ', 'jpx ']:
|
if self.brand not in ['jp2 ', 'jpx ']:
|
||||||
msg = "The file type brand must be either 'jp2 ' or 'jpx '."
|
msg = "The file type brand was '{0}'. "
|
||||||
self._dispatch_validation_error(msg, writing=writing)
|
msg += "It should be either 'jp2 ' or 'jpx '."
|
||||||
|
self._dispatch_validation_error(msg.format(self.brand),
|
||||||
|
writing=writing)
|
||||||
valid_cls = ['jp2 ', 'jpx ', 'jpxb']
|
valid_cls = ['jp2 ', 'jpx ', 'jpxb']
|
||||||
for item in self.compatibility_list:
|
for item in self.compatibility_list:
|
||||||
if item not in valid_cls:
|
if item not in valid_cls:
|
||||||
|
|
@ -2740,12 +2742,7 @@ class XMLBox(Jp2kBox):
|
||||||
def write(self, fptr):
|
def write(self, fptr):
|
||||||
"""Write an XML box to file.
|
"""Write an XML box to file.
|
||||||
"""
|
"""
|
||||||
try:
|
|
||||||
read_buffer = ET.tostring(self.xml, encoding='utf-8')
|
read_buffer = ET.tostring(self.xml, encoding='utf-8')
|
||||||
except (AttributeError, AssertionError):
|
|
||||||
# AssertionError on 2.6
|
|
||||||
read_buffer = ET.tostring(self.xml.getroot(), encoding='utf-8')
|
|
||||||
|
|
||||||
fptr.write(struct.pack('>I4s', len(read_buffer) + 8, b'xml '))
|
fptr.write(struct.pack('>I4s', len(read_buffer) + 8, b'xml '))
|
||||||
fptr.write(read_buffer)
|
fptr.write(read_buffer)
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -180,9 +180,9 @@ class Jp2k(Jp2kBox):
|
||||||
if re.match("2.0", version.openjpeg_version) is not None:
|
if re.match("2.0", version.openjpeg_version) is not None:
|
||||||
# 2.0 API
|
# 2.0 API
|
||||||
if fps == 24:
|
if fps == 24:
|
||||||
cparams.cp_cinema = core.OPJ_CINEMA_2K_24
|
cparams.cp_cinema = core.OPJ_CINEMA2K_24
|
||||||
else:
|
else:
|
||||||
cparams.cp_cinema = core.OPJ_CINEMA_2K_48
|
cparams.cp_cinema = core.OPJ_CINEMA2K_48
|
||||||
else:
|
else:
|
||||||
# 2.1 API
|
# 2.1 API
|
||||||
if fps == 24:
|
if fps == 24:
|
||||||
|
|
@ -198,7 +198,7 @@ class Jp2k(Jp2kBox):
|
||||||
# cinema4k
|
# cinema4k
|
||||||
if re.match("2.0", version.openjpeg_version) is not None:
|
if re.match("2.0", version.openjpeg_version) is not None:
|
||||||
# 2.0 API
|
# 2.0 API
|
||||||
cparams.cp_cinema = core.OPJ_CINEMA_4K_24
|
cparams.cp_cinema = core.OPJ_CINEMA4K_24
|
||||||
else:
|
else:
|
||||||
# 2.1 API
|
# 2.1 API
|
||||||
cparams.rsiz = core.OPJ_PROFILE_CINEMA_4K
|
cparams.rsiz = core.OPJ_PROFILE_CINEMA_4K
|
||||||
|
|
@ -271,6 +271,9 @@ class Jp2k(Jp2kBox):
|
||||||
cparams.tcp_numlayers = 1
|
cparams.tcp_numlayers = 1
|
||||||
cparams.cp_disto_alloc = 1
|
cparams.cp_disto_alloc = 1
|
||||||
|
|
||||||
|
if 'irreversible' in kwargs and kwargs['irreversible'] is True:
|
||||||
|
cparams.irreversible = 1
|
||||||
|
|
||||||
if 'cinema2k' in kwargs:
|
if 'cinema2k' in kwargs:
|
||||||
self._set_cinema_params(cparams, 'cinema2k', kwargs['cinema2k'])
|
self._set_cinema_params(cparams, 'cinema2k', kwargs['cinema2k'])
|
||||||
return cparams
|
return cparams
|
||||||
|
|
@ -416,6 +419,8 @@ class Jp2k(Jp2kBox):
|
||||||
If true, write SOP marker after each header packet.
|
If true, write SOP marker after each header packet.
|
||||||
grid_offset : tuple, optional
|
grid_offset : tuple, optional
|
||||||
Offset (DY, DX) of the origin of the image in the reference grid.
|
Offset (DY, DX) of the origin of the image in the reference grid.
|
||||||
|
irreversible : bool, optional
|
||||||
|
If true, use the irreversible DWT 9-7 transform.
|
||||||
mct : bool, optional
|
mct : bool, optional
|
||||||
Specifies usage of the multi component transform. If not
|
Specifies usage of the multi component transform. If not
|
||||||
specified, defaults to True if the colorspace is RGB.
|
specified, defaults to True if the colorspace is RGB.
|
||||||
|
|
|
||||||
|
|
@ -51,51 +51,6 @@ class TestCodestreamOpjData(unittest.TestCase):
|
||||||
def tearDown(self):
|
def tearDown(self):
|
||||||
pass
|
pass
|
||||||
|
|
||||||
def test_bad_rsiz(self):
|
|
||||||
"""Should warn if RSIZ is bad. Issue196"""
|
|
||||||
filename = opj_data_file('input/nonregression/edf_c2_1002767.jp2')
|
|
||||||
if sys.hexversion < 0x03000000:
|
|
||||||
with warnings.catch_warnings():
|
|
||||||
warnings.simplefilter("ignore")
|
|
||||||
j = Jp2k(filename)
|
|
||||||
else:
|
|
||||||
with self.assertWarns(UserWarning):
|
|
||||||
j = Jp2k(filename)
|
|
||||||
|
|
||||||
def test_bad_wavelet_transform(self):
|
|
||||||
"""Should warn if wavelet transform is bad. Issue195"""
|
|
||||||
filename = opj_data_file('input/nonregression/edf_c2_10025.jp2')
|
|
||||||
if sys.hexversion < 0x03000000:
|
|
||||||
with warnings.catch_warnings():
|
|
||||||
warnings.simplefilter("ignore")
|
|
||||||
j = Jp2k(filename)
|
|
||||||
else:
|
|
||||||
with self.assertWarns(UserWarning):
|
|
||||||
j = Jp2k(filename)
|
|
||||||
|
|
||||||
def test_invalid_progression_order(self):
|
|
||||||
"""Should still be able to parse even if prog order is invalid."""
|
|
||||||
jfile = opj_data_file('input/nonregression/2977.pdf.asan.67.2198.jp2')
|
|
||||||
if sys.hexversion < 0x03000000:
|
|
||||||
with warnings.catch_warnings():
|
|
||||||
warnings.simplefilter("ignore")
|
|
||||||
Jp2k(jfile)
|
|
||||||
else:
|
|
||||||
with self.assertWarns(UserWarning):
|
|
||||||
Jp2k(jfile)
|
|
||||||
|
|
||||||
def test_tile_height_is_zero(self):
|
|
||||||
"""Zero tile height should not cause an exception."""
|
|
||||||
filename = opj_data_file('input/nonregression/2539.pdf.SIGFPE.706.1712.jp2')
|
|
||||||
if sys.hexversion < 0x03000000:
|
|
||||||
with warnings.catch_warnings():
|
|
||||||
warnings.simplefilter("ignore")
|
|
||||||
Jp2k(filename)
|
|
||||||
else:
|
|
||||||
with self.assertWarns(UserWarning):
|
|
||||||
Jp2k(filename)
|
|
||||||
|
|
||||||
|
|
||||||
@unittest.skipIf(os.name == "nt", "Temporary file issue on window.")
|
@unittest.skipIf(os.name == "nt", "Temporary file issue on window.")
|
||||||
def test_reserved_marker_segment(self):
|
def test_reserved_marker_segment(self):
|
||||||
"""Reserved marker segments are ok."""
|
"""Reserved marker segments are ok."""
|
||||||
|
|
@ -127,37 +82,6 @@ class TestCodestreamOpjData(unittest.TestCase):
|
||||||
self.assertEqual(codestream.segment[2].length, 3)
|
self.assertEqual(codestream.segment[2].length, 3)
|
||||||
self.assertEqual(codestream.segment[2].data, b'\x00')
|
self.assertEqual(codestream.segment[2].data, b'\x00')
|
||||||
|
|
||||||
@unittest.skipIf(sys.hexversion < 0x03020000,
|
|
||||||
"Uses features introduced in 3.2.")
|
|
||||||
@unittest.skipIf(os.name == "nt", "Temporary file issue on window.")
|
|
||||||
def test_unknown_marker_segment(self):
|
|
||||||
"""Should warn for an unknown marker."""
|
|
||||||
# Let's inject a marker segment whose marker does not appear to
|
|
||||||
# be valid. We still parse the file, but warn about the offending
|
|
||||||
# marker.
|
|
||||||
filename = os.path.join(OPJ_DATA_ROOT, 'input/conformance/p0_01.j2k')
|
|
||||||
with tempfile.NamedTemporaryFile(suffix='.j2k') as tfile:
|
|
||||||
with open(filename, 'rb') as ifile:
|
|
||||||
# Everything up until the first QCD marker.
|
|
||||||
read_buffer = ifile.read(45)
|
|
||||||
tfile.write(read_buffer)
|
|
||||||
|
|
||||||
# Write the new marker segment, 0xff79 = 65401
|
|
||||||
read_buffer = struct.pack('>HHB', int(65401), int(3), int(0))
|
|
||||||
tfile.write(read_buffer)
|
|
||||||
|
|
||||||
# Get the rest of the input file.
|
|
||||||
read_buffer = ifile.read()
|
|
||||||
tfile.write(read_buffer)
|
|
||||||
tfile.flush()
|
|
||||||
|
|
||||||
with self.assertWarns(UserWarning):
|
|
||||||
codestream = Jp2k(tfile.name).get_codestream()
|
|
||||||
|
|
||||||
self.assertEqual(codestream.segment[2].marker_id, '0xff79')
|
|
||||||
self.assertEqual(codestream.segment[2].length, 3)
|
|
||||||
self.assertEqual(codestream.segment[2].data, b'\x00')
|
|
||||||
|
|
||||||
def test_psot_is_zero(self):
|
def test_psot_is_zero(self):
|
||||||
"""Psot=0 in SOT is perfectly legal. Issue #78."""
|
"""Psot=0 in SOT is perfectly legal. Issue #78."""
|
||||||
filename = os.path.join(OPJ_DATA_ROOT,
|
filename = os.path.join(OPJ_DATA_ROOT,
|
||||||
|
|
|
||||||
100
glymur/test/test_codestream_warnings.py
Normal file
100
glymur/test/test_codestream_warnings.py
Normal file
|
|
@ -0,0 +1,100 @@
|
||||||
|
"""
|
||||||
|
Test suite for codestream parsing.
|
||||||
|
"""
|
||||||
|
|
||||||
|
# unittest doesn't work well with R0904.
|
||||||
|
# pylint: disable=R0904
|
||||||
|
|
||||||
|
# tempfile.TemporaryDirectory, unittest.assertWarns introduced in 3.2
|
||||||
|
# pylint: disable=E1101
|
||||||
|
|
||||||
|
import os
|
||||||
|
import struct
|
||||||
|
import sys
|
||||||
|
import tempfile
|
||||||
|
import unittest
|
||||||
|
import warnings
|
||||||
|
|
||||||
|
from glymur import Jp2k
|
||||||
|
import glymur
|
||||||
|
|
||||||
|
from .fixtures import opj_data_file, OPJ_DATA_ROOT
|
||||||
|
|
||||||
|
@unittest.skipIf(sys.platform.startswith('linux'), 'warnings failing on linux')
|
||||||
|
@unittest.skipIf(OPJ_DATA_ROOT is None,
|
||||||
|
"OPJ_DATA_ROOT environment variable not set")
|
||||||
|
class TestCodestreamOpjDataWarnings(unittest.TestCase):
|
||||||
|
"""Test suite for unusual codestream cases. Uses OPJ_DATA_ROOT"""
|
||||||
|
|
||||||
|
def test_bad_rsiz(self):
|
||||||
|
"""Should warn if RSIZ is bad. Issue196"""
|
||||||
|
filename = opj_data_file('input/nonregression/edf_c2_1002767.jp2')
|
||||||
|
with warnings.catch_warnings(record=True) as w:
|
||||||
|
warnings.simplefilter('always')
|
||||||
|
j = Jp2k(filename)
|
||||||
|
self.assertEqual(len(w), 3)
|
||||||
|
self.assertTrue(issubclass(w[0].category, UserWarning))
|
||||||
|
self.assertTrue('Invalid profile' in str(w[0].message))
|
||||||
|
|
||||||
|
def test_bad_wavelet_transform(self):
|
||||||
|
"""Should warn if wavelet transform is bad. Issue195"""
|
||||||
|
filename = opj_data_file('input/nonregression/edf_c2_10025.jp2')
|
||||||
|
with warnings.catch_warnings(record=True) as w:
|
||||||
|
warnings.simplefilter('always')
|
||||||
|
j = Jp2k(filename)
|
||||||
|
self.assertTrue(issubclass(w[0].category, UserWarning))
|
||||||
|
self.assertTrue('Invalid wavelet transform' in str(w[0].message))
|
||||||
|
|
||||||
|
def test_invalid_progression_order(self):
|
||||||
|
"""Should still be able to parse even if prog order is invalid."""
|
||||||
|
jfile = opj_data_file('input/nonregression/2977.pdf.asan.67.2198.jp2')
|
||||||
|
with warnings.catch_warnings(record=True) as w:
|
||||||
|
warnings.simplefilter('always')
|
||||||
|
Jp2k(jfile)
|
||||||
|
self.assertTrue(issubclass(w[0].category, UserWarning))
|
||||||
|
self.assertTrue('Invalid progression order' in str(w[0].message))
|
||||||
|
|
||||||
|
def test_tile_height_is_zero(self):
|
||||||
|
"""Zero tile height should not cause an exception."""
|
||||||
|
filename = opj_data_file('input/nonregression/2539.pdf.SIGFPE.706.1712.jp2')
|
||||||
|
with warnings.catch_warnings(record=True) as w:
|
||||||
|
warnings.simplefilter('always')
|
||||||
|
Jp2k(filename)
|
||||||
|
self.assertTrue(issubclass(w[0].category, UserWarning))
|
||||||
|
self.assertTrue('Invalid tile dimensions' in str(w[0].message))
|
||||||
|
|
||||||
|
@unittest.skipIf(os.name == "nt", "Temporary file issue on window.")
|
||||||
|
def test_unknown_marker_segment(self):
|
||||||
|
"""Should warn for an unknown marker."""
|
||||||
|
# Let's inject a marker segment whose marker does not appear to
|
||||||
|
# be valid. We still parse the file, but warn about the offending
|
||||||
|
# marker.
|
||||||
|
filename = os.path.join(OPJ_DATA_ROOT, 'input/conformance/p0_01.j2k')
|
||||||
|
with tempfile.NamedTemporaryFile(suffix='.j2k') as tfile:
|
||||||
|
with open(filename, 'rb') as ifile:
|
||||||
|
# Everything up until the first QCD marker.
|
||||||
|
read_buffer = ifile.read(45)
|
||||||
|
tfile.write(read_buffer)
|
||||||
|
|
||||||
|
# Write the new marker segment, 0xff79 = 65401
|
||||||
|
read_buffer = struct.pack('>HHB', int(65401), int(3), int(0))
|
||||||
|
tfile.write(read_buffer)
|
||||||
|
|
||||||
|
# Get the rest of the input file.
|
||||||
|
read_buffer = ifile.read()
|
||||||
|
tfile.write(read_buffer)
|
||||||
|
tfile.flush()
|
||||||
|
|
||||||
|
with warnings.catch_warnings(record=True) as w:
|
||||||
|
warnings.simplefilter('always')
|
||||||
|
codestream = Jp2k(tfile.name).get_codestream()
|
||||||
|
self.assertTrue(issubclass(w[0].category, UserWarning))
|
||||||
|
self.assertTrue('Unrecognized marker' in str(w[0].message))
|
||||||
|
|
||||||
|
self.assertEqual(codestream.segment[2].marker_id, '0xff79')
|
||||||
|
self.assertEqual(codestream.segment[2].length, 3)
|
||||||
|
self.assertEqual(codestream.segment[2].data, b'\x00')
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
unittest.main()
|
||||||
|
|
@ -16,6 +16,7 @@ import os
|
||||||
import sys
|
import sys
|
||||||
import tempfile
|
import tempfile
|
||||||
import unittest
|
import unittest
|
||||||
|
import warnings
|
||||||
|
|
||||||
if sys.hexversion <= 0x03030000:
|
if sys.hexversion <= 0x03030000:
|
||||||
from mock import patch
|
from mock import patch
|
||||||
|
|
@ -83,8 +84,11 @@ class TestSuite(unittest.TestCase):
|
||||||
with patch.dict('os.environ', {'XDG_CONFIG_HOME': tdir}):
|
with patch.dict('os.environ', {'XDG_CONFIG_HOME': tdir}):
|
||||||
# Misconfigured new configuration file should
|
# Misconfigured new configuration file should
|
||||||
# be rejected.
|
# be rejected.
|
||||||
with self.assertWarns(UserWarning):
|
with warnings.catch_warnings(record=True) as w:
|
||||||
|
warnings.simplefilter('always')
|
||||||
imp.reload(glymur.lib.openjp2)
|
imp.reload(glymur.lib.openjp2)
|
||||||
|
self.assertTrue(issubclass(w[0].category,UserWarning))
|
||||||
|
self.assertTrue('could not be loaded' in str(w[0].message))
|
||||||
|
|
||||||
|
|
||||||
@unittest.skipIf(glymur.lib.openjp2.OPENJP2 is None and
|
@unittest.skipIf(glymur.lib.openjp2.OPENJP2 is None and
|
||||||
|
|
|
||||||
|
|
@ -62,16 +62,18 @@ class TestICC(unittest.TestCase):
|
||||||
|
|
||||||
self.assertEqual(profile['Creator'], 'JPEG')
|
self.assertEqual(profile['Creator'], 'JPEG')
|
||||||
|
|
||||||
@unittest.skipIf(sys.hexversion < 0x03020000,
|
@unittest.skipIf(sys.platform.startswith('linux'), 'Failing on linux')
|
||||||
"Uses features introduced in 3.2.")
|
|
||||||
def test_invalid_profile_header(self):
|
def test_invalid_profile_header(self):
|
||||||
"""invalid ICC header data should cause UserWarning"""
|
"""invalid ICC header data should cause UserWarning"""
|
||||||
jfile = opj_data_file('input/nonregression/orb-blue10-lin-jp2.jp2')
|
jfile = opj_data_file('input/nonregression/orb-blue10-lin-jp2.jp2')
|
||||||
|
|
||||||
# assertWarns in Python 3.3 (python2.7/pylint issue)
|
# assertWarns in Python 3.3 (python2.7/pylint issue)
|
||||||
# pylint: disable=E1101
|
# pylint: disable=E1101
|
||||||
with self.assertWarns(UserWarning):
|
with warnings.catch_warnings(record=True) as w:
|
||||||
|
warnings.simplefilter('always')
|
||||||
Jp2k(jfile)
|
Jp2k(jfile)
|
||||||
|
self.assertTrue(issubclass(w[0].category,UserWarning))
|
||||||
|
self.assertTrue('ICC profile header is corrupt' in str(w[0].message))
|
||||||
|
|
||||||
if __name__ == "__main__":
|
if __name__ == "__main__":
|
||||||
unittest.main()
|
unittest.main()
|
||||||
|
|
|
||||||
|
|
@ -357,7 +357,6 @@ class TestChannelDefinition(unittest.TestCase):
|
||||||
with self.assertRaises((IOError, OSError)):
|
with self.assertRaises((IOError, OSError)):
|
||||||
j2k.wrap(tfile.name, boxes=boxes)
|
j2k.wrap(tfile.name, boxes=boxes)
|
||||||
|
|
||||||
@unittest.skipIf(sys.hexversion < 0x03000000, "Needs unittest in 3.x.")
|
|
||||||
def test_bad_type(self):
|
def test_bad_type(self):
|
||||||
"""Channel types are limited to 0, 1, 2, 65535
|
"""Channel types are limited to 0, 1, 2, 65535
|
||||||
Should reject if not all of index, channel_type, association the
|
Should reject if not all of index, channel_type, association the
|
||||||
|
|
@ -365,20 +364,26 @@ class TestChannelDefinition(unittest.TestCase):
|
||||||
"""
|
"""
|
||||||
channel_type = (COLOR, COLOR, 3)
|
channel_type = (COLOR, COLOR, 3)
|
||||||
association = (RED, GREEN, BLUE)
|
association = (RED, GREEN, BLUE)
|
||||||
with self.assertWarns(UserWarning):
|
|
||||||
|
with warnings.catch_warnings(record=True) as w:
|
||||||
|
warnings.simplefilter('always')
|
||||||
glymur.jp2box.ChannelDefinitionBox(channel_type=channel_type,
|
glymur.jp2box.ChannelDefinitionBox(channel_type=channel_type,
|
||||||
association=association)
|
association=association)
|
||||||
|
self.assertEqual(len(w), 1)
|
||||||
|
self.assertTrue(issubclass(w[0].category, UserWarning))
|
||||||
|
|
||||||
@unittest.skipIf(sys.hexversion < 0x03000000, "Needs unittest in 3.x.")
|
|
||||||
def test_wrong_lengths(self):
|
def test_wrong_lengths(self):
|
||||||
"""Should reject if not all of index, channel_type, association the
|
"""Should reject if not all of index, channel_type, association the
|
||||||
same length.
|
same length.
|
||||||
"""
|
"""
|
||||||
channel_type = (COLOR, COLOR)
|
channel_type = (COLOR, COLOR)
|
||||||
association = (RED, GREEN, BLUE)
|
association = (RED, GREEN, BLUE)
|
||||||
with self.assertWarns(UserWarning):
|
with warnings.catch_warnings(record=True) as w:
|
||||||
|
warnings.simplefilter('always')
|
||||||
glymur.jp2box.ChannelDefinitionBox(channel_type=channel_type,
|
glymur.jp2box.ChannelDefinitionBox(channel_type=channel_type,
|
||||||
association=association)
|
association=association)
|
||||||
|
self.assertEqual(len(w), 1)
|
||||||
|
self.assertTrue(issubclass(w[0].category, UserWarning))
|
||||||
|
|
||||||
|
|
||||||
class TestFileTypeBox(unittest.TestCase):
|
class TestFileTypeBox(unittest.TestCase):
|
||||||
|
|
@ -474,32 +479,41 @@ class TestColourSpecificationBox(unittest.TestCase):
|
||||||
self.assertEqual(colr.colorspace, glymur.core.SRGB)
|
self.assertEqual(colr.colorspace, glymur.core.SRGB)
|
||||||
self.assertIsNone(colr.icc_profile)
|
self.assertIsNone(colr.icc_profile)
|
||||||
|
|
||||||
@unittest.skipIf(sys.hexversion < 0x03030000, "Requires 3.3+")
|
|
||||||
def test_colr_with_cspace_and_icc(self):
|
def test_colr_with_cspace_and_icc(self):
|
||||||
"""Colour specification boxes can't have both."""
|
"""Colour specification boxes can't have both."""
|
||||||
with self.assertWarns(UserWarning):
|
with warnings.catch_warnings(record=True) as w:
|
||||||
|
warnings.simplefilter('always')
|
||||||
colorspace = glymur.core.SRGB
|
colorspace = glymur.core.SRGB
|
||||||
rawb = b'\x01\x02\x03\x04'
|
rawb = b'\x01\x02\x03\x04'
|
||||||
glymur.jp2box.ColourSpecificationBox(colorspace=colorspace,
|
glymur.jp2box.ColourSpecificationBox(colorspace=colorspace,
|
||||||
icc_profile=rawb)
|
icc_profile=rawb)
|
||||||
|
self.assertTrue(issubclass(w[0].category,UserWarning))
|
||||||
|
msg = 'Colorspace and icc_profile cannot both be set'
|
||||||
|
self.assertTrue(msg in str(w[0].message))
|
||||||
|
|
||||||
@unittest.skipIf(sys.hexversion < 0x03030000, "Requires 3.3+")
|
|
||||||
def test_colr_with_bad_method(self):
|
def test_colr_with_bad_method(self):
|
||||||
"""colr must have a valid method field"""
|
"""colr must have a valid method field"""
|
||||||
colorspace = glymur.core.SRGB
|
colorspace = glymur.core.SRGB
|
||||||
method = -1
|
method = -1
|
||||||
with self.assertWarns(UserWarning):
|
with warnings.catch_warnings(record=True) as w:
|
||||||
|
warnings.simplefilter('always')
|
||||||
glymur.jp2box.ColourSpecificationBox(colorspace=colorspace,
|
glymur.jp2box.ColourSpecificationBox(colorspace=colorspace,
|
||||||
method=method)
|
method=method)
|
||||||
|
self.assertTrue(issubclass(w[0].category,UserWarning))
|
||||||
|
msg = 'Invalid method'
|
||||||
|
self.assertTrue(msg in str(w[0].message))
|
||||||
|
|
||||||
@unittest.skipIf(sys.hexversion < 0x03030000, "Requires 3.3+")
|
|
||||||
def test_colr_with_bad_approx(self):
|
def test_colr_with_bad_approx(self):
|
||||||
"""colr should have a valid approximation field"""
|
"""colr should have a valid approximation field"""
|
||||||
colorspace = glymur.core.SRGB
|
colorspace = glymur.core.SRGB
|
||||||
approx = -1
|
approx = -1
|
||||||
with self.assertWarns(UserWarning):
|
with warnings.catch_warnings(record=True) as w:
|
||||||
|
warnings.simplefilter('always')
|
||||||
glymur.jp2box.ColourSpecificationBox(colorspace=colorspace,
|
glymur.jp2box.ColourSpecificationBox(colorspace=colorspace,
|
||||||
approximation=approx)
|
approximation=approx)
|
||||||
|
self.assertTrue(issubclass(w[0].category,UserWarning))
|
||||||
|
msg = 'Invalid approximation'
|
||||||
|
self.assertTrue(msg in str(w[0].message))
|
||||||
|
|
||||||
def test_colr_with_bad_color(self):
|
def test_colr_with_bad_color(self):
|
||||||
"""colr must have a valid color, strange as though that may sound."""
|
"""colr must have a valid color, strange as though that may sound."""
|
||||||
|
|
@ -523,25 +537,29 @@ class TestPaletteBox(unittest.TestCase):
|
||||||
def tearDown(self):
|
def tearDown(self):
|
||||||
pass
|
pass
|
||||||
|
|
||||||
@unittest.skipIf(sys.hexversion < 0x03000000, "Needs unittest in 3.x.")
|
|
||||||
def test_mismatched_bitdepth_signed(self):
|
def test_mismatched_bitdepth_signed(self):
|
||||||
"""bitdepth and signed arguments must have equal length"""
|
"""bitdepth and signed arguments must have equal length"""
|
||||||
palette = np.array([[255, 0, 255], [0, 255, 0]], dtype=np.uint8)
|
palette = np.array([[255, 0, 255], [0, 255, 0]], dtype=np.uint8)
|
||||||
bps = (8, 8, 8)
|
bps = (8, 8, 8)
|
||||||
signed = (False, False)
|
signed = (False, False)
|
||||||
with self.assertWarns(UserWarning):
|
with warnings.catch_warnings(record=True) as w:
|
||||||
|
warnings.simplefilter('always')
|
||||||
pclr = glymur.jp2box.PaletteBox(palette, bits_per_component=bps,
|
pclr = glymur.jp2box.PaletteBox(palette, bits_per_component=bps,
|
||||||
signed=signed)
|
signed=signed)
|
||||||
|
self.assertEqual(len(w), 1)
|
||||||
|
self.assertTrue(issubclass(w[0].category, UserWarning))
|
||||||
|
|
||||||
@unittest.skipIf(sys.hexversion < 0x03000000, "Needs unittest in 3.x.")
|
|
||||||
def test_mismatched_signed_palette(self):
|
def test_mismatched_signed_palette(self):
|
||||||
"""bitdepth and signed arguments must have equal length"""
|
"""bitdepth and signed arguments must have equal length"""
|
||||||
palette = np.array([[255, 0, 255], [0, 255, 0]], dtype=np.uint8)
|
palette = np.array([[255, 0, 255], [0, 255, 0]], dtype=np.uint8)
|
||||||
bps = (8, 8, 8, 8)
|
bps = (8, 8, 8, 8)
|
||||||
signed = (False, False, False, False)
|
signed = (False, False, False, False)
|
||||||
with self.assertWarns(UserWarning):
|
with warnings.catch_warnings(record=True) as w:
|
||||||
|
warnings.simplefilter('always')
|
||||||
pclr = glymur.jp2box.PaletteBox(palette, bits_per_component=bps,
|
pclr = glymur.jp2box.PaletteBox(palette, bits_per_component=bps,
|
||||||
signed=signed)
|
signed=signed)
|
||||||
|
self.assertEqual(len(w), 1)
|
||||||
|
self.assertTrue(issubclass(w[0].category, UserWarning))
|
||||||
|
|
||||||
def test_writing_with_different_bitdepths(self):
|
def test_writing_with_different_bitdepths(self):
|
||||||
"""Bitdepths must be the same when writing."""
|
"""Bitdepths must be the same when writing."""
|
||||||
|
|
@ -554,6 +572,8 @@ class TestPaletteBox(unittest.TestCase):
|
||||||
with self.assertRaises(IOError):
|
with self.assertRaises(IOError):
|
||||||
pclr.write(tfile)
|
pclr.write(tfile)
|
||||||
|
|
||||||
|
|
||||||
|
@unittest.skipIf(os.name == "nt", "Temporary file issue on window.")
|
||||||
class TestAppend(unittest.TestCase):
|
class TestAppend(unittest.TestCase):
|
||||||
"""Tests for append method."""
|
"""Tests for append method."""
|
||||||
|
|
||||||
|
|
@ -1274,8 +1294,8 @@ class TestRepr(unittest.TestCase):
|
||||||
box = glymur.jp2box.XMLBox(xml=tree)
|
box = glymur.jp2box.XMLBox(xml=tree)
|
||||||
|
|
||||||
regexp = r"""glymur.jp2box.XMLBox"""
|
regexp = r"""glymur.jp2box.XMLBox"""
|
||||||
regexp += r"""\(xml=<lxml.etree._ElementTree object """
|
regexp += r"""[(]xml=<lxml.etree._ElementTree\sobject\s"""
|
||||||
regexp += """at 0x([a-f0-9]*)>\)"""
|
regexp += """at\s0x([a-fA-F0-9]*)>[)]"""
|
||||||
|
|
||||||
if sys.hexversion < 0x03000000:
|
if sys.hexversion < 0x03000000:
|
||||||
self.assertRegexpMatches(repr(box), regexp)
|
self.assertRegexpMatches(repr(box), regexp)
|
||||||
|
|
@ -1314,7 +1334,6 @@ class TestRepr(unittest.TestCase):
|
||||||
else:
|
else:
|
||||||
self.assertRegex(repr(box), regexp)
|
self.assertRegex(repr(box), regexp)
|
||||||
|
|
||||||
@unittest.skipIf(sys.hexversion < 0x02070000, "Requires 2.7+")
|
|
||||||
def test_uuid_box_xmp(self):
|
def test_uuid_box_xmp(self):
|
||||||
"""Verify uuid repr method for XMP UUID box."""
|
"""Verify uuid repr method for XMP UUID box."""
|
||||||
jp2file = glymur.data.nemo()
|
jp2file = glymur.data.nemo()
|
||||||
|
|
@ -1340,8 +1359,8 @@ class TestRepr(unittest.TestCase):
|
||||||
|
|
||||||
# Difficult to eval(repr()) this, so just match the general pattern.
|
# Difficult to eval(repr()) this, so just match the general pattern.
|
||||||
regexp = "glymur.jp2box.ContiguousCodeStreamBox"
|
regexp = "glymur.jp2box.ContiguousCodeStreamBox"
|
||||||
regexp += "\(main_header=<glymur.codestream.Codestream\sobject\s"
|
regexp += "[(]main_header=<glymur.codestream.Codestream\sobject\s"
|
||||||
regexp += "at\s0x([a-f0-9]*)>\)"
|
regexp += "at\s0x([a-fA-F0-9]*)>[)]"
|
||||||
|
|
||||||
if sys.hexversion < 0x03000000:
|
if sys.hexversion < 0x03000000:
|
||||||
self.assertRegexpMatches(repr(box), regexp)
|
self.assertRegexpMatches(repr(box), regexp)
|
||||||
|
|
|
||||||
|
|
@ -305,15 +305,17 @@ class TestJPXWrap(unittest.TestCase):
|
||||||
with self.assertRaises(IOError):
|
with self.assertRaises(IOError):
|
||||||
jp2.wrap(tfile.name, boxes=boxes)
|
jp2.wrap(tfile.name, boxes=boxes)
|
||||||
|
|
||||||
@unittest.skipIf(sys.hexversion < 0x03000000, "Needs unittest in 3.x.")
|
|
||||||
def test_deurl_child_of_dtbl(self):
|
def test_deurl_child_of_dtbl(self):
|
||||||
"""Data reference boxes can only contain data entry url boxes."""
|
"""Data reference boxes can only contain data entry url boxes."""
|
||||||
jp2 = Jp2k(self.jp2file)
|
jp2 = Jp2k(self.jp2file)
|
||||||
boxes = [jp2.box[idx] for idx in [0, 1, 2, 4]]
|
boxes = [jp2.box[idx] for idx in [0, 1, 2, 4]]
|
||||||
|
|
||||||
ftyp = glymur.jp2box.FileTypeBox()
|
ftyp = glymur.jp2box.FileTypeBox()
|
||||||
with self.assertWarns(UserWarning):
|
with warnings.catch_warnings(record=True) as w:
|
||||||
|
warnings.simplefilter('always')
|
||||||
dref = glymur.jp2box.DataReferenceBox([ftyp])
|
dref = glymur.jp2box.DataReferenceBox([ftyp])
|
||||||
|
self.assertEqual(len(w), 1)
|
||||||
|
self.assertTrue(issubclass(w[0].category, UserWarning))
|
||||||
|
|
||||||
# Try to get around it by appending the ftyp box after creation.
|
# Try to get around it by appending the ftyp box after creation.
|
||||||
dref = glymur.jp2box.DataReferenceBox()
|
dref = glymur.jp2box.DataReferenceBox()
|
||||||
|
|
@ -484,25 +486,6 @@ class TestJPX(unittest.TestCase):
|
||||||
with tempfile.TemporaryFile() as tfile:
|
with tempfile.TemporaryFile() as tfile:
|
||||||
ftbl.write(tfile)
|
ftbl.write(tfile)
|
||||||
|
|
||||||
@unittest.skip("Requires unnecessarily complicated code")
|
|
||||||
def test_unknown_superbox(self):
|
|
||||||
"""Verify that we can handle an unknown superbox."""
|
|
||||||
with tempfile.NamedTemporaryFile(suffix='.jpx') as tfile:
|
|
||||||
with open(self.jpxfile, 'rb') as ifile:
|
|
||||||
tfile.write(ifile.read())
|
|
||||||
|
|
||||||
# Add the header for an unknwon superbox.
|
|
||||||
write_buffer = struct.pack('>I4s', 20, 'grp '.encode())
|
|
||||||
tfile.write(write_buffer)
|
|
||||||
write_buffer = struct.pack('>I4sI', 12, 'free'.encode(), 0)
|
|
||||||
tfile.write(write_buffer)
|
|
||||||
tfile.flush()
|
|
||||||
|
|
||||||
with self.assertWarns(UserWarning):
|
|
||||||
jpx = Jp2k(tfile.name)
|
|
||||||
self.assertEqual(jpx.box[-1].box_id, b'grp ')
|
|
||||||
self.assertEqual(jpx.box[-1].box[0].box_id, 'free')
|
|
||||||
|
|
||||||
def test_data_reference_requires_dtbl(self):
|
def test_data_reference_requires_dtbl(self):
|
||||||
"""The existance of a data reference box requires a ftbl box as well."""
|
"""The existance of a data reference box requires a ftbl box as well."""
|
||||||
flag = 0
|
flag = 0
|
||||||
|
|
|
||||||
|
|
@ -45,6 +45,7 @@ from glymur import Jp2k
|
||||||
from .fixtures import OPJ_DATA_ROOT, opj_data_file, SimpleRDF
|
from .fixtures import OPJ_DATA_ROOT, opj_data_file, SimpleRDF
|
||||||
|
|
||||||
|
|
||||||
|
@unittest.skipIf(os.name == "nt", "Unexplained failure on windows")
|
||||||
class TestUUIDXMP(unittest.TestCase):
|
class TestUUIDXMP(unittest.TestCase):
|
||||||
"""Tests for UUIDs of XMP type."""
|
"""Tests for UUIDs of XMP type."""
|
||||||
|
|
||||||
|
|
@ -74,6 +75,7 @@ class TestUUIDXMP(unittest.TestCase):
|
||||||
self.assertTrue(isinstance(jp2.box[-1].data,
|
self.assertTrue(isinstance(jp2.box[-1].data,
|
||||||
lxml.etree._ElementTree))
|
lxml.etree._ElementTree))
|
||||||
|
|
||||||
|
@unittest.skipIf(os.name == "nt", "Unexplained failure on windows")
|
||||||
class TestUUIDExif(unittest.TestCase):
|
class TestUUIDExif(unittest.TestCase):
|
||||||
"""Tests for UUIDs of Exif type."""
|
"""Tests for UUIDs of Exif type."""
|
||||||
|
|
||||||
|
|
@ -83,7 +85,6 @@ class TestUUIDExif(unittest.TestCase):
|
||||||
def tearDown(self):
|
def tearDown(self):
|
||||||
pass
|
pass
|
||||||
|
|
||||||
@unittest.skipIf(sys.hexversion < 0x03000000, "Requires assertWarns, 3.2+")
|
|
||||||
def test_unrecognized_exif_tag(self):
|
def test_unrecognized_exif_tag(self):
|
||||||
"""Verify warning in case of unrecognized tag."""
|
"""Verify warning in case of unrecognized tag."""
|
||||||
with tempfile.NamedTemporaryFile(suffix='.jp2', mode='wb') as tfile:
|
with tempfile.NamedTemporaryFile(suffix='.jp2', mode='wb') as tfile:
|
||||||
|
|
@ -106,10 +107,13 @@ class TestUUIDExif(unittest.TestCase):
|
||||||
tfile.write(struct.pack('<HHI4s', 171, 2, 3, b'HTC\x00'))
|
tfile.write(struct.pack('<HHI4s', 171, 2, 3, b'HTC\x00'))
|
||||||
tfile.flush()
|
tfile.flush()
|
||||||
|
|
||||||
with self.assertWarns(UserWarning):
|
with warnings.catch_warnings(record=True) as w:
|
||||||
|
warnings.simplefilter('always')
|
||||||
j = glymur.Jp2k(tfile.name)
|
j = glymur.Jp2k(tfile.name)
|
||||||
|
self.assertTrue(issubclass(w[0].category, UserWarning))
|
||||||
|
msg = 'Unrecognized Exif tag'
|
||||||
|
self.assertTrue(msg in str(w[0].message))
|
||||||
|
|
||||||
@unittest.skipIf(sys.hexversion < 0x03000000, "Requires assertWarns, 3.2+")
|
|
||||||
def test_bad_tag_datatype(self):
|
def test_bad_tag_datatype(self):
|
||||||
"""Only certain datatypes are allowable"""
|
"""Only certain datatypes are allowable"""
|
||||||
with tempfile.NamedTemporaryFile(suffix='.jp2', mode='wb') as tfile:
|
with tempfile.NamedTemporaryFile(suffix='.jp2', mode='wb') as tfile:
|
||||||
|
|
@ -132,12 +136,15 @@ class TestUUIDExif(unittest.TestCase):
|
||||||
tfile.write(struct.pack('<HHI4s', 271, 2000, 3, b'HTC\x00'))
|
tfile.write(struct.pack('<HHI4s', 271, 2000, 3, b'HTC\x00'))
|
||||||
tfile.flush()
|
tfile.flush()
|
||||||
|
|
||||||
with self.assertWarns(UserWarning):
|
with warnings.catch_warnings(record=True) as w:
|
||||||
|
warnings.simplefilter('always')
|
||||||
j = glymur.Jp2k(tfile.name)
|
j = glymur.Jp2k(tfile.name)
|
||||||
|
self.assertTrue(issubclass(w[0].category, UserWarning))
|
||||||
|
msg = 'Invalid TIFF tag'
|
||||||
|
self.assertTrue(msg in str(w[0].message))
|
||||||
|
|
||||||
self.assertEqual(j.box[-1].box_id, 'uuid')
|
self.assertEqual(j.box[-1].box_id, 'uuid')
|
||||||
|
|
||||||
@unittest.skipIf(sys.hexversion < 0x03000000, "Requires assertWarns, 3.2+")
|
|
||||||
def test_bad_tiff_header_byte_order_indication(self):
|
def test_bad_tiff_header_byte_order_indication(self):
|
||||||
"""Only b'II' and b'MM' are allowed."""
|
"""Only b'II' and b'MM' are allowed."""
|
||||||
with tempfile.NamedTemporaryFile(suffix='.jp2', mode='wb') as tfile:
|
with tempfile.NamedTemporaryFile(suffix='.jp2', mode='wb') as tfile:
|
||||||
|
|
@ -160,8 +167,18 @@ class TestUUIDExif(unittest.TestCase):
|
||||||
tfile.write(struct.pack('<HHI4s', 271, 2, 3, b'HTC\x00'))
|
tfile.write(struct.pack('<HHI4s', 271, 2, 3, b'HTC\x00'))
|
||||||
tfile.flush()
|
tfile.flush()
|
||||||
|
|
||||||
with self.assertWarns(UserWarning):
|
with warnings.catch_warnings(record=True) as w:
|
||||||
|
warnings.simplefilter('always')
|
||||||
j = glymur.Jp2k(tfile.name)
|
j = glymur.Jp2k(tfile.name)
|
||||||
|
self.assertTrue(issubclass(w[0].category, UserWarning))
|
||||||
|
msg = 'The byte order indication in the TIFF header '
|
||||||
|
if sys.hexversion < 0x03000000:
|
||||||
|
msg += "(JI) is invalid. "
|
||||||
|
msg += "It should be either [73, 73] or [77, 77]."
|
||||||
|
else:
|
||||||
|
msg += "(b'JI') is invalid. "
|
||||||
|
msg += "It should be either b'II' or b'MM'."
|
||||||
|
self.assertTrue(msg in str(w[0].message))
|
||||||
|
|
||||||
self.assertEqual(j.box[-1].box_id, 'uuid')
|
self.assertEqual(j.box[-1].box_id, 'uuid')
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -207,18 +207,14 @@ class TestJp2kBadXmlFile(unittest.TestCase):
|
||||||
def tearDown(self):
|
def tearDown(self):
|
||||||
pass
|
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):
|
def test_invalid_xml_box(self):
|
||||||
"""Should be able to recover info from xml box with bad xml."""
|
"""Should be able to recover info from xml box with bad xml."""
|
||||||
with warnings.catch_warnings():
|
with warnings.catch_warnings(record=True) as w:
|
||||||
warnings.simplefilter("ignore")
|
warnings.simplefilter("always")
|
||||||
jp2k = Jp2k(self._bad_xml_file)
|
jp2k = Jp2k(self._bad_xml_file)
|
||||||
|
self.assertTrue(issubclass(w[0].category, UserWarning))
|
||||||
|
msg = 'No XML was retrieved'
|
||||||
|
self.assertTrue(msg in str(w[0].message))
|
||||||
|
|
||||||
self.assertEqual(jp2k.box[3].box_id, 'xml ')
|
self.assertEqual(jp2k.box[3].box_id, 'xml ')
|
||||||
self.assertEqual(jp2k.box[3].offset, 77)
|
self.assertEqual(jp2k.box[3].offset, 77)
|
||||||
|
|
@ -267,12 +263,14 @@ class TestBadButRecoverableXmlFile(unittest.TestCase):
|
||||||
def tearDownClass(cls):
|
def tearDownClass(cls):
|
||||||
os.unlink(cls._bad_xml_file)
|
os.unlink(cls._bad_xml_file)
|
||||||
|
|
||||||
@unittest.skipIf(sys.hexversion < 0x03020000,
|
|
||||||
"Uses features introduced in 3.2.")
|
|
||||||
def test_bad_xml_box_warning(self):
|
def test_bad_xml_box_warning(self):
|
||||||
"""Should warn in case of bad XML"""
|
"""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)
|
Jp2k(self._bad_xml_file)
|
||||||
|
self.assertTrue(issubclass(w[0].category, UserWarning))
|
||||||
|
msg = 'A UnicodeDecodeError was encountered parsing an XML box'
|
||||||
|
self.assertTrue(msg in str(w[0].message))
|
||||||
|
|
||||||
def test_recover_from_bad_xml(self):
|
def test_recover_from_bad_xml(self):
|
||||||
"""Should be able to recover info from xml box with bad xml."""
|
"""Should be able to recover info from xml box with bad xml."""
|
||||||
|
|
@ -292,18 +290,19 @@ class TestBadButRecoverableXmlFile(unittest.TestCase):
|
||||||
class TestXML_OpjDataRoot(unittest.TestCase):
|
class TestXML_OpjDataRoot(unittest.TestCase):
|
||||||
"""Test suite for XML boxes, requires OPJ_DATA_ROOT."""
|
"""Test suite for XML boxes, requires OPJ_DATA_ROOT."""
|
||||||
|
|
||||||
|
@unittest.skipIf(sys.platform.startswith('linux'), 'Failing on linux')
|
||||||
def test_bom(self):
|
def test_bom(self):
|
||||||
"""Byte order markers are illegal in UTF-8. Issue 185"""
|
"""Byte order markers are illegal in UTF-8. Issue 185"""
|
||||||
filename = opj_data_file(os.path.join('input',
|
filename = opj_data_file(os.path.join('input',
|
||||||
'nonregression',
|
'nonregression',
|
||||||
'issue171.jp2'))
|
'issue171.jp2'))
|
||||||
if sys.hexversion < 0x03000000:
|
with warnings.catch_warnings(record=True) as w:
|
||||||
with warnings.catch_warnings():
|
warnings.simplefilter("always")
|
||||||
warnings.simplefilter("ignore")
|
|
||||||
jp2 = Jp2k(filename)
|
|
||||||
else:
|
|
||||||
with self.assertWarns(UserWarning):
|
|
||||||
jp2 = Jp2k(filename)
|
jp2 = Jp2k(filename)
|
||||||
|
self.assertTrue(issubclass(w[0].category, UserWarning))
|
||||||
|
msg = 'An illegal BOM (byte order marker) was detected and removed'
|
||||||
|
self.assertTrue(msg in str(w[0].message))
|
||||||
|
|
||||||
self.assertIsNotNone(jp2.box[3].xml)
|
self.assertIsNotNone(jp2.box[3].xml)
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -312,13 +311,10 @@ class TestXML_OpjDataRoot(unittest.TestCase):
|
||||||
filename = opj_data_file(os.path.join('input',
|
filename = opj_data_file(os.path.join('input',
|
||||||
'nonregression',
|
'nonregression',
|
||||||
'26ccf3651020967f7778238ef5af08af.SIGFPE.d25.527.jp2'))
|
'26ccf3651020967f7778238ef5af08af.SIGFPE.d25.527.jp2'))
|
||||||
if sys.hexversion < 0x03000000:
|
with warnings.catch_warnings(record=True) as w:
|
||||||
with warnings.catch_warnings():
|
warnings.simplefilter("always")
|
||||||
warnings.simplefilter("ignore")
|
|
||||||
jp2 = Jp2k(filename)
|
|
||||||
else:
|
|
||||||
with self.assertWarns(UserWarning):
|
|
||||||
jp2 = Jp2k(filename)
|
jp2 = Jp2k(filename)
|
||||||
|
self.assertTrue(issubclass(w[0].category, UserWarning))
|
||||||
|
|
||||||
self.assertIsNone(jp2.box[3].box[1].box[1].xml)
|
self.assertIsNone(jp2.box[3].box[1].box[1].xml)
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -63,6 +63,25 @@ class TestJp2k(unittest.TestCase):
|
||||||
def tearDown(self):
|
def tearDown(self):
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
@unittest.skipIf(os.name == "nt", "Unexplained failure on windows")
|
||||||
|
def test_irreversible(self):
|
||||||
|
"""Irreversible"""
|
||||||
|
j = Jp2k(self.jp2file)
|
||||||
|
expdata = j.read()
|
||||||
|
with tempfile.NamedTemporaryFile(suffix='.j2k') as tfile:
|
||||||
|
j2 = Jp2k(tfile.name, 'wb')
|
||||||
|
j2.write(expdata, irreversible=True)
|
||||||
|
|
||||||
|
codestream = j2.get_codestream()
|
||||||
|
self.assertEqual(codestream.segment[2].spcod[8],
|
||||||
|
glymur.core.WAVELET_XFORM_9X7_IRREVERSIBLE)
|
||||||
|
|
||||||
|
actdata = j2.read()
|
||||||
|
self.assertTrue(fixtures.mse(actdata[0], expdata[0]) < 0.38)
|
||||||
|
|
||||||
|
@unittest.skipIf(re.match('1.5.(1|2)',
|
||||||
|
glymur.version.openjpeg_version) is not None,
|
||||||
|
"Mysteriously fails in 1.5.1 and 1.5.2")
|
||||||
def test_no_cxform_pclr_jpx(self):
|
def test_no_cxform_pclr_jpx(self):
|
||||||
"""Indices for pclr jpxfile if no color transform"""
|
"""Indices for pclr jpxfile if no color transform"""
|
||||||
j = Jp2k(self.jpxfile)
|
j = Jp2k(self.jpxfile)
|
||||||
|
|
@ -81,6 +100,7 @@ class TestJp2k(unittest.TestCase):
|
||||||
rgb_from_idx[r, c] = palette[idx[r, c]]
|
rgb_from_idx[r, c] = palette[idx[r, c]]
|
||||||
np.testing.assert_array_equal(rgb, rgb_from_idx)
|
np.testing.assert_array_equal(rgb, rgb_from_idx)
|
||||||
|
|
||||||
|
@unittest.skipIf(os.name == "nt", "Unexplained failure on windows")
|
||||||
def test_repr(self):
|
def test_repr(self):
|
||||||
"""Verify that results of __repr__ are eval-able."""
|
"""Verify that results of __repr__ are eval-able."""
|
||||||
j = Jp2k(self.j2kfile)
|
j = Jp2k(self.j2kfile)
|
||||||
|
|
@ -390,6 +410,7 @@ class TestJp2k(unittest.TestCase):
|
||||||
self.assertEqual(data.shape, (1024, 1024, 3))
|
self.assertEqual(data.shape, (1024, 1024, 3))
|
||||||
|
|
||||||
|
|
||||||
|
@unittest.skipIf(os.name == "nt", "NamedTemporaryFile issue on windows")
|
||||||
class TestJp2k_write(unittest.TestCase):
|
class TestJp2k_write(unittest.TestCase):
|
||||||
"""Write tests, can be run by versions 1.5+"""
|
"""Write tests, can be run by versions 1.5+"""
|
||||||
|
|
||||||
|
|
@ -400,8 +421,6 @@ class TestJp2k_write(unittest.TestCase):
|
||||||
def tearDown(self):
|
def tearDown(self):
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
|
||||||
@unittest.skipIf(os.name == "nt", "NamedTemporaryFile issue on windows")
|
|
||||||
def test_cblkh_different_than_width(self):
|
def test_cblkh_different_than_width(self):
|
||||||
"""Verify that we can set a code block size where height does not equal
|
"""Verify that we can set a code block size where height does not equal
|
||||||
width.
|
width.
|
||||||
|
|
@ -418,7 +437,6 @@ class TestJp2k_write(unittest.TestCase):
|
||||||
# Code block size is reported as XY in the codestream.
|
# Code block size is reported as XY in the codestream.
|
||||||
self.assertEqual(tuple(codestream.segment[2].spcod[5:7]), (3, 2))
|
self.assertEqual(tuple(codestream.segment[2].spcod[5:7]), (3, 2))
|
||||||
|
|
||||||
@unittest.skipIf(os.name == "nt", "NamedTemporaryFile issue on windows")
|
|
||||||
def test_too_many_dimensions(self):
|
def test_too_many_dimensions(self):
|
||||||
"""OpenJP2 only allows 2D or 3D images."""
|
"""OpenJP2 only allows 2D or 3D images."""
|
||||||
with tempfile.NamedTemporaryFile(suffix='.j2k') as tfile:
|
with tempfile.NamedTemporaryFile(suffix='.j2k') as tfile:
|
||||||
|
|
@ -427,7 +445,6 @@ class TestJp2k_write(unittest.TestCase):
|
||||||
data = np.zeros((128, 128, 2, 2), dtype=np.uint8)
|
data = np.zeros((128, 128, 2, 2), dtype=np.uint8)
|
||||||
j.write(data)
|
j.write(data)
|
||||||
|
|
||||||
@unittest.skipIf(os.name == "nt", "NamedTemporaryFile issue on windows")
|
|
||||||
def test_2d_rgb(self):
|
def test_2d_rgb(self):
|
||||||
"""RGB must have at least 3 components."""
|
"""RGB must have at least 3 components."""
|
||||||
with tempfile.NamedTemporaryFile(suffix='.jp2') as tfile:
|
with tempfile.NamedTemporaryFile(suffix='.jp2') as tfile:
|
||||||
|
|
@ -436,7 +453,6 @@ class TestJp2k_write(unittest.TestCase):
|
||||||
data = np.zeros((128, 128, 2), dtype=np.uint8)
|
data = np.zeros((128, 128, 2), dtype=np.uint8)
|
||||||
j.write(data, colorspace='rgb')
|
j.write(data, colorspace='rgb')
|
||||||
|
|
||||||
@unittest.skipIf(os.name == "nt", "NamedTemporaryFile issue on windows")
|
|
||||||
def test_colorspace_with_j2k(self):
|
def test_colorspace_with_j2k(self):
|
||||||
"""Specifying a colorspace with J2K does not make sense"""
|
"""Specifying a colorspace with J2K does not make sense"""
|
||||||
with tempfile.NamedTemporaryFile(suffix='.j2k') as tfile:
|
with tempfile.NamedTemporaryFile(suffix='.j2k') as tfile:
|
||||||
|
|
@ -445,7 +461,6 @@ class TestJp2k_write(unittest.TestCase):
|
||||||
data = np.zeros((128, 128, 3), dtype=np.uint8)
|
data = np.zeros((128, 128, 3), dtype=np.uint8)
|
||||||
j.write(data, colorspace='rgb')
|
j.write(data, colorspace='rgb')
|
||||||
|
|
||||||
@unittest.skipIf(os.name == "nt", "NamedTemporaryFile issue on windows")
|
|
||||||
def test_specify_rgb(self):
|
def test_specify_rgb(self):
|
||||||
"""specify RGB explicitly"""
|
"""specify RGB explicitly"""
|
||||||
with tempfile.NamedTemporaryFile(suffix='.jp2') as tfile:
|
with tempfile.NamedTemporaryFile(suffix='.jp2') as tfile:
|
||||||
|
|
@ -454,7 +469,6 @@ class TestJp2k_write(unittest.TestCase):
|
||||||
j.write(data, colorspace='rgb')
|
j.write(data, colorspace='rgb')
|
||||||
self.assertEqual(j.box[2].box[1].colorspace, glymur.core.SRGB)
|
self.assertEqual(j.box[2].box[1].colorspace, glymur.core.SRGB)
|
||||||
|
|
||||||
@unittest.skipIf(os.name == "nt", "NamedTemporaryFile issue on windows")
|
|
||||||
def test_specify_gray(self):
|
def test_specify_gray(self):
|
||||||
"""test gray explicitly specified (that's GRAY, not GREY)"""
|
"""test gray explicitly specified (that's GRAY, not GREY)"""
|
||||||
with tempfile.NamedTemporaryFile(suffix='.jp2') as tfile:
|
with tempfile.NamedTemporaryFile(suffix='.jp2') as tfile:
|
||||||
|
|
@ -464,7 +478,6 @@ class TestJp2k_write(unittest.TestCase):
|
||||||
self.assertEqual(j.box[2].box[1].colorspace,
|
self.assertEqual(j.box[2].box[1].colorspace,
|
||||||
glymur.core.GREYSCALE)
|
glymur.core.GREYSCALE)
|
||||||
|
|
||||||
@unittest.skipIf(os.name == "nt", "NamedTemporaryFile issue on windows")
|
|
||||||
def test_specify_grey(self):
|
def test_specify_grey(self):
|
||||||
"""test grey explicitly specified"""
|
"""test grey explicitly specified"""
|
||||||
with tempfile.NamedTemporaryFile(suffix='.jp2') as tfile:
|
with tempfile.NamedTemporaryFile(suffix='.jp2') as tfile:
|
||||||
|
|
@ -474,7 +487,6 @@ class TestJp2k_write(unittest.TestCase):
|
||||||
self.assertEqual(j.box[2].box[1].colorspace,
|
self.assertEqual(j.box[2].box[1].colorspace,
|
||||||
glymur.core.GREYSCALE)
|
glymur.core.GREYSCALE)
|
||||||
|
|
||||||
@unittest.skipIf(os.name == "nt", "NamedTemporaryFile issue on windows")
|
|
||||||
def test_grey_with_two_extra_comps(self):
|
def test_grey_with_two_extra_comps(self):
|
||||||
"""should be able to write gray + two extra components"""
|
"""should be able to write gray + two extra components"""
|
||||||
with tempfile.NamedTemporaryFile(suffix='.jp2') as tfile:
|
with tempfile.NamedTemporaryFile(suffix='.jp2') as tfile:
|
||||||
|
|
@ -495,7 +507,6 @@ class TestJp2k_write(unittest.TestCase):
|
||||||
data = np.zeros((128, 128, 3), dtype=np.uint8)
|
data = np.zeros((128, 128, 3), dtype=np.uint8)
|
||||||
j.write(data, colorspace='ycc')
|
j.write(data, colorspace='ycc')
|
||||||
|
|
||||||
@unittest.skipIf(os.name == "nt", "NamedTemporaryFile issue on windows")
|
|
||||||
def test_write_with_jp2_in_caps(self):
|
def test_write_with_jp2_in_caps(self):
|
||||||
"""should be able to write with JP2 suffix."""
|
"""should be able to write with JP2 suffix."""
|
||||||
j2k = Jp2k(self.j2kfile)
|
j2k = Jp2k(self.j2kfile)
|
||||||
|
|
@ -506,7 +517,6 @@ class TestJp2k_write(unittest.TestCase):
|
||||||
actdata = ofile.read()
|
actdata = ofile.read()
|
||||||
np.testing.assert_array_equal(actdata, expdata)
|
np.testing.assert_array_equal(actdata, expdata)
|
||||||
|
|
||||||
@unittest.skipIf(os.name == "nt", "NamedTemporaryFile issue on windows")
|
|
||||||
def test_write_srgb_without_mct(self):
|
def test_write_srgb_without_mct(self):
|
||||||
"""should be able to write RGB without specifying mct"""
|
"""should be able to write RGB without specifying mct"""
|
||||||
j2k = Jp2k(self.j2kfile)
|
j2k = Jp2k(self.j2kfile)
|
||||||
|
|
@ -520,7 +530,6 @@ class TestJp2k_write(unittest.TestCase):
|
||||||
codestream = ofile.get_codestream()
|
codestream = ofile.get_codestream()
|
||||||
self.assertEqual(codestream.segment[2].spcod[3], 0) # no mct
|
self.assertEqual(codestream.segment[2].spcod[3], 0) # no mct
|
||||||
|
|
||||||
@unittest.skipIf(os.name == "nt", "NamedTemporaryFile issue on windows")
|
|
||||||
def test_write_grayscale_with_mct(self):
|
def test_write_grayscale_with_mct(self):
|
||||||
"""MCT usage makes no sense for grayscale images."""
|
"""MCT usage makes no sense for grayscale images."""
|
||||||
j2k = Jp2k(self.j2kfile)
|
j2k = Jp2k(self.j2kfile)
|
||||||
|
|
@ -530,7 +539,6 @@ class TestJp2k_write(unittest.TestCase):
|
||||||
with self.assertRaises(IOError):
|
with self.assertRaises(IOError):
|
||||||
ofile.write(expdata[:, :, 0], mct=True)
|
ofile.write(expdata[:, :, 0], mct=True)
|
||||||
|
|
||||||
@unittest.skipIf(os.name == "nt", "NamedTemporaryFile issue on windows")
|
|
||||||
def test_write_cprl(self):
|
def test_write_cprl(self):
|
||||||
"""Must be able to write a CPRL progression order file"""
|
"""Must be able to write a CPRL progression order file"""
|
||||||
# Issue 17
|
# Issue 17
|
||||||
|
|
@ -757,7 +765,7 @@ class TestJp2k_2_1(unittest.TestCase):
|
||||||
@unittest.skipIf(OPJ_DATA_ROOT is None,
|
@unittest.skipIf(OPJ_DATA_ROOT is None,
|
||||||
"OPJ_DATA_ROOT environment variable not set")
|
"OPJ_DATA_ROOT environment variable not set")
|
||||||
class TestParsing(unittest.TestCase):
|
class TestParsing(unittest.TestCase):
|
||||||
"""Tests for verifying how paring may be altered."""
|
"""Tests for verifying how parsing may be altered."""
|
||||||
def setUp(self):
|
def setUp(self):
|
||||||
self.jp2file = glymur.data.nemo()
|
self.jp2file = glymur.data.nemo()
|
||||||
# Reset parseoptions for every test.
|
# Reset parseoptions for every test.
|
||||||
|
|
@ -766,6 +774,7 @@ class TestParsing(unittest.TestCase):
|
||||||
def tearDown(self):
|
def tearDown(self):
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
@unittest.skipIf(sys.platform.startswith('linux'), 'Failing on linux')
|
||||||
def test_bad_rsiz(self):
|
def test_bad_rsiz(self):
|
||||||
"""Should not warn if RSIZ when parsing is turned off."""
|
"""Should not warn if RSIZ when parsing is turned off."""
|
||||||
# Actually there are three warning triggered by this codestream.
|
# Actually there are three warning triggered by this codestream.
|
||||||
|
|
@ -776,11 +785,11 @@ class TestParsing(unittest.TestCase):
|
||||||
self.assertEqual(len(w), 0)
|
self.assertEqual(len(w), 0)
|
||||||
|
|
||||||
glymur.set_parseoptions(codestream=True)
|
glymur.set_parseoptions(codestream=True)
|
||||||
if sys.hexversion >= 0x03000000:
|
with warnings.catch_warnings(record=True) as w:
|
||||||
with self.assertWarns(UserWarning):
|
|
||||||
jp2 = Jp2k(filename)
|
jp2 = Jp2k(filename)
|
||||||
|
self.assertTrue(issubclass(w[0].category, UserWarning))
|
||||||
|
self.assertTrue('Invalid profile' in str(w[0].message))
|
||||||
|
|
||||||
#@unittest.skip("blah")
|
|
||||||
def test_main_header(self):
|
def test_main_header(self):
|
||||||
"""Verify that the main header is not loaded when parsing turned off."""
|
"""Verify that the main header is not loaded when parsing turned off."""
|
||||||
# The hidden _main_header attribute should show up after accessing it.
|
# The hidden _main_header attribute should show up after accessing it.
|
||||||
|
|
@ -793,44 +802,80 @@ class TestParsing(unittest.TestCase):
|
||||||
|
|
||||||
@unittest.skipIf(OPJ_DATA_ROOT is None,
|
@unittest.skipIf(OPJ_DATA_ROOT is None,
|
||||||
"OPJ_DATA_ROOT environment variable not set")
|
"OPJ_DATA_ROOT environment variable not set")
|
||||||
class TestJp2kOpjDataRoot(unittest.TestCase):
|
class TestJp2kOpjDataRootWarnings(unittest.TestCase):
|
||||||
"""These tests should be run by just about all configuration."""
|
"""These tests should be run by just about all configuration."""
|
||||||
|
|
||||||
def test_undecodeable_box_id(self):
|
def test_undecodeable_box_id(self):
|
||||||
"""Should warn in case of undecodeable box ID but not error out."""
|
"""Should warn in case of undecodeable box ID but not error out."""
|
||||||
filename = opj_data_file('input/nonregression/edf_c2_1013627.jp2')
|
filename = opj_data_file('input/nonregression/edf_c2_1013627.jp2')
|
||||||
if sys.hexversion < 0x03000000:
|
with warnings.catch_warnings(record=True) as w:
|
||||||
with warnings.catch_warnings():
|
warnings.simplefilter('always')
|
||||||
warnings.simplefilter("ignore")
|
|
||||||
jp2 = Jp2k(filename)
|
|
||||||
else:
|
|
||||||
with self.assertWarns(UserWarning):
|
|
||||||
jp2 = Jp2k(filename)
|
jp2 = Jp2k(filename)
|
||||||
|
self.assertTrue(issubclass(w[0].category, UserWarning))
|
||||||
|
self.assertTrue('Unrecognized box' in str(w[0].message))
|
||||||
|
|
||||||
# Now make sure we got all of the boxes. Ignore the last, which was
|
# Now make sure we got all of the boxes. Ignore the last, which was
|
||||||
# bad.
|
# bad.
|
||||||
box_ids = [box.box_id for box in jp2.box[:-1]]
|
box_ids = [box.box_id for box in jp2.box[:-1]]
|
||||||
self.assertEqual(box_ids, ['jP ', 'ftyp', 'jp2h', 'jp2c'])
|
self.assertEqual(box_ids, ['jP ', 'ftyp', 'jp2h', 'jp2c'])
|
||||||
|
|
||||||
def test_invalid_approximation(self):
|
def test_bad_ftyp_brand(self):
|
||||||
"""Should warn in case of bad ftyp brand."""
|
"""Should warn in case of bad ftyp brand."""
|
||||||
filename = opj_data_file('input/nonregression/edf_c2_1000290.jp2')
|
filename = opj_data_file('input/nonregression/edf_c2_1000290.jp2')
|
||||||
with self.assertWarns(UserWarning):
|
with warnings.catch_warnings(record=True) as w:
|
||||||
|
warnings.simplefilter('always')
|
||||||
jp2 = Jp2k(filename)
|
jp2 = Jp2k(filename)
|
||||||
|
self.assertTrue(issubclass(w[0].category, UserWarning))
|
||||||
|
|
||||||
@unittest.skipIf(sys.hexversion < 0x03000000, "Test requires Python 3.3+")
|
|
||||||
def test_invalid_approximation(self):
|
def test_invalid_approximation(self):
|
||||||
"""Should warn in case of invalid approximation."""
|
"""Should warn in case of invalid approximation."""
|
||||||
filename = opj_data_file('input/nonregression/edf_c2_1015644.jp2')
|
filename = opj_data_file('input/nonregression/edf_c2_1015644.jp2')
|
||||||
with self.assertWarns(UserWarning):
|
with warnings.catch_warnings(record=True) as w:
|
||||||
|
warnings.simplefilter('always')
|
||||||
jp2 = Jp2k(filename)
|
jp2 = Jp2k(filename)
|
||||||
|
self.assertTrue(issubclass(w[0].category, UserWarning))
|
||||||
|
self.assertTrue('Invalid approximation' in str(w[0].message))
|
||||||
|
|
||||||
@unittest.skipIf(sys.hexversion < 0x03000000, "Test requires Python 3.3+")
|
@unittest.skipIf(sys.platform.startswith('linux'), 'Failing on linux')
|
||||||
def test_invalid_colorspace(self):
|
def test_invalid_colorspace(self):
|
||||||
"""Should warn in case of invalid colorspace."""
|
"""Should warn in case of invalid colorspace."""
|
||||||
filename = opj_data_file('input/nonregression/edf_c2_1103421.jp2')
|
filename = opj_data_file('input/nonregression/edf_c2_1103421.jp2')
|
||||||
with self.assertWarns(UserWarning):
|
with warnings.catch_warnings(record=True) as w:
|
||||||
|
warnings.simplefilter('always')
|
||||||
jp2 = Jp2k(filename)
|
jp2 = Jp2k(filename)
|
||||||
|
self.assertTrue(issubclass(w[1].category, UserWarning))
|
||||||
|
self.assertTrue('Unrecognized colorspace' in str(w[1].message))
|
||||||
|
|
||||||
|
def test_stupid_windows_eol_at_end(self):
|
||||||
|
"""Garbage characters at the end of the file."""
|
||||||
|
filename = opj_data_file('input/nonregression/issue211.jp2')
|
||||||
|
with warnings.catch_warnings(record=True) as w:
|
||||||
|
warnings.simplefilter('always')
|
||||||
|
jp2 = Jp2k(filename)
|
||||||
|
self.assertTrue(issubclass(w[1].category, UserWarning))
|
||||||
|
|
||||||
|
|
||||||
|
@unittest.skipIf(OPJ_DATA_ROOT is None,
|
||||||
|
"OPJ_DATA_ROOT environment variable not set")
|
||||||
|
class TestJp2kOpjDataRoot(unittest.TestCase):
|
||||||
|
"""These tests should be run by just about all configuration."""
|
||||||
|
|
||||||
|
@unittest.skipIf(os.name == "nt", "NamedTemporaryFile issue on windows")
|
||||||
|
def test_irreversible(self):
|
||||||
|
"""Irreversible"""
|
||||||
|
filename = opj_data_file('input/nonregression/issue141.rawl')
|
||||||
|
expdata = np.fromfile(filename, dtype=np.uint16)
|
||||||
|
expdata.resize((2816, 2048))
|
||||||
|
with tempfile.NamedTemporaryFile(suffix='.j2k') as tfile:
|
||||||
|
j = Jp2k(tfile.name, 'wb')
|
||||||
|
j.write(expdata, irreversible=True)
|
||||||
|
|
||||||
|
codestream = j.get_codestream()
|
||||||
|
self.assertEqual(codestream.segment[2].spcod[8],
|
||||||
|
glymur.core.WAVELET_XFORM_9X7_IRREVERSIBLE)
|
||||||
|
|
||||||
|
actdata = j.read()
|
||||||
|
self.assertTrue(fixtures.mse(actdata, expdata) < 250)
|
||||||
|
|
||||||
def test_no_cxform_pclr_jp2(self):
|
def test_no_cxform_pclr_jp2(self):
|
||||||
"""Indices for pclr jpxfile if no color transform"""
|
"""Indices for pclr jpxfile if no color transform"""
|
||||||
|
|
@ -850,17 +895,6 @@ class TestJp2kOpjDataRoot(unittest.TestCase):
|
||||||
rgb_from_idx[r, c] = palette[idx[r, c]]
|
rgb_from_idx[r, c] = palette[idx[r, c]]
|
||||||
np.testing.assert_array_equal(rgb, rgb_from_idx)
|
np.testing.assert_array_equal(rgb, rgb_from_idx)
|
||||||
|
|
||||||
def test_stupid_windows_eol_at_end(self):
|
|
||||||
"""Garbage characters at the end of the file."""
|
|
||||||
filename = opj_data_file('input/nonregression/issue211.jp2')
|
|
||||||
if sys.hexversion < 0x03000000:
|
|
||||||
with warnings.catch_warnings():
|
|
||||||
warnings.simplefilter("ignore")
|
|
||||||
jp2 = Jp2k(filename)
|
|
||||||
else:
|
|
||||||
with self.assertWarns(UserWarning):
|
|
||||||
jp2 = Jp2k(filename)
|
|
||||||
|
|
||||||
def test_read_differing_subsamples(self):
|
def test_read_differing_subsamples(self):
|
||||||
"""should error out with read used on differently subsampled images"""
|
"""should error out with read used on differently subsampled images"""
|
||||||
# Verify that we error out appropriately if we use the read method
|
# Verify that we error out appropriately if we use the read method
|
||||||
|
|
|
||||||
File diff suppressed because it is too large
Load diff
389
glymur/test/test_opj_suite_2p1.py
Normal file
389
glymur/test/test_opj_suite_2p1.py
Normal file
|
|
@ -0,0 +1,389 @@
|
||||||
|
"""
|
||||||
|
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
|
||||||
|
|
||||||
|
import re
|
||||||
|
import sys
|
||||||
|
import unittest
|
||||||
|
|
||||||
|
import warnings
|
||||||
|
|
||||||
|
import numpy as np
|
||||||
|
|
||||||
|
from glymur import Jp2k
|
||||||
|
import glymur
|
||||||
|
|
||||||
|
from .fixtures import 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'''(1|2.0.0)''',
|
||||||
|
glymur.version.openjpeg_version) is not None,
|
||||||
|
"Only supported in 2.0.1 or higher")
|
||||||
|
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_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()
|
||||||
5320
glymur/test/test_opj_suite_dump.py
Normal file
5320
glymur/test/test_opj_suite_dump.py
Normal file
File diff suppressed because it is too large
Load diff
|
|
@ -13,6 +13,7 @@ import re
|
||||||
import sys
|
import sys
|
||||||
import tempfile
|
import tempfile
|
||||||
import unittest
|
import unittest
|
||||||
|
import warnings
|
||||||
|
|
||||||
import numpy as np
|
import numpy as np
|
||||||
|
|
||||||
|
|
@ -77,14 +78,13 @@ class TestSuiteNegative(unittest.TestCase):
|
||||||
jp2k.get_codestream(header_only=False)
|
jp2k.get_codestream(header_only=False)
|
||||||
self.assertTrue(True)
|
self.assertTrue(True)
|
||||||
|
|
||||||
@unittest.skipIf(sys.hexversion < 0x03020000,
|
|
||||||
"Uses features introduced in 3.2.")
|
|
||||||
def test_nr_illegalclrtransform(self):
|
def test_nr_illegalclrtransform(self):
|
||||||
"""EOC marker is bad"""
|
"""EOC marker is bad"""
|
||||||
relpath = 'input/nonregression/illegalcolortransform.j2k'
|
relpath = 'input/nonregression/illegalcolortransform.j2k'
|
||||||
jfile = opj_data_file(relpath)
|
jfile = opj_data_file(relpath)
|
||||||
jp2k = Jp2k(jfile)
|
jp2k = Jp2k(jfile)
|
||||||
with self.assertWarns(UserWarning):
|
with warnings.catch_warnings(record=True) as w:
|
||||||
|
warnings.simplefilter('ignore')
|
||||||
codestream = jp2k.get_codestream(header_only=False)
|
codestream = jp2k.get_codestream(header_only=False)
|
||||||
|
|
||||||
# Verify that the last segment returned in the codestream is SOD,
|
# Verify that the last segment returned in the codestream is SOD,
|
||||||
|
|
@ -119,8 +119,6 @@ class TestSuiteNegative(unittest.TestCase):
|
||||||
with self.assertRaises(IOError):
|
with self.assertRaises(IOError):
|
||||||
j.write(data, cbsize=(2, 2048))
|
j.write(data, cbsize=(2, 2048))
|
||||||
|
|
||||||
@unittest.skipIf(sys.hexversion < 0x03020000,
|
|
||||||
"Uses features introduced in 3.2.")
|
|
||||||
def test_exceeded_box(self):
|
def test_exceeded_box(self):
|
||||||
"""should warn if reading past end of a box"""
|
"""should warn if reading past end of a box"""
|
||||||
# Verify that a warning is issued if we read past the end of a box
|
# Verify that a warning is issued if we read past the end of a box
|
||||||
|
|
@ -128,7 +126,8 @@ class TestSuiteNegative(unittest.TestCase):
|
||||||
# short.
|
# short.
|
||||||
infile = os.path.join(OPJ_DATA_ROOT,
|
infile = os.path.join(OPJ_DATA_ROOT,
|
||||||
'input/nonregression/mem-b2ace68c-1381.jp2')
|
'input/nonregression/mem-b2ace68c-1381.jp2')
|
||||||
with self.assertWarns(UserWarning):
|
with warnings.catch_warnings(record=True) as w:
|
||||||
|
warnings.simplefilter('ignore')
|
||||||
Jp2k(infile)
|
Jp2k(infile)
|
||||||
|
|
||||||
@unittest.skipIf(os.name == "nt", "Temporary file issue on window.")
|
@unittest.skipIf(os.name == "nt", "Temporary file issue on window.")
|
||||||
|
|
|
||||||
376
glymur/test/test_opj_suite_warn.py
Normal file
376
glymur/test/test_opj_suite_warn.py
Normal file
|
|
@ -0,0 +1,376 @@
|
||||||
|
"""
|
||||||
|
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
|
||||||
|
|
||||||
|
import re
|
||||||
|
import sys
|
||||||
|
import unittest
|
||||||
|
|
||||||
|
import warnings
|
||||||
|
|
||||||
|
import numpy as np
|
||||||
|
|
||||||
|
from glymur import Jp2k
|
||||||
|
import glymur
|
||||||
|
|
||||||
|
from .fixtures import 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")
|
||||||
|
class TestSuiteDumpWarnings(unittest.TestCase):
|
||||||
|
|
||||||
|
def setUp(self):
|
||||||
|
pass
|
||||||
|
|
||||||
|
def tearDown(self):
|
||||||
|
pass
|
||||||
|
|
||||||
|
def test_NR_broken_jp2_dump(self):
|
||||||
|
jfile = opj_data_file('input/nonregression/broken.jp2')
|
||||||
|
with warnings.catch_warnings(record=True) as w:
|
||||||
|
warnings.simplefilter('ignore')
|
||||||
|
# colr box has bad length.
|
||||||
|
jp2 = Jp2k(jfile)
|
||||||
|
|
||||||
|
ids = [box.box_id for box in jp2.box]
|
||||||
|
self.assertEqual(ids, ['jP ', 'ftyp', 'jp2h', 'jp2c'])
|
||||||
|
|
||||||
|
ids = [box.box_id for box in jp2.box[2].box]
|
||||||
|
self.assertEqual(ids, ['ihdr', 'colr'])
|
||||||
|
|
||||||
|
# Signature box. Check for corruption.
|
||||||
|
self.assertEqual(jp2.box[0].signature, (13, 10, 135, 10))
|
||||||
|
|
||||||
|
# File type box.
|
||||||
|
self.assertEqual(jp2.box[1].brand, 'jp2 ')
|
||||||
|
self.assertEqual(jp2.box[1].minor_version, 0)
|
||||||
|
self.assertEqual(jp2.box[1].compatibility_list[0], 'jp2 ')
|
||||||
|
|
||||||
|
# Jp2 Header
|
||||||
|
# Image header
|
||||||
|
self.assertEqual(jp2.box[2].box[0].height, 152)
|
||||||
|
self.assertEqual(jp2.box[2].box[0].width, 203)
|
||||||
|
self.assertEqual(jp2.box[2].box[0].num_components, 3)
|
||||||
|
self.assertEqual(jp2.box[2].box[0].bits_per_component, 8)
|
||||||
|
self.assertEqual(jp2.box[2].box[0].signed, False)
|
||||||
|
self.assertEqual(jp2.box[2].box[0].compression, 7) # wavelet
|
||||||
|
self.assertEqual(jp2.box[2].box[0].colorspace_unknown, False)
|
||||||
|
self.assertEqual(jp2.box[2].box[0].ip_provided, False)
|
||||||
|
|
||||||
|
# Jp2 Header
|
||||||
|
# Colour specification
|
||||||
|
self.assertEqual(jp2.box[2].box[1].method,
|
||||||
|
glymur.core.ENUMERATED_COLORSPACE)
|
||||||
|
self.assertEqual(jp2.box[2].box[1].precedence, 0)
|
||||||
|
self.assertEqual(jp2.box[2].box[1].approximation, 0) # not allowed?
|
||||||
|
self.assertEqual(jp2.box[2].box[1].colorspace, glymur.core.SRGB)
|
||||||
|
|
||||||
|
c = jp2.box[3].main_header
|
||||||
|
|
||||||
|
ids = [x.marker_id for x in c.segment]
|
||||||
|
expected = ['SOC', 'SIZ', 'CME', 'COD', 'QCD', 'QCC', 'QCC']
|
||||||
|
self.assertEqual(ids, expected)
|
||||||
|
|
||||||
|
# SIZ: Image and tile size
|
||||||
|
# Profile:
|
||||||
|
self.assertEqual(c.segment[1].rsiz, 0)
|
||||||
|
# Reference grid size
|
||||||
|
self.assertEqual(c.segment[1].xsiz, 203)
|
||||||
|
self.assertEqual(c.segment[1].ysiz, 152)
|
||||||
|
# Reference grid offset
|
||||||
|
self.assertEqual((c.segment[1].xosiz, c.segment[1].yosiz), (0, 0))
|
||||||
|
# Tile size
|
||||||
|
self.assertEqual((c.segment[1].xtsiz, c.segment[1].ytsiz), (203, 152))
|
||||||
|
# Tile offset
|
||||||
|
self.assertEqual((c.segment[1].xtosiz, c.segment[1].ytosiz), (0, 0))
|
||||||
|
# bitdepth
|
||||||
|
self.assertEqual(c.segment[1].bitdepth, (8, 8, 8))
|
||||||
|
# signed
|
||||||
|
self.assertEqual(c.segment[1].signed, (False, False, False))
|
||||||
|
# subsampling
|
||||||
|
self.assertEqual(list(zip(c.segment[1].xrsiz, c.segment[1].yrsiz)),
|
||||||
|
[(1, 1)] * 3)
|
||||||
|
|
||||||
|
# COM: comment
|
||||||
|
# Registration
|
||||||
|
self.assertEqual(c.segment[2].rcme, glymur.core.RCME_ISO_8859_1)
|
||||||
|
# Comment value
|
||||||
|
self.assertEqual(c.segment[2].ccme.decode('latin-1'),
|
||||||
|
"Creator: JasPer Version 1.701.0")
|
||||||
|
|
||||||
|
# COD: Coding style default
|
||||||
|
self.assertFalse(c.segment[3].scod & 2) # no sop
|
||||||
|
self.assertFalse(c.segment[3].scod & 4) # no eph
|
||||||
|
self.assertEqual(c.segment[3].spcod[0], glymur.core.LRCP)
|
||||||
|
self.assertEqual(c.segment[3].layers, 1) # layers = 1
|
||||||
|
self.assertEqual(c.segment[3].spcod[3], 1) # mct
|
||||||
|
self.assertEqual(c.segment[3].spcod[4], 5) # level
|
||||||
|
self.assertEqual(tuple(c.segment[3].code_block_size),
|
||||||
|
(64, 64)) # cblk
|
||||||
|
# Selective arithmetic coding bypass
|
||||||
|
self.assertFalse(c.segment[3].spcod[7] & 0x01)
|
||||||
|
# Reset context probabilities
|
||||||
|
self.assertFalse(c.segment[3].spcod[7] & 0x02)
|
||||||
|
# Termination on each coding pass
|
||||||
|
self.assertFalse(c.segment[3].spcod[7] & 0x04)
|
||||||
|
# Vertically causal context
|
||||||
|
self.assertFalse(c.segment[3].spcod[7] & 0x08)
|
||||||
|
# Predictable termination
|
||||||
|
self.assertFalse(c.segment[3].spcod[7] & 0x0010)
|
||||||
|
# Segmentation symbols
|
||||||
|
self.assertFalse(c.segment[3].spcod[7] & 0x0020)
|
||||||
|
self.assertEqual(c.segment[3].spcod[8],
|
||||||
|
glymur.core.WAVELET_XFORM_5X3_REVERSIBLE)
|
||||||
|
self.assertEqual(len(c.segment[3].spcod), 9)
|
||||||
|
|
||||||
|
# QCD: Quantization default
|
||||||
|
self.assertEqual(c.segment[4].sqcd & 0x1f, 0)
|
||||||
|
self.assertEqual(c.segment[4].guard_bits, 2)
|
||||||
|
self.assertEqual(c.segment[4].mantissa, [0] * 16)
|
||||||
|
self.assertEqual(c.segment[4].exponent,
|
||||||
|
[8] + [9, 9, 10] * 5)
|
||||||
|
|
||||||
|
# QCC: Quantization component
|
||||||
|
# associated component
|
||||||
|
self.assertEqual(c.segment[5].cqcc, 1)
|
||||||
|
self.assertEqual(c.segment[5].guard_bits, 2)
|
||||||
|
# quantization type
|
||||||
|
self.assertEqual(c.segment[5].sqcc & 0x1f, 0) # none
|
||||||
|
self.assertEqual(c.segment[5].mantissa, [0] * 16)
|
||||||
|
self.assertEqual(c.segment[5].exponent,
|
||||||
|
[8] + [9, 9, 10] * 5)
|
||||||
|
|
||||||
|
# QCC: Quantization component
|
||||||
|
# associated component
|
||||||
|
self.assertEqual(c.segment[6].cqcc, 2)
|
||||||
|
self.assertEqual(c.segment[6].guard_bits, 2)
|
||||||
|
# quantization type
|
||||||
|
self.assertEqual(c.segment[6].sqcc & 0x1f, 0) # none
|
||||||
|
self.assertEqual(c.segment[6].mantissa, [0] * 16)
|
||||||
|
self.assertEqual(c.segment[6].exponent,
|
||||||
|
[8] + [9, 9, 10] * 5)
|
||||||
|
|
||||||
|
def test_NR_broken2_jp2_dump(self):
|
||||||
|
# Invalid marker ID on codestream.
|
||||||
|
jfile = opj_data_file('input/nonregression/broken2.jp2')
|
||||||
|
with warnings.catch_warnings(record=True) as w:
|
||||||
|
warnings.simplefilter('ignore')
|
||||||
|
jp2 = Jp2k(jfile)
|
||||||
|
|
||||||
|
self.assertEqual(jp2.box[-1].main_header.segment[-1].marker_id, 'QCC')
|
||||||
|
|
||||||
|
@unittest.skipIf(sys.maxsize < 2**32, 'Do not run on 32-bit platforms')
|
||||||
|
def test_NR_broken3_jp2_dump(self):
|
||||||
|
"""
|
||||||
|
NR_broken3_jp2_dump
|
||||||
|
|
||||||
|
The file in question here has a colr box with an erroneous box
|
||||||
|
length of over 1GB. Don't run it on 32-bit platforms.
|
||||||
|
"""
|
||||||
|
jfile = opj_data_file('input/nonregression/broken3.jp2')
|
||||||
|
with warnings.catch_warnings(record=True) as w:
|
||||||
|
warnings.simplefilter('ignore')
|
||||||
|
jp2 = Jp2k(jfile)
|
||||||
|
|
||||||
|
ids = [box.box_id for box in jp2.box]
|
||||||
|
self.assertEqual(ids, ['jP ', 'ftyp', 'jp2h', 'jp2c'])
|
||||||
|
|
||||||
|
ids = [box.box_id for box in jp2.box[2].box]
|
||||||
|
self.assertEqual(ids, ['ihdr', 'colr'])
|
||||||
|
|
||||||
|
# Signature box. Check for corruption.
|
||||||
|
self.assertEqual(jp2.box[0].signature, (13, 10, 135, 10))
|
||||||
|
|
||||||
|
# File type box.
|
||||||
|
self.assertEqual(jp2.box[1].brand, 'jp2 ')
|
||||||
|
self.assertEqual(jp2.box[1].minor_version, 0)
|
||||||
|
self.assertEqual(jp2.box[1].compatibility_list[0], 'jp2 ')
|
||||||
|
|
||||||
|
# Jp2 Header
|
||||||
|
# Image header
|
||||||
|
self.assertEqual(jp2.box[2].box[0].height, 152)
|
||||||
|
self.assertEqual(jp2.box[2].box[0].width, 203)
|
||||||
|
self.assertEqual(jp2.box[2].box[0].num_components, 3)
|
||||||
|
self.assertEqual(jp2.box[2].box[0].bits_per_component, 8)
|
||||||
|
self.assertEqual(jp2.box[2].box[0].signed, False)
|
||||||
|
self.assertEqual(jp2.box[2].box[0].compression, 7) # wavelet
|
||||||
|
self.assertEqual(jp2.box[2].box[0].colorspace_unknown, False)
|
||||||
|
self.assertEqual(jp2.box[2].box[0].ip_provided, False)
|
||||||
|
|
||||||
|
# Jp2 Header
|
||||||
|
# Colour specification
|
||||||
|
self.assertEqual(jp2.box[2].box[1].method,
|
||||||
|
glymur.core.ENUMERATED_COLORSPACE)
|
||||||
|
self.assertEqual(jp2.box[2].box[1].precedence, 0)
|
||||||
|
self.assertEqual(jp2.box[2].box[1].approximation, 0) # JP2
|
||||||
|
self.assertEqual(jp2.box[2].box[1].colorspace, glymur.core.SRGB)
|
||||||
|
|
||||||
|
c = jp2.box[3].main_header
|
||||||
|
|
||||||
|
ids = [x.marker_id for x in c.segment]
|
||||||
|
expected = ['SOC', 'SIZ', 'CME', 'COD', 'QCD', 'QCC', 'QCC']
|
||||||
|
self.assertEqual(ids, expected)
|
||||||
|
|
||||||
|
# SIZ: Image and tile size
|
||||||
|
# Profile:
|
||||||
|
self.assertEqual(c.segment[1].rsiz, 0)
|
||||||
|
# Reference grid size
|
||||||
|
self.assertEqual(c.segment[1].xsiz, 203)
|
||||||
|
self.assertEqual(c.segment[1].ysiz, 152)
|
||||||
|
# Reference grid offset
|
||||||
|
self.assertEqual((c.segment[1].xosiz, c.segment[1].yosiz), (0, 0))
|
||||||
|
# Tile size
|
||||||
|
self.assertEqual((c.segment[1].xtsiz, c.segment[1].ytsiz), (203, 152))
|
||||||
|
# Tile offset
|
||||||
|
self.assertEqual((c.segment[1].xtosiz, c.segment[1].ytosiz), (0, 0))
|
||||||
|
# bitdepth
|
||||||
|
self.assertEqual(c.segment[1].bitdepth, (8, 8, 8))
|
||||||
|
# signed
|
||||||
|
self.assertEqual(c.segment[1].signed, (False, False, False))
|
||||||
|
# subsampling
|
||||||
|
self.assertEqual(list(zip(c.segment[1].xrsiz, c.segment[1].yrsiz)),
|
||||||
|
[(1, 1)] * 3)
|
||||||
|
|
||||||
|
# COM: comment
|
||||||
|
# Registration
|
||||||
|
self.assertEqual(c.segment[2].rcme, glymur.core.RCME_ISO_8859_1)
|
||||||
|
# Comment value
|
||||||
|
self.assertEqual(c.segment[2].ccme.decode('latin-1'),
|
||||||
|
"Creator: JasPer Vers)on 1.701.0")
|
||||||
|
|
||||||
|
# COD: Coding style default
|
||||||
|
self.assertFalse(c.segment[3].scod & 2) # no sop
|
||||||
|
self.assertFalse(c.segment[3].scod & 4) # no eph
|
||||||
|
self.assertEqual(c.segment[3].spcod[0], glymur.core.LRCP)
|
||||||
|
self.assertEqual(c.segment[3].layers, 1) # layers = 1
|
||||||
|
self.assertEqual(c.segment[3].spcod[3], 1) # mct
|
||||||
|
self.assertEqual(c.segment[3].spcod[4], 5) # level
|
||||||
|
self.assertEqual(tuple(c.segment[3].code_block_size),
|
||||||
|
(64, 64)) # cblk
|
||||||
|
# Selective arithmetic coding bypass
|
||||||
|
self.assertFalse(c.segment[3].spcod[7] & 0x01)
|
||||||
|
# Reset context probabilities
|
||||||
|
self.assertFalse(c.segment[3].spcod[7] & 0x02)
|
||||||
|
# Termination on each coding pass
|
||||||
|
self.assertFalse(c.segment[3].spcod[7] & 0x04)
|
||||||
|
# Vertically causal context
|
||||||
|
self.assertFalse(c.segment[3].spcod[7] & 0x08)
|
||||||
|
# Predictable termination
|
||||||
|
self.assertFalse(c.segment[3].spcod[7] & 0x0010)
|
||||||
|
# Segmentation symbols
|
||||||
|
self.assertFalse(c.segment[3].spcod[7] & 0x0020)
|
||||||
|
self.assertEqual(c.segment[3].spcod[8],
|
||||||
|
glymur.core.WAVELET_XFORM_5X3_REVERSIBLE)
|
||||||
|
self.assertEqual(len(c.segment[3].spcod), 9)
|
||||||
|
|
||||||
|
# QCD: Quantization default
|
||||||
|
self.assertEqual(c.segment[4].sqcd & 0x1f, 0)
|
||||||
|
self.assertEqual(c.segment[4].guard_bits, 2)
|
||||||
|
self.assertEqual(c.segment[4].mantissa, [0] * 16)
|
||||||
|
self.assertEqual(c.segment[4].exponent,
|
||||||
|
[8] + [9, 9, 10] * 5)
|
||||||
|
|
||||||
|
# QCC: Quantization component
|
||||||
|
# associated component
|
||||||
|
self.assertEqual(c.segment[5].cqcc, 1)
|
||||||
|
self.assertEqual(c.segment[5].guard_bits, 2)
|
||||||
|
# quantization type
|
||||||
|
self.assertEqual(c.segment[5].sqcc & 0x1f, 0) # none
|
||||||
|
self.assertEqual(c.segment[5].mantissa, [0] * 16)
|
||||||
|
self.assertEqual(c.segment[5].exponent,
|
||||||
|
[8] + [9, 9, 10] * 5)
|
||||||
|
|
||||||
|
# QCC: Quantization component
|
||||||
|
# associated component
|
||||||
|
self.assertEqual(c.segment[6].cqcc, 2)
|
||||||
|
self.assertEqual(c.segment[6].guard_bits, 2)
|
||||||
|
# quantization type
|
||||||
|
self.assertEqual(c.segment[6].sqcc & 0x1f, 0) # none
|
||||||
|
self.assertEqual(c.segment[6].mantissa, [0] * 16)
|
||||||
|
self.assertEqual(c.segment[6].exponent,
|
||||||
|
[8] + [9, 9, 10] * 5)
|
||||||
|
|
||||||
|
def test_NR_broken4_jp2_dump(self):
|
||||||
|
# Has an invalid marker in the main header
|
||||||
|
jfile = opj_data_file('input/nonregression/broken4.jp2')
|
||||||
|
with warnings.catch_warnings(record=True) as w:
|
||||||
|
warnings.simplefilter('ignore')
|
||||||
|
jp2 = Jp2k(jfile)
|
||||||
|
|
||||||
|
self.assertEqual(jp2.box[-1].main_header.segment[-1].marker_id, 'QCC')
|
||||||
|
|
||||||
|
def test_NR_gdal_fuzzer_assert_in_opj_j2k_read_SQcd_SQcc_patch_jp2(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(record=True) as w:
|
||||||
|
warnings.simplefilter('ignore')
|
||||||
|
Jp2k(jfile)
|
||||||
|
|
||||||
|
def test_NR_gdal_fuzzer_check_comp_dx_dy_jp2_dump(self):
|
||||||
|
lst = ['input', 'nonregression', 'gdal_fuzzer_check_comp_dx_dy.jp2']
|
||||||
|
jfile = opj_data_file('/'.join(lst))
|
||||||
|
with warnings.catch_warnings(record=True) as w:
|
||||||
|
warnings.simplefilter('ignore')
|
||||||
|
Jp2k(jfile)
|
||||||
|
|
||||||
|
def test_NR_gdal_fuzzer_check_number_of_tiles(self):
|
||||||
|
# Has an impossible tiling setup.
|
||||||
|
lst = ['input', 'nonregression',
|
||||||
|
'gdal_fuzzer_check_number_of_tiles.jp2']
|
||||||
|
jfile = opj_data_file('/'.join(lst))
|
||||||
|
with warnings.catch_warnings(record=True) as w:
|
||||||
|
warnings.simplefilter('ignore')
|
||||||
|
Jp2k(jfile)
|
||||||
|
|
||||||
|
def test_NR_gdal_fuzzer_unchecked_numresolutions_dump(self):
|
||||||
|
# Has an invalid number of resolutions.
|
||||||
|
lst = ['input', 'nonregression',
|
||||||
|
'gdal_fuzzer_unchecked_numresolutions.jp2']
|
||||||
|
jfile = opj_data_file('/'.join(lst))
|
||||||
|
with warnings.catch_warnings(record=True) as w:
|
||||||
|
warnings.simplefilter('ignore')
|
||||||
|
Jp2k(jfile)
|
||||||
|
|
||||||
|
@unittest.skipIf(re.match("1.5|2.0.0", glymur.version.openjpeg_version),
|
||||||
|
"Test not passing on 1.5.x, not introduced until 2.x")
|
||||||
|
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('ignore')
|
||||||
|
j = Jp2k(jfile)
|
||||||
|
d = j.read()
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
unittest.main()
|
||||||
|
|
@ -13,6 +13,8 @@ import tempfile
|
||||||
import unittest
|
import unittest
|
||||||
import warnings
|
import warnings
|
||||||
|
|
||||||
|
import numpy as np
|
||||||
|
|
||||||
try:
|
try:
|
||||||
import skimage.io
|
import skimage.io
|
||||||
skimage.io.use_plugin('freeimage', 'imread')
|
skimage.io.use_plugin('freeimage', 'imread')
|
||||||
|
|
@ -271,6 +273,19 @@ class TestSuiteWrite(unittest.TestCase):
|
||||||
def tearDown(self):
|
def tearDown(self):
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
def test_NR_ENC_issue141_rawl_23_encode(self):
|
||||||
|
filename = opj_data_file('input/nonregression/issue141.rawl')
|
||||||
|
expdata = np.fromfile(filename, dtype=np.uint16)
|
||||||
|
expdata.resize((2816, 2048))
|
||||||
|
with tempfile.NamedTemporaryFile(suffix='.j2k') as tfile:
|
||||||
|
j = Jp2k(tfile.name, 'wb')
|
||||||
|
j.write(expdata, irreversible=True)
|
||||||
|
|
||||||
|
codestream = j.get_codestream()
|
||||||
|
self.assertEqual(codestream.segment[2].spcod[8],
|
||||||
|
glymur.core.WAVELET_XFORM_9X7_IRREVERSIBLE)
|
||||||
|
|
||||||
|
|
||||||
def test_NR_ENC_Bretagne1_ppm_1_encode(self):
|
def test_NR_ENC_Bretagne1_ppm_1_encode(self):
|
||||||
"""NR-ENC-Bretagne1.ppm-1-encode"""
|
"""NR-ENC-Bretagne1.ppm-1-encode"""
|
||||||
infile = opj_data_file('input/nonregression/Bretagne1.ppm')
|
infile = opj_data_file('input/nonregression/Bretagne1.ppm')
|
||||||
|
|
@ -1020,7 +1035,6 @@ class TestSuiteWrite(unittest.TestCase):
|
||||||
glymur.core.WAVELET_XFORM_5X3_REVERSIBLE)
|
glymur.core.WAVELET_XFORM_5X3_REVERSIBLE)
|
||||||
self.assertEqual(len(codestream.segment[2].spcod), 9)
|
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):
|
def test_NR_ENC_random_issue_0005_tif_12_encode(self):
|
||||||
"""NR-ENC-random-issue-0005.tif-12-encode"""
|
"""NR-ENC-random-issue-0005.tif-12-encode"""
|
||||||
# opj_decompress has trouble reading it, but that is not an issue here.
|
# opj_decompress has trouble reading it, but that is not an issue here.
|
||||||
|
|
|
||||||
|
|
@ -70,7 +70,6 @@ class TestPrinting(unittest.TestCase):
|
||||||
|
|
||||||
self.assertTrue(True)
|
self.assertTrue(True)
|
||||||
|
|
||||||
@unittest.skipIf(sys.hexversion < 0x03000000, "Needs unittest in 3.x.")
|
|
||||||
def test_unknown_superbox(self):
|
def test_unknown_superbox(self):
|
||||||
"""Verify that we can handle an unknown superbox."""
|
"""Verify that we can handle an unknown superbox."""
|
||||||
with tempfile.NamedTemporaryFile(suffix='.jpx') as tfile:
|
with tempfile.NamedTemporaryFile(suffix='.jpx') as tfile:
|
||||||
|
|
@ -87,14 +86,19 @@ class TestPrinting(unittest.TestCase):
|
||||||
tfile.write(write_buffer)
|
tfile.write(write_buffer)
|
||||||
tfile.flush()
|
tfile.flush()
|
||||||
|
|
||||||
with self.assertWarns(UserWarning):
|
with warnings.catch_warnings(record=True) as w:
|
||||||
|
warnings.simplefilter('always')
|
||||||
jpx = Jp2k(tfile.name)
|
jpx = Jp2k(tfile.name)
|
||||||
|
self.assertTrue(len(w), 1)
|
||||||
|
|
||||||
glymur.set_printoptions(short=True)
|
glymur.set_printoptions(short=True)
|
||||||
with patch('sys.stdout', new=StringIO()) as fake_out:
|
with patch('sys.stdout', new=StringIO()) as fake_out:
|
||||||
print(jpx.box[-1])
|
print(jpx.box[-1])
|
||||||
actual = fake_out.getvalue().strip()
|
actual = fake_out.getvalue().strip()
|
||||||
lines = ["Unknown Box (b'grp ') @ (1399071, 20)"]
|
if sys.hexversion < 0x03000000:
|
||||||
expected = '\n'.join(lines)
|
expected = "Unknown Box (grp ) @ (1399071, 20)"
|
||||||
|
else:
|
||||||
|
expected = "Unknown Box (b'grp ') @ (1399071, 20)"
|
||||||
self.assertEqual(actual, expected)
|
self.assertEqual(actual, expected)
|
||||||
|
|
||||||
def test_printoptions_bad_argument(self):
|
def test_printoptions_bad_argument(self):
|
||||||
|
|
@ -721,6 +725,8 @@ class TestPrintingOpjDataRoot(unittest.TestCase):
|
||||||
# Reset printoptions for every test.
|
# Reset printoptions for every test.
|
||||||
glymur.set_printoptions(short=False, xml=True, codestream=True)
|
glymur.set_printoptions(short=False, xml=True, codestream=True)
|
||||||
|
|
||||||
|
warnings.resetwarnings()
|
||||||
|
|
||||||
def tearDown(self):
|
def tearDown(self):
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -19,7 +19,7 @@ from .lib import openjp2 as opj2
|
||||||
|
|
||||||
# Do not change the format of this next line! Doing so risks breaking
|
# Do not change the format of this next line! Doing so risks breaking
|
||||||
# setup.py
|
# setup.py
|
||||||
version = "0.5.10"
|
version = "0.6.0"
|
||||||
_sv = LooseVersion(version)
|
_sv = LooseVersion(version)
|
||||||
version_tuple = _sv.version
|
version_tuple = _sv.version
|
||||||
|
|
||||||
|
|
|
||||||
1
setup.py
1
setup.py
|
|
@ -25,6 +25,7 @@ kwargs['install_requires'] = instllrqrs
|
||||||
clssfrs = ["Programming Language :: Python",
|
clssfrs = ["Programming Language :: Python",
|
||||||
"Programming Language :: Python :: 2.7",
|
"Programming Language :: Python :: 2.7",
|
||||||
"Programming Language :: Python :: 3.3",
|
"Programming Language :: Python :: 3.3",
|
||||||
|
"Programming Language :: Python :: 3.4",
|
||||||
"Programming Language :: Python :: Implementation :: CPython",
|
"Programming Language :: Python :: Implementation :: CPython",
|
||||||
"License :: OSI Approved :: MIT License",
|
"License :: OSI Approved :: MIT License",
|
||||||
"Development Status :: 5 - Production/Stable",
|
"Development Status :: 5 - Production/Stable",
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue