Compare commits
101 commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
f3db36017c | ||
|
|
3c7205038f | ||
|
|
2ffdf716c0 | ||
|
|
7b1522bb0e | ||
|
|
8cc1155252 | ||
|
|
1bfb2f5fc8 | ||
|
|
4686c40c57 | ||
|
|
05e343b2e4 | ||
|
|
4d680cf90b | ||
|
|
bd3f491e20 | ||
|
|
059bee50e2 | ||
|
|
4ceb4dce61 | ||
|
|
a24bff0af1 | ||
|
|
fe5e784b58 | ||
|
|
a131d83d48 | ||
|
|
aeec03c829 | ||
|
|
7dfcc0fd7c | ||
|
|
2755e8edd4 | ||
|
|
e2465c5c73 | ||
|
|
e93392a10e | ||
|
|
dc2b2bda15 | ||
|
|
c23fe48815 | ||
|
|
43da1824b6 | ||
|
|
48fdceda52 | ||
|
|
a921b1101d | ||
|
|
0ce15e93c4 | ||
|
|
80f696c600 | ||
|
|
3eae87543c | ||
|
|
3e723605b9 | ||
|
|
398125b1aa | ||
|
|
acf6b28bc9 | ||
|
|
6572fd8772 | ||
|
|
8440d69222 | ||
|
|
c16ecd7ae9 | ||
|
|
20f2c0c291 | ||
|
|
671bd88910 | ||
|
|
6f697526f2 | ||
|
|
13cc6aa7e5 | ||
|
|
02ff730784 | ||
|
|
39cc8a845a | ||
|
|
4a4f1f5738 | ||
|
|
4527c774fa | ||
|
|
c39661b586 | ||
|
|
5541fb6465 | ||
|
|
6a59e38aed | ||
|
|
0889d8999b | ||
|
|
03cb19d22b | ||
|
|
7cdc5c6828 | ||
|
|
eeee8ae9dc | ||
|
|
7633572b49 | ||
|
|
6ffd229512 | ||
|
|
1f0d0c3786 | ||
|
|
24ba8c1df8 | ||
|
|
1782cb957f | ||
|
|
73f2257d92 | ||
|
|
a713d44238 | ||
|
|
3e411ab5e1 | ||
|
|
aef47ed318 | ||
|
|
4aad8cd306 | ||
|
|
4ffb46833f | ||
|
|
41eaec6464 | ||
|
|
351ae294d6 | ||
|
|
fa23fddfd8 | ||
|
|
5c262025b3 | ||
|
|
34092dff5b | ||
|
|
d36f521b61 | ||
|
|
87c9aeedd9 | ||
|
|
5aac625981 | ||
|
|
9a6a5affb7 | ||
|
|
954e86a2ab | ||
|
|
cad26a2d88 | ||
|
|
61cafc00b8 | ||
|
|
22725b94b3 | ||
|
|
b9e44a4f8a | ||
|
|
529dc50465 | ||
|
|
fc4f5cec80 | ||
|
|
08ef7846bb | ||
|
|
1c87d982f8 | ||
|
|
689cedfa78 | ||
|
|
da25953de3 | ||
|
|
c1bb57f086 | ||
|
|
ad42363586 | ||
|
|
1211c83df2 | ||
|
|
3636939c12 | ||
|
|
84b0d4360e | ||
|
|
ff849df520 | ||
|
|
185f4da073 | ||
|
|
25d19226d2 | ||
|
|
5de1b8b240 | ||
|
|
dba289677d | ||
|
|
60dcdfe9c5 | ||
|
|
19b0533764 | ||
|
|
41252f54de | ||
|
|
ac019b32f7 | ||
|
|
378cab4350 | ||
|
|
6b7a3be5de | ||
|
|
f36c169f52 | ||
|
|
55acd9260c | ||
|
|
b500287700 | ||
|
|
944bf95d45 | ||
|
|
edde7d36b1 |
45 changed files with 3502 additions and 3609 deletions
|
|
@ -1,3 +1,8 @@
|
||||||
|
Jan 10, 2015 - v0.8.0 Reduced number of steps required for writing
|
||||||
|
images. Deprecated old read and write methods in favor of
|
||||||
|
array-style slicing. Added ignore_pclr_cmap_cdef, verbose,
|
||||||
|
shape, codestream, layer properties.
|
||||||
|
|
||||||
Oct 06, 2014 - v0.7.2 Added ellipsis support in array-style slicing.
|
Oct 06, 2014 - v0.7.2 Added ellipsis support in array-style slicing.
|
||||||
|
|
||||||
Oct 02, 2014 - v0.7.1 Fixed README to mention Python 3.4
|
Oct 02, 2014 - v0.7.1 Fixed README to mention Python 3.4
|
||||||
|
|
|
||||||
|
|
@ -1,116 +0,0 @@
|
||||||
---
|
|
||||||
API
|
|
||||||
---
|
|
||||||
|
|
||||||
Jp2k
|
|
||||||
----
|
|
||||||
.. autoclass:: glymur.Jp2k
|
|
||||||
:members: read, write, wrap, read_bands, get_codestream
|
|
||||||
|
|
||||||
Individual Boxes
|
|
||||||
----------------
|
|
||||||
Jp2kbox
|
|
||||||
'''''''
|
|
||||||
.. autoclass:: glymur.jp2box.Jp2kBox
|
|
||||||
:members:
|
|
||||||
|
|
||||||
AssociationBox
|
|
||||||
''''''''''''''
|
|
||||||
.. autoclass:: glymur.jp2box.AssociationBox
|
|
||||||
:members:
|
|
||||||
|
|
||||||
ColourSpecificationBox
|
|
||||||
''''''''''''''''''''''
|
|
||||||
.. autoclass:: glymur.jp2box.ColourSpecificationBox
|
|
||||||
:members:
|
|
||||||
|
|
||||||
ChannelDefinitionBox
|
|
||||||
''''''''''''''''''''''
|
|
||||||
.. autoclass:: glymur.jp2box.ChannelDefinitionBox
|
|
||||||
: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:
|
|
||||||
|
|
||||||
|
|
@ -13,7 +13,6 @@
|
||||||
# serve to show the default.
|
# serve to show the default.
|
||||||
|
|
||||||
import sys
|
import sys
|
||||||
import os
|
|
||||||
|
|
||||||
|
|
||||||
class Mock(object):
|
class Mock(object):
|
||||||
|
|
@ -42,12 +41,12 @@ for mod_name in MOCK_MODULES:
|
||||||
# If extensions (or modules to document with autodoc) are in another directory,
|
# If extensions (or modules to document with autodoc) are in another directory,
|
||||||
# add these directories to sys.path here. If the directory is relative to the
|
# add these directories to sys.path here. If the directory is relative to the
|
||||||
# documentation root, use os.path.abspath to make it absolute, like shown here.
|
# documentation root, use os.path.abspath to make it absolute, like shown here.
|
||||||
#sys.path.insert(0, os.path.abspath('.'))
|
# sys.path.insert(0, os.path.abspath('.'))
|
||||||
|
|
||||||
# -- General configuration ----------------------------------------------------
|
# -- General configuration ----------------------------------------------------
|
||||||
|
|
||||||
# If your documentation needs a minimal Sphinx version, state it here.
|
# If your documentation needs a minimal Sphinx version, state it here.
|
||||||
#needs_sphinx = '1.0'
|
# needs_sphinx = '1.0'
|
||||||
|
|
||||||
# Add any Sphinx extension module names here, as strings. They can be
|
# Add any Sphinx extension module names here, as strings. They can be
|
||||||
# extensions coming with Sphinx (named 'sphinx.ext.*') or your custom ones.
|
# extensions coming with Sphinx (named 'sphinx.ext.*') or your custom ones.
|
||||||
|
|
@ -62,7 +61,7 @@ templates_path = ['_templates']
|
||||||
source_suffix = '.rst'
|
source_suffix = '.rst'
|
||||||
|
|
||||||
# The encoding of source files.
|
# The encoding of source files.
|
||||||
#source_encoding = 'utf-8-sig'
|
# source_encoding = 'utf-8-sig'
|
||||||
|
|
||||||
# The master toctree document.
|
# The master toctree document.
|
||||||
master_doc = 'index'
|
master_doc = 'index'
|
||||||
|
|
@ -76,19 +75,19 @@ copyright = u'2013, John Evans'
|
||||||
# built documents.
|
# built documents.
|
||||||
#
|
#
|
||||||
# The short X.Y version.
|
# The short X.Y version.
|
||||||
version = '0.7'
|
version = '0.8'
|
||||||
# The full version, including alpha/beta/rc tags.
|
# The full version, including alpha/beta/rc tags.
|
||||||
release = '0.7.2'
|
release = '0.8.0'
|
||||||
|
|
||||||
# The language for content autogenerated by Sphinx. Refer to documentation
|
# The language for content autogenerated by Sphinx. Refer to documentation
|
||||||
# for a list of supported languages.
|
# for a list of supported languages.
|
||||||
#language = None
|
# language = None
|
||||||
|
|
||||||
# There are two options for replacing |today|: either, you set today to some
|
# There are two options for replacing |today|: either, you set today to some
|
||||||
# non-false value, then it is used:
|
# non-false value, then it is used:
|
||||||
#today = ''
|
# today = ''
|
||||||
# Else, today_fmt is used as the format for a strftime call.
|
# Else, today_fmt is used as the format for a strftime call.
|
||||||
#today_fmt = '%B %d, %Y'
|
# today_fmt = '%B %d, %Y'
|
||||||
|
|
||||||
# List of patterns, relative to source directory, that match files and
|
# List of patterns, relative to source directory, that match files and
|
||||||
# directories to ignore when looking for source files.
|
# directories to ignore when looking for source files.
|
||||||
|
|
@ -96,24 +95,24 @@ exclude_patterns = []
|
||||||
|
|
||||||
# The reST default role (used for this markup: `text`) to use for all
|
# The reST default role (used for this markup: `text`) to use for all
|
||||||
# documents.
|
# documents.
|
||||||
#default_role = None
|
# default_role = None
|
||||||
|
|
||||||
# If true, '()' will be appended to :func: etc. cross-reference text.
|
# If true, '()' will be appended to :func: etc. cross-reference text.
|
||||||
#add_function_parentheses = True
|
# add_function_parentheses = True
|
||||||
|
|
||||||
# If true, the current module name will be prepended to all description
|
# If true, the current module name will be prepended to all description
|
||||||
# unit titles (such as .. function::).
|
# unit titles (such as .. function::).
|
||||||
#add_module_names = True
|
# add_module_names = True
|
||||||
|
|
||||||
# If true, sectionauthor and moduleauthor directives will be shown in the
|
# If true, sectionauthor and moduleauthor directives will be shown in the
|
||||||
# output. They are ignored by default.
|
# output. They are ignored by default.
|
||||||
#show_authors = False
|
# show_authors = False
|
||||||
|
|
||||||
# The name of the Pygments (syntax highlighting) style to use.
|
# The name of the Pygments (syntax highlighting) style to use.
|
||||||
pygments_style = 'sphinx'
|
pygments_style = 'sphinx'
|
||||||
|
|
||||||
# A list of ignored prefixes for module index sorting.
|
# A list of ignored prefixes for module index sorting.
|
||||||
#modindex_common_prefix = []
|
# modindex_common_prefix = []
|
||||||
|
|
||||||
|
|
||||||
# -- Options for HTML output --------------------------------------------------
|
# -- Options for HTML output --------------------------------------------------
|
||||||
|
|
@ -125,26 +124,26 @@ html_theme = 'default'
|
||||||
# Theme options are theme-specific and customize the look and feel of a theme
|
# Theme options are theme-specific and customize the look and feel of a theme
|
||||||
# further. For a list of options available for each theme, see the
|
# further. For a list of options available for each theme, see the
|
||||||
# documentation.
|
# documentation.
|
||||||
#html_theme_options = {}
|
# html_theme_options = {}
|
||||||
|
|
||||||
# Add any paths that contain custom themes here, relative to this directory.
|
# Add any paths that contain custom themes here, relative to this directory.
|
||||||
#html_theme_path = []
|
# html_theme_path = []
|
||||||
|
|
||||||
# The name for this set of Sphinx documents. If None, it defaults to
|
# The name for this set of Sphinx documents. If None, it defaults to
|
||||||
# "<project> v<release> documentation".
|
# "<project> v<release> documentation".
|
||||||
#html_title = None
|
# html_title = None
|
||||||
|
|
||||||
# A shorter title for the navigation bar. Default is the same as html_title.
|
# A shorter title for the navigation bar. Default is the same as html_title.
|
||||||
#html_short_title = None
|
# html_short_title = None
|
||||||
|
|
||||||
# The name of an image file (relative to this directory) to place at the top
|
# The name of an image file (relative to this directory) to place at the top
|
||||||
# of the sidebar.
|
# of the sidebar.
|
||||||
#html_logo = None
|
# html_logo = None
|
||||||
|
|
||||||
# The name of an image file (within the static path) to use as favicon of the
|
# The name of an image file (within the static path) to use as favicon of the
|
||||||
# docs. This file should be a Windows icon file (.ico) being 16x16 or 32x32
|
# docs. This file should be a Windows icon file (.ico) being 16x16 or 32x32
|
||||||
# pixels large.
|
# pixels large.
|
||||||
#html_favicon = None
|
# html_favicon = None
|
||||||
|
|
||||||
# Add any paths that contain custom static files (such as style sheets) here,
|
# Add any paths that contain custom static files (such as style sheets) here,
|
||||||
# relative to this directory. They are copied after the builtin static files,
|
# relative to this directory. They are copied after the builtin static files,
|
||||||
|
|
@ -153,44 +152,44 @@ html_static_path = ['_static']
|
||||||
|
|
||||||
# If not '', a 'Last updated on:' timestamp is inserted at every page bottom,
|
# If not '', a 'Last updated on:' timestamp is inserted at every page bottom,
|
||||||
# using the given strftime format.
|
# using the given strftime format.
|
||||||
#html_last_updated_fmt = '%b %d, %Y'
|
# html_last_updated_fmt = '%b %d, %Y'
|
||||||
|
|
||||||
# If true, SmartyPants will be used to convert quotes and dashes to
|
# If true, SmartyPants will be used to convert quotes and dashes to
|
||||||
# typographically correct entities.
|
# typographically correct entities.
|
||||||
#html_use_smartypants = True
|
# html_use_smartypants = True
|
||||||
|
|
||||||
# Custom sidebar templates, maps document names to template names.
|
# Custom sidebar templates, maps document names to template names.
|
||||||
#html_sidebars = {}
|
# html_sidebars = {}
|
||||||
|
|
||||||
# Additional templates that should be rendered to pages, maps page names to
|
# Additional templates that should be rendered to pages, maps page names to
|
||||||
# template names.
|
# template names.
|
||||||
#html_additional_pages = {}
|
# html_additional_pages = {}
|
||||||
|
|
||||||
# If false, no module index is generated.
|
# If false, no module index is generated.
|
||||||
#html_domain_indices = True
|
# html_domain_indices = True
|
||||||
|
|
||||||
# If false, no index is generated.
|
# If false, no index is generated.
|
||||||
#html_use_index = True
|
# html_use_index = True
|
||||||
|
|
||||||
# If true, the index is split into individual pages for each letter.
|
# If true, the index is split into individual pages for each letter.
|
||||||
#html_split_index = False
|
# html_split_index = False
|
||||||
|
|
||||||
# If true, links to the reST sources are added to the pages.
|
# If true, links to the reST sources are added to the pages.
|
||||||
html_show_sourcelink = True
|
html_show_sourcelink = True
|
||||||
|
|
||||||
# If true, "Created using Sphinx" is shown in the HTML footer. Default is True.
|
# If true, "Created using Sphinx" is shown in the HTML footer. Default is True.
|
||||||
#html_show_sphinx = True
|
# html_show_sphinx = True
|
||||||
|
|
||||||
# If true, "(C) Copyright ..." is shown in the HTML footer. Default is True.
|
# If true, "(C) Copyright ..." is shown in the HTML footer. Default is True.
|
||||||
#html_show_copyright = True
|
# html_show_copyright = True
|
||||||
|
|
||||||
# If true, an OpenSearch description file will be output, and all pages will
|
# If true, an OpenSearch description file will be output, and all pages will
|
||||||
# contain a <link> tag referring to it. The value of this option must be the
|
# contain a <link> tag referring to it. The value of this option must be the
|
||||||
# base URL from which the finished HTML is served.
|
# base URL from which the finished HTML is served.
|
||||||
#html_use_opensearch = ''
|
# html_use_opensearch = ''
|
||||||
|
|
||||||
# This is the file name suffix for HTML files (e.g. ".xhtml").
|
# This is the file name suffix for HTML files (e.g. ".xhtml").
|
||||||
#html_file_suffix = None
|
# html_file_suffix = None
|
||||||
|
|
||||||
# Output file base name for HTML help builder.
|
# Output file base name for HTML help builder.
|
||||||
htmlhelp_basename = 'glymurdoc'
|
htmlhelp_basename = 'glymurdoc'
|
||||||
|
|
@ -199,13 +198,13 @@ htmlhelp_basename = 'glymurdoc'
|
||||||
# -- Options for LaTeX output -------------------------------------------------
|
# -- Options for LaTeX output -------------------------------------------------
|
||||||
|
|
||||||
# The paper size ('letterpaper' or 'a4paper').
|
# The paper size ('letterpaper' or 'a4paper').
|
||||||
#'papersize': 'letterpaper',
|
# 'papersize': 'letterpaper',
|
||||||
|
|
||||||
# The font size ('10pt', '11pt' or '12pt').
|
# The font size ('10pt', '11pt' or '12pt').
|
||||||
#'pointsize': '10pt',
|
# 'pointsize': '10pt',
|
||||||
|
|
||||||
# Additional stuff for the LaTeX preamble.
|
# Additional stuff for the LaTeX preamble.
|
||||||
#'preamble': '',
|
# 'preamble': '',
|
||||||
latex_elements = {}
|
latex_elements = {}
|
||||||
|
|
||||||
# Grouping the document tree into LaTeX files. List of tuples
|
# Grouping the document tree into LaTeX files. List of tuples
|
||||||
|
|
@ -216,23 +215,23 @@ latex_documents = [('index', 'glymur.tex', u'glymur Documentation',
|
||||||
|
|
||||||
# The name of an image file (relative to this directory) to place at the top of
|
# The name of an image file (relative to this directory) to place at the top of
|
||||||
# the title page.
|
# the title page.
|
||||||
#latex_logo = None
|
# latex_logo = None
|
||||||
|
|
||||||
# For "manual" documents, if this is true, then toplevel headings are parts,
|
# For "manual" documents, if this is true, then toplevel headings are parts,
|
||||||
# not chapters.
|
# not chapters.
|
||||||
#latex_use_parts = False
|
# latex_use_parts = False
|
||||||
|
|
||||||
# If true, show page references after internal links.
|
# If true, show page references after internal links.
|
||||||
#latex_show_pagerefs = False
|
# latex_show_pagerefs = False
|
||||||
|
|
||||||
# If true, show URL addresses after external links.
|
# If true, show URL addresses after external links.
|
||||||
#latex_show_urls = False
|
# latex_show_urls = False
|
||||||
|
|
||||||
# Documents to append as an appendix to all manuals.
|
# Documents to append as an appendix to all manuals.
|
||||||
#latex_appendices = []
|
# latex_appendices = []
|
||||||
|
|
||||||
# If false, no module index is generated.
|
# If false, no module index is generated.
|
||||||
#latex_domain_indices = True
|
# latex_domain_indices = True
|
||||||
|
|
||||||
|
|
||||||
# -- Options for manual page output -------------------------------------------
|
# -- Options for manual page output -------------------------------------------
|
||||||
|
|
@ -245,7 +244,7 @@ man_pages = [
|
||||||
]
|
]
|
||||||
|
|
||||||
# If true, show URL addresses after external links.
|
# If true, show URL addresses after external links.
|
||||||
#man_show_urls = False
|
# man_show_urls = False
|
||||||
|
|
||||||
|
|
||||||
# -- Options for Texinfo output -----------------------------------------------
|
# -- Options for Texinfo output -----------------------------------------------
|
||||||
|
|
@ -258,13 +257,13 @@ texinfo_documents = [('index', 'glymur', u'glymur Documentation',
|
||||||
'One line description of project.', 'Miscellaneous'), ]
|
'One line description of project.', 'Miscellaneous'), ]
|
||||||
|
|
||||||
# Documents to append as an appendix to all manuals.
|
# Documents to append as an appendix to all manuals.
|
||||||
#texinfo_appendices = []
|
# texinfo_appendices = []
|
||||||
|
|
||||||
# If false, no module index is generated.
|
# If false, no module index is generated.
|
||||||
#texinfo_domain_indices = True
|
# texinfo_domain_indices = True
|
||||||
|
|
||||||
# How to display URL addresses: 'footnote', 'no', or 'inline'.
|
# How to display URL addresses: 'footnote', 'no', or 'inline'.
|
||||||
#texinfo_show_urls = 'footnote'
|
# texinfo_show_urls = 'footnote'
|
||||||
|
|
||||||
|
|
||||||
# Example configuration for intersphinx: refer to the Python standard library.
|
# Example configuration for intersphinx: refer to the Python standard library.
|
||||||
|
|
|
||||||
|
|
@ -15,7 +15,7 @@ or if you use windows, then read on.
|
||||||
|
|
||||||
Glymur uses ctypes to access the openjp2/openjpeg libraries, and
|
Glymur uses ctypes to access the openjp2/openjpeg libraries, and
|
||||||
because ctypes accesses libraries in a platform-dependent manner,
|
because ctypes accesses libraries in a platform-dependent manner,
|
||||||
it is recommended that if you compile and install OpenJPEG into a
|
it is recommended that **if** you compile and install OpenJPEG into a
|
||||||
non-standard location, you should then create a configuration file
|
non-standard location, you should then create a configuration file
|
||||||
to help Glymur properly find the openjpeg or openjp2 libraries
|
to help Glymur properly find the openjpeg or openjp2 libraries
|
||||||
(linux users or macports users don’t need to bother with this if
|
(linux users or macports users don’t need to bother with this if
|
||||||
|
|
@ -50,6 +50,9 @@ installed in a non-standard place, i.e. ::
|
||||||
[library]
|
[library]
|
||||||
openjpeg: /somewhere/lib/libopenjpeg.so
|
openjpeg: /somewhere/lib/libopenjpeg.so
|
||||||
|
|
||||||
|
Once again, you should not have to bother with a configuration file if you use
|
||||||
|
mac or linux and OpenJPEG is provided by your package manager.
|
||||||
|
|
||||||
'''''''
|
'''''''
|
||||||
Testing
|
Testing
|
||||||
'''''''
|
'''''''
|
||||||
|
|
|
||||||
|
|
@ -14,27 +14,22 @@ retrieve a full resolution and first lower-resolution image ::
|
||||||
>>> jp2file = glymur.data.nemo() # just a path to a JPEG2000 file
|
>>> jp2file = glymur.data.nemo() # just a path to a JPEG2000 file
|
||||||
>>> jp2 = glymur.Jp2k(jp2file)
|
>>> jp2 = glymur.Jp2k(jp2file)
|
||||||
>>> fullres = jp2[:]
|
>>> fullres = jp2[:]
|
||||||
>>> print(fullres.shape)
|
>>> fullres.shape
|
||||||
(1456, 2592, 3)
|
(1456, 2592, 3)
|
||||||
>>> thumbnail = jp2[::2, ::2]
|
>>> thumbnail = jp2[::2, ::2]
|
||||||
>>> print(thumbnail.shape)
|
>>> thumbnail.shape
|
||||||
(728, 1296, 3)
|
(728, 1296, 3)
|
||||||
|
|
||||||
The :py:meth:`read` method exposes many more options for other JPEG 2000
|
|
||||||
features such as quality layers.
|
|
||||||
|
|
||||||
... write images?
|
... write images?
|
||||||
=================
|
=================
|
||||||
So long as the image data can fit entirely into memory, array-style slicing may
|
It's pretty simple, just supply the image data as the 2nd argument to the Jp2k
|
||||||
also be used to write JPEG 2000 files.
|
constructor.
|
||||||
|
|
||||||
>>> import glymur, numpy as np
|
>>> import glymur, numpy as np
|
||||||
>>> jp2 = glymur.Jp2k('zeros.jp2', mode='wb')
|
>>> jp2 = glymur.Jp2k('zeros.jp2', data=np.zeros((640, 480), dtype=np.uint8)
|
||||||
>>> jp2[:] = np.zeros((640, 480), dtype=np.uint8)
|
|
||||||
|
|
||||||
The :py:meth:`write` method exposes many more options for other JPEG 2000
|
You must have OpenJPEG version 1.5 or more recent in order to write JPEG 2000
|
||||||
features. You should have OpenJPEG version 1.5 or more recent before writing
|
images with glymur.
|
||||||
JPEG 2000 images.
|
|
||||||
|
|
||||||
... display metadata?
|
... display metadata?
|
||||||
=====================
|
=====================
|
||||||
|
|
@ -219,9 +214,9 @@ making use of the :py:meth:`set_printoptions` function::
|
||||||
UUID: be7acfcb-97a9-42e8-9c71-999491e3afac (XMP)
|
UUID: be7acfcb-97a9-42e8-9c71-999491e3afac (XMP)
|
||||||
Contiguous Codestream Box (jp2c) @ (3223, 1132296)
|
Contiguous Codestream Box (jp2c) @ (3223, 1132296)
|
||||||
|
|
||||||
It is possible to print all the gory codestream details as well, i.e. ::
|
It is possible to easily print the codestream header details as well, i.e. ::
|
||||||
|
|
||||||
>>> print(j.get_codestream()) # details not shown
|
>>> print(j.codestream) # details not show
|
||||||
|
|
||||||
... add XML metadata?
|
... add XML metadata?
|
||||||
=====================
|
=====================
|
||||||
|
|
@ -354,15 +349,14 @@ image isn't square. ::
|
||||||
>>> import numpy as np
|
>>> import numpy as np
|
||||||
>>> import glymur
|
>>> import glymur
|
||||||
>>> from glymur import Jp2k
|
>>> from glymur import Jp2k
|
||||||
>>> rgb = Jp2k(glymur.data.goodstuff()).read()
|
>>> rgb = Jp2k(glymur.data.goodstuff())[:]
|
||||||
>>> lx, ly = rgb.shape[0:2]
|
>>> lx, ly = rgb.shape[0:2]
|
||||||
>>> X, Y = np.ogrid[0:lx, 0:ly]
|
>>> X, Y = np.ogrid[0:lx, 0:ly]
|
||||||
>>> mask = ly**2*(X - lx / 2) ** 2 + lx**2*(Y - ly / 2) ** 2 > (lx * ly / 2)**2
|
>>> mask = ly**2*(X - lx / 2) ** 2 + lx**2*(Y - ly / 2) ** 2 > (lx * ly / 2)**2
|
||||||
>>> alpha = 255 * np.ones((lx, ly, 1), dtype=np.uint8)
|
>>> alpha = 255 * np.ones((lx, ly, 1), dtype=np.uint8)
|
||||||
>>> alpha[mask] = 0
|
>>> alpha[mask] = 0
|
||||||
>>> rgba = np.concatenate((rgb, alpha), axis=2)
|
>>> rgba = np.concatenate((rgb, alpha), axis=2)
|
||||||
>>> jp2 = Jp2k('tmp.jp2', 'wb')
|
>>> jp2 = Jp2k('tmp.jp2', data=rgba)
|
||||||
>>> jp2[:] = rgba
|
|
||||||
|
|
||||||
Next we need to specify what types of channels we have.
|
Next we need to specify what types of channels we have.
|
||||||
The first three channels are color channels, but we identify the fourth as
|
The first three channels are color channels, but we identify the fourth as
|
||||||
|
|
@ -448,7 +442,7 @@ following
|
||||||
'Google'
|
'Google'
|
||||||
|
|
||||||
But that would be painful. A better solution is to install the Python XMP
|
But that would be painful. A better solution is to install the Python XMP
|
||||||
Toolkit (make sure it is version 2.0)::
|
Toolkit (make sure it is at least version 2.0)::
|
||||||
|
|
||||||
>>> from libxmp import XMPMeta
|
>>> from libxmp import XMPMeta
|
||||||
>>> from libxmp.consts import XMP_NS_XMP as NS_XAP
|
>>> from libxmp.consts import XMP_NS_XMP as NS_XAP
|
||||||
|
|
@ -465,8 +459,7 @@ http://photojournal.jpl.nasa.gov/tiff/PIA17145.tif info JPEG 2000::
|
||||||
>>> import skimage.io
|
>>> import skimage.io
|
||||||
>>> image = skimage.io.imread('PIA17145.tif')
|
>>> image = skimage.io.imread('PIA17145.tif')
|
||||||
>>> from glymur import Jp2k
|
>>> from glymur import Jp2k
|
||||||
>>> jp2 = Jp2k('PIA17145.jp2', 'wb')
|
>>> jp2 = Jp2k('PIA17145.jp2', data=image)
|
||||||
>>> jp2[:] = image
|
|
||||||
|
|
||||||
Next you can extract the XMP metadata.
|
Next you can extract the XMP metadata.
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -17,7 +17,6 @@ Contents:
|
||||||
how_do_i
|
how_do_i
|
||||||
whatsnew/index
|
whatsnew/index
|
||||||
roadmap
|
roadmap
|
||||||
api
|
|
||||||
|
|
||||||
------------------
|
------------------
|
||||||
Indices and tables
|
Indices and tables
|
||||||
|
|
|
||||||
|
|
@ -1,12 +1,3 @@
|
||||||
-------------------------------------
|
|
||||||
Platforms Tested (0.7.0 release only)
|
|
||||||
-------------------------------------
|
|
||||||
* Linux Mint 17 / Python 3.4.0 and 2.7.6 / OpenJPEG 2.1.0 and 1.3.0
|
|
||||||
* MacOS 10.6.8 / MacPorts Python 3.4.1, 3.3.5,and 2.7.8 / OpenJPEG 2.1.0
|
|
||||||
* CentOS 6.5 / Anaconda Python 3.4.1 / OpenJPEG 1.3.0
|
|
||||||
* Fedora 20 i386 / Python 2.7.5 and 3.3.2 / OpenJPEG 1.5.1
|
|
||||||
* Windows 7 32bit / Anaconda Python 2.7.6 and 3.4.1 / OpenJPEG 2.1.0
|
|
||||||
|
|
||||||
------------
|
------------
|
||||||
Known Issues
|
Known Issues
|
||||||
------------
|
------------
|
||||||
|
|
|
||||||
|
|
@ -2,10 +2,26 @@
|
||||||
Changes in glymur 0.7
|
Changes in glymur 0.7
|
||||||
=====================
|
=====================
|
||||||
|
|
||||||
|
Changes in 0.7.3
|
||||||
|
=================
|
||||||
|
|
||||||
|
* added read support back for metadata only when the OpenJPEG library is
|
||||||
|
not installed
|
||||||
|
|
||||||
|
Changes in 0.7.2
|
||||||
|
=================
|
||||||
|
|
||||||
|
* added ellipsis support in array-style slicing
|
||||||
|
|
||||||
|
Changes in 0.7.1
|
||||||
|
=================
|
||||||
|
|
||||||
|
* fixed release notes regarding Python 3.4
|
||||||
|
|
||||||
Changes in 0.7.0
|
Changes in 0.7.0
|
||||||
=================
|
=================
|
||||||
|
|
||||||
* implemented :py:meth:`__getitem__`, :py:meth:`__setitem__` support
|
* implemented :py:meth:`__getitem__`, :py:meth:`__setitem__` support
|
||||||
* added back windows support
|
* added back windows support
|
||||||
* box_id and longname are class attributes now instead of instance
|
* box_id and longname are class attributes now instead of instance
|
||||||
attributes (see issue 248)
|
attributes
|
||||||
|
|
|
||||||
24
docs/source/whatsnew/0.8.rst
Normal file
24
docs/source/whatsnew/0.8.rst
Normal file
|
|
@ -0,0 +1,24 @@
|
||||||
|
=====================
|
||||||
|
Changes in glymur 0.8
|
||||||
|
=====================
|
||||||
|
|
||||||
|
Changes in 0.8.0
|
||||||
|
=================
|
||||||
|
|
||||||
|
* Simplified writing images by moving data and options into the
|
||||||
|
constructor.
|
||||||
|
* Deprecated :py:meth:`read` method in favor of array-style slicing.
|
||||||
|
In order to retain certain functionality, the following parameters
|
||||||
|
to the :py:meth:`read` method have become top-level properties
|
||||||
|
|
||||||
|
* verbose
|
||||||
|
* layer
|
||||||
|
* ignore_pclr_cmap_cdef
|
||||||
|
|
||||||
|
* Two additional properties were introduced.
|
||||||
|
|
||||||
|
* codestream
|
||||||
|
* shape
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -8,6 +8,7 @@ These document the changes between minor (or major) versions of glymur.
|
||||||
|
|
||||||
.. toctree::
|
.. toctree::
|
||||||
|
|
||||||
0.5
|
0.8
|
||||||
0.6
|
|
||||||
0.7
|
0.7
|
||||||
|
0.6
|
||||||
|
0.5
|
||||||
|
|
|
||||||
|
|
@ -1,19 +1,25 @@
|
||||||
"""glymur - read, write, and interrogate JPEG 2000 files
|
"""glymur - read, write, and interrogate JPEG 2000 files
|
||||||
"""
|
"""
|
||||||
import sys
|
|
||||||
import unittest
|
import unittest
|
||||||
|
|
||||||
from glymur import version
|
from glymur import version
|
||||||
__version__ = version.version
|
__version__ = version.version
|
||||||
|
|
||||||
from .jp2k import Jp2k
|
from .jp2k import Jp2k
|
||||||
from .jp2box import get_printoptions, set_printoptions
|
from .jp2box import (get_printoptions,
|
||||||
from .jp2box import get_parseoptions, set_parseoptions
|
set_printoptions,
|
||||||
|
get_parseoptions,
|
||||||
|
set_parseoptions)
|
||||||
|
|
||||||
from . import data
|
from . import data
|
||||||
|
|
||||||
|
|
||||||
def runtests():
|
def runtests():
|
||||||
"""Discover and run all tests for the glymur package.
|
"""Discover and run all tests for the glymur package.
|
||||||
"""
|
"""
|
||||||
suite = unittest.defaultTestLoader.discover(__path__[0])
|
suite = unittest.defaultTestLoader.discover(__path__[0])
|
||||||
unittest.TextTestRunner(verbosity=2).run(suite)
|
unittest.TextTestRunner(verbosity=2).run(suite)
|
||||||
|
|
||||||
|
|
||||||
|
__all__ = [__version__, Jp2k, get_printoptions, set_printoptions,
|
||||||
|
get_parseoptions, set_parseoptions, data, runtests]
|
||||||
|
|
|
||||||
|
|
@ -3,14 +3,13 @@
|
||||||
Part of glymur.
|
Part of glymur.
|
||||||
"""
|
"""
|
||||||
from collections import OrderedDict
|
from collections import OrderedDict
|
||||||
import pprint
|
|
||||||
import re
|
|
||||||
import struct
|
import struct
|
||||||
import sys
|
import sys
|
||||||
import warnings
|
import warnings
|
||||||
|
|
||||||
import lxml.etree as ET
|
import lxml.etree as ET
|
||||||
|
|
||||||
|
|
||||||
def xml(raw_data):
|
def xml(raw_data):
|
||||||
"""
|
"""
|
||||||
XMP data to be parsed as XML.
|
XMP data to be parsed as XML.
|
||||||
|
|
@ -23,6 +22,7 @@ def xml(raw_data):
|
||||||
|
|
||||||
return ET.ElementTree(elt)
|
return ET.ElementTree(elt)
|
||||||
|
|
||||||
|
|
||||||
def tiff_header(read_buffer):
|
def tiff_header(read_buffer):
|
||||||
"""
|
"""
|
||||||
Interpret the uuid raw data as a tiff header.
|
Interpret the uuid raw data as a tiff header.
|
||||||
|
|
@ -37,8 +37,8 @@ def tiff_header(read_buffer):
|
||||||
# big endian
|
# big endian
|
||||||
endian = '>'
|
endian = '>'
|
||||||
else:
|
else:
|
||||||
msg = "The byte order indication in the TIFF header ({0}) is invalid. "
|
msg = "The byte order indication in the TIFF header ({0}) is "
|
||||||
msg += "It should be either {1} or {2}."
|
msg += "invalid. It should be either {1} or {2}."
|
||||||
msg = msg.format(read_buffer[6:8], bytes([73, 73]), bytes([77, 77]))
|
msg = msg.format(read_buffer[6:8], bytes([73, 73]), bytes([77, 77]))
|
||||||
raise IOError(msg)
|
raise IOError(msg)
|
||||||
|
|
||||||
|
|
@ -503,6 +503,3 @@ class _ExifInteroperabilityIfd(_Ifd):
|
||||||
def __init__(self, endian, read_buffer, offset):
|
def __init__(self, endian, read_buffer, offset):
|
||||||
_Ifd.__init__(self, endian, read_buffer, offset)
|
_Ifd.__init__(self, endian, read_buffer, offset)
|
||||||
self.post_process(self.tagnum2name)
|
self.post_process(self.tagnum2name)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -6,16 +6,13 @@ codestreams.
|
||||||
|
|
||||||
# The number of lines in the module is long and that's ok. It would not help
|
# The number of lines in the module is long and that's ok. It would not help
|
||||||
# matters to move anything out to another file.
|
# matters to move anything out to another file.
|
||||||
# pylint: disable=C0302
|
|
||||||
|
|
||||||
# "Too many instance attributes", "Too many arguments"
|
# "Too many instance attributes", "Too many arguments"
|
||||||
# Some segments just have a lot of information.
|
# Some segments just have a lot of information.
|
||||||
# It doesn't make sense to subclass just for that.
|
# It doesn't make sense to subclass just for that.
|
||||||
# pylint: disable=R0902,R0913
|
|
||||||
|
|
||||||
# "Too few public methods" Some segments don't define any new methods from
|
# "Too few public methods" Some segments don't define any new methods from
|
||||||
# the base Segment class.
|
# the base Segment class.
|
||||||
# pylint: disable=R0903
|
|
||||||
|
|
||||||
import math
|
import math
|
||||||
import struct
|
import struct
|
||||||
|
|
@ -24,23 +21,22 @@ import warnings
|
||||||
|
|
||||||
import numpy as np
|
import numpy as np
|
||||||
|
|
||||||
from .core import LRCP, RLCP, RPCL, PCRL, CPRL
|
from .core import (LRCP, RLCP, RPCL, PCRL, CPRL,
|
||||||
from .core import WAVELET_XFORM_9X7_IRREVERSIBLE
|
WAVELET_XFORM_9X7_IRREVERSIBLE,
|
||||||
from .core import WAVELET_XFORM_5X3_REVERSIBLE
|
WAVELET_XFORM_5X3_REVERSIBLE,
|
||||||
from .core import _Keydefaultdict
|
_Keydefaultdict)
|
||||||
from .lib import openjp2 as opj2
|
from .lib import openjp2 as opj2
|
||||||
|
|
||||||
_factory = lambda x: '{0} (invalid)'.format(x)
|
_factory = lambda x: '{0} (invalid)'.format(x)
|
||||||
_PROGRESSION_ORDER_DISPLAY = _Keydefaultdict(_factory,
|
_PROGRESSION_ORDER_DISPLAY = _Keydefaultdict(_factory, {LRCP: 'LRCP',
|
||||||
{ LRCP: 'LRCP',
|
RLCP: 'RLCP',
|
||||||
RLCP: 'RLCP',
|
RPCL: 'RPCL',
|
||||||
RPCL: 'RPCL',
|
PCRL: 'PCRL',
|
||||||
PCRL: 'PCRL',
|
CPRL: 'CPRL'})
|
||||||
CPRL: 'CPRL'})
|
|
||||||
|
|
||||||
_WAVELET_TRANSFORM_DISPLAY = _Keydefaultdict(_factory,
|
_keysvalues = {WAVELET_XFORM_9X7_IRREVERSIBLE: '9-7 irreversible',
|
||||||
{ WAVELET_XFORM_9X7_IRREVERSIBLE: '9-7 irreversible',
|
WAVELET_XFORM_5X3_REVERSIBLE: '5-3 reversible'}
|
||||||
WAVELET_XFORM_5X3_REVERSIBLE: '5-3 reversible'})
|
_WAVELET_TRANSFORM_DISPLAY = _Keydefaultdict(_factory, _keysvalues)
|
||||||
|
|
||||||
_NO_PROFILE = 0
|
_NO_PROFILE = 0
|
||||||
_PROFILE_0 = 1
|
_PROFILE_0 = 1
|
||||||
|
|
@ -51,12 +47,11 @@ _PROFILE_4 = 4
|
||||||
_KNOWN_PROFILES = [_NO_PROFILE, _PROFILE_0, _PROFILE_1, _PROFILE_3, _PROFILE_4]
|
_KNOWN_PROFILES = [_NO_PROFILE, _PROFILE_0, _PROFILE_1, _PROFILE_3, _PROFILE_4]
|
||||||
|
|
||||||
# How to display the codestream profile.
|
# How to display the codestream profile.
|
||||||
_CAPABILITIES_DISPLAY = _Keydefaultdict(_factory,
|
_CAPABILITIES_DISPLAY = _Keydefaultdict(_factory, {_NO_PROFILE: 'no profile',
|
||||||
{ _NO_PROFILE: 'no profile',
|
_PROFILE_0: '0',
|
||||||
_PROFILE_0: '0',
|
_PROFILE_1: '1',
|
||||||
_PROFILE_1: '1',
|
_PROFILE_3: 'Cinema 2K',
|
||||||
_PROFILE_3: 'Cinema 2K',
|
_PROFILE_4: 'Cinema 4K'})
|
||||||
_PROFILE_4: 'Cinema 4K'} )
|
|
||||||
|
|
||||||
# Need a catch-all list of valid markers.
|
# Need a catch-all list of valid markers.
|
||||||
# See table A-1 in ISO/IEC FCD15444-1.
|
# See table A-1 in ISO/IEC FCD15444-1.
|
||||||
|
|
@ -298,7 +293,6 @@ class Codestream(object):
|
||||||
msg += ''.join(strs)
|
msg += ''.join(strs)
|
||||||
return msg
|
return msg
|
||||||
|
|
||||||
# pylint: disable=R0201
|
|
||||||
def _parse_cme_segment(self, fptr):
|
def _parse_cme_segment(self, fptr):
|
||||||
"""Parse the CME marker segment.
|
"""Parse the CME marker segment.
|
||||||
|
|
||||||
|
|
@ -694,7 +688,7 @@ class Codestream(object):
|
||||||
try:
|
try:
|
||||||
num_tiles_x = (xysiz[0] - xyosiz[0]) / (xytsiz[0] - xytosiz[0])
|
num_tiles_x = (xysiz[0] - xyosiz[0]) / (xytsiz[0] - xytosiz[0])
|
||||||
num_tiles_y = (xysiz[1] - xyosiz[1]) / (xytsiz[1] - xytosiz[1])
|
num_tiles_y = (xysiz[1] - xyosiz[1]) / (xytsiz[1] - xytosiz[1])
|
||||||
except ZeroDivisionError as err:
|
except ZeroDivisionError:
|
||||||
warnings.warn("Invalid tile dimensions.")
|
warnings.warn("Invalid tile dimensions.")
|
||||||
else:
|
else:
|
||||||
numtiles = math.ceil(num_tiles_x) * math.ceil(num_tiles_y)
|
numtiles = math.ceil(num_tiles_x) * math.ceil(num_tiles_y)
|
||||||
|
|
@ -702,7 +696,6 @@ class Codestream(object):
|
||||||
msg = "Invalid number of tiles ({0}).".format(numtiles)
|
msg = "Invalid number of tiles ({0}).".format(numtiles)
|
||||||
warnings.warn(msg)
|
warnings.warn(msg)
|
||||||
|
|
||||||
|
|
||||||
kwargs = {'rsiz': rsiz,
|
kwargs = {'rsiz': rsiz,
|
||||||
'xysiz': xysiz,
|
'xysiz': xysiz,
|
||||||
'xyosiz': xyosiz,
|
'xyosiz': xyosiz,
|
||||||
|
|
@ -829,7 +822,6 @@ class Codestream(object):
|
||||||
|
|
||||||
return TLMsegment(length, offset, ztlm, ttlm, ptlm)
|
return TLMsegment(length, offset, ztlm, ttlm, ptlm)
|
||||||
|
|
||||||
# pylint: disable=W0613
|
|
||||||
def _parse_reserved_marker(self, fptr):
|
def _parse_reserved_marker(self, fptr):
|
||||||
"""Marker range between 0xff30 and 0xff39.
|
"""Marker range between 0xff30 and 0xff39.
|
||||||
"""
|
"""
|
||||||
|
|
@ -1613,6 +1605,7 @@ class SOCsegment(Segment):
|
||||||
msg = "glymur.codestream.SOCsegment()"
|
msg = "glymur.codestream.SOCsegment()"
|
||||||
return msg
|
return msg
|
||||||
|
|
||||||
|
|
||||||
class SODsegment(Segment):
|
class SODsegment(Segment):
|
||||||
"""Container for Start of Data (SOD) segment information.
|
"""Container for Start of Data (SOD) segment information.
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -2,32 +2,36 @@
|
||||||
Entry point for console script jp2dump.
|
Entry point for console script jp2dump.
|
||||||
"""
|
"""
|
||||||
import argparse
|
import argparse
|
||||||
import sys
|
import os
|
||||||
import warnings
|
import warnings
|
||||||
from . import Jp2k, set_printoptions
|
|
||||||
|
from . import Jp2k, set_printoptions, set_parseoptions, lib
|
||||||
|
|
||||||
|
|
||||||
def main():
|
def main():
|
||||||
"""
|
"""
|
||||||
Entry point for console script jp2dump.
|
Entry point for console script jp2dump.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
description='Print JPEG2000 metadata.'
|
kwargs = {'description': 'Print JPEG2000 metadata.',
|
||||||
parser = argparse.ArgumentParser(description=description)
|
'formatter_class': argparse.ArgumentDefaultsHelpFormatter}
|
||||||
|
parser = argparse.ArgumentParser(**kwargs)
|
||||||
|
|
||||||
parser.add_argument('-x', '--noxml',
|
parser.add_argument('-x', '--noxml',
|
||||||
help='Suppress XML.',
|
help='suppress XML',
|
||||||
action='store_true')
|
action='store_true')
|
||||||
parser.add_argument('-s', '--short',
|
parser.add_argument('-s', '--short',
|
||||||
help='Only print box id, offset, and length.',
|
help='only print box id, offset, and length',
|
||||||
action='store_true')
|
action='store_true')
|
||||||
|
|
||||||
chelp = 'Level of codestream information. 0 suppressed all details, '
|
chelp = 'Level of codestream information. 0 suppresses all details, '
|
||||||
chelp += '1 prints headers, 2 prints the full codestream'
|
chelp += '1 prints the main header, 2 prints the full codestream.'
|
||||||
parser.add_argument('-c', '--codestream',
|
parser.add_argument('-c', '--codestream',
|
||||||
help=chelp,
|
help=chelp,
|
||||||
nargs=1,
|
metavar='LEVEL',
|
||||||
type=int,
|
nargs=1,
|
||||||
default=[0])
|
type=int,
|
||||||
|
default=[1])
|
||||||
|
|
||||||
parser.add_argument('filename')
|
parser.add_argument('filename')
|
||||||
|
|
||||||
|
|
@ -36,30 +40,33 @@ def main():
|
||||||
set_printoptions(xml=False)
|
set_printoptions(xml=False)
|
||||||
if args.short:
|
if args.short:
|
||||||
set_printoptions(short=True)
|
set_printoptions(short=True)
|
||||||
|
|
||||||
codestream_level = args.codestream[0]
|
codestream_level = args.codestream[0]
|
||||||
if codestream_level not in [0, 1, 2]:
|
if codestream_level not in [0, 1, 2]:
|
||||||
raise ValueError("Invalid level of codestream information specified.")
|
raise ValueError("Invalid level of codestream information specified.")
|
||||||
|
|
||||||
if codestream_level == 0:
|
if codestream_level == 0:
|
||||||
set_printoptions(codestream=False)
|
set_printoptions(codestream=False)
|
||||||
print_full_codestream = False
|
elif codestream_level == 2:
|
||||||
elif codestream_level == 1:
|
set_parseoptions(full_codestream=True)
|
||||||
print_full_codestream = False
|
|
||||||
else:
|
|
||||||
print_full_codestream = True
|
|
||||||
|
|
||||||
filename = args.filename
|
filename = args.filename
|
||||||
|
|
||||||
with warnings.catch_warnings(record=True) as wctx:
|
with warnings.catch_warnings(record=True) as wctx:
|
||||||
|
|
||||||
# JP2 metadata can be extensive, so don't print any warnings until we
|
# JP2 metadata can be extensive, so don't print any warnings until we
|
||||||
# are done with the metadata.
|
# are done with the metadata.
|
||||||
j = Jp2k(filename)
|
jp2 = Jp2k(filename)
|
||||||
if print_full_codestream:
|
if jp2._codec_format == lib.openjp2.CODEC_J2K:
|
||||||
print(j.get_codestream(header_only=False))
|
if codestream_level == 0:
|
||||||
|
print('File: {0}'.format(os.path.basename(filename)))
|
||||||
|
elif codestream_level == 1:
|
||||||
|
print(jp2)
|
||||||
|
elif codestream_level == 2:
|
||||||
|
print('File: {0}'.format(os.path.basename(filename)))
|
||||||
|
print(jp2.get_codestream(header_only=False))
|
||||||
else:
|
else:
|
||||||
print(j)
|
print(jp2)
|
||||||
|
|
||||||
# Re-emit any warnings that may have been suppressed.
|
# Re-emit any warnings that may have been suppressed.
|
||||||
if len(wctx) > 0:
|
if len(wctx) > 0:
|
||||||
|
|
|
||||||
|
|
@ -1,8 +1,7 @@
|
||||||
"""Core definitions to be shared amongst the modules.
|
"""Core definitions to be shared amongst the modules.
|
||||||
"""
|
"""
|
||||||
import collections
|
import collections
|
||||||
import copy
|
|
||||||
import lxml.etree as ET
|
|
||||||
|
|
||||||
class _Keydefaultdict(collections.defaultdict):
|
class _Keydefaultdict(collections.defaultdict):
|
||||||
"""Unlisted keys help form their own error message.
|
"""Unlisted keys help form their own error message.
|
||||||
|
|
@ -121,12 +120,12 @@ ROMM_RGB = 21
|
||||||
|
|
||||||
_factory = lambda x: '{0} (unrecognized)'.format(x)
|
_factory = lambda x: '{0} (unrecognized)'.format(x)
|
||||||
_COLORSPACE_MAP_DISPLAY = _Keydefaultdict(_factory,
|
_COLORSPACE_MAP_DISPLAY = _Keydefaultdict(_factory,
|
||||||
{ CMYK: 'CMYK',
|
{CMYK: 'CMYK',
|
||||||
SRGB: 'sRGB',
|
SRGB: 'sRGB',
|
||||||
GREYSCALE: 'greyscale',
|
GREYSCALE: 'greyscale',
|
||||||
YCC: 'YCC',
|
YCC: 'YCC',
|
||||||
E_SRGB: 'e-sRGB',
|
E_SRGB: 'e-sRGB',
|
||||||
ROMM_RGB: 'ROMM-RGB'} )
|
ROMM_RGB: 'ROMM-RGB'})
|
||||||
|
|
||||||
# enumerated color channel types
|
# enumerated color channel types
|
||||||
COLOR = 0
|
COLOR = 0
|
||||||
|
|
@ -134,11 +133,11 @@ OPACITY = 1
|
||||||
PRE_MULTIPLIED_OPACITY = 2
|
PRE_MULTIPLIED_OPACITY = 2
|
||||||
_UNSPECIFIED = 65535
|
_UNSPECIFIED = 65535
|
||||||
_factory = lambda x: '{0} (invalid)'.format(x)
|
_factory = lambda x: '{0} (invalid)'.format(x)
|
||||||
_COLOR_TYPE_MAP_DISPLAY = _Keydefaultdict(_factory,
|
_dict = {COLOR: 'color',
|
||||||
{ COLOR: 'color',
|
OPACITY: 'opacity',
|
||||||
OPACITY: 'opacity',
|
PRE_MULTIPLIED_OPACITY: 'pre-multiplied opacity',
|
||||||
PRE_MULTIPLIED_OPACITY: 'pre-multiplied opacity',
|
_UNSPECIFIED: 'unspecified'}
|
||||||
_UNSPECIFIED: 'unspecified'})
|
_COLOR_TYPE_MAP_DISPLAY = _Keydefaultdict(_factory, _dict)
|
||||||
|
|
||||||
# color channel definitions.
|
# color channel definitions.
|
||||||
RED = 1
|
RED = 1
|
||||||
|
|
@ -153,4 +152,3 @@ _COLORSPACE = {SRGB: {"R": 1, "G": 2, "B": 3},
|
||||||
YCC: {"Y": 1, "Cb": 2, "Cr": 3},
|
YCC: {"Y": 1, "Cb": 2, "Cr": 3},
|
||||||
E_SRGB: {"R": 1, "G": 2, "B": 3},
|
E_SRGB: {"R": 1, "G": 2, "B": 3},
|
||||||
ROMM_RGB: {"R": 1, "G": 2, "B": 3}}
|
ROMM_RGB: {"R": 1, "G": 2, "B": 3}}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -43,4 +43,3 @@ def jpxfile():
|
||||||
"""
|
"""
|
||||||
filename = pkg_resources.resource_filename(__name__, "heliov.jpx")
|
filename = pkg_resources.resource_filename(__name__, "heliov.jpx")
|
||||||
return filename
|
return filename
|
||||||
|
|
||||||
|
|
|
||||||
382
glymur/jp2box.py
382
glymur/jp2box.py
|
|
@ -11,8 +11,6 @@ References
|
||||||
Extensions
|
Extensions
|
||||||
"""
|
"""
|
||||||
|
|
||||||
# pylint: disable=C0302,R0903,R0913,W0142
|
|
||||||
|
|
||||||
from collections import OrderedDict
|
from collections import OrderedDict
|
||||||
import datetime
|
import datetime
|
||||||
import io
|
import io
|
||||||
|
|
@ -22,34 +20,37 @@ import pprint
|
||||||
import struct
|
import struct
|
||||||
import sys
|
import sys
|
||||||
import textwrap
|
import textwrap
|
||||||
import uuid
|
from uuid import UUID
|
||||||
import warnings
|
import warnings
|
||||||
|
|
||||||
import lxml.etree as ET
|
import lxml.etree as ET
|
||||||
import numpy as np
|
import numpy as np
|
||||||
|
|
||||||
from .codestream import Codestream
|
from .codestream import Codestream
|
||||||
from .core import _COLORSPACE_MAP_DISPLAY
|
from .core import (_COLORSPACE_MAP_DISPLAY, _COLOR_TYPE_MAP_DISPLAY,
|
||||||
from .core import _COLOR_TYPE_MAP_DISPLAY
|
SRGB, GREYSCALE, YCC,
|
||||||
from .core import SRGB, GREYSCALE, YCC
|
ENUMERATED_COLORSPACE, RESTRICTED_ICC_PROFILE,
|
||||||
from .core import ENUMERATED_COLORSPACE, RESTRICTED_ICC_PROFILE
|
ANY_ICC_PROFILE, VENDOR_COLOR_METHOD,
|
||||||
from .core import ANY_ICC_PROFILE, VENDOR_COLOR_METHOD
|
_Keydefaultdict)
|
||||||
from .core import _Keydefaultdict
|
|
||||||
|
|
||||||
from . import _uuid_io
|
from . import _uuid_io
|
||||||
|
|
||||||
_METHOD_DISPLAY = {
|
_factory = lambda x: '{0} (invalid)'.format(x)
|
||||||
ENUMERATED_COLORSPACE: 'enumerated colorspace',
|
_keysvalues = {ENUMERATED_COLORSPACE: 'enumerated colorspace',
|
||||||
RESTRICTED_ICC_PROFILE: 'restricted ICC profile',
|
RESTRICTED_ICC_PROFILE: 'restricted ICC profile',
|
||||||
ANY_ICC_PROFILE: 'any ICC profile',
|
ANY_ICC_PROFILE: 'any ICC profile',
|
||||||
VENDOR_COLOR_METHOD: 'vendor color method'}
|
VENDOR_COLOR_METHOD: 'vendor color method'}
|
||||||
|
_METHOD_DISPLAY = _Keydefaultdict(_factory, _keysvalues)
|
||||||
|
|
||||||
_factory = lambda x: '{0} (invalid)'.format(x)
|
_factory = lambda x: '{0} (invalid)'.format(x)
|
||||||
_APPROX_DISPLAY = _Keydefaultdict(_factory,
|
_keysvalues = {1: 'accurately represents correct colorspace definition',
|
||||||
{1: 'accurately represents correct colorspace definition',
|
2: ('approximates correct colorspace definition, '
|
||||||
2: 'approximates correct colorspace definition, exceptional quality',
|
'exceptional quality'),
|
||||||
3: 'approximates correct colorspace definition, reasonable quality',
|
3: ('approximates correct colorspace definition, '
|
||||||
4: 'approximates correct colorspace definition, poor quality'})
|
'reasonable quality'),
|
||||||
|
4: 'approximates correct colorspace definition, poor quality'}
|
||||||
|
_APPROX_DISPLAY = _Keydefaultdict(_factory, _keysvalues)
|
||||||
|
|
||||||
|
|
||||||
class Jp2kBox(object):
|
class Jp2kBox(object):
|
||||||
"""Superclass for JPEG 2000 boxes.
|
"""Superclass for JPEG 2000 boxes.
|
||||||
|
|
@ -108,7 +109,6 @@ class Jp2kBox(object):
|
||||||
msg += '\n' + self._indent(boxstr)
|
msg += '\n' + self._indent(boxstr)
|
||||||
return msg
|
return msg
|
||||||
|
|
||||||
|
|
||||||
def _indent(self, textstr, indent_level=4):
|
def _indent(self, textstr, indent_level=4):
|
||||||
"""
|
"""
|
||||||
Indent a string.
|
Indent a string.
|
||||||
|
|
@ -134,7 +134,6 @@ class Jp2kBox(object):
|
||||||
lst = [(' ' * indent_level + x) for x in textstr.split('\n')]
|
lst = [(' ' * indent_level + x) for x in textstr.split('\n')]
|
||||||
return '\n'.join(lst)
|
return '\n'.join(lst)
|
||||||
|
|
||||||
|
|
||||||
def _write_superbox(self, fptr, box_id):
|
def _write_superbox(self, fptr, box_id):
|
||||||
"""Write a superbox.
|
"""Write a superbox.
|
||||||
|
|
||||||
|
|
@ -190,13 +189,14 @@ class Jp2kBox(object):
|
||||||
try:
|
try:
|
||||||
box = parser(fptr, start, num_bytes)
|
box = parser(fptr, start, num_bytes)
|
||||||
except ValueError as err:
|
except ValueError as err:
|
||||||
msg = "Encountered an unrecoverable ValueError while parsing a {0} "
|
msg = "Encountered an unrecoverable ValueError while parsing a "
|
||||||
msg += "box at byte offset {1}. The original error message was "
|
msg += "{0} box at byte offset {1}. The original error message "
|
||||||
msg += "\"{2}\""
|
msg += "was \"{2}\""
|
||||||
msg = msg.format(_BOX_WITH_ID[box_id].longname, start, str(err))
|
msg = msg.format(_BOX_WITH_ID[box_id].longname, start, str(err))
|
||||||
warnings.warn(msg, UserWarning)
|
warnings.warn(msg, UserWarning)
|
||||||
box = UnknownBox(box_id.decode('utf-8'),
|
box = UnknownBox(box_id.decode('utf-8'),
|
||||||
length=num_bytes, offset=start, longname='Unknown')
|
length=num_bytes,
|
||||||
|
offset=start, longname='Unknown')
|
||||||
|
|
||||||
return box
|
return box
|
||||||
|
|
||||||
|
|
@ -298,6 +298,7 @@ class ColourSpecificationBox(Jp2kBox):
|
||||||
"""
|
"""
|
||||||
longname = 'Colour Specification'
|
longname = 'Colour Specification'
|
||||||
box_id = 'colr'
|
box_id = 'colr'
|
||||||
|
|
||||||
def __init__(self, method=ENUMERATED_COLORSPACE, precedence=0,
|
def __init__(self, method=ENUMERATED_COLORSPACE, precedence=0,
|
||||||
approximation=0, colorspace=None, icc_profile=None,
|
approximation=0, colorspace=None, icc_profile=None,
|
||||||
length=0, offset=-1):
|
length=0, offset=-1):
|
||||||
|
|
@ -336,16 +337,16 @@ class ColourSpecificationBox(Jp2kBox):
|
||||||
|
|
||||||
if self.icc_profile is None:
|
if self.icc_profile is None:
|
||||||
if self.colorspace not in [SRGB, GREYSCALE, YCC]:
|
if self.colorspace not in [SRGB, GREYSCALE, YCC]:
|
||||||
msg = "Colorspace should correspond to one of SRGB, GREYSCALE, "
|
msg = "Colorspace should correspond to one of SRGB, "
|
||||||
msg += "or YCC."
|
msg += "GREYSCALE, or YCC."
|
||||||
self._dispatch_validation_error(msg, writing=True)
|
self._dispatch_validation_error(msg, writing=True)
|
||||||
|
|
||||||
self._validate(writing=True)
|
self._validate(writing=True)
|
||||||
|
|
||||||
|
|
||||||
def __repr__(self):
|
def __repr__(self):
|
||||||
msg = "glymur.jp2box.ColourSpecificationBox("
|
msg = "glymur.jp2box.ColourSpecificationBox("
|
||||||
msg += "method={0}, precedence={1}, approximation={2}, colorspace={3}, "
|
msg += "method={0}, precedence={1}, approximation={2}, "
|
||||||
|
msg += "colorspace={3}, "
|
||||||
msg += "icc_profile={4})"
|
msg += "icc_profile={4})"
|
||||||
msg = msg.format(self.method,
|
msg = msg.format(self.method,
|
||||||
self.precedence,
|
self.precedence,
|
||||||
|
|
@ -356,7 +357,7 @@ class ColourSpecificationBox(Jp2kBox):
|
||||||
|
|
||||||
def __str__(self):
|
def __str__(self):
|
||||||
msg = Jp2kBox.__str__(self)
|
msg = Jp2kBox.__str__(self)
|
||||||
if _printoptions['short'] == True:
|
if _printoptions['short'] is True:
|
||||||
return msg
|
return msg
|
||||||
|
|
||||||
msg += '\n Method: {0}'.format(_METHOD_DISPLAY[self.method])
|
msg += '\n Method: {0}'.format(_METHOD_DISPLAY[self.method])
|
||||||
|
|
@ -618,10 +619,9 @@ class ChannelDefinitionBox(Jp2kBox):
|
||||||
msg += " 65535 - unspecified"
|
msg += " 65535 - unspecified"
|
||||||
self._dispatch_validation_error(msg, writing=writing)
|
self._dispatch_validation_error(msg, writing=writing)
|
||||||
|
|
||||||
|
|
||||||
def __str__(self):
|
def __str__(self):
|
||||||
msg = Jp2kBox.__str__(self)
|
msg = Jp2kBox.__str__(self)
|
||||||
if _printoptions['short'] == True:
|
if _printoptions['short'] is True:
|
||||||
return msg
|
return msg
|
||||||
|
|
||||||
for j in range(len(self.association)):
|
for j in range(len(self.association)):
|
||||||
|
|
@ -841,7 +841,7 @@ class CompositingLayerHeaderBox(Jp2kBox):
|
||||||
List of boxes contained in this superbox.
|
List of boxes contained in this superbox.
|
||||||
"""
|
"""
|
||||||
box_id = 'jplh'
|
box_id = 'jplh'
|
||||||
longname='Compositing Layer Header'
|
longname = 'Compositing Layer Header'
|
||||||
|
|
||||||
def __init__(self, box=None, length=0, offset=-1):
|
def __init__(self, box=None, length=0, offset=-1):
|
||||||
Jp2kBox.__init__(self)
|
Jp2kBox.__init__(self)
|
||||||
|
|
@ -930,7 +930,7 @@ class ComponentMappingBox(Jp2kBox):
|
||||||
|
|
||||||
def __str__(self):
|
def __str__(self):
|
||||||
msg = Jp2kBox.__str__(self)
|
msg = Jp2kBox.__str__(self)
|
||||||
if _printoptions['short'] == True:
|
if _printoptions['short'] is True:
|
||||||
return msg
|
return msg
|
||||||
|
|
||||||
for k in range(len(self.component_index)):
|
for k in range(len(self.component_index)):
|
||||||
|
|
@ -1001,18 +1001,19 @@ class ContiguousCodestreamBox(Jp2kBox):
|
||||||
offset of the box from the start of the file.
|
offset of the box from the start of the file.
|
||||||
longname : str
|
longname : str
|
||||||
more verbose description of the box.
|
more verbose description of the box.
|
||||||
main_header : Codestream object
|
codestream : Codestream object
|
||||||
contains list of main header marker/segments
|
Contains list of codestream marker/segments. By default, only the main
|
||||||
|
header is retrieved.
|
||||||
main_header_offset : int
|
main_header_offset : int
|
||||||
offset of main header from start of file
|
offset of main header from start of file
|
||||||
"""
|
"""
|
||||||
box_id = 'jp2c'
|
box_id = 'jp2c'
|
||||||
longname = 'Contiguous Codestream'
|
longname = 'Contiguous Codestream'
|
||||||
|
|
||||||
def __init__(self, main_header=None, main_header_offset=None, length=0,
|
def __init__(self, codestream=None, main_header_offset=None, length=0,
|
||||||
offset=-1):
|
offset=-1):
|
||||||
Jp2kBox.__init__(self)
|
Jp2kBox.__init__(self)
|
||||||
self._main_header = main_header
|
self._codestream = codestream
|
||||||
self.length = length
|
self.length = length
|
||||||
self.offset = offset
|
self.offset = offset
|
||||||
self.main_header_offset = main_header_offset
|
self.main_header_offset = main_header_offset
|
||||||
|
|
@ -1021,29 +1022,33 @@ class ContiguousCodestreamBox(Jp2kBox):
|
||||||
self._filename = None
|
self._filename = None
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def main_header(self):
|
def codestream(self):
|
||||||
if self._main_header is None:
|
if _parseoptions['full_codestream'] is True:
|
||||||
|
header_only = False
|
||||||
|
else:
|
||||||
|
header_only = True
|
||||||
|
if self._codestream is None:
|
||||||
if self._filename is not None:
|
if self._filename is not None:
|
||||||
with open(self._filename, 'rb') as fptr:
|
with open(self._filename, 'rb') as fptr:
|
||||||
fptr.seek(self.main_header_offset)
|
fptr.seek(self.main_header_offset)
|
||||||
main_header = Codestream(fptr, self._length, header_only=True)
|
codestream = Codestream(fptr, self._length,
|
||||||
self._main_header = main_header
|
header_only=header_only)
|
||||||
return self._main_header
|
self._codestream = codestream
|
||||||
|
return self._codestream
|
||||||
|
|
||||||
def __repr__(self):
|
def __repr__(self):
|
||||||
msg = "glymur.jp2box.ContiguousCodeStreamBox(main_header={0})"
|
msg = "glymur.jp2box.ContiguousCodeStreamBox(codestream={0})"
|
||||||
return msg.format(repr(self.main_header))
|
return msg.format(repr(self.codestream))
|
||||||
|
|
||||||
def __str__(self):
|
def __str__(self):
|
||||||
msg = Jp2kBox.__str__(self)
|
msg = Jp2kBox.__str__(self)
|
||||||
if _printoptions['short'] == True:
|
if _printoptions['short'] is True:
|
||||||
return msg
|
return msg
|
||||||
if _printoptions['codestream'] == False:
|
if _printoptions['codestream'] is False:
|
||||||
return msg
|
return msg
|
||||||
|
|
||||||
msg += '\n Main header:'
|
for segment in self.codestream.segment:
|
||||||
for segment in self.main_header.segment:
|
msg += '\n' + self._indent(str(segment), indent_level=4)
|
||||||
msg += '\n' + self._indent(str(segment), indent_level=8)
|
|
||||||
|
|
||||||
return msg
|
return msg
|
||||||
|
|
||||||
|
|
@ -1065,11 +1070,11 @@ class ContiguousCodestreamBox(Jp2kBox):
|
||||||
ContiguousCodestreamBox instance
|
ContiguousCodestreamBox instance
|
||||||
"""
|
"""
|
||||||
main_header_offset = fptr.tell()
|
main_header_offset = fptr.tell()
|
||||||
if _parseoptions['codestream'] is True:
|
if _parseoptions['full_codestream'] is True:
|
||||||
main_header = Codestream(fptr, length, header_only=True)
|
codestream = Codestream(fptr, length, header_only=False)
|
||||||
else:
|
else:
|
||||||
main_header = None
|
codestream = None
|
||||||
box = cls(main_header, main_header_offset=main_header_offset,
|
box = cls(codestream, main_header_offset=main_header_offset,
|
||||||
length=length, offset=offset)
|
length=length, offset=offset)
|
||||||
box._filename = fptr.name
|
box._filename = fptr.name
|
||||||
box._length = length
|
box._length = length
|
||||||
|
|
@ -1117,7 +1122,8 @@ class DataReferenceBox(Jp2kBox):
|
||||||
"""Verify that the box obeys the specifications for writing.
|
"""Verify that the box obeys the specifications for writing.
|
||||||
"""
|
"""
|
||||||
if len(self.DR) == 0:
|
if len(self.DR) == 0:
|
||||||
msg = "A data reference box cannot be empty when written to a file."
|
msg = "A data reference box cannot be empty when written to a "
|
||||||
|
msg += "file."
|
||||||
self._dispatch_validation_error(msg, writing=True)
|
self._dispatch_validation_error(msg, writing=True)
|
||||||
self._validate(writing=True)
|
self._validate(writing=True)
|
||||||
|
|
||||||
|
|
@ -1144,7 +1150,7 @@ class DataReferenceBox(Jp2kBox):
|
||||||
|
|
||||||
def __str__(self):
|
def __str__(self):
|
||||||
msg = Jp2kBox.__str__(self)
|
msg = Jp2kBox.__str__(self)
|
||||||
if _printoptions['short'] == True:
|
if _printoptions['short'] is True:
|
||||||
return msg
|
return msg
|
||||||
|
|
||||||
for box in self.DR:
|
for box in self.DR:
|
||||||
|
|
@ -1247,7 +1253,7 @@ class FileTypeBox(Jp2kBox):
|
||||||
|
|
||||||
def __str__(self):
|
def __str__(self):
|
||||||
msg = Jp2kBox.__str__(self)
|
msg = Jp2kBox.__str__(self)
|
||||||
if _printoptions['short'] == True:
|
if _printoptions['short'] is True:
|
||||||
return msg
|
return msg
|
||||||
|
|
||||||
lst = [msg,
|
lst = [msg,
|
||||||
|
|
@ -1310,12 +1316,18 @@ class FileTypeBox(Jp2kBox):
|
||||||
brand = brand.decode('utf-8')
|
brand = brand.decode('utf-8')
|
||||||
|
|
||||||
# Extract the compatibility list. Each entry has 4 bytes.
|
# Extract the compatibility list. Each entry has 4 bytes.
|
||||||
num_entries = int((length - 16)/ 4)
|
num_entries = int((length - 16) / 4)
|
||||||
compatibility_list = []
|
compatibility_list = []
|
||||||
for j in range(int(num_entries)):
|
for j in range(int(num_entries)):
|
||||||
entry, = struct.unpack_from('>4s', read_buffer, 8 + j * 4)
|
entry, = struct.unpack_from('>4s', read_buffer, 8 + j * 4)
|
||||||
if sys.hexversion >= 0x03000000:
|
if sys.hexversion >= 0x03000000:
|
||||||
entry = entry.decode('utf-8')
|
try:
|
||||||
|
entry = entry.decode('utf-8')
|
||||||
|
except UnicodeDecodeError:
|
||||||
|
# The entry is invalid, but we've got code to catch this
|
||||||
|
# later on.
|
||||||
|
pass
|
||||||
|
|
||||||
compatibility_list.append(entry)
|
compatibility_list.append(entry)
|
||||||
|
|
||||||
return cls(brand=brand, minor_version=minor_version,
|
return cls(brand=brand, minor_version=minor_version,
|
||||||
|
|
@ -1373,7 +1385,7 @@ class FragmentListBox(Jp2kBox):
|
||||||
|
|
||||||
def __str__(self):
|
def __str__(self):
|
||||||
msg = Jp2kBox.__str__(self)
|
msg = Jp2kBox.__str__(self)
|
||||||
if _printoptions['short'] == True:
|
if _printoptions['short'] is True:
|
||||||
return msg
|
return msg
|
||||||
|
|
||||||
for j in range(len(self.fragment_offset)):
|
for j in range(len(self.fragment_offset)):
|
||||||
|
|
@ -1457,7 +1469,10 @@ class FragmentTableBox(Jp2kBox):
|
||||||
|
|
||||||
def __repr__(self):
|
def __repr__(self):
|
||||||
msg = "glymur.jp2box.FragmentTableBox(box={0})"
|
msg = "glymur.jp2box.FragmentTableBox(box={0})"
|
||||||
msg = msg.format(None) if (len(self.box) == 0) else msg.format(self.box)
|
if len(self.box) == 0:
|
||||||
|
msg = msg.format(None)
|
||||||
|
else:
|
||||||
|
msg = msg.format(self.box)
|
||||||
return msg
|
return msg
|
||||||
|
|
||||||
def __str__(self):
|
def __str__(self):
|
||||||
|
|
@ -1504,7 +1519,6 @@ class FragmentTableBox(Jp2kBox):
|
||||||
self._write_superbox(fptr, b'ftbl')
|
self._write_superbox(fptr, b'ftbl')
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
class FreeBox(Jp2kBox):
|
class FreeBox(Jp2kBox):
|
||||||
"""Container for JPX free box information.
|
"""Container for JPX free box information.
|
||||||
|
|
||||||
|
|
@ -1533,7 +1547,7 @@ class FreeBox(Jp2kBox):
|
||||||
|
|
||||||
def __str__(self):
|
def __str__(self):
|
||||||
msg = Jp2kBox.__str__(self)
|
msg = Jp2kBox.__str__(self)
|
||||||
if _printoptions['short'] == True:
|
if _printoptions['short'] is True:
|
||||||
return msg
|
return msg
|
||||||
|
|
||||||
return msg
|
return msg
|
||||||
|
|
@ -1629,7 +1643,7 @@ class ImageHeaderBox(Jp2kBox):
|
||||||
|
|
||||||
def __str__(self):
|
def __str__(self):
|
||||||
msg = Jp2kBox.__str__(self)
|
msg = Jp2kBox.__str__(self)
|
||||||
if _printoptions['short'] == True:
|
if _printoptions['short'] is True:
|
||||||
return msg
|
return msg
|
||||||
|
|
||||||
msg = "{0}"
|
msg = "{0}"
|
||||||
|
|
@ -1860,7 +1874,7 @@ class JPEG2000SignatureBox(Jp2kBox):
|
||||||
|
|
||||||
def __str__(self):
|
def __str__(self):
|
||||||
msg = Jp2kBox.__str__(self)
|
msg = Jp2kBox.__str__(self)
|
||||||
if _printoptions['short'] == True:
|
if _printoptions['short'] is True:
|
||||||
return msg
|
return msg
|
||||||
|
|
||||||
msg += '\n Signature: {0:02x}{1:02x}{2:02x}{3:02x}'
|
msg += '\n Signature: {0:02x}{1:02x}{2:02x}{3:02x}'
|
||||||
|
|
@ -1949,7 +1963,7 @@ class PaletteBox(Jp2kBox):
|
||||||
|
|
||||||
def __str__(self):
|
def __str__(self):
|
||||||
msg = Jp2kBox.__str__(self)
|
msg = Jp2kBox.__str__(self)
|
||||||
if _printoptions['short'] == True:
|
if _printoptions['short'] is True:
|
||||||
return msg
|
return msg
|
||||||
|
|
||||||
msg += '\n Size: ({0} x {1})'.format(*self.palette.shape)
|
msg += '\n Size: ({0} x {1})'.format(*self.palette.shape)
|
||||||
|
|
@ -1979,7 +1993,6 @@ class PaletteBox(Jp2kBox):
|
||||||
*bps_signed)
|
*bps_signed)
|
||||||
fptr.write(write_buffer)
|
fptr.write(write_buffer)
|
||||||
|
|
||||||
bps = self.bits_per_component
|
|
||||||
# All components are the same. Writing is straightforward.
|
# All components are the same. Writing is straightforward.
|
||||||
if self.bits_per_component[0] <= 8:
|
if self.bits_per_component[0] <= 8:
|
||||||
write_buffer = memoryview(self.palette.astype(np.uint8))
|
write_buffer = memoryview(self.palette.astype(np.uint8))
|
||||||
|
|
@ -2019,13 +2032,10 @@ class PaletteBox(Jp2kBox):
|
||||||
# Ok the palette has the same datatype for all columns. We should
|
# Ok the palette has the same datatype for all columns. We should
|
||||||
# be able to efficiently read it.
|
# be able to efficiently read it.
|
||||||
if bps[0] <= 8:
|
if bps[0] <= 8:
|
||||||
nbytes_per_row = ncols
|
|
||||||
dtype = np.uint8
|
dtype = np.uint8
|
||||||
elif bps[0] <= 16:
|
elif bps[0] <= 16:
|
||||||
nbytes_per_row = 2 * ncols
|
|
||||||
dtype = np.uint16
|
dtype = np.uint16
|
||||||
elif bps[0] <= 32:
|
elif bps[0] <= 32:
|
||||||
nbytes_per_row = 3 * ncols
|
|
||||||
dtype = np.uint32
|
dtype = np.uint32
|
||||||
|
|
||||||
palette = np.frombuffer(read_buffer[3 + ncols:], dtype=dtype)
|
palette = np.frombuffer(read_buffer[3 + ncols:], dtype=dtype)
|
||||||
|
|
@ -2069,80 +2079,80 @@ _READER_REQUIREMENTS_DISPLAY = {
|
||||||
7: 'JPEG codestream as defined in ISO/IEC 10918-1',
|
7: 'JPEG codestream as defined in ISO/IEC 10918-1',
|
||||||
8: 'Deprecated - does not contain opacity',
|
8: 'Deprecated - does not contain opacity',
|
||||||
9: 'Non-premultiplied opacity channel',
|
9: 'Non-premultiplied opacity channel',
|
||||||
10: 'Premultiplied opacity channel',
|
10: 'Premultiplied opacity channel',
|
||||||
11: 'Chroma-key based opacity',
|
11: 'Chroma-key based opacity',
|
||||||
12: 'Deprecated - codestream is contiguous',
|
12: 'Deprecated - codestream is contiguous',
|
||||||
13: 'Fragmented codestream where all fragments are in file and in order',
|
13: 'Fragmented codestream where all fragments are in file and in order',
|
||||||
14: 'Fragmented codestream where all fragments are in file '
|
14: ('Fragmented codestream where all fragments are in file '
|
||||||
+ 'but are out of order',
|
'but are out of order'),
|
||||||
15: 'Fragmented codestream where not all fragments are within the file '
|
15: ('Fragmented codestream where not all fragments are within the file '
|
||||||
+ 'but are all in locally accessible files',
|
'but are all in locally accessible files'),
|
||||||
16: 'Fragmented codestream where some fragments may be accessible '
|
16: ('Fragmented codestream where some fragments may be accessible '
|
||||||
+ 'only through a URL specified network connection',
|
'only through a URL specified network connection'),
|
||||||
17: 'Compositing required to produce rendered result from multiple '
|
17: ('Compositing required to produce rendered result from multiple '
|
||||||
+ 'compositing layers',
|
'compositing layers'),
|
||||||
18: 'Deprecated - support for compositing is not required',
|
18: 'Deprecated - support for compositing is not required',
|
||||||
19: 'Deprecated - contains multiple, discrete layers that should not '
|
19: ('Deprecated - contains multiple, discrete layers that should not '
|
||||||
+ 'be combined through either animation or compositing',
|
'be combined through either animation or compositing'),
|
||||||
20: 'Deprecated - compositing layers each contain only a single '
|
20: ('Deprecated - compositing layers each contain only a single '
|
||||||
+ 'codestream',
|
'codestream'),
|
||||||
21: 'At least one compositing layer consists of multiple codestreams',
|
21: 'At least one compositing layer consists of multiple codestreams',
|
||||||
22: 'Deprecated - all compositing layers are in the same colourspace',
|
22: 'Deprecated - all compositing layers are in the same colourspace',
|
||||||
23: 'Colourspace transformations are required to combine compositing '
|
23: ('Colourspace transformations are required to combine compositing '
|
||||||
+ 'layers; not all compositing layers are in the same colourspace',
|
'layers; not all compositing layers are in the same colourspace'),
|
||||||
24: 'Deprecated - rendered result created without using animation',
|
24: 'Deprecated - rendered result created without using animation',
|
||||||
25: 'Deprecated - animated, but first layer covers entire area and is '
|
25: ('Deprecated - animated, but first layer covers entire area and is '
|
||||||
+ 'opaque',
|
'opaque'),
|
||||||
26: 'First animation layer does not cover entire rendered result',
|
26: 'First animation layer does not cover entire rendered result',
|
||||||
27: 'Deprecated - animated, and no layer is reused',
|
27: 'Deprecated - animated, and no layer is reused',
|
||||||
28: 'Reuse of animation layers',
|
28: 'Reuse of animation layers',
|
||||||
29: 'Deprecated - animated, but layers are reused',
|
29: 'Deprecated - animated, but layers are reused',
|
||||||
30: 'Some animated frames are non-persistent',
|
30: 'Some animated frames are non-persistent',
|
||||||
31: 'Deprecated - rendered result created without using scaling',
|
31: 'Deprecated - rendered result created without using scaling',
|
||||||
32: 'Rendered result involves scaling within a layer',
|
32: 'Rendered result involves scaling within a layer',
|
||||||
33: 'Rendered result involves scaling between layers',
|
33: 'Rendered result involves scaling between layers',
|
||||||
34: 'ROI metadata',
|
34: 'ROI metadata',
|
||||||
35: 'IPR metadata',
|
35: 'IPR metadata',
|
||||||
36: 'Content metadata',
|
36: 'Content metadata',
|
||||||
37: 'History metadata',
|
37: 'History metadata',
|
||||||
38: 'Creation metadata',
|
38: 'Creation metadata',
|
||||||
39: 'JPX digital signatures',
|
39: 'JPX digital signatures',
|
||||||
40: 'JPX checksums',
|
40: 'JPX checksums',
|
||||||
41: 'Desires Graphics Arts Reproduction specified',
|
41: 'Desires Graphics Arts Reproduction specified',
|
||||||
42: 'Deprecated - compositing layer uses palettized colour',
|
42: 'Deprecated - compositing layer uses palettized colour',
|
||||||
43: 'Deprecated - compositing layer uses restricted ICC profile',
|
43: 'Deprecated - compositing layer uses restricted ICC profile',
|
||||||
44: 'Compositing layer uses Any ICC profile',
|
44: 'Compositing layer uses Any ICC profile',
|
||||||
45: 'Deprecated - compositing layer uses sRGB enumerated colourspace',
|
45: 'Deprecated - compositing layer uses sRGB enumerated colourspace',
|
||||||
46: 'Deprecated - compositing layer uses sRGB-grey enumerated colourspace',
|
46: 'Deprecated - compositing layer uses sRGB-grey enumerated colourspace',
|
||||||
47: 'BiLevel 1 enumerated colourspace',
|
47: 'BiLevel 1 enumerated colourspace',
|
||||||
48: 'BiLevel 2 enumerated colourspace',
|
48: 'BiLevel 2 enumerated colourspace',
|
||||||
49: 'YCbCr 1 enumerated colourspace',
|
49: 'YCbCr 1 enumerated colourspace',
|
||||||
50: 'YCbCr 2 enumerated colourspace',
|
50: 'YCbCr 2 enumerated colourspace',
|
||||||
51: 'YCbCr 3 enumerated colourspace',
|
51: 'YCbCr 3 enumerated colourspace',
|
||||||
52: 'PhotoYCC enumerated colourspace',
|
52: 'PhotoYCC enumerated colourspace',
|
||||||
53: 'YCCK enumerated colourspace',
|
53: 'YCCK enumerated colourspace',
|
||||||
54: 'CMY enumerated colourspace',
|
54: 'CMY enumerated colourspace',
|
||||||
55: 'CMYK enumerated colorspace',
|
55: 'CMYK enumerated colorspace',
|
||||||
56: 'CIELab enumerated colourspace with default parameters',
|
56: 'CIELab enumerated colourspace with default parameters',
|
||||||
57: 'CIELab enumerated colourspace with non-default parameters',
|
57: 'CIELab enumerated colourspace with non-default parameters',
|
||||||
58: 'CIEJab enumerated colourspace with default parameters',
|
58: 'CIEJab enumerated colourspace with default parameters',
|
||||||
59: 'CIEJab enumerated colourspace with non-default parameters',
|
59: 'CIEJab enumerated colourspace with non-default parameters',
|
||||||
60: 'e-sRGB enumerated colorspace',
|
60: 'e-sRGB enumerated colorspace',
|
||||||
61: 'ROMM_RGB enumerated colorspace',
|
61: 'ROMM_RGB enumerated colorspace',
|
||||||
62: 'Non-square samples',
|
62: 'Non-square samples',
|
||||||
63: 'Deprecated - compositing layers have labels',
|
63: 'Deprecated - compositing layers have labels',
|
||||||
64: 'Deprecated - codestreams have labels',
|
64: 'Deprecated - codestreams have labels',
|
||||||
65: 'Deprecated - compositing layers have different colour spaces',
|
65: 'Deprecated - compositing layers have different colour spaces',
|
||||||
66: 'Deprecated - compositing layers have different metadata',
|
66: 'Deprecated - compositing layers have different metadata',
|
||||||
67: 'GIS metadata XML box',
|
67: 'GIS metadata XML box',
|
||||||
68: 'JPSEC extensions in codestream as specified by ISO/IEC 15444-8',
|
68: 'JPSEC extensions in codestream as specified by ISO/IEC 15444-8',
|
||||||
69: 'JP3D extensions in codestream as specified by ISO/IEC 15444-10',
|
69: 'JP3D extensions in codestream as specified by ISO/IEC 15444-10',
|
||||||
70: 'Deprecated - compositing layer uses sYCC enumerated colour space',
|
70: 'Deprecated - compositing layer uses sYCC enumerated colour space',
|
||||||
71: 'e-sYCC enumerated colourspace',
|
71: 'e-sYCC enumerated colourspace',
|
||||||
72: 'JPEG 2000 Part 2 codestream as restricted by baseline conformance '
|
72: ('JPEG 2000 Part 2 codestream as restricted by baseline conformance '
|
||||||
+ 'requirements in M.9.2.3',
|
'requirements in M.9.2.3'),
|
||||||
73: 'YPbPr(1125/60) enumerated colourspace',
|
73: 'YPbPr(1125/60) enumerated colourspace',
|
||||||
74: 'YPbPr(1250/50) enumerated colourspace'}
|
74: 'YPbPr(1250/50) enumerated colourspace'}
|
||||||
|
|
||||||
|
|
||||||
class ReaderRequirementsBox(Jp2kBox):
|
class ReaderRequirementsBox(Jp2kBox):
|
||||||
|
|
@ -2202,10 +2212,11 @@ class ReaderRequirementsBox(Jp2kBox):
|
||||||
|
|
||||||
def __str__(self):
|
def __str__(self):
|
||||||
msg = Jp2kBox.__str__(self)
|
msg = Jp2kBox.__str__(self)
|
||||||
if _printoptions['short'] == True:
|
if _printoptions['short'] is True:
|
||||||
return msg
|
return msg
|
||||||
|
|
||||||
msg += '\n Fully Understands Aspect Mask: 0x{0:x}'.format(self.fuam)
|
msg += '\n Fully Understands Aspect Mask: 0x{0:x}'
|
||||||
|
msg = msg.format(self.fuam)
|
||||||
msg += '\n Display Completely Mask: 0x{0:x}'.format(self.dcm)
|
msg += '\n Display Completely Mask: 0x{0:x}'.format(self.dcm)
|
||||||
|
|
||||||
msg += '\n Standard Features and Masks:'
|
msg += '\n Standard Features and Masks:'
|
||||||
|
|
@ -2261,7 +2272,8 @@ class ReaderRequirementsBox(Jp2kBox):
|
||||||
standard_flag, standard_mask = data
|
standard_flag, standard_mask = data
|
||||||
|
|
||||||
nflags = len(standard_flag)
|
nflags = len(standard_flag)
|
||||||
vendor_offset = 1 + 2 * mask_length + 2 + (2 + mask_length) * nflags
|
vendor_offset = (1 + 2 * mask_length + 2
|
||||||
|
+ (2 + mask_length) * nflags)
|
||||||
data = _parse_vendor_features(read_buffer[vendor_offset:],
|
data = _parse_vendor_features(read_buffer[vendor_offset:],
|
||||||
mask_length)
|
mask_length)
|
||||||
vendor_feature, vendor_mask = data
|
vendor_feature, vendor_mask = data
|
||||||
|
|
@ -2318,8 +2330,8 @@ def _parse_rreq3(read_buffer, length, offset):
|
||||||
read_buffer = read_buffer[9 + num_standard_features * 10:]
|
read_buffer = read_buffer[9 + num_standard_features * 10:]
|
||||||
for j in range(num_vendor_features):
|
for j in range(num_vendor_features):
|
||||||
uslice = slice(j * entry_length, (j + 1) * entry_length)
|
uslice = slice(j * entry_length, (j + 1) * entry_length)
|
||||||
ubuffer = read_buffer[slice]
|
ubuffer = read_buffer[uslice]
|
||||||
vendor_feature.append(uuid.UUID(bytes=ubuffer[0:16]))
|
vendor_feature.append(UUID(bytes=ubuffer[0:16]))
|
||||||
|
|
||||||
lst = struct.unpack('>BBB', ubuffer[16:])
|
lst = struct.unpack('>BBB', ubuffer[16:])
|
||||||
vmask = lst[0] << 16 | lst[1] << 8 | lst[2]
|
vmask = lst[0] << 16 | lst[1] << 8 | lst[2]
|
||||||
|
|
@ -2347,14 +2359,11 @@ def _parse_standard_flag(read_buffer, mask_length):
|
||||||
# from the buffer read from file.
|
# from the buffer read from file.
|
||||||
mask_format = {1: 'B', 2: 'H', 4: 'I'}[mask_length]
|
mask_format = {1: 'B', 2: 'H', 4: 'I'}[mask_length]
|
||||||
|
|
||||||
#read_buffer = fptr.read(2)
|
|
||||||
num_standard_flags, = struct.unpack_from('>H', read_buffer, offset=0)
|
num_standard_flags, = struct.unpack_from('>H', read_buffer, offset=0)
|
||||||
|
|
||||||
# Read in standard flags and standard masks. Each standard flag should
|
# Read in standard flags and standard masks. Each standard flag should
|
||||||
# be two bytes, but the standard mask flag is as long as specified by
|
# be two bytes, but the standard mask flag is as long as specified by
|
||||||
# the mask length.
|
# the mask length.
|
||||||
#read_buffer = fptr.read(num_standard_flags * (2 + mask_length))
|
|
||||||
|
|
||||||
fmt = '>' + ('H' + mask_format) * num_standard_flags
|
fmt = '>' + ('H' + mask_format) * num_standard_flags
|
||||||
data = struct.unpack_from(fmt, read_buffer, offset=2)
|
data = struct.unpack_from(fmt, read_buffer, offset=2)
|
||||||
|
|
||||||
|
|
@ -2385,13 +2394,12 @@ def _parse_vendor_features(read_buffer, mask_length):
|
||||||
# Each vendor feature consists of a 16-byte UUID plus a mask whose
|
# Each vendor feature consists of a 16-byte UUID plus a mask whose
|
||||||
# length is specified by, you guessed it, "mask_length".
|
# length is specified by, you guessed it, "mask_length".
|
||||||
entry_length = 16 + mask_length
|
entry_length = 16 + mask_length
|
||||||
#read_buffer = fptr.read(num_vendor_features * entry_length)
|
|
||||||
vendor_feature = []
|
vendor_feature = []
|
||||||
vendor_mask = []
|
vendor_mask = []
|
||||||
for j in range(num_vendor_features):
|
for j in range(num_vendor_features):
|
||||||
uslice = slice(2 + j * entry_length, 2 + (j + 1) * entry_length)
|
uslice = slice(2 + j * entry_length, 2 + (j + 1) * entry_length)
|
||||||
ubuffer = read_buffer[uslice]
|
ubuffer = read_buffer[uslice]
|
||||||
vendor_feature.append(uuid.UUID(bytes=ubuffer[0:16]))
|
vendor_feature.append(UUID(bytes=ubuffer[0:16]))
|
||||||
|
|
||||||
vmask = struct.unpack('>' + mask_format, ubuffer[16:])
|
vmask = struct.unpack('>' + mask_format, ubuffer[16:])
|
||||||
vendor_mask.append(vmask)
|
vendor_mask.append(vmask)
|
||||||
|
|
@ -2493,7 +2501,7 @@ class CaptureResolutionBox(Jp2kBox):
|
||||||
|
|
||||||
def __str__(self):
|
def __str__(self):
|
||||||
msg = Jp2kBox.__str__(self)
|
msg = Jp2kBox.__str__(self)
|
||||||
if _printoptions['short'] == True:
|
if _printoptions['short'] is True:
|
||||||
return msg
|
return msg
|
||||||
|
|
||||||
msg += '\n VCR: {0}'.format(self.vertical_resolution)
|
msg += '\n VCR: {0}'.format(self.vertical_resolution)
|
||||||
|
|
@ -2559,7 +2567,7 @@ class DisplayResolutionBox(Jp2kBox):
|
||||||
|
|
||||||
def __str__(self):
|
def __str__(self):
|
||||||
msg = Jp2kBox.__str__(self)
|
msg = Jp2kBox.__str__(self)
|
||||||
if _printoptions['short'] == True:
|
if _printoptions['short'] is True:
|
||||||
return msg
|
return msg
|
||||||
|
|
||||||
msg += '\n VDR: {0}'.format(self.vertical_resolution)
|
msg += '\n VDR: {0}'.format(self.vertical_resolution)
|
||||||
|
|
@ -2619,7 +2627,7 @@ class LabelBox(Jp2kBox):
|
||||||
|
|
||||||
def __str__(self):
|
def __str__(self):
|
||||||
msg = Jp2kBox.__str__(self)
|
msg = Jp2kBox.__str__(self)
|
||||||
if _printoptions['short'] == True:
|
if _printoptions['short'] is True:
|
||||||
return msg
|
return msg
|
||||||
|
|
||||||
msg += '\n Label: {0}'.format(self.label)
|
msg += '\n Label: {0}'.format(self.label)
|
||||||
|
|
@ -2687,7 +2695,7 @@ class NumberListBox(Jp2kBox):
|
||||||
|
|
||||||
def __str__(self):
|
def __str__(self):
|
||||||
msg = Jp2kBox.__str__(self)
|
msg = Jp2kBox.__str__(self)
|
||||||
if _printoptions['short'] == True:
|
if _printoptions['short'] is True:
|
||||||
return msg
|
return msg
|
||||||
|
|
||||||
for j, association in enumerate(self.associations):
|
for j, association in enumerate(self.associations):
|
||||||
|
|
@ -2737,7 +2745,8 @@ class NumberListBox(Jp2kBox):
|
||||||
def write(self, fptr):
|
def write(self, fptr):
|
||||||
"""Write a NumberList box to file.
|
"""Write a NumberList box to file.
|
||||||
"""
|
"""
|
||||||
fptr.write(struct.pack('>I4s', len(self.associations) * 4 + 8, b'nlst'))
|
fptr.write(struct.pack('>I4s',
|
||||||
|
len(self.associations) * 4 + 8, b'nlst'))
|
||||||
|
|
||||||
fmt = '>' + 'I' * len(self.associations)
|
fmt = '>' + 'I' * len(self.associations)
|
||||||
write_buffer = struct.pack(fmt, *self.associations)
|
write_buffer = struct.pack(fmt, *self.associations)
|
||||||
|
|
@ -2789,9 +2798,9 @@ class XMLBox(Jp2kBox):
|
||||||
|
|
||||||
def __str__(self):
|
def __str__(self):
|
||||||
msg = Jp2kBox.__str__(self)
|
msg = Jp2kBox.__str__(self)
|
||||||
if _printoptions['short'] == True:
|
if _printoptions['short'] is True:
|
||||||
return msg
|
return msg
|
||||||
if _printoptions['xml'] == False:
|
if _printoptions['xml'] is False:
|
||||||
return msg
|
return msg
|
||||||
|
|
||||||
msg += '\n'
|
msg += '\n'
|
||||||
|
|
@ -2910,7 +2919,7 @@ class UUIDListBox(Jp2kBox):
|
||||||
|
|
||||||
def __str__(self):
|
def __str__(self):
|
||||||
msg = Jp2kBox.__str__(self)
|
msg = Jp2kBox.__str__(self)
|
||||||
if _printoptions['short'] == True:
|
if _printoptions['short'] is True:
|
||||||
return msg
|
return msg
|
||||||
|
|
||||||
for j, uuid_item in enumerate(self.ulst):
|
for j, uuid_item in enumerate(self.ulst):
|
||||||
|
|
@ -2941,8 +2950,8 @@ class UUIDListBox(Jp2kBox):
|
||||||
|
|
||||||
ulst = []
|
ulst = []
|
||||||
for j in range(num_uuids):
|
for j in range(num_uuids):
|
||||||
uuid_buffer = read_buffer[2 + j * 16 : 2 + (j + 1) * 16]
|
uuid_buffer = read_buffer[2 + j * 16:2 + (j + 1) * 16]
|
||||||
ulst.append(uuid.UUID(bytes=uuid_buffer))
|
ulst.append(UUID(bytes=uuid_buffer))
|
||||||
|
|
||||||
return cls(ulst, length=length, offset=offset)
|
return cls(ulst, length=length, offset=offset)
|
||||||
|
|
||||||
|
|
@ -3055,7 +3064,6 @@ class DataEntryURLBox(Jp2kBox):
|
||||||
fptr.write(write_buffer)
|
fptr.write(write_buffer)
|
||||||
fptr.write(url)
|
fptr.write(url)
|
||||||
|
|
||||||
|
|
||||||
def __repr__(self):
|
def __repr__(self):
|
||||||
msg = "glymur.jp2box.DataEntryURLBox({0}, {1}, '{2}')"
|
msg = "glymur.jp2box.DataEntryURLBox({0}, {1}, '{2}')"
|
||||||
msg = msg.format(self.version, self.flag, self.url)
|
msg = msg.format(self.version, self.flag, self.url)
|
||||||
|
|
@ -3063,7 +3071,7 @@ class DataEntryURLBox(Jp2kBox):
|
||||||
|
|
||||||
def __str__(self):
|
def __str__(self):
|
||||||
msg = Jp2kBox.__str__(self)
|
msg = Jp2kBox.__str__(self)
|
||||||
if _printoptions['short'] == True:
|
if _printoptions['short'] is True:
|
||||||
return msg
|
return msg
|
||||||
|
|
||||||
msg += '\n '
|
msg += '\n '
|
||||||
|
|
@ -3201,7 +3209,7 @@ class UUIDBox(Jp2kBox):
|
||||||
"""
|
"""
|
||||||
Private function for parsing UUID payloads if possible.
|
Private function for parsing UUID payloads if possible.
|
||||||
"""
|
"""
|
||||||
if self.uuid == uuid.UUID('be7acfcb-97a9-42e8-9c71-999491e3afac'):
|
if self.uuid == UUID('be7acfcb-97a9-42e8-9c71-999491e3afac'):
|
||||||
self.data = _uuid_io.xml(self.raw_data)
|
self.data = _uuid_io.xml(self.raw_data)
|
||||||
elif self.uuid.bytes == b'JpgTiffExif->JP2':
|
elif self.uuid.bytes == b'JpgTiffExif->JP2':
|
||||||
self.data = _uuid_io.tiff_header(self.raw_data)
|
self.data = _uuid_io.tiff_header(self.raw_data)
|
||||||
|
|
@ -3215,23 +3223,23 @@ class UUIDBox(Jp2kBox):
|
||||||
|
|
||||||
def __str__(self):
|
def __str__(self):
|
||||||
msg = Jp2kBox.__str__(self)
|
msg = Jp2kBox.__str__(self)
|
||||||
if _printoptions['short'] == True:
|
if _printoptions['short'] is True:
|
||||||
return msg
|
return msg
|
||||||
|
|
||||||
msg = '{0}\n UUID: {1}'.format(msg, self.uuid)
|
msg = '{0}\n UUID: {1}'.format(msg, self.uuid)
|
||||||
if self.uuid == uuid.UUID('be7acfcb-97a9-42e8-9c71-999491e3afac'):
|
if self.uuid == UUID('be7acfcb-97a9-42e8-9c71-999491e3afac'):
|
||||||
msg += ' (XMP)'
|
msg += ' (XMP)'
|
||||||
elif self.uuid.bytes == b'JpgTiffExif->JP2':
|
elif self.uuid.bytes == b'JpgTiffExif->JP2':
|
||||||
msg += ' (EXIF)'
|
msg += ' (EXIF)'
|
||||||
else:
|
else:
|
||||||
msg += ' (unknown)'
|
msg += ' (unknown)'
|
||||||
|
|
||||||
if (((_printoptions['xml'] == False) and
|
if (((_printoptions['xml'] is False) and
|
||||||
(self.uuid == uuid.UUID('be7acfcb-97a9-42e8-9c71-999491e3afac')))):
|
(self.uuid == UUID('be7acfcb-97a9-42e8-9c71-999491e3afac')))):
|
||||||
# If it's an XMP UUID, don't print the XML contents.
|
# If it's an XMP UUID, don't print the XML contents.
|
||||||
return msg
|
return msg
|
||||||
|
|
||||||
if self.uuid == uuid.UUID('be7acfcb-97a9-42e8-9c71-999491e3afac'):
|
if self.uuid == UUID('be7acfcb-97a9-42e8-9c71-999491e3afac'):
|
||||||
line = '\n UUID Data:\n{0}'
|
line = '\n UUID Data:\n{0}'
|
||||||
xmlstring = ET.tostring(self.data,
|
xmlstring = ET.tostring(self.data,
|
||||||
encoding='utf-8',
|
encoding='utf-8',
|
||||||
|
|
@ -3274,7 +3282,7 @@ class UUIDBox(Jp2kBox):
|
||||||
"""
|
"""
|
||||||
num_bytes = offset + length - fptr.tell()
|
num_bytes = offset + length - fptr.tell()
|
||||||
read_buffer = fptr.read(num_bytes)
|
read_buffer = fptr.read(num_bytes)
|
||||||
the_uuid = uuid.UUID(bytes=read_buffer[0:16])
|
the_uuid = UUID(bytes=read_buffer[0:16])
|
||||||
return cls(the_uuid, read_buffer[16:], length=length, offset=offset)
|
return cls(the_uuid, read_buffer[16:], length=length, offset=offset)
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -3309,18 +3317,20 @@ _BOX_WITH_ID = {
|
||||||
b'uuid': UUIDBox,
|
b'uuid': UUIDBox,
|
||||||
b'xml ': XMLBox}
|
b'xml ': XMLBox}
|
||||||
|
|
||||||
_parseoptions = {'codestream': True}
|
_parseoptions = {'full_codestream': False}
|
||||||
|
|
||||||
def set_parseoptions(codestream=True):
|
|
||||||
|
def set_parseoptions(full_codestream=True):
|
||||||
"""Set parsing options.
|
"""Set parsing options.
|
||||||
|
|
||||||
These options determine the way JPEG 2000 boxes are parsed.
|
These options determine the way JPEG 2000 boxes are parsed.
|
||||||
|
|
||||||
Parameters
|
Parameters
|
||||||
----------
|
----------
|
||||||
codestream : bool, defaults to True
|
full_codestream : bool, defaults to True
|
||||||
When False, the codestream header is only parsed when accessed. This
|
When False, only the codestream header is parsed for metadata. This
|
||||||
can results in faster JP2/JPX parsing.
|
can results in faster JP2/JPX parsing. When True, the entire
|
||||||
|
codestream is parsed for metadata.
|
||||||
|
|
||||||
See also
|
See also
|
||||||
--------
|
--------
|
||||||
|
|
@ -3331,9 +3341,10 @@ def set_parseoptions(codestream=True):
|
||||||
To put back the default options, you can use:
|
To put back the default options, you can use:
|
||||||
|
|
||||||
>>> import glymur
|
>>> import glymur
|
||||||
>>> glymur.set_parseoptions(codestream=True)
|
>>> glymur.set_parseoptions(full_codestream=True)
|
||||||
"""
|
"""
|
||||||
_parseoptions['codestream'] = codestream
|
_parseoptions['full_codestream'] = full_codestream
|
||||||
|
|
||||||
|
|
||||||
def get_parseoptions():
|
def get_parseoptions():
|
||||||
"""Return the current parsing options.
|
"""Return the current parsing options.
|
||||||
|
|
@ -3355,6 +3366,7 @@ def get_parseoptions():
|
||||||
|
|
||||||
_printoptions = {'short': False, 'xml': True, 'codestream': True}
|
_printoptions = {'short': False, 'xml': True, 'codestream': True}
|
||||||
|
|
||||||
|
|
||||||
def set_printoptions(**kwargs):
|
def set_printoptions(**kwargs):
|
||||||
"""Set printing options.
|
"""Set printing options.
|
||||||
|
|
||||||
|
|
@ -3364,12 +3376,15 @@ def set_printoptions(**kwargs):
|
||||||
----------
|
----------
|
||||||
short : bool, optional
|
short : bool, optional
|
||||||
When True, only the box ID, offset, and length are displayed. Useful
|
When True, only the box ID, offset, and length are displayed. Useful
|
||||||
for displaying only the basic structure or skeleton of a JPEG 2000 file.
|
for displaying only the basic structure or skeleton of a JPEG 2000
|
||||||
|
file.
|
||||||
xml : bool, optional
|
xml : bool, optional
|
||||||
When False, printing of the XML contents of any XML boxes or UUID XMP
|
When False, printing of the XML contents of any XML boxes or UUID XMP
|
||||||
boxes is suppressed.
|
boxes is suppressed.
|
||||||
codestream : bool, optional
|
codestream : bool, optional
|
||||||
When False, printing of the codestream contents is suppressed.
|
When False, only the codestream header is printed. When True, the
|
||||||
|
entire codestream is printed. This option has no effect when the
|
||||||
|
'short' option is set to True.
|
||||||
|
|
||||||
See also
|
See also
|
||||||
--------
|
--------
|
||||||
|
|
@ -3387,6 +3402,7 @@ def set_printoptions(**kwargs):
|
||||||
raise TypeError('"{0}" not a valid keyword parameter.'.format(key))
|
raise TypeError('"{0}" not a valid keyword parameter.'.format(key))
|
||||||
_printoptions[key] = value
|
_printoptions[key] = value
|
||||||
|
|
||||||
|
|
||||||
def get_printoptions():
|
def get_printoptions():
|
||||||
"""Return the current print options.
|
"""Return the current print options.
|
||||||
|
|
||||||
|
|
@ -3406,5 +3422,3 @@ def get_printoptions():
|
||||||
set_printoptions
|
set_printoptions
|
||||||
"""
|
"""
|
||||||
return _printoptions
|
return _printoptions
|
||||||
|
|
||||||
|
|
||||||
|
|
|
||||||
1147
glymur/jp2k.py
1147
glymur/jp2k.py
File diff suppressed because it is too large
Load diff
|
|
@ -2,3 +2,5 @@
|
||||||
from . import openjp2 as openjp2
|
from . import openjp2 as openjp2
|
||||||
from . import openjpeg as openjpeg
|
from . import openjpeg as openjpeg
|
||||||
from . import c
|
from . import c
|
||||||
|
|
||||||
|
__all__ = [openjp2, openjpeg, c]
|
||||||
|
|
|
||||||
|
|
@ -1,9 +1,6 @@
|
||||||
"""
|
"""
|
||||||
Configure glymur to use installed libraries if possible.
|
Configure glymur to use installed libraries if possible.
|
||||||
"""
|
"""
|
||||||
# configparser is new in python3 (pylint/python-2.7)
|
|
||||||
# pylint: disable=F0401
|
|
||||||
|
|
||||||
import ctypes
|
import ctypes
|
||||||
from ctypes.util import find_library
|
from ctypes.util import find_library
|
||||||
import os
|
import os
|
||||||
|
|
@ -18,6 +15,22 @@ else:
|
||||||
from configparser import ConfigParser
|
from configparser import ConfigParser
|
||||||
from configparser import NoOptionError
|
from configparser import NoOptionError
|
||||||
|
|
||||||
|
# default library locations for MacPorts
|
||||||
|
_macports_default_location = {'openjp2': '/opt/local/lib/libopenjp2.dylib',
|
||||||
|
'openjpeg': '/opt/local/lib/libopenjpeg.dylib'}
|
||||||
|
|
||||||
|
# default library locations on Windows
|
||||||
|
_windows_default_location = {'openjp2': os.path.join('C:\\',
|
||||||
|
'Program files',
|
||||||
|
'OpenJPEG 2.0',
|
||||||
|
'bin',
|
||||||
|
'openjp2.dll'),
|
||||||
|
'openjpeg': os.path.join('C:\\',
|
||||||
|
'Program files',
|
||||||
|
'OpenJPEG 1.5',
|
||||||
|
'bin',
|
||||||
|
'openjpeg.dll')}
|
||||||
|
|
||||||
|
|
||||||
def glymurrc_fname():
|
def glymurrc_fname():
|
||||||
"""Return the path to the configuration file.
|
"""Return the path to the configuration file.
|
||||||
|
|
@ -43,51 +56,23 @@ def glymurrc_fname():
|
||||||
return None
|
return None
|
||||||
|
|
||||||
|
|
||||||
def load_openjpeg(path):
|
def load_openjpeg_library(libname):
|
||||||
"""Load the openjpeg library, falling back on defaults if necessary.
|
|
||||||
|
|
||||||
Parameters
|
path = read_config_file(libname)
|
||||||
----------
|
if path is not None:
|
||||||
path : str
|
return load_library_handle(path)
|
||||||
Path to openjpeg 1.5 library as specified by configuration file. Will
|
|
||||||
be None if no configuration file specified.
|
|
||||||
"""
|
|
||||||
if path is None:
|
|
||||||
# Let ctypes try to find it.
|
|
||||||
path = find_library('openjpeg')
|
|
||||||
|
|
||||||
# If we could not find it, then look in some likely locations on mac
|
# No location specified by the configuration file, must look for it
|
||||||
# and win.
|
# elsewhere.
|
||||||
if path is None:
|
path = find_library(libname)
|
||||||
# Could not find a library via ctypes
|
|
||||||
if platform.system() == 'Darwin':
|
|
||||||
# MacPorts
|
|
||||||
path = '/opt/local/lib/libopenjpeg.dylib'
|
|
||||||
elif os.name == 'nt':
|
|
||||||
path = os.path.join('C:\\', 'Program files', 'OpenJPEG 1.5',
|
|
||||||
'bin', 'openjpeg.dll')
|
|
||||||
|
|
||||||
if path is not None and not os.path.exists(path):
|
|
||||||
# the mac/win default location does not exist.
|
|
||||||
return None
|
|
||||||
|
|
||||||
return load_library_handle(path)
|
|
||||||
|
|
||||||
def load_openjp2(path):
|
|
||||||
"""Load the openjp2 library, falling back on defaults if necessary.
|
|
||||||
"""
|
|
||||||
if path is None:
|
|
||||||
# No help from the config file, try to find it via ctypes.
|
|
||||||
path = find_library('openjp2')
|
|
||||||
|
|
||||||
if path is None:
|
if path is None:
|
||||||
# Could not find a library via ctypes
|
# Could not find a library via ctypes
|
||||||
if platform.system() == 'Darwin':
|
if platform.system() == 'Darwin':
|
||||||
# MacPorts
|
# MacPorts
|
||||||
path = '/opt/local/lib/libopenjp2.dylib'
|
path = _macports_default_location[libname]
|
||||||
elif os.name == 'nt':
|
elif os.name == 'nt':
|
||||||
path = os.path.join('C:\\', 'Program files', 'OpenJPEG 2.0',
|
path = _windows_default_location[libname]
|
||||||
'bin', 'openjp2.dll')
|
|
||||||
|
|
||||||
if path is not None and not os.path.exists(path):
|
if path is not None and not os.path.exists(path):
|
||||||
# the mac/win default location does not exist.
|
# the mac/win default location does not exist.
|
||||||
|
|
@ -100,9 +85,10 @@ def load_library_handle(path):
|
||||||
"""Load the library, return the ctypes handle."""
|
"""Load the library, return the ctypes handle."""
|
||||||
|
|
||||||
if path is None or path in ['None', 'none']:
|
if path is None or path in ['None', 'none']:
|
||||||
# Either could not find a library via ctypes or user-configuration-file,
|
# Either could not find a library via ctypes or
|
||||||
# or we could not find it in any of the default locations.
|
# user-configuration-file, or we could not find it in any of the
|
||||||
# This is probably a very old linux.
|
# default locations, or possibly the user intentionally does not want
|
||||||
|
# one of the libraries to load.
|
||||||
return None
|
return None
|
||||||
|
|
||||||
try:
|
try:
|
||||||
|
|
@ -111,43 +97,59 @@ def load_library_handle(path):
|
||||||
else:
|
else:
|
||||||
opj_lib = ctypes.CDLL(path)
|
opj_lib = ctypes.CDLL(path)
|
||||||
except (TypeError, OSError):
|
except (TypeError, OSError):
|
||||||
msg = '"Library {0}" could not be loaded. Operating in degraded mode.'
|
msg = 'The library specified by configuration file at {0} could not '
|
||||||
msg = msg.format(path)
|
msg += 'be loaded.'
|
||||||
warnings.warn(msg, UserWarning)
|
warnings.warn(msg.format(path), UserWarning)
|
||||||
opj_lib = None
|
opj_lib = None
|
||||||
|
|
||||||
return opj_lib
|
return opj_lib
|
||||||
|
|
||||||
|
|
||||||
def read_config_file():
|
def read_config_file(libname):
|
||||||
"""
|
"""
|
||||||
We must use a configuration file that the user must write.
|
Extract library locations from a configuration file.
|
||||||
"""
|
|
||||||
lib = {'openjp2': None, 'openjpeg': None}
|
|
||||||
filename = glymurrc_fname()
|
|
||||||
if filename is not None:
|
|
||||||
# Read the configuration file for the library location.
|
|
||||||
parser = ConfigParser()
|
|
||||||
parser.read(filename)
|
|
||||||
for name in ['openjp2', 'openjpeg']:
|
|
||||||
try:
|
|
||||||
lib[name] = parser.get('library', name)
|
|
||||||
except NoOptionError:
|
|
||||||
pass
|
|
||||||
|
|
||||||
return lib
|
Parameters
|
||||||
|
----------
|
||||||
|
libname : str
|
||||||
|
One of either 'openjp2' or 'openjpeg'
|
||||||
|
|
||||||
|
Returns
|
||||||
|
-------
|
||||||
|
path : None or str
|
||||||
|
None if no location is specified, otherwise a path to the library
|
||||||
|
"""
|
||||||
|
filename = glymurrc_fname()
|
||||||
|
if filename is None:
|
||||||
|
# There's no library file path to return in this case.
|
||||||
|
return None
|
||||||
|
|
||||||
|
# Read the configuration file for the library location.
|
||||||
|
parser = ConfigParser()
|
||||||
|
parser.read(filename)
|
||||||
|
try:
|
||||||
|
path = parser.get('library', libname)
|
||||||
|
except NoOptionError:
|
||||||
|
path = None
|
||||||
|
return path
|
||||||
|
|
||||||
|
|
||||||
def glymur_config():
|
def glymur_config():
|
||||||
"""Try to ascertain locations of openjp2, openjpeg libraries.
|
|
||||||
"""
|
"""
|
||||||
libs = read_config_file()
|
Try to ascertain locations of openjp2, openjpeg libraries.
|
||||||
libopenjp2_handle = load_openjp2(libs['openjp2'])
|
|
||||||
libopenjpeg_handle = load_openjpeg(libs['openjpeg'])
|
Returns
|
||||||
if libopenjp2_handle is None and libopenjpeg_handle is None:
|
-------
|
||||||
|
tpl : tuple
|
||||||
|
tuple of library handles
|
||||||
|
"""
|
||||||
|
lst = []
|
||||||
|
for libname in ['openjp2', 'openjpeg']:
|
||||||
|
lst.append(load_openjpeg_library(libname))
|
||||||
|
if all(handle is None for handle in lst):
|
||||||
msg = "Neither the openjp2 nor the openjpeg library could be loaded. "
|
msg = "Neither the openjp2 nor the openjpeg library could be loaded. "
|
||||||
raise IOError(msg)
|
warnings.warn(msg)
|
||||||
return libopenjp2_handle, libopenjpeg_handle
|
return tuple(lst)
|
||||||
|
|
||||||
|
|
||||||
def get_configdir():
|
def get_configdir():
|
||||||
|
|
|
||||||
|
|
@ -2,15 +2,16 @@
|
||||||
Wraps individual functions in openjp2 library.
|
Wraps individual functions in openjp2 library.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
# pylint: disable=C0302,R0903,W0201
|
|
||||||
|
|
||||||
import ctypes
|
import ctypes
|
||||||
import re
|
import re
|
||||||
import sys
|
import sys
|
||||||
|
import textwrap
|
||||||
|
|
||||||
from .config import glymur_config
|
from .config import glymur_config
|
||||||
|
|
||||||
OPENJP2, OPENJPEG = glymur_config()
|
OPENJP2, OPENJPEG = glymur_config()
|
||||||
|
|
||||||
|
|
||||||
def version():
|
def version():
|
||||||
"""Wrapper for opj_version library routine."""
|
"""Wrapper for opj_version library routine."""
|
||||||
try:
|
try:
|
||||||
|
|
@ -48,13 +49,6 @@ JPWL_MAX_NO_TILESPECS = 16
|
||||||
TRUE = 1
|
TRUE = 1
|
||||||
FALSE = 0
|
FALSE = 0
|
||||||
|
|
||||||
#PROFILE = {'none': 0, # No profile
|
|
||||||
# 0: 1, # Profile 0
|
|
||||||
# 1: 2, # Profile 1
|
|
||||||
# 'part2': 0x8000, # At least one extension
|
|
||||||
# 'Cinema2K': 0x0003, # 2K cinema profile
|
|
||||||
# 'Cinema4K': 0x0004, # 4K cinema profile
|
|
||||||
|
|
||||||
# supported color spaces
|
# supported color spaces
|
||||||
CLRSPC_UNKNOWN = -1
|
CLRSPC_UNKNOWN = -1
|
||||||
CLRSPC_UNSPECIFIED = 0
|
CLRSPC_UNSPECIFIED = 0
|
||||||
|
|
@ -137,6 +131,13 @@ class PocType(ctypes.Structure):
|
||||||
("tx0_t", ctypes.c_uint32),
|
("tx0_t", ctypes.c_uint32),
|
||||||
("ty0_t", ctypes.c_uint32)]
|
("ty0_t", ctypes.c_uint32)]
|
||||||
|
|
||||||
|
def __str__(self):
|
||||||
|
msg = "{0}:\n".format(self.__class__)
|
||||||
|
for field_name, _ in self._fields_:
|
||||||
|
msg += " {0}: {1}\n".format(
|
||||||
|
field_name, getattr(self, field_name))
|
||||||
|
return msg
|
||||||
|
|
||||||
|
|
||||||
class DecompressionParametersType(ctypes.Structure):
|
class DecompressionParametersType(ctypes.Structure):
|
||||||
"""Decompression parameters.
|
"""Decompression parameters.
|
||||||
|
|
@ -200,6 +201,13 @@ class DecompressionParametersType(ctypes.Structure):
|
||||||
# maximum number of tiles
|
# maximum number of tiles
|
||||||
("flags", ctypes.c_uint32)]
|
("flags", ctypes.c_uint32)]
|
||||||
|
|
||||||
|
def __str__(self):
|
||||||
|
msg = "{0}:\n".format(self.__class__)
|
||||||
|
for field_name, _ in self._fields_:
|
||||||
|
msg += " {0}: {1}\n".format(
|
||||||
|
field_name, getattr(self, field_name))
|
||||||
|
return msg
|
||||||
|
|
||||||
|
|
||||||
class CompressionParametersType(ctypes.Structure):
|
class CompressionParametersType(ctypes.Structure):
|
||||||
"""Compression parameters.
|
"""Compression parameters.
|
||||||
|
|
@ -391,6 +399,46 @@ class CompressionParametersType(ctypes.Structure):
|
||||||
# values.
|
# values.
|
||||||
_fields_.append(("rsiz", ctypes.c_uint16))
|
_fields_.append(("rsiz", ctypes.c_uint16))
|
||||||
|
|
||||||
|
def __str__(self):
|
||||||
|
msg = "{0}:\n".format(self.__class__)
|
||||||
|
for field_name, _ in self._fields_:
|
||||||
|
|
||||||
|
if field_name == 'poc':
|
||||||
|
msg += " numpocs: {0}\n".format(self.numpocs)
|
||||||
|
for j in range(self.numpocs):
|
||||||
|
msg += " [#{0}]:".format(j)
|
||||||
|
msg += " {0}".format(str(self.poc[j]))
|
||||||
|
|
||||||
|
elif field_name in ['tcp_rates', 'tcp_distoratio']:
|
||||||
|
lst = []
|
||||||
|
arr = getattr(self, field_name)
|
||||||
|
lst = [arr[j] for j in range(self.tcp_numlayers)]
|
||||||
|
msg += " {0}: {1}\n".format(field_name, lst)
|
||||||
|
|
||||||
|
elif field_name in ['prcw_init', 'prch_init']:
|
||||||
|
pass
|
||||||
|
|
||||||
|
elif field_name == 'res_spec':
|
||||||
|
prcw_init = [self.prcw_init[j] for j in range(self.res_spec)]
|
||||||
|
prch_init = [self.prch_init[j] for j in range(self.res_spec)]
|
||||||
|
msg += " res_spec: {0}\n".format(self.res_spec)
|
||||||
|
msg += " prch_init: {0}\n".format(prch_init)
|
||||||
|
msg += " prcw_init: {0}\n".format(prcw_init)
|
||||||
|
|
||||||
|
elif field_name in [
|
||||||
|
'jpwl_hprot_tph_tileno', 'jpwl_hprot_tph',
|
||||||
|
'jpwl_pprot_tileno', 'jpwl_pprot_packno', 'jpwl_pprot',
|
||||||
|
'jpwl_sens_tph_tileno', 'jpwl_sens_tph']:
|
||||||
|
arr = getattr(self, field_name)
|
||||||
|
lst = [arr[j] for j in range(JPWL_MAX_NO_TILESPECS)]
|
||||||
|
msg += " {0}: {1}\n".format(field_name, lst)
|
||||||
|
|
||||||
|
else:
|
||||||
|
msg += " {0}: {1}\n".format(
|
||||||
|
field_name, getattr(self, field_name))
|
||||||
|
return msg
|
||||||
|
|
||||||
|
|
||||||
class ImageCompType(ctypes.Structure):
|
class ImageCompType(ctypes.Structure):
|
||||||
"""Defines a single image component.
|
"""Defines a single image component.
|
||||||
|
|
||||||
|
|
@ -432,6 +480,14 @@ class ImageCompType(ctypes.Structure):
|
||||||
if _MINOR == '1':
|
if _MINOR == '1':
|
||||||
_fields_.append(("alpha", ctypes.c_uint16))
|
_fields_.append(("alpha", ctypes.c_uint16))
|
||||||
|
|
||||||
|
def __str__(self):
|
||||||
|
msg = "{0}:\n".format(self.__class__)
|
||||||
|
for field_name, _ in self._fields_:
|
||||||
|
msg += " {0}: {1}\n".format(
|
||||||
|
field_name, getattr(self, field_name))
|
||||||
|
return msg
|
||||||
|
|
||||||
|
|
||||||
class ImageType(ctypes.Structure):
|
class ImageType(ctypes.Structure):
|
||||||
"""Defines image data and characteristics.
|
"""Defines image data and characteristics.
|
||||||
|
|
||||||
|
|
@ -462,6 +518,26 @@ class ImageType(ctypes.Structure):
|
||||||
# restricted ICC profile buffer length
|
# restricted ICC profile buffer length
|
||||||
("icc_profile_len", ctypes.c_uint32)]
|
("icc_profile_len", ctypes.c_uint32)]
|
||||||
|
|
||||||
|
def __str__(self):
|
||||||
|
msg = "{0}:\n".format(self.__class__)
|
||||||
|
for field_name, _ in self._fields_:
|
||||||
|
|
||||||
|
if field_name == "numcomps":
|
||||||
|
msg += " numcomps: {0}\n".format(self.numcomps)
|
||||||
|
for j in range(self.numcomps):
|
||||||
|
msg += " comps[#{0}]:\n".format(j)
|
||||||
|
msg += textwrap.indent(str(self.comps[j]), ' ' * 12)
|
||||||
|
|
||||||
|
elif field_name == "comps":
|
||||||
|
# handled above
|
||||||
|
pass
|
||||||
|
|
||||||
|
else:
|
||||||
|
msg += " {0}: {1}\n".format(
|
||||||
|
field_name, getattr(self, field_name))
|
||||||
|
|
||||||
|
return msg
|
||||||
|
|
||||||
|
|
||||||
class ImageComptParmType(ctypes.Structure):
|
class ImageComptParmType(ctypes.Structure):
|
||||||
"""Component parameters structure used by image_create function.
|
"""Component parameters structure used by image_create function.
|
||||||
|
|
@ -491,106 +567,12 @@ class ImageComptParmType(ctypes.Structure):
|
||||||
# signed (1) / unsigned (0)
|
# signed (1) / unsigned (0)
|
||||||
("sgnd", ctypes.c_uint32)]
|
("sgnd", ctypes.c_uint32)]
|
||||||
|
|
||||||
|
def __str__(self):
|
||||||
class TccpInfo(ctypes.Structure):
|
msg = "{0}:\n".format(self.__class__)
|
||||||
"""Tile-component coding parameters information.
|
for field_name, _ in self._fields_:
|
||||||
|
msg += " {0}: {1}\n".format(
|
||||||
Corresponds to tccp_info_t type in openjp2 header file.
|
field_name, getattr(self, field_name))
|
||||||
"""
|
return msg
|
||||||
_fields_ = [
|
|
||||||
# component index
|
|
||||||
("compno", ctypes.c_uint32),
|
|
||||||
|
|
||||||
# coding style
|
|
||||||
("csty", ctypes.c_uint32),
|
|
||||||
|
|
||||||
# number of resolutions
|
|
||||||
("numresolutions", ctypes.c_uint32),
|
|
||||||
|
|
||||||
# code-blocks width
|
|
||||||
("cblkw", ctypes.c_uint32),
|
|
||||||
|
|
||||||
# code-blocks height
|
|
||||||
("cblkh", ctypes.c_uint32),
|
|
||||||
|
|
||||||
# code-block coding style
|
|
||||||
("cblksty", ctypes.c_uint32),
|
|
||||||
|
|
||||||
# discrete wavelet transform identifier
|
|
||||||
("qmfbid", ctypes.c_uint32),
|
|
||||||
|
|
||||||
# quantization style
|
|
||||||
("qntsty", ctypes.c_uint32),
|
|
||||||
|
|
||||||
# stepsizes used for quantization
|
|
||||||
("stepsizes_mant", ctypes.c_uint32 * J2K_MAXBANDS),
|
|
||||||
("stepsizes_expn", ctypes.c_uint32 * J2K_MAXBANDS),
|
|
||||||
|
|
||||||
# stepsizes used for quantization
|
|
||||||
("numgbits", ctypes.c_uint32),
|
|
||||||
|
|
||||||
# region of interest shift
|
|
||||||
("roishift", ctypes.c_int32),
|
|
||||||
|
|
||||||
# precinct width
|
|
||||||
("prcw", ctypes.c_uint32 * J2K_MAXRLVLS),
|
|
||||||
|
|
||||||
# precinct width
|
|
||||||
("prch", ctypes.c_uint32 * J2K_MAXRLVLS)]
|
|
||||||
|
|
||||||
|
|
||||||
class TileInfoV2(ctypes.Structure):
|
|
||||||
"""Tile coding parameters information
|
|
||||||
|
|
||||||
Corresponds to tile_info_v2_t type in openjp2 headers.
|
|
||||||
"""
|
|
||||||
_fields_ = [
|
|
||||||
# number (index) of tile
|
|
||||||
("tileno", ctypes.c_int32),
|
|
||||||
|
|
||||||
# coding style
|
|
||||||
("csty", ctypes.c_uint32),
|
|
||||||
|
|
||||||
# progression order
|
|
||||||
("prg", PROG_ORDER_TYPE),
|
|
||||||
|
|
||||||
# number of layers
|
|
||||||
("numlayers", ctypes.c_uint32),
|
|
||||||
|
|
||||||
# multi-component transform identifier
|
|
||||||
("mct", ctypes.c_uint32),
|
|
||||||
|
|
||||||
# information concerning tile component parameters
|
|
||||||
("tccp_info", ctypes.POINTER(TccpInfo))]
|
|
||||||
|
|
||||||
|
|
||||||
class CodestreamInfoV2(ctypes.Structure):
|
|
||||||
"""information about the codestream.
|
|
||||||
|
|
||||||
Corresponds to codestream_info_v2_t type in openjp2 header files.
|
|
||||||
"""
|
|
||||||
_fields_ = [
|
|
||||||
# tile info
|
|
||||||
# tile origin in x, y (XTOsiz, YTOsiz)
|
|
||||||
("tx0", ctypes.c_uint32),
|
|
||||||
("ty0", ctypes.c_uint32),
|
|
||||||
|
|
||||||
# tile size in x, y = XTsiz, YTsiz
|
|
||||||
("tdx", ctypes.c_uint32),
|
|
||||||
("tdy", ctypes.c_uint32),
|
|
||||||
|
|
||||||
# number of tiles in X, Y
|
|
||||||
("tw", ctypes.c_uint32),
|
|
||||||
("th", ctypes.c_uint32),
|
|
||||||
|
|
||||||
# number of components
|
|
||||||
("nbcomps", ctypes.c_uint32),
|
|
||||||
|
|
||||||
# default information regarding tiles inside of image
|
|
||||||
("m_default_tile_info", TileInfoV2),
|
|
||||||
|
|
||||||
# information regarding tiles inside of image
|
|
||||||
("tile_info", ctypes.POINTER(TileInfoV2))]
|
|
||||||
|
|
||||||
|
|
||||||
def check_error(status):
|
def check_error(status):
|
||||||
|
|
@ -755,28 +737,6 @@ def encode(codec, stream):
|
||||||
OPENJP2.opj_encode(codec, stream)
|
OPENJP2.opj_encode(codec, stream)
|
||||||
|
|
||||||
|
|
||||||
def get_cstr_info(codec):
|
|
||||||
"""get the codestream information from the codec
|
|
||||||
|
|
||||||
Wraps the openjp2 library function opj_get_cstr_info.
|
|
||||||
|
|
||||||
Parameters
|
|
||||||
----------
|
|
||||||
codec : CODEC_TYPE
|
|
||||||
The jpeg2000 codec.
|
|
||||||
|
|
||||||
Returns
|
|
||||||
-------
|
|
||||||
cstr_info_p : CodestreamInfoV2
|
|
||||||
Reference to codestream information.
|
|
||||||
"""
|
|
||||||
OPENJP2.opj_get_cstr_info.argtypes = [CODEC_TYPE]
|
|
||||||
OPENJP2.opj_get_cstr_info.restype = ctypes.POINTER(CodestreamInfoV2)
|
|
||||||
|
|
||||||
cstr_info_p = OPENJP2.opj_get_cstr_info(codec)
|
|
||||||
return cstr_info_p
|
|
||||||
|
|
||||||
|
|
||||||
def get_decoded_tile(codec, stream, imagep, tile_index):
|
def get_decoded_tile(codec, stream, imagep, tile_index):
|
||||||
"""get the decoded tile from the codec
|
"""get the decoded tile from the codec
|
||||||
|
|
||||||
|
|
@ -807,23 +767,6 @@ def get_decoded_tile(codec, stream, imagep, tile_index):
|
||||||
OPENJP2.opj_get_decoded_tile(codec, stream, imagep, tile_index)
|
OPENJP2.opj_get_decoded_tile(codec, stream, imagep, tile_index)
|
||||||
|
|
||||||
|
|
||||||
def destroy_cstr_info(cstr_info_p):
|
|
||||||
"""destroy codestream information after compression or decompression
|
|
||||||
|
|
||||||
Wraps the openjp2 library function opj_destroy_cstr_info.
|
|
||||||
|
|
||||||
Parameters
|
|
||||||
----------
|
|
||||||
cstr_info_p : CodestreamInfoV2 pointer
|
|
||||||
Pointer to codestream info structure.
|
|
||||||
"""
|
|
||||||
ARGTYPES = [ctypes.POINTER(ctypes.POINTER(CodestreamInfoV2))]
|
|
||||||
OPENJP2.opj_destroy_cstr_info.argtypes = ARGTYPES
|
|
||||||
OPENJP2.opj_destroy_cstr_info.restype = ctypes.c_void_p
|
|
||||||
|
|
||||||
OPENJP2.opj_destroy_cstr_info(ctypes.byref(cstr_info_p))
|
|
||||||
|
|
||||||
|
|
||||||
def end_compress(codec, stream):
|
def end_compress(codec, stream):
|
||||||
"""End of compressing the current image.
|
"""End of compressing the current image.
|
||||||
|
|
||||||
|
|
@ -966,7 +909,7 @@ def read_header(stream, codec):
|
||||||
ARGTYPES = [STREAM_TYPE_P, CODEC_TYPE,
|
ARGTYPES = [STREAM_TYPE_P, CODEC_TYPE,
|
||||||
ctypes.POINTER(ctypes.POINTER(ImageType))]
|
ctypes.POINTER(ctypes.POINTER(ImageType))]
|
||||||
OPENJP2.opj_read_header.argtypes = ARGTYPES
|
OPENJP2.opj_read_header.argtypes = ARGTYPES
|
||||||
OPENJP2.opj_read_header.restype = check_error
|
OPENJP2.opj_read_header.restype = check_error
|
||||||
|
|
||||||
imagep = ctypes.POINTER(ImageType)()
|
imagep = ctypes.POINTER(ImageType)()
|
||||||
OPENJP2.opj_read_header(stream, codec, ctypes.byref(imagep))
|
OPENJP2.opj_read_header(stream, codec, ctypes.byref(imagep))
|
||||||
|
|
@ -1325,6 +1268,7 @@ def _stream_create_default_file_stream_2p0(fptr, isa_read_stream):
|
||||||
stream = OPENJP2.opj_stream_create_default_file_stream(fptr, read_stream)
|
stream = OPENJP2.opj_stream_create_default_file_stream(fptr, read_stream)
|
||||||
return stream
|
return stream
|
||||||
|
|
||||||
|
|
||||||
def _stream_create_default_file_stream_2p1(fname, isa_read_stream):
|
def _stream_create_default_file_stream_2p1(fname, isa_read_stream):
|
||||||
"""Wraps openjp2 library function opj_stream_create_default_vile_stream.
|
"""Wraps openjp2 library function opj_stream_create_default_vile_stream.
|
||||||
|
|
||||||
|
|
@ -1351,7 +1295,7 @@ def _stream_create_default_file_stream_2p1(fname, isa_read_stream):
|
||||||
stream = OPENJP2.opj_stream_create_default_file_stream(file_argument,
|
stream = OPENJP2.opj_stream_create_default_file_stream(file_argument,
|
||||||
read_stream)
|
read_stream)
|
||||||
return stream
|
return stream
|
||||||
|
|
||||||
if re.match(r'''2.0''', version()):
|
if re.match(r'''2.0''', version()):
|
||||||
stream_create_default_file_stream = _stream_create_default_file_stream_2p0
|
stream_create_default_file_stream = _stream_create_default_file_stream_2p0
|
||||||
else:
|
else:
|
||||||
|
|
|
||||||
|
|
@ -1,14 +1,11 @@
|
||||||
"""Wraps library calls to openjpeg.
|
"""Wraps library calls to openjpeg.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
# pylint: disable=R0903
|
|
||||||
|
|
||||||
import ctypes
|
import ctypes
|
||||||
import sys
|
import sys
|
||||||
|
|
||||||
import numpy as np
|
|
||||||
|
|
||||||
from .config import glymur_config
|
from .config import glymur_config
|
||||||
|
|
||||||
_, OPENJPEG = glymur_config()
|
_, OPENJPEG = glymur_config()
|
||||||
|
|
||||||
# Maximum number of tile parts expected by JPWL: increase at your will
|
# Maximum number of tile parts expected by JPWL: increase at your will
|
||||||
|
|
@ -58,8 +55,10 @@ class CommonStructType(ctypes.Structure):
|
||||||
("mj2_handle", ctypes.c_void_p)]
|
("mj2_handle", ctypes.c_void_p)]
|
||||||
|
|
||||||
|
|
||||||
STREAM_READ = 0x0001 # The stream was opened for reading.
|
STREAM_READ = 0x0001 # The stream was opened for reading.
|
||||||
STREAM_WRITE = 0x0002 # The stream was opened for writing.
|
STREAM_WRITE = 0x0002 # The stream was opened for writing.
|
||||||
|
|
||||||
|
|
||||||
class CioType(ctypes.Structure):
|
class CioType(ctypes.Structure):
|
||||||
"""Byte input-output stream (CIO)
|
"""Byte input-output stream (CIO)
|
||||||
|
|
||||||
|
|
@ -90,70 +89,57 @@ class CompressionInfoType(CommonStructType):
|
||||||
class PocType(ctypes.Structure):
|
class PocType(ctypes.Structure):
|
||||||
"""Progression order changes."""
|
"""Progression order changes."""
|
||||||
_fields_ = [("resno", ctypes.c_int),
|
_fields_ = [("resno", ctypes.c_int),
|
||||||
# Resolution num start, Component num start, given by POC
|
# Resolution num start, Component num start, given by POC
|
||||||
("compno0", ctypes.c_int),
|
("compno0", ctypes.c_int),
|
||||||
|
|
||||||
# Layer num end,Resolution num end, Component num end, given by POC
|
# Layer num end,Resolution num end, Component num end, given
|
||||||
("layno1", ctypes.c_int),
|
# by POC
|
||||||
("resno1", ctypes.c_int),
|
("layno1", ctypes.c_int),
|
||||||
("compno1", ctypes.c_int),
|
("resno1", ctypes.c_int),
|
||||||
|
("compno1", ctypes.c_int),
|
||||||
|
|
||||||
# Layer num start,Precinct num start, Precinct num end
|
# Layer num start,Precinct num start, Precinct num end
|
||||||
("layno0", ctypes.c_int),
|
("layno0", ctypes.c_int),
|
||||||
("precno0", ctypes.c_int),
|
("precno0", ctypes.c_int),
|
||||||
("precno1", ctypes.c_int),
|
("precno1", ctypes.c_int),
|
||||||
|
|
||||||
# Progression order enum
|
# Progression order enum
|
||||||
# OPJ_PROG_ORDER prg1,prg;
|
# OPJ_PROG_ORDER prg1,prg;
|
||||||
("prg1", ctypes.c_int),
|
("prg1", ctypes.c_int),
|
||||||
("prg", ctypes.c_int),
|
("prg", ctypes.c_int),
|
||||||
|
|
||||||
# Progression order string
|
# Progression order string
|
||||||
# char progorder[5];
|
# char progorder[5];
|
||||||
("progorder", ctypes.c_char * 5),
|
("progorder", ctypes.c_char * 5),
|
||||||
|
|
||||||
# Tile number
|
# Tile number
|
||||||
# int tile;
|
# int tile;
|
||||||
("tile", ctypes.c_int),
|
("tile", ctypes.c_int),
|
||||||
|
|
||||||
# /** Start and end values for Tile width and height*/
|
("tx0", ctypes.c_int),
|
||||||
# int tx0,tx1,ty0,ty1;
|
("tx1", ctypes.c_int),
|
||||||
("tx0", ctypes.c_int),
|
("ty0", ctypes.c_int),
|
||||||
("tx1", ctypes.c_int),
|
("ty1", ctypes.c_int),
|
||||||
("ty0", ctypes.c_int),
|
("layS", ctypes.c_int),
|
||||||
("ty1", ctypes.c_int),
|
("resS", ctypes.c_int),
|
||||||
|
("compS", ctypes.c_int),
|
||||||
# /** Start value, initialised in pi_initialise_encode*/
|
("prcS", ctypes.c_int),
|
||||||
# int layS, resS, compS, prcS;
|
("layE", ctypes.c_int),
|
||||||
("layS", ctypes.c_int),
|
("resE", ctypes.c_int),
|
||||||
("resS", ctypes.c_int),
|
("compE", ctypes.c_int),
|
||||||
("compS", ctypes.c_int),
|
("prcE", ctypes.c_int),
|
||||||
("prcS", ctypes.c_int),
|
("txS", ctypes.c_int),
|
||||||
|
("txE", ctypes.c_int),
|
||||||
# /** End value, initialised in pi_initialise_encode */
|
("tyS", ctypes.c_int),
|
||||||
# int layE, resE, compE, prcE;
|
("tyE", ctypes.c_int),
|
||||||
("layE", ctypes.c_int),
|
("dx", ctypes.c_int),
|
||||||
("resE", ctypes.c_int),
|
("dy", ctypes.c_int),
|
||||||
("compE", ctypes.c_int),
|
("lay_t", ctypes.c_int),
|
||||||
("prcE", ctypes.c_int),
|
("res_t", ctypes.c_int),
|
||||||
|
("comp_t", ctypes.c_int),
|
||||||
# Start and end values of Tile width and height, initialised in
|
("prc_t", ctypes.c_int),
|
||||||
# pi_initialise_encode int txS,txE,tyS,tyE,dx,dy;
|
("tx0_t", ctypes.c_int),
|
||||||
("txS", ctypes.c_int),
|
("ty0_t", ctypes.c_int)]
|
||||||
("txE", ctypes.c_int),
|
|
||||||
("tyS", ctypes.c_int),
|
|
||||||
("tyE", ctypes.c_int),
|
|
||||||
("dx", ctypes.c_int),
|
|
||||||
("dy", ctypes.c_int),
|
|
||||||
|
|
||||||
# Temporary values for Tile parts, initialised in pi_create_encode
|
|
||||||
# int lay_t, res_t, comp_t, prc_t,tx0_t,ty0_t;
|
|
||||||
("lay_t", ctypes.c_int),
|
|
||||||
("res_t", ctypes.c_int),
|
|
||||||
("comp_t", ctypes.c_int),
|
|
||||||
("prc_t", ctypes.c_int),
|
|
||||||
("tx0_t", ctypes.c_int),
|
|
||||||
("ty0_t", ctypes.c_int)]
|
|
||||||
|
|
||||||
|
|
||||||
class CompressionParametersType(ctypes.Structure):
|
class CompressionParametersType(ctypes.Structure):
|
||||||
|
|
@ -374,48 +360,47 @@ class DecompressionParametersType(ctypes.Structure):
|
||||||
class ImageComptParmType(ctypes.Structure):
|
class ImageComptParmType(ctypes.Structure):
|
||||||
"""Component parameters structure used by the opj_image_create function.
|
"""Component parameters structure used by the opj_image_create function.
|
||||||
"""
|
"""
|
||||||
_fields_ = [
|
_fields_ = [("dx", ctypes.c_int),
|
||||||
# XRsiz: horizontal separation of a sample of ith component with
|
# XRsiz: horizontal separation of a sample of ith component
|
||||||
# respect to the reference grid
|
# with respect to the reference grid
|
||||||
("dx", ctypes.c_int),
|
|
||||||
|
|
||||||
# YRsiz: vertical separation of a sample of ith component with
|
# YRsiz: vertical separation of a sample of ith component with
|
||||||
# respect to the reference grid */
|
# respect to the reference grid */
|
||||||
("dy", ctypes.c_int),
|
("dy", ctypes.c_int),
|
||||||
|
|
||||||
# data width, height
|
# data width, height
|
||||||
("w", ctypes.c_int),
|
("w", ctypes.c_int),
|
||||||
("h", ctypes.c_int),
|
("h", ctypes.c_int),
|
||||||
|
|
||||||
# x component offset compared to the whole image
|
# x component offset compared to the whole image
|
||||||
# y component offset compared to the whole image
|
# y component offset compared to the whole image
|
||||||
("x0", ctypes.c_int),
|
("x0", ctypes.c_int),
|
||||||
("y0", ctypes.c_int),
|
("y0", ctypes.c_int),
|
||||||
|
|
||||||
# precision
|
# precision
|
||||||
('prec', ctypes.c_int),
|
('prec', ctypes.c_int),
|
||||||
|
|
||||||
# image depth in bits
|
# image depth in bits
|
||||||
('bpp', ctypes.c_int),
|
('bpp', ctypes.c_int),
|
||||||
|
|
||||||
# signed (1) / unsigned (0)
|
# signed (1) / unsigned (0)
|
||||||
('sgnd', ctypes.c_int)]
|
('sgnd', ctypes.c_int)]
|
||||||
|
|
||||||
|
|
||||||
class ImageCompType(ctypes.Structure):
|
class ImageCompType(ctypes.Structure):
|
||||||
"""Defines a single image component. """
|
"""Defines a single image component. """
|
||||||
_fields_ = [("dx", ctypes.c_int),
|
_fields_ = [("dx", ctypes.c_int),
|
||||||
("dy", ctypes.c_int),
|
("dy", ctypes.c_int),
|
||||||
("w", ctypes.c_int),
|
("w", ctypes.c_int),
|
||||||
("h", ctypes.c_int),
|
("h", ctypes.c_int),
|
||||||
("x0", ctypes.c_int),
|
("x0", ctypes.c_int),
|
||||||
("y0", ctypes.c_int),
|
("y0", ctypes.c_int),
|
||||||
("prec", ctypes.c_int),
|
("prec", ctypes.c_int),
|
||||||
("bpp", ctypes.c_int),
|
("bpp", ctypes.c_int),
|
||||||
("sgnd", ctypes.c_int),
|
("sgnd", ctypes.c_int),
|
||||||
("resno_decoded", ctypes.c_int),
|
("resno_decoded", ctypes.c_int),
|
||||||
("factor", ctypes.c_int),
|
("factor", ctypes.c_int),
|
||||||
("data", ctypes.POINTER(ctypes.c_int))]
|
("data", ctypes.POINTER(ctypes.c_int))]
|
||||||
|
|
||||||
|
|
||||||
class ImageType(ctypes.Structure):
|
class ImageType(ctypes.Structure):
|
||||||
|
|
@ -467,6 +452,7 @@ def cio_tell(cio):
|
||||||
pos = OPENJPEG.cio_tell(cio)
|
pos = OPENJPEG.cio_tell(cio)
|
||||||
return pos
|
return pos
|
||||||
|
|
||||||
|
|
||||||
def create_compress(fmt):
|
def create_compress(fmt):
|
||||||
"""Wrapper for openjpeg library function opj_create_compress.
|
"""Wrapper for openjpeg library function opj_create_compress.
|
||||||
|
|
||||||
|
|
@ -537,56 +523,11 @@ def destroy_decompress(dinfo):
|
||||||
OPENJPEG.opj_destroy_decompress(dinfo)
|
OPENJPEG.opj_destroy_decompress(dinfo)
|
||||||
|
|
||||||
|
|
||||||
def image_cmptparm_t_from_np(np_image):
|
|
||||||
"""Return appropriate image_cmptparm_t based on given numpy array.
|
|
||||||
"""
|
|
||||||
try:
|
|
||||||
num_comps = np_image.shape[2]
|
|
||||||
except IndexError:
|
|
||||||
num_comps = 1
|
|
||||||
|
|
||||||
cmpt_parm_array_t = ImageCmptparmType * num_comps
|
|
||||||
tarr = cmpt_parm_array_t()
|
|
||||||
|
|
||||||
if np_image.dtype == np.uint8:
|
|
||||||
prec = 8
|
|
||||||
bpp = 8
|
|
||||||
sgnd = 0
|
|
||||||
elif np_image.dtype == np.int8:
|
|
||||||
prec = 8
|
|
||||||
bpp = 8
|
|
||||||
sgnd = 1
|
|
||||||
elif np_image.dtype == np.uint16:
|
|
||||||
prec = 16
|
|
||||||
bpp = 16
|
|
||||||
sgnd = 0
|
|
||||||
elif np_image.dtype == np.int16:
|
|
||||||
prec = 16
|
|
||||||
bpp = 16
|
|
||||||
sgnd = 1
|
|
||||||
else:
|
|
||||||
raise(TypeError("unhandled"))
|
|
||||||
|
|
||||||
for j in range(0, num_comps):
|
|
||||||
tarr[j].dx = 1
|
|
||||||
tarr[j].dy = 1
|
|
||||||
tarr[j].w = np_image.shape[1]
|
|
||||||
tarr[j].h = np_image.shape[0]
|
|
||||||
tarr[j].x0 = 0
|
|
||||||
tarr[j].y0 = 0
|
|
||||||
tarr[j].prec = prec
|
|
||||||
tarr[j].bpp = bpp
|
|
||||||
tarr[j].sgnd = sgnd
|
|
||||||
|
|
||||||
return(tarr)
|
|
||||||
|
|
||||||
|
|
||||||
def image_create(cmptparms, cspace):
|
def image_create(cmptparms, cspace):
|
||||||
"""Wrapper for openjpeg library function opj_image_create.
|
"""Wrapper for openjpeg library function opj_image_create.
|
||||||
"""
|
"""
|
||||||
OPENJPEG.opj_image_create.argtypes = [ctypes.c_int,
|
lst = [ctypes.c_int, ctypes.POINTER(ImageComptParmType), ctypes.c_int]
|
||||||
ctypes.POINTER(ImageComptParmType),
|
OPENJPEG.opj_image_create.argtypes = lst
|
||||||
ctypes.c_int]
|
|
||||||
OPENJPEG.opj_image_create.restype = ctypes.POINTER(ImageType)
|
OPENJPEG.opj_image_create.restype = ctypes.POINTER(ImageType)
|
||||||
|
|
||||||
image = OPENJPEG.opj_image_create(len(cmptparms), cmptparms, cspace)
|
image = OPENJPEG.opj_image_create(len(cmptparms), cmptparms, cspace)
|
||||||
|
|
|
||||||
144
glymur/lib/test/fixtures.py
Normal file
144
glymur/lib/test/fixtures.py
Normal file
|
|
@ -0,0 +1,144 @@
|
||||||
|
decompression_parameters_type = """<class 'glymur.lib.openjp2.DecompressionParametersType'>:
|
||||||
|
cp_reduce: 0
|
||||||
|
cp_layer: 0
|
||||||
|
infile: b''
|
||||||
|
outfile: b''
|
||||||
|
decod_format: -1
|
||||||
|
cod_format: -1
|
||||||
|
DA_x0: 0
|
||||||
|
DA_x1: 0
|
||||||
|
DA_y0: 0
|
||||||
|
DA_y1: 0
|
||||||
|
m_verbose: 0
|
||||||
|
tile_index: 0
|
||||||
|
nb_tile_to_decode: 0
|
||||||
|
jpwl_correct: 0
|
||||||
|
jpwl_exp_comps: 0
|
||||||
|
jpwl_max_tiles: 0
|
||||||
|
flags: 0"""
|
||||||
|
|
||||||
|
default_progression_order_changes_type = """<class 'glymur.lib.openjp2.PocType'>:
|
||||||
|
resno0: 0
|
||||||
|
compno0: 0
|
||||||
|
layno1: 0
|
||||||
|
resno1: 0
|
||||||
|
compno1: 0
|
||||||
|
layno0: 0
|
||||||
|
precno0: 0
|
||||||
|
precno1: 0
|
||||||
|
prg1: 0
|
||||||
|
prg: 0
|
||||||
|
progorder: b''
|
||||||
|
tile: 0
|
||||||
|
tx0: 0
|
||||||
|
tx1: 0
|
||||||
|
ty0: 0
|
||||||
|
ty1: 0
|
||||||
|
layS: 0
|
||||||
|
resS: 0
|
||||||
|
compS: 0
|
||||||
|
prcS: 0
|
||||||
|
layE: 0
|
||||||
|
resE: 0
|
||||||
|
compE: 0
|
||||||
|
prcE: 0
|
||||||
|
txS: 0
|
||||||
|
txE: 0
|
||||||
|
tyS: 0
|
||||||
|
tyE: 0
|
||||||
|
dx: 0
|
||||||
|
dy: 0
|
||||||
|
lay_t: 0
|
||||||
|
res_t: 0
|
||||||
|
comp_t: 0
|
||||||
|
prec_t: 0
|
||||||
|
tx0_t: 0
|
||||||
|
ty0_t: 0"""
|
||||||
|
|
||||||
|
default_compression_parameters_type = """<class 'glymur.lib.openjp2.CompressionParametersType'>:
|
||||||
|
tile_size_on: 0
|
||||||
|
cp_tx0: 0
|
||||||
|
cp_ty0: 0
|
||||||
|
cp_tdx: 0
|
||||||
|
cp_tdy: 0
|
||||||
|
cp_disto_alloc: 0
|
||||||
|
cp_fixed_alloc: 0
|
||||||
|
cp_fixed_quality: 0
|
||||||
|
cp_matrice: None
|
||||||
|
cp_comment: None
|
||||||
|
csty: 0
|
||||||
|
prog_order: 0
|
||||||
|
numpocs: 0
|
||||||
|
numpocs: 0
|
||||||
|
tcp_numlayers: 0
|
||||||
|
tcp_rates: []
|
||||||
|
tcp_distoratio: []
|
||||||
|
numresolution: 6
|
||||||
|
cblockw_init: 64
|
||||||
|
cblockh_init: 64
|
||||||
|
mode: 0
|
||||||
|
irreversible: 0
|
||||||
|
roi_compno: -1
|
||||||
|
roi_shift: 0
|
||||||
|
res_spec: 0
|
||||||
|
prch_init: []
|
||||||
|
prcw_init: []
|
||||||
|
infile: b''
|
||||||
|
outfile: b''
|
||||||
|
index_on: 0
|
||||||
|
index: b''
|
||||||
|
image_offset_x0: 0
|
||||||
|
image_offset_y0: 0
|
||||||
|
subsampling_dx: 1
|
||||||
|
subsampling_dy: 1
|
||||||
|
decod_format: -1
|
||||||
|
cod_format: -1
|
||||||
|
jpwl_epc_on: 0
|
||||||
|
jpwl_hprot_mh: 0
|
||||||
|
jpwl_hprot_tph_tileno: [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
|
||||||
|
jpwl_hprot_tph: [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
|
||||||
|
jpwl_pprot_tileno: [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
|
||||||
|
jpwl_pprot_packno: [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
|
||||||
|
jpwl_pprot: [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
|
||||||
|
jpwl_sens_size: 0
|
||||||
|
jpwl_sens_addr: 0
|
||||||
|
jpwl_sens_range: 0
|
||||||
|
jpwl_sens_mh: 0
|
||||||
|
jpwl_sens_tph_tileno: [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
|
||||||
|
jpwl_sens_tph: [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
|
||||||
|
cp_cinema: 0
|
||||||
|
max_comp_size: 0
|
||||||
|
cp_rsiz: 0
|
||||||
|
tp_on: 0
|
||||||
|
tp_flag: 0
|
||||||
|
tcp_mct: 0
|
||||||
|
jpip_on: 0
|
||||||
|
mct_data: None
|
||||||
|
max_cs_size: 0
|
||||||
|
rsiz: 0"""
|
||||||
|
|
||||||
|
default_image_component_parameters = """<class 'glymur.lib.openjp2.ImageComptParmType'>:
|
||||||
|
dx: 0
|
||||||
|
dy: 0
|
||||||
|
w: 0
|
||||||
|
h: 0
|
||||||
|
x0: 0
|
||||||
|
y0: 0
|
||||||
|
prec: 0
|
||||||
|
bpp: 0
|
||||||
|
sgnd: 0"""
|
||||||
|
|
||||||
|
# The "icc_profile_buf" field is problematic as it is a pointer value, i.e.
|
||||||
|
#
|
||||||
|
# icc_profile_buf: <glymur.lib.openjp2.LP_c_ubyte object at 0x7f28cd5d5d90>
|
||||||
|
#
|
||||||
|
# Have to treat it as a regular expression.
|
||||||
|
default_image_type = """<class 'glymur.lib.openjp2.ImageType'>:
|
||||||
|
x0: 0
|
||||||
|
y0: 0
|
||||||
|
x1: 0
|
||||||
|
y1: 0
|
||||||
|
numcomps: 0
|
||||||
|
color_space: 0
|
||||||
|
icc_profile_buf: <glymur.lib.openjp2.LP_c_ubyte object at 0x[0-9A-Fa-f]*>
|
||||||
|
icc_profile_len: 0"""
|
||||||
|
|
@ -1,13 +1,8 @@
|
||||||
"""
|
"""
|
||||||
Tests for libopenjp2 wrapping functions.
|
Tests for libopenjp2 wrapping functions.
|
||||||
"""
|
"""
|
||||||
# R0904: Seems like pylint is fooled in this situation
|
|
||||||
# W0142: using kwargs is ok in this context
|
|
||||||
# pylint: disable=R0904,W0142
|
|
||||||
|
|
||||||
import os
|
import os
|
||||||
import re
|
import re
|
||||||
import sys
|
|
||||||
import tempfile
|
import tempfile
|
||||||
import unittest
|
import unittest
|
||||||
|
|
||||||
|
|
@ -21,8 +16,8 @@ from glymur.lib import openjp2
|
||||||
@unittest.skipIf(openjp2.OPENJP2 is None,
|
@unittest.skipIf(openjp2.OPENJP2 is None,
|
||||||
"Missing openjp2 library.")
|
"Missing openjp2 library.")
|
||||||
@unittest.skipIf(re.match(r'''(1|2.0)''',
|
@unittest.skipIf(re.match(r'''(1|2.0)''',
|
||||||
glymur.version.openjpeg_version) is not None,
|
glymur.version.openjpeg_version) is not None,
|
||||||
"Not to be run until 2.1.0")
|
"Not to be run until 2.1.0")
|
||||||
class TestOpenJP2(unittest.TestCase):
|
class TestOpenJP2(unittest.TestCase):
|
||||||
"""Test openjp2 library functionality.
|
"""Test openjp2 library functionality.
|
||||||
|
|
||||||
|
|
@ -56,53 +51,6 @@ class TestOpenJP2(unittest.TestCase):
|
||||||
self.assertEqual(dparams.DA_x1, 0)
|
self.assertEqual(dparams.DA_x1, 0)
|
||||||
self.assertEqual(dparams.DA_y1, 0)
|
self.assertEqual(dparams.DA_y1, 0)
|
||||||
|
|
||||||
def tile_macro(self, codec, stream, imagep, tidx):
|
|
||||||
"""called only by j2k_random_tile_access"""
|
|
||||||
openjp2.get_decoded_tile(codec, stream, imagep, tidx)
|
|
||||||
for j in range(imagep.contents.numcomps):
|
|
||||||
self.assertIsNotNone(imagep.contents.comps[j].data)
|
|
||||||
|
|
||||||
def j2k_random_tile_access(self, filename, codec_format=None):
|
|
||||||
"""fixture called by the test_rtaX methods"""
|
|
||||||
dparam = openjp2.set_default_decoder_parameters()
|
|
||||||
|
|
||||||
infile = filename.encode()
|
|
||||||
nelts = openjp2.PATH_LEN - len(infile)
|
|
||||||
infile += b'0' * nelts
|
|
||||||
dparam.infile = infile
|
|
||||||
|
|
||||||
dparam.decod_format = codec_format
|
|
||||||
|
|
||||||
codec = openjp2.create_decompress(codec_format)
|
|
||||||
|
|
||||||
openjp2.set_info_handler(codec, None)
|
|
||||||
openjp2.set_warning_handler(codec, None)
|
|
||||||
openjp2.set_error_handler(codec, None)
|
|
||||||
|
|
||||||
stream = openjp2.stream_create_default_file_stream(filename, True)
|
|
||||||
|
|
||||||
openjp2.setup_decoder(codec, dparam)
|
|
||||||
image = openjp2.read_header(stream, codec)
|
|
||||||
|
|
||||||
cstr_info = openjp2.get_cstr_info(codec)
|
|
||||||
|
|
||||||
tile_ul = 0
|
|
||||||
tile_ur = cstr_info.contents.tw - 1
|
|
||||||
tile_lr = cstr_info.contents.tw * cstr_info.contents.th - 1
|
|
||||||
tile_ll = tile_lr - cstr_info.contents.tw
|
|
||||||
|
|
||||||
self.tile_macro(codec, stream, image, tile_ul)
|
|
||||||
self.tile_macro(codec, stream, image, tile_ur)
|
|
||||||
self.tile_macro(codec, stream, image, tile_lr)
|
|
||||||
self.tile_macro(codec, stream, image, tile_ll)
|
|
||||||
|
|
||||||
openjp2.destroy_cstr_info(cstr_info)
|
|
||||||
|
|
||||||
openjp2.end_decompress(codec, stream)
|
|
||||||
openjp2.destroy_codec(codec)
|
|
||||||
openjp2.stream_destroy(stream)
|
|
||||||
openjp2.image_destroy(image)
|
|
||||||
|
|
||||||
def test_tte0(self):
|
def test_tte0(self):
|
||||||
"""Runs test designated tte0 in OpenJPEG test suite."""
|
"""Runs test designated tte0 in OpenJPEG test suite."""
|
||||||
with tempfile.NamedTemporaryFile(suffix=".j2k") as tfile:
|
with tempfile.NamedTemporaryFile(suffix=".j2k") as tfile:
|
||||||
|
|
@ -160,15 +108,6 @@ class TestOpenJP2(unittest.TestCase):
|
||||||
tile_decoder(**kwargs)
|
tile_decoder(**kwargs)
|
||||||
self.assertTrue(True)
|
self.assertTrue(True)
|
||||||
|
|
||||||
def test_rta1(self):
|
|
||||||
"""Runs test designated rta1 in OpenJPEG test suite."""
|
|
||||||
with tempfile.NamedTemporaryFile(suffix=".j2k") as tfile:
|
|
||||||
self.xtx1_setup(tfile.name)
|
|
||||||
|
|
||||||
codec_format = openjp2.CODEC_J2K
|
|
||||||
self.j2k_random_tile_access(tfile.name, codec_format)
|
|
||||||
self.assertTrue(True)
|
|
||||||
|
|
||||||
def test_tte2(self):
|
def test_tte2(self):
|
||||||
"""Runs test designated tte2 in OpenJPEG test suite."""
|
"""Runs test designated tte2 in OpenJPEG test suite."""
|
||||||
with tempfile.NamedTemporaryFile(suffix=".jp2") as tfile:
|
with tempfile.NamedTemporaryFile(suffix=".jp2") as tfile:
|
||||||
|
|
@ -190,62 +129,25 @@ class TestOpenJP2(unittest.TestCase):
|
||||||
tile_decoder(**kwargs)
|
tile_decoder(**kwargs)
|
||||||
self.assertTrue(True)
|
self.assertTrue(True)
|
||||||
|
|
||||||
def test_rta2(self):
|
|
||||||
"""Runs test designated rta2 in OpenJPEG test suite."""
|
|
||||||
with tempfile.NamedTemporaryFile(suffix=".jp2") as tfile:
|
|
||||||
xtx2_setup(tfile.name)
|
|
||||||
|
|
||||||
codec_format = openjp2.CODEC_JP2
|
|
||||||
self.j2k_random_tile_access(tfile.name, codec_format)
|
|
||||||
|
|
||||||
def test_tte3(self):
|
def test_tte3(self):
|
||||||
"""Runs test designated tte3 in OpenJPEG test suite."""
|
"""Runs test designated tte3 in OpenJPEG test suite."""
|
||||||
with tempfile.NamedTemporaryFile(suffix=".j2k") as tfile:
|
with tempfile.NamedTemporaryFile(suffix=".j2k") as tfile:
|
||||||
xtx3_setup(tfile.name)
|
xtx3_setup(tfile.name)
|
||||||
self.assertTrue(True)
|
self.assertTrue(True)
|
||||||
|
|
||||||
def test_rta3(self):
|
|
||||||
"""Runs test designated rta3 in OpenJPEG test suite."""
|
|
||||||
with tempfile.NamedTemporaryFile(suffix=".j2k") as tfile:
|
|
||||||
xtx3_setup(tfile.name)
|
|
||||||
|
|
||||||
codec_format = openjp2.CODEC_J2K
|
|
||||||
self.j2k_random_tile_access(tfile.name, codec_format)
|
|
||||||
self.assertTrue(True)
|
|
||||||
|
|
||||||
def test_tte4(self):
|
def test_tte4(self):
|
||||||
"""Runs test designated tte4 in OpenJPEG test suite."""
|
"""Runs test designated tte4 in OpenJPEG test suite."""
|
||||||
with tempfile.NamedTemporaryFile(suffix=".j2k") as tfile:
|
with tempfile.NamedTemporaryFile(suffix=".j2k") as tfile:
|
||||||
xtx4_setup(tfile.name)
|
xtx4_setup(tfile.name)
|
||||||
self.assertTrue(True)
|
self.assertTrue(True)
|
||||||
|
|
||||||
def test_rta4(self):
|
|
||||||
"""Runs test designated rta4 in OpenJPEG test suite."""
|
|
||||||
with tempfile.NamedTemporaryFile(suffix=".j2k") as tfile:
|
|
||||||
xtx4_setup(tfile.name)
|
|
||||||
|
|
||||||
codec_format = openjp2.CODEC_J2K
|
|
||||||
self.j2k_random_tile_access(tfile.name, codec_format)
|
|
||||||
|
|
||||||
def test_tte5(self):
|
def test_tte5(self):
|
||||||
"""Runs test designated tte5 in OpenJPEG test suite."""
|
"""Runs test designated tte5 in OpenJPEG test suite."""
|
||||||
with tempfile.NamedTemporaryFile(suffix=".j2k") as tfile:
|
with tempfile.NamedTemporaryFile(suffix=".j2k") as tfile:
|
||||||
xtx5_setup(tfile.name)
|
xtx5_setup(tfile.name)
|
||||||
self.assertTrue(True)
|
self.assertTrue(True)
|
||||||
|
|
||||||
def test_rta5(self):
|
|
||||||
"""Runs test designated rta5 in OpenJPEG test suite."""
|
|
||||||
with tempfile.NamedTemporaryFile(suffix=".j2k") as tfile:
|
|
||||||
xtx5_setup(tfile.name)
|
|
||||||
|
|
||||||
codec_format = openjp2.CODEC_J2K
|
|
||||||
self.j2k_random_tile_access(tfile.name, codec_format)
|
|
||||||
|
|
||||||
|
|
||||||
#def tile_encoder(num_comps=None, tile_width=None, tile_height=None,
|
|
||||||
# filename=None, codec=None, comp_prec=None,
|
|
||||||
# image_width=None, image_height=None,
|
|
||||||
# irreversible=None):
|
|
||||||
def tile_encoder(**kwargs):
|
def tile_encoder(**kwargs):
|
||||||
"""Fixture used by many tests."""
|
"""Fixture used by many tests."""
|
||||||
num_tiles = ((kwargs['image_width'] / kwargs['tile_width']) *
|
num_tiles = ((kwargs['image_width'] / kwargs['tile_width']) *
|
||||||
|
|
@ -309,7 +211,7 @@ def tile_encoder(**kwargs):
|
||||||
openjp2.setup_encoder(codec, l_param, l_image)
|
openjp2.setup_encoder(codec, l_param, l_image)
|
||||||
|
|
||||||
stream = openjp2.stream_create_default_file_stream(kwargs['filename'],
|
stream = openjp2.stream_create_default_file_stream(kwargs['filename'],
|
||||||
False)
|
False)
|
||||||
openjp2.start_compress(codec, l_image, stream)
|
openjp2.start_compress(codec, l_image, stream)
|
||||||
|
|
||||||
for j in np.arange(num_tiles):
|
for j in np.arange(num_tiles):
|
||||||
|
|
@ -320,13 +222,14 @@ def tile_encoder(**kwargs):
|
||||||
openjp2.destroy_codec(codec)
|
openjp2.destroy_codec(codec)
|
||||||
openjp2.image_destroy(l_image)
|
openjp2.image_destroy(l_image)
|
||||||
|
|
||||||
|
|
||||||
def tile_decoder(**kwargs):
|
def tile_decoder(**kwargs):
|
||||||
"""Fixture called with various configurations by many tests.
|
"""Fixture called with various configurations by many tests.
|
||||||
|
|
||||||
Reads a tile. That's all it does.
|
Reads a tile. That's all it does.
|
||||||
"""
|
"""
|
||||||
stream = openjp2.stream_create_default_file_stream(kwargs['filename'],
|
stream = openjp2.stream_create_default_file_stream(kwargs['filename'],
|
||||||
True)
|
True)
|
||||||
dparam = openjp2.set_default_decoder_parameters()
|
dparam = openjp2.set_default_decoder_parameters()
|
||||||
|
|
||||||
dparam.decod_format = kwargs['codec_format']
|
dparam.decod_format = kwargs['codec_format']
|
||||||
|
|
@ -364,6 +267,7 @@ def tile_decoder(**kwargs):
|
||||||
openjp2.stream_destroy(stream)
|
openjp2.stream_destroy(stream)
|
||||||
openjp2.image_destroy(image)
|
openjp2.image_destroy(image)
|
||||||
|
|
||||||
|
|
||||||
def ttx0_setup(filename):
|
def ttx0_setup(filename):
|
||||||
"""Runs tests tte0, tte0."""
|
"""Runs tests tte0, tte0."""
|
||||||
kwargs = {'filename': filename,
|
kwargs = {'filename': filename,
|
||||||
|
|
@ -377,6 +281,7 @@ def ttx0_setup(filename):
|
||||||
'tile_width': 100}
|
'tile_width': 100}
|
||||||
tile_encoder(**kwargs)
|
tile_encoder(**kwargs)
|
||||||
|
|
||||||
|
|
||||||
def xtx2_setup(filename):
|
def xtx2_setup(filename):
|
||||||
"""Runs tests rta2, tte2, ttd2."""
|
"""Runs tests rta2, tte2, ttd2."""
|
||||||
kwargs = {'filename': filename,
|
kwargs = {'filename': filename,
|
||||||
|
|
@ -390,6 +295,7 @@ def xtx2_setup(filename):
|
||||||
'tile_width': 128}
|
'tile_width': 128}
|
||||||
tile_encoder(**kwargs)
|
tile_encoder(**kwargs)
|
||||||
|
|
||||||
|
|
||||||
def xtx3_setup(filename):
|
def xtx3_setup(filename):
|
||||||
"""Runs tests tte3, rta3."""
|
"""Runs tests tte3, rta3."""
|
||||||
kwargs = {'filename': filename,
|
kwargs = {'filename': filename,
|
||||||
|
|
@ -403,6 +309,7 @@ def xtx3_setup(filename):
|
||||||
'tile_width': 128}
|
'tile_width': 128}
|
||||||
tile_encoder(**kwargs)
|
tile_encoder(**kwargs)
|
||||||
|
|
||||||
|
|
||||||
def xtx4_setup(filename):
|
def xtx4_setup(filename):
|
||||||
"""Runs tests rta4, tte4."""
|
"""Runs tests rta4, tte4."""
|
||||||
kwargs = {'filename': filename,
|
kwargs = {'filename': filename,
|
||||||
|
|
@ -416,6 +323,7 @@ def xtx4_setup(filename):
|
||||||
'tile_width': 128}
|
'tile_width': 128}
|
||||||
tile_encoder(**kwargs)
|
tile_encoder(**kwargs)
|
||||||
|
|
||||||
|
|
||||||
def xtx5_setup(filename):
|
def xtx5_setup(filename):
|
||||||
"""Runs tests rta5, tte5."""
|
"""Runs tests rta5, tte5."""
|
||||||
kwargs = {'filename': filename,
|
kwargs = {'filename': filename,
|
||||||
|
|
@ -428,6 +336,3 @@ def xtx5_setup(filename):
|
||||||
'tile_height': 256,
|
'tile_height': 256,
|
||||||
'tile_width': 256}
|
'tile_width': 256}
|
||||||
tile_encoder(**kwargs)
|
tile_encoder(**kwargs)
|
||||||
|
|
||||||
if __name__ == "__main__":
|
|
||||||
unittest.main()
|
|
||||||
|
|
|
||||||
|
|
@ -1,8 +1,6 @@
|
||||||
"""
|
"""
|
||||||
Tests for OpenJPEG module.
|
Tests for OpenJPEG module.
|
||||||
"""
|
"""
|
||||||
# pylint: disable=E1101,R0904
|
|
||||||
|
|
||||||
import ctypes
|
import ctypes
|
||||||
import re
|
import re
|
||||||
import sys
|
import sys
|
||||||
|
|
@ -10,6 +8,7 @@ import unittest
|
||||||
|
|
||||||
import glymur
|
import glymur
|
||||||
|
|
||||||
|
|
||||||
@unittest.skipIf(glymur.lib.openjpeg.OPENJPEG is None,
|
@unittest.skipIf(glymur.lib.openjpeg.OPENJPEG is None,
|
||||||
"Missing openjpeg library.")
|
"Missing openjpeg library.")
|
||||||
class TestOpenJPEG(unittest.TestCase):
|
class TestOpenJPEG(unittest.TestCase):
|
||||||
|
|
|
||||||
75
glymur/lib/test/test_printing.py
Normal file
75
glymur/lib/test/test_printing.py
Normal file
|
|
@ -0,0 +1,75 @@
|
||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
"""Test suite for printing.
|
||||||
|
"""
|
||||||
|
|
||||||
|
import re
|
||||||
|
import sys
|
||||||
|
import unittest
|
||||||
|
|
||||||
|
if sys.hexversion < 0x03000000:
|
||||||
|
from mock import patch
|
||||||
|
from StringIO import StringIO
|
||||||
|
else:
|
||||||
|
from unittest.mock import patch
|
||||||
|
from io import StringIO
|
||||||
|
|
||||||
|
import glymur
|
||||||
|
from . import fixtures
|
||||||
|
|
||||||
|
|
||||||
|
@unittest.skipIf(sys.hexversion < 0x03000000, "do not care about 2.7 here")
|
||||||
|
@unittest.skipIf(re.match('0|1|2.0', glymur.version.openjpeg_version),
|
||||||
|
"Requires openjpeg 2.1.0 or higher")
|
||||||
|
class TestPrintingOpenjp2(unittest.TestCase):
|
||||||
|
"""Tests for verifying how printing works on openjp2 library structures."""
|
||||||
|
def setUp(self):
|
||||||
|
self.jp2file = glymur.data.nemo()
|
||||||
|
|
||||||
|
def tearDown(self):
|
||||||
|
pass
|
||||||
|
|
||||||
|
def test_decompression_parameters(self):
|
||||||
|
"""printing DecompressionParametersType"""
|
||||||
|
dparams = glymur.lib.openjp2.set_default_decoder_parameters()
|
||||||
|
with patch('sys.stdout', new=StringIO()) as fake_out:
|
||||||
|
print(dparams)
|
||||||
|
actual = fake_out.getvalue().strip()
|
||||||
|
expected = fixtures.decompression_parameters_type
|
||||||
|
self.assertEqual(actual, expected)
|
||||||
|
|
||||||
|
def test_progression_order_changes(self):
|
||||||
|
"""printing PocType"""
|
||||||
|
ptype = glymur.lib.openjp2.PocType()
|
||||||
|
with patch('sys.stdout', new=StringIO()) as fake_out:
|
||||||
|
print(ptype)
|
||||||
|
actual = fake_out.getvalue().strip()
|
||||||
|
expected = fixtures.default_progression_order_changes_type
|
||||||
|
self.assertEqual(actual, expected)
|
||||||
|
|
||||||
|
def test_default_compression_parameters(self):
|
||||||
|
"""printing default compression parameters"""
|
||||||
|
cparams = glymur.lib.openjp2.set_default_encoder_parameters()
|
||||||
|
with patch('sys.stdout', new=StringIO()) as fake_out:
|
||||||
|
print(cparams)
|
||||||
|
actual = fake_out.getvalue().strip()
|
||||||
|
expected = fixtures.default_compression_parameters_type
|
||||||
|
self.assertEqual(actual, expected)
|
||||||
|
|
||||||
|
def test_default_component_parameters(self):
|
||||||
|
"""printing default image component parameters"""
|
||||||
|
icpt = glymur.lib.openjp2.ImageComptParmType()
|
||||||
|
with patch('sys.stdout', new=StringIO()) as fake_out:
|
||||||
|
print(icpt)
|
||||||
|
actual = fake_out.getvalue().strip()
|
||||||
|
expected = fixtures.default_image_component_parameters
|
||||||
|
self.assertEqual(actual, expected)
|
||||||
|
|
||||||
|
def test_default_image_type(self):
|
||||||
|
"""printing default image type"""
|
||||||
|
it = glymur.lib.openjp2.ImageType()
|
||||||
|
with patch('sys.stdout', new=StringIO()) as fake_out:
|
||||||
|
print(it)
|
||||||
|
actual = fake_out.getvalue().strip()
|
||||||
|
|
||||||
|
expected = fixtures.default_image_type
|
||||||
|
self.assertRegex(actual, expected)
|
||||||
|
|
@ -13,6 +13,14 @@ import six
|
||||||
|
|
||||||
import glymur
|
import glymur
|
||||||
|
|
||||||
|
# If openjpeg is not installed, many tests cannot be run.
|
||||||
|
if glymur.version.openjpeg_version == '0.0.0':
|
||||||
|
OPENJPEG_NOT_AVAILABLE = True
|
||||||
|
OPENJPEG_NOT_AVAILABLE_MSG = 'OpenJPEG library not installed'
|
||||||
|
else:
|
||||||
|
OPENJPEG_NOT_AVAILABLE = False
|
||||||
|
OPENJPEG_NOT_AVAILABLE_MSG = None
|
||||||
|
|
||||||
# Some versions of "six" on python3 cause problems when verifying warnings.
|
# Some versions of "six" on python3 cause problems when verifying warnings.
|
||||||
# Only use when the version is 1.7 or higher.
|
# Only use when the version is 1.7 or higher.
|
||||||
# And moreover, we only test using the 3.x infrastructure, never on 2.x.
|
# And moreover, we only test using the 3.x infrastructure, never on 2.x.
|
||||||
|
|
@ -26,6 +34,10 @@ elif re.match('1.[0-6]', six.__version__) is not None:
|
||||||
msg = "Cannot run test with version {0} of python-six"
|
msg = "Cannot run test with version {0} of python-six"
|
||||||
WARNING_INFRASTRUCTURE_MSG = msg.format(six.__version__)
|
WARNING_INFRASTRUCTURE_MSG = msg.format(six.__version__)
|
||||||
|
|
||||||
|
# Cannot reopen a named temporary file in windows.
|
||||||
|
WINDOWS_TMP_FILE_MSG = "cannot use NamedTemporaryFile like this in windows"
|
||||||
|
|
||||||
|
|
||||||
class MetadataBase(unittest.TestCase):
|
class MetadataBase(unittest.TestCase):
|
||||||
"""
|
"""
|
||||||
Base class for testing metadata.
|
Base class for testing metadata.
|
||||||
|
|
@ -90,8 +102,8 @@ class MetadataBase(unittest.TestCase):
|
||||||
"""
|
"""
|
||||||
verify the fields of a RGN segment
|
verify the fields of a RGN segment
|
||||||
"""
|
"""
|
||||||
self.assertEqual(actual.crgn, expected.crgn) # 0 = component
|
self.assertEqual(actual.crgn, expected.crgn) # 0 = component
|
||||||
self.assertEqual(actual.srgn, expected.srgn) # 0 = implicit
|
self.assertEqual(actual.srgn, expected.srgn) # 0 = implicit
|
||||||
self.assertEqual(actual.sprgn, expected.sprgn)
|
self.assertEqual(actual.sprgn, expected.sprgn)
|
||||||
|
|
||||||
def verifySOTsegment(self, actual, expected):
|
def verifySOTsegment(self, actual, expected):
|
||||||
|
|
@ -114,8 +126,9 @@ class MetadataBase(unittest.TestCase):
|
||||||
"""
|
"""
|
||||||
Verify the fields of the SIZ segment.
|
Verify the fields of the SIZ segment.
|
||||||
"""
|
"""
|
||||||
for field in ['rsiz', 'xsiz', 'ysiz', 'xosiz', 'yosiz', 'xtsiz',
|
for field in ['rsiz', 'xsiz', 'ysiz', 'xosiz', 'yosiz', 'xtsiz',
|
||||||
'ytsiz', 'xtosiz', 'ytosiz', 'bitdepth', 'xrsiz', 'yrsiz']:
|
'ytsiz', 'xtosiz', 'ytosiz', 'bitdepth',
|
||||||
|
'xrsiz', 'yrsiz']:
|
||||||
self.assertEqual(getattr(actual, field), getattr(expected, field))
|
self.assertEqual(getattr(actual, field), getattr(expected, field))
|
||||||
|
|
||||||
def verifyImageHeaderBox(self, box1, box2):
|
def verifyImageHeaderBox(self, box1, box2):
|
||||||
|
|
@ -142,7 +155,7 @@ class MetadataBase(unittest.TestCase):
|
||||||
else:
|
else:
|
||||||
self.assertEqual(actual.colorspace, expected.colorspace)
|
self.assertEqual(actual.colorspace, expected.colorspace)
|
||||||
self.assertIsNone(actual.icc_profile)
|
self.assertIsNone(actual.icc_profile)
|
||||||
|
|
||||||
|
|
||||||
# The Python XMP Toolkit may be used for XMP UUIDs, but only if available and
|
# The Python XMP Toolkit may be used for XMP UUIDs, but only if available and
|
||||||
# if the version is at least 2.0.0.
|
# if the version is at least 2.0.0.
|
||||||
|
|
@ -172,7 +185,7 @@ except:
|
||||||
# The Cinema2K/4K tests seem to need the freeimage backend to skimage.io
|
# The Cinema2K/4K tests seem to need the freeimage backend to skimage.io
|
||||||
# in order to work. Unfortunately, scikit-image/freeimage is about as wonky as
|
# in order to work. Unfortunately, scikit-image/freeimage is about as wonky as
|
||||||
# it gets. Anaconda can get totally weirded out on versions up through 3.6.4
|
# it gets. Anaconda can get totally weirded out on versions up through 3.6.4
|
||||||
# on Python3 with scikit-image up through version 0.10.0.
|
# on Python3 with scikit-image up through version 0.10.0.
|
||||||
NO_SKIMAGE_FREEIMAGE_SUPPORT = False
|
NO_SKIMAGE_FREEIMAGE_SUPPORT = False
|
||||||
try:
|
try:
|
||||||
import skimage
|
import skimage
|
||||||
|
|
@ -200,7 +213,7 @@ def _indent(textstr):
|
||||||
String to be indented.
|
String to be indented.
|
||||||
indent_level : str
|
indent_level : str
|
||||||
Number of spaces of indentation to add.
|
Number of spaces of indentation to add.
|
||||||
|
|
||||||
Returns
|
Returns
|
||||||
-------
|
-------
|
||||||
indented_string : str
|
indented_string : str
|
||||||
|
|
@ -223,7 +236,6 @@ try:
|
||||||
|
|
||||||
# The whole point of trying to import PIL is to determine if it's there
|
# The whole point of trying to import PIL is to determine if it's there
|
||||||
# or not. We won't use it directly.
|
# or not. We won't use it directly.
|
||||||
# pylint: disable=F0401,W0611
|
|
||||||
import PIL
|
import PIL
|
||||||
|
|
||||||
NO_READ_BACKEND = False
|
NO_READ_BACKEND = False
|
||||||
|
|
@ -533,7 +545,7 @@ text_gbr_34 = """Colour Specification Box (colr) @ (179, 1339)
|
||||||
dump = r'''JPEG 2000 Signature Box (jP ) @ (0, 12)
|
dump = r'''JPEG 2000 Signature Box (jP ) @ (0, 12)
|
||||||
Signature: 0d0a870a
|
Signature: 0d0a870a
|
||||||
File Type Box (ftyp) @ (12, 20)
|
File Type Box (ftyp) @ (12, 20)
|
||||||
Brand: jp2
|
Brand: jp2
|
||||||
Compatibility: ['jp2 ']
|
Compatibility: ['jp2 ']
|
||||||
JP2 Header Box (jp2h) @ (32, 45)
|
JP2 Header Box (jp2h) @ (32, 45)
|
||||||
Image Header Box (ihdr) @ (40, 22)
|
Image Header Box (ihdr) @ (40, 22)
|
||||||
|
|
@ -589,7 +601,6 @@ Contiguous Codestream Box (jp2c) @ (3223, 1132296)
|
||||||
"Created by OpenJPEG version 2.0.0"'''
|
"Created by OpenJPEG version 2.0.0"'''
|
||||||
|
|
||||||
nemo_with_codestream_header = dump.format(_indent(nemo_xmp))
|
nemo_with_codestream_header = dump.format(_indent(nemo_xmp))
|
||||||
#nemo_dump_full = dump.format(_indent(nemo_xmp))
|
|
||||||
|
|
||||||
nemo_dump_short = r"""JPEG 2000 Signature Box (jP ) @ (0, 12)
|
nemo_dump_short = r"""JPEG 2000 Signature Box (jP ) @ (0, 12)
|
||||||
File Type Box (ftyp) @ (12, 20)
|
File Type Box (ftyp) @ (12, 20)
|
||||||
|
|
@ -602,7 +613,7 @@ Contiguous Codestream Box (jp2c) @ (3223, 1132296)"""
|
||||||
nemo_dump_no_xml = '''JPEG 2000 Signature Box (jP ) @ (0, 12)
|
nemo_dump_no_xml = '''JPEG 2000 Signature Box (jP ) @ (0, 12)
|
||||||
Signature: 0d0a870a
|
Signature: 0d0a870a
|
||||||
File Type Box (ftyp) @ (12, 20)
|
File Type Box (ftyp) @ (12, 20)
|
||||||
Brand: jp2
|
Brand: jp2
|
||||||
Compatibility: ['jp2 ']
|
Compatibility: ['jp2 ']
|
||||||
JP2 Header Box (jp2h) @ (32, 45)
|
JP2 Header Box (jp2h) @ (32, 45)
|
||||||
Image Header Box (ihdr) @ (40, 22)
|
Image Header Box (ihdr) @ (40, 22)
|
||||||
|
|
@ -658,7 +669,7 @@ Contiguous Codestream Box (jp2c) @ (3223, 1132296)
|
||||||
dump = r"""JPEG 2000 Signature Box (jP ) @ (0, 12)
|
dump = r"""JPEG 2000 Signature Box (jP ) @ (0, 12)
|
||||||
Signature: 0d0a870a
|
Signature: 0d0a870a
|
||||||
File Type Box (ftyp) @ (12, 20)
|
File Type Box (ftyp) @ (12, 20)
|
||||||
Brand: jp2
|
Brand: jp2
|
||||||
Compatibility: ['jp2 ']
|
Compatibility: ['jp2 ']
|
||||||
JP2 Header Box (jp2h) @ (32, 45)
|
JP2 Header Box (jp2h) @ (32, 45)
|
||||||
Image Header Box (ihdr) @ (40, 22)
|
Image Header Box (ihdr) @ (40, 22)
|
||||||
|
|
@ -681,7 +692,7 @@ nemo_dump_no_codestream = dump.format(_indent(nemo_xmp))
|
||||||
nemo_dump_no_codestream_no_xml = r"""JPEG 2000 Signature Box (jP ) @ (0, 12)
|
nemo_dump_no_codestream_no_xml = r"""JPEG 2000 Signature Box (jP ) @ (0, 12)
|
||||||
Signature: 0d0a870a
|
Signature: 0d0a870a
|
||||||
File Type Box (ftyp) @ (12, 20)
|
File Type Box (ftyp) @ (12, 20)
|
||||||
Brand: jp2
|
Brand: jp2
|
||||||
Compatibility: ['jp2 ']
|
Compatibility: ['jp2 ']
|
||||||
JP2 Header Box (jp2h) @ (32, 45)
|
JP2 Header Box (jp2h) @ (32, 45)
|
||||||
Image Header Box (ihdr) @ (40, 22)
|
Image Header Box (ihdr) @ (40, 22)
|
||||||
|
|
@ -698,6 +709,190 @@ UUID Box (uuid) @ (77, 3146)
|
||||||
UUID: be7acfcb-97a9-42e8-9c71-999491e3afac (XMP)
|
UUID: be7acfcb-97a9-42e8-9c71-999491e3afac (XMP)
|
||||||
Contiguous Codestream Box (jp2c) @ (3223, 1132296)"""
|
Contiguous Codestream Box (jp2c) @ (3223, 1132296)"""
|
||||||
|
|
||||||
|
nemo = """JPEG 2000 Signature Box (jP ) @ (0, 12)
|
||||||
|
Signature: 0d0a870a
|
||||||
|
File Type Box (ftyp) @ (12, 20)
|
||||||
|
Brand: jp2
|
||||||
|
Compatibility: ['jp2 ']
|
||||||
|
JP2 Header Box (jp2h) @ (32, 45)
|
||||||
|
Image Header Box (ihdr) @ (40, 22)
|
||||||
|
Size: [1456 2592 3]
|
||||||
|
Bitdepth: 8
|
||||||
|
Signed: False
|
||||||
|
Compression: wavelet
|
||||||
|
Colorspace Unknown: False
|
||||||
|
Colour Specification Box (colr) @ (62, 15)
|
||||||
|
Method: enumerated colorspace
|
||||||
|
Precedence: 0
|
||||||
|
Colorspace: sRGB
|
||||||
|
UUID Box (uuid) @ (77, 3146)
|
||||||
|
UUID: be7acfcb-97a9-42e8-9c71-999491e3afac (XMP)
|
||||||
|
UUID Data:
|
||||||
|
<?xpacket begin="" id="W5M0MpCehiHzreSzNTczkc9d"?>
|
||||||
|
<ns0:xmpmeta xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:ns0="adobe:ns:meta/" xmlns:ns2="http://ns.adobe.com/xap/1.0/" xmlns:ns3="http://ns.adobe.com/tiff/1.0/" xmlns:ns4="http://ns.adobe.com/exif/1.0/" xmlns:ns5="http://ns.adobe.com/photoshop/1.0/" xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" ns0:xmptk="Exempi + XMP Core 5.1.2">
|
||||||
|
<rdf:RDF>
|
||||||
|
<rdf:Description rdf:about="">
|
||||||
|
<ns2:CreatorTool>Google</ns2:CreatorTool>
|
||||||
|
<ns2:CreateDate>2013-02-09T14:47:53</ns2:CreateDate>
|
||||||
|
</rdf:Description>
|
||||||
|
<rdf:Description rdf:about="">
|
||||||
|
<ns3:YCbCrPositioning>1</ns3:YCbCrPositioning>
|
||||||
|
<ns3:XResolution>72/1</ns3:XResolution>
|
||||||
|
<ns3:YResolution>72/1</ns3:YResolution>
|
||||||
|
<ns3:ResolutionUnit>2</ns3:ResolutionUnit>
|
||||||
|
<ns3:Make>HTC</ns3:Make>
|
||||||
|
<ns3:Model>HTC Glacier</ns3:Model>
|
||||||
|
<ns3:ImageWidth>2592</ns3:ImageWidth>
|
||||||
|
<ns3:ImageLength>1456</ns3:ImageLength>
|
||||||
|
<ns3:BitsPerSample>
|
||||||
|
<rdf:Seq>
|
||||||
|
<rdf:li>8</rdf:li>
|
||||||
|
<rdf:li>8</rdf:li>
|
||||||
|
<rdf:li>8</rdf:li>
|
||||||
|
</rdf:Seq>
|
||||||
|
</ns3:BitsPerSample>
|
||||||
|
<ns3:PhotometricInterpretation>2</ns3:PhotometricInterpretation>
|
||||||
|
<ns3:SamplesPerPixel>3</ns3:SamplesPerPixel>
|
||||||
|
<ns3:WhitePoint>
|
||||||
|
<rdf:Seq>
|
||||||
|
<rdf:li>1343036288/4294967295</rdf:li>
|
||||||
|
<rdf:li>1413044224/4294967295</rdf:li>
|
||||||
|
</rdf:Seq>
|
||||||
|
</ns3:WhitePoint>
|
||||||
|
<ns3:PrimaryChromaticities>
|
||||||
|
<rdf:Seq>
|
||||||
|
<rdf:li>2748779008/4294967295</rdf:li>
|
||||||
|
<rdf:li>1417339264/4294967295</rdf:li>
|
||||||
|
<rdf:li>1288490240/4294967295</rdf:li>
|
||||||
|
<rdf:li>2576980480/4294967295</rdf:li>
|
||||||
|
<rdf:li>644245120/4294967295</rdf:li>
|
||||||
|
<rdf:li>257698032/4294967295</rdf:li>
|
||||||
|
</rdf:Seq>
|
||||||
|
</ns3:PrimaryChromaticities>
|
||||||
|
</rdf:Description>
|
||||||
|
<rdf:Description rdf:about="">
|
||||||
|
<ns4:ColorSpace>1</ns4:ColorSpace>
|
||||||
|
<ns4:PixelXDimension>2528</ns4:PixelXDimension>
|
||||||
|
<ns4:PixelYDimension>1424</ns4:PixelYDimension>
|
||||||
|
<ns4:FocalLength>353/100</ns4:FocalLength>
|
||||||
|
<ns4:GPSAltitudeRef>0</ns4:GPSAltitudeRef>
|
||||||
|
<ns4:GPSAltitude>0/1</ns4:GPSAltitude>
|
||||||
|
<ns4:GPSMapDatum>WGS-84</ns4:GPSMapDatum>
|
||||||
|
<ns4:DateTimeOriginal>2013-02-09T14:47:53</ns4:DateTimeOriginal>
|
||||||
|
<ns4:ISOSpeedRatings>
|
||||||
|
<rdf:Seq>
|
||||||
|
<rdf:li>76</rdf:li>
|
||||||
|
</rdf:Seq>
|
||||||
|
</ns4:ISOSpeedRatings>
|
||||||
|
<ns4:ExifVersion>0220</ns4:ExifVersion>
|
||||||
|
<ns4:FlashpixVersion>0100</ns4:FlashpixVersion>
|
||||||
|
<ns4:ComponentsConfiguration>
|
||||||
|
<rdf:Seq>
|
||||||
|
<rdf:li>1</rdf:li>
|
||||||
|
<rdf:li>2</rdf:li>
|
||||||
|
<rdf:li>3</rdf:li>
|
||||||
|
<rdf:li>0</rdf:li>
|
||||||
|
</rdf:Seq>
|
||||||
|
</ns4:ComponentsConfiguration>
|
||||||
|
<ns4:GPSLatitude>42,20.56N</ns4:GPSLatitude>
|
||||||
|
<ns4:GPSLongitude>71,5.29W</ns4:GPSLongitude>
|
||||||
|
<ns4:GPSTimeStamp>2013-02-09T19:47:53Z</ns4:GPSTimeStamp>
|
||||||
|
<ns4:GPSProcessingMethod>NETWORK</ns4:GPSProcessingMethod>
|
||||||
|
</rdf:Description>
|
||||||
|
<rdf:Description rdf:about="">
|
||||||
|
<ns5:DateCreated>2013-02-09T14:47:53</ns5:DateCreated>
|
||||||
|
</rdf:Description>
|
||||||
|
<rdf:Description rdf:about="">
|
||||||
|
<dc:Creator>
|
||||||
|
<rdf:Seq>
|
||||||
|
<rdf:li>Glymur</rdf:li>
|
||||||
|
<rdf:li>Python XMP Toolkit</rdf:li>
|
||||||
|
</rdf:Seq>
|
||||||
|
</dc:Creator>
|
||||||
|
</rdf:Description>
|
||||||
|
</rdf:RDF>
|
||||||
|
</ns0:xmpmeta>
|
||||||
|
<?xpacket end="w"?>
|
||||||
|
Contiguous Codestream Box (jp2c) @ (3223, 1132296)
|
||||||
|
SOC marker segment @ (3231, 0)
|
||||||
|
SIZ marker segment @ (3233, 47)
|
||||||
|
Profile: no profile
|
||||||
|
Reference Grid Height, Width: (1456 x 2592)
|
||||||
|
Vertical, Horizontal Reference Grid Offset: (0 x 0)
|
||||||
|
Reference Tile Height, Width: (1456 x 2592)
|
||||||
|
Vertical, Horizontal Reference Tile Offset: (0 x 0)
|
||||||
|
Bitdepth: (8, 8, 8)
|
||||||
|
Signed: (False, False, False)
|
||||||
|
Vertical, Horizontal Subsampling: ((1, 1), (1, 1), (1, 1))
|
||||||
|
COD marker segment @ (3282, 12)
|
||||||
|
Coding style:
|
||||||
|
Entropy coder, without partitions
|
||||||
|
SOP marker segments: False
|
||||||
|
EPH marker segments: False
|
||||||
|
Coding style parameters:
|
||||||
|
Progression order: LRCP
|
||||||
|
Number of layers: 2
|
||||||
|
Multiple component transformation usage: reversible
|
||||||
|
Number of resolutions: 2
|
||||||
|
Code block height, width: (64 x 64)
|
||||||
|
Wavelet transform: 5-3 reversible
|
||||||
|
Precinct size: default, 2^15 x 2^15
|
||||||
|
Code block context:
|
||||||
|
Selective arithmetic coding bypass: False
|
||||||
|
Reset context probabilities on coding pass boundaries: False
|
||||||
|
Termination on each coding pass: False
|
||||||
|
Vertically stripe causal context: False
|
||||||
|
Predictable termination: False
|
||||||
|
Segmentation symbols: False
|
||||||
|
QCD marker segment @ (3296, 7)
|
||||||
|
Quantization style: no quantization, 2 guard bits
|
||||||
|
Step size: [(0, 8), (0, 9), (0, 9), (0, 10)]
|
||||||
|
CME marker segment @ (3305, 37)
|
||||||
|
"Created by OpenJPEG version 2.0.0"
|
||||||
|
SOT marker segment @ (3344, 10)
|
||||||
|
Tile part index: 0
|
||||||
|
Tile part length: 1132173
|
||||||
|
Tile part instance: 0
|
||||||
|
Number of tile parts: 1
|
||||||
|
COC marker segment @ (3356, 9)
|
||||||
|
Associated component: 1
|
||||||
|
Coding style for this component: Entropy coder, PARTITION = 0
|
||||||
|
Coding style parameters:
|
||||||
|
Number of resolutions: 2
|
||||||
|
Code block height, width: (64 x 64)
|
||||||
|
Wavelet transform: 5-3 reversible
|
||||||
|
Code block context:
|
||||||
|
Selective arithmetic coding bypass: False
|
||||||
|
Reset context probabilities on coding pass boundaries: False
|
||||||
|
Termination on each coding pass: False
|
||||||
|
Vertically stripe causal context: False
|
||||||
|
Predictable termination: False
|
||||||
|
Segmentation symbols: False
|
||||||
|
QCC marker segment @ (3367, 8)
|
||||||
|
Associated Component: 1
|
||||||
|
Quantization style: no quantization, 2 guard bits
|
||||||
|
Step size: [(0, 8), (0, 9), (0, 9), (0, 10)]
|
||||||
|
COC marker segment @ (3377, 9)
|
||||||
|
Associated component: 2
|
||||||
|
Coding style for this component: Entropy coder, PARTITION = 0
|
||||||
|
Coding style parameters:
|
||||||
|
Number of resolutions: 2
|
||||||
|
Code block height, width: (64 x 64)
|
||||||
|
Wavelet transform: 5-3 reversible
|
||||||
|
Code block context:
|
||||||
|
Selective arithmetic coding bypass: False
|
||||||
|
Reset context probabilities on coding pass boundaries: False
|
||||||
|
Termination on each coding pass: False
|
||||||
|
Vertically stripe causal context: False
|
||||||
|
Predictable termination: False
|
||||||
|
Segmentation symbols: False
|
||||||
|
QCC marker segment @ (3388, 8)
|
||||||
|
Associated Component: 2
|
||||||
|
Quantization style: no quantization, 2 guard bits
|
||||||
|
Step size: [(0, 8), (0, 9), (0, 9), (0, 10)]
|
||||||
|
SOD marker segment @ (3398, 0)
|
||||||
|
EOC marker segment @ (1135517, 0)"""
|
||||||
|
|
||||||
# Output of reader requirements printing for text_GBR.jp2
|
# Output of reader requirements printing for text_GBR.jp2
|
||||||
text_GBR_rreq = r"""Reader Requirements Box (rreq) @ (40, 109)
|
text_GBR_rreq = r"""Reader Requirements Box (rreq) @ (40, 109)
|
||||||
Fully Understands Aspect Mask: 0xffff
|
Fully Understands Aspect Mask: 0xffff
|
||||||
|
|
@ -732,7 +927,7 @@ issue_183_colr = """Colour Specification Box (colr) @ (62, 12)
|
||||||
Method: restricted ICC profile
|
Method: restricted ICC profile
|
||||||
Precedence: 0
|
Precedence: 0
|
||||||
ICC Profile: None"""
|
ICC Profile: None"""
|
||||||
|
|
||||||
|
|
||||||
# Progression order is invalid.
|
# Progression order is invalid.
|
||||||
issue_186_progression_order = """COD marker segment @ (174, 12)
|
issue_186_progression_order = """COD marker segment @ (174, 12)
|
||||||
|
|
|
||||||
|
|
@ -1,12 +1,6 @@
|
||||||
"""
|
"""
|
||||||
Test suite for openjpeg's callback functions.
|
Test suite for openjpeg's callback functions.
|
||||||
"""
|
"""
|
||||||
# R0904: Seems like pylint is fooled in this situation
|
|
||||||
# pylint: disable=R0904
|
|
||||||
|
|
||||||
# 'mock' most certainly is in unittest (Python 3.3)
|
|
||||||
# pylint: disable=E0611,F0401
|
|
||||||
|
|
||||||
import os
|
import os
|
||||||
import re
|
import re
|
||||||
import sys
|
import sys
|
||||||
|
|
@ -25,8 +19,7 @@ import glymur
|
||||||
|
|
||||||
from .fixtures import WARNING_INFRASTRUCTURE_ISSUE, WARNING_INFRASTRUCTURE_MSG
|
from .fixtures import WARNING_INFRASTRUCTURE_ISSUE, WARNING_INFRASTRUCTURE_MSG
|
||||||
|
|
||||||
@unittest.skipIf(glymur.lib.openjp2.OPENJP2 is None,
|
|
||||||
"Missing openjp2 library.")
|
|
||||||
class TestCallbacks(unittest.TestCase):
|
class TestCallbacks(unittest.TestCase):
|
||||||
"""Test suite for callbacks."""
|
"""Test suite for callbacks."""
|
||||||
|
|
||||||
|
|
@ -37,68 +30,60 @@ class TestCallbacks(unittest.TestCase):
|
||||||
def tearDown(self):
|
def tearDown(self):
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
@unittest.skipIf(glymur.version.openjpeg_version[0] != '2',
|
||||||
|
"Missing openjp2 library.")
|
||||||
@unittest.skipIf(WARNING_INFRASTRUCTURE_ISSUE, WARNING_INFRASTRUCTURE_MSG)
|
@unittest.skipIf(WARNING_INFRASTRUCTURE_ISSUE, WARNING_INFRASTRUCTURE_MSG)
|
||||||
@unittest.skipIf(os.name == "nt", "Temporary file issue on window.")
|
@unittest.skipIf(os.name == "nt", "Temporary file issue on window.")
|
||||||
def test_info_callback_on_write(self):
|
def test_info_callback_on_write_backwards_compatibility(self):
|
||||||
"""Verify messages printed when writing an image in verbose mode."""
|
"""Verify messages printed when writing an image in verbose mode."""
|
||||||
j = glymur.Jp2k(self.jp2file)
|
j = glymur.Jp2k(self.jp2file)
|
||||||
with self.assertWarns(UserWarning):
|
with self.assertWarns(UserWarning):
|
||||||
tiledata = j.read(tile=0)
|
tiledata = j.read(tile=0)
|
||||||
with tempfile.NamedTemporaryFile(suffix='.jp2') as tfile:
|
with tempfile.NamedTemporaryFile(suffix='.jp2') as tfile:
|
||||||
j = glymur.Jp2k(tfile.name, 'wb')
|
|
||||||
with patch('sys.stdout', new=StringIO()) as fake_out:
|
with patch('sys.stdout', new=StringIO()) as fake_out:
|
||||||
j.write(tiledata, verbose=True)
|
glymur.Jp2k(tfile.name, data=tiledata, verbose=True)
|
||||||
|
actual = fake_out.getvalue().strip()
|
||||||
|
expected = '[INFO] tile number 1 / 1'
|
||||||
|
self.assertEqual(actual, expected)
|
||||||
|
|
||||||
|
@unittest.skipIf(glymur.version.openjpeg_version[0] != '2',
|
||||||
|
"Missing openjp2 library.")
|
||||||
|
@unittest.skipIf(os.name == "nt", "Temporary file issue on window.")
|
||||||
|
def test_info_callback_on_write(self):
|
||||||
|
"""Verify messages printed when writing an image in verbose mode."""
|
||||||
|
j = glymur.Jp2k(self.jp2file)
|
||||||
|
tiledata = j[:]
|
||||||
|
with tempfile.NamedTemporaryFile(suffix='.jp2') as tfile:
|
||||||
|
with patch('sys.stdout', new=StringIO()) as fake_out:
|
||||||
|
glymur.Jp2k(tfile.name, data=tiledata, verbose=True)
|
||||||
actual = fake_out.getvalue().strip()
|
actual = fake_out.getvalue().strip()
|
||||||
expected = '[INFO] tile number 1 / 1'
|
expected = '[INFO] tile number 1 / 1'
|
||||||
self.assertEqual(actual, expected)
|
self.assertEqual(actual, expected)
|
||||||
|
|
||||||
|
@unittest.skipIf(glymur.version.openjpeg_version[0] == '0',
|
||||||
|
"Missing openjpeg/openjp2 library.")
|
||||||
def test_info_callbacks_on_read(self):
|
def test_info_callbacks_on_read(self):
|
||||||
"""stdio output when info callback handler is enabled"""
|
"""stdio output when info callback handler is enabled"""
|
||||||
|
|
||||||
# Verify that we get the expected stdio output when our internal info
|
# Verify that we get the expected stdio output when our internal info
|
||||||
# callback handler is enabled.
|
# callback handler is enabled.
|
||||||
j = glymur.Jp2k(self.j2kfile)
|
jp2 = glymur.Jp2k(self.j2kfile)
|
||||||
with patch('sys.stdout', new=StringIO()) as fake_out:
|
with patch('sys.stdout', new=StringIO()) as fake_out:
|
||||||
j.read(rlevel=1, verbose=True, area=(0, 0, 200, 150))
|
jp2.verbose = True
|
||||||
|
jp2[::2, ::2]
|
||||||
actual = fake_out.getvalue().strip()
|
actual = fake_out.getvalue().strip()
|
||||||
|
|
||||||
lines = ['[INFO] Start to read j2k main header (0).',
|
if glymur.version.openjpeg_version[0] == '2':
|
||||||
'[INFO] Main header has been correctly decoded.',
|
lines = ['[INFO] Start to read j2k main header (0).',
|
||||||
'[INFO] Setting decoding area to 0,0,150,200',
|
'[INFO] Main header has been correctly decoded.',
|
||||||
'[INFO] Header of tile 0 / 0 has been read.',
|
'[INFO] Setting decoding area to 0,0,480,800',
|
||||||
'[INFO] Tile 1/1 has been decoded.',
|
'[INFO] Header of tile 0 / 0 has been read.',
|
||||||
'[INFO] Image data has been updated with tile 1.']
|
'[INFO] Tile 1/1 has been decoded.',
|
||||||
|
'[INFO] Image data has been updated with tile 1.']
|
||||||
expected = '\n'.join(lines)
|
|
||||||
self.assertEqual(actual, expected)
|
|
||||||
|
|
||||||
|
|
||||||
@unittest.skipIf(glymur.lib.openjpeg.OPENJPEG is None,
|
|
||||||
"Missing openjpeg library.")
|
|
||||||
class TestCallbacks15(unittest.TestCase):
|
|
||||||
"""This test suite is for OpenJPEG 1.5.1 properties.
|
|
||||||
"""
|
|
||||||
|
|
||||||
def setUp(self):
|
|
||||||
self.jp2file = glymur.data.nemo()
|
|
||||||
self.j2kfile = glymur.data.goodstuff()
|
|
||||||
|
|
||||||
def tearDown(self):
|
|
||||||
pass
|
|
||||||
|
|
||||||
def test_info_callbacks_on_read(self):
|
|
||||||
"""Verify stdout when reading.
|
|
||||||
|
|
||||||
Verify that we get the expected stdio output when our internal info
|
|
||||||
callback handler is enabled.
|
|
||||||
"""
|
|
||||||
with patch('glymur.lib.openjp2.OPENJP2', new=None):
|
|
||||||
# Force to use OPENJPEG instead of OPENJP2.
|
|
||||||
j = glymur.Jp2k(self.j2kfile)
|
|
||||||
with patch('sys.stdout', new=StringIO()) as fake_out:
|
|
||||||
j.read(rlevel=1, verbose=True)
|
|
||||||
actual = fake_out.getvalue().strip()
|
|
||||||
|
|
||||||
|
expected = '\n'.join(lines)
|
||||||
|
self.assertEqual(actual, expected)
|
||||||
|
else:
|
||||||
regex = re.compile(r"""\[INFO\]\stile\s1\sof\s1\s+
|
regex = re.compile(r"""\[INFO\]\stile\s1\sof\s1\s+
|
||||||
\[INFO\]\s-\stiers-1\stook\s
|
\[INFO\]\s-\stiers-1\stook\s
|
||||||
[0-9]+\.[0-9]+\ss\s+
|
[0-9]+\.[0-9]+\ss\s+
|
||||||
|
|
@ -108,13 +93,7 @@ class TestCallbacks15(unittest.TestCase):
|
||||||
[0-9]+\.[0-9]+\ss""",
|
[0-9]+\.[0-9]+\ss""",
|
||||||
re.VERBOSE)
|
re.VERBOSE)
|
||||||
|
|
||||||
# assertRegex in Python 3.3 (python2.7/pylint issue)
|
|
||||||
# pylint: disable=E1101
|
|
||||||
if sys.hexversion <= 0x03020000:
|
if sys.hexversion <= 0x03020000:
|
||||||
self.assertRegexpMatches(actual, regex)
|
self.assertRegexpMatches(actual, regex)
|
||||||
else:
|
else:
|
||||||
self.assertRegex(actual, regex)
|
self.assertRegex(actual, regex)
|
||||||
|
|
||||||
|
|
||||||
if __name__ == "__main__":
|
|
||||||
unittest.main()
|
|
||||||
|
|
|
||||||
|
|
@ -1,149 +0,0 @@
|
||||||
"""
|
|
||||||
Test suite for codestream parsing.
|
|
||||||
"""
|
|
||||||
|
|
||||||
# unittest doesn't work well with R0904.
|
|
||||||
# pylint: disable=R0904
|
|
||||||
|
|
||||||
import os
|
|
||||||
import struct
|
|
||||||
import sys
|
|
||||||
import tempfile
|
|
||||||
import unittest
|
|
||||||
|
|
||||||
from glymur import Jp2k
|
|
||||||
import glymur
|
|
||||||
|
|
||||||
from .fixtures import opj_data_file, OPJ_DATA_ROOT
|
|
||||||
|
|
||||||
class TestCodestream(unittest.TestCase):
|
|
||||||
"""Test suite for unusual codestream cases."""
|
|
||||||
|
|
||||||
def setUp(self):
|
|
||||||
self.jp2file = glymur.data.nemo()
|
|
||||||
|
|
||||||
def tearDown(self):
|
|
||||||
pass
|
|
||||||
|
|
||||||
def test_siz_segment_ssiz_unsigned(self):
|
|
||||||
"""ssiz attribute to be removed in future release"""
|
|
||||||
j = Jp2k(self.jp2file)
|
|
||||||
codestream = j.get_codestream()
|
|
||||||
|
|
||||||
# The ssiz attribute was simply a tuple of raw bytes.
|
|
||||||
# The first 7 bits are interpreted as the bitdepth, the MSB determines
|
|
||||||
# whether or not it is signed.
|
|
||||||
self.assertEqual(codestream.segment[1].ssiz, (7, 7, 7))
|
|
||||||
|
|
||||||
|
|
||||||
@unittest.skipIf(OPJ_DATA_ROOT is None,
|
|
||||||
"OPJ_DATA_ROOT environment variable not set")
|
|
||||||
class TestCodestreamOpjData(unittest.TestCase):
|
|
||||||
"""Test suite for unusual codestream cases. Uses OPJ_DATA_ROOT"""
|
|
||||||
|
|
||||||
def setUp(self):
|
|
||||||
self.jp2file = glymur.data.nemo()
|
|
||||||
|
|
||||||
def tearDown(self):
|
|
||||||
pass
|
|
||||||
|
|
||||||
@unittest.skipIf(os.name == "nt", "Temporary file issue on window.")
|
|
||||||
def test_reserved_marker_segment(self):
|
|
||||||
"""Reserved marker segments are ok."""
|
|
||||||
|
|
||||||
# Some marker segments were reserved in FCD15444-1. Since that
|
|
||||||
# standard is old, some of them may have come into use.
|
|
||||||
#
|
|
||||||
# Let's inject a reserved marker segment into a file that
|
|
||||||
# we know something about to make sure we can still parse it.
|
|
||||||
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, 0xff6f = 65391
|
|
||||||
read_buffer = struct.pack('>HHB', int(65391), 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()
|
|
||||||
|
|
||||||
codestream = Jp2k(tfile.name).get_codestream()
|
|
||||||
|
|
||||||
self.assertEqual(codestream.segment[2].marker_id, '0xff6f')
|
|
||||||
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,
|
|
||||||
'input/nonregression/123.j2c')
|
|
||||||
j = Jp2k(filename)
|
|
||||||
codestream = j.get_codestream(header_only=False)
|
|
||||||
|
|
||||||
# The codestream is valid, so we should be able to get the entire
|
|
||||||
# codestream, so the last one is EOC.
|
|
||||||
self.assertEqual(codestream.segment[-1].marker_id, 'EOC')
|
|
||||||
|
|
||||||
|
|
||||||
def test_siz_segment_ssiz_signed(self):
|
|
||||||
"""ssiz attribute to be removed in future release"""
|
|
||||||
filename = os.path.join(OPJ_DATA_ROOT, 'input/conformance/p0_03.j2k')
|
|
||||||
j = Jp2k(filename)
|
|
||||||
codestream = j.get_codestream()
|
|
||||||
|
|
||||||
# The ssiz attribute was simply a tuple of raw bytes.
|
|
||||||
# The first 7 bits are interpreted as the bitdepth, the MSB determines
|
|
||||||
# whether or not it is signed.
|
|
||||||
self.assertEqual(codestream.segment[1].ssiz, (131,))
|
|
||||||
|
|
||||||
|
|
||||||
class TestCodestreamRepr(unittest.TestCase):
|
|
||||||
|
|
||||||
def setUp(self):
|
|
||||||
self.jp2file = glymur.data.nemo()
|
|
||||||
|
|
||||||
def tearDown(self):
|
|
||||||
pass
|
|
||||||
|
|
||||||
def test_soc(self):
|
|
||||||
"""Test SOC segment repr"""
|
|
||||||
segment = glymur.codestream.SOCsegment()
|
|
||||||
newseg = eval(repr(segment))
|
|
||||||
self.assertEqual(newseg.marker_id, 'SOC')
|
|
||||||
|
|
||||||
def test_siz(self):
|
|
||||||
"""Test SIZ segment repr"""
|
|
||||||
kwargs = {'rsiz': 0,
|
|
||||||
'xysiz': (2592, 1456),
|
|
||||||
'xyosiz': (0, 0),
|
|
||||||
'xytsiz': (2592, 1456),
|
|
||||||
'xytosiz': (0, 0),
|
|
||||||
'Csiz': 3,
|
|
||||||
'bitdepth': (8, 8, 8),
|
|
||||||
'signed': (False, False, False),
|
|
||||||
'xyrsiz': ((1, 1, 1), (1, 1, 1))}
|
|
||||||
segment = glymur.codestream.SIZsegment(**kwargs)
|
|
||||||
newseg = eval(repr(segment))
|
|
||||||
self.assertEqual(newseg.marker_id, 'SIZ')
|
|
||||||
self.assertEqual(newseg.xsiz, 2592)
|
|
||||||
self.assertEqual(newseg.ysiz, 1456)
|
|
||||||
self.assertEqual(newseg.xosiz, 0)
|
|
||||||
self.assertEqual(newseg.yosiz, 0)
|
|
||||||
self.assertEqual(newseg.xtsiz, 2592)
|
|
||||||
self.assertEqual(newseg.ytsiz, 1456)
|
|
||||||
self.assertEqual(newseg.xtosiz, 0)
|
|
||||||
self.assertEqual(newseg.ytosiz, 0)
|
|
||||||
|
|
||||||
self.assertEqual(newseg.xrsiz, (1, 1, 1))
|
|
||||||
self.assertEqual(newseg.yrsiz, (1, 1, 1))
|
|
||||||
self.assertEqual(newseg.bitdepth, (8, 8, 8))
|
|
||||||
self.assertEqual(newseg.signed, (False, False, False))
|
|
||||||
|
|
||||||
|
|
||||||
if __name__ == "__main__":
|
|
||||||
unittest.main()
|
|
||||||
|
|
@ -1,16 +1,8 @@
|
||||||
"""These tests are for edge cases where OPENJPEG does not exist, but
|
"""These tests are for edge cases where OPENJPEG does not exist, but
|
||||||
OPENJP2 may be present in some form or other.
|
OPENJP2 may be present in some form or other.
|
||||||
"""
|
"""
|
||||||
# unittest doesn't work well with R0904.
|
import contextlib
|
||||||
# pylint: disable=R0904
|
import ctypes
|
||||||
|
|
||||||
# tempfile.TemporaryDirectory, unittest.assertWarns introduced in 3.2
|
|
||||||
# pylint: disable=E1101
|
|
||||||
|
|
||||||
# unittest.mock only in Python 3.3 (python2.7/pylint import issue)
|
|
||||||
# pylint: disable=E0611,F0401
|
|
||||||
|
|
||||||
|
|
||||||
import imp
|
import imp
|
||||||
import os
|
import os
|
||||||
import sys
|
import sys
|
||||||
|
|
@ -25,7 +17,43 @@ else:
|
||||||
import glymur
|
import glymur
|
||||||
from glymur import Jp2k
|
from glymur import Jp2k
|
||||||
|
|
||||||
from .fixtures import WARNING_INFRASTRUCTURE_ISSUE, WARNING_INFRASTRUCTURE_MSG
|
from .fixtures import (WARNING_INFRASTRUCTURE_ISSUE,
|
||||||
|
WARNING_INFRASTRUCTURE_MSG,
|
||||||
|
WINDOWS_TMP_FILE_MSG)
|
||||||
|
|
||||||
|
|
||||||
|
def openjpeg_not_found_by_ctypes():
|
||||||
|
"""
|
||||||
|
Need to know if openjpeg library can be picked right up by ctypes for one
|
||||||
|
of the tests.
|
||||||
|
"""
|
||||||
|
with patch.dict('os.environ',
|
||||||
|
{'DYLD_FALLBACK_LIBRARY_PATH': '/opt/local/lib'}):
|
||||||
|
if ctypes.util.find_library('openjpeg') is None:
|
||||||
|
return True
|
||||||
|
else:
|
||||||
|
return False
|
||||||
|
|
||||||
|
|
||||||
|
@contextlib.contextmanager
|
||||||
|
def chdir(dirname=None):
|
||||||
|
"""
|
||||||
|
This context manager restores the value of the current working directory
|
||||||
|
(cwd) after the enclosed code block completes or raises an exception. If a
|
||||||
|
directory name is supplied to the context manager then the cwd is changed
|
||||||
|
prior to running the code block.
|
||||||
|
|
||||||
|
Shamelessly lifted from
|
||||||
|
http://www.astropython.org/snippet/2009/10/chdir-context-manager
|
||||||
|
"""
|
||||||
|
curdir = os.getcwd()
|
||||||
|
try:
|
||||||
|
if dirname is not None:
|
||||||
|
os.chdir(dirname)
|
||||||
|
yield
|
||||||
|
finally:
|
||||||
|
os.chdir(curdir)
|
||||||
|
|
||||||
|
|
||||||
@unittest.skipIf(sys.hexversion < 0x03020000,
|
@unittest.skipIf(sys.hexversion < 0x03020000,
|
||||||
"TemporaryDirectory introduced in 3.2.")
|
"TemporaryDirectory introduced in 3.2.")
|
||||||
|
|
@ -61,7 +89,6 @@ class TestSuite(unittest.TestCase):
|
||||||
|
|
||||||
# Need to reliably recover the location of the openjp2 library,
|
# Need to reliably recover the location of the openjp2 library,
|
||||||
# so using '_name' appears to be the only way to do it.
|
# so using '_name' appears to be the only way to do it.
|
||||||
# pylint: disable=W0212
|
|
||||||
libloc = glymur.lib.openjp2.OPENJP2._name
|
libloc = glymur.lib.openjp2.OPENJP2._name
|
||||||
line = 'openjp2: {0}\n'.format(libloc)
|
line = 'openjp2: {0}\n'.format(libloc)
|
||||||
tfile.write(line)
|
tfile.write(line)
|
||||||
|
|
@ -71,7 +98,7 @@ class TestSuite(unittest.TestCase):
|
||||||
Jp2k(self.jp2file)
|
Jp2k(self.jp2file)
|
||||||
|
|
||||||
@unittest.skipIf(WARNING_INFRASTRUCTURE_ISSUE, WARNING_INFRASTRUCTURE_MSG)
|
@unittest.skipIf(WARNING_INFRASTRUCTURE_ISSUE, WARNING_INFRASTRUCTURE_MSG)
|
||||||
@unittest.skipIf(os.name == "nt", 'named temporary file issue on windows')
|
@unittest.skipIf(os.name == "nt", WINDOWS_TMP_FILE_MSG)
|
||||||
def test_xdg_env_config_file_is_bad(self):
|
def test_xdg_env_config_file_is_bad(self):
|
||||||
"""A non-existant library location should be rejected."""
|
"""A non-existant library location should be rejected."""
|
||||||
with tempfile.TemporaryDirectory() as tdir:
|
with tempfile.TemporaryDirectory() as tdir:
|
||||||
|
|
@ -90,50 +117,56 @@ class TestSuite(unittest.TestCase):
|
||||||
with self.assertWarnsRegex(UserWarning, regex):
|
with self.assertWarnsRegex(UserWarning, regex):
|
||||||
imp.reload(glymur.lib.openjp2)
|
imp.reload(glymur.lib.openjp2)
|
||||||
|
|
||||||
|
@unittest.skipIf(glymur.lib.openjp2.OPENJPEG is None,
|
||||||
|
"Needs openjp2 and openjpeg before this test make sense.")
|
||||||
|
@unittest.skipIf(os.name == "nt", WINDOWS_TMP_FILE_MSG)
|
||||||
|
def test_library_specified_as_None(self):
|
||||||
|
"""Verify that we can stop library from being loaded by using None."""
|
||||||
|
with tempfile.TemporaryDirectory() as tdir:
|
||||||
|
configdir = os.path.join(tdir, 'glymur')
|
||||||
|
os.mkdir(configdir)
|
||||||
|
fname = os.path.join(configdir, 'glymurrc')
|
||||||
|
with open(fname, 'w') as fptr:
|
||||||
|
# Essentially comment out openjp2 and preferentially load
|
||||||
|
# openjpeg instead.
|
||||||
|
fptr.write('[library]\n')
|
||||||
|
fptr.write('openjp2: None\n')
|
||||||
|
msg = 'openjpeg: {0}\n'
|
||||||
|
msg = msg.format(glymur.lib.openjp2.OPENJPEG._name)
|
||||||
|
fptr.write(msg)
|
||||||
|
fptr.flush()
|
||||||
|
with patch.dict('os.environ', {'XDG_CONFIG_HOME': tdir}):
|
||||||
|
imp.reload(glymur.lib.openjp2)
|
||||||
|
self.assertIsNone(glymur.lib.openjp2.OPENJP2)
|
||||||
|
self.assertIsNotNone(glymur.lib.openjp2.OPENJPEG)
|
||||||
|
|
||||||
@unittest.skipIf(glymur.lib.openjp2.OPENJP2 is None and
|
@unittest.skipIf(glymur.lib.openjp2.OPENJPEG is None,
|
||||||
glymur.lib.openjpeg.OPENJPEG is None,
|
"Needs openjpeg before this test make sense.")
|
||||||
"Missing openjp2 library.")
|
@unittest.skipIf(openjpeg_not_found_by_ctypes(),
|
||||||
class TestConfig(unittest.TestCase):
|
"OpenJPEG must be found before this test can work.")
|
||||||
"""Test suite for reading without proper library in place."""
|
@unittest.skipIf(os.name == "nt", WINDOWS_TMP_FILE_MSG)
|
||||||
|
def test_config_dir_but_no_config_file(self):
|
||||||
|
|
||||||
def setUp(self):
|
with tempfile.TemporaryDirectory() as tdir:
|
||||||
self.jp2file = glymur.data.nemo()
|
configdir = os.path.join(tdir, 'glymur')
|
||||||
self.j2kfile = glymur.data.goodstuff()
|
os.mkdir(configdir)
|
||||||
|
with patch.dict('os.environ', {'XDG_CONFIG_HOME': tdir}):
|
||||||
|
# Should still be able to load openjpeg, despite the
|
||||||
|
# configuration file not being there
|
||||||
|
imp.reload(glymur.lib.openjpeg)
|
||||||
|
self.assertIsNotNone(glymur.lib.openjp2.OPENJPEG)
|
||||||
|
|
||||||
def tearDown(self):
|
@unittest.skipIf(os.name == "nt", WINDOWS_TMP_FILE_MSG)
|
||||||
pass
|
def test_config_file_in_current_directory(self):
|
||||||
|
"""A configuration file in the current directory should be honored."""
|
||||||
def test_read_without_library(self):
|
libloc = glymur.lib.openjp2.OPENJP2._name
|
||||||
"""Don't have either openjp2 or openjpeg libraries? Must error out.
|
with tempfile.TemporaryDirectory() as tdir1:
|
||||||
"""
|
fname = os.path.join(tdir1, 'glymurrc')
|
||||||
with patch('glymur.lib.openjp2.OPENJP2', new=None):
|
with open(fname, 'w') as fptr:
|
||||||
with patch('glymur.lib.openjpeg.OPENJPEG', new=None):
|
fptr.write('[library]\n')
|
||||||
with self.assertRaises(glymur.jp2k.LibraryNotFoundError):
|
fptr.write('openjp2: {0}\n'.format(libloc))
|
||||||
glymur.Jp2k(self.jp2file).read()
|
fptr.flush()
|
||||||
|
with chdir(tdir1):
|
||||||
def test_read_bands_without_library(self):
|
# Should be able to load openjp2 as before.
|
||||||
"""Don't have openjp2 library? Must error out.
|
imp.reload(glymur.lib.openjp2)
|
||||||
"""
|
self.assertEqual(glymur.lib.openjp2.OPENJP2._name, libloc)
|
||||||
with patch('glymur.lib.openjp2.OPENJP2', new=None):
|
|
||||||
with patch('glymur.lib.openjpeg.OPENJPEG', new=None):
|
|
||||||
with patch('glymur.version.openjpeg_version_tuple',
|
|
||||||
new=(0, 0, 0)):
|
|
||||||
with self.assertRaises(glymur.jp2k.LibraryNotFoundError):
|
|
||||||
glymur.Jp2k(self.jp2file).read_bands()
|
|
||||||
|
|
||||||
@unittest.skipIf(os.name == "nt", "NamedTemporaryFile issue on windows")
|
|
||||||
def test_write_without_library(self):
|
|
||||||
"""Don't have openjpeg libraries? Must error out.
|
|
||||||
"""
|
|
||||||
data = glymur.Jp2k(self.j2kfile).read()
|
|
||||||
with patch('glymur.lib.openjp2.OPENJP2', new=None):
|
|
||||||
with patch('glymur.lib.openjpeg.OPENJPEG', new=None):
|
|
||||||
with self.assertRaises(glymur.jp2k.LibraryNotFoundError):
|
|
||||||
with tempfile.NamedTemporaryFile(suffix='.jp2') as tfile:
|
|
||||||
ofile = Jp2k(tfile.name, 'wb')
|
|
||||||
ofile.write(data)
|
|
||||||
|
|
||||||
|
|
||||||
if __name__ == "__main__":
|
|
||||||
unittest.main()
|
|
||||||
|
|
|
||||||
|
|
@ -1,34 +1,32 @@
|
||||||
"""
|
"""
|
||||||
Test suite for warnings issued by glymur.
|
Test suite for warnings issued by glymur.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
# unittest doesn't work well with R0904.
|
|
||||||
# pylint: disable=R0904
|
|
||||||
|
|
||||||
import platform
|
|
||||||
import os
|
import os
|
||||||
import re
|
import re
|
||||||
import struct
|
import struct
|
||||||
import sys
|
|
||||||
import tempfile
|
import tempfile
|
||||||
import unittest
|
import unittest
|
||||||
|
|
||||||
import six
|
|
||||||
|
|
||||||
from glymur import Jp2k
|
from glymur import Jp2k
|
||||||
import glymur
|
import glymur
|
||||||
|
|
||||||
from .fixtures import opj_data_file, OPJ_DATA_ROOT
|
from .fixtures import opj_data_file, OPJ_DATA_ROOT
|
||||||
from .fixtures import WARNING_INFRASTRUCTURE_ISSUE, WARNING_INFRASTRUCTURE_MSG
|
from .fixtures import WARNING_INFRASTRUCTURE_ISSUE, WARNING_INFRASTRUCTURE_MSG
|
||||||
|
|
||||||
@unittest.skipIf(sys.hexversion < 0x03040000 and platform.system() == 'Linux',
|
|
||||||
"inexplicable failures on 3.3 and linux")
|
|
||||||
@unittest.skipIf(OPJ_DATA_ROOT is None,
|
@unittest.skipIf(OPJ_DATA_ROOT is None,
|
||||||
"OPJ_DATA_ROOT environment variable not set")
|
"OPJ_DATA_ROOT environment variable not set")
|
||||||
@unittest.skipIf(WARNING_INFRASTRUCTURE_ISSUE, WARNING_INFRASTRUCTURE_MSG)
|
@unittest.skipIf(WARNING_INFRASTRUCTURE_ISSUE, WARNING_INFRASTRUCTURE_MSG)
|
||||||
class TestWarnings(unittest.TestCase):
|
class TestWarnings(unittest.TestCase):
|
||||||
"""Test suite for warnings issued by glymur."""
|
"""Test suite for warnings issued by glymur."""
|
||||||
|
|
||||||
|
def test_invalid_compatibility_list_entry(self):
|
||||||
|
"""should not error out with invalid compatibility list entry"""
|
||||||
|
filename = opj_data_file('input/nonregression/issue397.jp2')
|
||||||
|
with self.assertWarns(UserWarning):
|
||||||
|
Jp2k(filename)
|
||||||
|
self.assertTrue(True)
|
||||||
|
|
||||||
def test_exceeded_box_length(self):
|
def test_exceeded_box_length(self):
|
||||||
"""
|
"""
|
||||||
should warn if reading past end of a box
|
should warn if reading past end of a box
|
||||||
|
|
@ -55,12 +53,11 @@ class TestWarnings(unittest.TestCase):
|
||||||
"""
|
"""
|
||||||
relpath = 'input/nonregression/issue188_beach_64bitsbox.jp2'
|
relpath = 'input/nonregression/issue188_beach_64bitsbox.jp2'
|
||||||
jfile = opj_data_file(relpath)
|
jfile = opj_data_file(relpath)
|
||||||
regex = re.compile(r"""Unrecognized\sbox\s\(b'XML\s'\)\sencountered.""",
|
pattern = r"""Unrecognized\sbox\s\(b'XML\s'\)\sencountered."""
|
||||||
re.VERBOSE)
|
regex = re.compile(pattern, re.VERBOSE)
|
||||||
with self.assertWarnsRegex(UserWarning, regex):
|
with self.assertWarnsRegex(UserWarning, regex):
|
||||||
Jp2k(jfile)
|
Jp2k(jfile)
|
||||||
|
|
||||||
|
|
||||||
def test_NR_gdal_fuzzer_unchecked_numresolutions_dump(self):
|
def test_NR_gdal_fuzzer_unchecked_numresolutions_dump(self):
|
||||||
"""
|
"""
|
||||||
Has an invalid number of resolutions.
|
Has an invalid number of resolutions.
|
||||||
|
|
@ -72,7 +69,7 @@ class TestWarnings(unittest.TestCase):
|
||||||
\(\d+\)\.""",
|
\(\d+\)\.""",
|
||||||
re.VERBOSE)
|
re.VERBOSE)
|
||||||
with self.assertWarnsRegex(UserWarning, regex):
|
with self.assertWarnsRegex(UserWarning, regex):
|
||||||
Jp2k(jfile)
|
Jp2k(jfile).get_codestream()
|
||||||
|
|
||||||
@unittest.skipIf(re.match("1.5|2.0.0", glymur.version.openjpeg_version),
|
@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")
|
"Test not passing on 1.5.x, not introduced until 2.x")
|
||||||
|
|
@ -87,7 +84,7 @@ class TestWarnings(unittest.TestCase):
|
||||||
\(\d+\)\.""",
|
\(\d+\)\.""",
|
||||||
re.VERBOSE)
|
re.VERBOSE)
|
||||||
with self.assertWarnsRegex(UserWarning, regex):
|
with self.assertWarnsRegex(UserWarning, regex):
|
||||||
Jp2k(jfile)
|
Jp2k(jfile).get_codestream()
|
||||||
|
|
||||||
def test_NR_gdal_fuzzer_check_comp_dx_dy_jp2_dump(self):
|
def test_NR_gdal_fuzzer_check_comp_dx_dy_jp2_dump(self):
|
||||||
"""
|
"""
|
||||||
|
|
@ -100,7 +97,7 @@ class TestWarnings(unittest.TestCase):
|
||||||
dx=\d+,\s*dy=\d+""",
|
dx=\d+,\s*dy=\d+""",
|
||||||
re.VERBOSE)
|
re.VERBOSE)
|
||||||
with self.assertWarnsRegex(UserWarning, regex):
|
with self.assertWarnsRegex(UserWarning, regex):
|
||||||
Jp2k(jfile)
|
Jp2k(jfile).get_codestream()
|
||||||
|
|
||||||
def test_NR_gdal_fuzzer_assert_in_opj_j2k_read_SQcd_SQcc_patch_jp2(self):
|
def test_NR_gdal_fuzzer_assert_in_opj_j2k_read_SQcd_SQcc_patch_jp2(self):
|
||||||
lst = ['input', 'nonregression',
|
lst = ['input', 'nonregression',
|
||||||
|
|
@ -110,53 +107,32 @@ class TestWarnings(unittest.TestCase):
|
||||||
number\sof\scomponents\sis\sonly\s\d+""",
|
number\sof\scomponents\sis\sonly\s\d+""",
|
||||||
re.VERBOSE)
|
re.VERBOSE)
|
||||||
with self.assertWarnsRegex(UserWarning, regex):
|
with self.assertWarnsRegex(UserWarning, regex):
|
||||||
Jp2k(jfile)
|
Jp2k(jfile).get_codestream()
|
||||||
|
|
||||||
def test_NR_broken_jp2_dump(self):
|
|
||||||
"""
|
|
||||||
The colr box has a ridiculously incorrect box length.
|
|
||||||
"""
|
|
||||||
jfile = opj_data_file('input/nonregression/broken.jp2')
|
|
||||||
regex = re.compile(r'''b'colr'\sbox\shas\sincorrect\sbox\slength\s
|
|
||||||
\(\d+\)''',
|
|
||||||
re.VERBOSE)
|
|
||||||
with self.assertWarnsRegex(UserWarning, regex):
|
|
||||||
jp2 = Jp2k(jfile)
|
|
||||||
|
|
||||||
def test_NR_broken2_jp2_dump(self):
|
|
||||||
"""
|
|
||||||
Invalid marker ID on codestream.
|
|
||||||
"""
|
|
||||||
jfile = opj_data_file('input/nonregression/broken2.jp2')
|
|
||||||
regex = re.compile(r'''Invalid\smarker\sid\sencountered\sat\sbyte\s
|
|
||||||
\d+\sin\scodestream:\s*"0x[a-fA-F0-9]{4}"''',
|
|
||||||
re.VERBOSE)
|
|
||||||
with self.assertWarnsRegex(UserWarning, regex):
|
|
||||||
Jp2k(jfile)
|
|
||||||
|
|
||||||
def test_bad_rsiz(self):
|
def test_bad_rsiz(self):
|
||||||
"""Should warn if RSIZ is bad. Issue196"""
|
"""Should warn if RSIZ is bad. Issue196"""
|
||||||
filename = opj_data_file('input/nonregression/edf_c2_1002767.jp2')
|
filename = opj_data_file('input/nonregression/edf_c2_1002767.jp2')
|
||||||
with self.assertWarnsRegex(UserWarning, 'Invalid profile'):
|
with self.assertWarnsRegex(UserWarning, 'Invalid profile'):
|
||||||
Jp2k(filename)
|
Jp2k(filename).get_codestream()
|
||||||
|
|
||||||
def test_bad_wavelet_transform(self):
|
def test_bad_wavelet_transform(self):
|
||||||
"""Should warn if wavelet transform is bad. Issue195"""
|
"""Should warn if wavelet transform is bad. Issue195"""
|
||||||
filename = opj_data_file('input/nonregression/edf_c2_10025.jp2')
|
filename = opj_data_file('input/nonregression/edf_c2_10025.jp2')
|
||||||
with self.assertWarnsRegex(UserWarning, 'Invalid wavelet transform'):
|
with self.assertWarnsRegex(UserWarning, 'Invalid wavelet transform'):
|
||||||
Jp2k(filename)
|
Jp2k(filename).get_codestream()
|
||||||
|
|
||||||
def test_invalid_progression_order(self):
|
def test_invalid_progression_order(self):
|
||||||
"""Should still be able to parse even if prog order is invalid."""
|
"""Should still be able to parse even if prog order is invalid."""
|
||||||
jfile = opj_data_file('input/nonregression/2977.pdf.asan.67.2198.jp2')
|
jfile = opj_data_file('input/nonregression/2977.pdf.asan.67.2198.jp2')
|
||||||
with self.assertWarnsRegex(UserWarning, 'Invalid progression order'):
|
with self.assertWarnsRegex(UserWarning, 'Invalid progression order'):
|
||||||
Jp2k(jfile)
|
Jp2k(jfile).get_codestream()
|
||||||
|
|
||||||
def test_tile_height_is_zero(self):
|
def test_tile_height_is_zero(self):
|
||||||
"""Zero tile height should not cause an exception."""
|
"""Zero tile height should not cause an exception."""
|
||||||
filename = opj_data_file('input/nonregression/2539.pdf.SIGFPE.706.1712.jp2')
|
filename = 'input/nonregression/2539.pdf.SIGFPE.706.1712.jp2'
|
||||||
|
filename = opj_data_file(filename)
|
||||||
with self.assertWarnsRegex(UserWarning, 'Invalid tile dimensions'):
|
with self.assertWarnsRegex(UserWarning, 'Invalid tile dimensions'):
|
||||||
Jp2k(filename)
|
Jp2k(filename).get_codestream()
|
||||||
|
|
||||||
@unittest.skipIf(os.name == "nt", "Temporary file issue on window.")
|
@unittest.skipIf(os.name == "nt", "Temporary file issue on window.")
|
||||||
def test_unknown_marker_segment(self):
|
def test_unknown_marker_segment(self):
|
||||||
|
|
@ -179,9 +155,9 @@ class TestWarnings(unittest.TestCase):
|
||||||
read_buffer = ifile.read()
|
read_buffer = ifile.read()
|
||||||
tfile.write(read_buffer)
|
tfile.write(read_buffer)
|
||||||
tfile.flush()
|
tfile.flush()
|
||||||
|
|
||||||
with self.assertWarnsRegex(UserWarning, 'Unrecognized marker'):
|
with self.assertWarnsRegex(UserWarning, 'Unrecognized marker'):
|
||||||
codestream = Jp2k(tfile.name).get_codestream()
|
Jp2k(tfile.name).get_codestream()
|
||||||
|
|
||||||
|
|
||||||
if __name__ == "__main__":
|
if __name__ == "__main__":
|
||||||
|
|
|
||||||
|
|
@ -1,13 +1,7 @@
|
||||||
"""
|
"""
|
||||||
ICC profile tests.
|
ICC profile tests.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
# unittest doesn't work well with R0904.
|
|
||||||
# pylint: disable=R0904
|
|
||||||
|
|
||||||
import datetime
|
import datetime
|
||||||
import os
|
|
||||||
import sys
|
|
||||||
import unittest
|
import unittest
|
||||||
|
|
||||||
import numpy as np
|
import numpy as np
|
||||||
|
|
@ -66,11 +60,6 @@ class TestICC(unittest.TestCase):
|
||||||
"""invalid ICC header data should cause UserWarning"""
|
"""invalid ICC header data should cause UserWarning"""
|
||||||
jfile = opj_data_file('input/nonregression/orb-blue10-lin-jp2.jp2')
|
jfile = opj_data_file('input/nonregression/orb-blue10-lin-jp2.jp2')
|
||||||
|
|
||||||
# assertWarns in Python 3.3 (python2.7/pylint issue)
|
|
||||||
# pylint: disable=E1101
|
|
||||||
regex = 'ICC profile header is corrupt'
|
regex = 'ICC profile header is corrupt'
|
||||||
with self.assertWarnsRegex(UserWarning, regex):
|
with self.assertWarnsRegex(UserWarning, regex):
|
||||||
Jp2k(jfile)
|
Jp2k(jfile)
|
||||||
|
|
||||||
if __name__ == "__main__":
|
|
||||||
unittest.main()
|
|
||||||
|
|
|
||||||
|
|
@ -1,18 +1,6 @@
|
||||||
"""
|
"""
|
||||||
Test suite specifically targeting JP2 box layout.
|
Test suite specifically targeting JP2 box layout.
|
||||||
"""
|
"""
|
||||||
# E1103: return value from read may be list or np array
|
|
||||||
# pylint: disable=E1103
|
|
||||||
|
|
||||||
# R0902: More than 7 instance attributes are just fine for testing.
|
|
||||||
# pylint: disable=R0902
|
|
||||||
|
|
||||||
# R0904: Seems like pylint is fooled in this situation
|
|
||||||
# pylint: disable=R0904
|
|
||||||
|
|
||||||
# W0613: load_tests doesn't need to use ignore or loader arguments.
|
|
||||||
# pylint: disable=W0613
|
|
||||||
|
|
||||||
import doctest
|
import doctest
|
||||||
import os
|
import os
|
||||||
import re
|
import re
|
||||||
|
|
@ -20,7 +8,6 @@ import shutil
|
||||||
import struct
|
import struct
|
||||||
import sys
|
import sys
|
||||||
import tempfile
|
import tempfile
|
||||||
import uuid
|
|
||||||
from uuid import UUID
|
from uuid import UUID
|
||||||
import unittest
|
import unittest
|
||||||
|
|
||||||
|
|
@ -35,15 +22,13 @@ from glymur.jp2box import JPEG2000SignatureBox
|
||||||
from glymur.core import COLOR, OPACITY
|
from glymur.core import COLOR, OPACITY
|
||||||
from glymur.core import RED, GREEN, BLUE, GREY, WHOLE_IMAGE
|
from glymur.core import RED, GREEN, BLUE, GREY, WHOLE_IMAGE
|
||||||
|
|
||||||
from .fixtures import (
|
from .fixtures import (WARNING_INFRASTRUCTURE_ISSUE,
|
||||||
WARNING_INFRASTRUCTURE_ISSUE, WARNING_INFRASTRUCTURE_MSG,
|
WARNING_INFRASTRUCTURE_MSG,
|
||||||
MetadataBase
|
WINDOWS_TMP_FILE_MSG, MetadataBase)
|
||||||
)
|
|
||||||
|
|
||||||
try:
|
|
||||||
FORMAT_CORPUS_DATA_ROOT = os.environ['FORMAT_CORPUS_DATA_ROOT']
|
def docTearDown(doctest_obj):
|
||||||
except KeyError:
|
glymur.set_parseoptions(full_codestream=False)
|
||||||
FORMAT_CORPUS_DATA_ROOT = None
|
|
||||||
|
|
||||||
|
|
||||||
def load_tests(loader, tests, ignore):
|
def load_tests(loader, tests, ignore):
|
||||||
|
|
@ -51,31 +36,35 @@ def load_tests(loader, tests, ignore):
|
||||||
if os.name == "nt":
|
if os.name == "nt":
|
||||||
# Can't do it on windows, temporary file issue.
|
# Can't do it on windows, temporary file issue.
|
||||||
return tests
|
return tests
|
||||||
tests.addTests(doctest.DocTestSuite('glymur.jp2box'))
|
tests.addTests(doctest.DocTestSuite('glymur.jp2box',
|
||||||
|
tearDown=docTearDown))
|
||||||
return tests
|
return tests
|
||||||
|
|
||||||
@unittest.skipIf(os.name == "nt", "Temporary file issue on window.")
|
|
||||||
|
@unittest.skipIf(os.name == "nt", WINDOWS_TMP_FILE_MSG)
|
||||||
class TestDataEntryURL(unittest.TestCase):
|
class TestDataEntryURL(unittest.TestCase):
|
||||||
"""Test suite for DataEntryURL boxes."""
|
"""Test suite for DataEntryURL boxes."""
|
||||||
def setUp(self):
|
def setUp(self):
|
||||||
self.jp2file = glymur.data.nemo()
|
self.jp2file = glymur.data.nemo()
|
||||||
|
|
||||||
|
@unittest.skipIf(re.match("1.5|2",
|
||||||
|
glymur.version.openjpeg_version) is None,
|
||||||
|
"Must have openjpeg 1.5 or higher to run")
|
||||||
def test_wrap_greyscale(self):
|
def test_wrap_greyscale(self):
|
||||||
"""A single component should be wrapped as GREYSCALE."""
|
"""A single component should be wrapped as GREYSCALE."""
|
||||||
j = Jp2k(self.jp2file)
|
j = Jp2k(self.jp2file)
|
||||||
data = j.read()
|
data = j[:]
|
||||||
red = data[:, :, 0]
|
red = data[:, :, 0]
|
||||||
|
|
||||||
# Write it back out as a raw codestream.
|
# Write it back out as a raw codestream.
|
||||||
with tempfile.NamedTemporaryFile(suffix=".j2k") as tfile1:
|
with tempfile.NamedTemporaryFile(suffix=".j2k") as tfile1:
|
||||||
j2k = glymur.Jp2k(tfile1.name, 'wb')
|
j2k = glymur.Jp2k(tfile1.name, data=red)
|
||||||
j2k.write(data[:, :, 0])
|
|
||||||
|
|
||||||
# Ok, now rewrap it as JP2. The colorspace should be GREYSCALE.
|
# Ok, now rewrap it as JP2. The colorspace should be GREYSCALE.
|
||||||
with tempfile.NamedTemporaryFile(suffix=".jp2") as tfile2:
|
with tempfile.NamedTemporaryFile(suffix=".jp2") as tfile2:
|
||||||
jp2 = j2k.wrap(tfile2.name)
|
jp2 = j2k.wrap(tfile2.name)
|
||||||
self.assertEqual(jp2.box[2].box[1].colorspace,
|
self.assertEqual(jp2.box[2].box[1].colorspace,
|
||||||
glymur.core.GREYSCALE)
|
glymur.core.GREYSCALE)
|
||||||
|
|
||||||
def test_basic_url(self):
|
def test_basic_url(self):
|
||||||
"""Just your most basic URL box."""
|
"""Just your most basic URL box."""
|
||||||
|
|
@ -97,7 +86,7 @@ class TestDataEntryURL(unittest.TestCase):
|
||||||
self.assertEqual(jp22.box[4].url, url)
|
self.assertEqual(jp22.box[4].url, url)
|
||||||
|
|
||||||
def test_null_termination(self):
|
def test_null_termination(self):
|
||||||
"""I.9.3.2 specifies that the location field must be null terminated."""
|
"""I.9.3.2 specifies that location field must be null terminated."""
|
||||||
jp2 = Jp2k(self.jp2file)
|
jp2 = Jp2k(self.jp2file)
|
||||||
|
|
||||||
url = 'http://glymur.readthedocs.org'
|
url = 'http://glymur.readthedocs.org'
|
||||||
|
|
@ -108,21 +97,24 @@ class TestDataEntryURL(unittest.TestCase):
|
||||||
jp22 = jp2.wrap(tfile.name, boxes=boxes)
|
jp22 = jp2.wrap(tfile.name, boxes=boxes)
|
||||||
|
|
||||||
self.assertEqual(jp22.box[-1].length, 42)
|
self.assertEqual(jp22.box[-1].length, 42)
|
||||||
|
|
||||||
# Go to the last box. Seek past the L, T, version, and flag fields.
|
# Go to the last box. Seek past the L, T, version,
|
||||||
|
# and flag fields.
|
||||||
with open(tfile.name, 'rb') as fptr:
|
with open(tfile.name, 'rb') as fptr:
|
||||||
fptr.seek(jp22.box[-1].offset + 4 + 4 + 1 + 3)
|
fptr.seek(jp22.box[-1].offset + 4 + 4 + 1 + 3)
|
||||||
|
|
||||||
nbytes = jp22.box[-1].offset + jp22.box[-1].length - fptr.tell()
|
nbytes = (jp22.box[-1].offset +
|
||||||
|
jp22.box[-1].length -
|
||||||
|
fptr.tell())
|
||||||
read_buffer = fptr.read(nbytes)
|
read_buffer = fptr.read(nbytes)
|
||||||
read_url = read_buffer.decode('utf-8')
|
read_url = read_buffer.decode('utf-8')
|
||||||
self.assertEqual(url + chr(0), read_url)
|
self.assertEqual(url + chr(0), read_url)
|
||||||
|
|
||||||
|
|
||||||
@unittest.skipIf(re.match(r'''(1|2.0.0)''',
|
@unittest.skipIf(re.match(r'''0|1|2.0.0''',
|
||||||
glymur.version.openjpeg_version) is not None,
|
glymur.version.openjpeg_version) is not None,
|
||||||
"Not supported until 2.1")
|
"Not supported until 2.1")
|
||||||
@unittest.skipIf(os.name == "nt", "Temporary file issue on window.")
|
@unittest.skipIf(os.name == "nt", WINDOWS_TMP_FILE_MSG)
|
||||||
class TestChannelDefinition(unittest.TestCase):
|
class TestChannelDefinition(unittest.TestCase):
|
||||||
"""Test suite for channel definition boxes."""
|
"""Test suite for channel definition boxes."""
|
||||||
|
|
||||||
|
|
@ -130,24 +122,21 @@ class TestChannelDefinition(unittest.TestCase):
|
||||||
def setUpClass(cls):
|
def setUpClass(cls):
|
||||||
"""Need a one_plane plane image for greyscale testing."""
|
"""Need a one_plane plane image for greyscale testing."""
|
||||||
j2k = Jp2k(glymur.data.goodstuff())
|
j2k = Jp2k(glymur.data.goodstuff())
|
||||||
data = j2k.read()
|
data = j2k[:]
|
||||||
# Write the first component back out to file.
|
# Write the first component back out to file.
|
||||||
with tempfile.NamedTemporaryFile(suffix=".j2k", delete=False) as tfile:
|
with tempfile.NamedTemporaryFile(suffix=".j2k", delete=False) as tfile:
|
||||||
grey_j2k = Jp2k(tfile.name, 'wb')
|
Jp2k(tfile.name, data=data[:, :, 0])
|
||||||
grey_j2k.write(data[:, :, 0])
|
|
||||||
cls.one_plane = tfile.name
|
cls.one_plane = tfile.name
|
||||||
# Write the first two components back out to file.
|
# Write the first two components back out to file.
|
||||||
with tempfile.NamedTemporaryFile(suffix=".j2k", delete=False) as tfile:
|
with tempfile.NamedTemporaryFile(suffix=".j2k", delete=False) as tfile:
|
||||||
grey_j2k = Jp2k(tfile.name, 'wb')
|
Jp2k(tfile.name, data=data[:, :, 0:1])
|
||||||
grey_j2k.write(data[:, :, 0:1])
|
|
||||||
cls.two_planes = tfile.name
|
cls.two_planes = tfile.name
|
||||||
# Write four components back out to file.
|
# Write four components back out to file.
|
||||||
with tempfile.NamedTemporaryFile(suffix=".j2k", delete=False) as tfile:
|
with tempfile.NamedTemporaryFile(suffix=".j2k", delete=False) as tfile:
|
||||||
rgba_jp2 = Jp2k(tfile.name, 'wb')
|
|
||||||
shape = (data.shape[0], data.shape[1], 1)
|
shape = (data.shape[0], data.shape[1], 1)
|
||||||
alpha = np.zeros((shape), dtype=data.dtype)
|
alpha = np.zeros((shape), dtype=data.dtype)
|
||||||
data4 = np.concatenate((data, alpha), axis=2)
|
data4 = np.concatenate((data, alpha), axis=2)
|
||||||
rgba_jp2.write(data4)
|
Jp2k(tfile.name, data=data4)
|
||||||
cls.four_planes = tfile.name
|
cls.four_planes = tfile.name
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
|
|
@ -400,7 +389,7 @@ class TestFileTypeBox(unittest.TestCase):
|
||||||
ftyp = glymur.jp2box.FileTypeBox(brand='jp3')
|
ftyp = glymur.jp2box.FileTypeBox(brand='jp3')
|
||||||
with self.assertRaises(IOError):
|
with self.assertRaises(IOError):
|
||||||
with tempfile.TemporaryFile() as tfile:
|
with tempfile.TemporaryFile() as tfile:
|
||||||
ftyp.write(tfile)
|
ftyp.write(tfile)
|
||||||
|
|
||||||
@unittest.skipIf(WARNING_INFRASTRUCTURE_ISSUE, WARNING_INFRASTRUCTURE_MSG)
|
@unittest.skipIf(WARNING_INFRASTRUCTURE_ISSUE, WARNING_INFRASTRUCTURE_MSG)
|
||||||
def test_cl_entry_unknown(self):
|
def test_cl_entry_unknown(self):
|
||||||
|
|
@ -410,7 +399,8 @@ class TestFileTypeBox(unittest.TestCase):
|
||||||
ftyp = glymur.jp2box.FileTypeBox(compatibility_list=['jp3'])
|
ftyp = glymur.jp2box.FileTypeBox(compatibility_list=['jp3'])
|
||||||
with self.assertRaises(IOError):
|
with self.assertRaises(IOError):
|
||||||
with tempfile.TemporaryFile() as tfile:
|
with tempfile.TemporaryFile() as tfile:
|
||||||
ftyp.write(tfile)
|
ftyp.write(tfile)
|
||||||
|
|
||||||
|
|
||||||
class TestColourSpecificationBox(unittest.TestCase):
|
class TestColourSpecificationBox(unittest.TestCase):
|
||||||
"""Test suite for colr box instantiation."""
|
"""Test suite for colr box instantiation."""
|
||||||
|
|
@ -434,8 +424,7 @@ class TestColourSpecificationBox(unittest.TestCase):
|
||||||
def tearDown(self):
|
def tearDown(self):
|
||||||
pass
|
pass
|
||||||
|
|
||||||
@unittest.skipIf(os.name == "nt",
|
@unittest.skipIf(os.name == "nt", WINDOWS_TMP_FILE_MSG)
|
||||||
"Problems using NamedTemporaryFile on windows.")
|
|
||||||
def test_colr_with_out_enum_cspace(self):
|
def test_colr_with_out_enum_cspace(self):
|
||||||
"""must supply an enumerated colorspace when writing"""
|
"""must supply an enumerated colorspace when writing"""
|
||||||
j2k = Jp2k(self.j2kfile)
|
j2k = Jp2k(self.j2kfile)
|
||||||
|
|
@ -446,7 +435,7 @@ class TestColourSpecificationBox(unittest.TestCase):
|
||||||
with self.assertRaises(IOError):
|
with self.assertRaises(IOError):
|
||||||
j2k.wrap(tfile.name, boxes=boxes)
|
j2k.wrap(tfile.name, boxes=boxes)
|
||||||
|
|
||||||
@unittest.skipIf(os.name == "nt", "Temporary file issue on window.")
|
@unittest.skipIf(os.name == "nt", WINDOWS_TMP_FILE_MSG)
|
||||||
def test_missing_colr_box(self):
|
def test_missing_colr_box(self):
|
||||||
"""jp2h must have a colr box"""
|
"""jp2h must have a colr box"""
|
||||||
j2k = Jp2k(self.j2kfile)
|
j2k = Jp2k(self.j2kfile)
|
||||||
|
|
@ -456,7 +445,7 @@ class TestColourSpecificationBox(unittest.TestCase):
|
||||||
with self.assertRaises(IOError):
|
with self.assertRaises(IOError):
|
||||||
j2k.wrap(tfile.name, boxes=boxes)
|
j2k.wrap(tfile.name, boxes=boxes)
|
||||||
|
|
||||||
@unittest.skipIf(os.name == "nt", "Temporary file issue on window.")
|
@unittest.skipIf(os.name == "nt", WINDOWS_TMP_FILE_MSG)
|
||||||
def test_bad_approx_jp2_field(self):
|
def test_bad_approx_jp2_field(self):
|
||||||
"""JP2 has requirements for approx field"""
|
"""JP2 has requirements for approx field"""
|
||||||
j2k = Jp2k(self.j2kfile)
|
j2k = Jp2k(self.j2kfile)
|
||||||
|
|
@ -517,8 +506,7 @@ class TestColourSpecificationBox(unittest.TestCase):
|
||||||
colr.write(tfile)
|
colr.write(tfile)
|
||||||
|
|
||||||
|
|
||||||
@unittest.skipIf(os.name == "nt",
|
@unittest.skipIf(os.name == "nt", WINDOWS_TMP_FILE_MSG)
|
||||||
"Problems using NamedTemporaryFile on windows.")
|
|
||||||
class TestPaletteBox(unittest.TestCase):
|
class TestPaletteBox(unittest.TestCase):
|
||||||
"""Test suite for pclr box instantiation."""
|
"""Test suite for pclr box instantiation."""
|
||||||
|
|
||||||
|
|
@ -535,8 +523,8 @@ class TestPaletteBox(unittest.TestCase):
|
||||||
bps = (8, 8, 8)
|
bps = (8, 8, 8)
|
||||||
signed = (False, False)
|
signed = (False, False)
|
||||||
with self.assertWarns(UserWarning):
|
with self.assertWarns(UserWarning):
|
||||||
pclr = glymur.jp2box.PaletteBox(palette, bits_per_component=bps,
|
glymur.jp2box.PaletteBox(palette, bits_per_component=bps,
|
||||||
signed=signed)
|
signed=signed)
|
||||||
|
|
||||||
@unittest.skipIf(WARNING_INFRASTRUCTURE_ISSUE, WARNING_INFRASTRUCTURE_MSG)
|
@unittest.skipIf(WARNING_INFRASTRUCTURE_ISSUE, WARNING_INFRASTRUCTURE_MSG)
|
||||||
def test_mismatched_signed_palette(self):
|
def test_mismatched_signed_palette(self):
|
||||||
|
|
@ -545,8 +533,8 @@ class TestPaletteBox(unittest.TestCase):
|
||||||
bps = (8, 8, 8, 8)
|
bps = (8, 8, 8, 8)
|
||||||
signed = (False, False, False, False)
|
signed = (False, False, False, False)
|
||||||
with self.assertWarns(UserWarning):
|
with self.assertWarns(UserWarning):
|
||||||
pclr = glymur.jp2box.PaletteBox(palette, bits_per_component=bps,
|
glymur.jp2box.PaletteBox(palette, bits_per_component=bps,
|
||||||
signed=signed)
|
signed=signed)
|
||||||
|
|
||||||
def test_writing_with_different_bitdepths(self):
|
def test_writing_with_different_bitdepths(self):
|
||||||
"""Bitdepths must be the same when writing."""
|
"""Bitdepths must be the same when writing."""
|
||||||
|
|
@ -560,7 +548,7 @@ class TestPaletteBox(unittest.TestCase):
|
||||||
pclr.write(tfile)
|
pclr.write(tfile)
|
||||||
|
|
||||||
|
|
||||||
@unittest.skipIf(os.name == "nt", "Temporary file issue on window.")
|
@unittest.skipIf(os.name == "nt", WINDOWS_TMP_FILE_MSG)
|
||||||
class TestAppend(unittest.TestCase):
|
class TestAppend(unittest.TestCase):
|
||||||
"""Tests for append method."""
|
"""Tests for append method."""
|
||||||
|
|
||||||
|
|
@ -646,14 +634,14 @@ class TestAppend(unittest.TestCase):
|
||||||
jp2 = Jp2k(tfile.name)
|
jp2 = Jp2k(tfile.name)
|
||||||
|
|
||||||
# Make a UUID box. Only XMP UUID boxes can currently be appended.
|
# Make a UUID box. Only XMP UUID boxes can currently be appended.
|
||||||
uuid_instance = uuid.UUID('00000000-0000-0000-0000-000000000000')
|
uuid_instance = UUID('00000000-0000-0000-0000-000000000000')
|
||||||
data = b'0123456789'
|
data = b'0123456789'
|
||||||
uuidbox = glymur.jp2box.UUIDBox(uuid_instance, data)
|
uuidbox = glymur.jp2box.UUIDBox(uuid_instance, data)
|
||||||
with self.assertRaises(IOError):
|
with self.assertRaises(IOError):
|
||||||
jp2.append(uuidbox)
|
jp2.append(uuidbox)
|
||||||
|
|
||||||
|
|
||||||
@unittest.skipIf(os.name == "nt", "Temporary file issue on window.")
|
@unittest.skipIf(os.name == "nt", WINDOWS_TMP_FILE_MSG)
|
||||||
class TestWrap(unittest.TestCase):
|
class TestWrap(unittest.TestCase):
|
||||||
"""Tests for wrap method."""
|
"""Tests for wrap method."""
|
||||||
|
|
||||||
|
|
@ -802,7 +790,7 @@ class TestWrap(unittest.TestCase):
|
||||||
# list to trigger the error.
|
# list to trigger the error.
|
||||||
boxes[2].box = []
|
boxes[2].box = []
|
||||||
with self.assertRaises(IOError):
|
with self.assertRaises(IOError):
|
||||||
jp22 = jp2.wrap(tfile.name, boxes=boxes)
|
jp2.wrap(tfile.name, boxes=boxes)
|
||||||
|
|
||||||
def test_default_layout_with_boxes(self):
|
def test_default_layout_with_boxes(self):
|
||||||
"""basic test for rewrapping a jp2 file, boxes specified"""
|
"""basic test for rewrapping a jp2 file, boxes specified"""
|
||||||
|
|
@ -867,8 +855,8 @@ class TestWrap(unittest.TestCase):
|
||||||
"""A palette box must reside in a JP2 header box."""
|
"""A palette box must reside in a JP2 header box."""
|
||||||
palette = np.array([[255, 0, 255], [0, 255, 0]], dtype=np.int32)
|
palette = np.array([[255, 0, 255], [0, 255, 0]], dtype=np.int32)
|
||||||
bps = (8, 8, 8)
|
bps = (8, 8, 8)
|
||||||
signed = (True, False, True)
|
pclr = glymur.jp2box.PaletteBox(palette=palette,
|
||||||
pclr = glymur.jp2box.PaletteBox(palette=palette, bits_per_component=bps,
|
bits_per_component=bps,
|
||||||
signed=(True, False, True))
|
signed=(True, False, True))
|
||||||
|
|
||||||
j2k = Jp2k(self.j2kfile)
|
j2k = Jp2k(self.j2kfile)
|
||||||
|
|
@ -980,7 +968,8 @@ class TestWrap(unittest.TestCase):
|
||||||
"""Rewrap a jpx file."""
|
"""Rewrap a jpx file."""
|
||||||
with tempfile.NamedTemporaryFile(suffix='.jp2') as tfile1:
|
with tempfile.NamedTemporaryFile(suffix='.jp2') as tfile1:
|
||||||
jpx = Jp2k(self.jpxfile)
|
jpx = Jp2k(self.jpxfile)
|
||||||
idx = list(range(5)) + list(range(9, 12)) + list(range(6, 9)) + [12]
|
idx = (list(range(5)) +
|
||||||
|
list(range(9, 12)) + list(range(6, 9))) + [12]
|
||||||
boxes = [jpx.box[j] for j in idx]
|
boxes = [jpx.box[j] for j in idx]
|
||||||
jpx2 = jpx.wrap(tfile1.name, boxes=boxes)
|
jpx2 = jpx.wrap(tfile1.name, boxes=boxes)
|
||||||
exp_ids = [box.box_id for box in boxes]
|
exp_ids = [box.box_id for box in boxes]
|
||||||
|
|
@ -1032,11 +1021,11 @@ class TestJp2Boxes(unittest.TestCase):
|
||||||
"""Raw instantiation should not produce a main_header."""
|
"""Raw instantiation should not produce a main_header."""
|
||||||
box = ContiguousCodestreamBox()
|
box = ContiguousCodestreamBox()
|
||||||
self.assertEqual(box.box_id, 'jp2c')
|
self.assertEqual(box.box_id, 'jp2c')
|
||||||
self.assertIsNone(box.main_header)
|
self.assertIsNone(box.codestream)
|
||||||
|
|
||||||
def test_codestream_main_header_offset(self):
|
def test_codestream_main_header_offset(self):
|
||||||
"""main_header_offset is an attribute of the CCS box"""
|
"""main_header_offset is an attribute of the CCS box"""
|
||||||
j = Jp2k(self.jpxfile);
|
j = Jp2k(self.jpxfile)
|
||||||
self.assertEqual(j.box[5].main_header_offset,
|
self.assertEqual(j.box[5].main_header_offset,
|
||||||
j.box[5].offset + 8)
|
j.box[5].offset + 8)
|
||||||
|
|
||||||
|
|
@ -1237,8 +1226,8 @@ class TestRepr(MetadataBase):
|
||||||
|
|
||||||
def test_uuidlist_box(self):
|
def test_uuidlist_box(self):
|
||||||
"""Verify __repr__ method on ulst box."""
|
"""Verify __repr__ method on ulst box."""
|
||||||
uuid1 = uuid.UUID('00000000-0000-0000-0000-000000000001')
|
uuid1 = UUID('00000000-0000-0000-0000-000000000001')
|
||||||
uuid2 = uuid.UUID('00000000-0000-0000-0000-000000000002')
|
uuid2 = UUID('00000000-0000-0000-0000-000000000002')
|
||||||
uuids = [uuid1, uuid2]
|
uuids = [uuid1, uuid2]
|
||||||
ulst = glymur.jp2box.UUIDListBox(ulst=uuids)
|
ulst = glymur.jp2box.UUIDListBox(ulst=uuids)
|
||||||
newbox = eval(repr(ulst))
|
newbox = eval(repr(ulst))
|
||||||
|
|
@ -1250,7 +1239,6 @@ class TestRepr(MetadataBase):
|
||||||
"""Verify Palette box repr."""
|
"""Verify Palette box repr."""
|
||||||
palette = np.array([[255, 0, 1000], [0, 255, 0]], dtype=np.int32)
|
palette = np.array([[255, 0, 1000], [0, 255, 0]], dtype=np.int32)
|
||||||
bps = (8, 8, 16)
|
bps = (8, 8, 16)
|
||||||
signed = (True, False, True)
|
|
||||||
box = glymur.jp2box.PaletteBox(palette=palette, bits_per_component=bps,
|
box = glymur.jp2box.PaletteBox(palette=palette, bits_per_component=bps,
|
||||||
signed=(True, False, True))
|
signed=(True, False, True))
|
||||||
|
|
||||||
|
|
@ -1293,14 +1281,15 @@ class TestRepr(MetadataBase):
|
||||||
|
|
||||||
def test_uuid_box_generic(self):
|
def test_uuid_box_generic(self):
|
||||||
"""Verify uuid repr method."""
|
"""Verify uuid repr method."""
|
||||||
uuid_instance = uuid.UUID('00000000-0000-0000-0000-000000000000')
|
uuid_instance = UUID('00000000-0000-0000-0000-000000000000')
|
||||||
data = b'0123456789'
|
data = b'0123456789'
|
||||||
box = glymur.jp2box.UUIDBox(the_uuid=uuid_instance, raw_data=data)
|
box = glymur.jp2box.UUIDBox(the_uuid=uuid_instance, raw_data=data)
|
||||||
|
|
||||||
# Since the raw_data parameter is a sequence of bytes which could be
|
# Since the raw_data parameter is a sequence of bytes which could be
|
||||||
# quite long, don't bother trying to make it conform to eval(repr()).
|
# quite long, don't bother trying to make it conform to eval(repr()).
|
||||||
regexp = r"""glymur.jp2box.UUIDBox\("""
|
regexp = r"""glymur.jp2box.UUIDBox\("""
|
||||||
regexp += """the_uuid=UUID\('00000000-0000-0000-0000-000000000000'\),\s"""
|
regexp += """the_uuid="""
|
||||||
|
regexp += """UUID\('00000000-0000-0000-0000-000000000000'\),\s"""
|
||||||
regexp += """raw_data=<byte\sarray\s10\selements>\)"""
|
regexp += """raw_data=<byte\sarray\s10\selements>\)"""
|
||||||
|
|
||||||
if sys.hexversion < 0x03000000:
|
if sys.hexversion < 0x03000000:
|
||||||
|
|
@ -1317,7 +1306,8 @@ class TestRepr(MetadataBase):
|
||||||
# Since the raw_data parameter is a sequence of bytes which could be
|
# Since the raw_data parameter is a sequence of bytes which could be
|
||||||
# quite long, don't bother trying to make it conform to eval(repr()).
|
# quite long, don't bother trying to make it conform to eval(repr()).
|
||||||
regexp = r"""glymur.jp2box.UUIDBox\("""
|
regexp = r"""glymur.jp2box.UUIDBox\("""
|
||||||
regexp += """the_uuid=UUID\('be7acfcb-97a9-42e8-9c71-999491e3afac'\),\s"""
|
regexp += """the_uuid="""
|
||||||
|
regexp += """UUID\('be7acfcb-97a9-42e8-9c71-999491e3afac'\),\s"""
|
||||||
regexp += """raw_data=<byte\sarray\s3122\selements>\)"""
|
regexp += """raw_data=<byte\sarray\s3122\selements>\)"""
|
||||||
|
|
||||||
if sys.hexversion < 0x03000000:
|
if sys.hexversion < 0x03000000:
|
||||||
|
|
@ -1333,49 +1323,10 @@ class TestRepr(MetadataBase):
|
||||||
|
|
||||||
# Difficult to eval(repr()) this, so just match the general pattern.
|
# Difficult to eval(repr()) this, so just match the general pattern.
|
||||||
regexp = "glymur.jp2box.ContiguousCodeStreamBox"
|
regexp = "glymur.jp2box.ContiguousCodeStreamBox"
|
||||||
regexp += "[(]main_header=<glymur.codestream.Codestream\sobject\s"
|
regexp += "[(]codestream=<glymur.codestream.Codestream\sobject\s"
|
||||||
regexp += "at\s0x([a-fA-F0-9]*)>[)]"
|
regexp += "at\s0x([a-fA-F0-9]*)>[)]"
|
||||||
|
|
||||||
if sys.hexversion < 0x03000000:
|
if sys.hexversion < 0x03000000:
|
||||||
self.assertRegexpMatches(repr(box), regexp)
|
self.assertRegexpMatches(repr(box), regexp)
|
||||||
else:
|
else:
|
||||||
self.assertRegex(repr(box), regexp)
|
self.assertRegex(repr(box), regexp)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
class TestJpxBoxes(unittest.TestCase):
|
|
||||||
"""Tests for JPX boxes."""
|
|
||||||
|
|
||||||
def setUp(self):
|
|
||||||
pass
|
|
||||||
|
|
||||||
def tearDown(self):
|
|
||||||
pass
|
|
||||||
|
|
||||||
@unittest.skipIf(FORMAT_CORPUS_DATA_ROOT is None,
|
|
||||||
"FORMAT_CORPUS_DATA_ROOT environment variable not set")
|
|
||||||
def test_codestream_header(self):
|
|
||||||
"""Should recognize codestream header box."""
|
|
||||||
jfile = os.path.join(FORMAT_CORPUS_DATA_ROOT,
|
|
||||||
'jp2k-formats/balloon.jpf')
|
|
||||||
jpx = Jp2k(jfile)
|
|
||||||
|
|
||||||
# This superbox just happens to be empty.
|
|
||||||
self.assertEqual(jpx.box[4].box_id, 'jpch')
|
|
||||||
self.assertEqual(len(jpx.box[4].box), 0)
|
|
||||||
|
|
||||||
@unittest.skipIf(FORMAT_CORPUS_DATA_ROOT is None,
|
|
||||||
"FORMAT_CORPUS_DATA_ROOT environment variable not set")
|
|
||||||
def test_compositing_layer_header(self):
|
|
||||||
"""Should recognize compositing layer header box."""
|
|
||||||
jfile = os.path.join(FORMAT_CORPUS_DATA_ROOT,
|
|
||||||
'jp2k-formats/balloon.jpf')
|
|
||||||
jpx = Jp2k(jfile)
|
|
||||||
|
|
||||||
# This superbox just happens to be empty.
|
|
||||||
self.assertEqual(jpx.box[5].box_id, 'jplh')
|
|
||||||
self.assertEqual(len(jpx.box[5].box), 0)
|
|
||||||
|
|
||||||
|
|
||||||
if __name__ == "__main__":
|
|
||||||
unittest.main()
|
|
||||||
|
|
|
||||||
|
|
@ -6,7 +6,6 @@ Test suite specifically targeting JPX box layout.
|
||||||
import ctypes
|
import ctypes
|
||||||
import os
|
import os
|
||||||
import struct
|
import struct
|
||||||
import sys
|
|
||||||
import tempfile
|
import tempfile
|
||||||
import unittest
|
import unittest
|
||||||
|
|
||||||
|
|
@ -20,6 +19,7 @@ from glymur.jp2box import ColourSpecificationBox
|
||||||
|
|
||||||
from .fixtures import WARNING_INFRASTRUCTURE_ISSUE, WARNING_INFRASTRUCTURE_MSG
|
from .fixtures import WARNING_INFRASTRUCTURE_ISSUE, WARNING_INFRASTRUCTURE_MSG
|
||||||
|
|
||||||
|
|
||||||
@unittest.skipIf(os.name == "nt", "Temporary file issue on window.")
|
@unittest.skipIf(os.name == "nt", "Temporary file issue on window.")
|
||||||
class TestJPXWrap(unittest.TestCase):
|
class TestJPXWrap(unittest.TestCase):
|
||||||
"""Test suite for wrapping JPX files."""
|
"""Test suite for wrapping JPX files."""
|
||||||
|
|
@ -184,7 +184,7 @@ class TestJPXWrap(unittest.TestCase):
|
||||||
|
|
||||||
with tempfile.NamedTemporaryFile(suffix=".jpx") as tfile:
|
with tempfile.NamedTemporaryFile(suffix=".jpx") as tfile:
|
||||||
with self.assertRaises(IOError):
|
with self.assertRaises(IOError):
|
||||||
jpx = jp2.wrap(tfile.name, boxes=boxes)
|
jp2.wrap(tfile.name, boxes=boxes)
|
||||||
|
|
||||||
def test_cgrp_neg(self):
|
def test_cgrp_neg(self):
|
||||||
"""Can't write a cgrp with anything but colr sub boxes"""
|
"""Can't write a cgrp with anything but colr sub boxes"""
|
||||||
|
|
@ -204,7 +204,7 @@ class TestJPXWrap(unittest.TestCase):
|
||||||
|
|
||||||
with tempfile.NamedTemporaryFile(suffix=".jpx") as tfile:
|
with tempfile.NamedTemporaryFile(suffix=".jpx") as tfile:
|
||||||
with self.assertRaises(IOError):
|
with self.assertRaises(IOError):
|
||||||
jpx = jp2.wrap(tfile.name, boxes=boxes)
|
jp2.wrap(tfile.name, boxes=boxes)
|
||||||
|
|
||||||
def test_ftbl(self):
|
def test_ftbl(self):
|
||||||
"""Write a fragment table box."""
|
"""Write a fragment table box."""
|
||||||
|
|
@ -484,7 +484,7 @@ class TestJPX(unittest.TestCase):
|
||||||
ftbl.write(tfile)
|
ftbl.write(tfile)
|
||||||
|
|
||||||
def test_data_reference_requires_dtbl(self):
|
def test_data_reference_requires_dtbl(self):
|
||||||
"""The existance of a data reference box requires a ftbl box as well."""
|
"""The existance of data reference box requires a ftbl box as well."""
|
||||||
flag = 0
|
flag = 0
|
||||||
version = (0, 0, 0)
|
version = (0, 0, 0)
|
||||||
url1 = 'file:////usr/local/bin'
|
url1 = 'file:////usr/local/bin'
|
||||||
|
|
@ -574,7 +574,7 @@ class TestJPX(unittest.TestCase):
|
||||||
131072, 65536, 32768, 16384, 8192]
|
131072, 65536, 32768, 16384, 8192]
|
||||||
for j in range(len(standard_flags)):
|
for j in range(len(standard_flags)):
|
||||||
mask = (standard_masks[j] >> 16,
|
mask = (standard_masks[j] >> 16,
|
||||||
standard_masks[j] & 0x0000ffff>> 8,
|
standard_masks[j] & 0x0000ffff >> 8,
|
||||||
standard_masks[j] & 0x000000ff)
|
standard_masks[j] & 0x000000ff)
|
||||||
struct.pack_into('>HBBB', rreq_buffer, 17 + j * 5,
|
struct.pack_into('>HBBB', rreq_buffer, 17 + j * 5,
|
||||||
standard_flags[j], *mask)
|
standard_flags[j], *mask)
|
||||||
|
|
@ -599,7 +599,6 @@ class TestJPX(unittest.TestCase):
|
||||||
self.assertEqual(jpx.box[2].standard_flag,
|
self.assertEqual(jpx.box[2].standard_flag,
|
||||||
(5, 42, 45, 2, 18, 19, 1, 8, 12, 31, 20))
|
(5, 42, 45, 2, 18, 19, 1, 8, 12, 31, 20))
|
||||||
|
|
||||||
|
|
||||||
def test_nlst(self):
|
def test_nlst(self):
|
||||||
"""Verify that we can handle a number list box."""
|
"""Verify that we can handle a number list box."""
|
||||||
j = Jp2k(self.jpxfile)
|
j = Jp2k(self.jpxfile)
|
||||||
|
|
|
||||||
|
|
@ -1,17 +1,7 @@
|
||||||
# -*- coding: utf-8 -*-
|
# -*- coding: utf-8 -*-
|
||||||
"""Test suite for printing.
|
"""Test suite for printing.
|
||||||
"""
|
"""
|
||||||
# C0302: don't care too much about having too many lines in a test module
|
|
||||||
# pylint: disable=C0302
|
|
||||||
|
|
||||||
# E061: unittest.mock introduced in 3.3 (python-2.7/pylint issue)
|
|
||||||
# pylint: disable=E0611,F0401
|
|
||||||
|
|
||||||
# R0904: Not too many methods in unittest.
|
|
||||||
# pylint: disable=R0904
|
|
||||||
|
|
||||||
import os
|
import os
|
||||||
import re
|
|
||||||
import shutil
|
import shutil
|
||||||
import struct
|
import struct
|
||||||
import sys
|
import sys
|
||||||
|
|
@ -23,30 +13,18 @@ if sys.hexversion < 0x02070000:
|
||||||
else:
|
else:
|
||||||
import unittest
|
import unittest
|
||||||
|
|
||||||
if sys.hexversion < 0x03000000:
|
|
||||||
from StringIO import StringIO
|
|
||||||
else:
|
|
||||||
from io import StringIO
|
|
||||||
|
|
||||||
if sys.hexversion <= 0x03030000:
|
|
||||||
from mock import patch
|
|
||||||
else:
|
|
||||||
from unittest.mock import patch
|
|
||||||
|
|
||||||
import lxml.etree
|
import lxml.etree
|
||||||
|
|
||||||
from .fixtures import HAS_PYTHON_XMP_TOOLKIT, OPJ_DATA_ROOT
|
from .fixtures import (WARNING_INFRASTRUCTURE_ISSUE,
|
||||||
from .fixtures import WARNING_INFRASTRUCTURE_ISSUE, WARNING_INFRASTRUCTURE_MSG
|
WARNING_INFRASTRUCTURE_MSG,
|
||||||
|
WINDOWS_TMP_FILE_MSG)
|
||||||
if HAS_PYTHON_XMP_TOOLKIT:
|
|
||||||
from libxmp import XMPMeta
|
|
||||||
|
|
||||||
import glymur
|
import glymur
|
||||||
from glymur import Jp2k
|
from glymur import Jp2k
|
||||||
from .fixtures import OPJ_DATA_ROOT, opj_data_file, SimpleRDF
|
from .fixtures import SimpleRDF
|
||||||
|
|
||||||
|
|
||||||
@unittest.skipIf(os.name == "nt", "Unexplained failure on windows")
|
@unittest.skipIf(os.name == "nt", WINDOWS_TMP_FILE_MSG)
|
||||||
class TestSuite(unittest.TestCase):
|
class TestSuite(unittest.TestCase):
|
||||||
"""Tests for XMP, Exif UUIDs."""
|
"""Tests for XMP, Exif UUIDs."""
|
||||||
|
|
||||||
|
|
@ -101,8 +79,9 @@ class TestSuite(unittest.TestCase):
|
||||||
jp2 = glymur.Jp2k(tfile.name)
|
jp2 = glymur.Jp2k(tfile.name)
|
||||||
self.assertEqual(jp2.box[-1].data['Make'], "HTC")
|
self.assertEqual(jp2.box[-1].data['Make'], "HTC")
|
||||||
|
|
||||||
|
|
||||||
@unittest.skipIf(WARNING_INFRASTRUCTURE_ISSUE, WARNING_INFRASTRUCTURE_MSG)
|
@unittest.skipIf(WARNING_INFRASTRUCTURE_ISSUE, WARNING_INFRASTRUCTURE_MSG)
|
||||||
@unittest.skipIf(os.name == "nt", "Unexplained failure on windows")
|
@unittest.skipIf(os.name == "nt", WINDOWS_TMP_FILE_MSG)
|
||||||
class TestSuiteWarns(unittest.TestCase):
|
class TestSuiteWarns(unittest.TestCase):
|
||||||
"""Tests for XMP, Exif UUIDs, issues warnings."""
|
"""Tests for XMP, Exif UUIDs, issues warnings."""
|
||||||
|
|
||||||
|
|
@ -111,7 +90,7 @@ class TestSuiteWarns(unittest.TestCase):
|
||||||
|
|
||||||
def tearDown(self):
|
def tearDown(self):
|
||||||
pass
|
pass
|
||||||
|
|
||||||
def test_unrecognized_exif_tag(self):
|
def test_unrecognized_exif_tag(self):
|
||||||
"""Verify warning in case of unrecognized tag."""
|
"""Verify warning in case of unrecognized tag."""
|
||||||
with tempfile.NamedTemporaryFile(suffix='.jp2', mode='wb') as tfile:
|
with tempfile.NamedTemporaryFile(suffix='.jp2', mode='wb') as tfile:
|
||||||
|
|
@ -135,7 +114,7 @@ class TestSuiteWarns(unittest.TestCase):
|
||||||
tfile.flush()
|
tfile.flush()
|
||||||
|
|
||||||
with self.assertWarnsRegex(UserWarning, 'Unrecognized Exif tag'):
|
with self.assertWarnsRegex(UserWarning, 'Unrecognized Exif tag'):
|
||||||
j = glymur.Jp2k(tfile.name)
|
glymur.Jp2k(tfile.name)
|
||||||
|
|
||||||
def test_bad_tag_datatype(self):
|
def test_bad_tag_datatype(self):
|
||||||
"""Only certain datatypes are allowable"""
|
"""Only certain datatypes are allowable"""
|
||||||
|
|
@ -191,6 +170,3 @@ class TestSuiteWarns(unittest.TestCase):
|
||||||
jp2 = glymur.Jp2k(tfile.name)
|
jp2 = glymur.Jp2k(tfile.name)
|
||||||
|
|
||||||
self.assertEqual(jp2.box[-1].box_id, 'uuid')
|
self.assertEqual(jp2.box[-1].box_id, 'uuid')
|
||||||
|
|
||||||
if __name__ == "__main__":
|
|
||||||
unittest.main()
|
|
||||||
|
|
|
||||||
|
|
@ -2,35 +2,12 @@
|
||||||
"""
|
"""
|
||||||
Test suite specifically targeting JP2 box layout.
|
Test suite specifically targeting JP2 box layout.
|
||||||
"""
|
"""
|
||||||
# E1103: return value from read may be list or np array
|
|
||||||
# pylint: disable=E1103
|
|
||||||
|
|
||||||
# R0902: More than 7 instance attributes are just fine for testing.
|
|
||||||
# pylint: disable=R0902
|
|
||||||
|
|
||||||
# R0904: Seems like pylint is fooled in this situation
|
|
||||||
# pylint: disable=R0904
|
|
||||||
|
|
||||||
# W0613: load_tests doesn't need to use ignore or loader arguments.
|
|
||||||
# pylint: disable=W0613
|
|
||||||
|
|
||||||
import os
|
import os
|
||||||
import re
|
import re
|
||||||
import struct
|
import struct
|
||||||
import sys
|
|
||||||
import tempfile
|
import tempfile
|
||||||
import unittest
|
import unittest
|
||||||
|
|
||||||
if sys.hexversion < 0x03000000:
|
|
||||||
from StringIO import StringIO
|
|
||||||
else:
|
|
||||||
from io import StringIO
|
|
||||||
|
|
||||||
if sys.hexversion <= 0x03030000:
|
|
||||||
from mock import patch
|
|
||||||
else:
|
|
||||||
from unittest.mock import patch
|
|
||||||
|
|
||||||
import lxml.etree as ET
|
import lxml.etree as ET
|
||||||
|
|
||||||
import glymur
|
import glymur
|
||||||
|
|
@ -41,8 +18,10 @@ from glymur.jp2box import JPEG2000SignatureBox
|
||||||
|
|
||||||
from .fixtures import OPJ_DATA_ROOT, opj_data_file
|
from .fixtures import OPJ_DATA_ROOT, opj_data_file
|
||||||
from .fixtures import WARNING_INFRASTRUCTURE_ISSUE, WARNING_INFRASTRUCTURE_MSG
|
from .fixtures import WARNING_INFRASTRUCTURE_ISSUE, WARNING_INFRASTRUCTURE_MSG
|
||||||
|
from . import fixtures
|
||||||
|
|
||||||
@unittest.skipIf(os.name == "nt", "Temporary file issue on window.")
|
|
||||||
|
@unittest.skipIf(os.name == "nt", fixtures.WINDOWS_TMP_FILE_MSG)
|
||||||
class TestXML(unittest.TestCase):
|
class TestXML(unittest.TestCase):
|
||||||
"""Test suite for XML boxes."""
|
"""Test suite for XML boxes."""
|
||||||
|
|
||||||
|
|
@ -166,7 +145,6 @@ class TestXML(unittest.TestCase):
|
||||||
u'<country>Россия</country>')
|
u'<country>Россия</country>')
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
class TestJp2kBadXmlFile(unittest.TestCase):
|
class TestJp2kBadXmlFile(unittest.TestCase):
|
||||||
"""Test suite for bad XML box situations"""
|
"""Test suite for bad XML box situations"""
|
||||||
|
|
||||||
|
|
@ -219,7 +197,7 @@ class TestJp2kBadXmlFile(unittest.TestCase):
|
||||||
self.assertIsNone(jp2k.box[3].xml)
|
self.assertIsNone(jp2k.box[3].xml)
|
||||||
|
|
||||||
|
|
||||||
@unittest.skipIf(os.name == "nt", "NamedTemporaryFile issue on windows")
|
@unittest.skipIf(os.name == "nt", fixtures.WINDOWS_TMP_FILE_MSG)
|
||||||
class TestBadButRecoverableXmlFile(unittest.TestCase):
|
class TestBadButRecoverableXmlFile(unittest.TestCase):
|
||||||
"""Test suite for XML box that is bad, but we can still recover the XML."""
|
"""Test suite for XML box that is bad, but we can still recover the XML."""
|
||||||
|
|
||||||
|
|
@ -292,22 +270,19 @@ class TestXML_OpjDataRoot(unittest.TestCase):
|
||||||
'nonregression',
|
'nonregression',
|
||||||
'issue171.jp2'))
|
'issue171.jp2'))
|
||||||
msg = 'An illegal BOM \(byte order marker\) was detected and removed '
|
msg = 'An illegal BOM \(byte order marker\) was detected and removed '
|
||||||
msg += 'from the XML contents in the box starting at byte offset \d+'
|
msg += 'from the XML contents in the box starting at byte offset \d+'
|
||||||
with self.assertWarnsRegex(UserWarning, re.compile(msg)):
|
with self.assertWarnsRegex(UserWarning, re.compile(msg)):
|
||||||
jp2 = Jp2k(filename)
|
jp2 = Jp2k(filename)
|
||||||
|
|
||||||
self.assertIsNotNone(jp2.box[3].xml)
|
self.assertIsNotNone(jp2.box[3].xml)
|
||||||
|
|
||||||
|
|
||||||
def test_invalid_utf8(self):
|
def test_invalid_utf8(self):
|
||||||
"""Bad byte sequence that cannot be parsed."""
|
"""Bad byte sequence that cannot be parsed."""
|
||||||
|
relname = '26ccf3651020967f7778238ef5af08af.SIGFPE.d25.527.jp2'
|
||||||
filename = opj_data_file(os.path.join('input',
|
filename = opj_data_file(os.path.join('input',
|
||||||
'nonregression',
|
'nonregression',
|
||||||
'26ccf3651020967f7778238ef5af08af.SIGFPE.d25.527.jp2'))
|
relname))
|
||||||
with self.assertWarns((UserWarning, UserWarning)):
|
with self.assertWarns((UserWarning, UserWarning)):
|
||||||
jp2 = Jp2k(filename)
|
jp2 = Jp2k(filename)
|
||||||
|
|
||||||
self.assertIsNone(jp2.box[3].box[1].box[1].xml)
|
self.assertIsNone(jp2.box[3].box[1].box[1].xml)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
|
||||||
File diff suppressed because it is too large
Load diff
|
|
@ -2,34 +2,10 @@
|
||||||
The tests defined here roughly correspond to what is in the OpenJPEG test
|
The tests defined here roughly correspond to what is in the OpenJPEG test
|
||||||
suite.
|
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 re
|
||||||
import sys
|
import sys
|
||||||
import unittest
|
import unittest
|
||||||
|
import warnings
|
||||||
|
|
||||||
import numpy as np
|
import numpy as np
|
||||||
|
|
||||||
|
|
@ -37,13 +13,14 @@ import glymur
|
||||||
from glymur import Jp2k
|
from glymur import Jp2k
|
||||||
from glymur.jp2box import FileTypeBox, ImageHeaderBox, ColourSpecificationBox
|
from glymur.jp2box import FileTypeBox, ImageHeaderBox, ColourSpecificationBox
|
||||||
|
|
||||||
from .fixtures import (
|
from .fixtures import (OPJ_DATA_ROOT, MetadataBase,
|
||||||
OPJ_DATA_ROOT, MetadataBase,
|
WARNING_INFRASTRUCTURE_ISSUE,
|
||||||
WARNING_INFRASTRUCTURE_ISSUE, WARNING_INFRASTRUCTURE_MSG,
|
WARNING_INFRASTRUCTURE_MSG,
|
||||||
mse, peak_tolerance, read_pgx, opj_data_file
|
mse, peak_tolerance, read_pgx, opj_data_file,
|
||||||
)
|
OPENJPEG_NOT_AVAILABLE, OPENJPEG_NOT_AVAILABLE_MSG)
|
||||||
|
|
||||||
|
|
||||||
|
@unittest.skipIf(OPENJPEG_NOT_AVAILABLE, OPENJPEG_NOT_AVAILABLE_MSG)
|
||||||
@unittest.skipIf(OPJ_DATA_ROOT is None,
|
@unittest.skipIf(OPJ_DATA_ROOT is None,
|
||||||
"OPJ_DATA_ROOT environment variable not set")
|
"OPJ_DATA_ROOT environment variable not set")
|
||||||
class TestSuite(unittest.TestCase):
|
class TestSuite(unittest.TestCase):
|
||||||
|
|
@ -57,7 +34,7 @@ class TestSuite(unittest.TestCase):
|
||||||
def test_ETS_C1P0_p0_01_j2k(self):
|
def test_ETS_C1P0_p0_01_j2k(self):
|
||||||
jfile = opj_data_file('input/conformance/p0_01.j2k')
|
jfile = opj_data_file('input/conformance/p0_01.j2k')
|
||||||
jp2k = Jp2k(jfile)
|
jp2k = Jp2k(jfile)
|
||||||
jpdata = jp2k.read(rlevel=0)
|
jpdata = jp2k[:]
|
||||||
|
|
||||||
pgxfile = opj_data_file('baseline/conformance/c1p0_01_0.pgx')
|
pgxfile = opj_data_file('baseline/conformance/c1p0_01_0.pgx')
|
||||||
pgxdata = read_pgx(pgxfile)
|
pgxdata = read_pgx(pgxfile)
|
||||||
|
|
@ -67,7 +44,7 @@ class TestSuite(unittest.TestCase):
|
||||||
def test_ETS_C1P0_p0_03_j2k(self):
|
def test_ETS_C1P0_p0_03_j2k(self):
|
||||||
jfile = opj_data_file('input/conformance/p0_03.j2k')
|
jfile = opj_data_file('input/conformance/p0_03.j2k')
|
||||||
jp2k = Jp2k(jfile)
|
jp2k = Jp2k(jfile)
|
||||||
jpdata = jp2k.read(rlevel=0)
|
jpdata = jp2k[:]
|
||||||
|
|
||||||
pgxfile = opj_data_file('baseline/conformance/c1p0_03_0.pgx')
|
pgxfile = opj_data_file('baseline/conformance/c1p0_03_0.pgx')
|
||||||
pgxdata = read_pgx(pgxfile)
|
pgxdata = read_pgx(pgxfile)
|
||||||
|
|
@ -77,7 +54,7 @@ class TestSuite(unittest.TestCase):
|
||||||
def test_ETS_C1P0_p0_04_j2k(self):
|
def test_ETS_C1P0_p0_04_j2k(self):
|
||||||
jfile = opj_data_file('input/conformance/p0_04.j2k')
|
jfile = opj_data_file('input/conformance/p0_04.j2k')
|
||||||
jp2k = Jp2k(jfile)
|
jp2k = Jp2k(jfile)
|
||||||
jpdata = jp2k.read(rlevel=0)
|
jpdata = jp2k[:]
|
||||||
|
|
||||||
pgxfile = opj_data_file('baseline/conformance/c1p0_04_0.pgx')
|
pgxfile = opj_data_file('baseline/conformance/c1p0_04_0.pgx')
|
||||||
pgxdata = read_pgx(pgxfile)
|
pgxdata = read_pgx(pgxfile)
|
||||||
|
|
@ -97,7 +74,7 @@ class TestSuite(unittest.TestCase):
|
||||||
def test_ETS_C1P0_p0_08_j2k(self):
|
def test_ETS_C1P0_p0_08_j2k(self):
|
||||||
jfile = opj_data_file('input/conformance/p0_08.j2k')
|
jfile = opj_data_file('input/conformance/p0_08.j2k')
|
||||||
jp2k = Jp2k(jfile)
|
jp2k = Jp2k(jfile)
|
||||||
jpdata = jp2k.read(rlevel=1)
|
jpdata = jp2k[::2, ::2]
|
||||||
|
|
||||||
pgxfile = opj_data_file('baseline/conformance/c1p0_08_0.pgx')
|
pgxfile = opj_data_file('baseline/conformance/c1p0_08_0.pgx')
|
||||||
pgxdata = read_pgx(pgxfile)
|
pgxdata = read_pgx(pgxfile)
|
||||||
|
|
@ -114,7 +91,7 @@ class TestSuite(unittest.TestCase):
|
||||||
def test_ETS_C1P0_p0_09_j2k(self):
|
def test_ETS_C1P0_p0_09_j2k(self):
|
||||||
jfile = opj_data_file('input/conformance/p0_09.j2k')
|
jfile = opj_data_file('input/conformance/p0_09.j2k')
|
||||||
jp2k = Jp2k(jfile)
|
jp2k = Jp2k(jfile)
|
||||||
jpdata = jp2k.read(rlevel=0)
|
jpdata = jp2k[:]
|
||||||
|
|
||||||
pgxfile = opj_data_file('baseline/conformance/c1p0_09_0.pgx')
|
pgxfile = opj_data_file('baseline/conformance/c1p0_09_0.pgx')
|
||||||
pgxdata = read_pgx(pgxfile)
|
pgxdata = read_pgx(pgxfile)
|
||||||
|
|
@ -123,7 +100,7 @@ class TestSuite(unittest.TestCase):
|
||||||
def test_ETS_C1P0_p0_11_j2k(self):
|
def test_ETS_C1P0_p0_11_j2k(self):
|
||||||
jfile = opj_data_file('input/conformance/p0_11.j2k')
|
jfile = opj_data_file('input/conformance/p0_11.j2k')
|
||||||
jp2k = Jp2k(jfile)
|
jp2k = Jp2k(jfile)
|
||||||
jpdata = jp2k.read(rlevel=0)
|
jpdata = jp2k[:]
|
||||||
|
|
||||||
pgxfile = opj_data_file('baseline/conformance/c1p0_11_0.pgx')
|
pgxfile = opj_data_file('baseline/conformance/c1p0_11_0.pgx')
|
||||||
pgxdata = read_pgx(pgxfile)
|
pgxdata = read_pgx(pgxfile)
|
||||||
|
|
@ -132,7 +109,7 @@ class TestSuite(unittest.TestCase):
|
||||||
def test_ETS_C1P0_p0_14_j2k(self):
|
def test_ETS_C1P0_p0_14_j2k(self):
|
||||||
jfile = opj_data_file('input/conformance/p0_14.j2k')
|
jfile = opj_data_file('input/conformance/p0_14.j2k')
|
||||||
jp2k = Jp2k(jfile)
|
jp2k = Jp2k(jfile)
|
||||||
jpdata = jp2k.read(rlevel=0)
|
jpdata = jp2k[:]
|
||||||
|
|
||||||
pgxfile = opj_data_file('baseline/conformance/c1p0_14_0.pgx')
|
pgxfile = opj_data_file('baseline/conformance/c1p0_14_0.pgx')
|
||||||
pgxdata = read_pgx(pgxfile)
|
pgxdata = read_pgx(pgxfile)
|
||||||
|
|
@ -149,7 +126,7 @@ class TestSuite(unittest.TestCase):
|
||||||
def test_ETS_C1P0_p0_15_j2k(self):
|
def test_ETS_C1P0_p0_15_j2k(self):
|
||||||
jfile = opj_data_file('input/conformance/p0_15.j2k')
|
jfile = opj_data_file('input/conformance/p0_15.j2k')
|
||||||
jp2k = Jp2k(jfile)
|
jp2k = Jp2k(jfile)
|
||||||
jpdata = jp2k.read(rlevel=0)
|
jpdata = jp2k[:]
|
||||||
|
|
||||||
pgxfile = opj_data_file('baseline/conformance/c1p0_15_0.pgx')
|
pgxfile = opj_data_file('baseline/conformance/c1p0_15_0.pgx')
|
||||||
pgxdata = read_pgx(pgxfile)
|
pgxdata = read_pgx(pgxfile)
|
||||||
|
|
@ -158,7 +135,7 @@ class TestSuite(unittest.TestCase):
|
||||||
def test_ETS_C1P0_p0_16_j2k(self):
|
def test_ETS_C1P0_p0_16_j2k(self):
|
||||||
jfile = opj_data_file('input/conformance/p0_16.j2k')
|
jfile = opj_data_file('input/conformance/p0_16.j2k')
|
||||||
jp2k = Jp2k(jfile)
|
jp2k = Jp2k(jfile)
|
||||||
jpdata = jp2k.read(rlevel=0)
|
jpdata = jp2k[:]
|
||||||
|
|
||||||
pgxfile = opj_data_file('baseline/conformance/c1p0_16_0.pgx')
|
pgxfile = opj_data_file('baseline/conformance/c1p0_16_0.pgx')
|
||||||
pgxdata = read_pgx(pgxfile)
|
pgxdata = read_pgx(pgxfile)
|
||||||
|
|
@ -167,7 +144,7 @@ class TestSuite(unittest.TestCase):
|
||||||
def test_ETS_C1P1_p1_01_j2k(self):
|
def test_ETS_C1P1_p1_01_j2k(self):
|
||||||
jfile = opj_data_file('input/conformance/p1_01.j2k')
|
jfile = opj_data_file('input/conformance/p1_01.j2k')
|
||||||
jp2k = Jp2k(jfile)
|
jp2k = Jp2k(jfile)
|
||||||
jpdata = jp2k.read(rlevel=0)
|
jpdata = jp2k[:]
|
||||||
|
|
||||||
pgxfile = opj_data_file('baseline/conformance/c1p1_01_0.pgx')
|
pgxfile = opj_data_file('baseline/conformance/c1p1_01_0.pgx')
|
||||||
pgxdata = read_pgx(pgxfile)
|
pgxdata = read_pgx(pgxfile)
|
||||||
|
|
@ -176,7 +153,7 @@ class TestSuite(unittest.TestCase):
|
||||||
def test_ETS_C1P1_p1_02_j2k(self):
|
def test_ETS_C1P1_p1_02_j2k(self):
|
||||||
jfile = opj_data_file('input/conformance/p1_02.j2k')
|
jfile = opj_data_file('input/conformance/p1_02.j2k')
|
||||||
jp2k = Jp2k(jfile)
|
jp2k = Jp2k(jfile)
|
||||||
jpdata = jp2k.read(rlevel=0)
|
jpdata = jp2k[:]
|
||||||
|
|
||||||
pgxfile = opj_data_file('baseline/conformance/c1p1_02_0.pgx')
|
pgxfile = opj_data_file('baseline/conformance/c1p1_02_0.pgx')
|
||||||
pgxdata = read_pgx(pgxfile)
|
pgxdata = read_pgx(pgxfile)
|
||||||
|
|
@ -196,7 +173,7 @@ class TestSuite(unittest.TestCase):
|
||||||
def test_ETS_C1P1_p1_04_j2k(self):
|
def test_ETS_C1P1_p1_04_j2k(self):
|
||||||
jfile = opj_data_file('input/conformance/p1_04.j2k')
|
jfile = opj_data_file('input/conformance/p1_04.j2k')
|
||||||
jp2k = Jp2k(jfile)
|
jp2k = Jp2k(jfile)
|
||||||
jpdata = jp2k.read()
|
jpdata = jp2k[:]
|
||||||
|
|
||||||
pgxfile = opj_data_file('baseline/conformance/c1p1_04_0.pgx')
|
pgxfile = opj_data_file('baseline/conformance/c1p1_04_0.pgx')
|
||||||
pgxdata = read_pgx(pgxfile)
|
pgxdata = read_pgx(pgxfile)
|
||||||
|
|
@ -206,95 +183,95 @@ class TestSuite(unittest.TestCase):
|
||||||
def test_NR_DEC_Bretagne2_j2k_1_decode(self):
|
def test_NR_DEC_Bretagne2_j2k_1_decode(self):
|
||||||
jfile = opj_data_file('input/nonregression/Bretagne2.j2k')
|
jfile = opj_data_file('input/nonregression/Bretagne2.j2k')
|
||||||
jp2 = Jp2k(jfile)
|
jp2 = Jp2k(jfile)
|
||||||
jp2.read()
|
jp2[:]
|
||||||
self.assertTrue(True)
|
self.assertTrue(True)
|
||||||
|
|
||||||
def test_NR_DEC__00042_j2k_2_decode(self):
|
def test_NR_DEC__00042_j2k_2_decode(self):
|
||||||
jfile = opj_data_file('input/nonregression/_00042.j2k')
|
jfile = opj_data_file('input/nonregression/_00042.j2k')
|
||||||
jp2 = Jp2k(jfile)
|
jp2 = Jp2k(jfile)
|
||||||
jp2.read()
|
jp2[:]
|
||||||
self.assertTrue(True)
|
self.assertTrue(True)
|
||||||
|
|
||||||
def test_NR_DEC_buxI_j2k_9_decode(self):
|
def test_NR_DEC_buxI_j2k_9_decode(self):
|
||||||
jfile = opj_data_file('input/nonregression/buxI.j2k')
|
jfile = opj_data_file('input/nonregression/buxI.j2k')
|
||||||
Jp2k(jfile).read()
|
Jp2k(jfile)[:]
|
||||||
self.assertTrue(True)
|
self.assertTrue(True)
|
||||||
|
|
||||||
def test_NR_DEC_buxR_j2k_10_decode(self):
|
def test_NR_DEC_buxR_j2k_10_decode(self):
|
||||||
jfile = opj_data_file('input/nonregression/buxR.j2k')
|
jfile = opj_data_file('input/nonregression/buxR.j2k')
|
||||||
Jp2k(jfile).read()
|
Jp2k(jfile)[:]
|
||||||
self.assertTrue(True)
|
self.assertTrue(True)
|
||||||
|
|
||||||
def test_NR_DEC_Cannotreaddatawithnosizeknown_j2k_11_decode(self):
|
def test_NR_DEC_Cannotreaddatawithnosizeknown_j2k_11_decode(self):
|
||||||
relpath = 'input/nonregression/Cannotreaddatawithnosizeknown.j2k'
|
relpath = 'input/nonregression/Cannotreaddatawithnosizeknown.j2k'
|
||||||
jfile = opj_data_file(relpath)
|
jfile = opj_data_file(relpath)
|
||||||
Jp2k(jfile).read()
|
Jp2k(jfile)[:]
|
||||||
self.assertTrue(True)
|
self.assertTrue(True)
|
||||||
|
|
||||||
def test_NR_DEC_cthead1_j2k_12_decode(self):
|
def test_NR_DEC_cthead1_j2k_12_decode(self):
|
||||||
jfile = opj_data_file('input/nonregression/cthead1.j2k')
|
jfile = opj_data_file('input/nonregression/cthead1.j2k')
|
||||||
Jp2k(jfile).read()
|
Jp2k(jfile)[:]
|
||||||
self.assertTrue(True)
|
self.assertTrue(True)
|
||||||
|
|
||||||
def test_NR_DEC_CT_Phillips_JPEG2K_Decompr_Problem_j2k_13_decode(self):
|
def test_NR_DEC_CT_Phillips_JPEG2K_Decompr_Problem_j2k_13_decode(self):
|
||||||
relpath = 'input/nonregression/CT_Phillips_JPEG2K_Decompr_Problem.j2k'
|
relpath = 'input/nonregression/CT_Phillips_JPEG2K_Decompr_Problem.j2k'
|
||||||
jfile = opj_data_file(relpath)
|
jfile = opj_data_file(relpath)
|
||||||
Jp2k(jfile).read()
|
Jp2k(jfile)[:]
|
||||||
self.assertTrue(True)
|
self.assertTrue(True)
|
||||||
|
|
||||||
def test_NR_DEC_j2k32_j2k_15_decode(self):
|
def test_NR_DEC_j2k32_j2k_15_decode(self):
|
||||||
jfile = opj_data_file('input/nonregression/j2k32.j2k')
|
jfile = opj_data_file('input/nonregression/j2k32.j2k')
|
||||||
Jp2k(jfile).read()
|
Jp2k(jfile)[:]
|
||||||
self.assertTrue(True)
|
self.assertTrue(True)
|
||||||
|
|
||||||
def test_NR_DEC_MarkerIsNotCompliant_j2k_17_decode(self):
|
def test_NR_DEC_MarkerIsNotCompliant_j2k_17_decode(self):
|
||||||
jfile = opj_data_file('input/nonregression/MarkerIsNotCompliant.j2k')
|
jfile = opj_data_file('input/nonregression/MarkerIsNotCompliant.j2k')
|
||||||
Jp2k(jfile).read()
|
Jp2k(jfile)[:]
|
||||||
self.assertTrue(True)
|
self.assertTrue(True)
|
||||||
|
|
||||||
def test_NR_DEC_Marrin_jp2_18_decode(self):
|
def test_NR_DEC_Marrin_jp2_18_decode(self):
|
||||||
jfile = opj_data_file('input/nonregression/Marrin.jp2')
|
jfile = opj_data_file('input/nonregression/Marrin.jp2')
|
||||||
Jp2k(jfile).read()
|
Jp2k(jfile)[:]
|
||||||
self.assertTrue(True)
|
self.assertTrue(True)
|
||||||
|
|
||||||
def test_NR_DEC_movie_00000_j2k_20_decode(self):
|
def test_NR_DEC_movie_00000_j2k_20_decode(self):
|
||||||
jfile = opj_data_file('input/nonregression/movie_00000.j2k')
|
jfile = opj_data_file('input/nonregression/movie_00000.j2k')
|
||||||
Jp2k(jfile).read()
|
Jp2k(jfile)[:]
|
||||||
self.assertTrue(True)
|
self.assertTrue(True)
|
||||||
|
|
||||||
def test_NR_DEC_movie_00001_j2k_21_decode(self):
|
def test_NR_DEC_movie_00001_j2k_21_decode(self):
|
||||||
jfile = opj_data_file('input/nonregression/movie_00001.j2k')
|
jfile = opj_data_file('input/nonregression/movie_00001.j2k')
|
||||||
Jp2k(jfile).read()
|
Jp2k(jfile)[:]
|
||||||
self.assertTrue(True)
|
self.assertTrue(True)
|
||||||
|
|
||||||
def test_NR_DEC_movie_00002_j2k_22_decode(self):
|
def test_NR_DEC_movie_00002_j2k_22_decode(self):
|
||||||
jfile = opj_data_file('input/nonregression/movie_00002.j2k')
|
jfile = opj_data_file('input/nonregression/movie_00002.j2k')
|
||||||
Jp2k(jfile).read()
|
Jp2k(jfile)[:]
|
||||||
self.assertTrue(True)
|
self.assertTrue(True)
|
||||||
|
|
||||||
def test_NR_DEC_orb_blue_lin_j2k_j2k_23_decode(self):
|
def test_NR_DEC_orb_blue_lin_j2k_j2k_23_decode(self):
|
||||||
jfile = opj_data_file('input/nonregression/orb-blue10-lin-j2k.j2k')
|
jfile = opj_data_file('input/nonregression/orb-blue10-lin-j2k.j2k')
|
||||||
Jp2k(jfile).read()
|
Jp2k(jfile)[:]
|
||||||
self.assertTrue(True)
|
self.assertTrue(True)
|
||||||
|
|
||||||
def test_NR_DEC_orb_blue_win_j2k_j2k_24_decode(self):
|
def test_NR_DEC_orb_blue_win_j2k_j2k_24_decode(self):
|
||||||
jfile = opj_data_file('input/nonregression/orb-blue10-win-j2k.j2k')
|
jfile = opj_data_file('input/nonregression/orb-blue10-win-j2k.j2k')
|
||||||
Jp2k(jfile).read()
|
Jp2k(jfile)[:]
|
||||||
self.assertTrue(True)
|
self.assertTrue(True)
|
||||||
|
|
||||||
def test_NR_DEC_relax_jp2_27_decode(self):
|
def test_NR_DEC_relax_jp2_27_decode(self):
|
||||||
jfile = opj_data_file('input/nonregression/relax.jp2')
|
jfile = opj_data_file('input/nonregression/relax.jp2')
|
||||||
Jp2k(jfile).read()
|
Jp2k(jfile)[:]
|
||||||
self.assertTrue(True)
|
self.assertTrue(True)
|
||||||
|
|
||||||
def test_NR_DEC_test_lossless_j2k_28_decode(self):
|
def test_NR_DEC_test_lossless_j2k_28_decode(self):
|
||||||
jfile = opj_data_file('input/nonregression/test_lossless.j2k')
|
jfile = opj_data_file('input/nonregression/test_lossless.j2k')
|
||||||
Jp2k(jfile).read()
|
Jp2k(jfile)[:]
|
||||||
self.assertTrue(True)
|
self.assertTrue(True)
|
||||||
|
|
||||||
def test_NR_DEC_pacs_ge_j2k_30_decode(self):
|
def test_NR_DEC_pacs_ge_j2k_30_decode(self):
|
||||||
jfile = opj_data_file('input/nonregression/pacs.ge.j2k')
|
jfile = opj_data_file('input/nonregression/pacs.ge.j2k')
|
||||||
Jp2k(jfile).read()
|
Jp2k(jfile)[:]
|
||||||
self.assertTrue(True)
|
self.assertTrue(True)
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -317,14 +294,14 @@ class TestSuiteWarns(MetadataBase):
|
||||||
with self.assertWarns(UserWarning):
|
with self.assertWarns(UserWarning):
|
||||||
# Bad compatibility list item.
|
# Bad compatibility list item.
|
||||||
jp2k = Jp2k(jfile)
|
jp2k = Jp2k(jfile)
|
||||||
jpdata = jp2k.read()
|
jpdata = jp2k[:]
|
||||||
self.assertEqual(jpdata.shape, (512, 768, 3))
|
self.assertEqual(jpdata.shape, (512, 768, 3))
|
||||||
|
|
||||||
def test_ETS_JP2_file2(self):
|
def test_ETS_JP2_file2(self):
|
||||||
jfile = opj_data_file('input/conformance/file2.jp2')
|
jfile = opj_data_file('input/conformance/file2.jp2')
|
||||||
with self.assertWarns(UserWarning):
|
with self.assertWarns(UserWarning):
|
||||||
jp2k = Jp2k(jfile)
|
jp2k = Jp2k(jfile)
|
||||||
jpdata = jp2k.read()
|
jpdata = jp2k[:]
|
||||||
self.assertEqual(jpdata.shape, (640, 480, 3))
|
self.assertEqual(jpdata.shape, (640, 480, 3))
|
||||||
|
|
||||||
@unittest.skipIf(glymur.version.openjpeg_version_tuple[0] < 2,
|
@unittest.skipIf(glymur.version.openjpeg_version_tuple[0] < 2,
|
||||||
|
|
@ -342,7 +319,7 @@ class TestSuiteWarns(MetadataBase):
|
||||||
jfile = opj_data_file('input/conformance/file4.jp2')
|
jfile = opj_data_file('input/conformance/file4.jp2')
|
||||||
with self.assertWarns(UserWarning):
|
with self.assertWarns(UserWarning):
|
||||||
jp2k = Jp2k(jfile)
|
jp2k = Jp2k(jfile)
|
||||||
jpdata = jp2k.read()
|
jpdata = jp2k[:]
|
||||||
self.assertEqual(jpdata.shape, (512, 768))
|
self.assertEqual(jpdata.shape, (512, 768))
|
||||||
|
|
||||||
def test_ETS_JP2_file5(self):
|
def test_ETS_JP2_file5(self):
|
||||||
|
|
@ -351,42 +328,45 @@ class TestSuiteWarns(MetadataBase):
|
||||||
# There's a warning for an unknown compatibility entry.
|
# There's a warning for an unknown compatibility entry.
|
||||||
# Ignore it here.
|
# Ignore it here.
|
||||||
jp2k = Jp2k(jfile)
|
jp2k = Jp2k(jfile)
|
||||||
jpdata = jp2k.read()
|
jpdata = jp2k[:]
|
||||||
self.assertEqual(jpdata.shape, (512, 768, 3))
|
self.assertEqual(jpdata.shape, (512, 768, 3))
|
||||||
|
|
||||||
def test_ETS_JP2_file6(self):
|
def test_ETS_JP2_file6(self):
|
||||||
jfile = opj_data_file('input/conformance/file6.jp2')
|
jfile = opj_data_file('input/conformance/file6.jp2')
|
||||||
with self.assertWarns(UserWarning):
|
with self.assertWarns(UserWarning):
|
||||||
jp2k = Jp2k(jfile)
|
jp2k = Jp2k(jfile)
|
||||||
jpdata = jp2k.read()
|
jpdata = jp2k[:]
|
||||||
self.assertEqual(jpdata.shape, (512, 768))
|
self.assertEqual(jpdata.shape, (512, 768))
|
||||||
|
|
||||||
def test_ETS_JP2_file7(self):
|
def test_ETS_JP2_file7(self):
|
||||||
jfile = opj_data_file('input/conformance/file7.jp2')
|
jfile = opj_data_file('input/conformance/file7.jp2')
|
||||||
with self.assertWarns(UserWarning):
|
with self.assertWarns(UserWarning):
|
||||||
jp2k = Jp2k(jfile)
|
jp2k = Jp2k(jfile)
|
||||||
jpdata = jp2k.read()
|
jpdata = jp2k[:]
|
||||||
self.assertEqual(jpdata.shape, (640, 480, 3))
|
self.assertEqual(jpdata.shape, (640, 480, 3))
|
||||||
|
|
||||||
def test_ETS_JP2_file8(self):
|
def test_ETS_JP2_file8(self):
|
||||||
jfile = opj_data_file('input/conformance/file8.jp2')
|
jfile = opj_data_file('input/conformance/file8.jp2')
|
||||||
with self.assertWarns(UserWarning):
|
with self.assertWarns(UserWarning):
|
||||||
jp2k = Jp2k(jfile)
|
jp2k = Jp2k(jfile)
|
||||||
jpdata = jp2k.read()
|
jpdata = jp2k[:]
|
||||||
self.assertEqual(jpdata.shape, (400, 700))
|
self.assertEqual(jpdata.shape, (400, 700))
|
||||||
|
|
||||||
def test_ETS_JP2_file9(self):
|
def test_ETS_JP2_file9(self):
|
||||||
jfile = opj_data_file('input/conformance/file9.jp2')
|
jfile = opj_data_file('input/conformance/file9.jp2')
|
||||||
with self.assertWarns(UserWarning):
|
with self.assertWarns(UserWarning):
|
||||||
jp2k = Jp2k(jfile)
|
jp2k = Jp2k(jfile)
|
||||||
jpdata = jp2k.read()
|
jpdata = jp2k[:]
|
||||||
self.assertEqual(jpdata.shape, (512, 768, 3))
|
self.assertEqual(jpdata.shape, (512, 768, 3))
|
||||||
|
|
||||||
def test_NR_broken_jp2_dump(self):
|
def test_NR_broken1_jp2_dump(self):
|
||||||
jfile = opj_data_file('input/nonregression/broken.jp2')
|
jfile = opj_data_file('input/nonregression/broken1.jp2')
|
||||||
|
|
||||||
with self.assertWarns(UserWarning):
|
# The colr box has a ridiculously incorrect box length.
|
||||||
# colr box has bad length.
|
regex = re.compile(r'''b'colr'\sbox\shas\sincorrect\sbox\slength\s
|
||||||
|
\(\d+\)''',
|
||||||
|
re.VERBOSE)
|
||||||
|
with self.assertWarnsRegex(UserWarning, regex):
|
||||||
jp2 = Jp2k(jfile)
|
jp2 = Jp2k(jfile)
|
||||||
|
|
||||||
ids = [box.box_id for box in jp2.box]
|
ids = [box.box_id for box in jp2.box]
|
||||||
|
|
@ -405,23 +385,24 @@ class TestSuiteWarns(MetadataBase):
|
||||||
expected = ColourSpecificationBox(colorspace=glymur.core.SRGB)
|
expected = ColourSpecificationBox(colorspace=glymur.core.SRGB)
|
||||||
self.verifyColourSpecificationBox(jp2.box[2].box[1], expected)
|
self.verifyColourSpecificationBox(jp2.box[2].box[1], expected)
|
||||||
|
|
||||||
c = jp2.box[3].main_header
|
c = jp2.box[3].codestream
|
||||||
|
|
||||||
ids = [x.marker_id for x in c.segment]
|
ids = [x.marker_id for x in c.segment]
|
||||||
expected = ['SOC', 'SIZ', 'CME', 'COD', 'QCD', 'QCC', 'QCC']
|
expected = ['SOC', 'SIZ', 'CME', 'COD', 'QCD', 'QCC', 'QCC']
|
||||||
self.assertEqual(ids, expected)
|
self.assertEqual(ids, expected)
|
||||||
|
|
||||||
kwargs = {'rsiz': 0, 'xysiz': (203, 152), 'xyosiz': (0, 0),
|
kwargs = {'rsiz': 0, 'xysiz': (203, 152), 'xyosiz': (0, 0),
|
||||||
'xytsiz': (203, 152), 'xytosiz': (0, 0), 'bitdepth': (8, 8, 8),
|
'xytsiz': (203, 152), 'xytosiz': (0, 0),
|
||||||
'signed': (False, False, False),
|
'bitdepth': (8, 8, 8),
|
||||||
'xyrsiz': [(1, 1, 1), (1, 1, 1)]}
|
'signed': (False, False, False),
|
||||||
|
'xyrsiz': [(1, 1, 1), (1, 1, 1)]}
|
||||||
self.verifySizSegment(c.segment[1],
|
self.verifySizSegment(c.segment[1],
|
||||||
glymur.codestream.SIZsegment(**kwargs))
|
glymur.codestream.SIZsegment(**kwargs))
|
||||||
|
|
||||||
pargs = (glymur.core.RCME_ISO_8859_1,
|
pargs = (glymur.core.RCME_ISO_8859_1,
|
||||||
"Creator: JasPer Version 1.701.0".encode())
|
"Creator: JasPer Version 1.701.0".encode())
|
||||||
self.verifyCMEsegment(c.segment[2],
|
self.verifyCMEsegment(c.segment[2],
|
||||||
glymur.codestream.CMEsegment(*pargs))
|
glymur.codestream.CMEsegment(*pargs))
|
||||||
|
|
||||||
# COD: Coding style default
|
# COD: Coding style default
|
||||||
self.assertFalse(c.segment[3].scod & 2) # no sop
|
self.assertFalse(c.segment[3].scod & 2) # no sop
|
||||||
|
|
@ -433,7 +414,7 @@ class TestSuiteWarns(MetadataBase):
|
||||||
self.assertEqual(tuple(c.segment[3].code_block_size),
|
self.assertEqual(tuple(c.segment[3].code_block_size),
|
||||||
(64, 64)) # cblk
|
(64, 64)) # cblk
|
||||||
self.verify_codeblock_style(c.segment[3].spcod[7],
|
self.verify_codeblock_style(c.segment[3].spcod[7],
|
||||||
[False, False, False, False, False, False])
|
[False, False, False, False, False, False])
|
||||||
self.assertEqual(c.segment[3].spcod[8],
|
self.assertEqual(c.segment[3].spcod[8],
|
||||||
glymur.core.WAVELET_XFORM_5X3_REVERSIBLE)
|
glymur.core.WAVELET_XFORM_5X3_REVERSIBLE)
|
||||||
self.assertEqual(len(c.segment[3].spcod), 9)
|
self.assertEqual(len(c.segment[3].spcod), 9)
|
||||||
|
|
@ -469,19 +450,19 @@ class TestSuiteWarns(MetadataBase):
|
||||||
jfile = opj_data_file('input/nonregression/orb-blue10-lin-jp2.jp2')
|
jfile = opj_data_file('input/nonregression/orb-blue10-lin-jp2.jp2')
|
||||||
with self.assertWarns(UserWarning):
|
with self.assertWarns(UserWarning):
|
||||||
# This file has an invalid ICC profile
|
# This file has an invalid ICC profile
|
||||||
Jp2k(jfile).read()
|
Jp2k(jfile)[:]
|
||||||
self.assertTrue(True)
|
self.assertTrue(True)
|
||||||
|
|
||||||
def test_NR_DEC_orb_blue_win_jp2_26_decode(self):
|
def test_NR_DEC_orb_blue_win_jp2_26_decode(self):
|
||||||
jfile = opj_data_file('input/nonregression/orb-blue10-win-jp2.jp2')
|
jfile = opj_data_file('input/nonregression/orb-blue10-win-jp2.jp2')
|
||||||
with self.assertWarns(UserWarning):
|
with self.assertWarns(UserWarning):
|
||||||
Jp2k(jfile).read()
|
Jp2k(jfile)[:]
|
||||||
self.assertTrue(True)
|
self.assertTrue(True)
|
||||||
|
|
||||||
|
|
||||||
@unittest.skipIf(OPJ_DATA_ROOT is None,
|
@unittest.skipIf(OPJ_DATA_ROOT is None,
|
||||||
"OPJ_DATA_ROOT environment variable not set")
|
"OPJ_DATA_ROOT environment variable not set")
|
||||||
@unittest.skipIf(glymur.version.openjpeg_version_tuple[0] == 1,
|
@unittest.skipIf(glymur.version.openjpeg_version_tuple[0] != 2,
|
||||||
"Feature not supported in glymur until openjpeg 2.0")
|
"Feature not supported in glymur until openjpeg 2.0")
|
||||||
class TestSuiteBands(unittest.TestCase):
|
class TestSuiteBands(unittest.TestCase):
|
||||||
"""
|
"""
|
||||||
|
|
@ -576,7 +557,7 @@ class TestSuiteBands(unittest.TestCase):
|
||||||
|
|
||||||
@unittest.skipIf(OPJ_DATA_ROOT is None,
|
@unittest.skipIf(OPJ_DATA_ROOT is None,
|
||||||
"OPJ_DATA_ROOT environment variable not set")
|
"OPJ_DATA_ROOT environment variable not set")
|
||||||
@unittest.skipIf(glymur.version.openjpeg_version_tuple[0] == 1,
|
@unittest.skipIf(glymur.version.openjpeg_version_tuple[0] < 2,
|
||||||
"Tests not passing until 2.0")
|
"Tests not passing until 2.0")
|
||||||
class TestSuite2point0(unittest.TestCase):
|
class TestSuite2point0(unittest.TestCase):
|
||||||
"""Runs tests introduced in version 2.0 or that pass only in 2.0"""
|
"""Runs tests introduced in version 2.0 or that pass only in 2.0"""
|
||||||
|
|
@ -590,7 +571,7 @@ class TestSuite2point0(unittest.TestCase):
|
||||||
def test_ETS_C1P0_p0_10_j2k(self):
|
def test_ETS_C1P0_p0_10_j2k(self):
|
||||||
jfile = opj_data_file('input/conformance/p0_10.j2k')
|
jfile = opj_data_file('input/conformance/p0_10.j2k')
|
||||||
jp2k = Jp2k(jfile)
|
jp2k = Jp2k(jfile)
|
||||||
jpdata = jp2k.read(rlevel=0)
|
jpdata = jp2k[:]
|
||||||
|
|
||||||
pgxfile = opj_data_file('baseline/conformance/c1p0_10_0.pgx')
|
pgxfile = opj_data_file('baseline/conformance/c1p0_10_0.pgx')
|
||||||
pgxdata = read_pgx(pgxfile)
|
pgxdata = read_pgx(pgxfile)
|
||||||
|
|
@ -606,13 +587,16 @@ class TestSuite2point0(unittest.TestCase):
|
||||||
|
|
||||||
@unittest.skipIf(WARNING_INFRASTRUCTURE_ISSUE, WARNING_INFRASTRUCTURE_MSG)
|
@unittest.skipIf(WARNING_INFRASTRUCTURE_ISSUE, WARNING_INFRASTRUCTURE_MSG)
|
||||||
def test_NR_DEC_broken2_jp2_5_decode(self):
|
def test_NR_DEC_broken2_jp2_5_decode(self):
|
||||||
# Null pointer access
|
"""
|
||||||
|
Invalid marker ID on codestream, Null pointer access upon read.
|
||||||
|
"""
|
||||||
jfile = opj_data_file('input/nonregression/broken2.jp2')
|
jfile = opj_data_file('input/nonregression/broken2.jp2')
|
||||||
|
regex = re.compile(r'''Invalid\smarker\sid\sencountered\sat\sbyte\s
|
||||||
|
\d+\sin\scodestream:\s*"0x[a-fA-F0-9]{4}"''',
|
||||||
|
re.VERBOSE)
|
||||||
with self.assertRaises(IOError):
|
with self.assertRaises(IOError):
|
||||||
with self.assertWarns(UserWarning):
|
with self.assertWarnsRegex(UserWarning, regex):
|
||||||
# Invalid marker ID.
|
Jp2k(jfile)[:]
|
||||||
Jp2k(jfile).read()
|
|
||||||
self.assertTrue(True)
|
|
||||||
|
|
||||||
@unittest.skipIf(WARNING_INFRASTRUCTURE_ISSUE, WARNING_INFRASTRUCTURE_MSG)
|
@unittest.skipIf(WARNING_INFRASTRUCTURE_ISSUE, WARNING_INFRASTRUCTURE_MSG)
|
||||||
def test_NR_DEC_broken4_jp2_7_decode(self):
|
def test_NR_DEC_broken4_jp2_7_decode(self):
|
||||||
|
|
@ -620,7 +604,7 @@ class TestSuite2point0(unittest.TestCase):
|
||||||
with self.assertRaises(IOError):
|
with self.assertRaises(IOError):
|
||||||
with self.assertWarns(UserWarning):
|
with self.assertWarns(UserWarning):
|
||||||
# invalid number of subbands, bad marker ID
|
# invalid number of subbands, bad marker ID
|
||||||
Jp2k(jfile).read()
|
Jp2k(jfile)[:]
|
||||||
self.assertTrue(True)
|
self.assertTrue(True)
|
||||||
|
|
||||||
@unittest.skipIf(WARNING_INFRASTRUCTURE_ISSUE, WARNING_INFRASTRUCTURE_MSG)
|
@unittest.skipIf(WARNING_INFRASTRUCTURE_ISSUE, WARNING_INFRASTRUCTURE_MSG)
|
||||||
|
|
@ -632,11 +616,344 @@ class TestSuite2point0(unittest.TestCase):
|
||||||
if glymur.version.openjpeg_version_tuple[0] < 2:
|
if glymur.version.openjpeg_version_tuple[0] < 2:
|
||||||
with self.assertWarns(UserWarning):
|
with self.assertWarns(UserWarning):
|
||||||
# Incorrect warning issued about tile parts.
|
# Incorrect warning issued about tile parts.
|
||||||
Jp2k(jfile).read()
|
Jp2k(jfile)[:]
|
||||||
else:
|
else:
|
||||||
Jp2k(jfile).read()
|
Jp2k(jfile)[:]
|
||||||
self.assertTrue(True)
|
self.assertTrue(True)
|
||||||
|
|
||||||
|
|
||||||
if __name__ == "__main__":
|
@unittest.skipIf(OPJ_DATA_ROOT is None,
|
||||||
unittest.main()
|
"OPJ_DATA_ROOT environment variable not set")
|
||||||
|
@unittest.skipIf(re.match(r'''0|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
|
||||||
|
|
||||||
|
@unittest.skipIf(WARNING_INFRASTRUCTURE_ISSUE, WARNING_INFRASTRUCTURE_MSG)
|
||||||
|
def test_NR_DEC_text_GBR_jp2_29_decode(self):
|
||||||
|
jfile = opj_data_file('input/nonregression/text_GBR.jp2')
|
||||||
|
with self.assertWarns(UserWarning):
|
||||||
|
# brand is 'jp2 ', but has any icc profile.
|
||||||
|
jp2 = Jp2k(jfile)
|
||||||
|
jp2[:]
|
||||||
|
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)[:]
|
||||||
|
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)[::4, ::4]
|
||||||
|
self.assertTrue(True)
|
||||||
|
|
||||||
|
def test_NR_DEC_issue104_jpxstream_jp2_33_decode(self):
|
||||||
|
jfile = opj_data_file('input/nonregression/issue104_jpxstream.jp2')
|
||||||
|
Jp2k(jfile)[:]
|
||||||
|
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)[:]
|
||||||
|
self.assertTrue(True)
|
||||||
|
|
||||||
|
@unittest.skipIf(WARNING_INFRASTRUCTURE_ISSUE, WARNING_INFRASTRUCTURE_MSG)
|
||||||
|
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 self.assertWarns(UserWarning):
|
||||||
|
# Invalid number of resolutions.
|
||||||
|
j = Jp2k(jfile)
|
||||||
|
with self.assertRaises(IOError):
|
||||||
|
j[:]
|
||||||
|
|
||||||
|
@unittest.skipIf(WARNING_INFRASTRUCTURE_ISSUE, WARNING_INFRASTRUCTURE_MSG)
|
||||||
|
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 self.assertWarns(UserWarning):
|
||||||
|
# Invalid number of tiles.
|
||||||
|
j = Jp2k(jfile)
|
||||||
|
with self.assertRaises(IOError):
|
||||||
|
j[:]
|
||||||
|
|
||||||
|
@unittest.skipIf(WARNING_INFRASTRUCTURE_ISSUE, WARNING_INFRASTRUCTURE_MSG)
|
||||||
|
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 self.assertWarns(UserWarning):
|
||||||
|
# Invalid subsampling value
|
||||||
|
with self.assertRaises(IOError):
|
||||||
|
Jp2k(jfile)[:]
|
||||||
|
|
||||||
|
def test_NR_DEC_file_409752_jp2_40_decode(self):
|
||||||
|
jfile = opj_data_file('input/nonregression/file409752.jp2')
|
||||||
|
with self.assertRaises(RuntimeError):
|
||||||
|
Jp2k(jfile)[:]
|
||||||
|
|
||||||
|
def test_NR_DEC_issue206_image_000_jp2_42_decode(self):
|
||||||
|
jfile = opj_data_file('input/nonregression/issue206_image-000.jp2')
|
||||||
|
Jp2k(jfile)[:]
|
||||||
|
self.assertTrue(True)
|
||||||
|
|
||||||
|
def test_NR_DEC_p1_04_j2k_57_decode(self):
|
||||||
|
jfile = opj_data_file('input/conformance/p1_04.j2k')
|
||||||
|
jp2k = Jp2k(jfile)
|
||||||
|
tdata = jp2k[896:1024, 896:1024] # last tile
|
||||||
|
odata = jp2k[:]
|
||||||
|
np.testing.assert_array_equal(tdata, odata[896:1024, 896:1024])
|
||||||
|
|
||||||
|
@unittest.skipIf(WARNING_INFRASTRUCTURE_ISSUE, WARNING_INFRASTRUCTURE_MSG)
|
||||||
|
def test_NR_DEC_p1_04_j2k_57_decode_0p7_backwards_compatibility(self):
|
||||||
|
"""
|
||||||
|
0.7.x usage deprecated
|
||||||
|
"""
|
||||||
|
jfile = opj_data_file('input/conformance/p1_04.j2k')
|
||||||
|
jp2k = Jp2k(jfile)
|
||||||
|
if sys.hexversion < 0x03000000:
|
||||||
|
with warnings.catch_warnings():
|
||||||
|
# Suppress a warning due to deprecated syntax
|
||||||
|
warnings.simplefilter("ignore")
|
||||||
|
tdata = jp2k.read(tile=63) # last tile
|
||||||
|
else:
|
||||||
|
with self.assertWarns(DeprecationWarning):
|
||||||
|
tdata = jp2k.read(tile=63) # last tile
|
||||||
|
odata = jp2k[:]
|
||||||
|
np.testing.assert_array_equal(tdata, odata[896:1024, 896:1024])
|
||||||
|
|
||||||
|
@unittest.skipIf(WARNING_INFRASTRUCTURE_ISSUE, WARNING_INFRASTRUCTURE_MSG)
|
||||||
|
def test_NR_DEC_p1_04_j2k_58_decode_0p7_backwards_compatibility(self):
|
||||||
|
"""
|
||||||
|
0.7.x usage deprecated
|
||||||
|
"""
|
||||||
|
jfile = opj_data_file('input/conformance/p1_04.j2k')
|
||||||
|
jp2k = Jp2k(jfile)
|
||||||
|
if sys.hexversion < 0x03000000:
|
||||||
|
with warnings.catch_warnings():
|
||||||
|
# Suppress a warning due to deprecated syntax
|
||||||
|
tdata = jp2k.read(tile=63, rlevel=2) # last tile
|
||||||
|
else:
|
||||||
|
with self.assertWarns(DeprecationWarning):
|
||||||
|
tdata = jp2k.read(tile=63, rlevel=2) # last tile
|
||||||
|
odata = jp2k[::4, ::4]
|
||||||
|
np.testing.assert_array_equal(tdata, odata[224:256, 224:256])
|
||||||
|
|
||||||
|
def test_NR_DEC_p1_04_j2k_58_decode(self):
|
||||||
|
jfile = opj_data_file('input/conformance/p1_04.j2k')
|
||||||
|
jp2k = Jp2k(jfile)
|
||||||
|
tdata = jp2k[896:1024:4, 896:1024:4] # last tile
|
||||||
|
odata = jp2k[::4, ::4]
|
||||||
|
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[128:256, 512:640] # 2nd row, 5th column
|
||||||
|
odata = jp2k[:]
|
||||||
|
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[128:256:2, 512:640:2] # 2nd row, 5th column
|
||||||
|
odata = jp2k[::2, ::2]
|
||||||
|
np.testing.assert_array_equal(tdata, odata[64:128, 256:320])
|
||||||
|
|
||||||
|
@unittest.skipIf(WARNING_INFRASTRUCTURE_ISSUE, WARNING_INFRASTRUCTURE_MSG)
|
||||||
|
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 self.assertWarns(UserWarning):
|
||||||
|
# Invalid component number.
|
||||||
|
j = Jp2k(jfile)
|
||||||
|
with self.assertRaises(IOError):
|
||||||
|
j[:]
|
||||||
|
|
||||||
|
|
||||||
|
@unittest.skipIf(OPJ_DATA_ROOT is None,
|
||||||
|
"OPJ_DATA_ROOT environment variable not set")
|
||||||
|
@unittest.skipIf(re.match(r'''0|1|2.0.0''',
|
||||||
|
glymur.version.openjpeg_version) is not None,
|
||||||
|
"Only supported in 2.0.1 or higher")
|
||||||
|
class TestReadArea(unittest.TestCase):
|
||||||
|
"""
|
||||||
|
Runs tests introduced in version 2.0+ or that pass only in 2.0+
|
||||||
|
|
||||||
|
Specifically for read method with area parameter.
|
||||||
|
"""
|
||||||
|
@classmethod
|
||||||
|
def setUpClass(self):
|
||||||
|
|
||||||
|
jfile = opj_data_file('input/conformance/p1_04.j2k')
|
||||||
|
self.j2k = Jp2k(jfile)
|
||||||
|
self.j2k_data = self.j2k[:]
|
||||||
|
self.j2k_half_data = self.j2k[::2, ::2]
|
||||||
|
self.j2k_quarter_data = self.j2k[::4, ::4]
|
||||||
|
|
||||||
|
jfile = opj_data_file('input/conformance/p1_06.j2k')
|
||||||
|
self.j2k_p1_06 = Jp2k(jfile)
|
||||||
|
|
||||||
|
def test_NR_DEC_p1_04_j2k_43_decode(self):
|
||||||
|
actual = self.j2k[:1024, :1024]
|
||||||
|
expected = self.j2k_data
|
||||||
|
np.testing.assert_array_equal(actual, expected)
|
||||||
|
|
||||||
|
def test_NR_DEC_p1_04_j2k_44_decode(self):
|
||||||
|
actual = self.j2k[640:768, 512:640]
|
||||||
|
expected = self.j2k_data[640:768, 512:640]
|
||||||
|
np.testing.assert_array_equal(actual, expected)
|
||||||
|
|
||||||
|
def test_NR_DEC_p1_04_j2k_45_decode(self):
|
||||||
|
actual = self.j2k[896:1024, 896:1024]
|
||||||
|
expected = self.j2k_data[896:1024, 896:1024]
|
||||||
|
np.testing.assert_array_equal(actual, expected)
|
||||||
|
|
||||||
|
def test_NR_DEC_p1_04_j2k_46_decode(self):
|
||||||
|
actual = self.j2k[500:800, 100:300]
|
||||||
|
expected = self.j2k_data[500:800, 100:300]
|
||||||
|
np.testing.assert_array_equal(actual, expected)
|
||||||
|
|
||||||
|
def test_NR_DEC_p1_04_j2k_47_decode(self):
|
||||||
|
actual = self.j2k[520:600, 260:360]
|
||||||
|
expected = self.j2k_data[520:600, 260:360]
|
||||||
|
np.testing.assert_array_equal(actual, expected)
|
||||||
|
|
||||||
|
def test_NR_DEC_p1_04_j2k_48_decode(self):
|
||||||
|
actual = self.j2k[520:660, 260:360]
|
||||||
|
expected = self.j2k_data[520:660, 260:360]
|
||||||
|
np.testing.assert_array_equal(actual, expected)
|
||||||
|
|
||||||
|
def test_NR_DEC_p1_04_j2k_49_decode(self):
|
||||||
|
actual = self.j2k[520:600, 360:400]
|
||||||
|
expected = self.j2k_data[520:600, 360:400]
|
||||||
|
np.testing.assert_array_equal(actual, expected)
|
||||||
|
|
||||||
|
def test_NR_DEC_p1_04_j2k_50_decode(self):
|
||||||
|
actual = self.j2k[:1024:4, :1024:4]
|
||||||
|
expected = self.j2k_quarter_data
|
||||||
|
np.testing.assert_array_equal(actual, expected)
|
||||||
|
|
||||||
|
def test_NR_DEC_p1_04_j2k_51_decode(self):
|
||||||
|
actual = self.j2k[640:768:4, 512:640:4]
|
||||||
|
expected = self.j2k_quarter_data[160:192, 128:160]
|
||||||
|
np.testing.assert_array_equal(actual, expected)
|
||||||
|
|
||||||
|
def test_NR_DEC_p1_04_j2k_52_decode(self):
|
||||||
|
actual = self.j2k[896:1024:4, 896:1024:4]
|
||||||
|
expected = self.j2k_quarter_data[224:352, 224:352]
|
||||||
|
np.testing.assert_array_equal(actual, expected)
|
||||||
|
|
||||||
|
def test_NR_DEC_p1_04_j2k_53_decode(self):
|
||||||
|
actual = self.j2k[500:800:4, 100:300:4]
|
||||||
|
expected = self.j2k_quarter_data[125:200, 25:75]
|
||||||
|
np.testing.assert_array_equal(actual, expected)
|
||||||
|
|
||||||
|
def test_NR_DEC_p1_04_j2k_54_decode(self):
|
||||||
|
actual = self.j2k[520:600:4, 260:360:4]
|
||||||
|
expected = self.j2k_quarter_data[130:150, 65:90]
|
||||||
|
np.testing.assert_array_equal(actual, expected)
|
||||||
|
|
||||||
|
def test_NR_DEC_p1_04_j2k_55_decode(self):
|
||||||
|
actual = self.j2k[520:660:4, 260:360:4]
|
||||||
|
expected = self.j2k_quarter_data[130:165, 65:90]
|
||||||
|
np.testing.assert_array_equal(actual, expected)
|
||||||
|
|
||||||
|
def test_NR_DEC_p1_04_j2k_56_decode(self):
|
||||||
|
actual = self.j2k[520:600:4, 360:400:4]
|
||||||
|
expected = self.j2k_quarter_data[130:150, 90:100]
|
||||||
|
np.testing.assert_array_equal(actual, expected)
|
||||||
|
|
||||||
|
def test_NR_DEC_p1_06_j2k_70_decode(self):
|
||||||
|
actual = self.j2k_p1_06[9:12:2, 9:12:2]
|
||||||
|
self.assertEqual(actual.shape, (1, 1, 3))
|
||||||
|
|
||||||
|
def test_NR_DEC_p1_06_j2k_71_decode(self):
|
||||||
|
actual = self.j2k_p1_06[10:12:2, 4:10:2]
|
||||||
|
self.assertEqual(actual.shape, (1, 3, 3))
|
||||||
|
|
||||||
|
def test_NR_DEC_p1_06_j2k_72_decode(self):
|
||||||
|
ssdata = self.j2k_p1_06[3:9:2, 3:9:2]
|
||||||
|
self.assertEqual(ssdata.shape, (3, 3, 3))
|
||||||
|
|
||||||
|
def test_NR_DEC_p1_06_j2k_73_decode(self):
|
||||||
|
ssdata = self.j2k_p1_06[4:7:2, 4:7:2]
|
||||||
|
self.assertEqual(ssdata.shape, (2, 2, 3))
|
||||||
|
|
||||||
|
def test_NR_DEC_p1_06_j2k_74_decode(self):
|
||||||
|
ssdata = self.j2k_p1_06[4:5:2, 4:5:2]
|
||||||
|
self.assertEqual(ssdata.shape, (1, 1, 3))
|
||||||
|
|
||||||
|
def test_NR_DEC_p1_06_j2k_75_decode(self):
|
||||||
|
# Image size would be 0 x 0.
|
||||||
|
with self.assertRaises((IOError, OSError)):
|
||||||
|
self.j2k_p1_06[9:12:4, 9:12:4]
|
||||||
|
|
||||||
|
def test_NR_DEC_p0_04_j2k_85_decode(self):
|
||||||
|
actual = self.j2k[:256, :256]
|
||||||
|
expected = self.j2k_data[:256, :256]
|
||||||
|
np.testing.assert_array_equal(actual, expected)
|
||||||
|
|
||||||
|
def test_NR_DEC_p0_04_j2k_86_decode(self):
|
||||||
|
actual = self.j2k[:128, 128:256]
|
||||||
|
expected = self.j2k_data[:128, 128:256]
|
||||||
|
np.testing.assert_array_equal(actual, expected)
|
||||||
|
|
||||||
|
def test_NR_DEC_p0_04_j2k_87_decode(self):
|
||||||
|
actual = self.j2k[10:200, 50:120]
|
||||||
|
expected = self.j2k_data[10:200, 50:120]
|
||||||
|
np.testing.assert_array_equal(actual, expected)
|
||||||
|
|
||||||
|
def test_NR_DEC_p0_04_j2k_88_decode(self):
|
||||||
|
actual = self.j2k[150:210, 10:190]
|
||||||
|
expected = self.j2k_data[150:210, 10:190]
|
||||||
|
np.testing.assert_array_equal(actual, expected)
|
||||||
|
|
||||||
|
def test_NR_DEC_p0_04_j2k_89_decode(self):
|
||||||
|
actual = self.j2k[80:150, 100:200]
|
||||||
|
expected = self.j2k_data[80:150, 100:200]
|
||||||
|
np.testing.assert_array_equal(actual, expected)
|
||||||
|
|
||||||
|
def test_NR_DEC_p0_04_j2k_90_decode(self):
|
||||||
|
actual = self.j2k[20:50, 150:200]
|
||||||
|
expected = self.j2k_data[20:50, 150:200]
|
||||||
|
np.testing.assert_array_equal(actual, expected)
|
||||||
|
|
||||||
|
def test_NR_DEC_p0_04_j2k_91_decode(self):
|
||||||
|
actual = self.j2k[:256:4, :256:4]
|
||||||
|
expected = self.j2k_quarter_data[0:64, 0:64]
|
||||||
|
np.testing.assert_array_equal(actual, expected)
|
||||||
|
|
||||||
|
def test_NR_DEC_p0_04_j2k_92_decode(self):
|
||||||
|
actual = self.j2k[:128:4, 128:256:4]
|
||||||
|
expected = self.j2k_quarter_data[:32, 32:64]
|
||||||
|
np.testing.assert_array_equal(actual, expected)
|
||||||
|
|
||||||
|
def test_NR_DEC_p0_04_j2k_93_decode(self):
|
||||||
|
actual = self.j2k[10:200:4, 50:120:4]
|
||||||
|
expected = self.j2k_quarter_data[3:50, 13:30]
|
||||||
|
np.testing.assert_array_equal(actual, expected)
|
||||||
|
|
||||||
|
def test_NR_DEC_p0_04_j2k_94_decode(self):
|
||||||
|
actual = self.j2k[150:210:4, 10:190:4]
|
||||||
|
expected = self.j2k_quarter_data[38:53, 3:48]
|
||||||
|
np.testing.assert_array_equal(actual, expected)
|
||||||
|
|
||||||
|
def test_NR_DEC_p0_04_j2k_95_decode(self):
|
||||||
|
actual = self.j2k[80:150:4, 100:200:4]
|
||||||
|
expected = self.j2k_quarter_data[20:38, 25:50]
|
||||||
|
np.testing.assert_array_equal(actual, expected)
|
||||||
|
|
||||||
|
def test_NR_DEC_p0_04_j2k_96_decode(self):
|
||||||
|
actual = self.j2k[20:50:4, 150:200:4]
|
||||||
|
expected = self.j2k_quarter_data[5:13, 38:50]
|
||||||
|
np.testing.assert_array_equal(actual, expected)
|
||||||
|
|
|
||||||
|
|
@ -1,342 +0,0 @@
|
||||||
"""
|
|
||||||
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 numpy as np
|
|
||||||
|
|
||||||
from glymur import Jp2k
|
|
||||||
import glymur
|
|
||||||
|
|
||||||
from .fixtures import OPJ_DATA_ROOT
|
|
||||||
from .fixtures import WARNING_INFRASTRUCTURE_ISSUE, WARNING_INFRASTRUCTURE_MSG
|
|
||||||
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
|
|
||||||
|
|
||||||
@unittest.skipIf(WARNING_INFRASTRUCTURE_ISSUE, WARNING_INFRASTRUCTURE_MSG)
|
|
||||||
def test_NR_DEC_text_GBR_jp2_29_decode(self):
|
|
||||||
jfile = opj_data_file('input/nonregression/text_GBR.jp2')
|
|
||||||
with self.assertWarns(UserWarning):
|
|
||||||
# brand is 'jp2 ', but has any icc profile.
|
|
||||||
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)
|
|
||||||
|
|
||||||
@unittest.skipIf(WARNING_INFRASTRUCTURE_ISSUE, WARNING_INFRASTRUCTURE_MSG)
|
|
||||||
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 self.assertWarns(UserWarning):
|
|
||||||
# Invalid number of resolutions.
|
|
||||||
j = Jp2k(jfile)
|
|
||||||
with self.assertRaises(IOError):
|
|
||||||
j.read()
|
|
||||||
|
|
||||||
@unittest.skipIf(WARNING_INFRASTRUCTURE_ISSUE, WARNING_INFRASTRUCTURE_MSG)
|
|
||||||
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 self.assertWarns(UserWarning):
|
|
||||||
# Invalid number of tiles.
|
|
||||||
j = Jp2k(jfile)
|
|
||||||
with self.assertRaises(IOError):
|
|
||||||
j.read()
|
|
||||||
|
|
||||||
@unittest.skipIf(WARNING_INFRASTRUCTURE_ISSUE, WARNING_INFRASTRUCTURE_MSG)
|
|
||||||
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 self.assertWarns(UserWarning):
|
|
||||||
# Invalid subsampling value
|
|
||||||
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_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])
|
|
||||||
|
|
||||||
@unittest.skipIf(WARNING_INFRASTRUCTURE_ISSUE, WARNING_INFRASTRUCTURE_MSG)
|
|
||||||
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 self.assertWarns(UserWarning):
|
|
||||||
# Invalid component number.
|
|
||||||
j = Jp2k(jfile)
|
|
||||||
with self.assertRaises(IOError):
|
|
||||||
j.read()
|
|
||||||
|
|
||||||
@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 TestReadArea(unittest.TestCase):
|
|
||||||
"""
|
|
||||||
Runs tests introduced in version 2.0+ or that pass only in 2.0+
|
|
||||||
|
|
||||||
Specifically for read method with area parameter.
|
|
||||||
"""
|
|
||||||
@classmethod
|
|
||||||
def setUpClass(self):
|
|
||||||
|
|
||||||
jfile = opj_data_file('input/conformance/p1_04.j2k')
|
|
||||||
self.j2k = Jp2k(jfile)
|
|
||||||
self.j2k_data = self.j2k.read()
|
|
||||||
self.j2k_half_data = self.j2k.read(rlevel=1)
|
|
||||||
self.j2k_quarter_data = self.j2k.read(rlevel=2)
|
|
||||||
|
|
||||||
jfile = opj_data_file('input/conformance/p1_06.j2k')
|
|
||||||
self.j2k_p1_06 = Jp2k(jfile)
|
|
||||||
|
|
||||||
def test_NR_DEC_p1_04_j2k_43_decode(self):
|
|
||||||
actual = self.j2k.read(area=(0, 0, 1024, 1024))
|
|
||||||
expected = self.j2k_data
|
|
||||||
np.testing.assert_array_equal(actual, expected)
|
|
||||||
|
|
||||||
def test_NR_DEC_p1_04_j2k_44_decode(self):
|
|
||||||
actual = self.j2k.read(area=(640, 512, 768, 640))
|
|
||||||
expected = self.j2k_data[640:768, 512:640]
|
|
||||||
np.testing.assert_array_equal(actual, expected)
|
|
||||||
|
|
||||||
def test_NR_DEC_p1_04_j2k_45_decode(self):
|
|
||||||
actual = self.j2k.read(area=(896, 896, 1024, 1024))
|
|
||||||
expected = self.j2k_data[896:1024, 896:1024]
|
|
||||||
np.testing.assert_array_equal(actual, expected)
|
|
||||||
|
|
||||||
def test_NR_DEC_p1_04_j2k_46_decode(self):
|
|
||||||
actual = self.j2k.read(area=(500, 100, 800, 300))
|
|
||||||
expected = self.j2k_data[500:800, 100:300]
|
|
||||||
np.testing.assert_array_equal(actual, expected)
|
|
||||||
|
|
||||||
def test_NR_DEC_p1_04_j2k_47_decode(self):
|
|
||||||
actual = self.j2k.read(area=(520, 260, 600, 360))
|
|
||||||
expected = self.j2k_data[520:600, 260:360]
|
|
||||||
np.testing.assert_array_equal(actual, expected)
|
|
||||||
|
|
||||||
def test_NR_DEC_p1_04_j2k_48_decode(self):
|
|
||||||
actual = self.j2k.read(area=(520, 260, 660, 360))
|
|
||||||
expected = self.j2k_data[520:660, 260:360]
|
|
||||||
np.testing.assert_array_equal(actual, expected)
|
|
||||||
|
|
||||||
def test_NR_DEC_p1_04_j2k_49_decode(self):
|
|
||||||
actual = self.j2k.read(area=(520, 360, 600, 400))
|
|
||||||
expected = self.j2k_data[520:600, 360:400]
|
|
||||||
np.testing.assert_array_equal(actual, expected)
|
|
||||||
|
|
||||||
def test_NR_DEC_p1_04_j2k_50_decode(self):
|
|
||||||
actual = self.j2k.read(area=(0, 0, 1024, 1024), rlevel=2)
|
|
||||||
expected = self.j2k_quarter_data
|
|
||||||
np.testing.assert_array_equal(actual, expected)
|
|
||||||
|
|
||||||
def test_NR_DEC_p1_04_j2k_51_decode(self):
|
|
||||||
actual = self.j2k.read(area=(640, 512, 768, 640), rlevel=2)
|
|
||||||
expected = self.j2k_quarter_data[160:192, 128:160]
|
|
||||||
np.testing.assert_array_equal(actual, expected)
|
|
||||||
|
|
||||||
def test_NR_DEC_p1_04_j2k_52_decode(self):
|
|
||||||
actual = self.j2k.read(area=(896, 896, 1024, 1024), rlevel=2)
|
|
||||||
expected = self.j2k_quarter_data[224:352, 224:352]
|
|
||||||
np.testing.assert_array_equal(actual, expected)
|
|
||||||
|
|
||||||
def test_NR_DEC_p1_04_j2k_53_decode(self):
|
|
||||||
actual = self.j2k.read(area=(500, 100, 800, 300), rlevel=2)
|
|
||||||
expected = self.j2k_quarter_data[125:200, 25:75]
|
|
||||||
np.testing.assert_array_equal(actual, expected)
|
|
||||||
|
|
||||||
def test_NR_DEC_p1_04_j2k_54_decode(self):
|
|
||||||
actual = self.j2k.read(area=(520, 260, 600, 360), rlevel=2)
|
|
||||||
expected = self.j2k_quarter_data[130:150, 65:90]
|
|
||||||
np.testing.assert_array_equal(actual, expected)
|
|
||||||
|
|
||||||
def test_NR_DEC_p1_04_j2k_55_decode(self):
|
|
||||||
actual = self.j2k.read(area=(520, 260, 660, 360), rlevel=2)
|
|
||||||
expected = self.j2k_quarter_data[130:165, 65:90]
|
|
||||||
np.testing.assert_array_equal(actual, expected)
|
|
||||||
|
|
||||||
def test_NR_DEC_p1_04_j2k_56_decode(self):
|
|
||||||
actual = self.j2k.read(area=(520, 360, 600, 400), rlevel=2)
|
|
||||||
expected = self.j2k_quarter_data[130:150, 90:100]
|
|
||||||
np.testing.assert_array_equal(actual, expected)
|
|
||||||
|
|
||||||
def test_NR_DEC_p1_06_j2k_70_decode(self):
|
|
||||||
actual = self.j2k_p1_06.read(area=(9, 9, 12, 12), rlevel=1)
|
|
||||||
self.assertEqual(actual.shape, (1, 1, 3))
|
|
||||||
|
|
||||||
def test_NR_DEC_p1_06_j2k_71_decode(self):
|
|
||||||
actual = self.j2k_p1_06.read(area=(10, 4, 12, 10), rlevel=1)
|
|
||||||
self.assertEqual(actual.shape, (1, 3, 3))
|
|
||||||
|
|
||||||
def test_NR_DEC_p1_06_j2k_72_decode(self):
|
|
||||||
ssdata = self.j2k_p1_06.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):
|
|
||||||
ssdata = self.j2k_p1_06.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):
|
|
||||||
ssdata = self.j2k_p1_06.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.
|
|
||||||
with self.assertRaises((IOError, OSError)):
|
|
||||||
self.j2k_p1_06.read(area=(9, 9, 12, 12), rlevel=2)
|
|
||||||
|
|
||||||
def test_NR_DEC_p0_04_j2k_85_decode(self):
|
|
||||||
actual = self.j2k.read(area=(0, 0, 256, 256))
|
|
||||||
expected = self.j2k_data[:256, :256]
|
|
||||||
np.testing.assert_array_equal(actual, expected)
|
|
||||||
|
|
||||||
def test_NR_DEC_p0_04_j2k_86_decode(self):
|
|
||||||
actual = self.j2k.read(area=(0, 128, 128, 256))
|
|
||||||
expected = self.j2k_data[:128, 128:256]
|
|
||||||
np.testing.assert_array_equal(actual, expected)
|
|
||||||
|
|
||||||
def test_NR_DEC_p0_04_j2k_87_decode(self):
|
|
||||||
actual = self.j2k.read(area=(10, 50, 200, 120))
|
|
||||||
expected = self.j2k_data[10:200, 50:120]
|
|
||||||
np.testing.assert_array_equal(actual, expected)
|
|
||||||
|
|
||||||
def test_NR_DEC_p0_04_j2k_88_decode(self):
|
|
||||||
actual = self.j2k.read(area=(150, 10, 210, 190))
|
|
||||||
expected = self.j2k_data[150:210, 10:190]
|
|
||||||
np.testing.assert_array_equal(actual, expected)
|
|
||||||
|
|
||||||
def test_NR_DEC_p0_04_j2k_89_decode(self):
|
|
||||||
actual = self.j2k.read(area=(80, 100, 150, 200))
|
|
||||||
expected = self.j2k_data[80:150, 100:200]
|
|
||||||
np.testing.assert_array_equal(actual, expected)
|
|
||||||
|
|
||||||
def test_NR_DEC_p0_04_j2k_90_decode(self):
|
|
||||||
actual = self.j2k.read(area=(20, 150, 50, 200))
|
|
||||||
expected = self.j2k_data[20:50, 150:200]
|
|
||||||
np.testing.assert_array_equal(actual, expected)
|
|
||||||
|
|
||||||
def test_NR_DEC_p0_04_j2k_91_decode(self):
|
|
||||||
actual = self.j2k.read(area=(0, 0, 256, 256), rlevel=2)
|
|
||||||
expected = self.j2k_quarter_data[0:64, 0:64]
|
|
||||||
np.testing.assert_array_equal(actual, expected)
|
|
||||||
|
|
||||||
def test_NR_DEC_p0_04_j2k_92_decode(self):
|
|
||||||
actual = self.j2k.read(area=(0, 128, 128, 256), rlevel=2)
|
|
||||||
expected = self.j2k_quarter_data[:32, 32:64]
|
|
||||||
np.testing.assert_array_equal(actual, expected)
|
|
||||||
|
|
||||||
def test_NR_DEC_p0_04_j2k_93_decode(self):
|
|
||||||
actual = self.j2k.read(area=(10, 50, 200, 120), rlevel=2)
|
|
||||||
expected = self.j2k_quarter_data[3:50, 13:30]
|
|
||||||
np.testing.assert_array_equal(actual, expected)
|
|
||||||
|
|
||||||
def test_NR_DEC_p0_04_j2k_94_decode(self):
|
|
||||||
actual = self.j2k.read(area=(150, 10, 210, 190), rlevel=2)
|
|
||||||
expected = self.j2k_quarter_data[38:53, 3:48]
|
|
||||||
np.testing.assert_array_equal(actual, expected)
|
|
||||||
|
|
||||||
def test_NR_DEC_p0_04_j2k_95_decode(self):
|
|
||||||
actual = self.j2k.read(area=(80, 100, 150, 200), rlevel=2)
|
|
||||||
expected = self.j2k_quarter_data[20:38, 25:50]
|
|
||||||
np.testing.assert_array_equal(actual, expected)
|
|
||||||
|
|
||||||
def test_NR_DEC_p0_04_j2k_96_decode(self):
|
|
||||||
actual = self.j2k.read(area=(20, 150, 50, 200), rlevel=2)
|
|
||||||
expected = self.j2k_quarter_data[5:13, 38:50]
|
|
||||||
np.testing.assert_array_equal(actual, expected)
|
|
||||||
File diff suppressed because it is too large
Load diff
|
|
@ -2,15 +2,8 @@
|
||||||
The tests here do not correspond directly to the OpenJPEG test suite, but
|
The tests here do not correspond directly to the OpenJPEG test suite, but
|
||||||
seem like logical negative tests to add.
|
seem like logical negative tests to add.
|
||||||
"""
|
"""
|
||||||
# E1101: assertWarns introduced in python 3.2
|
|
||||||
# pylint: disable=E1101
|
|
||||||
|
|
||||||
# R0904: Not too many methods in unittest.
|
|
||||||
# pylint: disable=R0904
|
|
||||||
|
|
||||||
import os
|
import os
|
||||||
import re
|
import re
|
||||||
import sys
|
|
||||||
import tempfile
|
import tempfile
|
||||||
import unittest
|
import unittest
|
||||||
|
|
||||||
|
|
@ -24,6 +17,7 @@ from .fixtures import OPJ_DATA_ROOT, opj_data_file, read_image
|
||||||
from .fixtures import NO_READ_BACKEND, NO_READ_BACKEND_MSG
|
from .fixtures import NO_READ_BACKEND, NO_READ_BACKEND_MSG
|
||||||
from .fixtures import NO_SKIMAGE_FREEIMAGE_SUPPORT
|
from .fixtures import NO_SKIMAGE_FREEIMAGE_SUPPORT
|
||||||
from .fixtures import WARNING_INFRASTRUCTURE_ISSUE, WARNING_INFRASTRUCTURE_MSG
|
from .fixtures import WARNING_INFRASTRUCTURE_ISSUE, WARNING_INFRASTRUCTURE_MSG
|
||||||
|
from . import fixtures
|
||||||
|
|
||||||
from glymur import Jp2k
|
from glymur import Jp2k
|
||||||
import glymur
|
import glymur
|
||||||
|
|
@ -31,7 +25,7 @@ import glymur
|
||||||
|
|
||||||
@unittest.skipIf(OPJ_DATA_ROOT is None,
|
@unittest.skipIf(OPJ_DATA_ROOT is None,
|
||||||
"OPJ_OPJ_DATA_ROOT environment variable not set")
|
"OPJ_OPJ_DATA_ROOT environment variable not set")
|
||||||
class TestSuiteNegative(unittest.TestCase):
|
class TestSuiteNegativeRead(unittest.TestCase):
|
||||||
"""Test suite for certain negative tests from openjpeg suite."""
|
"""Test suite for certain negative tests from openjpeg suite."""
|
||||||
|
|
||||||
def setUp(self):
|
def setUp(self):
|
||||||
|
|
@ -41,33 +35,6 @@ class TestSuiteNegative(unittest.TestCase):
|
||||||
def tearDown(self):
|
def tearDown(self):
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
|
||||||
@unittest.skipIf(NO_SKIMAGE_FREEIMAGE_SUPPORT,
|
|
||||||
"Cannot read input image without scikit-image/freeimage")
|
|
||||||
@unittest.skipIf(os.name == "nt", "Temporary file issue on window.")
|
|
||||||
def test_cinema2K_bad_frame_rate(self):
|
|
||||||
"""Cinema2k frame rate must be either 24 or 48."""
|
|
||||||
relfile = 'input/nonregression/X_5_2K_24_235_CBR_STEM24_000.tif'
|
|
||||||
infile = opj_data_file(relfile)
|
|
||||||
data = skimage.io.imread(infile)
|
|
||||||
with tempfile.NamedTemporaryFile(suffix='.j2k') as tfile:
|
|
||||||
j = Jp2k(tfile.name, 'wb')
|
|
||||||
with self.assertRaises(IOError):
|
|
||||||
j.write(data, cinema2k=36)
|
|
||||||
|
|
||||||
|
|
||||||
@unittest.skipIf(NO_READ_BACKEND, NO_READ_BACKEND_MSG)
|
|
||||||
@unittest.skipIf(os.name == "nt", "Temporary file issue on window.")
|
|
||||||
def test_psnr_with_cratios(self):
|
|
||||||
"""Using psnr with cratios options is not allowed."""
|
|
||||||
# Not an OpenJPEG test, but close.
|
|
||||||
infile = opj_data_file('input/nonregression/Bretagne1.ppm')
|
|
||||||
data = read_image(infile)
|
|
||||||
with tempfile.NamedTemporaryFile(suffix='.j2k') as tfile:
|
|
||||||
j = Jp2k(tfile.name, 'wb')
|
|
||||||
with self.assertRaises(IOError):
|
|
||||||
j.write(data, psnr=[30, 35, 40], cratios=[2, 3, 4])
|
|
||||||
|
|
||||||
def test_nr_marker_not_compliant(self):
|
def test_nr_marker_not_compliant(self):
|
||||||
"""non-compliant marker, should still be able to read"""
|
"""non-compliant marker, should still be able to read"""
|
||||||
relpath = 'input/nonregression/MarkerIsNotCompliant.j2k'
|
relpath = 'input/nonregression/MarkerIsNotCompliant.j2k'
|
||||||
|
|
@ -98,56 +65,80 @@ class TestSuiteNegative(unittest.TestCase):
|
||||||
jp2k.get_codestream(header_only=False)
|
jp2k.get_codestream(header_only=False)
|
||||||
self.assertTrue(True)
|
self.assertTrue(True)
|
||||||
|
|
||||||
@unittest.skipIf(os.name == "nt", "Temporary file issue on window.")
|
|
||||||
|
@unittest.skipIf(re.match("1.5|2", glymur.version.openjpeg_version) is None,
|
||||||
|
"Must have openjpeg 1.5 or higher to run")
|
||||||
|
@unittest.skipIf(os.name == "nt", fixtures.WINDOWS_TMP_FILE_MSG)
|
||||||
|
@unittest.skipIf(OPJ_DATA_ROOT is None,
|
||||||
|
"OPJ_OPJ_DATA_ROOT environment variable not set")
|
||||||
|
class TestSuiteNegativeWrite(unittest.TestCase):
|
||||||
|
"""Test suite for certain negative tests from openjpeg suite."""
|
||||||
|
|
||||||
|
def setUp(self):
|
||||||
|
self.jp2file = glymur.data.nemo()
|
||||||
|
self.j2kfile = glymur.data.goodstuff()
|
||||||
|
|
||||||
|
def tearDown(self):
|
||||||
|
pass
|
||||||
|
|
||||||
|
@unittest.skipIf(NO_SKIMAGE_FREEIMAGE_SUPPORT,
|
||||||
|
"Cannot read input image without scikit-image/freeimage")
|
||||||
|
def test_cinema2K_bad_frame_rate(self):
|
||||||
|
"""Cinema2k frame rate must be either 24 or 48."""
|
||||||
|
relfile = 'input/nonregression/X_5_2K_24_235_CBR_STEM24_000.tif'
|
||||||
|
infile = opj_data_file(relfile)
|
||||||
|
data = skimage.io.imread(infile)
|
||||||
|
with tempfile.NamedTemporaryFile(suffix='.j2k') as tfile:
|
||||||
|
with self.assertRaises(IOError):
|
||||||
|
Jp2k(tfile.name, data=data, cinema2k=36)
|
||||||
|
|
||||||
|
@unittest.skipIf(NO_READ_BACKEND, NO_READ_BACKEND_MSG)
|
||||||
|
def test_psnr_with_cratios(self):
|
||||||
|
"""Using psnr with cratios options is not allowed."""
|
||||||
|
# Not an OpenJPEG test, but close.
|
||||||
|
infile = opj_data_file('input/nonregression/Bretagne1.ppm')
|
||||||
|
data = read_image(infile)
|
||||||
|
with tempfile.NamedTemporaryFile(suffix='.j2k') as tfile:
|
||||||
|
with self.assertRaises(IOError):
|
||||||
|
Jp2k(tfile.name,
|
||||||
|
data=data, psnr=[30, 35, 40], cratios=[2, 3, 4])
|
||||||
|
|
||||||
def test_code_block_dimensions(self):
|
def test_code_block_dimensions(self):
|
||||||
"""don't allow extreme codeblock sizes"""
|
"""don't allow extreme codeblock sizes"""
|
||||||
# opj_compress doesn't allow the dimensions of a codeblock
|
# opj_compress doesn't allow the dimensions of a codeblock
|
||||||
# to be too small or too big, so neither will we.
|
# to be too small or too big, so neither will we.
|
||||||
data = np.zeros((256, 256), dtype=np.uint8)
|
data = np.zeros((256, 256), dtype=np.uint8)
|
||||||
with tempfile.NamedTemporaryFile(suffix='.j2k') as tfile:
|
with tempfile.NamedTemporaryFile(suffix='.j2k') as tfile:
|
||||||
j = Jp2k(tfile.name, 'wb')
|
|
||||||
|
|
||||||
# opj_compress doesn't allow code block area to exceed 4096.
|
# opj_compress doesn't allow code block area to exceed 4096.
|
||||||
with self.assertRaises(IOError):
|
with self.assertRaises(IOError):
|
||||||
j.write(data, cbsize=(256, 256))
|
Jp2k(tfile.name, data=data, cbsize=(256, 256))
|
||||||
|
|
||||||
# opj_compress doesn't allow either dimension to be less than 4.
|
# opj_compress doesn't allow either dimension to be less than 4.
|
||||||
with self.assertRaises(IOError):
|
with self.assertRaises(IOError):
|
||||||
j.write(data, cbsize=(2048, 2))
|
Jp2k(tfile.name, data=data, cbsize=(2048, 2))
|
||||||
with self.assertRaises(IOError):
|
with self.assertRaises(IOError):
|
||||||
j.write(data, cbsize=(2, 2048))
|
Jp2k(tfile.name, data=data, cbsize=(2, 2048))
|
||||||
|
|
||||||
@unittest.skipIf(os.name == "nt", "Temporary file issue on window.")
|
|
||||||
def test_precinct_size_not_p2(self):
|
def test_precinct_size_not_p2(self):
|
||||||
"""precinct sizes should be powers of two."""
|
"""precinct sizes should be powers of two."""
|
||||||
ifile = Jp2k(self.j2kfile)
|
ifile = Jp2k(self.j2kfile)
|
||||||
data = ifile.read(rlevel=2)
|
data = ifile[::4, ::4]
|
||||||
with tempfile.NamedTemporaryFile(suffix='.jp2') as tfile:
|
with tempfile.NamedTemporaryFile(suffix='.jp2') as tfile:
|
||||||
ofile = Jp2k(tfile.name, 'wb')
|
|
||||||
with self.assertRaises(IOError):
|
with self.assertRaises(IOError):
|
||||||
ofile.write(data, psizes=[(13, 13)])
|
Jp2k(tfile.name, data=data, psizes=[(13, 13)])
|
||||||
|
|
||||||
@unittest.skipIf(os.name == "nt", "Temporary file issue on window.")
|
|
||||||
def test_cblk_size_not_power_of_two(self):
|
def test_cblk_size_not_power_of_two(self):
|
||||||
"""code block sizes should be powers of two."""
|
"""code block sizes should be powers of two."""
|
||||||
ifile = Jp2k(self.j2kfile)
|
ifile = Jp2k(self.j2kfile)
|
||||||
data = ifile.read(rlevel=2)
|
data = ifile[::4, ::4]
|
||||||
with tempfile.NamedTemporaryFile(suffix='.jp2') as tfile:
|
with tempfile.NamedTemporaryFile(suffix='.jp2') as tfile:
|
||||||
ofile = Jp2k(tfile.name, 'wb')
|
|
||||||
with self.assertRaises(IOError):
|
with self.assertRaises(IOError):
|
||||||
ofile.write(data, cbsize=(13, 12))
|
Jp2k(tfile.name, data=data, cbsize=(13, 12))
|
||||||
|
|
||||||
@unittest.skipIf(os.name == "nt", "Temporary file issue on window.")
|
|
||||||
def test_cblk_size_precinct_size(self):
|
def test_cblk_size_precinct_size(self):
|
||||||
"""code block sizes should never exceed half that of precinct size."""
|
"""code block sizes should never exceed half that of precinct size."""
|
||||||
ifile = Jp2k(self.j2kfile)
|
ifile = Jp2k(self.j2kfile)
|
||||||
data = ifile.read(rlevel=2)
|
data = ifile[::4, ::4]
|
||||||
with tempfile.NamedTemporaryFile(suffix='.jp2') as tfile:
|
with tempfile.NamedTemporaryFile(suffix='.jp2') as tfile:
|
||||||
ofile = Jp2k(tfile.name, 'wb')
|
|
||||||
with self.assertRaises(IOError):
|
with self.assertRaises(IOError):
|
||||||
ofile.write(data,
|
Jp2k(tfile.name, data=data, cbsize=(64, 64), psizes=[(64, 64)])
|
||||||
cbsize=(64, 64),
|
|
||||||
psizes=[(64, 64)])
|
|
||||||
|
|
||||||
if __name__ == "__main__":
|
|
||||||
unittest.main()
|
|
||||||
|
|
|
||||||
|
|
@ -2,16 +2,17 @@
|
||||||
The tests defined here roughly correspond to what is in the OpenJPEG test
|
The tests defined here roughly correspond to what is in the OpenJPEG test
|
||||||
suite.
|
suite.
|
||||||
"""
|
"""
|
||||||
# C0103: method names longer that 30 chars are ok in tests, IMHO
|
|
||||||
# R0904: Seems like pylint is fooled in this situation
|
|
||||||
# pylint: disable=R0904,C0103
|
|
||||||
|
|
||||||
import os
|
import os
|
||||||
import re
|
import re
|
||||||
import sys
|
import sys
|
||||||
import tempfile
|
import tempfile
|
||||||
import unittest
|
import unittest
|
||||||
|
|
||||||
|
if sys.hexversion <= 0x03030000:
|
||||||
|
from mock import patch
|
||||||
|
else:
|
||||||
|
from unittest.mock import patch
|
||||||
|
|
||||||
import numpy as np
|
import numpy as np
|
||||||
try:
|
try:
|
||||||
import skimage.io
|
import skimage.io
|
||||||
|
|
@ -29,6 +30,7 @@ from glymur import Jp2k
|
||||||
from glymur.codestream import SIZsegment
|
from glymur.codestream import SIZsegment
|
||||||
from glymur.version import openjpeg_version
|
from glymur.version import openjpeg_version
|
||||||
|
|
||||||
|
|
||||||
class CinemaBase(fixtures.MetadataBase):
|
class CinemaBase(fixtures.MetadataBase):
|
||||||
|
|
||||||
def verify_cinema_cod(self, cod_segment):
|
def verify_cinema_cod(self, cod_segment):
|
||||||
|
|
@ -39,14 +41,14 @@ class CinemaBase(fixtures.MetadataBase):
|
||||||
self.assertEqual(cod_segment.layers, 1)
|
self.assertEqual(cod_segment.layers, 1)
|
||||||
self.assertEqual(cod_segment.spcod[3], 1) # mct
|
self.assertEqual(cod_segment.spcod[3], 1) # mct
|
||||||
self.assertEqual(cod_segment.spcod[4], 5) # levels
|
self.assertEqual(cod_segment.spcod[4], 5) # levels
|
||||||
self.assertEqual(tuple(cod_segment.code_block_size), (32, 32)) # cblksz
|
self.assertEqual(tuple(cod_segment.code_block_size), (32, 32))
|
||||||
|
|
||||||
def check_cinema4k_codestream(self, codestream, image_size):
|
def check_cinema4k_codestream(self, codestream, image_size):
|
||||||
|
|
||||||
kwargs = {'rsiz': 4, 'xysiz': image_size, 'xyosiz': (0, 0),
|
kwargs = {'rsiz': 4, 'xysiz': image_size, 'xyosiz': (0, 0),
|
||||||
'xytsiz': image_size, 'xytosiz': (0, 0),
|
'xytsiz': image_size, 'xytosiz': (0, 0),
|
||||||
'bitdepth': (12, 12, 12), 'signed': (False, False, False),
|
'bitdepth': (12, 12, 12), 'signed': (False, False, False),
|
||||||
'xyrsiz': [(1, 1, 1), (1, 1, 1)]}
|
'xyrsiz': [(1, 1, 1), (1, 1, 1)]}
|
||||||
self.verifySizSegment(codestream.segment[1], SIZsegment(**kwargs))
|
self.verifySizSegment(codestream.segment[1], SIZsegment(**kwargs))
|
||||||
|
|
||||||
self.verify_cinema_cod(codestream.segment[2])
|
self.verify_cinema_cod(codestream.segment[2])
|
||||||
|
|
@ -54,9 +56,9 @@ class CinemaBase(fixtures.MetadataBase):
|
||||||
def check_cinema2k_codestream(self, codestream, image_size):
|
def check_cinema2k_codestream(self, codestream, image_size):
|
||||||
|
|
||||||
kwargs = {'rsiz': 3, 'xysiz': image_size, 'xyosiz': (0, 0),
|
kwargs = {'rsiz': 3, 'xysiz': image_size, 'xyosiz': (0, 0),
|
||||||
'xytsiz': image_size, 'xytosiz': (0, 0),
|
'xytsiz': image_size, 'xytosiz': (0, 0),
|
||||||
'bitdepth': (12, 12, 12), 'signed': (False, False, False),
|
'bitdepth': (12, 12, 12), 'signed': (False, False, False),
|
||||||
'xyrsiz': [(1, 1, 1), (1, 1, 1)]}
|
'xyrsiz': [(1, 1, 1), (1, 1, 1)]}
|
||||||
self.verifySizSegment(codestream.segment[1], SIZsegment(**kwargs))
|
self.verifySizSegment(codestream.segment[1], SIZsegment(**kwargs))
|
||||||
|
|
||||||
self.verify_cinema_cod(codestream.segment[2])
|
self.verify_cinema_cod(codestream.segment[2])
|
||||||
|
|
@ -64,7 +66,7 @@ class CinemaBase(fixtures.MetadataBase):
|
||||||
|
|
||||||
@unittest.skipIf(NO_SKIMAGE_FREEIMAGE_SUPPORT,
|
@unittest.skipIf(NO_SKIMAGE_FREEIMAGE_SUPPORT,
|
||||||
"Cannot read input image without scikit-image/freeimage")
|
"Cannot read input image without scikit-image/freeimage")
|
||||||
@unittest.skipIf(os.name == "nt", "no write support on windows, period")
|
@unittest.skipIf(os.name == "nt", fixtures.WINDOWS_TMP_FILE_MSG)
|
||||||
@unittest.skipIf(re.match(r'''(1|2.0.0)''',
|
@unittest.skipIf(re.match(r'''(1|2.0.0)''',
|
||||||
glymur.version.openjpeg_version) is not None,
|
glymur.version.openjpeg_version) is not None,
|
||||||
"Uses features not supported until 2.0.1")
|
"Uses features not supported until 2.0.1")
|
||||||
|
|
@ -82,9 +84,9 @@ class WriteCinema(CinemaBase):
|
||||||
infile = opj_data_file(relfile)
|
infile = opj_data_file(relfile)
|
||||||
data = skimage.io.imread(infile)
|
data = skimage.io.imread(infile)
|
||||||
with tempfile.NamedTemporaryFile(suffix='.j2k') as tfile:
|
with tempfile.NamedTemporaryFile(suffix='.j2k') as tfile:
|
||||||
j = Jp2k(tfile.name, 'wb')
|
|
||||||
with self.assertRaises(IOError):
|
with self.assertRaises(IOError):
|
||||||
j.write(data, cinema2k=48, cratios=[200, 100, 50])
|
Jp2k(tfile.name, data=data,
|
||||||
|
cinema2k=48, cratios=[200, 100, 50])
|
||||||
|
|
||||||
def test_cinema4K_with_others(self):
|
def test_cinema4K_with_others(self):
|
||||||
"""Can't specify cinema4k with any other options."""
|
"""Can't specify cinema4k with any other options."""
|
||||||
|
|
@ -92,15 +94,15 @@ class WriteCinema(CinemaBase):
|
||||||
infile = opj_data_file(relfile)
|
infile = opj_data_file(relfile)
|
||||||
data = skimage.io.imread(infile)
|
data = skimage.io.imread(infile)
|
||||||
with tempfile.NamedTemporaryFile(suffix='.j2k') as tfile:
|
with tempfile.NamedTemporaryFile(suffix='.j2k') as tfile:
|
||||||
j = Jp2k(tfile.name, 'wb')
|
|
||||||
with self.assertRaises(IOError):
|
with self.assertRaises(IOError):
|
||||||
j.write(data, cinema4k=True, cratios=[200, 100, 50])
|
Jp2k(tfile.name, data=data,
|
||||||
|
cinema4k=True, cratios=[200, 100, 50])
|
||||||
|
|
||||||
|
|
||||||
@unittest.skipIf(WARNING_INFRASTRUCTURE_ISSUE, WARNING_INFRASTRUCTURE_MSG)
|
@unittest.skipIf(WARNING_INFRASTRUCTURE_ISSUE, WARNING_INFRASTRUCTURE_MSG)
|
||||||
@unittest.skipIf(NO_SKIMAGE_FREEIMAGE_SUPPORT,
|
@unittest.skipIf(NO_SKIMAGE_FREEIMAGE_SUPPORT,
|
||||||
"Cannot read input image without scikit-image/freeimage")
|
"Cannot read input image without scikit-image/freeimage")
|
||||||
@unittest.skipIf(os.name == "nt", "no write support on windows, period")
|
@unittest.skipIf(os.name == "nt", fixtures.WINDOWS_TMP_FILE_MSG)
|
||||||
@unittest.skipIf(re.match(r'''(1|2.0.0)''',
|
@unittest.skipIf(re.match(r'''(1|2.0.0)''',
|
||||||
glymur.version.openjpeg_version) is not None,
|
glymur.version.openjpeg_version) is not None,
|
||||||
"Uses features not supported until 2.0.1")
|
"Uses features not supported until 2.0.1")
|
||||||
|
|
@ -118,10 +120,9 @@ class WriteCinemaWarns(CinemaBase):
|
||||||
infile = opj_data_file(relfile)
|
infile = opj_data_file(relfile)
|
||||||
data = skimage.io.imread(infile)
|
data = skimage.io.imread(infile)
|
||||||
with tempfile.NamedTemporaryFile(suffix='.j2k') as tfile:
|
with tempfile.NamedTemporaryFile(suffix='.j2k') as tfile:
|
||||||
j = Jp2k(tfile.name, 'wb')
|
|
||||||
regex = 'OpenJPEG library warning:.*'
|
regex = 'OpenJPEG library warning:.*'
|
||||||
with self.assertWarnsRegex(UserWarning, re.compile(regex)):
|
with self.assertWarnsRegex(UserWarning, re.compile(regex)):
|
||||||
j.write(data, cinema4k=True)
|
j = Jp2k(tfile.name, data=data, cinema4k=True)
|
||||||
|
|
||||||
codestream = j.get_codestream()
|
codestream = j.get_codestream()
|
||||||
self.check_cinema4k_codestream(codestream, (4096, 2160))
|
self.check_cinema4k_codestream(codestream, (4096, 2160))
|
||||||
|
|
@ -131,9 +132,9 @@ class WriteCinemaWarns(CinemaBase):
|
||||||
infile = opj_data_file(relfile)
|
infile = opj_data_file(relfile)
|
||||||
data = skimage.io.imread(infile)
|
data = skimage.io.imread(infile)
|
||||||
with tempfile.NamedTemporaryFile(suffix='.j2k') as tfile:
|
with tempfile.NamedTemporaryFile(suffix='.j2k') as tfile:
|
||||||
j = Jp2k(tfile.name, 'wb')
|
with self.assertWarnsRegex(UserWarning,
|
||||||
with self.assertWarnsRegex(UserWarning, 'OpenJPEG library warning'):
|
'OpenJPEG library warning'):
|
||||||
j.write(data, cinema2k=48)
|
j = Jp2k(tfile.name, data=data, cinema2k=48)
|
||||||
|
|
||||||
codestream = j.get_codestream()
|
codestream = j.get_codestream()
|
||||||
self.check_cinema2k_codestream(codestream, (2048, 857))
|
self.check_cinema2k_codestream(codestream, (2048, 857))
|
||||||
|
|
@ -143,9 +144,9 @@ class WriteCinemaWarns(CinemaBase):
|
||||||
infile = opj_data_file(relfile)
|
infile = opj_data_file(relfile)
|
||||||
data = skimage.io.imread(infile)
|
data = skimage.io.imread(infile)
|
||||||
with tempfile.NamedTemporaryFile(suffix='.j2k') as tfile:
|
with tempfile.NamedTemporaryFile(suffix='.j2k') as tfile:
|
||||||
j = Jp2k(tfile.name, 'wb')
|
with self.assertWarnsRegex(UserWarning,
|
||||||
with self.assertWarnsRegex(UserWarning, 'OpenJPEG library warning'):
|
'OpenJPEG library warning'):
|
||||||
j.write(data, cinema2k=48)
|
j = Jp2k(tfile.name, data=data, cinema2k=48)
|
||||||
|
|
||||||
codestream = j.get_codestream()
|
codestream = j.get_codestream()
|
||||||
self.check_cinema2k_codestream(codestream, (2048, 1080))
|
self.check_cinema2k_codestream(codestream, (2048, 1080))
|
||||||
|
|
@ -155,9 +156,9 @@ class WriteCinemaWarns(CinemaBase):
|
||||||
infile = opj_data_file(relfile)
|
infile = opj_data_file(relfile)
|
||||||
data = skimage.io.imread(infile)
|
data = skimage.io.imread(infile)
|
||||||
with tempfile.NamedTemporaryFile(suffix='.j2k') as tfile:
|
with tempfile.NamedTemporaryFile(suffix='.j2k') as tfile:
|
||||||
j = Jp2k(tfile.name, 'wb')
|
with self.assertWarnsRegex(UserWarning,
|
||||||
with self.assertWarnsRegex(UserWarning, 'OpenJPEG library warning'):
|
'OpenJPEG library warning'):
|
||||||
j.write(data, cinema2k=24)
|
j = Jp2k(tfile.name, data=data, cinema2k=24)
|
||||||
|
|
||||||
codestream = j.get_codestream()
|
codestream = j.get_codestream()
|
||||||
self.check_cinema2k_codestream(codestream, (2048, 1080))
|
self.check_cinema2k_codestream(codestream, (2048, 1080))
|
||||||
|
|
@ -167,11 +168,11 @@ class WriteCinemaWarns(CinemaBase):
|
||||||
infile = opj_data_file(relfile)
|
infile = opj_data_file(relfile)
|
||||||
data = skimage.io.imread(infile)
|
data = skimage.io.imread(infile)
|
||||||
with tempfile.NamedTemporaryFile(suffix='.j2k') as tfile:
|
with tempfile.NamedTemporaryFile(suffix='.j2k') as tfile:
|
||||||
j = Jp2k(tfile.name, 'wb')
|
with self.assertWarnsRegex(UserWarning,
|
||||||
with self.assertWarnsRegex(UserWarning, 'OpenJPEG library warning'):
|
'OpenJPEG library warning'):
|
||||||
# OpenJPEG library warning: The desired maximum codestream
|
# OpenJPEG library warning: The desired maximum codestream
|
||||||
# size has limited at least one of the desired quality layers
|
# size has limited at least one of the desired quality layers
|
||||||
j.write(data, cinema2k=24)
|
j = Jp2k(tfile.name, data=data, cinema2k=24)
|
||||||
|
|
||||||
codestream = j.get_codestream()
|
codestream = j.get_codestream()
|
||||||
self.check_cinema2k_codestream(codestream, (2048, 857))
|
self.check_cinema2k_codestream(codestream, (2048, 857))
|
||||||
|
|
@ -181,12 +182,11 @@ class WriteCinemaWarns(CinemaBase):
|
||||||
infile = opj_data_file(relfile)
|
infile = opj_data_file(relfile)
|
||||||
data = skimage.io.imread(infile)
|
data = skimage.io.imread(infile)
|
||||||
with tempfile.NamedTemporaryFile(suffix='.j2k') as tfile:
|
with tempfile.NamedTemporaryFile(suffix='.j2k') as tfile:
|
||||||
j = Jp2k(tfile.name, 'wb')
|
|
||||||
regex = 'OpenJPEG library warning'
|
regex = 'OpenJPEG library warning'
|
||||||
with self.assertWarnsRegex(UserWarning, regex):
|
with self.assertWarnsRegex(UserWarning, regex):
|
||||||
# OpenJPEG library warning: The desired maximum codestream
|
# OpenJPEG library warning: The desired maximum codestream
|
||||||
# size has limited at least one of the desired quality layers
|
# size has limited at least one of the desired quality layers
|
||||||
j.write(data, cinema2k=48)
|
j = Jp2k(tfile.name, data=data, cinema2k=48)
|
||||||
|
|
||||||
codestream = j.get_codestream()
|
codestream = j.get_codestream()
|
||||||
self.check_cinema2k_codestream(codestream, (1998, 1080))
|
self.check_cinema2k_codestream(codestream, (1998, 1080))
|
||||||
|
|
@ -194,13 +194,11 @@ class WriteCinemaWarns(CinemaBase):
|
||||||
|
|
||||||
@unittest.skipIf(NO_SKIMAGE_FREEIMAGE_SUPPORT,
|
@unittest.skipIf(NO_SKIMAGE_FREEIMAGE_SUPPORT,
|
||||||
"Cannot read input image without scikit-image/freeimage")
|
"Cannot read input image without scikit-image/freeimage")
|
||||||
@unittest.skipIf(os.name == "nt", "Temporary file issue on window.")
|
@unittest.skipIf(os.name == "nt", fixtures.WINDOWS_TMP_FILE_MSG)
|
||||||
@unittest.skipIf(not re.match("(1.5|2.0.0)", glymur.version.openjpeg_version),
|
|
||||||
"Functionality implemented for 2.0.1")
|
|
||||||
@unittest.skipIf(OPJ_DATA_ROOT is None,
|
@unittest.skipIf(OPJ_DATA_ROOT is None,
|
||||||
"OPJ_OPJ_DATA_ROOT environment variable not set")
|
"OPJ_OPJ_DATA_ROOT environment variable not set")
|
||||||
class TestSuiteNegative2pointzero(unittest.TestCase):
|
class TestNegative2pointzero(unittest.TestCase):
|
||||||
"""Feature set not supported for versions less than 2.0"""
|
"""Feature set not supported for versions less than 2.0.1"""
|
||||||
|
|
||||||
def setUp(self):
|
def setUp(self):
|
||||||
self.jp2file = glymur.data.nemo()
|
self.jp2file = glymur.data.nemo()
|
||||||
|
|
@ -210,18 +208,21 @@ class TestSuiteNegative2pointzero(unittest.TestCase):
|
||||||
pass
|
pass
|
||||||
|
|
||||||
def test_cinema_mode(self):
|
def test_cinema_mode(self):
|
||||||
|
"""Cinema mode not allowed for anything less than 2.0.1"""
|
||||||
relfile = 'input/nonregression/X_4_2K_24_185_CBR_WB_000.tif'
|
relfile = 'input/nonregression/X_4_2K_24_185_CBR_WB_000.tif'
|
||||||
infile = opj_data_file(relfile)
|
infile = opj_data_file(relfile)
|
||||||
data = skimage.io.imread(infile)
|
data = skimage.io.imread(infile)
|
||||||
with tempfile.NamedTemporaryFile(suffix='.j2k') as tfile:
|
versions = ["1.5.0", "2.0.0"]
|
||||||
j = Jp2k(tfile.name, 'wb')
|
for version in versions:
|
||||||
with self.assertRaises(IOError):
|
with patch('glymur.version.openjpeg_version', new=version):
|
||||||
j.write(data, cinema2k=48)
|
with tempfile.NamedTemporaryFile(suffix='.j2k') as tfile:
|
||||||
|
with self.assertRaises(IOError):
|
||||||
|
Jp2k(tfile.name, data=data, cinema2k=48)
|
||||||
|
|
||||||
|
|
||||||
@unittest.skipIf(re.match(r'''1.[0-4]''', openjpeg_version) is not None,
|
@unittest.skipIf(re.match(r'''1.[0-4]''', openjpeg_version) is not None,
|
||||||
"Writing not supported until OpenJPEG 1.5")
|
"Writing not supported until OpenJPEG 1.5")
|
||||||
@unittest.skipIf(os.name == "nt", "no write support on windows, period")
|
@unittest.skipIf(os.name == "nt", fixtures.WINDOWS_TMP_FILE_MSG)
|
||||||
@unittest.skipIf(NO_READ_BACKEND, NO_READ_BACKEND_MSG)
|
@unittest.skipIf(NO_READ_BACKEND, NO_READ_BACKEND_MSG)
|
||||||
@unittest.skipIf(OPJ_DATA_ROOT is None,
|
@unittest.skipIf(OPJ_DATA_ROOT is None,
|
||||||
"OPJ_DATA_ROOT environment variable not set")
|
"OPJ_DATA_ROOT environment variable not set")
|
||||||
|
|
@ -242,30 +243,28 @@ class TestSuiteWrite(fixtures.MetadataBase):
|
||||||
expdata = np.fromfile(filename, dtype=np.uint16)
|
expdata = np.fromfile(filename, dtype=np.uint16)
|
||||||
expdata.resize((2816, 2048))
|
expdata.resize((2816, 2048))
|
||||||
with tempfile.NamedTemporaryFile(suffix='.j2k') as tfile:
|
with tempfile.NamedTemporaryFile(suffix='.j2k') as tfile:
|
||||||
j = Jp2k(tfile.name, 'wb')
|
j = Jp2k(tfile.name, data=expdata, irreversible=True)
|
||||||
j.write(expdata, irreversible=True)
|
|
||||||
|
|
||||||
codestream = j.get_codestream()
|
codestream = j.get_codestream()
|
||||||
self.assertEqual(codestream.segment[2].spcod[8],
|
self.assertEqual(codestream.segment[2].spcod[8],
|
||||||
glymur.core.WAVELET_XFORM_9X7_IRREVERSIBLE)
|
glymur.core.WAVELET_XFORM_9X7_IRREVERSIBLE)
|
||||||
|
|
||||||
|
|
||||||
def test_NR_ENC_Bretagne1_ppm_1_encode(self):
|
def test_NR_ENC_Bretagne1_ppm_1_encode(self):
|
||||||
"""NR-ENC-Bretagne1.ppm-1-encode"""
|
"""NR-ENC-Bretagne1.ppm-1-encode"""
|
||||||
infile = opj_data_file('input/nonregression/Bretagne1.ppm')
|
infile = opj_data_file('input/nonregression/Bretagne1.ppm')
|
||||||
data = read_image(infile)
|
data = read_image(infile)
|
||||||
with tempfile.NamedTemporaryFile(suffix='.j2k') as tfile:
|
with tempfile.NamedTemporaryFile(suffix='.j2k') as tfile:
|
||||||
j = Jp2k(tfile.name, 'wb')
|
j = Jp2k(tfile.name, data=data, cratios=[200, 100, 50])
|
||||||
j.write(data, cratios=[200, 100, 50])
|
|
||||||
|
|
||||||
# Should be three layers.
|
# Should be three layers.
|
||||||
c = j.get_codestream()
|
c = j.get_codestream()
|
||||||
|
|
||||||
kwargs = {'rsiz': 0, 'xysiz': (640, 480), 'xyosiz': (0, 0),
|
kwargs = {'rsiz': 0, 'xysiz': (640, 480), 'xyosiz': (0, 0),
|
||||||
'xytsiz': (640, 480), 'xytosiz': (0, 0),
|
'xytsiz': (640, 480), 'xytosiz': (0, 0),
|
||||||
'bitdepth': (8, 8, 8), 'signed': (False, False, False),
|
'bitdepth': (8, 8, 8), 'signed': (False, False, False),
|
||||||
'xyrsiz': [(1, 1, 1), (1, 1, 1)]}
|
'xyrsiz': [(1, 1, 1), (1, 1, 1)]}
|
||||||
self.verifySizSegment(c.segment[1], glymur.codestream.SIZsegment(**kwargs))
|
self.verifySizSegment(c.segment[1],
|
||||||
|
glymur.codestream.SIZsegment(**kwargs))
|
||||||
|
|
||||||
# COD: Coding style default
|
# COD: Coding style default
|
||||||
self.assertFalse(c.segment[2].scod & 2) # no sop
|
self.assertFalse(c.segment[2].scod & 2) # no sop
|
||||||
|
|
@ -277,7 +276,7 @@ class TestSuiteWrite(fixtures.MetadataBase):
|
||||||
self.assertEqual(tuple(c.segment[2].code_block_size),
|
self.assertEqual(tuple(c.segment[2].code_block_size),
|
||||||
(64, 64)) # cblksz
|
(64, 64)) # cblksz
|
||||||
self.verify_codeblock_style(c.segment[2].spcod[7],
|
self.verify_codeblock_style(c.segment[2].spcod[7],
|
||||||
[False, False, False, False, False, False])
|
[False, False, False, False, False, False])
|
||||||
self.assertEqual(c.segment[2].spcod[8],
|
self.assertEqual(c.segment[2].spcod[8],
|
||||||
glymur.core.WAVELET_XFORM_5X3_REVERSIBLE)
|
glymur.core.WAVELET_XFORM_5X3_REVERSIBLE)
|
||||||
self.assertEqual(len(c.segment[2].spcod), 9)
|
self.assertEqual(len(c.segment[2].spcod), 9)
|
||||||
|
|
@ -287,17 +286,17 @@ class TestSuiteWrite(fixtures.MetadataBase):
|
||||||
infile = opj_data_file('input/nonregression/Bretagne1.ppm')
|
infile = opj_data_file('input/nonregression/Bretagne1.ppm')
|
||||||
data = read_image(infile)
|
data = read_image(infile)
|
||||||
with tempfile.NamedTemporaryFile(suffix='.j2k') as tfile:
|
with tempfile.NamedTemporaryFile(suffix='.j2k') as tfile:
|
||||||
j = Jp2k(tfile.name, 'wb')
|
j = Jp2k(tfile.name, data=data, psnr=[30, 35, 40], numres=2)
|
||||||
j.write(data, psnr=[30, 35, 40], numres=2)
|
|
||||||
|
|
||||||
# Should be three layers.
|
# Should be three layers.
|
||||||
codestream = j.get_codestream()
|
codestream = j.get_codestream()
|
||||||
|
|
||||||
kwargs = {'rsiz': 0, 'xysiz': (640, 480), 'xyosiz': (0, 0),
|
kwargs = {'rsiz': 0, 'xysiz': (640, 480), 'xyosiz': (0, 0),
|
||||||
'xytsiz': (640, 480), 'xytosiz': (0, 0),
|
'xytsiz': (640, 480), 'xytosiz': (0, 0),
|
||||||
'bitdepth': (8, 8, 8), 'signed': (False, False, False),
|
'bitdepth': (8, 8, 8), 'signed': (False, False, False),
|
||||||
'xyrsiz': [(1, 1, 1), (1, 1, 1)]}
|
'xyrsiz': [(1, 1, 1), (1, 1, 1)]}
|
||||||
self.verifySizSegment(codestream.segment[1], glymur.codestream.SIZsegment(**kwargs))
|
self.verifySizSegment(codestream.segment[1],
|
||||||
|
glymur.codestream.SIZsegment(**kwargs))
|
||||||
|
|
||||||
# COD: Coding style default
|
# COD: Coding style default
|
||||||
self.assertFalse(codestream.segment[2].scod & 2) # no sop
|
self.assertFalse(codestream.segment[2].scod & 2) # no sop
|
||||||
|
|
@ -309,7 +308,8 @@ class TestSuiteWrite(fixtures.MetadataBase):
|
||||||
self.assertEqual(tuple(codestream.segment[2].code_block_size),
|
self.assertEqual(tuple(codestream.segment[2].code_block_size),
|
||||||
(64, 64)) # cblksz
|
(64, 64)) # cblksz
|
||||||
self.verify_codeblock_style(codestream.segment[2].spcod[7],
|
self.verify_codeblock_style(codestream.segment[2].spcod[7],
|
||||||
[False, False, False, False, False, False])
|
[False, False,
|
||||||
|
False, False, False, False])
|
||||||
self.assertEqual(codestream.segment[2].spcod[8],
|
self.assertEqual(codestream.segment[2].spcod[8],
|
||||||
glymur.core.WAVELET_XFORM_5X3_REVERSIBLE)
|
glymur.core.WAVELET_XFORM_5X3_REVERSIBLE)
|
||||||
self.assertEqual(len(codestream.segment[2].spcod), 9)
|
self.assertEqual(len(codestream.segment[2].spcod), 9)
|
||||||
|
|
@ -319,18 +319,19 @@ class TestSuiteWrite(fixtures.MetadataBase):
|
||||||
infile = opj_data_file('input/nonregression/Bretagne1.ppm')
|
infile = opj_data_file('input/nonregression/Bretagne1.ppm')
|
||||||
data = read_image(infile)
|
data = read_image(infile)
|
||||||
with tempfile.NamedTemporaryFile(suffix='.j2k') as tfile:
|
with tempfile.NamedTemporaryFile(suffix='.j2k') as tfile:
|
||||||
j = Jp2k(tfile.name, 'wb')
|
j = Jp2k(tfile.name,
|
||||||
j.write(data, psnr=[30, 35, 40], cbsize=(16, 16),
|
data=data,
|
||||||
psizes=[(64, 64)])
|
psnr=[30, 35, 40], cbsize=(16, 16), psizes=[(64, 64)])
|
||||||
|
|
||||||
# Should be three layers.
|
# Should be three layers.
|
||||||
codestream = j.get_codestream()
|
codestream = j.get_codestream()
|
||||||
|
|
||||||
kwargs = {'rsiz': 0, 'xysiz': (640, 480), 'xyosiz': (0, 0),
|
kwargs = {'rsiz': 0, 'xysiz': (640, 480), 'xyosiz': (0, 0),
|
||||||
'xytsiz': (640, 480), 'xytosiz': (0, 0),
|
'xytsiz': (640, 480), 'xytosiz': (0, 0),
|
||||||
'bitdepth': (8, 8, 8), 'signed': (False, False, False),
|
'bitdepth': (8, 8, 8), 'signed': (False, False, False),
|
||||||
'xyrsiz': [(1, 1, 1), (1, 1, 1)]}
|
'xyrsiz': [(1, 1, 1), (1, 1, 1)]}
|
||||||
self.verifySizSegment(codestream.segment[1], glymur.codestream.SIZsegment(**kwargs))
|
self.verifySizSegment(codestream.segment[1],
|
||||||
|
glymur.codestream.SIZsegment(**kwargs))
|
||||||
|
|
||||||
# COD: Coding style default
|
# COD: Coding style default
|
||||||
self.assertFalse(codestream.segment[2].scod & 2) # no sop
|
self.assertFalse(codestream.segment[2].scod & 2) # no sop
|
||||||
|
|
@ -342,7 +343,8 @@ class TestSuiteWrite(fixtures.MetadataBase):
|
||||||
self.assertEqual(tuple(codestream.segment[2].code_block_size),
|
self.assertEqual(tuple(codestream.segment[2].code_block_size),
|
||||||
(16, 16)) # cblksz
|
(16, 16)) # cblksz
|
||||||
self.verify_codeblock_style(codestream.segment[2].spcod[7],
|
self.verify_codeblock_style(codestream.segment[2].spcod[7],
|
||||||
[False, False, False, False, False, False])
|
[False, False,
|
||||||
|
False, False, False, False])
|
||||||
self.assertEqual(codestream.segment[2].spcod[8],
|
self.assertEqual(codestream.segment[2].spcod[8],
|
||||||
glymur.core.WAVELET_XFORM_5X3_REVERSIBLE)
|
glymur.core.WAVELET_XFORM_5X3_REVERSIBLE)
|
||||||
self.assertEqual(codestream.segment[2].precinct_size,
|
self.assertEqual(codestream.segment[2].precinct_size,
|
||||||
|
|
@ -354,21 +356,22 @@ class TestSuiteWrite(fixtures.MetadataBase):
|
||||||
infile = opj_data_file('input/nonregression/Bretagne2.ppm')
|
infile = opj_data_file('input/nonregression/Bretagne2.ppm')
|
||||||
data = read_image(infile)
|
data = read_image(infile)
|
||||||
with tempfile.NamedTemporaryFile(suffix='.j2k') as tfile:
|
with tempfile.NamedTemporaryFile(suffix='.j2k') as tfile:
|
||||||
j = Jp2k(tfile.name, 'wb')
|
j = Jp2k(tfile.name,
|
||||||
j.write(data,
|
data=data,
|
||||||
psizes=[(128, 128)] * 3,
|
psizes=[(128, 128)] * 3,
|
||||||
cratios=[100, 20, 2],
|
cratios=[100, 20, 2],
|
||||||
tilesize=(480, 640),
|
tilesize=(480, 640),
|
||||||
cbsize=(32, 32))
|
cbsize=(32, 32))
|
||||||
|
|
||||||
# Should be three layers.
|
# Should be three layers.
|
||||||
codestream = j.get_codestream()
|
codestream = j.get_codestream()
|
||||||
|
|
||||||
kwargs = {'rsiz': 0, 'xysiz': (2592, 1944), 'xyosiz': (0, 0),
|
kwargs = {'rsiz': 0, 'xysiz': (2592, 1944), 'xyosiz': (0, 0),
|
||||||
'xytsiz': (640, 480), 'xytosiz': (0, 0),
|
'xytsiz': (640, 480), 'xytosiz': (0, 0),
|
||||||
'bitdepth': (8, 8, 8), 'signed': (False, False, False),
|
'bitdepth': (8, 8, 8), 'signed': (False, False, False),
|
||||||
'xyrsiz': [(1, 1, 1), (1, 1, 1)]}
|
'xyrsiz': [(1, 1, 1), (1, 1, 1)]}
|
||||||
self.verifySizSegment(codestream.segment[1], glymur.codestream.SIZsegment(**kwargs))
|
self.verifySizSegment(codestream.segment[1],
|
||||||
|
glymur.codestream.SIZsegment(**kwargs))
|
||||||
|
|
||||||
# COD: Coding style default
|
# COD: Coding style default
|
||||||
self.assertFalse(codestream.segment[2].scod & 2) # no sop
|
self.assertFalse(codestream.segment[2].scod & 2) # no sop
|
||||||
|
|
@ -380,7 +383,8 @@ class TestSuiteWrite(fixtures.MetadataBase):
|
||||||
self.assertEqual(tuple(codestream.segment[2].code_block_size),
|
self.assertEqual(tuple(codestream.segment[2].code_block_size),
|
||||||
(32, 32)) # cblksz
|
(32, 32)) # cblksz
|
||||||
self.verify_codeblock_style(codestream.segment[2].spcod[7],
|
self.verify_codeblock_style(codestream.segment[2].spcod[7],
|
||||||
[False, False, False, False, False, False])
|
[False, False,
|
||||||
|
False, False, False, False])
|
||||||
self.assertEqual(codestream.segment[2].spcod[8],
|
self.assertEqual(codestream.segment[2].spcod[8],
|
||||||
glymur.core.WAVELET_XFORM_5X3_REVERSIBLE)
|
glymur.core.WAVELET_XFORM_5X3_REVERSIBLE)
|
||||||
self.assertEqual(codestream.segment[2].precinct_size,
|
self.assertEqual(codestream.segment[2].precinct_size,
|
||||||
|
|
@ -391,16 +395,16 @@ class TestSuiteWrite(fixtures.MetadataBase):
|
||||||
infile = opj_data_file('input/nonregression/Bretagne2.ppm')
|
infile = opj_data_file('input/nonregression/Bretagne2.ppm')
|
||||||
data = read_image(infile)
|
data = read_image(infile)
|
||||||
with tempfile.NamedTemporaryFile(suffix='.j2k') as tfile:
|
with tempfile.NamedTemporaryFile(suffix='.j2k') as tfile:
|
||||||
j = Jp2k(tfile.name, 'wb')
|
j = Jp2k(tfile.name, data=data, tilesize=(127, 127), prog="PCRL")
|
||||||
j.write(data, tilesize=(127, 127), prog="PCRL")
|
|
||||||
|
|
||||||
codestream = j.get_codestream()
|
codestream = j.get_codestream()
|
||||||
|
|
||||||
kwargs = {'rsiz': 0, 'xysiz': (2592, 1944), 'xyosiz': (0, 0),
|
kwargs = {'rsiz': 0, 'xysiz': (2592, 1944), 'xyosiz': (0, 0),
|
||||||
'xytsiz': (127, 127), 'xytosiz': (0, 0),
|
'xytsiz': (127, 127), 'xytosiz': (0, 0),
|
||||||
'bitdepth': (8, 8, 8), 'signed': (False, False, False),
|
'bitdepth': (8, 8, 8), 'signed': (False, False, False),
|
||||||
'xyrsiz': [(1, 1, 1), (1, 1, 1)]}
|
'xyrsiz': [(1, 1, 1), (1, 1, 1)]}
|
||||||
self.verifySizSegment(codestream.segment[1], glymur.codestream.SIZsegment(**kwargs))
|
self.verifySizSegment(codestream.segment[1],
|
||||||
|
glymur.codestream.SIZsegment(**kwargs))
|
||||||
|
|
||||||
# COD: Coding style default
|
# COD: Coding style default
|
||||||
self.assertFalse(codestream.segment[2].scod & 2) # no sop
|
self.assertFalse(codestream.segment[2].scod & 2) # no sop
|
||||||
|
|
@ -412,7 +416,8 @@ class TestSuiteWrite(fixtures.MetadataBase):
|
||||||
self.assertEqual(tuple(codestream.segment[2].code_block_size),
|
self.assertEqual(tuple(codestream.segment[2].code_block_size),
|
||||||
(64, 64)) # cblksz
|
(64, 64)) # cblksz
|
||||||
self.verify_codeblock_style(codestream.segment[2].spcod[7],
|
self.verify_codeblock_style(codestream.segment[2].spcod[7],
|
||||||
[False, False, False, False, False, False])
|
[False, False,
|
||||||
|
False, False, False, False])
|
||||||
self.assertEqual(codestream.segment[2].spcod[8],
|
self.assertEqual(codestream.segment[2].spcod[8],
|
||||||
glymur.core.WAVELET_XFORM_5X3_REVERSIBLE)
|
glymur.core.WAVELET_XFORM_5X3_REVERSIBLE)
|
||||||
self.assertEqual(len(codestream.segment[2].spcod), 9)
|
self.assertEqual(len(codestream.segment[2].spcod), 9)
|
||||||
|
|
@ -422,16 +427,16 @@ class TestSuiteWrite(fixtures.MetadataBase):
|
||||||
infile = opj_data_file('input/nonregression/Bretagne2.ppm')
|
infile = opj_data_file('input/nonregression/Bretagne2.ppm')
|
||||||
data = read_image(infile)
|
data = read_image(infile)
|
||||||
with tempfile.NamedTemporaryFile(suffix='.j2k') as tfile:
|
with tempfile.NamedTemporaryFile(suffix='.j2k') as tfile:
|
||||||
j = Jp2k(tfile.name, 'wb')
|
j = Jp2k(tfile.name, data=data, subsam=(2, 2), sop=True)
|
||||||
j.write(data, subsam=(2, 2), sop=True)
|
|
||||||
|
|
||||||
codestream = j.get_codestream(header_only=False)
|
codestream = j.get_codestream(header_only=False)
|
||||||
|
|
||||||
kwargs = {'rsiz': 0, 'xysiz': (5183, 3887), 'xyosiz': (0, 0),
|
kwargs = {'rsiz': 0, 'xysiz': (5183, 3887), 'xyosiz': (0, 0),
|
||||||
'xytsiz': (5183, 3887), 'xytosiz': (0, 0),
|
'xytsiz': (5183, 3887), 'xytosiz': (0, 0),
|
||||||
'bitdepth': (8, 8, 8), 'signed': (False, False, False),
|
'bitdepth': (8, 8, 8), 'signed': (False, False, False),
|
||||||
'xyrsiz': [(2, 2, 2), (2, 2, 2)]}
|
'xyrsiz': [(2, 2, 2), (2, 2, 2)]}
|
||||||
self.verifySizSegment(codestream.segment[1], glymur.codestream.SIZsegment(**kwargs))
|
self.verifySizSegment(codestream.segment[1],
|
||||||
|
glymur.codestream.SIZsegment(**kwargs))
|
||||||
|
|
||||||
# COD: Coding style default
|
# COD: Coding style default
|
||||||
self.assertTrue(codestream.segment[2].scod & 2) # sop
|
self.assertTrue(codestream.segment[2].scod & 2) # sop
|
||||||
|
|
@ -443,7 +448,8 @@ class TestSuiteWrite(fixtures.MetadataBase):
|
||||||
self.assertEqual(tuple(codestream.segment[2].code_block_size),
|
self.assertEqual(tuple(codestream.segment[2].code_block_size),
|
||||||
(64, 64)) # cblksz
|
(64, 64)) # cblksz
|
||||||
self.verify_codeblock_style(codestream.segment[2].spcod[7],
|
self.verify_codeblock_style(codestream.segment[2].spcod[7],
|
||||||
[False, False, False, False, False, False])
|
[False, False, False,
|
||||||
|
False, False, False])
|
||||||
self.assertEqual(codestream.segment[2].spcod[8],
|
self.assertEqual(codestream.segment[2].spcod[8],
|
||||||
glymur.core.WAVELET_XFORM_5X3_REVERSIBLE)
|
glymur.core.WAVELET_XFORM_5X3_REVERSIBLE)
|
||||||
self.assertEqual(len(codestream.segment[2].spcod), 9)
|
self.assertEqual(len(codestream.segment[2].spcod), 9)
|
||||||
|
|
@ -458,16 +464,16 @@ class TestSuiteWrite(fixtures.MetadataBase):
|
||||||
infile = opj_data_file('input/nonregression/Bretagne2.ppm')
|
infile = opj_data_file('input/nonregression/Bretagne2.ppm')
|
||||||
data = read_image(infile)
|
data = read_image(infile)
|
||||||
with tempfile.NamedTemporaryFile(suffix='.j2k') as tfile:
|
with tempfile.NamedTemporaryFile(suffix='.j2k') as tfile:
|
||||||
j = Jp2k(tfile.name, 'wb')
|
j = Jp2k(tfile.name, data=data, modesw=38, eph=True)
|
||||||
j.write(data, modesw=38, eph=True)
|
|
||||||
|
|
||||||
codestream = j.get_codestream(header_only=False)
|
codestream = j.get_codestream(header_only=False)
|
||||||
|
|
||||||
kwargs = {'rsiz': 0, 'xysiz': (2592, 1944), 'xyosiz': (0, 0),
|
kwargs = {'rsiz': 0, 'xysiz': (2592, 1944), 'xyosiz': (0, 0),
|
||||||
'xytsiz': (2592, 1944), 'xytosiz': (0, 0),
|
'xytsiz': (2592, 1944), 'xytosiz': (0, 0),
|
||||||
'bitdepth': (8, 8, 8), 'signed': (False, False, False),
|
'bitdepth': (8, 8, 8), 'signed': (False, False, False),
|
||||||
'xyrsiz': [(1, 1, 1), (1, 1, 1)]}
|
'xyrsiz': [(1, 1, 1), (1, 1, 1)]}
|
||||||
self.verifySizSegment(codestream.segment[1], glymur.codestream.SIZsegment(**kwargs))
|
self.verifySizSegment(codestream.segment[1],
|
||||||
|
glymur.codestream.SIZsegment(**kwargs))
|
||||||
|
|
||||||
# COD: Coding style default
|
# COD: Coding style default
|
||||||
self.assertFalse(codestream.segment[2].scod & 2) # no sop
|
self.assertFalse(codestream.segment[2].scod & 2) # no sop
|
||||||
|
|
@ -477,9 +483,10 @@ class TestSuiteWrite(fixtures.MetadataBase):
|
||||||
self.assertEqual(codestream.segment[2].spcod[3], 1) # mct
|
self.assertEqual(codestream.segment[2].spcod[3], 1) # mct
|
||||||
self.assertEqual(codestream.segment[2].spcod[4], 5) # levels
|
self.assertEqual(codestream.segment[2].spcod[4], 5) # levels
|
||||||
self.assertEqual(tuple(codestream.segment[2].code_block_size),
|
self.assertEqual(tuple(codestream.segment[2].code_block_size),
|
||||||
(64, 64)) # cblksz
|
(64, 64)) # cblksz
|
||||||
self.verify_codeblock_style(codestream.segment[2].spcod[7],
|
self.verify_codeblock_style(codestream.segment[2].spcod[7],
|
||||||
[False, True, True, False, False, True])
|
[False, True, True,
|
||||||
|
False, False, True])
|
||||||
self.assertEqual(codestream.segment[2].spcod[8],
|
self.assertEqual(codestream.segment[2].spcod[8],
|
||||||
glymur.core.WAVELET_XFORM_5X3_REVERSIBLE)
|
glymur.core.WAVELET_XFORM_5X3_REVERSIBLE)
|
||||||
self.assertEqual(len(codestream.segment[2].spcod), 9)
|
self.assertEqual(len(codestream.segment[2].spcod), 9)
|
||||||
|
|
@ -493,16 +500,17 @@ class TestSuiteWrite(fixtures.MetadataBase):
|
||||||
infile = opj_data_file('input/nonregression/Bretagne2.ppm')
|
infile = opj_data_file('input/nonregression/Bretagne2.ppm')
|
||||||
data = read_image(infile)
|
data = read_image(infile)
|
||||||
with tempfile.NamedTemporaryFile(suffix='.j2k') as tfile:
|
with tempfile.NamedTemporaryFile(suffix='.j2k') as tfile:
|
||||||
j = Jp2k(tfile.name, 'wb')
|
j = Jp2k(tfile.name,
|
||||||
j.write(data, grid_offset=[300, 150], cratios=[800])
|
data=data, grid_offset=[300, 150], cratios=[800])
|
||||||
|
|
||||||
codestream = j.get_codestream(header_only=False)
|
codestream = j.get_codestream(header_only=False)
|
||||||
|
|
||||||
kwargs = {'rsiz': 0, 'xysiz': (2742, 2244), 'xyosiz': (150, 300),
|
kwargs = {'rsiz': 0, 'xysiz': (2742, 2244), 'xyosiz': (150, 300),
|
||||||
'xytsiz': (2742, 2244), 'xytosiz': (0, 0),
|
'xytsiz': (2742, 2244), 'xytosiz': (0, 0),
|
||||||
'bitdepth': (8, 8, 8), 'signed': (False, False, False),
|
'bitdepth': (8, 8, 8), 'signed': (False, False, False),
|
||||||
'xyrsiz': [(1, 1, 1), (1, 1, 1)]}
|
'xyrsiz': [(1, 1, 1), (1, 1, 1)]}
|
||||||
self.verifySizSegment(codestream.segment[1], glymur.codestream.SIZsegment(**kwargs))
|
self.verifySizSegment(codestream.segment[1],
|
||||||
|
glymur.codestream.SIZsegment(**kwargs))
|
||||||
|
|
||||||
# COD: Coding style default
|
# COD: Coding style default
|
||||||
self.assertFalse(codestream.segment[2].scod & 2) # no sop
|
self.assertFalse(codestream.segment[2].scod & 2) # no sop
|
||||||
|
|
@ -514,7 +522,8 @@ class TestSuiteWrite(fixtures.MetadataBase):
|
||||||
self.assertEqual(tuple(codestream.segment[2].code_block_size),
|
self.assertEqual(tuple(codestream.segment[2].code_block_size),
|
||||||
(64, 64)) # cblksz
|
(64, 64)) # cblksz
|
||||||
self.verify_codeblock_style(codestream.segment[2].spcod[7],
|
self.verify_codeblock_style(codestream.segment[2].spcod[7],
|
||||||
[False, False, False, False, False, False])
|
[False, False, False,
|
||||||
|
False, False, False])
|
||||||
self.assertEqual(codestream.segment[2].spcod[8],
|
self.assertEqual(codestream.segment[2].spcod[8],
|
||||||
glymur.core.WAVELET_XFORM_5X3_REVERSIBLE)
|
glymur.core.WAVELET_XFORM_5X3_REVERSIBLE)
|
||||||
self.assertEqual(len(codestream.segment[2].spcod), 9)
|
self.assertEqual(len(codestream.segment[2].spcod), 9)
|
||||||
|
|
@ -524,16 +533,16 @@ class TestSuiteWrite(fixtures.MetadataBase):
|
||||||
infile = opj_data_file('input/nonregression/Cevennes1.bmp')
|
infile = opj_data_file('input/nonregression/Cevennes1.bmp')
|
||||||
data = read_image(infile)
|
data = read_image(infile)
|
||||||
with tempfile.NamedTemporaryFile(suffix='.j2k') as tfile:
|
with tempfile.NamedTemporaryFile(suffix='.j2k') as tfile:
|
||||||
j = Jp2k(tfile.name, 'wb')
|
j = Jp2k(tfile.name, data=data, cratios=[800])
|
||||||
j.write(data, cratios=[800])
|
|
||||||
|
|
||||||
codestream = j.get_codestream(header_only=False)
|
codestream = j.get_codestream(header_only=False)
|
||||||
|
|
||||||
kwargs = {'rsiz': 0, 'xysiz': (2592, 1944), 'xyosiz': (0, 0),
|
kwargs = {'rsiz': 0, 'xysiz': (2592, 1944), 'xyosiz': (0, 0),
|
||||||
'xytsiz': (2592, 1944), 'xytosiz': (0, 0),
|
'xytsiz': (2592, 1944), 'xytosiz': (0, 0),
|
||||||
'bitdepth': (8, 8, 8), 'signed': (False, False, False),
|
'bitdepth': (8, 8, 8), 'signed': (False, False, False),
|
||||||
'xyrsiz': [(1, 1, 1), (1, 1, 1)]}
|
'xyrsiz': [(1, 1, 1), (1, 1, 1)]}
|
||||||
self.verifySizSegment(codestream.segment[1], glymur.codestream.SIZsegment(**kwargs))
|
self.verifySizSegment(codestream.segment[1],
|
||||||
|
glymur.codestream.SIZsegment(**kwargs))
|
||||||
|
|
||||||
# COD: Coding style default
|
# COD: Coding style default
|
||||||
self.assertFalse(codestream.segment[2].scod & 2) # no sop
|
self.assertFalse(codestream.segment[2].scod & 2) # no sop
|
||||||
|
|
@ -545,7 +554,8 @@ class TestSuiteWrite(fixtures.MetadataBase):
|
||||||
self.assertEqual(tuple(codestream.segment[2].code_block_size),
|
self.assertEqual(tuple(codestream.segment[2].code_block_size),
|
||||||
(64, 64)) # cblksz
|
(64, 64)) # cblksz
|
||||||
self.verify_codeblock_style(codestream.segment[2].spcod[7],
|
self.verify_codeblock_style(codestream.segment[2].spcod[7],
|
||||||
[False, False, False, False, False, False])
|
[False, False, False,
|
||||||
|
False, False, False])
|
||||||
self.assertEqual(codestream.segment[2].spcod[8],
|
self.assertEqual(codestream.segment[2].spcod[8],
|
||||||
glymur.core.WAVELET_XFORM_5X3_REVERSIBLE)
|
glymur.core.WAVELET_XFORM_5X3_REVERSIBLE)
|
||||||
self.assertEqual(len(codestream.segment[2].spcod), 9)
|
self.assertEqual(len(codestream.segment[2].spcod), 9)
|
||||||
|
|
@ -555,16 +565,16 @@ class TestSuiteWrite(fixtures.MetadataBase):
|
||||||
infile = opj_data_file('input/nonregression/Cevennes2.ppm')
|
infile = opj_data_file('input/nonregression/Cevennes2.ppm')
|
||||||
data = read_image(infile)
|
data = read_image(infile)
|
||||||
with tempfile.NamedTemporaryFile(suffix='.j2k') as tfile:
|
with tempfile.NamedTemporaryFile(suffix='.j2k') as tfile:
|
||||||
j = Jp2k(tfile.name, 'wb')
|
j = Jp2k(tfile.name, data=data, cratios=[50])
|
||||||
j.write(data, cratios=[50])
|
|
||||||
|
|
||||||
codestream = j.get_codestream(header_only=False)
|
codestream = j.get_codestream(header_only=False)
|
||||||
|
|
||||||
kwargs = {'rsiz': 0, 'xysiz': (640, 480), 'xyosiz': (0, 0),
|
kwargs = {'rsiz': 0, 'xysiz': (640, 480), 'xyosiz': (0, 0),
|
||||||
'xytsiz': (640, 480), 'xytosiz': (0, 0),
|
'xytsiz': (640, 480), 'xytosiz': (0, 0),
|
||||||
'bitdepth': (8, 8, 8), 'signed': (False, False, False),
|
'bitdepth': (8, 8, 8), 'signed': (False, False, False),
|
||||||
'xyrsiz': [(1, 1, 1), (1, 1, 1)]}
|
'xyrsiz': [(1, 1, 1), (1, 1, 1)]}
|
||||||
self.verifySizSegment(codestream.segment[1], glymur.codestream.SIZsegment(**kwargs))
|
self.verifySizSegment(codestream.segment[1],
|
||||||
|
glymur.codestream.SIZsegment(**kwargs))
|
||||||
|
|
||||||
# COD: Coding style default
|
# COD: Coding style default
|
||||||
self.assertFalse(codestream.segment[2].scod & 2) # no sop
|
self.assertFalse(codestream.segment[2].scod & 2) # no sop
|
||||||
|
|
@ -576,7 +586,8 @@ class TestSuiteWrite(fixtures.MetadataBase):
|
||||||
self.assertEqual(tuple(codestream.segment[2].code_block_size),
|
self.assertEqual(tuple(codestream.segment[2].code_block_size),
|
||||||
(64, 64)) # cblksz
|
(64, 64)) # cblksz
|
||||||
self.verify_codeblock_style(codestream.segment[2].spcod[7],
|
self.verify_codeblock_style(codestream.segment[2].spcod[7],
|
||||||
[False, False, False, False, False, False])
|
[False, False, False,
|
||||||
|
False, False, False])
|
||||||
self.assertEqual(codestream.segment[2].spcod[8],
|
self.assertEqual(codestream.segment[2].spcod[8],
|
||||||
glymur.core.WAVELET_XFORM_5X3_REVERSIBLE)
|
glymur.core.WAVELET_XFORM_5X3_REVERSIBLE)
|
||||||
self.assertEqual(len(codestream.segment[2].spcod), 9)
|
self.assertEqual(len(codestream.segment[2].spcod), 9)
|
||||||
|
|
@ -585,8 +596,8 @@ class TestSuiteWrite(fixtures.MetadataBase):
|
||||||
"""NR-ENC-Rome.bmp-11-encode"""
|
"""NR-ENC-Rome.bmp-11-encode"""
|
||||||
data = read_image(opj_data_file('input/nonregression/Rome.bmp'))
|
data = read_image(opj_data_file('input/nonregression/Rome.bmp'))
|
||||||
with tempfile.NamedTemporaryFile(suffix='.jp2') as tfile:
|
with tempfile.NamedTemporaryFile(suffix='.jp2') as tfile:
|
||||||
jp2 = Jp2k(tfile.name, 'wb')
|
jp2 = Jp2k(tfile.name,
|
||||||
jp2.write(data, psnr=[30, 35, 50], prog='LRCP', numres=3)
|
data=data, psnr=[30, 35, 50], prog='LRCP', numres=3)
|
||||||
|
|
||||||
ids = [box.box_id for box in jp2.box]
|
ids = [box.box_id for box in jp2.box]
|
||||||
self.assertEqual(ids, ['jP ', 'ftyp', 'jp2h', 'jp2c'])
|
self.assertEqual(ids, ['jP ', 'ftyp', 'jp2h', 'jp2c'])
|
||||||
|
|
@ -621,13 +632,14 @@ class TestSuiteWrite(fixtures.MetadataBase):
|
||||||
self.assertIsNone(jp2.box[2].box[1].icc_profile)
|
self.assertIsNone(jp2.box[2].box[1].icc_profile)
|
||||||
self.assertEqual(jp2.box[2].box[1].colorspace, glymur.core.SRGB)
|
self.assertEqual(jp2.box[2].box[1].colorspace, glymur.core.SRGB)
|
||||||
|
|
||||||
codestream = jp2.box[3].main_header
|
codestream = jp2.box[3].codestream
|
||||||
|
|
||||||
kwargs = {'rsiz': 0, 'xysiz': (640, 480), 'xyosiz': (0, 0),
|
kwargs = {'rsiz': 0, 'xysiz': (640, 480), 'xyosiz': (0, 0),
|
||||||
'xytsiz': (640, 480), 'xytosiz': (0, 0),
|
'xytsiz': (640, 480), 'xytosiz': (0, 0),
|
||||||
'bitdepth': (8, 8, 8), 'signed': (False, False, False),
|
'bitdepth': (8, 8, 8), 'signed': (False, False, False),
|
||||||
'xyrsiz': [(1, 1, 1), (1, 1, 1)]}
|
'xyrsiz': [(1, 1, 1), (1, 1, 1)]}
|
||||||
self.verifySizSegment(codestream.segment[1], glymur.codestream.SIZsegment(**kwargs))
|
self.verifySizSegment(codestream.segment[1],
|
||||||
|
glymur.codestream.SIZsegment(**kwargs))
|
||||||
|
|
||||||
# COD: Coding style default
|
# COD: Coding style default
|
||||||
self.assertFalse(codestream.segment[2].scod & 2) # no sop
|
self.assertFalse(codestream.segment[2].scod & 2) # no sop
|
||||||
|
|
@ -639,7 +651,8 @@ class TestSuiteWrite(fixtures.MetadataBase):
|
||||||
self.assertEqual(tuple(codestream.segment[2].code_block_size),
|
self.assertEqual(tuple(codestream.segment[2].code_block_size),
|
||||||
(64, 64)) # cblksz
|
(64, 64)) # cblksz
|
||||||
self.verify_codeblock_style(codestream.segment[2].spcod[7],
|
self.verify_codeblock_style(codestream.segment[2].spcod[7],
|
||||||
[False, False, False, False, False, False])
|
[False, False, False,
|
||||||
|
False, False, False])
|
||||||
self.assertEqual(codestream.segment[2].spcod[8],
|
self.assertEqual(codestream.segment[2].spcod[8],
|
||||||
glymur.core.WAVELET_XFORM_5X3_REVERSIBLE)
|
glymur.core.WAVELET_XFORM_5X3_REVERSIBLE)
|
||||||
self.assertEqual(len(codestream.segment[2].spcod), 9)
|
self.assertEqual(len(codestream.segment[2].spcod), 9)
|
||||||
|
|
@ -651,16 +664,16 @@ class TestSuiteWrite(fixtures.MetadataBase):
|
||||||
infile = opj_data_file('input/nonregression/random-issue-0005.tif')
|
infile = opj_data_file('input/nonregression/random-issue-0005.tif')
|
||||||
data = read_image(infile)
|
data = read_image(infile)
|
||||||
with tempfile.NamedTemporaryFile(suffix='.j2k') as tfile:
|
with tempfile.NamedTemporaryFile(suffix='.j2k') as tfile:
|
||||||
j = Jp2k(tfile.name, 'wb')
|
j = Jp2k(tfile.name, data=data)
|
||||||
j.write(data)
|
|
||||||
|
|
||||||
codestream = j.get_codestream(header_only=False)
|
codestream = j.get_codestream(header_only=False)
|
||||||
|
|
||||||
kwargs = {'rsiz': 0, 'xysiz': (1024, 1024), 'xyosiz': (0, 0),
|
kwargs = {'rsiz': 0, 'xysiz': (1024, 1024), 'xyosiz': (0, 0),
|
||||||
'xytsiz': (1024, 1024), 'xytosiz': (0, 0),
|
'xytsiz': (1024, 1024), 'xytosiz': (0, 0),
|
||||||
'bitdepth': (16,), 'signed': (False,),
|
'bitdepth': (16,), 'signed': (False,),
|
||||||
'xyrsiz': [(1,), (1,)]}
|
'xyrsiz': [(1,), (1,)]}
|
||||||
self.verifySizSegment(codestream.segment[1], glymur.codestream.SIZsegment(**kwargs))
|
self.verifySizSegment(codestream.segment[1],
|
||||||
|
glymur.codestream.SIZsegment(**kwargs))
|
||||||
|
|
||||||
# COD: Coding style default
|
# COD: Coding style default
|
||||||
self.assertFalse(codestream.segment[2].scod & 2) # no sop
|
self.assertFalse(codestream.segment[2].scod & 2) # no sop
|
||||||
|
|
@ -672,7 +685,8 @@ class TestSuiteWrite(fixtures.MetadataBase):
|
||||||
self.assertEqual(tuple(codestream.segment[2].code_block_size),
|
self.assertEqual(tuple(codestream.segment[2].code_block_size),
|
||||||
(64, 64)) # cblksz
|
(64, 64)) # cblksz
|
||||||
self.verify_codeblock_style(codestream.segment[2].spcod[7],
|
self.verify_codeblock_style(codestream.segment[2].spcod[7],
|
||||||
[False, False, False, False, False, False])
|
[False, False, False,
|
||||||
|
False, False, False])
|
||||||
self.assertEqual(codestream.segment[2].spcod[8],
|
self.assertEqual(codestream.segment[2].spcod[8],
|
||||||
glymur.core.WAVELET_XFORM_5X3_REVERSIBLE)
|
glymur.core.WAVELET_XFORM_5X3_REVERSIBLE)
|
||||||
self.assertEqual(len(codestream.segment[2].spcod), 9)
|
self.assertEqual(len(codestream.segment[2].spcod), 9)
|
||||||
|
|
|
||||||
|
|
@ -1,15 +1,6 @@
|
||||||
# -*- coding: utf-8 -*-
|
# -*- coding: utf-8 -*-
|
||||||
"""Test suite for printing.
|
"""Test suite for printing.
|
||||||
"""
|
"""
|
||||||
# C0302: don't care too much about having too many lines in a test module
|
|
||||||
# pylint: disable=C0302
|
|
||||||
|
|
||||||
# E061: unittest.mock introduced in 3.3 (python-2.7/pylint issue)
|
|
||||||
# pylint: disable=E0611,F0401
|
|
||||||
|
|
||||||
# R0904: Not too many methods in unittest.
|
|
||||||
# pylint: disable=R0904
|
|
||||||
|
|
||||||
import os
|
import os
|
||||||
import re
|
import re
|
||||||
import struct
|
import struct
|
||||||
|
|
@ -32,12 +23,14 @@ import lxml.etree as ET
|
||||||
import glymur
|
import glymur
|
||||||
from glymur import Jp2k, command_line
|
from glymur import Jp2k, command_line
|
||||||
from . import fixtures
|
from . import fixtures
|
||||||
from .fixtures import OPJ_DATA_ROOT, opj_data_file
|
from .fixtures import (OPJ_DATA_ROOT, opj_data_file,
|
||||||
from .fixtures import WARNING_INFRASTRUCTURE_ISSUE, WARNING_INFRASTRUCTURE_MSG
|
WARNING_INFRASTRUCTURE_ISSUE,
|
||||||
from .fixtures import text_gbr_27, text_gbr_33, text_gbr_34
|
WARNING_INFRASTRUCTURE_MSG,
|
||||||
|
WINDOWS_TMP_FILE_MSG,
|
||||||
|
text_gbr_27, text_gbr_33, text_gbr_34)
|
||||||
|
|
||||||
|
|
||||||
@unittest.skipIf(os.name == "nt", "Temporary file issue on window.")
|
@unittest.skipIf(os.name == "nt", WINDOWS_TMP_FILE_MSG)
|
||||||
class TestPrinting(unittest.TestCase):
|
class TestPrinting(unittest.TestCase):
|
||||||
"""Tests for verifying how printing works."""
|
"""Tests for verifying how printing works."""
|
||||||
def setUp(self):
|
def setUp(self):
|
||||||
|
|
@ -49,25 +42,13 @@ class TestPrinting(unittest.TestCase):
|
||||||
glymur.set_printoptions(short=False, xml=True, codestream=True)
|
glymur.set_printoptions(short=False, xml=True, codestream=True)
|
||||||
|
|
||||||
def tearDown(self):
|
def tearDown(self):
|
||||||
pass
|
glymur.set_parseoptions(full_codestream=False)
|
||||||
|
|
||||||
def test_codestream(self):
|
|
||||||
"""Should be able to print a raw codestream."""
|
|
||||||
j = glymur.Jp2k(self.j2kfile)
|
|
||||||
with patch('sys.stdout', new=StringIO()) as fake_out:
|
|
||||||
print(j)
|
|
||||||
actual = fake_out.getvalue().strip()
|
|
||||||
# Remove the file line, as that is filesystem-dependent.
|
|
||||||
lines = actual.split('\n')
|
|
||||||
actual = '\n'.join(lines[1:])
|
|
||||||
|
|
||||||
self.assertEqual(actual, fixtures.codestream)
|
|
||||||
|
|
||||||
def test_version_info(self):
|
def test_version_info(self):
|
||||||
"""Should be able to print(glymur.version.info)"""
|
"""Should be able to print(glymur.version.info)"""
|
||||||
with patch('sys.stdout', new=StringIO()) as fake_out:
|
with patch('sys.stdout', new=StringIO()) as fake_out:
|
||||||
print(glymur.version.info)
|
print(glymur.version.info)
|
||||||
actual = fake_out.getvalue().strip()
|
fake_out.getvalue().strip()
|
||||||
|
|
||||||
self.assertTrue(True)
|
self.assertTrue(True)
|
||||||
|
|
||||||
|
|
@ -77,7 +58,7 @@ class TestPrinting(unittest.TestCase):
|
||||||
with tempfile.NamedTemporaryFile(suffix='.jpx') as tfile:
|
with tempfile.NamedTemporaryFile(suffix='.jpx') as tfile:
|
||||||
with open(self.jpxfile, 'rb') as ifile:
|
with open(self.jpxfile, 'rb') as ifile:
|
||||||
tfile.write(ifile.read())
|
tfile.write(ifile.read())
|
||||||
|
|
||||||
# Add the header for an unknown superbox.
|
# Add the header for an unknown superbox.
|
||||||
write_buffer = struct.pack('>I4s', 20, 'grp '.encode())
|
write_buffer = struct.pack('>I4s', 20, 'grp '.encode())
|
||||||
tfile.write(write_buffer)
|
tfile.write(write_buffer)
|
||||||
|
|
@ -106,16 +87,17 @@ class TestPrinting(unittest.TestCase):
|
||||||
with self.assertRaises(TypeError):
|
with self.assertRaises(TypeError):
|
||||||
glymur.set_printoptions(hi='low')
|
glymur.set_printoptions(hi='low')
|
||||||
|
|
||||||
|
@unittest.skipIf(re.match("1.5|2",
|
||||||
|
glymur.version.openjpeg_version) is None,
|
||||||
|
"Must have openjpeg 1.5 or higher to run")
|
||||||
def test_asoc_label_box(self):
|
def test_asoc_label_box(self):
|
||||||
"""verify printing of asoc, label boxes"""
|
"""verify printing of asoc, label boxes"""
|
||||||
# Construct a fake file with an asoc and a label box, as
|
# Construct a fake file with an asoc and a label box, as
|
||||||
# OpenJPEG doesn't have such a file.
|
# OpenJPEG doesn't have such a file.
|
||||||
data = glymur.Jp2k(self.jp2file).read(rlevel=1)
|
data = glymur.Jp2k(self.jp2file)[::2, ::2]
|
||||||
with tempfile.NamedTemporaryFile(suffix='.jp2') as tfile:
|
with tempfile.NamedTemporaryFile(suffix='.jp2') as tfile:
|
||||||
j = glymur.Jp2k(tfile.name, 'wb')
|
|
||||||
j.write(data)
|
|
||||||
|
|
||||||
with tempfile.NamedTemporaryFile(suffix='.jp2') as tfile2:
|
with tempfile.NamedTemporaryFile(suffix='.jp2') as tfile2:
|
||||||
|
glymur.Jp2k(tfile.name, data=data)
|
||||||
|
|
||||||
# Offset of the codestream is where we start.
|
# Offset of the codestream is where we start.
|
||||||
wbuffer = tfile.read(77)
|
wbuffer = tfile.read(77)
|
||||||
|
|
@ -417,7 +399,7 @@ class TestPrinting(unittest.TestCase):
|
||||||
@unittest.skipIf(sys.hexversion < 0x03000000,
|
@unittest.skipIf(sys.hexversion < 0x03000000,
|
||||||
"Only trusting python3 for printing non-ascii chars")
|
"Only trusting python3 for printing non-ascii chars")
|
||||||
def test_xml_cyrrilic(self):
|
def test_xml_cyrrilic(self):
|
||||||
"""Should be able to print an XMLBox with utf-8 encoding (cyrrillic)."""
|
"""Should be able to print XMLBox with utf-8 encoding (cyrrillic)."""
|
||||||
# Seems to be inconsistencies between different versions of python2.x
|
# Seems to be inconsistencies between different versions of python2.x
|
||||||
# as to what gets printed.
|
# as to what gets printed.
|
||||||
#
|
#
|
||||||
|
|
@ -435,7 +417,8 @@ class TestPrinting(unittest.TestCase):
|
||||||
actual = fake_out.getvalue().strip()
|
actual = fake_out.getvalue().strip()
|
||||||
if sys.hexversion < 0x03000000:
|
if sys.hexversion < 0x03000000:
|
||||||
lines = ["XML Box (xml ) @ (-1, 0)",
|
lines = ["XML Box (xml ) @ (-1, 0)",
|
||||||
" <country>Россия</country>"]
|
(" <country>Росс",
|
||||||
|
"ия</country>")]
|
||||||
else:
|
else:
|
||||||
lines = ["XML Box (xml ) @ (-1, 0)",
|
lines = ["XML Box (xml ) @ (-1, 0)",
|
||||||
" <country>Россия</country>"]
|
" <country>Россия</country>"]
|
||||||
|
|
@ -611,7 +594,8 @@ class TestPrinting(unittest.TestCase):
|
||||||
|
|
||||||
lines = ["UUID Box (uuid) @ (1135519, 76)",
|
lines = ["UUID Box (uuid) @ (1135519, 76)",
|
||||||
" UUID: 4a706754-6966-6645-7869-662d3e4a5032 (EXIF)",
|
" UUID: 4a706754-6966-6645-7869-662d3e4a5032 (EXIF)",
|
||||||
" UUID Data: OrderedDict([('ImageWidth', 256), ('ImageLength', 512), ('Make', 'HTC')])"]
|
(" UUID Data: OrderedDict([('ImageWidth', 256),"
|
||||||
|
" ('ImageLength', 512), ('Make', 'HTC')])")]
|
||||||
|
|
||||||
expected = '\n'.join(lines)
|
expected = '\n'.join(lines)
|
||||||
|
|
||||||
|
|
@ -825,6 +809,7 @@ class TestPrintingOpjDataRoot(unittest.TestCase):
|
||||||
expected = '\n'.join(lines)
|
expected = '\n'.join(lines)
|
||||||
self.assertEqual(actual, expected)
|
self.assertEqual(actual, expected)
|
||||||
|
|
||||||
|
|
||||||
@unittest.skipIf(OPJ_DATA_ROOT is None,
|
@unittest.skipIf(OPJ_DATA_ROOT is None,
|
||||||
"OPJ_DATA_ROOT environment variable not set")
|
"OPJ_DATA_ROOT environment variable not set")
|
||||||
@unittest.skipIf(os.name == "nt", "Temporary file issue on window.")
|
@unittest.skipIf(os.name == "nt", "Temporary file issue on window.")
|
||||||
|
|
@ -846,20 +831,31 @@ class TestPrintingOpjDataRootWarns(unittest.TestCase):
|
||||||
def tearDown(self):
|
def tearDown(self):
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
def test_invalid_colour_specification_method(self):
|
||||||
|
"""should not error out with invalid colour specification method"""
|
||||||
|
# Don't care so much about what the output looks like, just that we
|
||||||
|
# do not error out.
|
||||||
|
filename = opj_data_file('input/nonregression/issue397.jp2')
|
||||||
|
with self.assertWarns(UserWarning):
|
||||||
|
jp2 = Jp2k(filename)
|
||||||
|
with patch('sys.stdout', new=StringIO()):
|
||||||
|
print(jp2)
|
||||||
|
self.assertTrue(True)
|
||||||
|
|
||||||
def test_invalid_colorspace(self):
|
def test_invalid_colorspace(self):
|
||||||
"""An invalid colorspace shouldn't cause an error."""
|
"""An invalid colorspace shouldn't cause an error."""
|
||||||
filename = opj_data_file('input/nonregression/edf_c2_1103421.jp2')
|
filename = opj_data_file('input/nonregression/edf_c2_1103421.jp2')
|
||||||
with self.assertWarns(UserWarning):
|
with self.assertWarns(UserWarning):
|
||||||
jp2 = Jp2k(filename)
|
jp2 = Jp2k(filename)
|
||||||
with patch('sys.stdout', new=StringIO()) as fake_out:
|
with patch('sys.stdout', new=StringIO()):
|
||||||
print(jp2)
|
print(jp2)
|
||||||
|
|
||||||
def test_bad_rsiz(self):
|
def test_bad_rsiz(self):
|
||||||
"""Should still be able to print if rsiz is bad, issue196"""
|
"""Should still be able to print if rsiz is bad, issue196"""
|
||||||
filename = opj_data_file('input/nonregression/edf_c2_1002767.jp2')
|
filename = opj_data_file('input/nonregression/edf_c2_1002767.jp2')
|
||||||
with self.assertWarns(UserWarning):
|
with self.assertWarns(UserWarning):
|
||||||
j = Jp2k(filename)
|
j = Jp2k(filename).get_codestream()
|
||||||
with patch('sys.stdout', new=StringIO()) as fake_out:
|
with patch('sys.stdout', new=StringIO()):
|
||||||
print(j)
|
print(j)
|
||||||
|
|
||||||
def test_bad_wavelet_transform(self):
|
def test_bad_wavelet_transform(self):
|
||||||
|
|
@ -867,7 +863,7 @@ class TestPrintingOpjDataRootWarns(unittest.TestCase):
|
||||||
filename = opj_data_file('input/nonregression/edf_c2_10025.jp2')
|
filename = opj_data_file('input/nonregression/edf_c2_10025.jp2')
|
||||||
with self.assertWarns(UserWarning):
|
with self.assertWarns(UserWarning):
|
||||||
jp2 = Jp2k(filename)
|
jp2 = Jp2k(filename)
|
||||||
with patch('sys.stdout', new=StringIO()) as fake_out:
|
with patch('sys.stdout', new=StringIO()):
|
||||||
print(jp2)
|
print(jp2)
|
||||||
|
|
||||||
def test_invalid_progression_order(self):
|
def test_invalid_progression_order(self):
|
||||||
|
|
@ -1028,7 +1024,7 @@ class TestPrintingOpjDataRootWarns(unittest.TestCase):
|
||||||
'issue171.jp2'))
|
'issue171.jp2'))
|
||||||
with self.assertWarns(UserWarning):
|
with self.assertWarns(UserWarning):
|
||||||
jp2 = Jp2k(filename)
|
jp2 = Jp2k(filename)
|
||||||
with patch('sys.stdout', new=StringIO()) as fake_out:
|
with patch('sys.stdout', new=StringIO()):
|
||||||
# No need to verify, it's enough that we don't error out.
|
# No need to verify, it's enough that we don't error out.
|
||||||
print(jp2)
|
print(jp2)
|
||||||
|
|
||||||
|
|
@ -1044,9 +1040,10 @@ class TestJp2dump(unittest.TestCase):
|
||||||
|
|
||||||
# Reset printoptions for every test.
|
# Reset printoptions for every test.
|
||||||
glymur.set_printoptions(short=False, xml=True, codestream=True)
|
glymur.set_printoptions(short=False, xml=True, codestream=True)
|
||||||
|
glymur.set_parseoptions(full_codestream=False)
|
||||||
|
|
||||||
def tearDown(self):
|
def tearDown(self):
|
||||||
pass
|
glymur.set_parseoptions(full_codestream=False)
|
||||||
|
|
||||||
def run_jp2dump(self, args):
|
def run_jp2dump(self, args):
|
||||||
sys.argv = args
|
sys.argv = args
|
||||||
|
|
@ -1059,24 +1056,53 @@ class TestJp2dump(unittest.TestCase):
|
||||||
return actual
|
return actual
|
||||||
|
|
||||||
def test_default_nemo(self):
|
def test_default_nemo(self):
|
||||||
"""Should be able to dump a JP2 file's metadata with no codestream."""
|
"""by default one should get the main header"""
|
||||||
actual = self.run_jp2dump(['', self.jp2file])
|
actual = self.run_jp2dump(['', self.jp2file])
|
||||||
|
|
||||||
self.assertEqual(actual, fixtures.nemo_dump_no_codestream)
|
# shave off the non-main-header segments
|
||||||
|
lines = fixtures.nemo.split('\n')
|
||||||
|
expected = lines[0:140]
|
||||||
|
expected = '\n'.join(expected)
|
||||||
|
self.assertEqual(actual, expected)
|
||||||
|
|
||||||
def test_codestream_0(self):
|
def test_jp2_codestream_0(self):
|
||||||
"""Verify dumping with -c 0, supressing all codestream details."""
|
"""Verify dumping with -c 0, supressing all codestream details."""
|
||||||
actual = self.run_jp2dump(['', '-c', '0', self.jp2file])
|
actual = self.run_jp2dump(['', '-c', '0', self.jp2file])
|
||||||
|
|
||||||
self.assertEqual(actual, fixtures.nemo_dump_no_codestream)
|
# shave off the codestream details
|
||||||
|
lines = fixtures.nemo.split('\n')
|
||||||
|
expected = lines[0:105]
|
||||||
|
expected = '\n'.join(expected)
|
||||||
|
self.assertEqual(actual, expected)
|
||||||
|
|
||||||
def test_codestream_1(self):
|
def test_jp2_codestream_1(self):
|
||||||
"""Verify dumping with -c 1, print just the header."""
|
"""Verify dumping with -c 1, print just the header."""
|
||||||
actual = self.run_jp2dump(['', '-c', '1', self.jp2file])
|
actual = self.run_jp2dump(['', '-c', '1', self.jp2file])
|
||||||
|
|
||||||
self.assertEqual(actual, fixtures.nemo_with_codestream_header)
|
# shave off the non-main-header segments
|
||||||
|
lines = fixtures.nemo.split('\n')
|
||||||
|
expected = lines[0:140]
|
||||||
|
expected = '\n'.join(expected)
|
||||||
|
self.assertEqual(actual, expected)
|
||||||
|
|
||||||
def test_codestream_2(self):
|
def test_jp2_codestream_2(self):
|
||||||
|
"""Verify dumping with -c 2, print entire jp2 jacket, codestream."""
|
||||||
|
actual = self.run_jp2dump(['', '-c', '2', self.jp2file])
|
||||||
|
|
||||||
|
# shave off the non-main-header segments
|
||||||
|
expected = fixtures.nemo
|
||||||
|
self.assertEqual(actual, expected)
|
||||||
|
|
||||||
|
@unittest.skipIf(sys.hexversion < 0x03000000, "assertRegex not in 2.7")
|
||||||
|
def test_j2k_codestream_0(self):
|
||||||
|
"""-c 0 should print just a single line when used on a codestream."""
|
||||||
|
sys.argv = ['', '-c', '0', self.j2kfile]
|
||||||
|
with patch('sys.stdout', new=StringIO()) as fake_out:
|
||||||
|
command_line.main()
|
||||||
|
actual = fake_out.getvalue().strip()
|
||||||
|
self.assertRegex(actual, "File: .*")
|
||||||
|
|
||||||
|
def test_j2k_codestream_2(self):
|
||||||
"""Verify dumping with -c 2, full details."""
|
"""Verify dumping with -c 2, full details."""
|
||||||
with patch('sys.stdout', new=StringIO()) as fake_out:
|
with patch('sys.stdout', new=StringIO()) as fake_out:
|
||||||
sys.argv = ['', '-c', '2', self.j2kfile]
|
sys.argv = ['', '-c', '2', self.j2kfile]
|
||||||
|
|
@ -1101,4 +1127,9 @@ class TestJp2dump(unittest.TestCase):
|
||||||
"""Verify dumping with -x, suppress XML."""
|
"""Verify dumping with -x, suppress XML."""
|
||||||
actual = self.run_jp2dump(['', '-x', self.jp2file])
|
actual = self.run_jp2dump(['', '-x', self.jp2file])
|
||||||
|
|
||||||
self.assertEqual(actual, fixtures.nemo_dump_no_codestream_no_xml)
|
# shave off the XML and non-main-header segments
|
||||||
|
lines = fixtures.nemo.split('\n')
|
||||||
|
expected = lines[0:18]
|
||||||
|
expected.extend(lines[104:140])
|
||||||
|
expected = '\n'.join(expected)
|
||||||
|
self.assertEqual(actual, expected)
|
||||||
|
|
|
||||||
|
|
@ -14,12 +14,11 @@ from distutils.version import LooseVersion
|
||||||
import lxml.etree
|
import lxml.etree
|
||||||
import numpy as np
|
import numpy as np
|
||||||
|
|
||||||
from .lib import openjpeg as opj
|
from .lib import openjpeg as opj, openjp2 as opj2
|
||||||
from .lib import openjp2 as opj2
|
|
||||||
|
|
||||||
# Do not change the format of this next line! Doing so risks breaking
|
# Do not change the format of this next line! Doing so risks breaking
|
||||||
# setup.py
|
# setup.py
|
||||||
version = "0.7.2"
|
version = "0.8.0"
|
||||||
_sv = LooseVersion(version)
|
_sv = LooseVersion(version)
|
||||||
version_tuple = _sv.version
|
version_tuple = _sv.version
|
||||||
|
|
||||||
|
|
|
||||||
14
setup.py
14
setup.py
|
|
@ -1,4 +1,4 @@
|
||||||
from setuptools import setup, find_packages
|
from setuptools import setup
|
||||||
import os
|
import os
|
||||||
import re
|
import re
|
||||||
import sys
|
import sys
|
||||||
|
|
@ -11,18 +11,20 @@ kwargs = {'name': 'Glymur',
|
||||||
'url': 'https://github.com/quintusdias/glymur',
|
'url': 'https://github.com/quintusdias/glymur',
|
||||||
'packages': ['glymur', 'glymur.data', 'glymur.test', 'glymur.lib',
|
'packages': ['glymur', 'glymur.data', 'glymur.test', 'glymur.lib',
|
||||||
'glymur.lib.test'],
|
'glymur.lib.test'],
|
||||||
'package_data': {'glymur': ['data/*.jp2', 'data/*.j2k', 'data/*.jpx']},
|
'package_data': {'glymur': ['data/*.jp2',
|
||||||
|
'data/*.j2k',
|
||||||
|
'data/*.jpx']},
|
||||||
'entry_points': {
|
'entry_points': {
|
||||||
'console_scripts': ['jp2dump=glymur.command_line:main'],
|
'console_scripts': ['jp2dump=glymur.command_line:main'],
|
||||||
},
|
},
|
||||||
'license': 'MIT',
|
'license': 'MIT',
|
||||||
'test_suite': 'glymur.test'}
|
'test_suite': 'glymur.test'}
|
||||||
|
|
||||||
instllrqrs = ['numpy>=1.4.1', 'lxml>=2.3.2']
|
install_requires = ['numpy>=1.7.0', 'lxml>=3.0.0']
|
||||||
if sys.hexversion < 0x03030000:
|
if sys.hexversion < 0x03030000:
|
||||||
instllrqrs.append('contextlib2>=0.4')
|
install_requires.append('contextlib2>=0.4')
|
||||||
instllrqrs.append('mock>=1.0.1')
|
install_requires.append('mock>=1.0.1')
|
||||||
kwargs['install_requires'] = instllrqrs
|
kwargs['install_requires'] = install_requires
|
||||||
|
|
||||||
clssfrs = ["Programming Language :: Python",
|
clssfrs = ["Programming Language :: Python",
|
||||||
"Programming Language :: Python :: 2.7",
|
"Programming Language :: Python :: 2.7",
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue