Merge branch 'devel'
This commit is contained in:
commit
2ed2ae7f12
24 changed files with 1245 additions and 568 deletions
23
CHANGES.txt
23
CHANGES.txt
|
|
@ -1,5 +1,20 @@
|
|||
May 27, 2013 - v0.1.1, Changed write example to not rely on matplotlib. Fixed
|
||||
readthedocs.org setup to build documentation automatically. Can import
|
||||
glymur without libopenjp2 actually being present.
|
||||
Jun 06, 2013 - v0.1.6 Exif classes made private. Refactored IFD post
|
||||
processing. Corrected omission of Exif in UUIDBox docstring.
|
||||
|
||||
May 27, 2013 - Changed write example to not rely on matplotlib.
|
||||
Jun 06, 2013 - v0.1.5 Changed ColourSpecificationBox attribute "color_space"
|
||||
to "colorspace". Fixed MANIFEST issue affecting PyPI installs.
|
||||
|
||||
Jun 05, 2013 - v0.1.4 Added Exif UUID read support.
|
||||
|
||||
Jun 02, 2013 - v0.1.3p1 Raising IOErrors when code block size and precinct
|
||||
sizes are not in harmony. Added statement to docs about upstream library
|
||||
dependence. Added roadmap to docs.
|
||||
|
||||
May 30, 2013 - v0.1.2. Added XMP UUID read support. Added jp2 boxes to rst
|
||||
docs, XMLBox.indent method made into a private module method. Precinct
|
||||
sizes restricted to be multiples of two.
|
||||
|
||||
May 27, 2013 - v0.1.1. Changed write example to not rely on matplotlib. Fixed
|
||||
readthedocs.org setup to build documentation automatically. Can import
|
||||
glymur without libopenjp2 actually being present. Changed write example
|
||||
to not rely on matplotlib.
|
||||
|
|
|
|||
21
LICENSE.txt
Normal file
21
LICENSE.txt
Normal file
|
|
@ -0,0 +1,21 @@
|
|||
The MIT License (MIT)
|
||||
|
||||
Copyright (c) 2013 John Evans
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
14
MANIFEST
14
MANIFEST
|
|
@ -1,14 +0,0 @@
|
|||
# file GENERATED by distutils, do NOT edit
|
||||
README
|
||||
setup.py
|
||||
jptools/__init__.py
|
||||
jptools/codestream.py
|
||||
jptools/core.py
|
||||
jptools/jp2box.py
|
||||
jptools/jp2k.py
|
||||
jptools/data/emneck.jp2
|
||||
jptools/test/__init__.py
|
||||
jptools/test/test_codestream.py
|
||||
jptools/test/test_conformance.py
|
||||
jptools/test/test_jp2k.py
|
||||
jptools/test/test_printing.py
|
||||
4
MANIFEST.in
Normal file
4
MANIFEST.in
Normal file
|
|
@ -0,0 +1,4 @@
|
|||
include *.txt *.md
|
||||
recursive-include *.txt *.py
|
||||
prune build
|
||||
exclude readthedocs-pip-requirements.txt
|
||||
187
README
187
README
|
|
@ -1,187 +0,0 @@
|
|||
=========================================
|
||||
glymur: a Python interface for JPEG 2000
|
||||
=========================================
|
||||
|
||||
**glymur** contains a Python interface to the OpenJPEG library
|
||||
which allows linux and mac users to read and write JPEG 2000 files. For more
|
||||
information about OpenJPEG, please consult http://www.openjpeg.org. **glymur**
|
||||
should be considered to be alpha-quality software.
|
||||
|
||||
**glymur** tries to support reading (including all metadata) and writing of
|
||||
JP2 and J2C files. Writing J2C/JP2 files is currently limited to images that
|
||||
can fit in memory, however.
|
||||
|
||||
There is some very limited support for reading JPX
|
||||
metadata. For instance, **asoc** and **labl** boxes are recognized, so GMLJP2
|
||||
metadata can be retrieved from such JPX files.
|
||||
|
||||
------------
|
||||
Requirements
|
||||
------------
|
||||
**glymur** works on Python 2.7 and 3.3. Python 3.3 is strongly recommended.
|
||||
|
||||
OpenJPEG
|
||||
========
|
||||
OpenJPEG must be built as a shared library. In addition, you
|
||||
currently must compile OpenJPEG from the developmental source that
|
||||
you can retrieve via subversion. As of this time of writing, svn
|
||||
revision 2345 works. In addition, you should also retrieve their test data, as
|
||||
you will need it when running **glymur**'s test suite.
|
||||
|
||||
Earlier versions of OpenJPEG through the 2.0 official release are not supported.
|
||||
|
||||
Be sure to have the following ports/RPMs/debs installed.
|
||||
|
||||
* gcc
|
||||
* gcc-c++
|
||||
* cmake
|
||||
|
||||
You should build OpenJPEG with testing turned on. Consult the OpenJPEG
|
||||
documentation on how to do this. If you use linux, make sure that you
|
||||
have the following development packages installed
|
||||
|
||||
* zlib-devel
|
||||
* png-devel
|
||||
* libtiff-devel
|
||||
* lcms2-devel
|
||||
|
||||
OS
|
||||
==
|
||||
|
||||
Mac OS X
|
||||
--------
|
||||
All the necessary packages are available to use **glymur** with Python 3.3 via
|
||||
MacPorts. A minimal set of ports includes
|
||||
|
||||
* python33
|
||||
* py33-numpy
|
||||
* py33-distribute
|
||||
|
||||
To run all the testing, one of the following combinations of ports must
|
||||
additionally be installed:
|
||||
|
||||
* py33-scikit-image and either py33-Pillow or freeimage
|
||||
* py33-matplotlib and py33-Pillow
|
||||
|
||||
Linux
|
||||
-----
|
||||
|
||||
Fedora 18
|
||||
'''''''''
|
||||
Fedora 18 ships with Python 3.3, so all the necessary RPMs are available to
|
||||
meet the minimal set of requirements.
|
||||
|
||||
* python3
|
||||
* python3-numpy
|
||||
* python3-setuptools
|
||||
* python3-matplotlib (for running tests)
|
||||
* python3-matplotlib-tk (or whichever matplotlib backend you prefer)
|
||||
|
||||
A few tests still will not run, however, unless one of the following
|
||||
combinations of RPMs / Python packages is installed.
|
||||
|
||||
* scikit-image and either Pillow or freeimage
|
||||
* matplotlib and Pillow
|
||||
|
||||
The 2nd route is probably the easiest, so go ahead and install **Pillow**
|
||||
via **pip** since **Pillow** is not yet available in Fedora 18 default
|
||||
repositories::
|
||||
|
||||
$ yum install python3-devel # pip needs this in order to compile Pillow
|
||||
$ yum install python3-pip # First one must install pip of course!
|
||||
$ pip-python3 install Pillow --user
|
||||
$ export PYTHONPATH=$HOME/.local/lib/python3.3/site-packages:$PYTHONPATH
|
||||
|
||||
Fedora 17
|
||||
'''''''''
|
||||
Fedora 17 ships with Python 3.2 and 2.7, so these steps detail working with
|
||||
2.7.
|
||||
|
||||
Required RPMs include::
|
||||
|
||||
* python
|
||||
* python-mock
|
||||
* python-pip
|
||||
* python-setuptools
|
||||
* numpy
|
||||
|
||||
In addition, you must install **contextlib2** via pip.
|
||||
|
||||
A few tests still will not run, however, unless one of the following
|
||||
combinations of RPMs / Python packages is installed.
|
||||
|
||||
* scikit-image and either Pillow or freeimage
|
||||
* matplotlib and Pillow
|
||||
|
||||
**scikit-image** is not available in the Fedora 17 default repositories, but
|
||||
it may be installed via **pip**::
|
||||
|
||||
$ yum install Cython # pip needs this in order to compile scikit-image
|
||||
$ yum install python-devel # pip needs this in order to compile scikit-image
|
||||
$ yum install freeimage # scikit-image uses this as a backend
|
||||
$ yum install scipy # needed by scikit-image
|
||||
$ pip-python install scikit-image --user
|
||||
$ pip-python install contextlib2 --user
|
||||
$ export PYTHONPATH=$HOME/.local/lib/python2.7/site-packages:$PYTHONPATH
|
||||
|
||||
Windows
|
||||
-------
|
||||
Not currently supported.
|
||||
|
||||
------------------------------------
|
||||
Installation, Testing, Configuration
|
||||
------------------------------------
|
||||
|
||||
From this point forward, python3 will be referred to as just "python".
|
||||
|
||||
Installation
|
||||
============
|
||||
|
||||
In addition to merely installing **glymur**, you should adjust your **$PATH**
|
||||
environment variable in order to be able to use the **jp2dump** script from
|
||||
the unix command line.
|
||||
|
||||
::
|
||||
|
||||
$ python setup.py install --prefix=/install/path
|
||||
$ export PYTHONPATH=/install/path/lib/python3.3/site-packages
|
||||
$ export PATH=/install/path/bin:$PATH
|
||||
|
||||
|
||||
Configuration
|
||||
=============
|
||||
glymur uses **ctypes** (for the moment) to access the openjp2 library, and
|
||||
because **ctypes** access libraries in a platform-dependent manner, it is
|
||||
recommended that you create a configuration file to help glymur properly find
|
||||
the openjp2 library. You may create the configuration file as follows::
|
||||
|
||||
$ mkdir ~/.glymur
|
||||
$ cd ~/.glymur
|
||||
$ cat > glymurrc << EOF
|
||||
> [library]
|
||||
> openjp2: /opt/openjp2-svn/lib/libopenjp2.so
|
||||
> EOF
|
||||
|
||||
That assumes, of course, that you've installed OpenJPEG into /opt/openjp2-svn.
|
||||
|
||||
|
||||
Testing
|
||||
=======
|
||||
In order to run all of the test suite, you will first need the OpenJPEG test
|
||||
data that you previously retrieved.
|
||||
Then you should set the **OPJ_DATA_ROOT** environment variable to
|
||||
point to this directory, e.g.::
|
||||
|
||||
$ cd /somewhere/outside/the/glymur/unpacking/directory
|
||||
$ svn co http://openjpeg.googlecode.com/svn/data
|
||||
$ export OPJ_DATA_ROOT=`pwd`/data
|
||||
|
||||
The test suite may then be run with::
|
||||
|
||||
$ cd /back/to/glymur/unpacking/directory
|
||||
$ python -m unittest discover
|
||||
|
||||
At the moment, the development version of the library prints quite a few
|
||||
warnings to stderr, which you may ignore. There are also more skipped tests
|
||||
on Python 2.7 than on Python 3.3. The important thing will be whether
|
||||
or not any test errors are reported at the end.
|
||||
4
TODO
4
TODO
|
|
@ -1,4 +0,0 @@
|
|||
Test -c options with multiple values.
|
||||
Test -b options with h*w>4096
|
||||
Test -b options with h or w > 1024
|
||||
Test -b options with h or w < 4
|
||||
|
|
@ -1,5 +1,116 @@
|
|||
---
|
||||
API
|
||||
===
|
||||
---
|
||||
|
||||
Jp2k
|
||||
----
|
||||
.. autoclass:: glymur.Jp2k
|
||||
:members: read, write, read_bands, get_codestream
|
||||
|
||||
Individual Boxes
|
||||
----------------
|
||||
Jp2kbox
|
||||
'''''''
|
||||
.. autoclass:: glymur.jp2box.Jp2kBox
|
||||
:members:
|
||||
|
||||
AssociationBox
|
||||
''''''''''''''
|
||||
.. autoclass:: glymur.jp2box.AssociationBox
|
||||
:members:
|
||||
|
||||
ColourSpecificationBox
|
||||
''''''''''''''''''''''
|
||||
.. autoclass:: glymur.jp2box.ColourSpecificationBox
|
||||
:members:
|
||||
|
||||
ComponentDefinitionBox
|
||||
''''''''''''''''''''''
|
||||
.. autoclass:: glymur.jp2box.ComponentDefinitionBox
|
||||
:members:
|
||||
|
||||
ComponentMappingBox
|
||||
'''''''''''''''''''
|
||||
.. autoclass:: glymur.jp2box.ComponentMappingBox
|
||||
:members:
|
||||
|
||||
ContiguousCodestreamBox
|
||||
'''''''''''''''''''''''
|
||||
.. autoclass:: glymur.jp2box.ContiguousCodestreamBox
|
||||
:members:
|
||||
|
||||
DataEntryURLBox
|
||||
'''''''''''''''
|
||||
.. autoclass:: glymur.jp2box.DataEntryURLBox
|
||||
:members:
|
||||
|
||||
FileTypeBox
|
||||
'''''''''''
|
||||
.. autoclass:: glymur.jp2box.FileTypeBox
|
||||
:members:
|
||||
|
||||
ImageHeaderBox
|
||||
''''''''''''''
|
||||
.. autoclass:: glymur.jp2box.ImageHeaderBox
|
||||
:members:
|
||||
|
||||
JP2HeaderBox
|
||||
''''''''''''
|
||||
.. autoclass:: glymur.jp2box.JP2HeaderBox
|
||||
:members:
|
||||
|
||||
JPEG2000SignatureBox
|
||||
''''''''''''''''''''
|
||||
.. autoclass:: glymur.jp2box.JPEG2000SignatureBox
|
||||
:members:
|
||||
|
||||
LabelBox
|
||||
''''''''
|
||||
.. autoclass:: glymur.jp2box.LabelBox
|
||||
:members:
|
||||
|
||||
PaletteBox
|
||||
''''''''''
|
||||
.. autoclass:: glymur.jp2box.PaletteBox
|
||||
:members:
|
||||
|
||||
ReaderRequirementsBox
|
||||
'''''''''''''''''''''
|
||||
.. autoclass:: glymur.jp2box.ReaderRequirementsBox
|
||||
:members:
|
||||
|
||||
ResolutionBox
|
||||
'''''''''''''
|
||||
.. autoclass:: glymur.jp2box.ResolutionBox
|
||||
:members:
|
||||
|
||||
CaptureResolutionBox
|
||||
''''''''''''''''''''
|
||||
.. autoclass:: glymur.jp2box.CaptureResolutionBox
|
||||
:members:
|
||||
|
||||
DisplayResolutionBox
|
||||
''''''''''''''''''''
|
||||
.. autoclass:: glymur.jp2box.DisplayResolutionBox
|
||||
:members:
|
||||
|
||||
UUIDBox
|
||||
'''''''
|
||||
.. autoclass:: glymur.jp2box.UUIDBox
|
||||
:members:
|
||||
|
||||
UUIDInfoBox
|
||||
'''''''''''
|
||||
.. autoclass:: glymur.jp2box.UUIDInfoBox
|
||||
:members:
|
||||
|
||||
UUIDListBox
|
||||
'''''''''''
|
||||
.. autoclass:: glymur.jp2box.UUIDListBox
|
||||
:members:
|
||||
|
||||
XMLBox
|
||||
''''''
|
||||
.. autoclass:: glymur.jp2box.XMLBox
|
||||
:members:
|
||||
|
||||
|
|
|
|||
|
|
@ -3,7 +3,8 @@
|
|||
# glymur documentation build configuration file, created by
|
||||
# sphinx-quickstart on Sun May 26 11:29:54 2013.
|
||||
#
|
||||
# This file is execfile()d with the current directory set to its containing dir.
|
||||
# This file is execfile()d with the current directory set to its containing
|
||||
# dir.
|
||||
#
|
||||
# Note that not all possible configuration values are present in this
|
||||
# autogenerated file.
|
||||
|
|
@ -11,7 +12,9 @@
|
|||
# All configuration values have a default; values that are commented out
|
||||
# serve to show the default.
|
||||
|
||||
import sys, os
|
||||
import sys
|
||||
import os
|
||||
|
||||
|
||||
class Mock(object):
|
||||
def __init__(self, *args, **kwargs):
|
||||
|
|
@ -41,13 +44,13 @@ for mod_name in MOCK_MODULES:
|
|||
# documentation root, use os.path.abspath to make it absolute, like shown here.
|
||||
#sys.path.insert(0, os.path.abspath('.'))
|
||||
|
||||
# -- General configuration -----------------------------------------------------
|
||||
# -- General configuration ----------------------------------------------------
|
||||
|
||||
# If your documentation needs a minimal Sphinx version, state it here.
|
||||
#needs_sphinx = '1.0'
|
||||
|
||||
# Add any Sphinx extension module names here, as strings. They can be extensions
|
||||
# coming with Sphinx (named 'sphinx.ext.*') or your custom ones.
|
||||
# Add any Sphinx extension module names here, as strings. They can be
|
||||
# extensions coming with Sphinx (named 'sphinx.ext.*') or your custom ones.
|
||||
extensions = ['sphinx.ext.autodoc', 'sphinx.ext.doctest',
|
||||
'sphinx.ext.autosummary',
|
||||
'sphinx.ext.intersphinx', 'sphinx.ext.todo', 'numpydoc']
|
||||
|
|
@ -75,7 +78,7 @@ copyright = u'2013, John Evans'
|
|||
# The short X.Y version.
|
||||
version = '0.1'
|
||||
# The full version, including alpha/beta/rc tags.
|
||||
release = '0.1.1'
|
||||
release = '0.1.6'
|
||||
|
||||
# The language for content autogenerated by Sphinx. Refer to documentation
|
||||
# for a list of supported languages.
|
||||
|
|
@ -91,7 +94,8 @@ release = '0.1.1'
|
|||
# directories to ignore when looking for source files.
|
||||
exclude_patterns = []
|
||||
|
||||
# The reST default role (used for this markup: `text`) to use for all documents.
|
||||
# The reST default role (used for this markup: `text`) to use for all
|
||||
# documents.
|
||||
#default_role = None
|
||||
|
||||
# If true, '()' will be appended to :func: etc. cross-reference text.
|
||||
|
|
@ -112,7 +116,7 @@ pygments_style = 'sphinx'
|
|||
#modindex_common_prefix = []
|
||||
|
||||
|
||||
# -- Options for HTML output ---------------------------------------------------
|
||||
# -- Options for HTML output --------------------------------------------------
|
||||
|
||||
# The theme to use for HTML and HTML Help pages. See the documentation for
|
||||
# a list of builtin themes.
|
||||
|
|
@ -192,9 +196,8 @@ html_show_sourcelink = True
|
|||
htmlhelp_basename = 'glymurdoc'
|
||||
|
||||
|
||||
# -- Options for LaTeX output --------------------------------------------------
|
||||
# -- Options for LaTeX output -------------------------------------------------
|
||||
|
||||
latex_elements = {
|
||||
# The paper size ('letterpaper' or 'a4paper').
|
||||
#'papersize': 'letterpaper',
|
||||
|
||||
|
|
@ -203,14 +206,13 @@ latex_elements = {
|
|||
|
||||
# Additional stuff for the LaTeX preamble.
|
||||
#'preamble': '',
|
||||
}
|
||||
latex_elements = {}
|
||||
|
||||
# Grouping the document tree into LaTeX files. List of tuples
|
||||
# (source start file, target name, title, author, documentclass [howto/manual]).
|
||||
latex_documents = [
|
||||
('index', 'glymur.tex', u'glymur Documentation',
|
||||
u'John Evans', 'manual'),
|
||||
]
|
||||
# (source start file, target name, title, author, documentclass
|
||||
# [howto/manual]).
|
||||
latex_documents = [('index', 'glymur.tex', u'glymur Documentation',
|
||||
u'John Evans', 'manual'), ]
|
||||
|
||||
# The name of an image file (relative to this directory) to place at the top of
|
||||
# the title page.
|
||||
|
|
@ -233,7 +235,7 @@ latex_documents = [
|
|||
#latex_domain_indices = True
|
||||
|
||||
|
||||
# -- Options for manual page output --------------------------------------------
|
||||
# -- Options for manual page output -------------------------------------------
|
||||
|
||||
# One entry per manual page. List of tuples
|
||||
# (source start file, name, description, authors, manual section).
|
||||
|
|
@ -246,16 +248,14 @@ man_pages = [
|
|||
#man_show_urls = False
|
||||
|
||||
|
||||
# -- Options for Texinfo output ------------------------------------------------
|
||||
# -- Options for Texinfo output -----------------------------------------------
|
||||
|
||||
# Grouping the document tree into Texinfo files. List of tuples
|
||||
# (source start file, target name, title, author,
|
||||
# dir menu entry, description, category)
|
||||
texinfo_documents = [
|
||||
('index', 'glymur', u'glymur Documentation',
|
||||
u'John Evans', 'glymur', 'One line description of project.',
|
||||
'Miscellaneous'),
|
||||
]
|
||||
texinfo_documents = [('index', 'glymur', u'glymur Documentation',
|
||||
u'John Evans', 'glymur',
|
||||
'One line description of project.', 'Miscellaneous'), ]
|
||||
|
||||
# Documents to append as an appendix to all manuals.
|
||||
#texinfo_appendices = []
|
||||
|
|
|
|||
|
|
@ -1,15 +1,16 @@
|
|||
************
|
||||
------------
|
||||
How do I...?
|
||||
************
|
||||
------------
|
||||
|
||||
|
||||
Display metadata?
|
||||
=================
|
||||
There are two ways. From the unix command line, the script **jp2dump** is
|
||||
available.::
|
||||
There are two ways. From the unix command line, the script *jp2dump* is
|
||||
available. ::
|
||||
|
||||
$ jp2dump /path/to/glymur/installation/data/nemo.jp2
|
||||
|
||||
From within Python, it is as simple as printing the Jp2k object, i.e.::
|
||||
From within Python, it is as simple as printing the Jp2k object, i.e. ::
|
||||
|
||||
>>> import pkg_resources
|
||||
>>> from glymur import Jp2k
|
||||
|
|
@ -17,8 +18,40 @@ From within Python, it is as simple as printing the Jp2k object, i.e.::
|
|||
>>> j = Jp2k(file)
|
||||
>>> print(j)
|
||||
|
||||
The primary emphasis is on JP2 metadata, but it is possible to
|
||||
display raw codestream as well::
|
||||
This prints the metadata found in the JP2 boxes, but in the case of the
|
||||
codestream box, only the main header is printed. It is possible to print
|
||||
**only** the codestream information as well, i.e. ::
|
||||
|
||||
>>> print(j.get_codestream())
|
||||
|
||||
Work with XMP UUIDs?
|
||||
====================
|
||||
The example JP2 file shipped with glymur has an XMP UUID::
|
||||
|
||||
>>> import pkg_resources
|
||||
>>> from glymur import Jp2k
|
||||
>>> file = pkg_resources.resource_filename(glymur.__name__, "data/nemo.jp2")
|
||||
>>> j = Jp2k(file)
|
||||
>>> print(j.box[4])
|
||||
UUID Box (uuid) @ (715, 2412)
|
||||
UUID: be7acfcb-97a9-42e8-9c71-999491e3afac (XMP)
|
||||
UUID Data:
|
||||
<ns0:xmpmeta xmlns:ns0="adobe:ns:meta/" xmlns:ns2="http://ns.adobe.com/xap/1.0/" xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" ns0:xmptk="XMP Core 4.4.0-Exiv2">
|
||||
<rdf:RDF>
|
||||
<rdf:Description ns2:CreatorTool="glymur" rdf:about="" />
|
||||
</rdf:RDF>
|
||||
</ns0:xmpmeta>
|
||||
|
||||
Since the UUID data in this case is returned as an ElementTree Element, one can
|
||||
use ElementTree to access the data. For example, to extract the
|
||||
**CreatorTool** attribute value, the following would work::
|
||||
|
||||
>>> xmp = j.box[4].data
|
||||
>>> ns0 = '{http://www.w3.org/1999/02/22-rdf-syntax-ns#}'
|
||||
>>> ns1 = '{http://ns.adobe.com/xap/1.0/}'
|
||||
>>> name = '{0}RDF/{0}Description'.format(ns0)
|
||||
>>> elt = xmp.find(name)
|
||||
>>> elt
|
||||
<Element '{http://www.w3.org/1999/02/22-rdf-syntax-ns#}Description' at 0xb4baa93c>
|
||||
>>> elt.attrib['{0}CreatorTool'.format(ns1)]
|
||||
'glymur'
|
||||
|
|
|
|||
|
|
@ -3,8 +3,9 @@
|
|||
You can adapt this file completely to your liking, but it should at least
|
||||
contain the root `toctree` directive.
|
||||
|
||||
==================================
|
||||
Welcome to glymur's documentation!
|
||||
===================================
|
||||
==================================
|
||||
|
||||
Contents:
|
||||
|
||||
|
|
@ -14,10 +15,11 @@ Contents:
|
|||
introduction
|
||||
api
|
||||
how_do_i
|
||||
roadmap
|
||||
|
||||
|
||||
------------------
|
||||
Indices and tables
|
||||
==================
|
||||
------------------
|
||||
|
||||
* :ref:`genindex`
|
||||
* :ref:`modindex`
|
||||
|
|
|
|||
|
|
@ -1,23 +1,27 @@
|
|||
=========================================
|
||||
glymur: a Python interface for JPEG 2000
|
||||
=========================================
|
||||
----------------------------------------
|
||||
Glymur: a Python interface for JPEG 2000
|
||||
----------------------------------------
|
||||
|
||||
**glymur** contains a Python interface to the OpenJPEG library
|
||||
**Glymur** contains a Python interface to the OpenJPEG library
|
||||
which allows linux and mac users to read and write JPEG 2000 files. For more
|
||||
information about OpenJPEG, please consult http://www.openjpeg.org. glymur
|
||||
should be considered to be alpha-quality software.
|
||||
information about OpenJPEG, please consult http://www.openjpeg.org. Glymur
|
||||
currently relies upon a development version of the OpenJPEG library, and so,
|
||||
while useable, it is totally at the mercy of any upstream changes
|
||||
made to the development version of OpenJPEG.
|
||||
|
||||
glymur tries to support reading (including all metadata) and writing of
|
||||
JP2 and J2C files. Writing J2C/JP2 files is currently limited to images that
|
||||
can fit in memory, however.
|
||||
Glymur supports both reading and writing of JPEG 2000 images (part 1). Writing
|
||||
JPEG 2000 images is currently limited to images that can fit in memory,
|
||||
however.
|
||||
|
||||
There is some very limited support for reading JPX
|
||||
metadata. For instance, **asoc** and **labl** boxes are recognized, so GMLJP2
|
||||
metadata can be retrieved from such JPX files.
|
||||
Of particular focus is retrieval of metadata. Reading Exif UUIDs is supported,
|
||||
as is reading XMP UUIDs as the XMP data packet is just XML. There is
|
||||
some very limited support for reading JPX metadata. For instance,
|
||||
**asoc** and **labl** boxes are recognized, so GMLJP2 metadata can
|
||||
be retrieved from such JPX files.
|
||||
|
||||
------------
|
||||
''''''''''''
|
||||
Requirements
|
||||
------------
|
||||
''''''''''''
|
||||
glymur works on Python 2.7 and 3.3. Python 3.3 is strongly recommended.
|
||||
|
||||
OpenJPEG
|
||||
|
|
@ -28,7 +32,8 @@ you can retrieve via subversion. As of this time of writing, svn
|
|||
revision 2345 works. In addition, you should also retrieve their test data, as
|
||||
you will need it when running glymur's test suite.
|
||||
|
||||
Earlier versions of OpenJPEG through the 2.0 official release are not supported.
|
||||
Earlier versions of OpenJPEG through the 2.0 official release will **NOT**
|
||||
work and are not supported.
|
||||
|
||||
Be sure to have the following ports/RPMs/debs installed.
|
||||
|
||||
|
|
@ -128,22 +133,34 @@ Windows
|
|||
-------
|
||||
Not currently supported.
|
||||
|
||||
------------------------------------
|
||||
''''''''''''''''''''''''''''''''''''
|
||||
Installation, Testing, Configuration
|
||||
------------------------------------
|
||||
''''''''''''''''''''''''''''''''''''
|
||||
|
||||
From this point forward, python3 will be referred to as just "python".
|
||||
|
||||
Installation
|
||||
============
|
||||
|
||||
You can install glymur via pip from the command line::
|
||||
|
||||
$ pip install glymur
|
||||
|
||||
or manually retrieve the code from either of GitHub or PyPI
|
||||
|
||||
* https://pypi.python.org/pypi/Glymur/ (stable releases)
|
||||
* http://github.com/quintusdias/glymur (bleeding edge)
|
||||
|
||||
and then unpack and install with::
|
||||
|
||||
$ python setup.py install --prefix=/install/path
|
||||
|
||||
In addition to merely installing glymur, you should adjust your **$PATH**
|
||||
environment variable in order to be able to use the **jp2dump** script from
|
||||
environment variable in order to be able to use the *jp2dump* script from
|
||||
the unix command line.
|
||||
|
||||
::
|
||||
|
||||
$ python setup.py install --prefix=/install/path
|
||||
$ export PYTHONPATH=/install/path/lib/python3.3/site-packages
|
||||
$ export PATH=/install/path/bin:$PATH
|
||||
|
||||
|
|
@ -181,7 +198,10 @@ The test suite may then be run with::
|
|||
$ cd /back/to/glymur/unpacking/directory
|
||||
$ python -m unittest discover
|
||||
|
||||
At the moment, the development version of the library prints quite a few
|
||||
warnings to stderr, which you may ignore. There are also more skipped tests
|
||||
on Python 2.7 than on Python 3.3. The important thing will be whether
|
||||
or not any test errors are reported at the end.
|
||||
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 the tests are actually passing), they've been
|
||||
filtered out for now. There are also more skipped tests on Python 2.7
|
||||
than on Python 3.3. The important point to remember is whether or not any test
|
||||
errors are reported at the end.
|
||||
|
|
|
|||
12
docs/source/roadmap.rst
Normal file
12
docs/source/roadmap.rst
Normal file
|
|
@ -0,0 +1,12 @@
|
|||
-------
|
||||
Roadmap
|
||||
-------
|
||||
|
||||
Here's an incomplete list of what I'd like to focus on in the near future.
|
||||
|
||||
* continue to monitor upstream changes in the openjp2 library
|
||||
* investigate using CFFI or cython instead of ctypes to wrap openjp2
|
||||
* eventually expose the openjp2 API
|
||||
* add metadata support for ICC profiles
|
||||
* investigate JPIP
|
||||
|
||||
|
|
@ -16,24 +16,15 @@ def _glymurrc_fname():
|
|||
if os.path.exists(fname):
|
||||
return fname
|
||||
|
||||
# environ var GLYMURCONFIGDIR
|
||||
if 'GLYMURCONFIGDIR' in os.environ:
|
||||
path = os.environ['GLYMURCONFIGDIR']
|
||||
if os.path.exists(path):
|
||||
fname = os.path.join(path, 'glymurrc')
|
||||
if os.path.exists(fname):
|
||||
return fname
|
||||
else:
|
||||
msg = "glymurrc file hinted at by GLYMURCONFIGDIR does not "
|
||||
msg += "exist."
|
||||
warnings.warn(msg, UserWarning)
|
||||
|
||||
# HOME/.glymur/glymurrc
|
||||
# Either GLYMURCONFIGDIR/glymurrc or $HOME/.glymur/glymurrc
|
||||
confdir = _get_configdir()
|
||||
if confdir is not None:
|
||||
fname = os.path.join(_get_configdir(), 'glymurrc')
|
||||
fname = os.path.join(confdir, 'glymurrc')
|
||||
if os.path.exists(fname):
|
||||
return fname
|
||||
else:
|
||||
msg = "Configuration file '{0}' does not exist.".format(confdir)
|
||||
warnings.warn(msg, UserWarning)
|
||||
|
||||
# didn't find a configuration file.
|
||||
return None
|
||||
|
|
|
|||
|
|
@ -472,8 +472,6 @@ class Codestream:
|
|||
SPcod = f.read(n)
|
||||
kwargs['SPcod'] = np.frombuffer(SPcod, dtype=np.uint8)
|
||||
|
||||
# 0:
|
||||
# 1: layers
|
||||
params = struct.unpack('>BHBBBBBB', SPcod[0:9])
|
||||
kwargs['_layers'] = params[1]
|
||||
kwargs['_numresolutions'] = params[3]
|
||||
|
|
|
|||
Binary file not shown.
782
glymur/jp2box.py
782
glymur/jp2box.py
File diff suppressed because it is too large
Load diff
|
|
@ -8,6 +8,7 @@ if sys.hexversion >= 0x03030000:
|
|||
else:
|
||||
from contextlib2 import ExitStack
|
||||
import ctypes
|
||||
import math
|
||||
import os
|
||||
import struct
|
||||
import warnings
|
||||
|
|
@ -152,7 +153,7 @@ class Jp2k(Jp2kBox):
|
|||
data : array
|
||||
Image data to be written to file.
|
||||
callbacks : bool, optional
|
||||
If true, enable default info handler such that INFO messages
|
||||
If true, enable default info handler such that INFO messages
|
||||
produced by the OpenJPEG library are output to the console. By
|
||||
default, OpenJPEG warning and error messages are captured by
|
||||
Python's own warning and error mechanisms.
|
||||
|
|
@ -181,7 +182,8 @@ class Jp2k(Jp2kBox):
|
|||
psnr : list, optional
|
||||
Different PSNR for successive layers.
|
||||
psizes : list, optional
|
||||
List of precinct sizes.
|
||||
List of precinct sizes. Each precinct size tuple is defined in
|
||||
(height x width).
|
||||
sop : bool, optional
|
||||
If true, write SOP marker before each packet.
|
||||
subsam : tuple, optional
|
||||
|
|
@ -231,6 +233,11 @@ class Jp2k(Jp2kBox):
|
|||
msg = "Code block area cannot exceed 4096. "
|
||||
msg += "Code block height and width must be larger than 4."
|
||||
raise RuntimeError(msg)
|
||||
if ((math.log(h, 2) != math.floor(math.log(h, 2)) or
|
||||
math.log(w, 2) != math.floor(math.log(w, 2)))):
|
||||
msg = "Bad code block size ({0}, {1}), "
|
||||
msg += "must be powers of 2."
|
||||
raise IOError(msg.format(h, w))
|
||||
cparams.cblockw_init = w
|
||||
cparams.cblockh_init = h
|
||||
|
||||
|
|
@ -266,9 +273,21 @@ class Jp2k(Jp2kBox):
|
|||
cparams.cp_fixed_quality = 1
|
||||
|
||||
if psizes is not None:
|
||||
for j, precinct in enumerate(psizes):
|
||||
cparams.prcw_init[j] = precinct[0]
|
||||
cparams.prch_init[j] = precinct[1]
|
||||
for j, (prch, prcw) in enumerate(psizes):
|
||||
if j == 0 and cbsize is not None:
|
||||
cblkh, cblkw = cbsize
|
||||
if cblkh * 2 > prch or cblkw * 2 > prcw:
|
||||
msg = "Highest Resolution precinct size must be at "
|
||||
msg += "least twice that of the code block dimensions."
|
||||
raise IOError(msg)
|
||||
if ((math.log(prch, 2) != math.floor(math.log(prch, 2)) or
|
||||
math.log(prcw, 2) != math.floor(math.log(prcw, 2)))):
|
||||
msg = "Bad precinct sizes ({0}, {1}), "
|
||||
msg += "must be powers of 2."
|
||||
raise IOError(msg.format(prch, prcw))
|
||||
|
||||
cparams.prcw_init[j] = prcw
|
||||
cparams.prch_init[j] = prch
|
||||
cparams.csty |= 0x01
|
||||
cparams.res_spec = len(psizes)
|
||||
|
||||
|
|
@ -634,7 +653,7 @@ class Jp2k(Jp2kBox):
|
|||
>>> jp = glymur.Jp2k(jfile)
|
||||
>>> codestream = jp.get_codestream()
|
||||
>>> print(codestream.segment[1])
|
||||
SIZ marker segment @ (87, 47)
|
||||
SIZ marker segment @ (3137, 47)
|
||||
Profile: 2
|
||||
Reference Grid Height, Width: (1456 x 2592)
|
||||
Vertical, Horizontal Reference Grid Offset: (0 x 0)
|
||||
|
|
|
|||
|
|
@ -53,7 +53,7 @@ class TestCallbacks(unittest.TestCase):
|
|||
d = j.read(reduce=3, verbose=True, area=(0, 0, 512, 1024))
|
||||
actual = sys.stdout.getvalue().strip()
|
||||
|
||||
lines = ['[INFO] Start to read j2k main header (85).',
|
||||
lines = ['[INFO] Start to read j2k main header (3135).',
|
||||
'[INFO] Main header has been correctly decoded.',
|
||||
'[INFO] Setting decoding area to 0,0,1024,512',
|
||||
'[INFO] Header of tile 0 / 17 has been read.',
|
||||
|
|
|
|||
|
|
@ -50,19 +50,14 @@ def chdir(dirname=None):
|
|||
|
||||
class TestJp2k(unittest.TestCase):
|
||||
|
||||
def setUp(self):
|
||||
self.jp2file = pkg_resources.resource_filename(glymur.__name__,
|
||||
"data/nemo.jp2")
|
||||
|
||||
def tearDown(self):
|
||||
pass
|
||||
|
||||
@unittest.skipIf(sys.hexversion < 0x03020000,
|
||||
"Uses features introduced in 3.2.")
|
||||
def test_invalid_xml_box(self):
|
||||
# Should be able to recover from xml box with bad xml.
|
||||
with tempfile.NamedTemporaryFile(suffix='.jp2') as tfile:
|
||||
with open(self.jp2file, 'rb') as ifile:
|
||||
@classmethod
|
||||
def setUpClass(cls):
|
||||
# Setup a JP2 file with a bad XML box.
|
||||
jp2file = pkg_resources.resource_filename(glymur.__name__,
|
||||
"data/nemo.jp2")
|
||||
with tempfile.NamedTemporaryFile(suffix='.jp2', delete=False) as tfile:
|
||||
cls._bad_xml_file = tfile.name
|
||||
with open(jp2file, 'rb') as ifile:
|
||||
# Everything up until the jp2c box.
|
||||
buffer = ifile.read(77)
|
||||
tfile.write(buffer)
|
||||
|
|
@ -81,13 +76,35 @@ class TestJp2k(unittest.TestCase):
|
|||
tfile.write(buffer)
|
||||
tfile.flush()
|
||||
|
||||
with self.assertWarns(UserWarning) as cw:
|
||||
jp2k = Jp2k(tfile.name)
|
||||
@classmethod
|
||||
def tearDownClass(cls):
|
||||
os.unlink(cls._bad_xml_file)
|
||||
|
||||
self.assertEqual(jp2k.box[3].id, 'xml ')
|
||||
self.assertEqual(jp2k.box[3].offset, 77)
|
||||
self.assertEqual(jp2k.box[3].length, 28)
|
||||
self.assertIsNone(jp2k.box[3].xml)
|
||||
def setUp(self):
|
||||
self.jp2file = pkg_resources.resource_filename(glymur.__name__,
|
||||
"data/nemo.jp2")
|
||||
|
||||
def tearDown(self):
|
||||
pass
|
||||
|
||||
@unittest.skipIf(sys.hexversion < 0x03020000,
|
||||
"Uses features introduced in 3.2.")
|
||||
def test_invalid_xml_box_warning(self):
|
||||
# Should be able to recover from xml box with bad xml.
|
||||
# Just verify that a warning is issued on 3.2+
|
||||
with self.assertWarns(UserWarning) as cw:
|
||||
jp2k = Jp2k(self._bad_xml_file)
|
||||
|
||||
def test_invalid_xml_box(self):
|
||||
# Should be able to recover from xml box with bad xml.
|
||||
with warnings.catch_warnings():
|
||||
warnings.simplefilter("ignore")
|
||||
jp2k = Jp2k(self._bad_xml_file)
|
||||
|
||||
self.assertEqual(jp2k.box[3].id, 'xml ')
|
||||
self.assertEqual(jp2k.box[3].offset, 77)
|
||||
self.assertEqual(jp2k.box[3].length, 28)
|
||||
self.assertIsNone(jp2k.box[3].xml)
|
||||
|
||||
def test_bad_area_parameter(self):
|
||||
# Verify that we error out appropriately if given a bad area parameter.
|
||||
|
|
@ -134,12 +151,25 @@ class TestJp2k(unittest.TestCase):
|
|||
subsetdata = j.read(area=(0, 0, 512, 512))
|
||||
np.testing.assert_array_equal(tiledata, subsetdata)
|
||||
|
||||
def test_write_cprl(self):
|
||||
# Issue 17
|
||||
j = Jp2k(self.jp2file)
|
||||
expdata = j.read(reduce=2)
|
||||
with tempfile.NamedTemporaryFile(suffix='.jp2') as tfile:
|
||||
ofile = Jp2k(tfile.name, 'wb')
|
||||
ofile.write(expdata, prog='CPRL')
|
||||
actdata = ofile.read()
|
||||
np.testing.assert_array_equal(actdata, expdata)
|
||||
|
||||
c = ofile.get_codestream()
|
||||
self.assertEqual(c.segment[2].SPcod[0], glymur.core.CPRL)
|
||||
|
||||
def test_jp2_boxes(self):
|
||||
# Verify the boxes of a JP2 file.
|
||||
jp2k = Jp2k(self.jp2file)
|
||||
|
||||
# top-level boxes
|
||||
self.assertEqual(len(jp2k.box), 4)
|
||||
self.assertEqual(len(jp2k.box), 6)
|
||||
|
||||
self.assertEqual(jp2k.box[0].id, 'jP ')
|
||||
self.assertEqual(jp2k.box[0].offset, 0)
|
||||
|
|
@ -156,9 +186,17 @@ class TestJp2k(unittest.TestCase):
|
|||
self.assertEqual(jp2k.box[2].length, 45)
|
||||
self.assertEqual(jp2k.box[2].longname, 'JP2 Header')
|
||||
|
||||
self.assertEqual(jp2k.box[3].id, 'jp2c')
|
||||
self.assertEqual(jp2k.box[3].id, 'uuid')
|
||||
self.assertEqual(jp2k.box[3].offset, 77)
|
||||
self.assertEqual(jp2k.box[3].length, 1133427)
|
||||
self.assertEqual(jp2k.box[3].length, 638)
|
||||
|
||||
self.assertEqual(jp2k.box[4].id, 'uuid')
|
||||
self.assertEqual(jp2k.box[4].offset, 715)
|
||||
self.assertEqual(jp2k.box[4].length, 2412)
|
||||
|
||||
self.assertEqual(jp2k.box[5].id, 'jp2c')
|
||||
self.assertEqual(jp2k.box[5].offset, 3127)
|
||||
self.assertEqual(jp2k.box[5].length, 1133427)
|
||||
|
||||
# jp2h super box
|
||||
self.assertEqual(len(jp2k.box[2].box), 2)
|
||||
|
|
@ -182,7 +220,7 @@ class TestJp2k(unittest.TestCase):
|
|||
self.assertEqual(jp2k.box[2].box[1].longname, 'Colour Specification')
|
||||
self.assertEqual(jp2k.box[2].box[1].precedence, 0)
|
||||
self.assertEqual(jp2k.box[2].box[1].approximation, 0)
|
||||
self.assertEqual(jp2k.box[2].box[1].color_space, glymur.core.SRGB)
|
||||
self.assertEqual(jp2k.box[2].box[1].colorspace, glymur.core.SRGB)
|
||||
self.assertIsNone(jp2k.box[2].box[1].icc_profile)
|
||||
|
||||
@unittest.skipIf(data_root is None,
|
||||
|
|
@ -200,7 +238,7 @@ class TestJp2k(unittest.TestCase):
|
|||
with tempfile.NamedTemporaryFile(suffix='.jp2') as tfile:
|
||||
with open(self.jp2file, 'rb') as ifile:
|
||||
# Everything up until the jp2c box.
|
||||
buffer = ifile.read(77)
|
||||
buffer = ifile.read(3127)
|
||||
tfile.write(buffer)
|
||||
|
||||
# The L field must be 1 in order to signal the presence of the
|
||||
|
|
@ -221,9 +259,9 @@ class TestJp2k(unittest.TestCase):
|
|||
|
||||
jp2k = Jp2k(tfile.name)
|
||||
|
||||
self.assertEqual(jp2k.box[3].id, 'jp2c')
|
||||
self.assertEqual(jp2k.box[3].offset, 77)
|
||||
self.assertEqual(jp2k.box[3].length, 1133427 + 8)
|
||||
self.assertEqual(jp2k.box[5].id, 'jp2c')
|
||||
self.assertEqual(jp2k.box[5].offset, 3127)
|
||||
self.assertEqual(jp2k.box[5].length, 1133427 + 8)
|
||||
|
||||
def test_L_is_zero(self):
|
||||
# Verify that boxes with the L field as zero are correctly read.
|
||||
|
|
@ -332,14 +370,14 @@ class TestJp2k(unittest.TestCase):
|
|||
j = Jp2k(tfile.name, 'wb')
|
||||
data = np.zeros((128, 128, 3), dtype=np.uint8)
|
||||
j.write(data, colorspace='rgb')
|
||||
self.assertEqual(j.box[2].box[1].color_space, glymur.core.SRGB)
|
||||
self.assertEqual(j.box[2].box[1].colorspace, glymur.core.SRGB)
|
||||
|
||||
def test_specify_gray(self):
|
||||
with tempfile.NamedTemporaryFile(suffix='.jp2') as tfile:
|
||||
j = Jp2k(tfile.name, 'wb')
|
||||
data = np.zeros((128, 128), dtype=np.uint8)
|
||||
j.write(data, colorspace='gray')
|
||||
self.assertEqual(j.box[2].box[1].color_space,
|
||||
self.assertEqual(j.box[2].box[1].colorspace,
|
||||
glymur.core.GREYSCALE)
|
||||
|
||||
def test_specify_grey(self):
|
||||
|
|
@ -347,7 +385,7 @@ class TestJp2k(unittest.TestCase):
|
|||
j = Jp2k(tfile.name, 'wb')
|
||||
data = np.zeros((128, 128), dtype=np.uint8)
|
||||
j.write(data, colorspace='grey')
|
||||
self.assertEqual(j.box[2].box[1].color_space,
|
||||
self.assertEqual(j.box[2].box[1].colorspace,
|
||||
glymur.core.GREYSCALE)
|
||||
|
||||
def test_grey_with_extra_component(self):
|
||||
|
|
@ -358,7 +396,7 @@ class TestJp2k(unittest.TestCase):
|
|||
self.assertEqual(j.box[2].box[0].height, 128)
|
||||
self.assertEqual(j.box[2].box[0].width, 128)
|
||||
self.assertEqual(j.box[2].box[0].num_components, 2)
|
||||
self.assertEqual(j.box[2].box[1].color_space,
|
||||
self.assertEqual(j.box[2].box[1].colorspace,
|
||||
glymur.core.GREYSCALE)
|
||||
|
||||
def test_grey_with_two_extra_components(self):
|
||||
|
|
@ -369,7 +407,7 @@ class TestJp2k(unittest.TestCase):
|
|||
self.assertEqual(j.box[2].box[0].height, 128)
|
||||
self.assertEqual(j.box[2].box[0].width, 128)
|
||||
self.assertEqual(j.box[2].box[0].num_components, 3)
|
||||
self.assertEqual(j.box[2].box[1].color_space,
|
||||
self.assertEqual(j.box[2].box[1].colorspace,
|
||||
glymur.core.GREYSCALE)
|
||||
|
||||
def test_rgb_with_extra_component(self):
|
||||
|
|
@ -380,7 +418,7 @@ class TestJp2k(unittest.TestCase):
|
|||
self.assertEqual(j.box[2].box[0].height, 128)
|
||||
self.assertEqual(j.box[2].box[0].width, 128)
|
||||
self.assertEqual(j.box[2].box[0].num_components, 4)
|
||||
self.assertEqual(j.box[2].box[1].color_space, glymur.core.SRGB)
|
||||
self.assertEqual(j.box[2].box[1].colorspace, glymur.core.SRGB)
|
||||
|
||||
def test_specify_ycc(self):
|
||||
# We don't support writing YCC at the moment.
|
||||
|
|
@ -513,10 +551,9 @@ class TestJp2k(unittest.TestCase):
|
|||
|
||||
# Now append the codestream.
|
||||
tfile2.write(codestream)
|
||||
tfile2.flush()
|
||||
|
||||
with warnings.catch_warnings():
|
||||
warnings.simplefilter("ignore")
|
||||
jasoc = Jp2k(tfile2.name)
|
||||
jasoc = Jp2k(tfile2.name)
|
||||
self.assertEqual(jasoc.box[3].id, 'asoc')
|
||||
self.assertEqual(jasoc.box[3].box[0].id, 'lbl ')
|
||||
self.assertEqual(jasoc.box[3].box[0].label, 'label')
|
||||
|
|
@ -528,17 +565,19 @@ class TestJp2k(unittest.TestCase):
|
|||
with open(self.jp2file, 'rb') as fp:
|
||||
data = fp.read()
|
||||
with tempfile.NamedTemporaryFile(suffix='.jp2') as tfile:
|
||||
tfile.write(data[0:129])
|
||||
# Codestream starts at byte 3127. SIZ marker at 3137.
|
||||
# COD marker at 3186. Subsampling at 3180.
|
||||
tfile.write(data[0:3179])
|
||||
|
||||
# Make the DY bytes of the SIZ segment zero. That means that
|
||||
# a subsampling factor is zero, which is illegal.
|
||||
tfile.write(b'\x00')
|
||||
tfile.write(data[130:132])
|
||||
tfile.write(data[3180:3182])
|
||||
tfile.write(b'\x00')
|
||||
tfile.write(data[134:136])
|
||||
tfile.write(data[3184:3186])
|
||||
tfile.write(b'\x00')
|
||||
|
||||
tfile.write(data[136:])
|
||||
tfile.write(data[3186:])
|
||||
tfile.flush()
|
||||
with warnings.catch_warnings():
|
||||
warnings.simplefilter("ignore")
|
||||
|
|
@ -597,6 +636,27 @@ class TestJp2k(unittest.TestCase):
|
|||
with self.assertWarns(UserWarning) as cw:
|
||||
imp.reload(glymur)
|
||||
|
||||
@unittest.skipIf(sys.hexversion < 0x03020000,
|
||||
"Uses features introduced in 3.2.")
|
||||
def test_home_dir_missing_config_dir(self):
|
||||
# Verify no exception is raised if $HOME is missing .glymur directory.
|
||||
with tempfile.TemporaryDirectory() as tdir:
|
||||
with patch.dict('os.environ', {'HOME': tdir}):
|
||||
# Misconfigured new configuration file should
|
||||
# be rejected.
|
||||
with self.assertWarns(UserWarning) as cw:
|
||||
imp.reload(glymur)
|
||||
|
||||
def test_xmp_attribute(self):
|
||||
# Verify that we can read the XMP packet in our shipping example file.
|
||||
j = Jp2k(self.jp2file)
|
||||
xmp = j.box[4].data
|
||||
ns0 = '{http://www.w3.org/1999/02/22-rdf-syntax-ns#}'
|
||||
ns1 = '{http://ns.adobe.com/xap/1.0/}'
|
||||
name = '{0}RDF/{0}Description'.format(ns0)
|
||||
elt = xmp.find(name)
|
||||
attr_value = elt.attrib['{0}CreatorTool'.format(ns1)]
|
||||
self.assertEqual(attr_value, 'glymur')
|
||||
|
||||
if __name__ == "__main__":
|
||||
unittest.main()
|
||||
|
|
|
|||
|
|
@ -3,6 +3,7 @@ The tests defined here roughly correspond to what is in the OpenJPEG test
|
|||
suite.
|
||||
"""
|
||||
|
||||
from contextlib import contextmanager
|
||||
import os
|
||||
import platform
|
||||
import re
|
||||
|
|
@ -11,6 +12,13 @@ from xml.etree import cElementTree as ET
|
|||
import unittest
|
||||
import warnings
|
||||
|
||||
if sys.hexversion <= 0x03030000:
|
||||
from mock import patch
|
||||
from StringIO import StringIO
|
||||
else:
|
||||
from unittest.mock import patch
|
||||
from io import StringIO
|
||||
|
||||
import numpy as np
|
||||
|
||||
from glymur import Jp2k
|
||||
|
|
@ -263,6 +271,7 @@ class TestSuite(unittest.TestCase):
|
|||
|
||||
np.testing.assert_array_equal(jpdata, pgxdata)
|
||||
|
||||
@unittest.skip("fprintf stderr output in r2343.")
|
||||
def test_ETS_C0P0_p0_12_j2k(self):
|
||||
jfile = os.path.join(data_root, 'input/conformance/p0_12.j2k')
|
||||
jp2k = Jp2k(jfile)
|
||||
|
|
@ -622,6 +631,7 @@ class TestSuite(unittest.TestCase):
|
|||
pgxdata = read_pgx(pgxfile)
|
||||
np.testing.assert_array_equal(jpdata, pgxdata)
|
||||
|
||||
@unittest.skip("fprintf stderr output in r2343.")
|
||||
def test_ETS_C1P0_p0_12_j2k(self):
|
||||
jfile = os.path.join(data_root, 'input/conformance/p0_12.j2k')
|
||||
jp2k = Jp2k(jfile)
|
||||
|
|
@ -631,6 +641,7 @@ class TestSuite(unittest.TestCase):
|
|||
pgxdata = read_pgx(pgxfile)
|
||||
np.testing.assert_array_equal(jpdata, pgxdata)
|
||||
|
||||
@unittest.skip("fprintf stderr output in r2343.")
|
||||
def test_ETS_C1P0_p0_13_j2k(self):
|
||||
jfile = os.path.join(data_root, 'input/conformance/p0_13.j2k')
|
||||
jp2k = Jp2k(jfile)
|
||||
|
|
@ -750,6 +761,7 @@ class TestSuite(unittest.TestCase):
|
|||
self.assertTrue(peak_tolerance(jpdata, pgxdata) < 624)
|
||||
self.assertTrue(mse(jpdata, pgxdata) < 3080)
|
||||
|
||||
@unittest.skip("fprintf stderr output in r2343.")
|
||||
def test_ETS_C1P1_p1_05_j2k(self):
|
||||
jfile = os.path.join(data_root, 'input/conformance/p1_05.j2k')
|
||||
jp2k = Jp2k(jfile)
|
||||
|
|
@ -770,6 +782,7 @@ class TestSuite(unittest.TestCase):
|
|||
self.assertTrue(peak_tolerance(jpdata[:, :, 2], pgxdata) < 40)
|
||||
self.assertTrue(mse(jpdata[:, :, 2], pgxdata) < 10.154)
|
||||
|
||||
@unittest.skip("fprintf stderr output in r2343.")
|
||||
def test_ETS_C1P1_p1_06_j2k(self):
|
||||
jfile = os.path.join(data_root, 'input/conformance/p1_06.j2k')
|
||||
jp2k = Jp2k(jfile)
|
||||
|
|
@ -790,6 +803,7 @@ class TestSuite(unittest.TestCase):
|
|||
self.assertTrue(peak_tolerance(jpdata[:, :, 2], pgxdata) < 2)
|
||||
self.assertTrue(mse(jpdata[:, :, 2], pgxdata) < 0.6)
|
||||
|
||||
@unittest.skip("fprintf stderr output in r2343.")
|
||||
def test_ETS_C1P1_p1_07_j2k(self):
|
||||
jfile = os.path.join(data_root, 'input/conformance/p1_07.j2k')
|
||||
jp2k = Jp2k(jfile)
|
||||
|
|
@ -3389,7 +3403,7 @@ class TestSuite(unittest.TestCase):
|
|||
self.assertEqual(jp2.box[3].box[1].method, 1)
|
||||
self.assertEqual(jp2.box[3].box[1].precedence, 0)
|
||||
self.assertEqual(jp2.box[3].box[1].approximation, 1) # JPX exact ??
|
||||
self.assertEqual(jp2.box[3].box[1].color_space, glymur.core.SRGB)
|
||||
self.assertEqual(jp2.box[3].box[1].colorspace, glymur.core.SRGB)
|
||||
|
||||
# XML box
|
||||
tags = [x.tag for x in jp2.box[4].xml]
|
||||
|
|
@ -3431,7 +3445,7 @@ class TestSuite(unittest.TestCase):
|
|||
self.assertEqual(jp2.box[2].box[1].method, 1)
|
||||
self.assertEqual(jp2.box[2].box[1].precedence, 0)
|
||||
self.assertEqual(jp2.box[2].box[1].approximation, 1) # JPX exact??
|
||||
self.assertEqual(jp2.box[2].box[1].color_space, glymur.core.YCC)
|
||||
self.assertEqual(jp2.box[2].box[1].colorspace, glymur.core.YCC)
|
||||
|
||||
# Jp2 Header
|
||||
# Channel Definition
|
||||
|
|
@ -3477,7 +3491,7 @@ class TestSuite(unittest.TestCase):
|
|||
self.assertEqual(jp2.box[2].box[1].method, 1)
|
||||
self.assertEqual(jp2.box[2].box[1].precedence, 0)
|
||||
self.assertEqual(jp2.box[2].box[1].approximation, 1) # JPX exact
|
||||
self.assertEqual(jp2.box[2].box[1].color_space, glymur.core.YCC)
|
||||
self.assertEqual(jp2.box[2].box[1].colorspace, glymur.core.YCC)
|
||||
|
||||
# sub-sampling
|
||||
codestream = jp2.get_codestream()
|
||||
|
|
@ -3523,7 +3537,7 @@ class TestSuite(unittest.TestCase):
|
|||
self.assertEqual(jp2.box[2].box[1].method, 1)
|
||||
self.assertEqual(jp2.box[2].box[1].precedence, 0)
|
||||
self.assertEqual(jp2.box[2].box[1].approximation, 1) # JPX exact?
|
||||
self.assertEqual(jp2.box[2].box[1].color_space, glymur.core.GREYSCALE)
|
||||
self.assertEqual(jp2.box[2].box[1].colorspace, glymur.core.GREYSCALE)
|
||||
|
||||
def test_NR_file5_dump(self):
|
||||
# Three 8-bit components in the ROMM-RGB colourspace, encapsulated in a
|
||||
|
|
@ -3566,7 +3580,7 @@ class TestSuite(unittest.TestCase):
|
|||
self.assertEqual(jp2.box[3].box[1].precedence, 0)
|
||||
self.assertEqual(jp2.box[3].box[1].approximation, 1) # JPX exact
|
||||
self.assertEqual(len(jp2.box[3].box[1].icc_profile), 546)
|
||||
self.assertIsNone(jp2.box[3].box[1].color_space)
|
||||
self.assertIsNone(jp2.box[3].box[1].colorspace)
|
||||
|
||||
# Jp2 Header
|
||||
# Colour specification
|
||||
|
|
@ -3574,7 +3588,7 @@ class TestSuite(unittest.TestCase):
|
|||
self.assertEqual(jp2.box[3].box[2].precedence, 1)
|
||||
self.assertEqual(jp2.box[3].box[2].approximation, 1) # JPX exact
|
||||
self.assertIsNone(jp2.box[3].box[2].icc_profile)
|
||||
self.assertEqual(jp2.box[3].box[2].color_space,
|
||||
self.assertEqual(jp2.box[3].box[2].colorspace,
|
||||
glymur.core.ROMM_RGB)
|
||||
|
||||
def test_NR_file6_dump(self):
|
||||
|
|
@ -3612,7 +3626,7 @@ class TestSuite(unittest.TestCase):
|
|||
self.assertEqual(jp2.box[2].box[1].precedence, 0)
|
||||
self.assertEqual(jp2.box[2].box[1].approximation, 1) # JPX exact
|
||||
self.assertIsNone(jp2.box[2].box[1].icc_profile)
|
||||
self.assertEqual(jp2.box[2].box[1].color_space,
|
||||
self.assertEqual(jp2.box[2].box[1].colorspace,
|
||||
glymur.core.GREYSCALE)
|
||||
|
||||
def test_NR_file7_dump(self):
|
||||
|
|
@ -3661,7 +3675,7 @@ class TestSuite(unittest.TestCase):
|
|||
self.assertEqual(jp2.box[3].box[1].precedence, 0)
|
||||
self.assertEqual(jp2.box[3].box[1].approximation, 1) # JPX exact
|
||||
self.assertEqual(len(jp2.box[3].box[1].icc_profile), 13332)
|
||||
self.assertIsNone(jp2.box[3].box[1].color_space)
|
||||
self.assertIsNone(jp2.box[3].box[1].colorspace)
|
||||
|
||||
# Jp2 Header
|
||||
# Colour specification
|
||||
|
|
@ -3669,7 +3683,7 @@ class TestSuite(unittest.TestCase):
|
|||
self.assertEqual(jp2.box[3].box[2].precedence, 1)
|
||||
self.assertEqual(jp2.box[3].box[2].approximation, 1) # JPX exact
|
||||
self.assertIsNone(jp2.box[3].box[2].icc_profile)
|
||||
self.assertEqual(jp2.box[3].box[2].color_space,
|
||||
self.assertEqual(jp2.box[3].box[2].colorspace,
|
||||
glymur.core.E_SRGB)
|
||||
|
||||
def test_NR_file8_dump(self):
|
||||
|
|
@ -3710,7 +3724,7 @@ class TestSuite(unittest.TestCase):
|
|||
self.assertEqual(jp2.box[2].box[1].precedence, 0)
|
||||
self.assertEqual(jp2.box[2].box[1].approximation, 1) # JPX exact
|
||||
self.assertEqual(len(jp2.box[2].box[1].icc_profile), 414)
|
||||
self.assertIsNone(jp2.box[2].box[1].color_space)
|
||||
self.assertIsNone(jp2.box[2].box[1].colorspace)
|
||||
|
||||
# XML box
|
||||
tags = [x.tag for x in jp2.box[3].xml]
|
||||
|
|
@ -3782,7 +3796,7 @@ class TestSuite(unittest.TestCase):
|
|||
self.assertEqual(jp2.box[2].box[3].precedence, 0)
|
||||
self.assertEqual(jp2.box[2].box[3].approximation, 1) # JPX exact
|
||||
self.assertIsNone(jp2.box[2].box[3].icc_profile)
|
||||
self.assertEqual(jp2.box[2].box[3].color_space, glymur.core.SRGB)
|
||||
self.assertEqual(jp2.box[2].box[3].colorspace, glymur.core.SRGB)
|
||||
|
||||
def test_NR_00042_j2k_dump(self):
|
||||
# Profile 3.
|
||||
|
|
@ -4313,6 +4327,7 @@ class TestSuite(unittest.TestCase):
|
|||
# Comment value
|
||||
self.assertEqual(c.segment[4].Ccme.decode('latin-1'), "Kakadu-v6.3.1")
|
||||
|
||||
@unittest.skip("fprintf stderr output in r2343.")
|
||||
def test_NR_illegalcolortransform_dump(self):
|
||||
jfile = os.path.join(data_root,
|
||||
'input/nonregression/illegalcolortransform.j2k')
|
||||
|
|
@ -5257,7 +5272,7 @@ class TestSuite(unittest.TestCase):
|
|||
self.assertEqual(jp2.box[2].box[1].method, 1)
|
||||
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].color_space, glymur.core.SRGB)
|
||||
self.assertEqual(jp2.box[2].box[1].colorspace, glymur.core.SRGB)
|
||||
|
||||
c = jp2.box[3].main_header
|
||||
|
||||
|
|
@ -5390,7 +5405,7 @@ class TestSuite(unittest.TestCase):
|
|||
self.assertEqual(jp2.box[2].box[1].method, 1)
|
||||
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].color_space, glymur.core.SRGB)
|
||||
self.assertEqual(jp2.box[2].box[1].colorspace, glymur.core.SRGB)
|
||||
|
||||
c = jp2.box[3].main_header
|
||||
|
||||
|
|
@ -5518,7 +5533,7 @@ class TestSuite(unittest.TestCase):
|
|||
self.assertEqual(jp2.box[2].box[1].method, 1)
|
||||
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].color_space, glymur.core.YCC)
|
||||
self.assertEqual(jp2.box[2].box[1].colorspace, glymur.core.YCC)
|
||||
|
||||
c = jp2.box[3].main_header
|
||||
|
||||
|
|
@ -5658,7 +5673,7 @@ class TestSuite(unittest.TestCase):
|
|||
self.assertEqual(jp2.box[3].box[1].method, 1) # enumerated
|
||||
self.assertEqual(jp2.box[3].box[1].precedence, 2)
|
||||
self.assertEqual(jp2.box[3].box[1].approximation, 1) # exact
|
||||
self.assertEqual(jp2.box[3].box[1].color_space, glymur.core.SRGB)
|
||||
self.assertEqual(jp2.box[3].box[1].colorspace, glymur.core.SRGB)
|
||||
|
||||
# Jp2 Header
|
||||
# Palette box.
|
||||
|
|
@ -5769,7 +5784,7 @@ class TestSuite(unittest.TestCase):
|
|||
self.assertEqual(jp2.box[2].box[1].method, 1)
|
||||
self.assertEqual(jp2.box[2].box[1].precedence, 0)
|
||||
self.assertEqual(jp2.box[2].box[1].approximation, 0)
|
||||
self.assertEqual(jp2.box[2].box[1].color_space, glymur.core.SRGB)
|
||||
self.assertEqual(jp2.box[2].box[1].colorspace, glymur.core.SRGB)
|
||||
|
||||
# Skip the 4th box, it is uknown.
|
||||
|
||||
|
|
@ -5869,7 +5884,7 @@ class TestSuite(unittest.TestCase):
|
|||
self.assertEqual(jp2.box[3].box[1].method, 1) # ICC
|
||||
self.assertEqual(jp2.box[3].box[1].precedence, 2)
|
||||
self.assertEqual(jp2.box[3].box[1].approximation, 1) # JPX exact
|
||||
self.assertEqual(jp2.box[3].box[1].color_space, glymur.core.SRGB)
|
||||
self.assertEqual(jp2.box[3].box[1].colorspace, glymur.core.SRGB)
|
||||
|
||||
c = jp2.box[4].main_header
|
||||
|
||||
|
|
@ -5966,7 +5981,7 @@ class TestSuite(unittest.TestCase):
|
|||
self.assertEqual(jp2.box[2].box[1].method, 1)
|
||||
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].color_space, glymur.core.GREYSCALE)
|
||||
self.assertEqual(jp2.box[2].box[1].colorspace, glymur.core.GREYSCALE)
|
||||
|
||||
# Jp2 Header
|
||||
# Channel Definition
|
||||
|
|
@ -6085,7 +6100,7 @@ class TestSuite(unittest.TestCase):
|
|||
self.assertEqual(jp2.box[3].box[1].method, 1) # enumerated
|
||||
self.assertEqual(jp2.box[3].box[1].precedence, 2)
|
||||
self.assertEqual(jp2.box[3].box[1].approximation, 1) # JPX exact
|
||||
self.assertEqual(jp2.box[3].box[1].color_space, glymur.core.CMYK)
|
||||
self.assertEqual(jp2.box[3].box[1].colorspace, glymur.core.CMYK)
|
||||
|
||||
# Jp2 Header
|
||||
# Palette box.
|
||||
|
|
@ -6199,7 +6214,7 @@ class TestSuite(unittest.TestCase):
|
|||
self.assertEqual(jp2.box[3].box[1].method, 1) # enumerated
|
||||
self.assertEqual(jp2.box[3].box[1].precedence, 2)
|
||||
self.assertEqual(jp2.box[3].box[1].approximation, 1) # JPX exact
|
||||
self.assertEqual(jp2.box[3].box[1].color_space, glymur.core.SRGB)
|
||||
self.assertEqual(jp2.box[3].box[1].colorspace, glymur.core.SRGB)
|
||||
|
||||
# Jp2 Header
|
||||
# Palette box.
|
||||
|
|
@ -6307,7 +6322,7 @@ class TestSuite(unittest.TestCase):
|
|||
self.assertEqual(jp2.box[2].box[1].method, 1)
|
||||
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].color_space, glymur.core.YCC)
|
||||
self.assertEqual(jp2.box[2].box[1].colorspace, glymur.core.YCC)
|
||||
|
||||
c = jp2.box[3].main_header
|
||||
|
||||
|
|
@ -6412,7 +6427,7 @@ class TestSuite(unittest.TestCase):
|
|||
self.assertEqual(jp2.box[2].box[1].precedence, 0)
|
||||
self.assertEqual(jp2.box[2].box[1].approximation, 0) # JP2
|
||||
self.assertEqual(len(jp2.box[2].box[1].icc_profile), 1)
|
||||
self.assertIsNone(jp2.box[2].box[1].color_space)
|
||||
self.assertIsNone(jp2.box[2].box[1].colorspace)
|
||||
|
||||
c = jp2.box[3].main_header
|
||||
|
||||
|
|
@ -6508,7 +6523,7 @@ class TestSuite(unittest.TestCase):
|
|||
self.assertEqual(jp2.box[2].box[1].precedence, 0)
|
||||
self.assertEqual(jp2.box[2].box[1].approximation, 0) # JP2
|
||||
self.assertEqual(len(jp2.box[2].box[1].icc_profile), 1)
|
||||
self.assertIsNone(jp2.box[2].box[1].color_space)
|
||||
self.assertIsNone(jp2.box[2].box[1].colorspace)
|
||||
|
||||
c = jp2.box[3].main_header
|
||||
|
||||
|
|
@ -6610,7 +6625,7 @@ class TestSuite(unittest.TestCase):
|
|||
self.assertEqual(jp2.box[3].box[1].precedence, 2)
|
||||
self.assertEqual(jp2.box[3].box[1].approximation, 1) # JPX exact
|
||||
self.assertEqual(len(jp2.box[3].box[1].icc_profile), 1328)
|
||||
self.assertIsNone(jp2.box[3].box[1].color_space)
|
||||
self.assertIsNone(jp2.box[3].box[1].colorspace)
|
||||
|
||||
# UUID boxes. All mentioned in the RREQ box.
|
||||
self.assertEqual(jp2.box[2].vendor_feature[0], jp2.box[4].uuid)
|
||||
|
|
@ -6690,6 +6705,7 @@ class TestSuite(unittest.TestCase):
|
|||
data = jp2.read()
|
||||
self.assertTrue(True)
|
||||
|
||||
@unittest.skip("fprintf stderr output in r2343.")
|
||||
def test_NR_DEC_123_j2c_3_decode(self):
|
||||
jfile = os.path.join(data_root,
|
||||
'input/nonregression/123.j2c')
|
||||
|
|
@ -6735,6 +6751,7 @@ class TestSuite(unittest.TestCase):
|
|||
data = Jp2k(jfile).read()
|
||||
self.assertTrue(True)
|
||||
|
||||
@unittest.skip("fprintf stderr output in r2343.")
|
||||
def test_NR_DEC_bug_j2c_8_decode(self):
|
||||
jfile = os.path.join(data_root,
|
||||
'input/nonregression/bug.j2c')
|
||||
|
|
@ -6771,6 +6788,7 @@ class TestSuite(unittest.TestCase):
|
|||
data = Jp2k(jfile).read()
|
||||
self.assertTrue(True)
|
||||
|
||||
@unittest.skip("fprintf stderr output in r2343.")
|
||||
def test_NR_DEC_illegalcolortransform_j2k_14_decode(self):
|
||||
# Stream too short, expected SOT.
|
||||
jfile = os.path.join(data_root,
|
||||
|
|
@ -7102,6 +7120,7 @@ class TestSuite(unittest.TestCase):
|
|||
odata = jp2k.read(reduce=1)
|
||||
np.testing.assert_array_equal(tdata, odata[64:128, 256:320])
|
||||
|
||||
@unittest.skip("fprintf stderr output in r2343.")
|
||||
def test_NR_DEC_p1_06_j2k_61_decode(self):
|
||||
jfile = os.path.join(data_root, 'input/conformance/p1_06.j2k')
|
||||
jp2k = Jp2k(jfile)
|
||||
|
|
@ -7109,6 +7128,7 @@ class TestSuite(unittest.TestCase):
|
|||
odata = jp2k.read()
|
||||
np.testing.assert_array_equal(ssdata, odata[0:12, 0:12])
|
||||
|
||||
@unittest.skip("fprintf stderr output in r2343.")
|
||||
def test_NR_DEC_p1_06_j2k_62_decode(self):
|
||||
jfile = os.path.join(data_root, 'input/conformance/p1_06.j2k')
|
||||
jp2k = Jp2k(jfile)
|
||||
|
|
@ -7116,6 +7136,7 @@ class TestSuite(unittest.TestCase):
|
|||
odata = jp2k.read()
|
||||
np.testing.assert_array_equal(ssdata, odata[1:8, 8:11])
|
||||
|
||||
@unittest.skip("fprintf stderr output in r2343.")
|
||||
def test_NR_DEC_p1_06_j2k_63_decode(self):
|
||||
jfile = os.path.join(data_root, 'input/conformance/p1_06.j2k')
|
||||
jp2k = Jp2k(jfile)
|
||||
|
|
@ -7123,6 +7144,7 @@ class TestSuite(unittest.TestCase):
|
|||
odata = jp2k.read()
|
||||
np.testing.assert_array_equal(ssdata, odata[9:12, 9:12])
|
||||
|
||||
@unittest.skip("fprintf stderr output in r2343.")
|
||||
def test_NR_DEC_p1_06_j2k_64_decode(self):
|
||||
jfile = os.path.join(data_root, 'input/conformance/p1_06.j2k')
|
||||
jp2k = Jp2k(jfile)
|
||||
|
|
@ -7130,6 +7152,7 @@ class TestSuite(unittest.TestCase):
|
|||
odata = jp2k.read()
|
||||
np.testing.assert_array_equal(ssdata, odata[10:12, 4:10])
|
||||
|
||||
@unittest.skip("fprintf stderr output in r2343.")
|
||||
def test_NR_DEC_p1_06_j2k_65_decode(self):
|
||||
jfile = os.path.join(data_root, 'input/conformance/p1_06.j2k')
|
||||
jp2k = Jp2k(jfile)
|
||||
|
|
@ -7137,6 +7160,7 @@ class TestSuite(unittest.TestCase):
|
|||
odata = jp2k.read()
|
||||
np.testing.assert_array_equal(ssdata, odata[3:9, 3:9])
|
||||
|
||||
@unittest.skip("fprintf stderr output in r2343.")
|
||||
def test_NR_DEC_p1_06_j2k_66_decode(self):
|
||||
jfile = os.path.join(data_root, 'input/conformance/p1_06.j2k')
|
||||
jp2k = Jp2k(jfile)
|
||||
|
|
@ -7144,6 +7168,7 @@ class TestSuite(unittest.TestCase):
|
|||
odata = jp2k.read()
|
||||
np.testing.assert_array_equal(ssdata, odata[4:7, 4:7])
|
||||
|
||||
@unittest.skip("fprintf stderr output in r2343.")
|
||||
def test_NR_DEC_p1_06_j2k_67_decode(self):
|
||||
jfile = os.path.join(data_root, 'input/conformance/p1_06.j2k')
|
||||
jp2k = Jp2k(jfile)
|
||||
|
|
@ -7151,6 +7176,7 @@ class TestSuite(unittest.TestCase):
|
|||
odata = jp2k.read()
|
||||
np.testing.assert_array_equal(ssdata, odata[4:5, 4: 5])
|
||||
|
||||
@unittest.skip("fprintf stderr output in r2343.")
|
||||
def test_NR_DEC_p1_06_j2k_68_decode(self):
|
||||
jfile = os.path.join(data_root, 'input/conformance/p1_06.j2k')
|
||||
jp2k = Jp2k(jfile)
|
||||
|
|
@ -7158,6 +7184,7 @@ class TestSuite(unittest.TestCase):
|
|||
odata = jp2k.read(reduce=1)
|
||||
np.testing.assert_array_equal(ssdata, odata[0:6, 0:6])
|
||||
|
||||
@unittest.skip("fprintf stderr output in r2343.")
|
||||
def test_NR_DEC_p1_06_j2k_69_decode(self):
|
||||
jfile = os.path.join(data_root, 'input/conformance/p1_06.j2k')
|
||||
jp2k = Jp2k(jfile)
|
||||
|
|
@ -7201,6 +7228,7 @@ class TestSuite(unittest.TestCase):
|
|||
with self.assertRaises((IOError, OSError)) as ce:
|
||||
ssdata = jp2k.read(area=(9, 9, 12, 12), reduce=2)
|
||||
|
||||
@unittest.skip("fprintf stderr output in r2343.")
|
||||
def test_NR_DEC_p1_06_j2k_76_decode(self):
|
||||
jfile = os.path.join(data_root, 'input/conformance/p1_06.j2k')
|
||||
jp2k = Jp2k(jfile)
|
||||
|
|
@ -7210,6 +7238,7 @@ class TestSuite(unittest.TestCase):
|
|||
tiledata = jp2k.read(tile=0)
|
||||
np.testing.assert_array_equal(tiledata, fulldata[0:3, 0:3])
|
||||
|
||||
@unittest.skip("fprintf stderr output in r2343.")
|
||||
def test_NR_DEC_p1_06_j2k_77_decode(self):
|
||||
jfile = os.path.join(data_root, 'input/conformance/p1_06.j2k')
|
||||
jp2k = Jp2k(jfile)
|
||||
|
|
@ -7219,6 +7248,7 @@ class TestSuite(unittest.TestCase):
|
|||
tiledata = jp2k.read(tile=5)
|
||||
np.testing.assert_array_equal(tiledata, fulldata[3:6, 3:6])
|
||||
|
||||
@unittest.skip("fprintf stderr output in r2343.")
|
||||
def test_NR_DEC_p1_06_j2k_78_decode(self):
|
||||
jfile = os.path.join(data_root, 'input/conformance/p1_06.j2k')
|
||||
jp2k = Jp2k(jfile)
|
||||
|
|
@ -7228,6 +7258,7 @@ class TestSuite(unittest.TestCase):
|
|||
tiledata = jp2k.read(tile=9)
|
||||
np.testing.assert_array_equal(tiledata, fulldata[6:9, 3:6])
|
||||
|
||||
@unittest.skip("fprintf stderr output in r2343.")
|
||||
def test_NR_DEC_p1_06_j2k_79_decode(self):
|
||||
jfile = os.path.join(data_root, 'input/conformance/p1_06.j2k')
|
||||
jp2k = Jp2k(jfile)
|
||||
|
|
@ -7237,6 +7268,7 @@ class TestSuite(unittest.TestCase):
|
|||
tiledata = jp2k.read(tile=15)
|
||||
np.testing.assert_array_equal(tiledata, fulldata[9:12, 9:12])
|
||||
|
||||
@unittest.skip("fprintf stderr output in r2343.")
|
||||
def test_NR_DEC_p1_06_j2k_80_decode(self):
|
||||
# Just read the data, don't bother verifying.
|
||||
jfile = os.path.join(data_root, 'input/conformance/p1_06.j2k')
|
||||
|
|
@ -7245,6 +7277,7 @@ class TestSuite(unittest.TestCase):
|
|||
warnings.simplefilter("ignore")
|
||||
tiledata = jp2k.read(tile=0, reduce=2)
|
||||
|
||||
@unittest.skip("fprintf stderr output in r2343.")
|
||||
def test_NR_DEC_p1_06_j2k_81_decode(self):
|
||||
# Just read the data, don't bother verifying.
|
||||
jfile = os.path.join(data_root, 'input/conformance/p1_06.j2k')
|
||||
|
|
@ -7253,6 +7286,7 @@ class TestSuite(unittest.TestCase):
|
|||
warnings.simplefilter("ignore")
|
||||
tiledata = jp2k.read(tile=5, reduce=2)
|
||||
|
||||
@unittest.skip("fprintf stderr output in r2343.")
|
||||
def test_NR_DEC_p1_06_j2k_82_decode(self):
|
||||
# Just read the data, don't bother verifying.
|
||||
jfile = os.path.join(data_root, 'input/conformance/p1_06.j2k')
|
||||
|
|
@ -7261,6 +7295,7 @@ class TestSuite(unittest.TestCase):
|
|||
warnings.simplefilter("ignore")
|
||||
tiledata = jp2k.read(tile=9, reduce=2)
|
||||
|
||||
@unittest.skip("fprintf stderr output in r2343.")
|
||||
def test_NR_DEC_p1_06_j2k_83_decode(self):
|
||||
# tile size is 3x3. Reducing two levels results in no data.
|
||||
jfile = os.path.join(data_root, 'input/conformance/p1_06.j2k')
|
||||
|
|
@ -7270,11 +7305,12 @@ class TestSuite(unittest.TestCase):
|
|||
with self.assertRaises((IOError, OSError)) as ce:
|
||||
tiledata = jp2k.read(tile=15, reduce=2)
|
||||
|
||||
@unittest.skip("fprintf stderr output in r2343.")
|
||||
def test_NR_DEC_p1_06_j2k_84_decode(self):
|
||||
# Just read the data, don't bother verifying.
|
||||
jfile = os.path.join(data_root, 'input/conformance/p1_06.j2k')
|
||||
jp2k = Jp2k(jfile)
|
||||
tiledata = jp2k.read(reduce=4)
|
||||
data = jp2k.read(reduce=4)
|
||||
|
||||
def test_NR_DEC_p0_04_j2k_85_decode(self):
|
||||
jfile = os.path.join(data_root, 'input/conformance/p0_04.j2k')
|
||||
|
|
|
|||
|
|
@ -9,6 +9,7 @@ import unittest
|
|||
import warnings
|
||||
|
||||
import numpy as np
|
||||
import pkg_resources
|
||||
|
||||
from ..lib import openjp2 as opj2
|
||||
|
||||
|
|
@ -62,7 +63,8 @@ def read_image(infile):
|
|||
class TestSuiteNegative(unittest.TestCase):
|
||||
|
||||
def setUp(self):
|
||||
pass
|
||||
self.jp2file = pkg_resources.resource_filename(glymur.__name__,
|
||||
"data/nemo.jp2")
|
||||
|
||||
def tearDown(self):
|
||||
pass
|
||||
|
|
@ -150,5 +152,35 @@ class TestSuiteNegative(unittest.TestCase):
|
|||
with self.assertWarns(UserWarning) as cw:
|
||||
j = Jp2k(infile)
|
||||
|
||||
def test_precinct_size_not_multiple_of_two(self):
|
||||
# Seems like precinct sizes should be powers of two.
|
||||
ifile = Jp2k(self.jp2file)
|
||||
data = ifile.read(reduce=3)
|
||||
with tempfile.NamedTemporaryFile(suffix='.jp2') as tfile:
|
||||
ofile = Jp2k(tfile.name, 'wb')
|
||||
with self.assertRaises(IOError) as ce:
|
||||
ofile.write(data, psizes=[(13, 13)])
|
||||
|
||||
def test_codeblock_size_not_multiple_of_two(self):
|
||||
# Seems like code block sizes should be powers of two.
|
||||
ifile = Jp2k(self.jp2file)
|
||||
data = ifile.read(reduce=3)
|
||||
with tempfile.NamedTemporaryFile(suffix='.jp2') as tfile:
|
||||
ofile = Jp2k(tfile.name, 'wb')
|
||||
with self.assertRaises(IOError) as ce:
|
||||
ofile.write(data, cbsize=(13, 12))
|
||||
|
||||
def test_codeblock_size_with_precinct_size(self):
|
||||
# Seems like code block sizes should never exceed half that of
|
||||
# precinct size.
|
||||
ifile = Jp2k(self.jp2file)
|
||||
data = ifile.read(reduce=3)
|
||||
with tempfile.NamedTemporaryFile(suffix='.jp2') as tfile:
|
||||
ofile = Jp2k(tfile.name, 'wb')
|
||||
with self.assertRaises(IOError) as ce:
|
||||
ofile.write(data,
|
||||
cbsize=(64, 64),
|
||||
psizes=[(64, 64)])
|
||||
|
||||
if __name__ == "__main__":
|
||||
unittest.main()
|
||||
|
|
|
|||
|
|
@ -693,7 +693,7 @@ class TestSuiteWrite(unittest.TestCase):
|
|||
self.assertEqual(jp2.box[2].box[1].precedence, 0)
|
||||
self.assertEqual(jp2.box[2].box[1].approximation, 0)
|
||||
self.assertIsNone(jp2.box[2].box[1].icc_profile)
|
||||
self.assertEqual(jp2.box[2].box[1].color_space, glymur.core.SRGB)
|
||||
self.assertEqual(jp2.box[2].box[1].colorspace, glymur.core.SRGB)
|
||||
|
||||
c = jp2.box[3].main_header
|
||||
|
||||
|
|
|
|||
|
|
@ -11,6 +11,7 @@ else:
|
|||
from io import StringIO
|
||||
|
||||
import glymur
|
||||
from glymur import Jp2k
|
||||
|
||||
try:
|
||||
data_root = os.environ['OPJ_DATA_ROOT']
|
||||
|
|
@ -22,6 +23,22 @@ except:
|
|||
|
||||
class TestPrinting(unittest.TestCase):
|
||||
|
||||
@classmethod
|
||||
def setUpClass(cls):
|
||||
# Setup a plain JP2 file without the two UUID boxes.
|
||||
jp2file = pkg_resources.resource_filename(glymur.__name__,
|
||||
"data/nemo.jp2")
|
||||
with tempfile.NamedTemporaryFile(suffix='.jp2', delete=False) as tfile:
|
||||
cls._plain_nemo_file = tfile.name
|
||||
ijfile = Jp2k(jp2file)
|
||||
data = ijfile.read(reduce=3)
|
||||
ojfile = Jp2k(cls._plain_nemo_file, 'wb')
|
||||
ojfile.write(data)
|
||||
|
||||
@classmethod
|
||||
def tearDownClass(cls):
|
||||
os.unlink(cls._plain_nemo_file)
|
||||
|
||||
def setUp(self):
|
||||
# Save sys.stdout.
|
||||
self.stdout = sys.stdout
|
||||
|
|
@ -30,15 +47,14 @@ class TestPrinting(unittest.TestCase):
|
|||
"data/nemo.jp2")
|
||||
|
||||
# Save the output of dumping nemo.jp2 for more than one test.
|
||||
lines = ['File: nemo.jp2',
|
||||
'JPEG 2000 Signature Box (jP ) @ (0, 12)',
|
||||
lines = ['JPEG 2000 Signature Box (jP ) @ (0, 12)',
|
||||
' Signature: 0d0a870a',
|
||||
'File Type Box (ftyp) @ (12, 20)',
|
||||
' Brand: jp2 ',
|
||||
" Compatibility: ['jp2 ']",
|
||||
'JP2 Header Box (jp2h) @ (32, 45)',
|
||||
' Image Header Box (ihdr) @ (40, 22)',
|
||||
' Size: [1456 2592 3]',
|
||||
' Size: [182 324 3]',
|
||||
' Bitdepth: 8',
|
||||
' Signed: False',
|
||||
' Compression: wavelet',
|
||||
|
|
@ -47,15 +63,15 @@ class TestPrinting(unittest.TestCase):
|
|||
' Method: enumerated colorspace',
|
||||
' Precedence: 0',
|
||||
' Colorspace: sRGB',
|
||||
'Contiguous Codestream Box (jp2c) @ (77, 1133427)',
|
||||
'Contiguous Codestream Box (jp2c) @ (77, 112814)',
|
||||
' Main header:',
|
||||
' SOC marker segment @ (85, 0)',
|
||||
' SIZ marker segment @ (87, 47)',
|
||||
' Profile: 2',
|
||||
' Reference Grid Height, Width: (1456 x 2592)',
|
||||
' Reference Grid Height, Width: (182 x 324)',
|
||||
' Vertical, Horizontal Reference Grid Offset: '
|
||||
+ '(0 x 0)',
|
||||
' Reference Tile Height, Width: (512 x 512)',
|
||||
' Reference Tile Height, Width: (182 x 324)',
|
||||
' Vertical, Horizontal Reference Tile Offset: '
|
||||
+ '(0 x 0)',
|
||||
' Bitdepth: (8, 8, 8)',
|
||||
|
|
@ -69,7 +85,7 @@ class TestPrinting(unittest.TestCase):
|
|||
' EPH marker segments: False',
|
||||
' Coding style parameters:',
|
||||
' Progression order: LRCP',
|
||||
' Number of layers: 3',
|
||||
' Number of layers: 1',
|
||||
' Multiple component transformation usage: '
|
||||
+ 'reversible',
|
||||
' Number of resolutions: 6',
|
||||
|
|
@ -93,16 +109,22 @@ class TestPrinting(unittest.TestCase):
|
|||
+ '(0, 10), (0, 9), (0, 9), (0, 10), (0, 9), (0, 9), '
|
||||
+ '(0, 10), (0, 9), (0, 9), (0, 10), (0, 9), (0, 9), '
|
||||
+ '(0, 10)]']
|
||||
self.expectedNemo = '\n'.join(lines)
|
||||
self.expectedPlain = '\n'.join(lines)
|
||||
|
||||
def tearDown(self):
|
||||
# Restore stdout.
|
||||
sys.stdout = self.stdout
|
||||
|
||||
def test_jp2dump(self):
|
||||
glymur.jp2dump(self.jp2file)
|
||||
glymur.jp2dump(self._plain_nemo_file)
|
||||
actual = sys.stdout.getvalue().strip()
|
||||
self.assertEqual(actual, self.expectedNemo)
|
||||
|
||||
# Get rid of the filename line, as it is not set in stone.
|
||||
lst = actual.split('\n')
|
||||
lst = lst[1:]
|
||||
actual = '\n'.join(lst)
|
||||
|
||||
self.assertEqual(actual, self.expectedPlain)
|
||||
|
||||
def test_COC_segment(self):
|
||||
j = glymur.Jp2k(self.jp2file)
|
||||
|
|
@ -110,7 +132,7 @@ class TestPrinting(unittest.TestCase):
|
|||
print(codestream.segment[5])
|
||||
actual = sys.stdout.getvalue().strip()
|
||||
|
||||
lines = ['COC marker segment @ (183, 9)',
|
||||
lines = ['COC marker segment @ (3233, 9)',
|
||||
' Associated component: 1',
|
||||
' Coding style for this component: '
|
||||
+ 'Entropy coder, PARTITION = 0',
|
||||
|
|
@ -136,7 +158,7 @@ class TestPrinting(unittest.TestCase):
|
|||
print(codestream.segment[2])
|
||||
actual = sys.stdout.getvalue().strip()
|
||||
|
||||
lines = ['COD marker segment @ (136, 12)',
|
||||
lines = ['COD marker segment @ (3186, 12)',
|
||||
' Coding style:',
|
||||
' Entropy coder, without partitions',
|
||||
' SOP marker segments: False',
|
||||
|
|
@ -226,7 +248,7 @@ class TestPrinting(unittest.TestCase):
|
|||
print(codestream.segment[-1])
|
||||
actual = sys.stdout.getvalue().strip()
|
||||
|
||||
lines = ['EOC marker segment @ (1133502, 0)']
|
||||
lines = ['EOC marker segment @ (1136552, 0)']
|
||||
expected = '\n'.join(lines)
|
||||
self.assertEqual(actual, expected)
|
||||
|
||||
|
|
@ -313,7 +335,7 @@ class TestPrinting(unittest.TestCase):
|
|||
print(codestream.segment[6])
|
||||
actual = sys.stdout.getvalue().strip()
|
||||
|
||||
lines = ['QCC marker segment @ (194, 20)',
|
||||
lines = ['QCC marker segment @ (3244, 20)',
|
||||
' Associated Component: 1',
|
||||
' Quantization style: no quantization, 2 guard bits',
|
||||
' Step size: [(0, 8), (0, 9), (0, 9), (0, 10), (0, 9), '
|
||||
|
|
@ -329,7 +351,7 @@ class TestPrinting(unittest.TestCase):
|
|||
print(codestream.segment[3])
|
||||
actual = sys.stdout.getvalue().strip()
|
||||
|
||||
lines = ['QCD marker segment @ (150, 19)',
|
||||
lines = ['QCD marker segment @ (3200, 19)',
|
||||
' Quantization style: no quantization, 2 guard bits',
|
||||
' Step size: [(0, 8), (0, 9), (0, 9), (0, 10), (0, 9), '
|
||||
+ '(0, 9), (0, 10), (0, 9), (0, 9), (0, 10), (0, 9), '
|
||||
|
|
@ -344,7 +366,7 @@ class TestPrinting(unittest.TestCase):
|
|||
print(codestream.segment[1])
|
||||
actual = sys.stdout.getvalue().strip()
|
||||
|
||||
lines = ['SIZ marker segment @ (87, 47)',
|
||||
lines = ['SIZ marker segment @ (3137, 47)',
|
||||
' Profile: 2',
|
||||
' Reference Grid Height, Width: (1456 x 2592)',
|
||||
' Vertical, Horizontal Reference Grid Offset: (0 x 0)',
|
||||
|
|
@ -364,7 +386,7 @@ class TestPrinting(unittest.TestCase):
|
|||
print(codestream.segment[0])
|
||||
actual = sys.stdout.getvalue().strip()
|
||||
|
||||
lines = ['SOC marker segment @ (85, 0)']
|
||||
lines = ['SOC marker segment @ (3135, 0)']
|
||||
expected = '\n'.join(lines)
|
||||
self.assertEqual(actual, expected)
|
||||
|
||||
|
|
@ -374,7 +396,7 @@ class TestPrinting(unittest.TestCase):
|
|||
print(codestream.segment[9])
|
||||
actual = sys.stdout.getvalue().strip()
|
||||
|
||||
lines = ['SOD marker segment @ (249, 0)']
|
||||
lines = ['SOD marker segment @ (3299, 0)']
|
||||
expected = '\n'.join(lines)
|
||||
self.assertEqual(actual, expected)
|
||||
|
||||
|
|
@ -384,7 +406,7 @@ class TestPrinting(unittest.TestCase):
|
|||
print(codestream.segment[4])
|
||||
actual = sys.stdout.getvalue().strip()
|
||||
|
||||
lines = ['SOT marker segment @ (171, 10)',
|
||||
lines = ['SOT marker segment @ (3221, 10)',
|
||||
' Tile part index: 0',
|
||||
' Tile part length: 78629',
|
||||
' Tile part instance: 0',
|
||||
|
|
@ -410,20 +432,45 @@ class TestPrinting(unittest.TestCase):
|
|||
expected = '\n'.join(lines)
|
||||
self.assertEqual(actual, expected)
|
||||
|
||||
def test_entire_file(self):
|
||||
def test_xmp(self):
|
||||
# Verify the printing of a UUID/XMP box.
|
||||
j = glymur.Jp2k(self.jp2file)
|
||||
print(j.box[4])
|
||||
actual = sys.stdout.getvalue().strip()
|
||||
lst = ['UUID Box (uuid) @ (715, 2412)',
|
||||
' UUID: be7acfcb-97a9-42e8-9c71-999491e3afac (XMP)',
|
||||
' UUID Data: ',
|
||||
' <ns0:xmpmeta xmlns:ns0="adobe:ns:meta/" '
|
||||
+ 'xmlns:ns2="http://ns.adobe.com/xap/1.0/" '
|
||||
+ 'xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" '
|
||||
+ 'ns0:xmptk="XMP Core 4.4.0-Exiv2">',
|
||||
' <rdf:RDF>',
|
||||
' <rdf:Description ns2:CreatorTool="glymur" '
|
||||
+ 'rdf:about="" />',
|
||||
' </rdf:RDF>',
|
||||
' </ns0:xmpmeta>']
|
||||
expected = '\n'.join(lst)
|
||||
self.assertEqual(actual, expected)
|
||||
|
||||
def test_entire_file(self):
|
||||
j = glymur.Jp2k(self._plain_nemo_file)
|
||||
print(j)
|
||||
actual = sys.stdout.getvalue().strip()
|
||||
self.assertEqual(actual, self.expectedNemo)
|
||||
|
||||
# Get rid of the filename line, as it is not set in stone.
|
||||
lst = actual.split('\n')
|
||||
lst = lst[1:]
|
||||
actual = '\n'.join(lst)
|
||||
|
||||
self.assertEqual(actual, self.expectedPlain)
|
||||
|
||||
def test_codestream(self):
|
||||
j = glymur.Jp2k(self.jp2file)
|
||||
print(j.get_codestream())
|
||||
actual = sys.stdout.getvalue().strip()
|
||||
|
||||
lst = ['Codestream:',
|
||||
' SOC marker segment @ (85, 0)',
|
||||
' SIZ marker segment @ (87, 47)',
|
||||
' SOC marker segment @ (3135, 0)',
|
||||
' SIZ marker segment @ (3137, 47)',
|
||||
' Profile: 2',
|
||||
' Reference Grid Height, Width: (1456 x 2592)',
|
||||
' Vertical, Horizontal Reference Grid Offset: (0 x 0)',
|
||||
|
|
@ -433,7 +480,7 @@ class TestPrinting(unittest.TestCase):
|
|||
' Signed: (False, False, False)',
|
||||
' Vertical, Horizontal Subsampling: '
|
||||
+ '((1, 1), (1, 1), (1, 1))',
|
||||
' COD marker segment @ (136, 12)',
|
||||
' COD marker segment @ (3186, 12)',
|
||||
' Coding style:',
|
||||
' Entropy coder, without partitions',
|
||||
' SOP marker segments: False',
|
||||
|
|
@ -455,7 +502,7 @@ class TestPrinting(unittest.TestCase):
|
|||
' Vertically stripe causal context: False',
|
||||
' Predictable termination: False',
|
||||
' Segmentation symbols: False',
|
||||
' QCD marker segment @ (150, 19)',
|
||||
' QCD marker segment @ (3200, 19)',
|
||||
' Quantization style: no quantization, '
|
||||
+ '2 guard bits',
|
||||
' Step size: [(0, 8), (0, 9), (0, 9), '
|
||||
|
|
@ -642,6 +689,7 @@ class TestPrinting(unittest.TestCase):
|
|||
|
||||
# Now append the codestream.
|
||||
tfile2.write(codestream)
|
||||
tfile2.flush()
|
||||
|
||||
jasoc = glymur.Jp2k(tfile2.name)
|
||||
print(jasoc.box[3])
|
||||
|
|
@ -763,5 +811,63 @@ class TestPrinting(unittest.TestCase):
|
|||
expected = '\n'.join(lines)
|
||||
self.assertEqual(actual, expected)
|
||||
|
||||
def test_exif_uuid(self):
|
||||
j = glymur.Jp2k(self.jp2file)
|
||||
|
||||
print(j.box[3])
|
||||
actual = sys.stdout.getvalue().strip()
|
||||
|
||||
lines = ["UUID Box (uuid) @ (77, 638)",
|
||||
" UUID: 4a706754-6966-6645-7869-662d3e4a5032 (Exif)",
|
||||
" UUID Data: ",
|
||||
"{'Exif': {'ExifTag': 138,",
|
||||
" 'GPSTag': 354,",
|
||||
" 'Make': 'HTC',",
|
||||
" 'Model': 'HTC Glacier',",
|
||||
" 'ResolutionUnit': 2,",
|
||||
" 'XResolution': 72.0,",
|
||||
" 'YCbCrPositioning': 1,",
|
||||
" 'YResolution': 72.0},",
|
||||
" 'GPSInfo': {'GPSAltitude': 0.0,",
|
||||
" 'GPSAltitudeRef': 0,",
|
||||
" 'GPSDateStamp': '2013:02:09',",
|
||||
" 'GPSLatitude': [42.0, 20.0, 33.61],",
|
||||
" 'GPSLatitudeRef': 'N',",
|
||||
" 'GPSLongitude': [71.0, 5.0, 17.32],",
|
||||
" 'GPSLongitudeRef': 'W',",
|
||||
" 'GPSMapDatum': 'WGS-84',",
|
||||
" 'GPSProcessingMethod': (65,",
|
||||
" 83,",
|
||||
" 67,",
|
||||
" 73,",
|
||||
" 73,",
|
||||
" 0,",
|
||||
" 0,",
|
||||
" 0,",
|
||||
" 78,",
|
||||
" 69,",
|
||||
" 84,",
|
||||
" 87,",
|
||||
" 79,",
|
||||
" 82,",
|
||||
" 75),",
|
||||
" 'GPSTimeStamp': [19.0, 47.0, 53.0],",
|
||||
" 'GPSVersionID': (2, 2, 0)},",
|
||||
" 'Iop': None,",
|
||||
" 'Photo': {'ColorSpace': 1,",
|
||||
" 'ComponentsConfiguration': (1, 2, 3, 0),",
|
||||
" 'DateTimeDigitized': '2013:02:09 14:47:53',",
|
||||
" 'DateTimeOriginal': '2013:02:09 14:47:53',",
|
||||
" 'ExifVersion': (48, 50, 50, 48),",
|
||||
" 'FlashpixVersion': (48, 49, 48, 48),",
|
||||
" 'FocalLength': 3.53,",
|
||||
" 'ISOSpeedRatings': 76,",
|
||||
" 'InteroperabilityTag': 324,",
|
||||
" 'PixelXDimension': 2528,",
|
||||
" 'PixelYDimension': 1424}}"]
|
||||
|
||||
expected = '\n'.join(lines)
|
||||
self.assertEqual(actual, expected)
|
||||
|
||||
if __name__ == "__main__":
|
||||
unittest.main()
|
||||
|
|
|
|||
12
setup.py
12
setup.py
|
|
@ -1,9 +1,9 @@
|
|||
from distutils.core import setup
|
||||
|
||||
kwargs = {'name': 'glymur',
|
||||
'version': '0.1.1',
|
||||
'description': 'Tools for manipulating JPEG2000 files',
|
||||
'long_description': open('README').read(),
|
||||
kwargs = {'name': 'Glymur',
|
||||
'version': '0.1.6',
|
||||
'description': 'Tools for accessing JPEG2000 files',
|
||||
'long_description': open('README.md').read(),
|
||||
'author': 'John Evans',
|
||||
'author_email': 'johnevans938 at gmail dot com',
|
||||
'url': 'https://github.com/quintusdias/glymur',
|
||||
|
|
@ -18,10 +18,10 @@ clssfrs = ["Programming Language :: Python",
|
|||
"Programming Language :: Python :: 3.3",
|
||||
"Programming Language :: Python :: Implementation :: CPython",
|
||||
"License :: OSI Approved :: MIT License",
|
||||
"Development Status :: 1 - Alpha",
|
||||
"Development Status :: 3 - Alpha",
|
||||
"Operating System :: MacOS",
|
||||
"Operating System :: POSIX :: Linux",
|
||||
"Intended Audience :: Scientific/Research",
|
||||
"Intended Audience :: Science/Research",
|
||||
"Intended Audience :: Information Technology",
|
||||
"Topic :: Software Development :: Libraries :: Python Modules"]
|
||||
kwargs['classifiers'] = clssfrs
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue