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:
|
||||
- "2.7"
|
||||
- "3.3"
|
||||
- "3.4"
|
||||
|
||||
before_install:
|
||||
- sudo apt-get update -qq
|
||||
|
|
@ -13,6 +14,7 @@ before_install:
|
|||
install:
|
||||
- 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.4' ]]; then pip install lxml numpy; fi
|
||||
|
||||
# command to run tests
|
||||
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.
|
||||
#
|
||||
# The short X.Y version.
|
||||
version = '0.5'
|
||||
version = '0.6'
|
||||
# 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
|
||||
# for a list of supported languages.
|
||||
|
|
|
|||
|
|
@ -1,34 +1,27 @@
|
|||
----------------------------------
|
||||
Advanced Installation Instructions
|
||||
----------------------------------
|
||||
Most users won't need to read this! You've been warned...
|
||||
|
||||
''''''''''''''''''''''
|
||||
Glymur Configuration
|
||||
''''''''''''''''''''''
|
||||
|
||||
The default glymur installation process relies upon OpenJPEG
|
||||
being properly installed on your system. If you have version 1.5 you can
|
||||
both read and write JPEG 2000 files, but you may wish to install version 2.0
|
||||
or the 2.0+ version from OpenJPEG's development trunk for better performance.
|
||||
If you do that, you should compile it as a shared library (named *openjp2*
|
||||
instead of *openjpeg*) from the developmental source that you can retrieve
|
||||
via subversion. As of this time of writing, svn revision 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. ::
|
||||
The default glymur installation process relies upon OpenJPEG being
|
||||
properly installed on your system as a shared library. If you have
|
||||
OpenJPEG installed through your system’s package manager on linux
|
||||
or if you use MacPorts on the mac, you are probably already set to
|
||||
go. But if you have OpenJPEG installed into a non-standard place
|
||||
or if you use windows, then read on.
|
||||
|
||||
$ svn co http://openjpeg.googlecode.com/svn/data
|
||||
$ export OPJ_DATA_ROOT=`pwd`/data
|
||||
|
||||
Glymur uses ctypes to access the openjp2/openjpeg libraries,
|
||||
and because ctypes accesses libraries in a platform-dependent manner, it is
|
||||
recommended that you create a configuration file to help Glymur properly find
|
||||
the openjpeg or openjp2 libraries (linux users don't need to bother with this
|
||||
if you are using OpenJPEG as provided by your package manager). The
|
||||
configuration format is the same as used by Python's configparser module,
|
||||
i.e. ::
|
||||
Glymur uses ctypes to access the openjp2/openjpeg libraries, and
|
||||
because ctypes accesses libraries in a platform-dependent manner,
|
||||
it is recommended that if you compile and install OpenJPEG into a
|
||||
non-standard location, you should then create a configuration file
|
||||
to help Glymur properly find the openjpeg or openjp2 libraries
|
||||
(linux users or macports users don’t need to bother with this if
|
||||
you are using OpenJPEG as provided by your package manager). The
|
||||
configuration format is the same as used by Python’s configparser
|
||||
module, i.e. ::
|
||||
|
||||
[library]
|
||||
openjp2: /opt/openjp2-svn/lib/libopenjp2.so
|
||||
|
|
@ -45,78 +38,30 @@ the path will be ::
|
|||
|
||||
$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
|
||||
installed in a non-standard place, i.e. ::
|
||||
|
||||
[library]
|
||||
openjpeg: /not/the/usual/location/lib/libopenjpeg.so
|
||||
|
||||
''''''''''''''''''''''''''''''
|
||||
Package Management Suggestions
|
||||
''''''''''''''''''''''''''''''
|
||||
|
||||
You only need to read this section if you want detailed
|
||||
platform-specific instructions on running as many tests as possible or wish to
|
||||
use your system's package manager to install as many required
|
||||
packages/RPMs/ports/whatever without going through pip.
|
||||
|
||||
|
||||
Mac OS X
|
||||
--------
|
||||
All the necessary packages are available to use glymur with 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
|
||||
'''''''
|
||||
|
||||
There are two environment variables you may wish to set before running the
|
||||
tests.
|
||||
It is not necessary, but you may wish to download OpenJPEG's test
|
||||
data for the purpose of configuring and running OpenJPEG's test
|
||||
suite. Check their instructions on how to do that. You can then
|
||||
set the **OPJ_DATA_ROOT** environment variable for the purpose of
|
||||
pointing Glymur to OpenJPEG's test suite. ::
|
||||
|
||||
* **OPJ_DATA_ROOT** - points to directory for OpenJPEG test data (see above)
|
||||
* **FORMAT_CORPUS_DATA_ROOT** - points to directory for format-corpus repository (see https://github.com/openplanets/format-corpus if you wish, but you really don't need to bother with this)
|
||||
|
||||
Setting these two environment variables is not required, as any tests using
|
||||
either of them will be skipped.
|
||||
$ svn co http://openjpeg.googlecode.com/svn/data
|
||||
$ export OPJ_DATA_ROOT=`pwd`/data
|
||||
|
||||
In order to run the tests, you can either run them from within
|
||||
python as follows ... ::
|
||||
|
|
@ -128,11 +73,3 @@ or from the command line. ::
|
|||
|
||||
$ cd /to/where/you/unpacked/glymur
|
||||
$ python -m unittest discover
|
||||
|
||||
Quite a few tests are currently skipped. These include tests whose
|
||||
OpenJPEG counterparts are already failing, and others which do pass but
|
||||
still produce heaps of output on stderr. Rather than let this swamp
|
||||
the signal (that most of those tests are actually passing), they've been
|
||||
filtered out for now. There are also more skipped tests on Python 2.7
|
||||
than on 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. ::
|
||||
|
||||
>>> import glymur
|
||||
>>> file = glymur.data.nemo()
|
||||
>>> jp2 = glymur.Jp2k(file)
|
||||
>>> jp2file = glymur.data.nemo()
|
||||
>>> jp2 = glymur.Jp2k(jp2file)
|
||||
>>> thumbnail = jp2.read(rlevel=-1)
|
||||
|
||||
... 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. ::
|
||||
|
||||
$ 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. ::
|
||||
|
||||
>>> import glymur
|
||||
>>> file = glymur.data.nemo()
|
||||
>>> jp2 = glymur.Jp2k(file)
|
||||
>>> jp2file = glymur.data.nemo()
|
||||
>>> jp2 = glymur.Jp2k(jp2file)
|
||||
>>> print(jp2)
|
||||
File: nemo.jp2
|
||||
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
|
||||
>>> glymur.set_printoptions(codestream=False)
|
||||
>>> jfile = glymur.data.goodstuff()
|
||||
>>> j2k = glymur.Jp2k(jfile)
|
||||
>>> jp2file = glymur.data.goodstuff()
|
||||
>>> j2k = glymur.Jp2k(jp2file)
|
||||
>>> jp2 = j2k.wrap("newfile.jp2")
|
||||
>>> print(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::
|
||||
|
||||
>>> import glymur
|
||||
>>> jfile = glymur.data.goodstuff()
|
||||
>>> j2k = glymur.Jp2k(jfile)
|
||||
>>> j2kfile = glymur.data.goodstuff()
|
||||
>>> j2k = glymur.Jp2k(j2kfile)
|
||||
>>> jp2 = j2k.wrap("goodstuff.jp2")
|
||||
|
||||
Now build up the metadata piece-by-piece. It would help to have the XMP
|
||||
|
|
|
|||
|
|
@ -15,9 +15,9 @@ Contents:
|
|||
introduction
|
||||
detailed_installation
|
||||
how_do_i
|
||||
roadmap
|
||||
changelog
|
||||
api
|
||||
whatsnew/index
|
||||
roadmap
|
||||
|
||||
------------------
|
||||
Indices and tables
|
||||
|
|
|
|||
|
|
@ -3,13 +3,13 @@ Glymur: a Python interface for JPEG 2000
|
|||
----------------------------------------
|
||||
|
||||
**Glymur** is an interface to the OpenJPEG library
|
||||
which allows one to read and write JPEG 2000 files from within Python.
|
||||
which allows one to read and write JPEG 2000 files from Python.
|
||||
Glymur supports both reading and writing of JPEG 2000 images, but writing
|
||||
JPEG 2000 images is currently limited to images that can fit in memory
|
||||
|
||||
In regards to metadata, most JP2 boxes are properly interpreted.
|
||||
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,
|
||||
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
|
||||
|
||||
* 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 ::
|
||||
|
||||
$ pip install glymur
|
||||
|
||||
This will install the **jp2dump** script that can be used from the unix command
|
||||
line, so you should adjust your **$PATH**
|
||||
to take advantage of it. For example, if you install with pip's
|
||||
`--user` option on linux ::
|
||||
This will install a script **jp2dump** that can be used from the unix command
|
||||
line for dumping JP2 metadata, so you should adjust your **$PATH**
|
||||
environment variable to take advantage of it. For example, if you install
|
||||
with pip's `--user` option on linux ::
|
||||
|
||||
$ 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
|
||||
-------
|
||||
|
|
|
|||
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
|
||||
endian = '>'
|
||||
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)
|
||||
|
||||
_, offset = struct.unpack(endian + 'HI', read_buffer[8:14])
|
||||
|
|
@ -99,8 +101,12 @@ class _Ifd(object):
|
|||
def parse_tag(self, dtype, count, offset_buf):
|
||||
"""Interpret an Exif image tag data payload.
|
||||
"""
|
||||
fmt = self.datatype2fmt[dtype][0] * count
|
||||
payload_size = self.datatype2fmt[dtype][1] * count
|
||||
try:
|
||||
fmt = self.datatype2fmt[dtype][0] * 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:
|
||||
# Interpret the payload from the 4 bytes in the tag entry.
|
||||
|
|
|
|||
|
|
@ -1241,8 +1241,10 @@ class FileTypeBox(Jp2kBox):
|
|||
def _validate(self, writing=False):
|
||||
"""Validate the box before writing to file."""
|
||||
if self.brand not in ['jp2 ', 'jpx ']:
|
||||
msg = "The file type brand must be either 'jp2 ' or 'jpx '."
|
||||
self._dispatch_validation_error(msg, writing=writing)
|
||||
msg = "The file type brand was '{0}'. "
|
||||
msg += "It should be either 'jp2 ' or 'jpx '."
|
||||
self._dispatch_validation_error(msg.format(self.brand),
|
||||
writing=writing)
|
||||
valid_cls = ['jp2 ', 'jpx ', 'jpxb']
|
||||
for item in self.compatibility_list:
|
||||
if item not in valid_cls:
|
||||
|
|
@ -2740,12 +2742,7 @@ class XMLBox(Jp2kBox):
|
|||
def write(self, fptr):
|
||||
"""Write an XML box to file.
|
||||
"""
|
||||
try:
|
||||
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')
|
||||
|
||||
read_buffer = ET.tostring(self.xml, encoding='utf-8')
|
||||
fptr.write(struct.pack('>I4s', len(read_buffer) + 8, b'xml '))
|
||||
fptr.write(read_buffer)
|
||||
|
||||
|
|
|
|||
|
|
@ -180,9 +180,9 @@ class Jp2k(Jp2kBox):
|
|||
if re.match("2.0", version.openjpeg_version) is not None:
|
||||
# 2.0 API
|
||||
if fps == 24:
|
||||
cparams.cp_cinema = core.OPJ_CINEMA_2K_24
|
||||
cparams.cp_cinema = core.OPJ_CINEMA2K_24
|
||||
else:
|
||||
cparams.cp_cinema = core.OPJ_CINEMA_2K_48
|
||||
cparams.cp_cinema = core.OPJ_CINEMA2K_48
|
||||
else:
|
||||
# 2.1 API
|
||||
if fps == 24:
|
||||
|
|
@ -198,7 +198,7 @@ class Jp2k(Jp2kBox):
|
|||
# cinema4k
|
||||
if re.match("2.0", version.openjpeg_version) is not None:
|
||||
# 2.0 API
|
||||
cparams.cp_cinema = core.OPJ_CINEMA_4K_24
|
||||
cparams.cp_cinema = core.OPJ_CINEMA4K_24
|
||||
else:
|
||||
# 2.1 API
|
||||
cparams.rsiz = core.OPJ_PROFILE_CINEMA_4K
|
||||
|
|
@ -271,6 +271,9 @@ class Jp2k(Jp2kBox):
|
|||
cparams.tcp_numlayers = 1
|
||||
cparams.cp_disto_alloc = 1
|
||||
|
||||
if 'irreversible' in kwargs and kwargs['irreversible'] is True:
|
||||
cparams.irreversible = 1
|
||||
|
||||
if 'cinema2k' in kwargs:
|
||||
self._set_cinema_params(cparams, 'cinema2k', kwargs['cinema2k'])
|
||||
return cparams
|
||||
|
|
@ -416,6 +419,8 @@ class Jp2k(Jp2kBox):
|
|||
If true, write SOP marker after each header packet.
|
||||
grid_offset : tuple, optional
|
||||
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
|
||||
Specifies usage of the multi component transform. If not
|
||||
specified, defaults to True if the colorspace is RGB.
|
||||
|
|
|
|||
|
|
@ -51,51 +51,6 @@ class TestCodestreamOpjData(unittest.TestCase):
|
|||
def tearDown(self):
|
||||
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.")
|
||||
def test_reserved_marker_segment(self):
|
||||
"""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].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):
|
||||
"""Psot=0 in SOT is perfectly legal. Issue #78."""
|
||||
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 tempfile
|
||||
import unittest
|
||||
import warnings
|
||||
|
||||
if sys.hexversion <= 0x03030000:
|
||||
from mock import patch
|
||||
|
|
@ -83,8 +84,11 @@ class TestSuite(unittest.TestCase):
|
|||
with patch.dict('os.environ', {'XDG_CONFIG_HOME': tdir}):
|
||||
# Misconfigured new configuration file should
|
||||
# be rejected.
|
||||
with self.assertWarns(UserWarning):
|
||||
with warnings.catch_warnings(record=True) as w:
|
||||
warnings.simplefilter('always')
|
||||
imp.reload(glymur.lib.openjp2)
|
||||
self.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
|
||||
|
|
|
|||
|
|
@ -62,16 +62,18 @@ class TestICC(unittest.TestCase):
|
|||
|
||||
self.assertEqual(profile['Creator'], 'JPEG')
|
||||
|
||||
@unittest.skipIf(sys.hexversion < 0x03020000,
|
||||
"Uses features introduced in 3.2.")
|
||||
@unittest.skipIf(sys.platform.startswith('linux'), 'Failing on linux')
|
||||
def test_invalid_profile_header(self):
|
||||
"""invalid ICC header data should cause UserWarning"""
|
||||
jfile = opj_data_file('input/nonregression/orb-blue10-lin-jp2.jp2')
|
||||
|
||||
# assertWarns in Python 3.3 (python2.7/pylint issue)
|
||||
# pylint: disable=E1101
|
||||
with self.assertWarns(UserWarning):
|
||||
with warnings.catch_warnings(record=True) as w:
|
||||
warnings.simplefilter('always')
|
||||
Jp2k(jfile)
|
||||
self.assertTrue(issubclass(w[0].category,UserWarning))
|
||||
self.assertTrue('ICC profile header is corrupt' in str(w[0].message))
|
||||
|
||||
if __name__ == "__main__":
|
||||
unittest.main()
|
||||
|
|
|
|||
|
|
@ -357,7 +357,6 @@ class TestChannelDefinition(unittest.TestCase):
|
|||
with self.assertRaises((IOError, OSError)):
|
||||
j2k.wrap(tfile.name, boxes=boxes)
|
||||
|
||||
@unittest.skipIf(sys.hexversion < 0x03000000, "Needs unittest in 3.x.")
|
||||
def test_bad_type(self):
|
||||
"""Channel types are limited to 0, 1, 2, 65535
|
||||
Should reject if not all of index, channel_type, association the
|
||||
|
|
@ -365,20 +364,26 @@ class TestChannelDefinition(unittest.TestCase):
|
|||
"""
|
||||
channel_type = (COLOR, COLOR, 3)
|
||||
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,
|
||||
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):
|
||||
"""Should reject if not all of index, channel_type, association the
|
||||
same length.
|
||||
"""
|
||||
channel_type = (COLOR, COLOR)
|
||||
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,
|
||||
association=association)
|
||||
self.assertEqual(len(w), 1)
|
||||
self.assertTrue(issubclass(w[0].category, UserWarning))
|
||||
|
||||
|
||||
class TestFileTypeBox(unittest.TestCase):
|
||||
|
|
@ -474,32 +479,41 @@ class TestColourSpecificationBox(unittest.TestCase):
|
|||
self.assertEqual(colr.colorspace, glymur.core.SRGB)
|
||||
self.assertIsNone(colr.icc_profile)
|
||||
|
||||
@unittest.skipIf(sys.hexversion < 0x03030000, "Requires 3.3+")
|
||||
def test_colr_with_cspace_and_icc(self):
|
||||
"""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
|
||||
rawb = b'\x01\x02\x03\x04'
|
||||
glymur.jp2box.ColourSpecificationBox(colorspace=colorspace,
|
||||
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):
|
||||
"""colr must have a valid method field"""
|
||||
colorspace = glymur.core.SRGB
|
||||
method = -1
|
||||
with self.assertWarns(UserWarning):
|
||||
with warnings.catch_warnings(record=True) as w:
|
||||
warnings.simplefilter('always')
|
||||
glymur.jp2box.ColourSpecificationBox(colorspace=colorspace,
|
||||
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):
|
||||
"""colr should have a valid approximation field"""
|
||||
colorspace = glymur.core.SRGB
|
||||
approx = -1
|
||||
with self.assertWarns(UserWarning):
|
||||
with warnings.catch_warnings(record=True) as w:
|
||||
warnings.simplefilter('always')
|
||||
glymur.jp2box.ColourSpecificationBox(colorspace=colorspace,
|
||||
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):
|
||||
"""colr must have a valid color, strange as though that may sound."""
|
||||
|
|
@ -523,25 +537,29 @@ class TestPaletteBox(unittest.TestCase):
|
|||
def tearDown(self):
|
||||
pass
|
||||
|
||||
@unittest.skipIf(sys.hexversion < 0x03000000, "Needs unittest in 3.x.")
|
||||
def test_mismatched_bitdepth_signed(self):
|
||||
"""bitdepth and signed arguments must have equal length"""
|
||||
palette = np.array([[255, 0, 255], [0, 255, 0]], dtype=np.uint8)
|
||||
bps = (8, 8, 8)
|
||||
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,
|
||||
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):
|
||||
"""bitdepth and signed arguments must have equal length"""
|
||||
palette = np.array([[255, 0, 255], [0, 255, 0]], dtype=np.uint8)
|
||||
bps = (8, 8, 8, 8)
|
||||
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,
|
||||
signed=signed)
|
||||
self.assertEqual(len(w), 1)
|
||||
self.assertTrue(issubclass(w[0].category, UserWarning))
|
||||
|
||||
def test_writing_with_different_bitdepths(self):
|
||||
"""Bitdepths must be the same when writing."""
|
||||
|
|
@ -554,6 +572,8 @@ class TestPaletteBox(unittest.TestCase):
|
|||
with self.assertRaises(IOError):
|
||||
pclr.write(tfile)
|
||||
|
||||
|
||||
@unittest.skipIf(os.name == "nt", "Temporary file issue on window.")
|
||||
class TestAppend(unittest.TestCase):
|
||||
"""Tests for append method."""
|
||||
|
||||
|
|
@ -1274,8 +1294,8 @@ class TestRepr(unittest.TestCase):
|
|||
box = glymur.jp2box.XMLBox(xml=tree)
|
||||
|
||||
regexp = r"""glymur.jp2box.XMLBox"""
|
||||
regexp += r"""\(xml=<lxml.etree._ElementTree object """
|
||||
regexp += """at 0x([a-f0-9]*)>\)"""
|
||||
regexp += r"""[(]xml=<lxml.etree._ElementTree\sobject\s"""
|
||||
regexp += """at\s0x([a-fA-F0-9]*)>[)]"""
|
||||
|
||||
if sys.hexversion < 0x03000000:
|
||||
self.assertRegexpMatches(repr(box), regexp)
|
||||
|
|
@ -1314,7 +1334,6 @@ class TestRepr(unittest.TestCase):
|
|||
else:
|
||||
self.assertRegex(repr(box), regexp)
|
||||
|
||||
@unittest.skipIf(sys.hexversion < 0x02070000, "Requires 2.7+")
|
||||
def test_uuid_box_xmp(self):
|
||||
"""Verify uuid repr method for XMP UUID box."""
|
||||
jp2file = glymur.data.nemo()
|
||||
|
|
@ -1340,8 +1359,8 @@ class TestRepr(unittest.TestCase):
|
|||
|
||||
# Difficult to eval(repr()) this, so just match the general pattern.
|
||||
regexp = "glymur.jp2box.ContiguousCodeStreamBox"
|
||||
regexp += "\(main_header=<glymur.codestream.Codestream\sobject\s"
|
||||
regexp += "at\s0x([a-f0-9]*)>\)"
|
||||
regexp += "[(]main_header=<glymur.codestream.Codestream\sobject\s"
|
||||
regexp += "at\s0x([a-fA-F0-9]*)>[)]"
|
||||
|
||||
if sys.hexversion < 0x03000000:
|
||||
self.assertRegexpMatches(repr(box), regexp)
|
||||
|
|
|
|||
|
|
@ -305,15 +305,17 @@ class TestJPXWrap(unittest.TestCase):
|
|||
with self.assertRaises(IOError):
|
||||
jp2.wrap(tfile.name, boxes=boxes)
|
||||
|
||||
@unittest.skipIf(sys.hexversion < 0x03000000, "Needs unittest in 3.x.")
|
||||
def test_deurl_child_of_dtbl(self):
|
||||
"""Data reference boxes can only contain data entry url boxes."""
|
||||
jp2 = Jp2k(self.jp2file)
|
||||
boxes = [jp2.box[idx] for idx in [0, 1, 2, 4]]
|
||||
|
||||
ftyp = glymur.jp2box.FileTypeBox()
|
||||
with self.assertWarns(UserWarning):
|
||||
with warnings.catch_warnings(record=True) as w:
|
||||
warnings.simplefilter('always')
|
||||
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.
|
||||
dref = glymur.jp2box.DataReferenceBox()
|
||||
|
|
@ -484,25 +486,6 @@ class TestJPX(unittest.TestCase):
|
|||
with tempfile.TemporaryFile() as 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):
|
||||
"""The existance of a data reference box requires a ftbl box as well."""
|
||||
flag = 0
|
||||
|
|
|
|||
|
|
@ -45,6 +45,7 @@ from glymur import Jp2k
|
|||
from .fixtures import OPJ_DATA_ROOT, opj_data_file, SimpleRDF
|
||||
|
||||
|
||||
@unittest.skipIf(os.name == "nt", "Unexplained failure on windows")
|
||||
class TestUUIDXMP(unittest.TestCase):
|
||||
"""Tests for UUIDs of XMP type."""
|
||||
|
||||
|
|
@ -74,6 +75,7 @@ class TestUUIDXMP(unittest.TestCase):
|
|||
self.assertTrue(isinstance(jp2.box[-1].data,
|
||||
lxml.etree._ElementTree))
|
||||
|
||||
@unittest.skipIf(os.name == "nt", "Unexplained failure on windows")
|
||||
class TestUUIDExif(unittest.TestCase):
|
||||
"""Tests for UUIDs of Exif type."""
|
||||
|
||||
|
|
@ -83,7 +85,6 @@ class TestUUIDExif(unittest.TestCase):
|
|||
def tearDown(self):
|
||||
pass
|
||||
|
||||
@unittest.skipIf(sys.hexversion < 0x03000000, "Requires assertWarns, 3.2+")
|
||||
def test_unrecognized_exif_tag(self):
|
||||
"""Verify warning in case of unrecognized tag."""
|
||||
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.flush()
|
||||
|
||||
with self.assertWarns(UserWarning):
|
||||
with warnings.catch_warnings(record=True) as w:
|
||||
warnings.simplefilter('always')
|
||||
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):
|
||||
"""Only certain datatypes are allowable"""
|
||||
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.flush()
|
||||
|
||||
with self.assertWarns(UserWarning):
|
||||
with warnings.catch_warnings(record=True) as w:
|
||||
warnings.simplefilter('always')
|
||||
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')
|
||||
|
||||
@unittest.skipIf(sys.hexversion < 0x03000000, "Requires assertWarns, 3.2+")
|
||||
def test_bad_tiff_header_byte_order_indication(self):
|
||||
"""Only b'II' and b'MM' are allowed."""
|
||||
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.flush()
|
||||
|
||||
with self.assertWarns(UserWarning):
|
||||
with warnings.catch_warnings(record=True) as w:
|
||||
warnings.simplefilter('always')
|
||||
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')
|
||||
|
||||
|
|
|
|||
|
|
@ -207,18 +207,14 @@ class TestJp2kBadXmlFile(unittest.TestCase):
|
|||
def tearDown(self):
|
||||
pass
|
||||
|
||||
@unittest.skipIf(sys.hexversion < 0x03020000,
|
||||
"Uses features introduced in 3.2.")
|
||||
def test_invalid_xml_box_warning(self):
|
||||
"""Should warn in case of bad XML"""
|
||||
with self.assertWarns(UserWarning):
|
||||
Jp2k(self._bad_xml_file)
|
||||
|
||||
def test_invalid_xml_box(self):
|
||||
"""Should be able to recover info from xml box with bad xml."""
|
||||
with warnings.catch_warnings():
|
||||
warnings.simplefilter("ignore")
|
||||
with warnings.catch_warnings(record=True) as w:
|
||||
warnings.simplefilter("always")
|
||||
jp2k = Jp2k(self._bad_xml_file)
|
||||
self.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].offset, 77)
|
||||
|
|
@ -267,12 +263,14 @@ class TestBadButRecoverableXmlFile(unittest.TestCase):
|
|||
def tearDownClass(cls):
|
||||
os.unlink(cls._bad_xml_file)
|
||||
|
||||
@unittest.skipIf(sys.hexversion < 0x03020000,
|
||||
"Uses features introduced in 3.2.")
|
||||
def test_bad_xml_box_warning(self):
|
||||
"""Should warn in case of bad XML"""
|
||||
with self.assertWarns(UserWarning):
|
||||
with warnings.catch_warnings(record=True) as w:
|
||||
warnings.simplefilter('always')
|
||||
Jp2k(self._bad_xml_file)
|
||||
self.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):
|
||||
"""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):
|
||||
"""Test suite for XML boxes, requires OPJ_DATA_ROOT."""
|
||||
|
||||
@unittest.skipIf(sys.platform.startswith('linux'), 'Failing on linux')
|
||||
def test_bom(self):
|
||||
"""Byte order markers are illegal in UTF-8. Issue 185"""
|
||||
filename = opj_data_file(os.path.join('input',
|
||||
'nonregression',
|
||||
'issue171.jp2'))
|
||||
if sys.hexversion < 0x03000000:
|
||||
with warnings.catch_warnings():
|
||||
warnings.simplefilter("ignore")
|
||||
jp2 = Jp2k(filename)
|
||||
else:
|
||||
with self.assertWarns(UserWarning):
|
||||
jp2 = Jp2k(filename)
|
||||
with warnings.catch_warnings(record=True) as w:
|
||||
warnings.simplefilter("always")
|
||||
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)
|
||||
|
||||
|
||||
|
|
@ -312,13 +311,10 @@ class TestXML_OpjDataRoot(unittest.TestCase):
|
|||
filename = opj_data_file(os.path.join('input',
|
||||
'nonregression',
|
||||
'26ccf3651020967f7778238ef5af08af.SIGFPE.d25.527.jp2'))
|
||||
if sys.hexversion < 0x03000000:
|
||||
with warnings.catch_warnings():
|
||||
warnings.simplefilter("ignore")
|
||||
jp2 = Jp2k(filename)
|
||||
else:
|
||||
with self.assertWarns(UserWarning):
|
||||
jp2 = Jp2k(filename)
|
||||
with warnings.catch_warnings(record=True) as w:
|
||||
warnings.simplefilter("always")
|
||||
jp2 = Jp2k(filename)
|
||||
self.assertTrue(issubclass(w[0].category, UserWarning))
|
||||
|
||||
self.assertIsNone(jp2.box[3].box[1].box[1].xml)
|
||||
|
||||
|
|
|
|||
|
|
@ -63,6 +63,25 @@ class TestJp2k(unittest.TestCase):
|
|||
def tearDown(self):
|
||||
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):
|
||||
"""Indices for pclr jpxfile if no color transform"""
|
||||
j = Jp2k(self.jpxfile)
|
||||
|
|
@ -81,6 +100,7 @@ class TestJp2k(unittest.TestCase):
|
|||
rgb_from_idx[r, c] = palette[idx[r, c]]
|
||||
np.testing.assert_array_equal(rgb, rgb_from_idx)
|
||||
|
||||
@unittest.skipIf(os.name == "nt", "Unexplained failure on windows")
|
||||
def test_repr(self):
|
||||
"""Verify that results of __repr__ are eval-able."""
|
||||
j = Jp2k(self.j2kfile)
|
||||
|
|
@ -390,6 +410,7 @@ class TestJp2k(unittest.TestCase):
|
|||
self.assertEqual(data.shape, (1024, 1024, 3))
|
||||
|
||||
|
||||
@unittest.skipIf(os.name == "nt", "NamedTemporaryFile issue on windows")
|
||||
class TestJp2k_write(unittest.TestCase):
|
||||
"""Write tests, can be run by versions 1.5+"""
|
||||
|
||||
|
|
@ -400,8 +421,6 @@ class TestJp2k_write(unittest.TestCase):
|
|||
def tearDown(self):
|
||||
pass
|
||||
|
||||
|
||||
@unittest.skipIf(os.name == "nt", "NamedTemporaryFile issue on windows")
|
||||
def test_cblkh_different_than_width(self):
|
||||
"""Verify that we can set a code block size where height does not equal
|
||||
width.
|
||||
|
|
@ -418,7 +437,6 @@ class TestJp2k_write(unittest.TestCase):
|
|||
# Code block size is reported as XY in the codestream.
|
||||
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):
|
||||
"""OpenJP2 only allows 2D or 3D images."""
|
||||
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)
|
||||
j.write(data)
|
||||
|
||||
@unittest.skipIf(os.name == "nt", "NamedTemporaryFile issue on windows")
|
||||
def test_2d_rgb(self):
|
||||
"""RGB must have at least 3 components."""
|
||||
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)
|
||||
j.write(data, colorspace='rgb')
|
||||
|
||||
@unittest.skipIf(os.name == "nt", "NamedTemporaryFile issue on windows")
|
||||
def test_colorspace_with_j2k(self):
|
||||
"""Specifying a colorspace with J2K does not make sense"""
|
||||
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)
|
||||
j.write(data, colorspace='rgb')
|
||||
|
||||
@unittest.skipIf(os.name == "nt", "NamedTemporaryFile issue on windows")
|
||||
def test_specify_rgb(self):
|
||||
"""specify RGB explicitly"""
|
||||
with tempfile.NamedTemporaryFile(suffix='.jp2') as tfile:
|
||||
|
|
@ -454,7 +469,6 @@ class TestJp2k_write(unittest.TestCase):
|
|||
j.write(data, colorspace='rgb')
|
||||
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):
|
||||
"""test gray explicitly specified (that's GRAY, not GREY)"""
|
||||
with tempfile.NamedTemporaryFile(suffix='.jp2') as tfile:
|
||||
|
|
@ -464,7 +478,6 @@ class TestJp2k_write(unittest.TestCase):
|
|||
self.assertEqual(j.box[2].box[1].colorspace,
|
||||
glymur.core.GREYSCALE)
|
||||
|
||||
@unittest.skipIf(os.name == "nt", "NamedTemporaryFile issue on windows")
|
||||
def test_specify_grey(self):
|
||||
"""test grey explicitly specified"""
|
||||
with tempfile.NamedTemporaryFile(suffix='.jp2') as tfile:
|
||||
|
|
@ -474,7 +487,6 @@ class TestJp2k_write(unittest.TestCase):
|
|||
self.assertEqual(j.box[2].box[1].colorspace,
|
||||
glymur.core.GREYSCALE)
|
||||
|
||||
@unittest.skipIf(os.name == "nt", "NamedTemporaryFile issue on windows")
|
||||
def test_grey_with_two_extra_comps(self):
|
||||
"""should be able to write gray + two extra components"""
|
||||
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)
|
||||
j.write(data, colorspace='ycc')
|
||||
|
||||
@unittest.skipIf(os.name == "nt", "NamedTemporaryFile issue on windows")
|
||||
def test_write_with_jp2_in_caps(self):
|
||||
"""should be able to write with JP2 suffix."""
|
||||
j2k = Jp2k(self.j2kfile)
|
||||
|
|
@ -506,7 +517,6 @@ class TestJp2k_write(unittest.TestCase):
|
|||
actdata = ofile.read()
|
||||
np.testing.assert_array_equal(actdata, expdata)
|
||||
|
||||
@unittest.skipIf(os.name == "nt", "NamedTemporaryFile issue on windows")
|
||||
def test_write_srgb_without_mct(self):
|
||||
"""should be able to write RGB without specifying mct"""
|
||||
j2k = Jp2k(self.j2kfile)
|
||||
|
|
@ -520,7 +530,6 @@ class TestJp2k_write(unittest.TestCase):
|
|||
codestream = ofile.get_codestream()
|
||||
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):
|
||||
"""MCT usage makes no sense for grayscale images."""
|
||||
j2k = Jp2k(self.j2kfile)
|
||||
|
|
@ -530,7 +539,6 @@ class TestJp2k_write(unittest.TestCase):
|
|||
with self.assertRaises(IOError):
|
||||
ofile.write(expdata[:, :, 0], mct=True)
|
||||
|
||||
@unittest.skipIf(os.name == "nt", "NamedTemporaryFile issue on windows")
|
||||
def test_write_cprl(self):
|
||||
"""Must be able to write a CPRL progression order file"""
|
||||
# Issue 17
|
||||
|
|
@ -757,7 +765,7 @@ class TestJp2k_2_1(unittest.TestCase):
|
|||
@unittest.skipIf(OPJ_DATA_ROOT is None,
|
||||
"OPJ_DATA_ROOT environment variable not set")
|
||||
class TestParsing(unittest.TestCase):
|
||||
"""Tests for verifying how paring may be altered."""
|
||||
"""Tests for verifying how parsing may be altered."""
|
||||
def setUp(self):
|
||||
self.jp2file = glymur.data.nemo()
|
||||
# Reset parseoptions for every test.
|
||||
|
|
@ -766,6 +774,7 @@ class TestParsing(unittest.TestCase):
|
|||
def tearDown(self):
|
||||
pass
|
||||
|
||||
@unittest.skipIf(sys.platform.startswith('linux'), 'Failing on linux')
|
||||
def test_bad_rsiz(self):
|
||||
"""Should not warn if RSIZ when parsing is turned off."""
|
||||
# Actually there are three warning triggered by this codestream.
|
||||
|
|
@ -776,11 +785,11 @@ class TestParsing(unittest.TestCase):
|
|||
self.assertEqual(len(w), 0)
|
||||
|
||||
glymur.set_parseoptions(codestream=True)
|
||||
if sys.hexversion >= 0x03000000:
|
||||
with self.assertWarns(UserWarning):
|
||||
jp2 = Jp2k(filename)
|
||||
with warnings.catch_warnings(record=True) as w:
|
||||
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):
|
||||
"""Verify that the main header is not loaded when parsing turned off."""
|
||||
# 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,
|
||||
"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."""
|
||||
|
||||
def test_undecodeable_box_id(self):
|
||||
"""Should warn in case of undecodeable box ID but not error out."""
|
||||
filename = opj_data_file('input/nonregression/edf_c2_1013627.jp2')
|
||||
if sys.hexversion < 0x03000000:
|
||||
with warnings.catch_warnings():
|
||||
warnings.simplefilter("ignore")
|
||||
jp2 = Jp2k(filename)
|
||||
else:
|
||||
with self.assertWarns(UserWarning):
|
||||
jp2 = Jp2k(filename)
|
||||
with warnings.catch_warnings(record=True) as w:
|
||||
warnings.simplefilter('always')
|
||||
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
|
||||
# bad.
|
||||
box_ids = [box.box_id for box in jp2.box[:-1]]
|
||||
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."""
|
||||
filename = opj_data_file('input/nonregression/edf_c2_1000290.jp2')
|
||||
with self.assertWarns(UserWarning):
|
||||
jp2 = Jp2k(filename)
|
||||
with warnings.catch_warnings(record=True) as w:
|
||||
warnings.simplefilter('always')
|
||||
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):
|
||||
"""Should warn in case of invalid approximation."""
|
||||
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)
|
||||
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):
|
||||
"""Should warn in case of invalid colorspace."""
|
||||
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)
|
||||
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):
|
||||
"""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]]
|
||||
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):
|
||||
"""should error out with read used on differently subsampled images"""
|
||||
# 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 tempfile
|
||||
import unittest
|
||||
import warnings
|
||||
|
||||
import numpy as np
|
||||
|
||||
|
|
@ -77,14 +78,13 @@ class TestSuiteNegative(unittest.TestCase):
|
|||
jp2k.get_codestream(header_only=False)
|
||||
self.assertTrue(True)
|
||||
|
||||
@unittest.skipIf(sys.hexversion < 0x03020000,
|
||||
"Uses features introduced in 3.2.")
|
||||
def test_nr_illegalclrtransform(self):
|
||||
"""EOC marker is bad"""
|
||||
relpath = 'input/nonregression/illegalcolortransform.j2k'
|
||||
jfile = opj_data_file(relpath)
|
||||
jp2k = Jp2k(jfile)
|
||||
with self.assertWarns(UserWarning):
|
||||
with warnings.catch_warnings(record=True) as w:
|
||||
warnings.simplefilter('ignore')
|
||||
codestream = jp2k.get_codestream(header_only=False)
|
||||
|
||||
# Verify that the last segment returned in the codestream is SOD,
|
||||
|
|
@ -119,8 +119,6 @@ class TestSuiteNegative(unittest.TestCase):
|
|||
with self.assertRaises(IOError):
|
||||
j.write(data, cbsize=(2, 2048))
|
||||
|
||||
@unittest.skipIf(sys.hexversion < 0x03020000,
|
||||
"Uses features introduced in 3.2.")
|
||||
def test_exceeded_box(self):
|
||||
"""should warn if reading past end of a box"""
|
||||
# Verify that a warning is issued if we read past the end of a box
|
||||
|
|
@ -128,7 +126,8 @@ class TestSuiteNegative(unittest.TestCase):
|
|||
# short.
|
||||
infile = os.path.join(OPJ_DATA_ROOT,
|
||||
'input/nonregression/mem-b2ace68c-1381.jp2')
|
||||
with self.assertWarns(UserWarning):
|
||||
with warnings.catch_warnings(record=True) as w:
|
||||
warnings.simplefilter('ignore')
|
||||
Jp2k(infile)
|
||||
|
||||
@unittest.skipIf(os.name == "nt", "Temporary file issue on window.")
|
||||
|
|
|
|||
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 warnings
|
||||
|
||||
import numpy as np
|
||||
|
||||
try:
|
||||
import skimage.io
|
||||
skimage.io.use_plugin('freeimage', 'imread')
|
||||
|
|
@ -271,6 +273,19 @@ class TestSuiteWrite(unittest.TestCase):
|
|||
def tearDown(self):
|
||||
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):
|
||||
"""NR-ENC-Bretagne1.ppm-1-encode"""
|
||||
infile = opj_data_file('input/nonregression/Bretagne1.ppm')
|
||||
|
|
@ -1020,7 +1035,6 @@ class TestSuiteWrite(unittest.TestCase):
|
|||
glymur.core.WAVELET_XFORM_5X3_REVERSIBLE)
|
||||
self.assertEqual(len(codestream.segment[2].spcod), 9)
|
||||
|
||||
#@unittest.skip("Known failure in openjpeg test suite.")
|
||||
def test_NR_ENC_random_issue_0005_tif_12_encode(self):
|
||||
"""NR-ENC-random-issue-0005.tif-12-encode"""
|
||||
# opj_decompress has trouble reading it, but that is not an issue here.
|
||||
|
|
|
|||
|
|
@ -70,7 +70,6 @@ class TestPrinting(unittest.TestCase):
|
|||
|
||||
self.assertTrue(True)
|
||||
|
||||
@unittest.skipIf(sys.hexversion < 0x03000000, "Needs unittest in 3.x.")
|
||||
def test_unknown_superbox(self):
|
||||
"""Verify that we can handle an unknown superbox."""
|
||||
with tempfile.NamedTemporaryFile(suffix='.jpx') as tfile:
|
||||
|
|
@ -87,14 +86,19 @@ class TestPrinting(unittest.TestCase):
|
|||
tfile.write(write_buffer)
|
||||
tfile.flush()
|
||||
|
||||
with self.assertWarns(UserWarning):
|
||||
with warnings.catch_warnings(record=True) as w:
|
||||
warnings.simplefilter('always')
|
||||
jpx = Jp2k(tfile.name)
|
||||
self.assertTrue(len(w), 1)
|
||||
|
||||
glymur.set_printoptions(short=True)
|
||||
with patch('sys.stdout', new=StringIO()) as fake_out:
|
||||
print(jpx.box[-1])
|
||||
actual = fake_out.getvalue().strip()
|
||||
lines = ["Unknown Box (b'grp ') @ (1399071, 20)"]
|
||||
expected = '\n'.join(lines)
|
||||
if sys.hexversion < 0x03000000:
|
||||
expected = "Unknown Box (grp ) @ (1399071, 20)"
|
||||
else:
|
||||
expected = "Unknown Box (b'grp ') @ (1399071, 20)"
|
||||
self.assertEqual(actual, expected)
|
||||
|
||||
def test_printoptions_bad_argument(self):
|
||||
|
|
@ -721,6 +725,8 @@ class TestPrintingOpjDataRoot(unittest.TestCase):
|
|||
# Reset printoptions for every test.
|
||||
glymur.set_printoptions(short=False, xml=True, codestream=True)
|
||||
|
||||
warnings.resetwarnings()
|
||||
|
||||
def tearDown(self):
|
||||
pass
|
||||
|
||||
|
|
@ -767,7 +773,7 @@ class TestPrintingOpjDataRoot(unittest.TestCase):
|
|||
with warnings.catch_warnings():
|
||||
warnings.simplefilter("ignore")
|
||||
jp2 = Jp2k(jfile)
|
||||
codestream = jp2.get_codestream()
|
||||
codestream = jp2.get_codestream()
|
||||
with patch('sys.stdout', new=StringIO()) as fake_out:
|
||||
print(codestream.segment[2])
|
||||
actual = fake_out.getvalue().strip()
|
||||
|
|
|
|||
|
|
@ -19,7 +19,7 @@ from .lib import openjp2 as opj2
|
|||
|
||||
# Do not change the format of this next line! Doing so risks breaking
|
||||
# setup.py
|
||||
version = "0.5.10"
|
||||
version = "0.6.0"
|
||||
_sv = LooseVersion(version)
|
||||
version_tuple = _sv.version
|
||||
|
||||
|
|
|
|||
1
setup.py
1
setup.py
|
|
@ -25,6 +25,7 @@ kwargs['install_requires'] = instllrqrs
|
|||
clssfrs = ["Programming Language :: Python",
|
||||
"Programming Language :: Python :: 2.7",
|
||||
"Programming Language :: Python :: 3.3",
|
||||
"Programming Language :: Python :: 3.4",
|
||||
"Programming Language :: Python :: Implementation :: CPython",
|
||||
"License :: OSI Approved :: MIT License",
|
||||
"Development Status :: 5 - Production/Stable",
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue