diff --git a/.travis.yml b/.travis.yml index 406e470..822c717 100644 --- a/.travis.yml +++ b/.travis.yml @@ -9,6 +9,7 @@ before_install: - sudo apt-get install -qq python-numpy - wget http://openjpeg.googlecode.com/files/openjpeg-1.5.0-Linux-x86_64.tar.gz - sudo tar -xvf openjpeg-1.5.0-Linux-x86_64.tar.gz --strip-components=1 -C / + - pip install coveralls # command to install dependencies install: @@ -19,6 +20,11 @@ install: # command to run tests script: - python -m unittest discover +after_success: + - if [[ $ENV == pythone=3.4* ]]; then + coveralls; + fi + notifications: email: "john.g.evans.ne@gmail.com" diff --git a/CHANGES.txt b/CHANGES.txt index 042e351..758941b 100644 --- a/CHANGES.txt +++ b/CHANGES.txt @@ -1,8 +1,3 @@ -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 02, 2014 - v0.7.1 Fixed README to mention Python 3.4 diff --git a/docs/source/api.rst b/docs/source/api.rst new file mode 100644 index 0000000..7584718 --- /dev/null +++ b/docs/source/api.rst @@ -0,0 +1,116 @@ +--- +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: + diff --git a/docs/source/conf.py b/docs/source/conf.py index 76f96f6..8a87a64 100644 --- a/docs/source/conf.py +++ b/docs/source/conf.py @@ -13,6 +13,7 @@ # serve to show the default. import sys +import os class Mock(object): @@ -41,12 +42,12 @@ for mod_name in MOCK_MODULES: # 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 # 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 ---------------------------------------------------- # 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 # extensions coming with Sphinx (named 'sphinx.ext.*') or your custom ones. @@ -61,7 +62,7 @@ templates_path = ['_templates'] source_suffix = '.rst' # The encoding of source files. -# source_encoding = 'utf-8-sig' +#source_encoding = 'utf-8-sig' # The master toctree document. master_doc = 'index' @@ -75,19 +76,19 @@ copyright = u'2013, John Evans' # built documents. # # The short X.Y version. -version = '0.8' +version = '0.7' # The full version, including alpha/beta/rc tags. -release = '0.8.0' +release = '0.7.2' # The language for content autogenerated by Sphinx. Refer to documentation # for a list of supported languages. -# language = None +#language = None # There are two options for replacing |today|: either, you set today to some # non-false value, then it is used: -# today = '' +#today = '' # 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 # directories to ignore when looking for source files. @@ -95,24 +96,24 @@ exclude_patterns = [] # The reST default role (used for this markup: `text`) to use for all # documents. -# default_role = None +#default_role = None # 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 # unit titles (such as .. function::). -# add_module_names = True +#add_module_names = True # If true, sectionauthor and moduleauthor directives will be shown in the # output. They are ignored by default. -# show_authors = False +#show_authors = False # The name of the Pygments (syntax highlighting) style to use. pygments_style = 'sphinx' # A list of ignored prefixes for module index sorting. -# modindex_common_prefix = [] +#modindex_common_prefix = [] # -- Options for HTML output -------------------------------------------------- @@ -124,26 +125,26 @@ html_theme = 'default' # 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 # documentation. -# html_theme_options = {} +#html_theme_options = {} # 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 # " v documentation". -# html_title = None +#html_title = None # 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 # 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 # docs. This file should be a Windows icon file (.ico) being 16x16 or 32x32 # pixels large. -# html_favicon = None +#html_favicon = None # 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, @@ -152,44 +153,44 @@ html_static_path = ['_static'] # If not '', a 'Last updated on:' timestamp is inserted at every page bottom, # 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 # typographically correct entities. -# html_use_smartypants = True +#html_use_smartypants = True # 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 # template names. -# html_additional_pages = {} +#html_additional_pages = {} # If false, no module index is generated. -# html_domain_indices = True +#html_domain_indices = True # 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. -# html_split_index = False +#html_split_index = False # If true, links to the reST sources are added to the pages. html_show_sourcelink = 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. -# html_show_copyright = True +#html_show_copyright = True # If true, an OpenSearch description file will be output, and all pages will # contain a tag referring to it. The value of this option must be the # 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"). -# html_file_suffix = None +#html_file_suffix = None # Output file base name for HTML help builder. htmlhelp_basename = 'glymurdoc' @@ -198,13 +199,13 @@ htmlhelp_basename = 'glymurdoc' # -- Options for LaTeX output ------------------------------------------------- # The paper size ('letterpaper' or 'a4paper'). -# 'papersize': 'letterpaper', +#'papersize': 'letterpaper', # The font size ('10pt', '11pt' or '12pt'). -# 'pointsize': '10pt', +#'pointsize': '10pt', # Additional stuff for the LaTeX preamble. -# 'preamble': '', +#'preamble': '', latex_elements = {} # Grouping the document tree into LaTeX files. List of tuples @@ -215,23 +216,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 title page. -# latex_logo = None +#latex_logo = None # For "manual" documents, if this is true, then toplevel headings are parts, # not chapters. -# latex_use_parts = False +#latex_use_parts = False # If true, show page references after internal links. -# latex_show_pagerefs = False +#latex_show_pagerefs = False # 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. -# latex_appendices = [] +#latex_appendices = [] # If false, no module index is generated. -# latex_domain_indices = True +#latex_domain_indices = True # -- Options for manual page output ------------------------------------------- @@ -244,7 +245,7 @@ man_pages = [ ] # If true, show URL addresses after external links. -# man_show_urls = False +#man_show_urls = False # -- Options for Texinfo output ----------------------------------------------- @@ -257,13 +258,13 @@ texinfo_documents = [('index', 'glymur', u'glymur Documentation', 'One line description of project.', 'Miscellaneous'), ] # Documents to append as an appendix to all manuals. -# texinfo_appendices = [] +#texinfo_appendices = [] # If false, no module index is generated. -# texinfo_domain_indices = True +#texinfo_domain_indices = True # 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. diff --git a/docs/source/detailed_installation.rst b/docs/source/detailed_installation.rst index 7068b56..1a9281c 100644 --- a/docs/source/detailed_installation.rst +++ b/docs/source/detailed_installation.rst @@ -15,7 +15,7 @@ or if you use windows, then read on. Glymur uses ctypes to access the openjp2/openjpeg libraries, and because ctypes accesses libraries in a platform-dependent manner, -it is recommended that **if** you compile and install OpenJPEG into a +it is recommended that if you compile and install OpenJPEG into a non-standard location, you should then create a configuration file to help Glymur properly find the openjpeg or openjp2 libraries (linux users or macports users don’t need to bother with this if @@ -50,9 +50,6 @@ installed in a non-standard place, i.e. :: [library] 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 ''''''' diff --git a/docs/source/how_do_i.rst b/docs/source/how_do_i.rst index 88d94fa..8a62b32 100644 --- a/docs/source/how_do_i.rst +++ b/docs/source/how_do_i.rst @@ -26,10 +26,10 @@ It's pretty simple, just supply the image data as the 2nd argument to the Jp2k constructor. >>> import glymur, numpy as np - >>> jp2 = glymur.Jp2k('zeros.jp2', data=np.zeros((640, 480), dtype=np.uint8) + >>> data = np.zeros((640, 480), dtype=np.uint8) + >>> jp2 = glymur.Jp2k('zeros.jp2', data=data) -You must have OpenJPEG version 1.5 or more recent in order to write JPEG 2000 -images with glymur. +You should have OpenJPEG version 1.5 or more recent before writing JPEG 2000 images. ... display metadata? ===================== @@ -214,9 +214,9 @@ making use of the :py:meth:`set_printoptions` function:: UUID: be7acfcb-97a9-42e8-9c71-999491e3afac (XMP) Contiguous Codestream Box (jp2c) @ (3223, 1132296) -It is possible to easily print the codestream header details as well, i.e. :: +It is possible to print all the gory codestream details as well, i.e. :: - >>> print(j.codestream) # details not show + >>> print(j.get_codestream()) # details not shown ... add XML metadata? ===================== @@ -442,7 +442,7 @@ following 'Google' But that would be painful. A better solution is to install the Python XMP -Toolkit (make sure it is at least version 2.0):: +Toolkit (make sure it is version 2.0):: >>> from libxmp import XMPMeta >>> from libxmp.consts import XMP_NS_XMP as NS_XAP diff --git a/docs/source/index.rst b/docs/source/index.rst index 62e118d..8c1fb03 100644 --- a/docs/source/index.rst +++ b/docs/source/index.rst @@ -17,6 +17,7 @@ Contents: how_do_i whatsnew/index roadmap + api ------------------ Indices and tables diff --git a/docs/source/whatsnew/0.8.rst b/docs/source/whatsnew/0.8.rst index e7215ad..1f2c88b 100644 --- a/docs/source/whatsnew/0.8.rst +++ b/docs/source/whatsnew/0.8.rst @@ -6,19 +6,6 @@ Changes in 0.8.0 ================= * Simplified writing images by moving data and options into the - constructor. + constructor. This is backwards-incompatible with 0.7.x. + * Tilesize parameter is now called tileshape. * 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 - - - diff --git a/glymur/__init__.py b/glymur/__init__.py index d8971b2..9a4d8b1 100644 --- a/glymur/__init__.py +++ b/glymur/__init__.py @@ -1,25 +1,21 @@ """glymur - read, write, and interrogate JPEG 2000 files """ +import sys import unittest from glymur import version __version__ = version.version from .jp2k import Jp2k -from .jp2box import (get_printoptions, - set_printoptions, - get_parseoptions, - set_parseoptions) +from .jp2box import ( + get_printoptions, set_printoptions, + get_parseoptions, set_parseoptions +) from . import data - def runtests(): """Discover and run all tests for the glymur package. """ suite = unittest.defaultTestLoader.discover(__path__[0]) unittest.TextTestRunner(verbosity=2).run(suite) - - -__all__ = [__version__, Jp2k, get_printoptions, set_printoptions, - get_parseoptions, set_parseoptions, data, runtests] diff --git a/glymur/_uuid_io.py b/glymur/_uuid_io.py index 3c63b0a..7bcf2cb 100644 --- a/glymur/_uuid_io.py +++ b/glymur/_uuid_io.py @@ -3,6 +3,8 @@ Part of glymur. """ from collections import OrderedDict +import pprint +import re import struct import sys import warnings diff --git a/glymur/codestream.py b/glymur/codestream.py index ea94afd..aa12bd7 100644 --- a/glymur/codestream.py +++ b/glymur/codestream.py @@ -6,13 +6,16 @@ codestreams. # 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. +# pylint: disable=C0302 # "Too many instance attributes", "Too many arguments" # Some segments just have a lot of information. # 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 # the base Segment class. +# pylint: disable=R0903 import math import struct @@ -28,15 +31,16 @@ from .core import (LRCP, RLCP, RPCL, PCRL, CPRL, from .lib import openjp2 as opj2 _factory = lambda x: '{0} (invalid)'.format(x) -_PROGRESSION_ORDER_DISPLAY = _Keydefaultdict(_factory, {LRCP: 'LRCP', - RLCP: 'RLCP', - RPCL: 'RPCL', - PCRL: 'PCRL', - CPRL: 'CPRL'}) +_PROGRESSION_ORDER_DISPLAY = _Keydefaultdict(_factory, + { LRCP: 'LRCP', + RLCP: 'RLCP', + RPCL: 'RPCL', + PCRL: 'PCRL', + CPRL: 'CPRL'}) -_keysvalues = {WAVELET_XFORM_9X7_IRREVERSIBLE: '9-7 irreversible', - WAVELET_XFORM_5X3_REVERSIBLE: '5-3 reversible'} -_WAVELET_TRANSFORM_DISPLAY = _Keydefaultdict(_factory, _keysvalues) +_WAVELET_TRANSFORM_DISPLAY = _Keydefaultdict(_factory, + { WAVELET_XFORM_9X7_IRREVERSIBLE: '9-7 irreversible', + WAVELET_XFORM_5X3_REVERSIBLE: '5-3 reversible'}) _NO_PROFILE = 0 _PROFILE_0 = 1 @@ -47,11 +51,12 @@ _PROFILE_4 = 4 _KNOWN_PROFILES = [_NO_PROFILE, _PROFILE_0, _PROFILE_1, _PROFILE_3, _PROFILE_4] # How to display the codestream profile. -_CAPABILITIES_DISPLAY = _Keydefaultdict(_factory, {_NO_PROFILE: 'no profile', - _PROFILE_0: '0', - _PROFILE_1: '1', - _PROFILE_3: 'Cinema 2K', - _PROFILE_4: 'Cinema 4K'}) +_CAPABILITIES_DISPLAY = _Keydefaultdict(_factory, + { _NO_PROFILE: 'no profile', + _PROFILE_0: '0', + _PROFILE_1: '1', + _PROFILE_3: 'Cinema 2K', + _PROFILE_4: 'Cinema 4K'}) # Need a catch-all list of valid markers. # See table A-1 in ISO/IEC FCD15444-1. @@ -293,6 +298,7 @@ class Codestream(object): msg += ''.join(strs) return msg + # pylint: disable=R0201 def _parse_cme_segment(self, fptr): """Parse the CME marker segment. @@ -688,7 +694,7 @@ class Codestream(object): try: num_tiles_x = (xysiz[0] - xyosiz[0]) / (xytsiz[0] - xytosiz[0]) num_tiles_y = (xysiz[1] - xyosiz[1]) / (xytsiz[1] - xytosiz[1]) - except ZeroDivisionError: + except ZeroDivisionError as err: warnings.warn("Invalid tile dimensions.") else: numtiles = math.ceil(num_tiles_x) * math.ceil(num_tiles_y) @@ -822,6 +828,7 @@ class Codestream(object): return TLMsegment(length, offset, ztlm, ttlm, ptlm) + # pylint: disable=W0613 def _parse_reserved_marker(self, fptr): """Marker range between 0xff30 and 0xff39. """ diff --git a/glymur/command_line.py b/glymur/command_line.py index 3d1d57e..5f0d357 100644 --- a/glymur/command_line.py +++ b/glymur/command_line.py @@ -3,9 +3,10 @@ Entry point for console script jp2dump. """ import argparse import os +import sys import warnings -from . import Jp2k, set_printoptions, set_parseoptions, lib +from . import Jp2k, set_printoptions, lib def main(): @@ -13,25 +14,23 @@ def main(): Entry point for console script jp2dump. """ - kwargs = {'description': 'Print JPEG2000 metadata.', - 'formatter_class': argparse.ArgumentDefaultsHelpFormatter} - parser = argparse.ArgumentParser(**kwargs) + description = 'Print JPEG2000 metadata.' + parser = argparse.ArgumentParser(description=description) parser.add_argument('-x', '--noxml', - help='suppress XML', + help='Suppress XML.', action='store_true') parser.add_argument('-s', '--short', - help='only print box id, offset, and length', + help='Only print box id, offset, and length.', action='store_true') - chelp = 'Level of codestream information. 0 suppresses all details, ' - chelp += '1 prints the main header, 2 prints the full codestream.' + chelp = 'Level of codestream information. 0 suppressed all details, ' + chelp += '1 prints headers, 2 prints the full codestream' parser.add_argument('-c', '--codestream', help=chelp, - metavar='LEVEL', nargs=1, type=int, - default=[1]) + default=[0]) parser.add_argument('filename') @@ -47,8 +46,11 @@ def main(): if codestream_level == 0: set_printoptions(codestream=False) - elif codestream_level == 2: - set_parseoptions(full_codestream=True) + print_full_codestream = False + elif codestream_level == 1: + print_full_codestream = False + else: + print_full_codestream = True filename = args.filename @@ -57,14 +59,11 @@ def main(): # JP2 metadata can be extensive, so don't print any warnings until we # are done with the metadata. jp2 = Jp2k(filename) - if jp2._codec_format == lib.openjp2.CODEC_J2K: - 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)) + if (((jp2._codec_format == lib.openjp2.CODEC_J2K) and + (codestream_level == 0))): + print('File: {0}'.format(os.path.basename(filename))) + elif print_full_codestream: + print(jp2.get_codestream(header_only=False)) else: print(jp2) diff --git a/glymur/core.py b/glymur/core.py index 644dcfd..3327253 100644 --- a/glymur/core.py +++ b/glymur/core.py @@ -1,6 +1,8 @@ """Core definitions to be shared amongst the modules. """ import collections +import copy +import lxml.etree as ET class _Keydefaultdict(collections.defaultdict): diff --git a/glymur/data/__init__.py b/glymur/data/__init__.py index 066edd2..de1e62a 100644 --- a/glymur/data/__init__.py +++ b/glymur/data/__init__.py @@ -43,3 +43,4 @@ def jpxfile(): """ filename = pkg_resources.resource_filename(__name__, "heliov.jpx") return filename + diff --git a/glymur/jp2box.py b/glymur/jp2box.py index 98b0e6a..39e1f6a 100644 --- a/glymur/jp2box.py +++ b/glymur/jp2box.py @@ -11,6 +11,8 @@ References Extensions """ +# pylint: disable=C0302,R0903,R0913,W0142 + from collections import OrderedDict import datetime import io @@ -20,7 +22,7 @@ import pprint import struct import sys import textwrap -from uuid import UUID +import uuid import warnings import lxml.etree as ET @@ -35,21 +37,18 @@ from .core import (_COLORSPACE_MAP_DISPLAY, _COLOR_TYPE_MAP_DISPLAY, from . import _uuid_io -_factory = lambda x: '{0} (invalid)'.format(x) -_keysvalues = {ENUMERATED_COLORSPACE: 'enumerated colorspace', - RESTRICTED_ICC_PROFILE: 'restricted ICC profile', - ANY_ICC_PROFILE: 'any ICC profile', - VENDOR_COLOR_METHOD: 'vendor color method'} -_METHOD_DISPLAY = _Keydefaultdict(_factory, _keysvalues) +_METHOD_DISPLAY = { + ENUMERATED_COLORSPACE: 'enumerated colorspace', + RESTRICTED_ICC_PROFILE: 'restricted ICC profile', + ANY_ICC_PROFILE: 'any ICC profile', + VENDOR_COLOR_METHOD: 'vendor color method'} _factory = lambda x: '{0} (invalid)'.format(x) -_keysvalues = {1: 'accurately represents correct colorspace definition', - 2: ('approximates correct colorspace definition, ' - 'exceptional quality'), - 3: ('approximates correct colorspace definition, ' - 'reasonable quality'), - 4: 'approximates correct colorspace definition, poor quality'} -_APPROX_DISPLAY = _Keydefaultdict(_factory, _keysvalues) +_APPROX_DISPLAY = _Keydefaultdict(_factory, + {1: 'accurately represents correct colorspace definition', + 2: 'approximates correct colorspace definition, exceptional quality', + 3: 'approximates correct colorspace definition, reasonable quality', + 4: 'approximates correct colorspace definition, poor quality'}) class Jp2kBox(object): @@ -1001,19 +1000,18 @@ class ContiguousCodestreamBox(Jp2kBox): offset of the box from the start of the file. longname : str more verbose description of the box. - codestream : Codestream object - Contains list of codestream marker/segments. By default, only the main - header is retrieved. + main_header : Codestream object + contains list of main header marker/segments main_header_offset : int offset of main header from start of file """ box_id = 'jp2c' longname = 'Contiguous Codestream' - def __init__(self, codestream=None, main_header_offset=None, length=0, + def __init__(self, main_header=None, main_header_offset=None, length=0, offset=-1): Jp2kBox.__init__(self) - self._codestream = codestream + self._main_header = main_header self.length = length self.offset = offset self.main_header_offset = main_header_offset @@ -1022,23 +1020,20 @@ class ContiguousCodestreamBox(Jp2kBox): self._filename = None @property - def codestream(self): - if _parseoptions['full_codestream'] is True: - header_only = False - else: - header_only = True - if self._codestream is None: + def main_header(self): + if self._main_header is None: if self._filename is not None: with open(self._filename, 'rb') as fptr: fptr.seek(self.main_header_offset) - codestream = Codestream(fptr, self._length, - header_only=header_only) - self._codestream = codestream - return self._codestream + main_header = Codestream(fptr, + self._length, + header_only=True) + self._main_header = main_header + return self._main_header def __repr__(self): - msg = "glymur.jp2box.ContiguousCodeStreamBox(codestream={0})" - return msg.format(repr(self.codestream)) + msg = "glymur.jp2box.ContiguousCodeStreamBox(main_header={0})" + return msg.format(repr(self.main_header)) def __str__(self): msg = Jp2kBox.__str__(self) @@ -1047,8 +1042,9 @@ class ContiguousCodestreamBox(Jp2kBox): if _printoptions['codestream'] is False: return msg - for segment in self.codestream.segment: - msg += '\n' + self._indent(str(segment), indent_level=4) + msg += '\n Main header:' + for segment in self.main_header.segment: + msg += '\n' + self._indent(str(segment), indent_level=8) return msg @@ -1070,11 +1066,11 @@ class ContiguousCodestreamBox(Jp2kBox): ContiguousCodestreamBox instance """ main_header_offset = fptr.tell() - if _parseoptions['full_codestream'] is True: - codestream = Codestream(fptr, length, header_only=False) + if _parseoptions['codestream'] is True: + main_header = Codestream(fptr, length, header_only=True) else: - codestream = None - box = cls(codestream, main_header_offset=main_header_offset, + main_header = None + box = cls(main_header, main_header_offset=main_header_offset, length=length, offset=offset) box._filename = fptr.name box._length = length @@ -1321,13 +1317,7 @@ class FileTypeBox(Jp2kBox): for j in range(int(num_entries)): entry, = struct.unpack_from('>4s', read_buffer, 8 + j * 4) if sys.hexversion >= 0x03000000: - try: - entry = entry.decode('utf-8') - except UnicodeDecodeError: - # The entry is invalid, but we've got code to catch this - # later on. - pass - + entry = entry.decode('utf-8') compatibility_list.append(entry) return cls(brand=brand, minor_version=minor_version, @@ -1993,6 +1983,7 @@ class PaletteBox(Jp2kBox): *bps_signed) fptr.write(write_buffer) + bps = self.bits_per_component # All components are the same. Writing is straightforward. if self.bits_per_component[0] <= 8: write_buffer = memoryview(self.palette.astype(np.uint8)) @@ -2032,10 +2023,13 @@ class PaletteBox(Jp2kBox): # Ok the palette has the same datatype for all columns. We should # be able to efficiently read it. if bps[0] <= 8: + nbytes_per_row = ncols dtype = np.uint8 elif bps[0] <= 16: + nbytes_per_row = 2 * ncols dtype = np.uint16 elif bps[0] <= 32: + nbytes_per_row = 3 * ncols dtype = np.uint32 palette = np.frombuffer(read_buffer[3 + ncols:], dtype=dtype) @@ -2079,80 +2073,80 @@ _READER_REQUIREMENTS_DISPLAY = { 7: 'JPEG codestream as defined in ISO/IEC 10918-1', 8: 'Deprecated - does not contain opacity', 9: 'Non-premultiplied opacity channel', - 10: 'Premultiplied opacity channel', - 11: 'Chroma-key based opacity', - 12: 'Deprecated - codestream is contiguous', - 13: 'Fragmented codestream where all fragments are in file and in order', - 14: ('Fragmented codestream where all fragments are in file ' - 'but are out of order'), - 15: ('Fragmented codestream where not all fragments are within the file ' - 'but are all in locally accessible files'), - 16: ('Fragmented codestream where some fragments may be accessible ' - 'only through a URL specified network connection'), - 17: ('Compositing required to produce rendered result from multiple ' - 'compositing layers'), - 18: 'Deprecated - support for compositing is not required', - 19: ('Deprecated - contains multiple, discrete layers that should not ' - 'be combined through either animation or compositing'), - 20: ('Deprecated - compositing layers each contain only a single ' - 'codestream'), - 21: 'At least one compositing layer consists of multiple codestreams', - 22: 'Deprecated - all compositing layers are in the same colourspace', - 23: ('Colourspace transformations are required to combine compositing ' - 'layers; not all compositing layers are in the same colourspace'), - 24: 'Deprecated - rendered result created without using animation', - 25: ('Deprecated - animated, but first layer covers entire area and is ' - 'opaque'), - 26: 'First animation layer does not cover entire rendered result', - 27: 'Deprecated - animated, and no layer is reused', - 28: 'Reuse of animation layers', - 29: 'Deprecated - animated, but layers are reused', - 30: 'Some animated frames are non-persistent', - 31: 'Deprecated - rendered result created without using scaling', - 32: 'Rendered result involves scaling within a layer', - 33: 'Rendered result involves scaling between layers', - 34: 'ROI metadata', - 35: 'IPR metadata', - 36: 'Content metadata', - 37: 'History metadata', - 38: 'Creation metadata', - 39: 'JPX digital signatures', - 40: 'JPX checksums', - 41: 'Desires Graphics Arts Reproduction specified', - 42: 'Deprecated - compositing layer uses palettized colour', - 43: 'Deprecated - compositing layer uses restricted ICC profile', - 44: 'Compositing layer uses Any ICC profile', - 45: 'Deprecated - compositing layer uses sRGB enumerated colourspace', - 46: 'Deprecated - compositing layer uses sRGB-grey enumerated colourspace', - 47: 'BiLevel 1 enumerated colourspace', - 48: 'BiLevel 2 enumerated colourspace', - 49: 'YCbCr 1 enumerated colourspace', - 50: 'YCbCr 2 enumerated colourspace', - 51: 'YCbCr 3 enumerated colourspace', - 52: 'PhotoYCC enumerated colourspace', - 53: 'YCCK enumerated colourspace', - 54: 'CMY enumerated colourspace', - 55: 'CMYK enumerated colorspace', - 56: 'CIELab enumerated colourspace with default parameters', - 57: 'CIELab enumerated colourspace with non-default parameters', - 58: 'CIEJab enumerated colourspace with default parameters', - 59: 'CIEJab enumerated colourspace with non-default parameters', - 60: 'e-sRGB enumerated colorspace', - 61: 'ROMM_RGB enumerated colorspace', - 62: 'Non-square samples', - 63: 'Deprecated - compositing layers have labels', - 64: 'Deprecated - codestreams have labels', - 65: 'Deprecated - compositing layers have different colour spaces', - 66: 'Deprecated - compositing layers have different metadata', - 67: 'GIS metadata XML box', - 68: 'JPSEC extensions in codestream as specified by ISO/IEC 15444-8', - 69: 'JP3D extensions in codestream as specified by ISO/IEC 15444-10', - 70: 'Deprecated - compositing layer uses sYCC enumerated colour space', - 71: 'e-sYCC enumerated colourspace', - 72: ('JPEG 2000 Part 2 codestream as restricted by baseline conformance ' - 'requirements in M.9.2.3'), - 73: 'YPbPr(1125/60) enumerated colourspace', - 74: 'YPbPr(1250/50) enumerated colourspace'} + 10: 'Premultiplied opacity channel', + 11: 'Chroma-key based opacity', + 12: 'Deprecated - codestream is contiguous', + 13: 'Fragmented codestream where all fragments are in file and in order', + 14: 'Fragmented codestream where all fragments are in file ' + + 'but are out of order', + 15: 'Fragmented codestream where not all fragments are within the file ' + + 'but are all in locally accessible files', + 16: 'Fragmented codestream where some fragments may be accessible ' + + 'only through a URL specified network connection', + 17: 'Compositing required to produce rendered result from multiple ' + + 'compositing layers', + 18: 'Deprecated - support for compositing is not required', + 19: 'Deprecated - contains multiple, discrete layers that should not ' + + 'be combined through either animation or compositing', + 20: 'Deprecated - compositing layers each contain only a single ' + + 'codestream', + 21: 'At least one compositing layer consists of multiple codestreams', + 22: 'Deprecated - all compositing layers are in the same colourspace', + 23: 'Colourspace transformations are required to combine compositing ' + + 'layers; not all compositing layers are in the same colourspace', + 24: 'Deprecated - rendered result created without using animation', + 25: 'Deprecated - animated, but first layer covers entire area and is ' + + 'opaque', + 26: 'First animation layer does not cover entire rendered result', + 27: 'Deprecated - animated, and no layer is reused', + 28: 'Reuse of animation layers', + 29: 'Deprecated - animated, but layers are reused', + 30: 'Some animated frames are non-persistent', + 31: 'Deprecated - rendered result created without using scaling', + 32: 'Rendered result involves scaling within a layer', + 33: 'Rendered result involves scaling between layers', + 34: 'ROI metadata', + 35: 'IPR metadata', + 36: 'Content metadata', + 37: 'History metadata', + 38: 'Creation metadata', + 39: 'JPX digital signatures', + 40: 'JPX checksums', + 41: 'Desires Graphics Arts Reproduction specified', + 42: 'Deprecated - compositing layer uses palettized colour', + 43: 'Deprecated - compositing layer uses restricted ICC profile', + 44: 'Compositing layer uses Any ICC profile', + 45: 'Deprecated - compositing layer uses sRGB enumerated colourspace', + 46: 'Deprecated - compositing layer uses sRGB-grey enumerated colourspace', + 47: 'BiLevel 1 enumerated colourspace', + 48: 'BiLevel 2 enumerated colourspace', + 49: 'YCbCr 1 enumerated colourspace', + 50: 'YCbCr 2 enumerated colourspace', + 51: 'YCbCr 3 enumerated colourspace', + 52: 'PhotoYCC enumerated colourspace', + 53: 'YCCK enumerated colourspace', + 54: 'CMY enumerated colourspace', + 55: 'CMYK enumerated colorspace', + 56: 'CIELab enumerated colourspace with default parameters', + 57: 'CIELab enumerated colourspace with non-default parameters', + 58: 'CIEJab enumerated colourspace with default parameters', + 59: 'CIEJab enumerated colourspace with non-default parameters', + 60: 'e-sRGB enumerated colorspace', + 61: 'ROMM_RGB enumerated colorspace', + 62: 'Non-square samples', + 63: 'Deprecated - compositing layers have labels', + 64: 'Deprecated - codestreams have labels', + 65: 'Deprecated - compositing layers have different colour spaces', + 66: 'Deprecated - compositing layers have different metadata', + 67: 'GIS metadata XML box', + 68: 'JPSEC extensions in codestream as specified by ISO/IEC 15444-8', + 69: 'JP3D extensions in codestream as specified by ISO/IEC 15444-10', + 70: 'Deprecated - compositing layer uses sYCC enumerated colour space', + 71: 'e-sYCC enumerated colourspace', + 72: 'JPEG 2000 Part 2 codestream as restricted by baseline conformance ' + + 'requirements in M.9.2.3', + 73: 'YPbPr(1125/60) enumerated colourspace', + 74: 'YPbPr(1250/50) enumerated colourspace'} class ReaderRequirementsBox(Jp2kBox): @@ -2215,8 +2209,7 @@ class ReaderRequirementsBox(Jp2kBox): if _printoptions['short'] is True: return msg - msg += '\n Fully Understands Aspect Mask: 0x{0:x}' - msg = msg.format(self.fuam) + msg += '\n Fully Understands Aspect Mask: 0x{0:x}'.format(self.fuam) msg += '\n Display Completely Mask: 0x{0:x}'.format(self.dcm) msg += '\n Standard Features and Masks:' @@ -2272,8 +2265,8 @@ class ReaderRequirementsBox(Jp2kBox): standard_flag, standard_mask = data 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:], mask_length) vendor_feature, vendor_mask = data @@ -2330,8 +2323,8 @@ def _parse_rreq3(read_buffer, length, offset): read_buffer = read_buffer[9 + num_standard_features * 10:] for j in range(num_vendor_features): uslice = slice(j * entry_length, (j + 1) * entry_length) - ubuffer = read_buffer[uslice] - vendor_feature.append(UUID(bytes=ubuffer[0:16])) + ubuffer = read_buffer[slice] + vendor_feature.append(uuid.UUID(bytes=ubuffer[0:16])) lst = struct.unpack('>BBB', ubuffer[16:]) vmask = lst[0] << 16 | lst[1] << 8 | lst[2] @@ -2399,7 +2392,7 @@ def _parse_vendor_features(read_buffer, mask_length): for j in range(num_vendor_features): uslice = slice(2 + j * entry_length, 2 + (j + 1) * entry_length) ubuffer = read_buffer[uslice] - vendor_feature.append(UUID(bytes=ubuffer[0:16])) + vendor_feature.append(uuid.UUID(bytes=ubuffer[0:16])) vmask = struct.unpack('>' + mask_format, ubuffer[16:]) vendor_mask.append(vmask) @@ -2951,7 +2944,7 @@ class UUIDListBox(Jp2kBox): ulst = [] for j in range(num_uuids): uuid_buffer = read_buffer[2 + j * 16:2 + (j + 1) * 16] - ulst.append(UUID(bytes=uuid_buffer)) + ulst.append(uuid.UUID(bytes=uuid_buffer)) return cls(ulst, length=length, offset=offset) @@ -3209,7 +3202,7 @@ class UUIDBox(Jp2kBox): """ Private function for parsing UUID payloads if possible. """ - if self.uuid == UUID('be7acfcb-97a9-42e8-9c71-999491e3afac'): + if self.uuid == uuid.UUID('be7acfcb-97a9-42e8-9c71-999491e3afac'): self.data = _uuid_io.xml(self.raw_data) elif self.uuid.bytes == b'JpgTiffExif->JP2': self.data = _uuid_io.tiff_header(self.raw_data) @@ -3227,7 +3220,7 @@ class UUIDBox(Jp2kBox): return msg msg = '{0}\n UUID: {1}'.format(msg, self.uuid) - if self.uuid == UUID('be7acfcb-97a9-42e8-9c71-999491e3afac'): + if self.uuid == uuid.UUID('be7acfcb-97a9-42e8-9c71-999491e3afac'): msg += ' (XMP)' elif self.uuid.bytes == b'JpgTiffExif->JP2': msg += ' (EXIF)' @@ -3235,11 +3228,11 @@ class UUIDBox(Jp2kBox): msg += ' (unknown)' if (((_printoptions['xml'] is False) and - (self.uuid == UUID('be7acfcb-97a9-42e8-9c71-999491e3afac')))): + (self.uuid == uuid.UUID('be7acfcb-97a9-42e8-9c71-999491e3afac')))): # If it's an XMP UUID, don't print the XML contents. return msg - if self.uuid == UUID('be7acfcb-97a9-42e8-9c71-999491e3afac'): + if self.uuid == uuid.UUID('be7acfcb-97a9-42e8-9c71-999491e3afac'): line = '\n UUID Data:\n{0}' xmlstring = ET.tostring(self.data, encoding='utf-8', @@ -3282,7 +3275,7 @@ class UUIDBox(Jp2kBox): """ num_bytes = offset + length - fptr.tell() read_buffer = fptr.read(num_bytes) - the_uuid = UUID(bytes=read_buffer[0:16]) + the_uuid = uuid.UUID(bytes=read_buffer[0:16]) return cls(the_uuid, read_buffer[16:], length=length, offset=offset) @@ -3317,20 +3310,19 @@ _BOX_WITH_ID = { b'uuid': UUIDBox, b'xml ': XMLBox} -_parseoptions = {'full_codestream': False} +_parseoptions = {'codestream': True} -def set_parseoptions(full_codestream=True): +def set_parseoptions(codestream=True): """Set parsing options. These options determine the way JPEG 2000 boxes are parsed. Parameters ---------- - full_codestream : bool, defaults to True - When False, only the codestream header is parsed for metadata. This - can results in faster JP2/JPX parsing. When True, the entire - codestream is parsed for metadata. + codestream : bool, defaults to True + When False, the codestream header is only parsed when accessed. This + can results in faster JP2/JPX parsing. See also -------- @@ -3341,9 +3333,9 @@ def set_parseoptions(full_codestream=True): To put back the default options, you can use: >>> import glymur - >>> glymur.set_parseoptions(full_codestream=True) + >>> glymur.set_parseoptions(codestream=True) """ - _parseoptions['full_codestream'] = full_codestream + _parseoptions['codestream'] = codestream def get_parseoptions(): @@ -3382,9 +3374,7 @@ def set_printoptions(**kwargs): When False, printing of the XML contents of any XML boxes or UUID XMP boxes is suppressed. codestream : bool, optional - 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. + When False, printing of the codestream contents is suppressed. See also -------- diff --git a/glymur/jp2k.py b/glymur/jp2k.py index ee6eedc..e2764a1 100644 --- a/glymur/jp2k.py +++ b/glymur/jp2k.py @@ -10,12 +10,13 @@ License: MIT import sys # Exitstack not found in contextlib in 2.7 +# pylint: disable=E0611 if sys.hexversion >= 0x03030000: from contextlib import ExitStack - from itertools import filterfalse + from itertools import compress, filterfalse else: from contextlib2 import ExitStack - from itertools import ifilterfalse as filterfalse + from itertools import compress, ifilterfalse as filterfalse from collections import Counter import ctypes @@ -60,8 +61,6 @@ class Jp2k(Jp2kBox): verbose : bool whether or not to print informational messages produced by the OpenJPEG library, defaults to false - codestream : object - JP2 or J2K codestream object Examples -------- @@ -81,7 +80,8 @@ class Jp2k(Jp2kBox): (728, 1296, 3) """ - def __init__(self, filename, data=None, shape=None, **kwargs): + def __init__(self, filename, data=None, shape=None, tileshape=None, + **kwargs): """ Only the filename parameter is required in order to read a JPEG 2000 file. @@ -94,6 +94,8 @@ class Jp2k(Jp2kBox): image data to be written shape : tuple size of image data, only required when image_data is not provided + tileshape : tuple, optional, default is same as shape + tile size cbsize : tuple, optional code block size (DY, DX) cinema2k : int, optional @@ -134,9 +136,6 @@ class Jp2k(Jp2kBox): if true, write SOP marker before each packet subsam : tuple, optional subsampling factors (dy, dx) - tilesize : tuple, optional - numeric tuple specifying tile size in terms of (numrows, numcols), - not (X, Y) verbose : bool, optional print informational messages produced by the OpenJPEG library """ @@ -147,12 +146,16 @@ class Jp2k(Jp2kBox): self._codec_format = None self._colorspace = None self._layer = 0 - self._codestream = None if data is not None: self._shape = data.shape else: self._shape = shape + if tileshape is not None: + self._tileshape = tileshape + else: + self._tileshape = shape + self._ignore_pclr_cmap_cdef = False self._verbose = False @@ -182,16 +185,6 @@ class Jp2k(Jp2kBox): raise RuntimeError(msg) self._layer = layer - @property - def codestream(self): - if self._codestream is None: - self._codestream = self.get_codestream(header_only=True) - return self._codestream - - @codestream.setter - def codestream(self, the_codestream): - self._codestream = the_codestream - @property def verbose(self): return self._verbose @@ -205,30 +198,28 @@ class Jp2k(Jp2kBox): if self._shape is not None: return self._shape - if self._codec_format == opj2.CODEC_J2K: - # get the image size from the codestream - cstr = self.codestream - height = cstr.segment[1].ysiz - width = cstr.segment[1].xsiz - num_components = len(cstr.segment[1].xrsiz) - else: - # try to get the image size from the IHDR box - jp2h = [box for box in self.box if box.box_id == 'jp2h'][0] - ihdr = [box for box in jp2h.box if box.box_id == 'ihdr'][0] - - height, width = ihdr.height, ihdr.width - num_components = ihdr.num_components - - if num_components == 1: - # but if there is a PCLR box, then we need to check that as - # well, as that turns a single-channel image into a - # multi-channel image - pclr = [box for box in jp2h.box if box.box_id == 'pclr'] - if len(pclr) > 0: - num_components = len(pclr[0].signed) + cstr = self.get_codestream(header_only=True) + height = cstr.segment[1].ysiz + width = cstr.segment[1].xsiz + num_components = len(cstr.segment[1].xrsiz) + # If JP2 and a palette box is present, then determine the shape from + # that. if num_components == 1: - self.shape = (height, width) + if self._codec_format == opj2.CODEC_J2K: + # There's no palette box or component mapping in a J2K file. + # The 3rd component in the shape would then be 1, but we'll + # ignore that. + self.shape = (height, width) + else: + jp2h = [box for box in self.box if box.box_id == 'jp2h'][0] + pclr = [box for box in jp2h.box if box.box_id == 'pclr'] + if len(pclr) == 0: + # No palette box, so just one component, which we will + # ignore. + self.shape = (height, width) + else: + self.shape = (height, width, len(pclr[0].signed)) else: self.shape = (height, width, num_components) @@ -248,9 +239,93 @@ class Jp2k(Jp2kBox): for box in self.box: metadata.append(str(box)) else: - metadata.append(str(self.codestream)) + codestream = self.get_codestream() + metadata.append(str(codestream)) return '\n'.join(metadata) + def __enter__(self): + """ + """ + self._determine_colorspace() + self._populate_cparams() + + #self._cparams.cp_fixed_quality = 1 + #self._cparams.tcp_distoratio[0] = 20 + # set cp_fixed_quality = 1 ?? + + self._num_tiles_per_row = np.ceil(self.shape[1] / self._tileshape[1]) + + if len(self.shape) == 2: + num_comps = 1 + else: + num_comps = self.shape[2] + + # Populate comptparms + # Only two precisions are possible. + #if img_array.dtype == np.uint8: + comp_prec = 8 + #else: + #comp_prec = 16 + + if len(self.shape) == 2: + numrows, numcols = self.shape + numcops = 1 + else: + numrows, numcols, num_comps = self.shape + comptparms = (opj2.ImageComptParmType * num_comps)() + + for j in range(num_comps): + comptparms[j].dx = self._cparams.subsampling_dx + comptparms[j].dy = self._cparams.subsampling_dy + comptparms[j].w = numcols + comptparms[j].h = numrows + comptparms[j].x0 = self._cparams.image_offset_x0 + comptparms[j].y0 = self._cparams.image_offset_y0 + comptparms[j].prec = comp_prec + comptparms[j].bpp = comp_prec + comptparms[j].sgnd = 0 + self._comptparms = comptparms + + self._codec = opj2.create_compress(self._cparams.codec_fmt) + + num_tile_pixels = self._cparams.cp_tdx * self._cparams.cp_tdy + self._tile_size = num_tile_pixels * num_comps * comptparms[j].prec / 8 + + #self._image = opj2.image_tile_create(self._comptparms, self._colorspace) + self._image = opj2.image_create(self._comptparms, self._colorspace) + + self._image.contents.x0 = 0 + self._image.contents.y0 = 0 + self._image.contents.x1 = self.shape[1] + self._image.contents.y1 = self.shape[0] + + # Is this needed? + self._image.contents.color_space = self._colorspace + + opj2.setup_encoder(self._codec, self._cparams, self._image) + self._stream = opj2.stream_create_default_file_stream(self.filename, + False) + opj2.start_compress(self._codec, self._image, self._stream) + + #print('cparams') + #print(self._cparams) + #print('comptparms[0]') + #print(self._comptparms[0]) + #print('comptparms[1]') + #print(self._comptparms[1]) + #print('comptparms[2]') + #print(self._comptparms[2]) + #print('image') + #print(self._image[0]) + + return self + + def __exit__(self, *pargs): + opj2.end_compress(self._codec, self._stream) + opj2.stream_destroy(self._stream) + opj2.destroy_codec(self._codec) + opj2.image_destroy(self._image) + def parse(self): """Parses the JPEG 2000 file. @@ -363,7 +438,7 @@ class Jp2k(Jp2kBox): # 2.1 API self._cparams.rsiz = core.OPJ_PROFILE_CINEMA_4K - def _populate_cparams(self, img_array, **kwargs): + def _populate_cparams(self, **kwargs): """Directs processing of write method arguments. Parameters @@ -465,9 +540,9 @@ class Jp2k(Jp2kBox): cparams.subsampling_dy = kwargs['subsam'][0] cparams.subsampling_dx = kwargs['subsam'][1] - if 'tilesize' in kwargs: - cparams.cp_tdx = kwargs['tilesize'][1] - cparams.cp_tdy = kwargs['tilesize'][0] + if self._tileshape is not None: + cparams.cp_tdx = self._tileshape[1] + cparams.cp_tdy = self._tileshape[0] cparams.tile_size_on = opj2.TRUE try: @@ -485,7 +560,7 @@ class Jp2k(Jp2kBox): else: cparams.tcp_mct = 0 - self._validate_compression_params(img_array, cparams, **kwargs) + self._validate_compression_params(cparams, **kwargs) self._cparams = cparams @@ -501,8 +576,27 @@ class Jp2k(Jp2kBox): msg += "in order to write images." raise RuntimeError(msg) + # What would the point of 1D images be? + if img_array.ndim == 1 or img_array.ndim > 3: + msg = "{0}D imagery is not allowed.".format(img_array.ndim) + raise IOError(msg) + + if re.match("2.0.0", version.openjpeg_version) is not None: + if (((img_array.ndim != 2) and + (img_array.shape[2] != 1 and img_array.shape[2] != 3))): + msg = "Writing images is restricted to single-channel " + msg += "greyscale images or three-channel RGB images when " + msg += "the OpenJPEG library version is the official 2.0.0 " + msg += "release." + raise IOError(msg) + + if img_array.dtype != np.uint8 and img_array.dtype != np.uint16: + msg = "Only uint8 and uint16 datatypes are currently supported " + msg += "when writing." + raise RuntimeError(msg) + self._determine_colorspace(**kwargs) - self._populate_cparams(img_array, **kwargs) + self._populate_cparams(**kwargs) if opj2.OPENJP2 is not None: self._write_openjp2(img_array, verbose=verbose) @@ -530,12 +624,12 @@ class Jp2k(Jp2kBox): # set image offset and reference grid image.contents.x0 = self._cparams.image_offset_x0 image.contents.y0 = self._cparams.image_offset_y0 - image.contents.x1 = (image.contents.x0 - + (numcols - 1) * self._cparams.subsampling_dx - + 1) - image.contents.y1 = (image.contents.y0 - + (numrows - 1) * self._cparams.subsampling_dy - + 1) + image.contents.x1 = image.contents.x0 \ + + (numcols - 1) * self._cparams.subsampling_dx \ + + 1 + image.contents.y1 = image.contents.y0 \ + + (numrows - 1) * self._cparams.subsampling_dy \ + + 1 # Stage the image data to the openjpeg data structure. for k in range(0, numlayers): @@ -576,13 +670,11 @@ class Jp2k(Jp2kBox): self.parse() - def _validate_compression_params(self, img_array, cparams, **kwargs): + def _validate_compression_params(self, cparams, **kwargs): """Check that the compression parameters are valid. Parameters ---------- - img_array : ndarray - Image data to be written to file. cparams : CompressionParametersType(ctypes.Structure) Corresponds to cparameters_t type in openjp2 headers. """ @@ -627,25 +719,6 @@ class Jp2k(Jp2kBox): msg += "must be powers of 2." raise IOError(msg.format(prch, prcw)) - # What would the point of 1D images be? - if img_array.ndim == 1 or img_array.ndim > 3: - msg = "{0}D imagery is not allowed.".format(img_array.ndim) - raise IOError(msg) - - if re.match("2.0.0", version.openjpeg_version) is not None: - if (((img_array.ndim != 2) and - (img_array.shape[2] != 1 and img_array.shape[2] != 3))): - msg = "Writing images is restricted to single-channel " - msg += "greyscale images or three-channel RGB images when " - msg += "the OpenJPEG library version is the official 2.0.0 " - msg += "release." - raise IOError(msg) - - if img_array.dtype != np.uint8 and img_array.dtype != np.uint16: - msg = "Only uint8 and uint16 datatypes are currently supported " - msg += "when writing." - raise RuntimeError(msg) - def _determine_colorspace(self, colorspace=None, **kwargs): """Determine the colorspace from the supplied inputs. @@ -845,7 +918,7 @@ class Jp2k(Jp2kBox): raise IOError(msg) # Find the first codestream in the file. - jp2c = [_box for _box in self.box if _box.box_id == 'jp2c'] + jp2c = [box for box in self.box if box.box_id == 'jp2c'] offset = jp2c[0].offset # Ready to write the codestream. @@ -879,9 +952,10 @@ class Jp2k(Jp2kBox): FileTypeBox(), JP2HeaderBox(), ContiguousCodestreamBox()] - height = self.codestream.segment[1].ysiz - width = self.codestream.segment[1].xsiz - num_components = len(self.codestream.segment[1].xrsiz) + codestream = self.get_codestream() + height = codestream.segment[1].ysiz + width = codestream.segment[1].xsiz + num_components = len(codestream.segment[1].xrsiz) if num_components < 3: colorspace = core.GREYSCALE else: @@ -912,6 +986,52 @@ class Jp2k(Jp2kBox): # # Should have a slice object where start = stop = step = None self._write(data) + + elif isinstance(index, tuple): + + # determine what tile number to write to + rows, cols = index + if rows.start is None: + tr1 = 0 + else: + tr1 = np.floor(rows.start / self._tileshape[0]) + if rows.stop is None: + tr2 = np.floor(self._shape[0] / self._tileshape[0]) + else: + tr2 = np.floor((rows.stop - 1) / self._tileshape[0]) + + if tr1 == tr2: + tile_row = tr1 + else: + msg = "Slice arguments cannot cross tile boundaries." + raise IOError(msg) + + if cols.start is None: + tc1 = 0 + else: + tc1 = np.floor(cols.start / self._tileshape[1]) + if rows.stop is None: + tc2 = np.floor(self._shape[1] / self._tileshape[1]) + else: + tc2 = np.floor((cols.stop - 1) / self._tileshape[1]) + + if tc1 == tc2: + tile_col = tc1 + else: + msg = "Slice arguments cannot cross tile boundaries." + raise IOError(msg) + + num_tile_pixels = self._cparams.cp_tdx * self._cparams.cp_tdy + num_comps = len(self._shape) + if data.dtype == np.uint8: + nbytes = num_tile_pixels * num_comps + else: + nbytes = num_tile_pixels * num_comps * 2 + + tile_no = tile_row * self._num_tiles_per_row + tile_col + opj2.write_tile(self._codec, tile_no, data, nbytes, self._stream) + return + else: msg = "Partial write operations are currently not allowed." raise TypeError(msg) @@ -920,11 +1040,10 @@ class Jp2k(Jp2kBox): """ Slicing protocol. """ - if len(self.shape) == 2: - numrows, numcols = self.shape - numbands = 1 - else: - numrows, numcols, numbands = self.shape + codestream = self.get_codestream(header_only=True) + numrows = codestream.segment[1].ysiz + numcols = codestream.segment[1].xsiz + numbands = codestream.segment[1].Csiz if isinstance(pargs, int): # Not a very good use of this protocol, but technically legal. @@ -1086,8 +1205,9 @@ class Jp2k(Jp2kBox): def _subsampling_sanity_check(self): """Check for differing subsample factors. """ - dxs = np.array(self.codestream.segment[1].xrsiz) - dys = np.array(self.codestream.segment[1].yrsiz) + codestream = self.get_codestream(header_only=True) + dxs = np.array(codestream.segment[1].xrsiz) + dys = np.array(codestream.segment[1].yrsiz) if np.any(dxs - dxs[0]) or np.any(dys - dys[0]): msg = "Components must all have the same subsampling factors " msg += "to use this method. Please consider using OPENJP2 and " @@ -1290,7 +1410,8 @@ class Jp2k(Jp2kBox): # Must check the specified rlevel against the maximum. if rlevel != 0: # Must check the specified rlevel against the maximum. - max_rlevel = self.codestream.segment[2].spcod[4] + codestream = self.get_codestream() + max_rlevel = codestream.segment[2].spcod[4] if rlevel == -1: # -1 is shorthand for the largest rlevel rlevel = max_rlevel @@ -1446,6 +1567,7 @@ class Jp2k(Jp2kBox): codestream = Codestream(fptr, self.length, header_only=header_only) else: + ftyp = self.box[1] box = [x for x in self.box if x.box_id == 'jp2c'] fptr.seek(box[0].offset) read_buffer = fptr.read(8) diff --git a/glymur/lib/__init__.py b/glymur/lib/__init__.py index ddce813..a283f7f 100644 --- a/glymur/lib/__init__.py +++ b/glymur/lib/__init__.py @@ -2,5 +2,3 @@ from . import openjp2 as openjp2 from . import openjpeg as openjpeg from . import c - -__all__ = [openjp2, openjpeg, c] diff --git a/glymur/lib/config.py b/glymur/lib/config.py index 8af038a..3aca5aa 100644 --- a/glymur/lib/config.py +++ b/glymur/lib/config.py @@ -1,6 +1,9 @@ """ Configure glymur to use installed libraries if possible. """ +# configparser is new in python3 (pylint/python-2.7) +# pylint: disable=F0401 + import ctypes from ctypes.util import find_library import os @@ -16,21 +19,18 @@ else: from configparser import NoOptionError # default library locations for MacPorts -_macports_default_location = {'openjp2': '/opt/local/lib/libopenjp2.dylib', - 'openjpeg': '/opt/local/lib/libopenjpeg.dylib'} +_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')} - +_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(): """Return the path to the configuration file. @@ -55,9 +55,8 @@ def glymurrc_fname(): # didn't find a configuration file. return None - def load_openjpeg_library(libname): - + path = read_config_file(libname) if path is not None: return load_library_handle(path) @@ -80,15 +79,13 @@ def load_openjpeg_library(libname): return load_library_handle(path) - def load_library_handle(path): """Load the library, return the ctypes handle.""" if path is None or path in ['None', 'none']: - # Either could not find a library via ctypes or - # user-configuration-file, or we could not find it in any of the - # default locations, or possibly the user intentionally does not want - # one of the libraries to load. + # Either could not find a library via ctypes or user-configuration-file, + # or we could not find it in any of the default locations, or possibly + # the user intentionally does not want one of the libraries to load. return None try: @@ -97,10 +94,10 @@ def load_library_handle(path): else: opj_lib = ctypes.CDLL(path) except (TypeError, OSError): - msg = 'The library specified by configuration file at {0} could not ' - msg += 'be loaded.' - warnings.warn(msg.format(path), UserWarning) - opj_lib = None + msg = 'The library specified by configuration file at {0} could not be ' + msg += 'loaded.' + warnings.warn(msg.format(path), UserWarning) + opj_lib = None return opj_lib @@ -133,7 +130,6 @@ def read_config_file(libname): path = None return path - def glymur_config(): """ Try to ascertain locations of openjp2, openjpeg libraries. @@ -151,7 +147,6 @@ def glymur_config(): warnings.warn(msg) return tuple(lst) - def get_configdir(): """Return string representing the configuration directory. diff --git a/glymur/lib/openjp2.py b/glymur/lib/openjp2.py index aed4db6..24122b9 100644 --- a/glymur/lib/openjp2.py +++ b/glymur/lib/openjp2.py @@ -2,6 +2,8 @@ Wraps individual functions in openjp2 library. """ +# pylint: disable=C0302,R0903,W0201 + import ctypes import re import sys @@ -408,6 +410,7 @@ class CompressionParametersType(ctypes.Structure): for j in range(self.numpocs): msg += " [#{0}]:".format(j) msg += " {0}".format(str(self.poc[j])) + msg += textwrap.indent(textstr, ' ' * 12) elif field_name in ['tcp_rates', 'tcp_distoratio']: lst = [] @@ -737,6 +740,28 @@ def 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): """get the decoded tile from the codec @@ -767,6 +792,23 @@ def 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): """End of compressing the current image. diff --git a/glymur/lib/openjpeg.py b/glymur/lib/openjpeg.py index d2f156b..924cac5 100644 --- a/glymur/lib/openjpeg.py +++ b/glymur/lib/openjpeg.py @@ -1,9 +1,13 @@ """Wraps library calls to openjpeg. """ +# pylint: disable=R0903 + import ctypes import sys +import numpy as np + from .config import glymur_config _, OPENJPEG = glymur_config() @@ -360,9 +364,9 @@ class DecompressionParametersType(ctypes.Structure): class ImageComptParmType(ctypes.Structure): """Component parameters structure used by the opj_image_create function. """ - _fields_ = [("dx", ctypes.c_int), - # XRsiz: horizontal separation of a sample of ith component + _fields_ = [# XRsiz: horizontal separation of a sample of ith component # with respect to the reference grid + ("dx", ctypes.c_int), # YRsiz: vertical separation of a sample of ith component with # respect to the reference grid */ @@ -523,6 +527,50 @@ def 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): """Wrapper for openjpeg library function opj_image_create. """ diff --git a/glymur/lib/test/test_openjp2.py b/glymur/lib/test/test_openjp2.py index c32ee89..988ace1 100644 --- a/glymur/lib/test/test_openjp2.py +++ b/glymur/lib/test/test_openjp2.py @@ -1,8 +1,13 @@ """ 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 re +import sys import tempfile import unittest @@ -16,8 +21,8 @@ from glymur.lib import openjp2 @unittest.skipIf(openjp2.OPENJP2 is None, "Missing openjp2 library.") @unittest.skipIf(re.match(r'''(1|2.0)''', - glymur.version.openjpeg_version) is not None, - "Not to be run until 2.1.0") + glymur.version.openjpeg_version) is not None, + "Not to be run until 2.1.0") class TestOpenJP2(unittest.TestCase): """Test openjp2 library functionality. @@ -147,7 +152,6 @@ class TestOpenJP2(unittest.TestCase): xtx5_setup(tfile.name) self.assertTrue(True) - def tile_encoder(**kwargs): """Fixture used by many tests.""" num_tiles = ((kwargs['image_width'] / kwargs['tile_width']) * @@ -211,7 +215,7 @@ def tile_encoder(**kwargs): openjp2.setup_encoder(codec, l_param, l_image) stream = openjp2.stream_create_default_file_stream(kwargs['filename'], - False) + False) openjp2.start_compress(codec, l_image, stream) for j in np.arange(num_tiles): @@ -222,14 +226,13 @@ def tile_encoder(**kwargs): openjp2.destroy_codec(codec) openjp2.image_destroy(l_image) - def tile_decoder(**kwargs): """Fixture called with various configurations by many tests. Reads a tile. That's all it does. """ stream = openjp2.stream_create_default_file_stream(kwargs['filename'], - True) + True) dparam = openjp2.set_default_decoder_parameters() dparam.decod_format = kwargs['codec_format'] @@ -267,7 +270,6 @@ def tile_decoder(**kwargs): openjp2.stream_destroy(stream) openjp2.image_destroy(image) - def ttx0_setup(filename): """Runs tests tte0, tte0.""" kwargs = {'filename': filename, @@ -281,7 +283,6 @@ def ttx0_setup(filename): 'tile_width': 100} tile_encoder(**kwargs) - def xtx2_setup(filename): """Runs tests rta2, tte2, ttd2.""" kwargs = {'filename': filename, @@ -295,7 +296,6 @@ def xtx2_setup(filename): 'tile_width': 128} tile_encoder(**kwargs) - def xtx3_setup(filename): """Runs tests tte3, rta3.""" kwargs = {'filename': filename, @@ -309,7 +309,6 @@ def xtx3_setup(filename): 'tile_width': 128} tile_encoder(**kwargs) - def xtx4_setup(filename): """Runs tests rta4, tte4.""" kwargs = {'filename': filename, @@ -323,7 +322,6 @@ def xtx4_setup(filename): 'tile_width': 128} tile_encoder(**kwargs) - def xtx5_setup(filename): """Runs tests rta5, tte5.""" kwargs = {'filename': filename, @@ -336,3 +334,6 @@ def xtx5_setup(filename): 'tile_height': 256, 'tile_width': 256} tile_encoder(**kwargs) + +if __name__ == "__main__": + unittest.main() diff --git a/glymur/lib/test/test_openjpeg.py b/glymur/lib/test/test_openjpeg.py index 449083f..f28656c 100644 --- a/glymur/lib/test/test_openjpeg.py +++ b/glymur/lib/test/test_openjpeg.py @@ -1,6 +1,8 @@ """ Tests for OpenJPEG module. """ +# pylint: disable=E1101,R0904 + import ctypes import re import sys @@ -8,7 +10,6 @@ import unittest import glymur - @unittest.skipIf(glymur.lib.openjpeg.OPENJPEG is None, "Missing openjpeg library.") class TestOpenJPEG(unittest.TestCase): diff --git a/glymur/lib/test/test_printing.py b/glymur/lib/test/test_printing.py index c7be21c..fb78676 100644 --- a/glymur/lib/test/test_printing.py +++ b/glymur/lib/test/test_printing.py @@ -16,7 +16,6 @@ else: 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") @@ -73,3 +72,6 @@ class TestPrintingOpenjp2(unittest.TestCase): expected = fixtures.default_image_type self.assertRegex(actual, expected) + + + diff --git a/glymur/test/fixtures.py b/glymur/test/fixtures.py index 34327fc..113a47b 100644 --- a/glymur/test/fixtures.py +++ b/glymur/test/fixtures.py @@ -37,7 +37,6 @@ elif re.match('1.[0-6]', six.__version__) is not None: # Cannot reopen a named temporary file in windows. WINDOWS_TMP_FILE_MSG = "cannot use NamedTemporaryFile like this in windows" - class MetadataBase(unittest.TestCase): """ Base class for testing metadata. @@ -102,8 +101,8 @@ class MetadataBase(unittest.TestCase): """ verify the fields of a RGN segment """ - self.assertEqual(actual.crgn, expected.crgn) # 0 = component - self.assertEqual(actual.srgn, expected.srgn) # 0 = implicit + self.assertEqual(actual.crgn, expected.crgn) # 0 = component + self.assertEqual(actual.srgn, expected.srgn) # 0 = implicit self.assertEqual(actual.sprgn, expected.sprgn) def verifySOTsegment(self, actual, expected): @@ -126,9 +125,8 @@ class MetadataBase(unittest.TestCase): """ Verify the fields of the SIZ segment. """ - for field in ['rsiz', 'xsiz', 'ysiz', 'xosiz', 'yosiz', 'xtsiz', - 'ytsiz', 'xtosiz', 'ytosiz', 'bitdepth', - 'xrsiz', 'yrsiz']: + for field in ['rsiz', 'xsiz', 'ysiz', 'xosiz', 'yosiz', 'xtsiz', + 'ytsiz', 'xtosiz', 'ytosiz', 'bitdepth', 'xrsiz', 'yrsiz']: self.assertEqual(getattr(actual, field), getattr(expected, field)) def verifyImageHeaderBox(self, box1, box2): @@ -155,7 +153,7 @@ class MetadataBase(unittest.TestCase): else: self.assertEqual(actual.colorspace, expected.colorspace) self.assertIsNone(actual.icc_profile) - + # The Python XMP Toolkit may be used for XMP UUIDs, but only if available and # if the version is at least 2.0.0. @@ -185,7 +183,7 @@ except: # 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 # 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 try: import skimage @@ -213,7 +211,7 @@ def _indent(textstr): String to be indented. indent_level : str Number of spaces of indentation to add. - + Returns ------- indented_string : str @@ -236,6 +234,7 @@ try: # The whole point of trying to import PIL is to determine if it's there # or not. We won't use it directly. + # pylint: disable=F0401,W0611 import PIL NO_READ_BACKEND = False @@ -545,7 +544,7 @@ text_gbr_34 = """Colour Specification Box (colr) @ (179, 1339) dump = r'''JPEG 2000 Signature Box (jP ) @ (0, 12) Signature: 0d0a870a File Type Box (ftyp) @ (12, 20) - Brand: jp2 + Brand: jp2 Compatibility: ['jp2 '] JP2 Header Box (jp2h) @ (32, 45) Image Header Box (ihdr) @ (40, 22) @@ -601,6 +600,7 @@ Contiguous Codestream Box (jp2c) @ (3223, 1132296) "Created by OpenJPEG version 2.0.0"''' 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) File Type Box (ftyp) @ (12, 20) @@ -613,7 +613,7 @@ Contiguous Codestream Box (jp2c) @ (3223, 1132296)""" nemo_dump_no_xml = '''JPEG 2000 Signature Box (jP ) @ (0, 12) Signature: 0d0a870a File Type Box (ftyp) @ (12, 20) - Brand: jp2 + Brand: jp2 Compatibility: ['jp2 '] JP2 Header Box (jp2h) @ (32, 45) Image Header Box (ihdr) @ (40, 22) @@ -669,7 +669,7 @@ Contiguous Codestream Box (jp2c) @ (3223, 1132296) dump = r"""JPEG 2000 Signature Box (jP ) @ (0, 12) Signature: 0d0a870a File Type Box (ftyp) @ (12, 20) - Brand: jp2 + Brand: jp2 Compatibility: ['jp2 '] JP2 Header Box (jp2h) @ (32, 45) Image Header Box (ihdr) @ (40, 22) @@ -691,26 +691,6 @@ nemo_dump_no_codestream = dump.format(_indent(nemo_xmp)) nemo_dump_no_codestream_no_xml = r"""JPEG 2000 Signature Box (jP ) @ (0, 12) Signature: 0d0a870a -File Type Box (ftyp) @ (12, 20) - Brand: jp2 - Compatibility: ['jp2 '] -JP2 Header Box (jp2h) @ (32, 45) - Image Header Box (ihdr) @ (40, 22) - Size: [1456 2592 3] - Bitdepth: 8 - Signed: False - Compression: wavelet - Colorspace Unknown: False - Colour Specification Box (colr) @ (62, 15) - Method: enumerated colorspace - Precedence: 0 - Colorspace: sRGB -UUID Box (uuid) @ (77, 3146) - UUID: be7acfcb-97a9-42e8-9c71-999491e3afac (XMP) -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 '] @@ -727,171 +707,7 @@ JP2 Header Box (jp2h) @ (32, 45) Colorspace: sRGB UUID Box (uuid) @ (77, 3146) UUID: be7acfcb-97a9-42e8-9c71-999491e3afac (XMP) - UUID Data: - - - - - Google - 2013-02-09T14:47:53 - - - 1 - 72/1 - 72/1 - 2 - HTC - HTC Glacier - 2592 - 1456 - - - 8 - 8 - 8 - - - 2 - 3 - - - 1343036288/4294967295 - 1413044224/4294967295 - - - - - 2748779008/4294967295 - 1417339264/4294967295 - 1288490240/4294967295 - 2576980480/4294967295 - 644245120/4294967295 - 257698032/4294967295 - - - - - 1 - 2528 - 1424 - 353/100 - 0 - 0/1 - WGS-84 - 2013-02-09T14:47:53 - - - 76 - - - 0220 - 0100 - - - 1 - 2 - 3 - 0 - - - 42,20.56N - 71,5.29W - 2013-02-09T19:47:53Z - NETWORK - - - 2013-02-09T14:47:53 - - - - - Glymur - Python XMP Toolkit - - - - - - -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)""" +Contiguous Codestream Box (jp2c) @ (3223, 1132296)""" # Output of reader requirements printing for text_GBR.jp2 text_GBR_rreq = r"""Reader Requirements Box (rreq) @ (40, 109) @@ -927,7 +743,7 @@ issue_183_colr = """Colour Specification Box (colr) @ (62, 12) Method: restricted ICC profile Precedence: 0 ICC Profile: None""" - + # Progression order is invalid. issue_186_progression_order = """COD marker segment @ (174, 12) @@ -1092,3 +908,4 @@ goodstuff_with_full_header = r"""Codestream: Step size: [(0, 8), (0, 9), (0, 9), (0, 10), (0, 9), (0, 9), (0, 10), (0, 9), (0, 9), (0, 10), (0, 9), (0, 9), (0, 10), (0, 9), (0, 9), (0, 10)] SOD marker segment @ (164, 0) EOC marker segment @ (115218, 0)""" + diff --git a/glymur/test/test_callbacks.py b/glymur/test/test_callbacks.py index cc30de8..849d987 100644 --- a/glymur/test/test_callbacks.py +++ b/glymur/test/test_callbacks.py @@ -1,6 +1,12 @@ """ 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 re import sys @@ -19,7 +25,6 @@ import glymur from .fixtures import WARNING_INFRASTRUCTURE_ISSUE, WARNING_INFRASTRUCTURE_MSG - class TestCallbacks(unittest.TestCase): """Test suite for callbacks.""" @@ -41,7 +46,7 @@ class TestCallbacks(unittest.TestCase): tiledata = j.read(tile=0) with tempfile.NamedTemporaryFile(suffix='.jp2') as tfile: with patch('sys.stdout', new=StringIO()) as fake_out: - glymur.Jp2k(tfile.name, data=tiledata, verbose=True) + j = glymur.Jp2k(tfile.name, data=tiledata, verbose=True) actual = fake_out.getvalue().strip() expected = '[INFO] tile number 1 / 1' self.assertEqual(actual, expected) @@ -55,7 +60,7 @@ class TestCallbacks(unittest.TestCase): 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) + jp2 = glymur.Jp2k(tfile.name, data=tiledata, verbose=True) actual = fake_out.getvalue().strip() expected = '[INFO] tile number 1 / 1' self.assertEqual(actual, expected) @@ -93,6 +98,8 @@ class TestCallbacks(unittest.TestCase): [0-9]+\.[0-9]+\ss""", re.VERBOSE) + # assertRegex in Python 3.3 (python2.7/pylint issue) + # pylint: disable=E1101 if sys.hexversion <= 0x03020000: self.assertRegexpMatches(actual, regex) else: diff --git a/glymur/test/test_config.py b/glymur/test/test_config.py index 59a8ef3..feb3235 100644 --- a/glymur/test/test_config.py +++ b/glymur/test/test_config.py @@ -1,7 +1,16 @@ """These tests are for edge cases where OPENJPEG does not exist, but OPENJP2 may be present in some form or other. """ -import contextlib +# unittest doesn't work well with R0904. +# pylint: disable=R0904 + +# 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 contextlib import ctypes import imp import os @@ -17,42 +26,41 @@ else: import glymur from glymur import Jp2k -from .fixtures import (WARNING_INFRASTRUCTURE_ISSUE, - WARNING_INFRASTRUCTURE_MSG, - WINDOWS_TMP_FILE_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'}): + 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): +@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. + 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) + curdir = os.getcwd() + try: + if dirname is not None: + os.chdir(dirname) + yield + finally: + os.chdir(curdir) @unittest.skipIf(sys.hexversion < 0x03020000, @@ -89,6 +97,7 @@ class TestSuite(unittest.TestCase): # Need to reliably recover the location of the openjp2 library, # so using '_name' appears to be the only way to do it. + # pylint: disable=W0212 libloc = glymur.lib.openjp2.OPENJP2._name line = 'openjp2: {0}\n'.format(libloc) tfile.write(line) @@ -121,7 +130,7 @@ class TestSuite(unittest.TestCase): "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.""" + """Verify that we can stop a library from being loaded by using None.""" with tempfile.TemporaryDirectory() as tdir: configdir = os.path.join(tdir, 'glymur') os.mkdir(configdir) @@ -131,9 +140,7 @@ class TestSuite(unittest.TestCase): # 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.write('openjpeg: {0}\n'.format(glymur.lib.openjp2.OPENJPEG._name)) fptr.flush() with patch.dict('os.environ', {'XDG_CONFIG_HOME': tdir}): imp.reload(glymur.lib.openjp2) @@ -142,17 +149,18 @@ class TestSuite(unittest.TestCase): @unittest.skipIf(glymur.lib.openjp2.OPENJPEG is None, "Needs openjpeg before this test make sense.") - @unittest.skipIf(openjpeg_not_found_by_ctypes(), - "OpenJPEG must be found before this test can work.") + @unittest.skipIf(openjpeg_not_found_by_ctypes(), + "OpenJPEG must be easily found before this test can work.") @unittest.skipIf(os.name == "nt", WINDOWS_TMP_FILE_MSG) def test_config_dir_but_no_config_file(self): with tempfile.TemporaryDirectory() as tdir: configdir = os.path.join(tdir, 'glymur') os.mkdir(configdir) + fname = os.path.join(configdir, 'glymurrc') with patch.dict('os.environ', {'XDG_CONFIG_HOME': tdir}): # Should still be able to load openjpeg, despite the - # configuration file not being there + # configuration file being empty. imp.reload(glymur.lib.openjpeg) self.assertIsNotNone(glymur.lib.openjp2.OPENJPEG) @@ -170,3 +178,4 @@ class TestSuite(unittest.TestCase): # Should be able to load openjp2 as before. imp.reload(glymur.lib.openjp2) self.assertEqual(glymur.lib.openjp2.OPENJP2._name, libloc) + diff --git a/glymur/test/test_glymur_warnings.py b/glymur/test/test_glymur_warnings.py index 8086004..b8e5c8b 100644 --- a/glymur/test/test_glymur_warnings.py +++ b/glymur/test/test_glymur_warnings.py @@ -1,32 +1,32 @@ """ Test suite for warnings issued by glymur. """ + +# unittest doesn't work well with R0904. +# pylint: disable=R0904 + +import platform import os import re import struct +import sys import tempfile import unittest +import six + from glymur import Jp2k import glymur from .fixtures import opj_data_file, OPJ_DATA_ROOT from .fixtures import WARNING_INFRASTRUCTURE_ISSUE, WARNING_INFRASTRUCTURE_MSG - @unittest.skipIf(OPJ_DATA_ROOT is None, "OPJ_DATA_ROOT environment variable not set") @unittest.skipIf(WARNING_INFRASTRUCTURE_ISSUE, WARNING_INFRASTRUCTURE_MSG) class TestWarnings(unittest.TestCase): """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): """ should warn if reading past end of a box @@ -53,11 +53,12 @@ class TestWarnings(unittest.TestCase): """ relpath = 'input/nonregression/issue188_beach_64bitsbox.jp2' jfile = opj_data_file(relpath) - pattern = r"""Unrecognized\sbox\s\(b'XML\s'\)\sencountered.""" - regex = re.compile(pattern, re.VERBOSE) + regex = re.compile(r"""Unrecognized\sbox\s\(b'XML\s'\)\sencountered.""", + re.VERBOSE) with self.assertWarnsRegex(UserWarning, regex): Jp2k(jfile) + def test_NR_gdal_fuzzer_unchecked_numresolutions_dump(self): """ Has an invalid number of resolutions. @@ -69,7 +70,7 @@ class TestWarnings(unittest.TestCase): \(\d+\)\.""", re.VERBOSE) with self.assertWarnsRegex(UserWarning, regex): - Jp2k(jfile).get_codestream() + Jp2k(jfile) @unittest.skipIf(re.match("1.5|2.0.0", glymur.version.openjpeg_version), "Test not passing on 1.5.x, not introduced until 2.x") @@ -84,7 +85,7 @@ class TestWarnings(unittest.TestCase): \(\d+\)\.""", re.VERBOSE) with self.assertWarnsRegex(UserWarning, regex): - Jp2k(jfile).get_codestream() + Jp2k(jfile) def test_NR_gdal_fuzzer_check_comp_dx_dy_jp2_dump(self): """ @@ -97,7 +98,7 @@ class TestWarnings(unittest.TestCase): dx=\d+,\s*dy=\d+""", re.VERBOSE) with self.assertWarnsRegex(UserWarning, regex): - Jp2k(jfile).get_codestream() + Jp2k(jfile) def test_NR_gdal_fuzzer_assert_in_opj_j2k_read_SQcd_SQcc_patch_jp2(self): lst = ['input', 'nonregression', @@ -107,32 +108,53 @@ class TestWarnings(unittest.TestCase): number\sof\scomponents\sis\sonly\s\d+""", re.VERBOSE) with self.assertWarnsRegex(UserWarning, regex): - Jp2k(jfile).get_codestream() + Jp2k(jfile) + + 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): """Should warn if RSIZ is bad. Issue196""" filename = opj_data_file('input/nonregression/edf_c2_1002767.jp2') with self.assertWarnsRegex(UserWarning, 'Invalid profile'): - Jp2k(filename).get_codestream() + Jp2k(filename) def test_bad_wavelet_transform(self): """Should warn if wavelet transform is bad. Issue195""" filename = opj_data_file('input/nonregression/edf_c2_10025.jp2') with self.assertWarnsRegex(UserWarning, 'Invalid wavelet transform'): - Jp2k(filename).get_codestream() + Jp2k(filename) def test_invalid_progression_order(self): """Should still be able to parse even if prog order is invalid.""" jfile = opj_data_file('input/nonregression/2977.pdf.asan.67.2198.jp2') with self.assertWarnsRegex(UserWarning, 'Invalid progression order'): - Jp2k(jfile).get_codestream() + Jp2k(jfile) def test_tile_height_is_zero(self): """Zero tile height should not cause an exception.""" - filename = 'input/nonregression/2539.pdf.SIGFPE.706.1712.jp2' - filename = opj_data_file(filename) + filename = opj_data_file('input/nonregression/2539.pdf.SIGFPE.706.1712.jp2') with self.assertWarnsRegex(UserWarning, 'Invalid tile dimensions'): - Jp2k(filename).get_codestream() + Jp2k(filename) @unittest.skipIf(os.name == "nt", "Temporary file issue on window.") def test_unknown_marker_segment(self): @@ -155,9 +177,9 @@ class TestWarnings(unittest.TestCase): read_buffer = ifile.read() tfile.write(read_buffer) tfile.flush() - + with self.assertWarnsRegex(UserWarning, 'Unrecognized marker'): - Jp2k(tfile.name).get_codestream() + codestream = Jp2k(tfile.name).get_codestream() if __name__ == "__main__": diff --git a/glymur/test/test_icc.py b/glymur/test/test_icc.py index e18775c..c6b63e8 100644 --- a/glymur/test/test_icc.py +++ b/glymur/test/test_icc.py @@ -1,7 +1,13 @@ """ ICC profile tests. """ + +# unittest doesn't work well with R0904. +# pylint: disable=R0904 + import datetime +import os +import sys import unittest import numpy as np @@ -60,6 +66,11 @@ class TestICC(unittest.TestCase): """invalid ICC header data should cause UserWarning""" jfile = opj_data_file('input/nonregression/orb-blue10-lin-jp2.jp2') + # assertWarns in Python 3.3 (python2.7/pylint issue) + # pylint: disable=E1101 regex = 'ICC profile header is corrupt' with self.assertWarnsRegex(UserWarning, regex): Jp2k(jfile) + +if __name__ == "__main__": + unittest.main() diff --git a/glymur/test/test_jp2box.py b/glymur/test/test_jp2box.py index f9e7c5c..28ae4fe 100644 --- a/glymur/test/test_jp2box.py +++ b/glymur/test/test_jp2box.py @@ -1,6 +1,18 @@ """ 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 os import re @@ -8,6 +20,7 @@ import shutil import struct import sys import tempfile +import uuid from uuid import UUID import unittest @@ -22,33 +35,26 @@ from glymur.jp2box import JPEG2000SignatureBox from glymur.core import COLOR, OPACITY from glymur.core import RED, GREEN, BLUE, GREY, WHOLE_IMAGE -from .fixtures import (WARNING_INFRASTRUCTURE_ISSUE, - WARNING_INFRASTRUCTURE_MSG, - WINDOWS_TMP_FILE_MSG, MetadataBase) - - -def docTearDown(doctest_obj): - glymur.set_parseoptions(full_codestream=False) - +from .fixtures import ( + WARNING_INFRASTRUCTURE_ISSUE, WARNING_INFRASTRUCTURE_MSG, + WINDOWS_TMP_FILE_MSG, MetadataBase +) def load_tests(loader, tests, ignore): """Run doc tests as well.""" if os.name == "nt": # Can't do it on windows, temporary file issue. return tests - tests.addTests(doctest.DocTestSuite('glymur.jp2box', - tearDown=docTearDown)) + tests.addTests(doctest.DocTestSuite('glymur.jp2box')) return tests - @unittest.skipIf(os.name == "nt", WINDOWS_TMP_FILE_MSG) class TestDataEntryURL(unittest.TestCase): """Test suite for DataEntryURL boxes.""" def setUp(self): self.jp2file = glymur.data.nemo() - @unittest.skipIf(re.match("1.5|2", - glymur.version.openjpeg_version) is None, + @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): """A single component should be wrapped as GREYSCALE.""" @@ -64,7 +70,7 @@ class TestDataEntryURL(unittest.TestCase): with tempfile.NamedTemporaryFile(suffix=".jp2") as tfile2: jp2 = j2k.wrap(tfile2.name) self.assertEqual(jp2.box[2].box[1].colorspace, - glymur.core.GREYSCALE) + glymur.core.GREYSCALE) def test_basic_url(self): """Just your most basic URL box.""" @@ -86,7 +92,7 @@ class TestDataEntryURL(unittest.TestCase): self.assertEqual(jp22.box[4].url, url) def test_null_termination(self): - """I.9.3.2 specifies that location field must be null terminated.""" + """I.9.3.2 specifies that the location field must be null terminated.""" jp2 = Jp2k(self.jp2file) url = 'http://glymur.readthedocs.org' @@ -97,15 +103,12 @@ class TestDataEntryURL(unittest.TestCase): jp22 = jp2.wrap(tfile.name, boxes=boxes) 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: 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_url = read_buffer.decode('utf-8') self.assertEqual(url + chr(0), read_url) @@ -125,18 +128,18 @@ class TestChannelDefinition(unittest.TestCase): data = j2k[:] # Write the first component back out to file. with tempfile.NamedTemporaryFile(suffix=".j2k", delete=False) as tfile: - Jp2k(tfile.name, data=data[:, :, 0]) + grey_j2k = Jp2k(tfile.name, data=data[:, :, 0]) cls.one_plane = tfile.name # Write the first two components back out to file. with tempfile.NamedTemporaryFile(suffix=".j2k", delete=False) as tfile: - Jp2k(tfile.name, data=data[:, :, 0:1]) + grey_j2k = Jp2k(tfile.name, data=data[:, :, 0:1]) cls.two_planes = tfile.name # Write four components back out to file. with tempfile.NamedTemporaryFile(suffix=".j2k", delete=False) as tfile: shape = (data.shape[0], data.shape[1], 1) alpha = np.zeros((shape), dtype=data.dtype) data4 = np.concatenate((data, alpha), axis=2) - Jp2k(tfile.name, data=data4) + rgba_jp2 = Jp2k(tfile.name, data=data4) cls.four_planes = tfile.name @classmethod @@ -389,7 +392,7 @@ class TestFileTypeBox(unittest.TestCase): ftyp = glymur.jp2box.FileTypeBox(brand='jp3') with self.assertRaises(IOError): with tempfile.TemporaryFile() as tfile: - ftyp.write(tfile) + ftyp.write(tfile) @unittest.skipIf(WARNING_INFRASTRUCTURE_ISSUE, WARNING_INFRASTRUCTURE_MSG) def test_cl_entry_unknown(self): @@ -399,8 +402,7 @@ class TestFileTypeBox(unittest.TestCase): ftyp = glymur.jp2box.FileTypeBox(compatibility_list=['jp3']) with self.assertRaises(IOError): with tempfile.TemporaryFile() as tfile: - ftyp.write(tfile) - + ftyp.write(tfile) class TestColourSpecificationBox(unittest.TestCase): """Test suite for colr box instantiation.""" @@ -523,8 +525,8 @@ class TestPaletteBox(unittest.TestCase): bps = (8, 8, 8) signed = (False, False) with self.assertWarns(UserWarning): - glymur.jp2box.PaletteBox(palette, bits_per_component=bps, - signed=signed) + pclr = glymur.jp2box.PaletteBox(palette, bits_per_component=bps, + signed=signed) @unittest.skipIf(WARNING_INFRASTRUCTURE_ISSUE, WARNING_INFRASTRUCTURE_MSG) def test_mismatched_signed_palette(self): @@ -533,8 +535,8 @@ class TestPaletteBox(unittest.TestCase): bps = (8, 8, 8, 8) signed = (False, False, False, False) with self.assertWarns(UserWarning): - glymur.jp2box.PaletteBox(palette, bits_per_component=bps, - signed=signed) + pclr = glymur.jp2box.PaletteBox(palette, bits_per_component=bps, + signed=signed) def test_writing_with_different_bitdepths(self): """Bitdepths must be the same when writing.""" @@ -634,7 +636,7 @@ class TestAppend(unittest.TestCase): jp2 = Jp2k(tfile.name) # Make a UUID box. Only XMP UUID boxes can currently be appended. - uuid_instance = UUID('00000000-0000-0000-0000-000000000000') + uuid_instance = uuid.UUID('00000000-0000-0000-0000-000000000000') data = b'0123456789' uuidbox = glymur.jp2box.UUIDBox(uuid_instance, data) with self.assertRaises(IOError): @@ -790,7 +792,7 @@ class TestWrap(unittest.TestCase): # list to trigger the error. boxes[2].box = [] with self.assertRaises(IOError): - jp2.wrap(tfile.name, boxes=boxes) + jp22 = jp2.wrap(tfile.name, boxes=boxes) def test_default_layout_with_boxes(self): """basic test for rewrapping a jp2 file, boxes specified""" @@ -855,8 +857,8 @@ class TestWrap(unittest.TestCase): """A palette box must reside in a JP2 header box.""" palette = np.array([[255, 0, 255], [0, 255, 0]], dtype=np.int32) bps = (8, 8, 8) - pclr = glymur.jp2box.PaletteBox(palette=palette, - bits_per_component=bps, + signed = (True, False, True) + pclr = glymur.jp2box.PaletteBox(palette=palette, bits_per_component=bps, signed=(True, False, True)) j2k = Jp2k(self.j2kfile) @@ -968,8 +970,7 @@ class TestWrap(unittest.TestCase): """Rewrap a jpx file.""" with tempfile.NamedTemporaryFile(suffix='.jp2') as tfile1: 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] jpx2 = jpx.wrap(tfile1.name, boxes=boxes) exp_ids = [box.box_id for box in boxes] @@ -1021,11 +1022,11 @@ class TestJp2Boxes(unittest.TestCase): """Raw instantiation should not produce a main_header.""" box = ContiguousCodestreamBox() self.assertEqual(box.box_id, 'jp2c') - self.assertIsNone(box.codestream) + self.assertIsNone(box.main_header) def test_codestream_main_header_offset(self): """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, j.box[5].offset + 8) @@ -1226,8 +1227,8 @@ class TestRepr(MetadataBase): def test_uuidlist_box(self): """Verify __repr__ method on ulst box.""" - uuid1 = UUID('00000000-0000-0000-0000-000000000001') - uuid2 = UUID('00000000-0000-0000-0000-000000000002') + uuid1 = uuid.UUID('00000000-0000-0000-0000-000000000001') + uuid2 = uuid.UUID('00000000-0000-0000-0000-000000000002') uuids = [uuid1, uuid2] ulst = glymur.jp2box.UUIDListBox(ulst=uuids) newbox = eval(repr(ulst)) @@ -1239,6 +1240,7 @@ class TestRepr(MetadataBase): """Verify Palette box repr.""" palette = np.array([[255, 0, 1000], [0, 255, 0]], dtype=np.int32) bps = (8, 8, 16) + signed = (True, False, True) box = glymur.jp2box.PaletteBox(palette=palette, bits_per_component=bps, signed=(True, False, True)) @@ -1281,15 +1283,14 @@ class TestRepr(MetadataBase): def test_uuid_box_generic(self): """Verify uuid repr method.""" - uuid_instance = UUID('00000000-0000-0000-0000-000000000000') + uuid_instance = uuid.UUID('00000000-0000-0000-0000-000000000000') data = b'0123456789' box = glymur.jp2box.UUIDBox(the_uuid=uuid_instance, raw_data=data) # 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()). regexp = r"""glymur.jp2box.UUIDBox\(""" - regexp += """the_uuid=""" - regexp += """UUID\('00000000-0000-0000-0000-000000000000'\),\s""" + regexp += """the_uuid=UUID\('00000000-0000-0000-0000-000000000000'\),\s""" regexp += """raw_data=\)""" if sys.hexversion < 0x03000000: @@ -1306,8 +1307,7 @@ class TestRepr(MetadataBase): # 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()). regexp = r"""glymur.jp2box.UUIDBox\(""" - regexp += """the_uuid=""" - regexp += """UUID\('be7acfcb-97a9-42e8-9c71-999491e3afac'\),\s""" + regexp += """the_uuid=UUID\('be7acfcb-97a9-42e8-9c71-999491e3afac'\),\s""" regexp += """raw_data=\)""" if sys.hexversion < 0x03000000: @@ -1323,7 +1323,7 @@ class TestRepr(MetadataBase): # Difficult to eval(repr()) this, so just match the general pattern. regexp = "glymur.jp2box.ContiguousCodeStreamBox" - regexp += "[(]codestream=> 16, - standard_masks[j] & 0x0000ffff >> 8, + standard_masks[j] & 0x0000ffff>> 8, standard_masks[j] & 0x000000ff) struct.pack_into('>HBBB', rreq_buffer, 17 + j * 5, standard_flags[j], *mask) @@ -599,6 +599,7 @@ class TestJPX(unittest.TestCase): self.assertEqual(jpx.box[2].standard_flag, (5, 42, 45, 2, 18, 19, 1, 8, 12, 31, 20)) + def test_nlst(self): """Verify that we can handle a number list box.""" j = Jp2k(self.jpxfile) diff --git a/glymur/test/test_jp2box_uuid.py b/glymur/test/test_jp2box_uuid.py index 6886c30..8ec35a2 100644 --- a/glymur/test/test_jp2box_uuid.py +++ b/glymur/test/test_jp2box_uuid.py @@ -1,7 +1,17 @@ # -*- coding: utf-8 -*- """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 re import shutil import struct import sys @@ -13,18 +23,30 @@ if sys.hexversion < 0x02070000: else: 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 -from .fixtures import (WARNING_INFRASTRUCTURE_ISSUE, - WARNING_INFRASTRUCTURE_MSG, - WINDOWS_TMP_FILE_MSG) +from .fixtures import HAS_PYTHON_XMP_TOOLKIT, OPJ_DATA_ROOT +from .fixtures import WARNING_INFRASTRUCTURE_ISSUE, WARNING_INFRASTRUCTURE_MSG + +if HAS_PYTHON_XMP_TOOLKIT: + from libxmp import XMPMeta import glymur from glymur import Jp2k -from .fixtures import SimpleRDF +from .fixtures import OPJ_DATA_ROOT, opj_data_file, SimpleRDF -@unittest.skipIf(os.name == "nt", WINDOWS_TMP_FILE_MSG) +@unittest.skipIf(os.name == "nt", "Unexplained failure on windows") class TestSuite(unittest.TestCase): """Tests for XMP, Exif UUIDs.""" @@ -79,9 +101,8 @@ class TestSuite(unittest.TestCase): jp2 = glymur.Jp2k(tfile.name) self.assertEqual(jp2.box[-1].data['Make'], "HTC") - @unittest.skipIf(WARNING_INFRASTRUCTURE_ISSUE, WARNING_INFRASTRUCTURE_MSG) -@unittest.skipIf(os.name == "nt", WINDOWS_TMP_FILE_MSG) +@unittest.skipIf(os.name == "nt", "Unexplained failure on windows") class TestSuiteWarns(unittest.TestCase): """Tests for XMP, Exif UUIDs, issues warnings.""" @@ -90,7 +111,7 @@ class TestSuiteWarns(unittest.TestCase): def tearDown(self): pass - + def test_unrecognized_exif_tag(self): """Verify warning in case of unrecognized tag.""" with tempfile.NamedTemporaryFile(suffix='.jp2', mode='wb') as tfile: @@ -114,7 +135,7 @@ class TestSuiteWarns(unittest.TestCase): tfile.flush() with self.assertWarnsRegex(UserWarning, 'Unrecognized Exif tag'): - glymur.Jp2k(tfile.name) + j = glymur.Jp2k(tfile.name) def test_bad_tag_datatype(self): """Only certain datatypes are allowable""" @@ -170,3 +191,6 @@ class TestSuiteWarns(unittest.TestCase): jp2 = glymur.Jp2k(tfile.name) self.assertEqual(jp2.box[-1].box_id, 'uuid') + +if __name__ == "__main__": + unittest.main() diff --git a/glymur/test/test_jp2box_xml.py b/glymur/test/test_jp2box_xml.py index 87bdd38..45d02f1 100644 --- a/glymur/test/test_jp2box_xml.py +++ b/glymur/test/test_jp2box_xml.py @@ -2,12 +2,35 @@ """ 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 re import struct +import sys import tempfile 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 glymur @@ -20,7 +43,6 @@ from .fixtures import OPJ_DATA_ROOT, opj_data_file from .fixtures import WARNING_INFRASTRUCTURE_ISSUE, WARNING_INFRASTRUCTURE_MSG from . import fixtures - @unittest.skipIf(os.name == "nt", fixtures.WINDOWS_TMP_FILE_MSG) class TestXML(unittest.TestCase): """Test suite for XML boxes.""" @@ -145,6 +167,7 @@ class TestXML(unittest.TestCase): u'Россия') + class TestJp2kBadXmlFile(unittest.TestCase): """Test suite for bad XML box situations""" @@ -270,19 +293,22 @@ class TestXML_OpjDataRoot(unittest.TestCase): 'nonregression', 'issue171.jp2')) 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)): jp2 = Jp2k(filename) self.assertIsNotNone(jp2.box[3].xml) + def test_invalid_utf8(self): """Bad byte sequence that cannot be parsed.""" - relname = '26ccf3651020967f7778238ef5af08af.SIGFPE.d25.527.jp2' filename = opj_data_file(os.path.join('input', 'nonregression', - relname)) + '26ccf3651020967f7778238ef5af08af.SIGFPE.d25.527.jp2')) with self.assertWarns((UserWarning, UserWarning)): jp2 = Jp2k(filename) self.assertIsNone(jp2.box[3].box[1].box[1].xml) + + + diff --git a/glymur/test/test_jp2k.py b/glymur/test/test_jp2k.py index 52945f9..f311c5c 100644 --- a/glymur/test/test_jp2k.py +++ b/glymur/test/test_jp2k.py @@ -1,9 +1,19 @@ """ Tests for general glymur functionality. """ +# E1101: assertWarns introduced in python 3.2 +# pylint: disable=E1101 + +# R0904: Not too many methods in unittest. +# pylint: disable=R0904 + +# E0611: unittest.mock is unknown to python2.7/pylint +# pylint: disable=E0611,F0401 + import doctest import os import re +import shutil import struct import sys import tempfile @@ -35,20 +45,18 @@ if HAS_PYTHON_XMP_TOOLKIT: from .fixtures import OPJ_DATA_ROOT, opj_data_file from . import fixtures - -def docTearDown(doctest_obj): - glymur.set_parseoptions(full_codestream=False) - - # Doc tests should be run as well. def load_tests(loader, tests, ignore): + # W0613: "loader" and "ignore" are necessary for the protocol + # They are unused here, however. + # pylint: disable=W0613 + """Should run doc tests as well""" if os.name == "nt": # Can't do it on windows, temporary file issue. return tests if glymur.lib.openjp2.OPENJP2 is not None: - tests.addTests(doctest.DocTestSuite('glymur.jp2k', - tearDown=docTearDown)) + tests.addTests(doctest.DocTestSuite('glymur.jp2k')) return tests @@ -69,13 +77,30 @@ class SliceProtocolBase(unittest.TestCase): self.j2k_data_r1 = self.j2k[::2, ::2] self.j2k_data_r5 = self.j2k[::32, ::32] - @unittest.skipIf(OPENJPEG_NOT_AVAILABLE, OPENJPEG_NOT_AVAILABLE_MSG) @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) class TestSliceProtocolBaseWrite(SliceProtocolBase): + def test_basic_write_by_tile_2d(self): + data = self.j2k_data[:, :, 0].copy() + with tempfile.NamedTemporaryFile(suffix='.jp2') as tfile: + kwargs = { + 'shape': (800, 480), + 'tileshape': (400, 240) + } + with Jp2k(tfile.name, **kwargs) as jp2: + jp2[:400, :240] = data[:400, :240] + jp2[:400, 240:480] = data[:400, 240:480] + jp2[400:800, :240] = data[400:800, :240] + jp2[400:800, 240:480] = data[400:800, 240:480] + + actual = Jp2k(tfile.name).read() + expected = data + import shutil; shutil.copyfile(tfile.name, '/Users/jevans/aa.jp2') + np.testing.assert_array_equal(actual, expected) + def test_write_ellipsis(self): expected = self.j2k_data @@ -141,6 +166,11 @@ class TestSliceProtocolBaseWrite(SliceProtocolBase): @unittest.skipIf(OPENJPEG_NOT_AVAILABLE, OPENJPEG_NOT_AVAILABLE_MSG) class TestSliceProtocolRead(SliceProtocolBase): + def test_resolution_strides_cannot_differ(self): + with self.assertRaises(IndexError): + # Strides in x/y directions cannot differ. + self.j2k[::2, ::3] + def test_resolution_strides_cannot_differ(self): with self.assertRaises(IndexError): # Strides in x/y directions cannot differ. @@ -157,8 +187,8 @@ class TestSliceProtocolRead(SliceProtocolBase): np.testing.assert_array_equal(self.j2k_data[:, :, j], band) def test_slice_in_third_dimension(self): - actual = self.j2k[:, :, 1:3] - expected = self.j2k_data[:, :, 1:3] + actual = self.j2k[:,:,1:3] + expected = self.j2k_data[:,:,1:3] np.testing.assert_array_equal(actual, expected) def test_reduce_resolution_and_slice_in_third_dimension(self): @@ -172,12 +202,12 @@ class TestSliceProtocolRead(SliceProtocolBase): np.testing.assert_array_equal(actual, expected) def test_retrieve_single_pixel(self): - actual = self.jp2[0, 0] + actual = self.jp2[0,0] expected = self.jp2_data[0, 0] np.testing.assert_array_equal(actual, expected) def test_retrieve_single_component(self): - actual = self.jp2[20, 20, 2] + actual = self.jp2[20,20,2] expected = self.jp2_data[20, 20, 2] np.testing.assert_array_equal(actual, expected) @@ -214,7 +244,7 @@ class TestSliceProtocolRead(SliceProtocolBase): def test_single_slice(self): rows = slice(3, 8) actual = self.j2k[rows] - expected = self.j2k_data[3:8, :, :] + expected = self.j2k_data[3:8, :,:] np.testing.assert_array_equal(actual, expected) @unittest.skipIf(re.match("0|1", glymur.version.openjpeg_version), @@ -223,7 +253,7 @@ class TestSliceProtocolRead(SliceProtocolBase): """ maximim rlevel - There seems to be a difference between version of openjpeg, as + There seems to be a difference between version of openjpeg, as openjp2 produces an image of size (16, 13, 3) and openjpeg produced (17, 12, 3). """ @@ -231,7 +261,6 @@ class TestSliceProtocolRead(SliceProtocolBase): expected = self.j2k_data_r5[1:17, 1:14] np.testing.assert_array_equal(actual, expected) - class TestJp2k(unittest.TestCase): """These tests should be run by just about all configuration.""" @@ -308,7 +337,7 @@ class TestJp2k(unittest.TestCase): @unittest.skipIf(OPENJPEG_NOT_AVAILABLE, OPENJPEG_NOT_AVAILABLE_MSG) @unittest.skipIf(re.match('1.[0-4]', openjpeg_version) is not None, - "Not supported on OpenJPEG {0}".format(openjpeg_version)) + "Not supported with OpenJPEG {0}".format(openjpeg_version)) @unittest.skipIf(re.match('1.5.(1|2)', openjpeg_version) is not None, "Mysteriously fails in 1.5.1 and 1.5.2") def test_no_cxform_pclr_jpx(self): @@ -627,7 +656,7 @@ class TestJp2k(unittest.TestCase): self.assertEqual(ET.tostring(jp2k.box[3].xml.getroot()), b'this is a test') - @unittest.skipIf(not HAS_PYTHON_XMP_TOOLKIT, + @unittest.skipIf(not HAS_PYTHON_XMP_TOOLKIT, "Requires Python XMP Toolkit >= 2.0") def test_xmp_attribute(self): """Verify the XMP packet in the shipping example file can be read.""" @@ -643,9 +672,8 @@ class TestJp2k(unittest.TestCase): xmp = XMPMeta() xmp.parse_from_str(j.box[3].raw_data.decode('utf-8'), xmpmeta_wrap=False) - creator_tool = xmp.get_property(libxmp.consts.XMP_NS_XMP, - 'CreatorTool') - self.assertEqual(creator_tool, 'Google') + creator_tool = xmp.get_property(libxmp.consts.XMP_NS_XMP, 'CreatorTool') + self.assertEqual(creator_tool, 'Google') @unittest.skipIf(OPENJPEG_NOT_AVAILABLE, OPENJPEG_NOT_AVAILABLE_MSG) @unittest.skipIf(re.match(r'''(1|2.0.0)''', @@ -664,7 +692,6 @@ class TestJp2k(unittest.TestCase): with self.assertRaises(RuntimeError): glymur.Jp2k(self.jp2file).read_bands() - @unittest.skipIf(OPENJPEG_NOT_AVAILABLE, OPENJPEG_NOT_AVAILABLE_MSG) @unittest.skipIf(re.match('1.[0-4]', openjpeg_version) is not None, "Not supported with OpenJPEG {0}".format(openjpeg_version)) @@ -684,30 +711,30 @@ class TestJp2k_write(unittest.TestCase): data = np.zeros((640, 480), dtype=np.uint8) with tempfile.NamedTemporaryFile(suffix='.j2k') as tfile: with self.assertRaises(IOError): - Jp2k(tfile.name, data=data, - cbsize=(16, 16), psizes=[(16, 16)]) + j = Jp2k(tfile.name, data=data, + cbsize=(16, 16), psizes=[(16, 16)]) def test_precinct_size_not_power_of_two(self): """must be power of two""" data = np.zeros((640, 480), dtype=np.uint8) with tempfile.NamedTemporaryFile(suffix='.j2k') as tfile: with self.assertRaises(IOError): - Jp2k(tfile.name, data=data, - cbsize=(16, 16), psizes=[(48, 48)]) + j = Jp2k(tfile.name, data=data, + cbsize=(16, 16), psizes=[(48, 48)]) def test_unsupported_int32(self): """Should raise a runtime error if trying to write int32""" data = np.zeros((128, 128), dtype=np.int32) with tempfile.NamedTemporaryFile(suffix='.j2k') as tfile: with self.assertRaises(RuntimeError): - Jp2k(tfile.name, data=data) + j = Jp2k(tfile.name, data=data) def test_unsupported_uint32(self): """Should raise a runtime error if trying to write uint32""" data = np.zeros((128, 128), dtype=np.uint32) with tempfile.NamedTemporaryFile(suffix='.j2k') as tfile: with self.assertRaises(RuntimeError): - Jp2k(tfile.name, data=data) + j = Jp2k(tfile.name, data=data) def test_write_with_version_too_early(self): """Should raise a runtime error if trying to write with version 1.3""" @@ -717,7 +744,7 @@ class TestJp2k_write(unittest.TestCase): with patch('glymur.version.openjpeg_version', new=version): with tempfile.NamedTemporaryFile(suffix='.j2k') as tfile: with self.assertRaises(RuntimeError): - Jp2k(tfile.name, data=data) + j = Jp2k(tfile.name, data=data) def test_cblkh_different_than_width(self): """Verify that we can set a code block size where height does not equal @@ -736,31 +763,31 @@ class TestJp2k_write(unittest.TestCase): """OpenJP2 only allows 2D or 3D images.""" with tempfile.NamedTemporaryFile(suffix='.j2k') as tfile: with self.assertRaises(IOError): - Jp2k(tfile.name, - data=np.zeros((128, 128, 2, 2), dtype=np.uint8)) + j = Jp2k(tfile.name, + data=np.zeros((128, 128, 2, 2), dtype=np.uint8)) def test_2d_rgb(self): """RGB must have at least 3 components.""" with tempfile.NamedTemporaryFile(suffix='.jp2') as tfile: with self.assertRaises(IOError): - Jp2k(tfile.name, - data=np.zeros((128, 128, 2), dtype=np.uint8), - colorspace='rgb') + j = Jp2k(tfile.name, + data=np.zeros((128, 128, 2), dtype=np.uint8), + colorspace='rgb') def test_colorspace_with_j2k(self): """Specifying a colorspace with J2K does not make sense""" with tempfile.NamedTemporaryFile(suffix='.j2k') as tfile: with self.assertRaises(IOError): - Jp2k(tfile.name, - data=np.zeros((128, 128, 3), dtype=np.uint8), - colorspace='rgb') + j = Jp2k(tfile.name, + data=np.zeros((128, 128, 3), dtype=np.uint8), + colorspace='rgb') def test_specify_rgb(self): """specify RGB explicitly""" with tempfile.NamedTemporaryFile(suffix='.jp2') as tfile: j = Jp2k(tfile.name, - data=np.zeros((128, 128, 3), dtype=np.uint8), - colorspace='rgb') + data=np.zeros((128, 128, 3), dtype=np.uint8), + colorspace='rgb') self.assertEqual(j.box[2].box[1].colorspace, glymur.core.SRGB) def test_specify_gray(self): @@ -795,7 +822,7 @@ class TestJp2k_write(unittest.TestCase): with tempfile.NamedTemporaryFile(suffix='.jp2') as tfile: with self.assertRaises(IOError): data = np.zeros((128, 128, 3), dtype=np.uint8) - Jp2k(tfile.name, data=data, colorspace='ycc') + j = Jp2k(tfile.name, data=data, colorspace='ycc') def test_write_with_jp2_in_caps(self): """should be able to write with JP2 suffix.""" @@ -824,7 +851,7 @@ class TestJp2k_write(unittest.TestCase): expdata = j2k[:] with tempfile.NamedTemporaryFile(suffix='.jp2') as tfile: with self.assertRaises(IOError): - Jp2k(tfile.name, data=expdata[:, :, 0], mct=True) + ofile = Jp2k(tfile.name, data=expdata[:, :, 0], mct=True) def test_write_cprl(self): """Must be able to write a CPRL progression order file""" @@ -915,7 +942,7 @@ class TestJp2k_2_0(unittest.TestCase): with tempfile.NamedTemporaryFile(suffix='.jp2') as tfile: data = np.zeros((128, 128, 3), dtype=np.uint8) with self.assertRaises(IOError): - Jp2k(tfile.name, data=data, colorspace='cmyk') + j = Jp2k(tfile.name, data=data, colorspace='cmyk') @unittest.skipIf(os.name == "nt", fixtures.WINDOWS_TMP_FILE_MSG) def test_asoc_label_box(self): @@ -924,7 +951,7 @@ class TestJp2k_2_0(unittest.TestCase): # OpenJPEG doesn't have such a file. data = Jp2k(self.jp2file)[::2, ::2] with tempfile.NamedTemporaryFile(suffix='.jp2') as tfile: - Jp2k(tfile.name, data=data) + j = Jp2k(tfile.name, data=data) with tempfile.NamedTemporaryFile(suffix='.jp2') as tfile2: @@ -1032,15 +1059,12 @@ class TestJp2k_2_1(unittest.TestCase): Invalid\svalues\sfor\scomp\s=\s0\s+ :\sdx=1\sdy=0''', re.VERBOSE) if sys.hexversion < 0x03020000: - with self.assertRaisesRegexp((IOError, OSError), - regexp): + with self.assertRaisesRegexp((IOError, OSError), regexp): j[::2, ::2] else: - with self.assertRaisesRegex((IOError, OSError), - regexp): + with self.assertRaisesRegex((IOError, OSError), regexp): j[::2, ::2] - @unittest.skipIf(OPJ_DATA_ROOT is None, "OPJ_DATA_ROOT environment variable not set") class TestParsing(unittest.TestCase): @@ -1048,31 +1072,31 @@ class TestParsing(unittest.TestCase): def setUp(self): self.jp2file = glymur.data.nemo() # Reset parseoptions for every test. - glymur.set_parseoptions(full_codestream=False) + glymur.set_parseoptions(codestream=True) def tearDown(self): - glymur.set_parseoptions(full_codestream=False) + glymur.set_parseoptions(codestream=True) @unittest.skipIf(WARNING_INFRASTRUCTURE_ISSUE, WARNING_INFRASTRUCTURE_MSG) def test_bad_rsiz(self): """Should not warn if RSIZ when parsing is turned off.""" filename = opj_data_file('input/nonregression/edf_c2_1002767.jp2') - glymur.set_parseoptions(full_codestream=False) - Jp2k(filename) + glymur.set_parseoptions(codestream=False) + j = Jp2k(filename) - glymur.set_parseoptions(full_codestream=True) + glymur.set_parseoptions(codestream=True) with self.assertWarnsRegex(UserWarning, 'Invalid profile'): - Jp2k(filename) + jp2 = Jp2k(filename) def test_main_header(self): - """verify that the main header isn't loaded during normal parsing""" + """Verify that the main header is not loaded when parsing turned off.""" # The hidden _main_header attribute should show up after accessing it. + glymur.set_parseoptions(codestream=False) jp2 = Jp2k(self.jp2file) jp2c = jp2.box[4] - self.assertIsNone(jp2c._codestream) - jp2c.codestream - self.assertIsNotNone(jp2c._codestream) - + self.assertIsNone(jp2c._main_header) + main_header = jp2c.main_header + self.assertIsNotNone(jp2c._main_header) @unittest.skipIf(WARNING_INFRASTRUCTURE_ISSUE, WARNING_INFRASTRUCTURE_MSG) @unittest.skipIf(OPJ_DATA_ROOT is None, @@ -1095,13 +1119,13 @@ class TestJp2kOpjDataRootWarnings(unittest.TestCase): """Should warn in case of bad ftyp brand.""" filename = opj_data_file('input/nonregression/edf_c2_1000290.jp2') with self.assertWarns(UserWarning): - Jp2k(filename) + jp2 = Jp2k(filename) def test_invalid_approximation(self): """Should warn in case of invalid approximation.""" filename = opj_data_file('input/nonregression/edf_c2_1015644.jp2') with self.assertWarnsRegex(UserWarning, 'Invalid approximation'): - Jp2k(filename) + jp2 = Jp2k(filename) def test_invalid_colorspace(self): """ @@ -1111,19 +1135,19 @@ class TestJp2kOpjDataRootWarnings(unittest.TestCase): """ filename = opj_data_file('input/nonregression/edf_c2_1103421.jp2') with self.assertWarns(UserWarning): - Jp2k(filename) + jp2 = Jp2k(filename) def test_stupid_windows_eol_at_end(self): """Garbage characters at the end of the file.""" filename = opj_data_file('input/nonregression/issue211.jp2') with self.assertWarns(UserWarning): - Jp2k(filename) + jp2 = Jp2k(filename) @unittest.skipIf(OPJ_DATA_ROOT is None, "OPJ_DATA_ROOT environment variable not set") class TestJp2kOpjDataRoot(unittest.TestCase): - """These tests should be run by just about all configurations.""" + """These tests should be run by just about all configuration.""" @unittest.skipIf(re.match("0|1.[0-4]", glymur.version.openjpeg_version), "Must have openjpeg 1.5 or higher to run") @@ -1132,9 +1156,9 @@ class TestJp2kOpjDataRoot(unittest.TestCase): """Irreversible""" filename = opj_data_file('input/nonregression/issue141.rawl') expdata = np.fromfile(filename, dtype=np.uint16) - expdata.resize((32, 2048)) + expdata.resize((2816, 2048)) with tempfile.NamedTemporaryFile(suffix='.j2k') as tfile: - j = Jp2k(tfile.name, data=expdata, irreversible=True, numres=5) + j = Jp2k(tfile.name, data=expdata, irreversible=True) codestream = j.get_codestream() self.assertEqual(codestream.segment[2].spcod[8], @@ -1142,7 +1166,7 @@ class TestJp2kOpjDataRoot(unittest.TestCase): actdata = j[:] self.assertTrue(fixtures.mse(actdata, expdata) < 250) - + @unittest.skipIf(WARNING_INFRASTRUCTURE_ISSUE, WARNING_INFRASTRUCTURE_MSG) def test_no_cxform_pclr_jp2(self): """Indices for pclr jpxfile if no color transform""" @@ -1174,7 +1198,7 @@ class TestJp2kOpjDataRoot(unittest.TestCase): j = Jp2k(filename) with self.assertRaises(RuntimeError): j[:] - + @unittest.skipIf(WARNING_INFRASTRUCTURE_ISSUE, WARNING_INFRASTRUCTURE_MSG) def test_no_cxform_cmap(self): """Bands as physically ordered, not as physically intended""" @@ -1190,11 +1214,31 @@ class TestJp2kOpjDataRoot(unittest.TestCase): expected = np.zeros(ycbcr.shape, ycbcr.dtype) for k in range(crcby.shape[2]): - expected[:, :, crcby.shape[2] - k - 1] = crcby[:, :, k] + expected[:,:,crcby.shape[2] - k - 1] = crcby[:,:,k] np.testing.assert_array_equal(ycbcr, expected) +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): @@ -1248,6 +1292,7 @@ class TestCodestreamOpjData(unittest.TestCase): # 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') @@ -1302,16 +1347,6 @@ class TestCodestreamRepr(unittest.TestCase): self.assertEqual(newseg.bitdepth, (8, 8, 8)) self.assertEqual(newseg.signed, (False, False, False)) - 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)) - class TestCodestream(unittest.TestCase): """Test suite for unusual codestream cases.""" @@ -1331,3 +1366,112 @@ class TestCodestream(unittest.TestCase): # 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)) diff --git a/glymur/test/test_opj_suite.py b/glymur/test/test_opj_suite.py index 9e8a0eb..028734d 100644 --- a/glymur/test/test_opj_suite.py +++ b/glymur/test/test_opj_suite.py @@ -2,6 +2,31 @@ 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 @@ -13,11 +38,12 @@ import glymur from glymur import Jp2k from glymur.jp2box import FileTypeBox, ImageHeaderBox, ColourSpecificationBox -from .fixtures import (OPJ_DATA_ROOT, MetadataBase, - WARNING_INFRASTRUCTURE_ISSUE, - WARNING_INFRASTRUCTURE_MSG, - mse, peak_tolerance, read_pgx, opj_data_file, - OPENJPEG_NOT_AVAILABLE, OPENJPEG_NOT_AVAILABLE_MSG) +from .fixtures import ( + OPJ_DATA_ROOT, MetadataBase, + WARNING_INFRASTRUCTURE_ISSUE, WARNING_INFRASTRUCTURE_MSG, + mse, peak_tolerance, read_pgx, opj_data_file, + OPENJPEG_NOT_AVAILABLE, OPENJPEG_NOT_AVAILABLE_MSG +) @unittest.skipIf(OPENJPEG_NOT_AVAILABLE, OPENJPEG_NOT_AVAILABLE_MSG) @@ -359,14 +385,11 @@ class TestSuiteWarns(MetadataBase): jpdata = jp2k[:] self.assertEqual(jpdata.shape, (512, 768, 3)) - def test_NR_broken1_jp2_dump(self): - jfile = opj_data_file('input/nonregression/broken1.jp2') + def test_NR_broken_jp2_dump(self): + jfile = opj_data_file('input/nonregression/broken.jp2') - # The colr box has a ridiculously incorrect box length. - regex = re.compile(r'''b'colr'\sbox\shas\sincorrect\sbox\slength\s - \(\d+\)''', - re.VERBOSE) - with self.assertWarnsRegex(UserWarning, regex): + with self.assertWarns(UserWarning): + # colr box has bad length. jp2 = Jp2k(jfile) ids = [box.box_id for box in jp2.box] @@ -385,24 +408,23 @@ class TestSuiteWarns(MetadataBase): expected = ColourSpecificationBox(colorspace=glymur.core.SRGB) self.verifyColourSpecificationBox(jp2.box[2].box[1], expected) - c = jp2.box[3].codestream + c = jp2.box[3].main_header ids = [x.marker_id for x in c.segment] expected = ['SOC', 'SIZ', 'CME', 'COD', 'QCD', 'QCC', 'QCC'] self.assertEqual(ids, expected) kwargs = {'rsiz': 0, 'xysiz': (203, 152), 'xyosiz': (0, 0), - 'xytsiz': (203, 152), 'xytosiz': (0, 0), - 'bitdepth': (8, 8, 8), - 'signed': (False, False, False), - 'xyrsiz': [(1, 1, 1), (1, 1, 1)]} + 'xytsiz': (203, 152), 'xytosiz': (0, 0), 'bitdepth': (8, 8, 8), + 'signed': (False, False, False), + 'xyrsiz': [(1, 1, 1), (1, 1, 1)]} self.verifySizSegment(c.segment[1], - glymur.codestream.SIZsegment(**kwargs)) + glymur.codestream.SIZsegment(**kwargs)) 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], - glymur.codestream.CMEsegment(*pargs)) + glymur.codestream.CMEsegment(*pargs)) # COD: Coding style default self.assertFalse(c.segment[3].scod & 2) # no sop @@ -414,7 +436,7 @@ class TestSuiteWarns(MetadataBase): self.assertEqual(tuple(c.segment[3].code_block_size), (64, 64)) # cblk 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], glymur.core.WAVELET_XFORM_5X3_REVERSIBLE) self.assertEqual(len(c.segment[3].spcod), 9) @@ -587,16 +609,13 @@ class TestSuite2point0(unittest.TestCase): @unittest.skipIf(WARNING_INFRASTRUCTURE_ISSUE, WARNING_INFRASTRUCTURE_MSG) def test_NR_DEC_broken2_jp2_5_decode(self): - """ - Invalid marker ID on codestream, Null pointer access upon read. - """ + # Null pointer access 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.assertWarnsRegex(UserWarning, regex): + with self.assertWarns(UserWarning): + # Invalid marker ID. Jp2k(jfile)[:] + self.assertTrue(True) @unittest.skipIf(WARNING_INFRASTRUCTURE_ISSUE, WARNING_INFRASTRUCTURE_MSG) def test_NR_DEC_broken4_jp2_7_decode(self): @@ -707,7 +726,7 @@ class TestSuite2point1(unittest.TestCase): 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 + tdata = jp2k[896:1024, 896:1024] # last tile odata = jp2k[:] np.testing.assert_array_equal(tdata, odata[896:1024, 896:1024]) @@ -779,7 +798,6 @@ class TestSuite2point1(unittest.TestCase): 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''', @@ -788,7 +806,7 @@ class TestSuite2point1(unittest.TestCase): 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 diff --git a/glymur/test/test_opj_suite_dump.py b/glymur/test/test_opj_suite_dump.py index 7ac513f..ee1838b 100644 --- a/glymur/test/test_opj_suite_dump.py +++ b/glymur/test/test_opj_suite_dump.py @@ -2,26 +2,48 @@ The tests defined here roughly correspond to what is in the OpenJPEG test suite. """ + +# Some test names correspond with openjpeg tests. Long names are ok in this +# case. +# pylint: disable=C0103 + +# All of these tests correspond to tests in openjpeg, so no docstring is really +# needed. +# pylint: disable=C0111 + +# This module is very long, cannot be helped. +# pylint: disable=C0302 + +# unittest fools pylint with "too many public methods" +# pylint: disable=R0904 + +# Some tests use numpy test infrastructure, which means the tests never +# reference "self", so pylint claims it should be a function. No, no, no. +# pylint: disable=R0201 + +# Many tests are pretty long and that can't be helped. +# pylint: disable=R0915 + +# asserWarns introduced in python 3.2 (python2.7/pylint issue) +# pylint: disable=E1101 + import re +import sys import unittest -import warnings import numpy as np import glymur from glymur import Jp2k from glymur.codestream import CMEsegment, SOTsegment, RGNsegment -from glymur.core import (RCME_ISO_8859_1, RCME_BINARY, SRGB, - GREYSCALE, RESTRICTED_ICC_PROFILE, - ENUMERATED_COLORSPACE) +from glymur.core import RCME_ISO_8859_1, RCME_BINARY from glymur.jp2box import FileTypeBox -from .fixtures import (MetadataBase, OPJ_DATA_ROOT, - WARNING_INFRASTRUCTURE_ISSUE, - WARNING_INFRASTRUCTURE_MSG, - opj_data_file) - -comment1 = "Creator: AV-J2K (c) 2000,2001 Algo Vision Technology" +from .fixtures import ( + MetadataBase, OPJ_DATA_ROOT, + WARNING_INFRASTRUCTURE_ISSUE, WARNING_INFRASTRUCTURE_MSG, + mse, peak_tolerance, read_pgx, opj_data_file +) @unittest.skipIf(OPJ_DATA_ROOT is None, @@ -53,19 +75,17 @@ class TestSuite(MetadataBase): colr = glymur.jp2box.ColourSpecificationBox(colorspace=glymur.core.YCC) self.verifyColourSpecificationBox(jp2.box[2].box[1], colr) - c = jp2.box[3].codestream + c = jp2.box[3].main_header ids = [x.marker_id for x in c.segment] expected = ['SOC', 'SIZ', 'COD', 'QCD'] self.assertEqual(ids, expected) kwargs = {'rsiz': 0, 'xysiz': (720, 243), 'xyosiz': (0, 0), - 'xytsiz': (720, 243), 'xytosiz': (0, 0), - 'bitdepth': (8, 8, 8), - 'signed': (False, False, False), - 'xyrsiz': [(1, 2, 2), (1, 1, 1)]} - self.verifySizSegment(c.segment[1], - glymur.codestream.SIZsegment(**kwargs)) + 'xytsiz': (720, 243), 'xytosiz': (0, 0), 'bitdepth': (8, 8, 8), + 'signed': (False, False, False), + 'xyrsiz': [(1, 2, 2), (1, 1, 1)]} + self.verifySizSegment(c.segment[1], glymur.codestream.SIZsegment(**kwargs)) # COD: Coding style default self.assertFalse(c.segment[2].scod & 2) # no sop @@ -77,7 +97,7 @@ class TestSuite(MetadataBase): self.assertEqual(tuple(c.segment[2].code_block_size), (32, 128)) # cblk 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], glymur.core.WAVELET_XFORM_9X7_IRREVERSIBLE) self.assertEqual(len(c.segment[2].spcod), 9) @@ -101,10 +121,9 @@ class TestSuite(MetadataBase): self.assertEqual(actual, expected) kwargs = {'rsiz': 1, 'xysiz': (128, 128), 'xyosiz': (0, 0), - 'xytsiz': (128, 128), 'xytosiz': (0, 0), 'bitdepth': (8,), - 'signed': (False,), 'xyrsiz': [(1,), (1,)]} - self.verifySizSegment(c.segment[1], - glymur.codestream.SIZsegment(**kwargs)) + 'xytsiz': (128, 128), 'xytosiz': (0, 0), 'bitdepth': (8,), + 'signed': (False,), 'xyrsiz': [(1,), (1,)]} + self.verifySizSegment(c.segment[1], glymur.codestream.SIZsegment(**kwargs)) # QCD: Quantization default self.assertEqual(c.segment[2].sqcd & 0x1f, 0) @@ -124,7 +143,7 @@ class TestSuite(MetadataBase): self.assertEqual(tuple(c.segment[3].code_block_size), (64, 64)) # cblk 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], glymur.core.WAVELET_XFORM_5X3_REVERSIBLE) @@ -135,10 +154,9 @@ class TestSuite(MetadataBase): c = Jp2k(jfile).get_codestream(header_only=False) kwargs = {'rsiz': 1, 'xysiz': (127, 126), 'xyosiz': (0, 0), - 'xytsiz': (127, 126), 'xytosiz': (0, 0), 'bitdepth': (8,), - 'signed': (False,), 'xyrsiz': [(2,), (1,)]} - self.verifySizSegment(c.segment[1], - glymur.codestream.SIZsegment(**kwargs)) + 'xytsiz': (127, 126), 'xytosiz': (0, 0), 'bitdepth': (8,), + 'signed': (False,), 'xyrsiz': [(2,), (1,)]} + self.verifySizSegment(c.segment[1], glymur.codestream.SIZsegment(**kwargs)) # COD: Coding style default self.assertTrue(c.segment[2].scod & 2) # sop @@ -150,7 +168,7 @@ class TestSuite(MetadataBase): self.assertEqual(tuple(c.segment[2].code_block_size), (64, 64)) # cblk self.verify_codeblock_style(c.segment[2].spcod[7], - [False, False, True, False, True, True]) + [False, False, True, False, True, True]) self.assertEqual(c.segment[2].spcod[8], glymur.core.WAVELET_XFORM_9X7_IRREVERSIBLE) @@ -160,7 +178,7 @@ class TestSuite(MetadataBase): self.assertEqual(tuple(c.segment[3].code_block_size), (32, 32)) # cblk self.verify_codeblock_style(c.segment[3].spcoc[3], - [False, False, True, False, True, True]) + [False, False, True, False, True, True]) self.assertEqual(c.segment[3].spcoc[4], glymur.core.WAVELET_XFORM_5X3_REVERSIBLE) @@ -173,8 +191,7 @@ class TestSuite(MetadataBase): self.assertEqual(c.segment[4].mantissa, [0, 0, 0, 0, 0, 0, 0, 0, 0, 0]) - pargs = (RCME_ISO_8859_1, - "Creator: AV-J2K (c) 2000,2001 Algo Vision".encode()) + pargs = RCME_ISO_8859_1, "Creator: AV-J2K (c) 2000,2001 Algo Vision".encode() self.verifyCMEsegment(c.segment[5], CMEsegment(*pargs)) # One unknown marker @@ -200,10 +217,9 @@ class TestSuite(MetadataBase): c = Jp2k(jfile).get_codestream(header_only=False) kwargs = {'rsiz': 1, 'xysiz': (256, 256), 'xyosiz': (0, 0), - 'xytsiz': (128, 128), 'xytosiz': (0, 0), 'bitdepth': (4,), - 'signed': (True,), 'xyrsiz': [(1,), (1,)]} - self.verifySizSegment(c.segment[1], - glymur.codestream.SIZsegment(**kwargs)) + 'xytsiz': (128, 128), 'xytosiz': (0, 0), 'bitdepth': (4,), + 'signed': (True,), 'xyrsiz': [(1,), (1,)]} + self.verifySizSegment(c.segment[1], glymur.codestream.SIZsegment(**kwargs)) # COD: Coding style default self.assertTrue(c.segment[2].scod & 2) @@ -215,7 +231,7 @@ class TestSuite(MetadataBase): self.assertEqual(tuple(c.segment[2].code_block_size), (64, 64)) # cblk 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], glymur.core.WAVELET_XFORM_5X3_REVERSIBLE) @@ -247,11 +263,11 @@ class TestSuite(MetadataBase): self.assertEqual(c.segment[6].xcrg, (65424,)) self.assertEqual(c.segment[6].ycrg, (32558,)) - pargs = (RCME_ISO_8859_1, - "Creator: AV-J2K (c) 2000,2001 Algo Vision".encode()) + pargs = RCME_ISO_8859_1, "Creator: AV-J2K (c) 2000,2001 Algo Vision".encode() self.verifyCMEsegment(c.segment[7], CMEsegment(*pargs)) - pargs = (RCME_ISO_8859_1, comment1.encode()) + pargs = (RCME_ISO_8859_1, + "Creator: AV-J2K (c) 2000,2001 Algo Vision Technology".encode()) self.verifyCMEsegment(c.segment[8], CMEsegment(*pargs)) pargs = (RCME_BINARY, c.segment[9].ccme) @@ -274,12 +290,10 @@ class TestSuite(MetadataBase): c = Jp2k(jfile).get_codestream(header_only=False) kwargs = {'rsiz': 1, 'xysiz': (640, 480), 'xyosiz': (0, 0), - 'xytsiz': (640, 480), 'xytosiz': (0, 0), - 'bitdepth': (8, 8, 8), - 'signed': (False, False, False), - 'xyrsiz': [(1, 1, 1), (1, 1, 1)]} - self.verifySizSegment(c.segment[1], - glymur.codestream.SIZsegment(**kwargs)) + 'xytsiz': (640, 480), 'xytosiz': (0, 0), 'bitdepth': (8, 8, 8), + 'signed': (False, False, False), + 'xyrsiz': [(1, 1, 1), (1, 1, 1)]} + self.verifySizSegment(c.segment[1], glymur.codestream.SIZsegment(**kwargs)) # COD: Coding style default self.assertFalse(c.segment[2].scod & 2) @@ -291,7 +305,7 @@ class TestSuite(MetadataBase): self.assertEqual(tuple(c.segment[2].code_block_size), (64, 64)) # cblk self.verify_codeblock_style(c.segment[2].spcod[7], - [False, False, True, False, False, False]) + [False, False, True, False, False, False]) self.assertEqual(c.segment[2].spcod[8], glymur.core.WAVELET_XFORM_9X7_IRREVERSIBLE) self.assertEqual(c.segment[2].precinct_size, @@ -339,7 +353,7 @@ class TestSuite(MetadataBase): 2002, 1888]) pargs = (RCME_ISO_8859_1, - "Creator: AV-J2K (c) 2000,2001 Algo Vision".encode()) + "Creator: AV-J2K (c) 2000,2001 Algo Vision".encode()) self.verifyCMEsegment(c.segment[6], CMEsegment(*pargs)) self.verifySOTsegment(c.segment[7], SOTsegment(0, 264383, 0, 1)) @@ -353,12 +367,11 @@ class TestSuite(MetadataBase): c = Jp2k(jfile).get_codestream(header_only=False) kwargs = {'rsiz': 1, 'xysiz': (1024, 1024), 'xyosiz': (0, 0), - 'xytsiz': (1024, 1024), 'xytosiz': (0, 0), - 'bitdepth': (8, 8, 8, 8), - 'signed': (False, False, False, False), - 'xyrsiz': [(1, 1, 2, 2), (1, 1, 2, 2)]} - self.verifySizSegment(c.segment[1], - glymur.codestream.SIZsegment(**kwargs)) + 'xytsiz': (1024, 1024), 'xytosiz': (0, 0), + 'bitdepth': (8, 8, 8, 8), + 'signed': (False, False, False, False), + 'xyrsiz': [(1, 1, 2, 2), (1, 1, 2, 2)]} + self.verifySizSegment(c.segment[1], glymur.codestream.SIZsegment(**kwargs)) # COD: Coding style default self.assertFalse(c.segment[2].scod & 2) @@ -370,7 +383,7 @@ class TestSuite(MetadataBase): self.assertEqual(tuple(c.segment[2].code_block_size), (32, 32)) # cblk 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], glymur.core.WAVELET_XFORM_9X7_IRREVERSIBLE) self.assertEqual(len(c.segment[2].spcod), 9) @@ -381,7 +394,7 @@ class TestSuite(MetadataBase): self.assertEqual(tuple(c.segment[3].code_block_size), (32, 32)) # cblk self.verify_codeblock_style(c.segment[3].spcoc[3], - [False, False, False, False, False, False]) + [False, False, False, False, False, False]) self.assertEqual(c.segment[3].spcoc[4], glymur.core.WAVELET_XFORM_9X7_IRREVERSIBLE) @@ -391,7 +404,7 @@ class TestSuite(MetadataBase): self.assertEqual(tuple(c.segment[4].code_block_size), (32, 32)) # cblk self.verify_codeblock_style(c.segment[4].spcoc[3], - [False, False, False, False, False, False]) + [False, False, False, False, False, False]) self.assertEqual(c.segment[4].spcoc[4], glymur.core.WAVELET_XFORM_5X3_REVERSIBLE) @@ -428,7 +441,7 @@ class TestSuite(MetadataBase): self.assertEqual(c.segment[7].mantissa, [0] * 19) pargs = (RCME_ISO_8859_1, - "Creator: AV-J2K (c) 2000,2001 Algo Vision".encode()) + "Creator: AV-J2K (c) 2000,2001 Algo Vision".encode()) self.verifyCMEsegment(c.segment[8], CMEsegment(*pargs)) # TLM (tile-part length) @@ -447,12 +460,11 @@ class TestSuite(MetadataBase): c = Jp2k(jfile).get_codestream(header_only=False) kwargs = {'rsiz': 2, 'xysiz': (513, 129), 'xyosiz': (0, 0), - 'xytsiz': (513, 129), 'xytosiz': (0, 0), - 'bitdepth': (12, 12, 12, 12), - 'signed': (False, False, False, False), - 'xyrsiz': [(1, 2, 1, 2), (1, 1, 2, 2)]} - self.verifySizSegment(c.segment[1], - glymur.codestream.SIZsegment(**kwargs)) + 'xytsiz': (513, 129), 'xytosiz': (0, 0), + 'bitdepth': (12, 12, 12, 12), + 'signed': (False, False, False, False), + 'xyrsiz': [(1, 2, 1, 2), (1, 1, 2, 2)]} + self.verifySizSegment(c.segment[1], glymur.codestream.SIZsegment(**kwargs)) # COD: Coding style default self.assertFalse(c.segment[2].scod & 2) @@ -464,7 +476,7 @@ class TestSuite(MetadataBase): self.assertEqual(tuple(c.segment[2].code_block_size), (64, 64)) # cblk 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], glymur.core.WAVELET_XFORM_9X7_IRREVERSIBLE) self.assertEqual(len(c.segment[2].spcod), 9) @@ -523,7 +535,7 @@ class TestSuite(MetadataBase): self.assertEqual(tuple(c.segment[7].code_block_size), (64, 64)) # cblk self.verify_codeblock_style(c.segment[7].spcoc[3], - [False, False, False, False, False, False]) + [False, False, False, False, False, False]) self.assertEqual(c.segment[7].spcoc[4], glymur.core.WAVELET_XFORM_5X3_REVERSIBLE) @@ -540,12 +552,10 @@ class TestSuite(MetadataBase): c = Jp2k(jfile).get_codestream(header_only=False) kwargs = {'rsiz': 1, 'xysiz': (2048, 2048), 'xyosiz': (0, 0), - 'xytsiz': (128, 128), 'xytosiz': (0, 0), - 'bitdepth': (12, 12, 12), - 'signed': (True, True, True), - 'xyrsiz': [(1, 1, 1), (1, 1, 1)]} - self.verifySizSegment(c.segment[1], - glymur.codestream.SIZsegment(**kwargs)) + 'xytsiz': (128, 128), 'xytosiz': (0, 0), 'bitdepth': (12, 12, 12), + 'signed': (True, True, True), + 'xyrsiz': [(1, 1, 1), (1, 1, 1)]} + self.verifySizSegment(c.segment[1], glymur.codestream.SIZsegment(**kwargs)) # COD: Coding style default self.assertTrue(c.segment[2].scod & 2) @@ -557,7 +567,7 @@ class TestSuite(MetadataBase): self.assertEqual(tuple(c.segment[2].code_block_size), (64, 64)) # cblk 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], glymur.core.WAVELET_XFORM_5X3_REVERSIBLE) self.assertEqual(len(c.segment[2].spcod), 9) @@ -585,6 +595,7 @@ class TestSuite(MetadataBase): # PLT: packet length, tile part self.assertEqual(c.segment[7].zplt, 0) + #self.assertEqual(c.segment[7].iplt), 99) # SOD: start of data self.assertEqual(c.segment[8].marker_id, 'SOD') @@ -594,12 +605,10 @@ class TestSuite(MetadataBase): c = Jp2k(jfile).get_codestream(header_only=False) kwargs = {'rsiz': 1, 'xysiz': (513, 3072), 'xyosiz': (0, 0), - 'xytsiz': (513, 3072), 'xytosiz': (0, 0), - 'bitdepth': (12, 12, 12), - 'signed': (True, True, True), - 'xyrsiz': [(1, 1, 1), (1, 1, 1)]} - self.verifySizSegment(c.segment[1], - glymur.codestream.SIZsegment(**kwargs)) + 'xytsiz': (513, 3072), 'xytosiz': (0, 0), 'bitdepth': (12, 12, 12), + 'signed': (True, True, True), + 'xyrsiz': [(1, 1, 1), (1, 1, 1)]} + self.verifySizSegment(c.segment[1], glymur.codestream.SIZsegment(**kwargs)) # COD: Coding style default self.assertTrue(c.segment[2].scod & 2) @@ -611,7 +620,7 @@ class TestSuite(MetadataBase): self.assertEqual(tuple(c.segment[2].code_block_size), (64, 64)) # cblk 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], glymur.core.WAVELET_XFORM_5X3_REVERSIBLE) self.assertEqual(len(c.segment[2].spcod), 9) @@ -622,7 +631,7 @@ class TestSuite(MetadataBase): self.assertEqual(tuple(c.segment[3].code_block_size), (64, 64)) # cblk self.verify_codeblock_style(c.segment[3].spcoc[3], - [False, False, False, False, False, False]) + [False, False, False, False, False, False]) self.assertEqual(c.segment[3].spcoc[4], glymur.core.WAVELET_XFORM_5X3_REVERSIBLE) @@ -632,7 +641,7 @@ class TestSuite(MetadataBase): self.assertEqual(tuple(c.segment[4].code_block_size), (32, 32)) # cblk self.verify_codeblock_style(c.segment[4].spcoc[3], - [False, False, False, False, False, False]) + [False, False, False, False, False, False]) self.assertEqual(c.segment[4].spcoc[4], glymur.core.WAVELET_XFORM_5X3_REVERSIBLE) @@ -642,7 +651,7 @@ class TestSuite(MetadataBase): self.assertEqual(tuple(c.segment[5].code_block_size), (64, 64)) # cblk self.verify_codeblock_style(c.segment[5].spcoc[3], - [False, False, False, False, False, False]) + [False, False, False, False, False, False]) self.assertEqual(c.segment[5].spcoc[4], glymur.core.WAVELET_XFORM_5X3_REVERSIBLE) @@ -687,10 +696,9 @@ class TestSuite(MetadataBase): c = Jp2k(jfile).get_codestream(header_only=False) kwargs = {'rsiz': 0, 'xysiz': (17, 37), 'xyosiz': (0, 0), - 'xytsiz': (17, 37), 'xytosiz': (0, 0), 'bitdepth': (8,), - 'signed': (False,), 'xyrsiz': [(1,), (1,)]} - self.verifySizSegment(c.segment[1], - glymur.codestream.SIZsegment(**kwargs)) + 'xytsiz': (17, 37), 'xytosiz': (0, 0), 'bitdepth': (8,), + 'signed': (False,), 'xyrsiz': [(1,), (1,)]} + self.verifySizSegment(c.segment[1], glymur.codestream.SIZsegment(**kwargs)) # COD: Coding style default self.assertFalse(c.segment[2].scod & 2) @@ -702,7 +710,7 @@ class TestSuite(MetadataBase): self.assertEqual(tuple(c.segment[2].code_block_size), (64, 64)) # cblk 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], glymur.core.WAVELET_XFORM_9X7_IRREVERSIBLE) self.assertEqual(len(c.segment[2].spcod), 9) @@ -735,12 +743,10 @@ class TestSuite(MetadataBase): c = Jp2k(jfile).get_codestream(header_only=False) kwargs = {'rsiz': 1, 'xysiz': (256, 256), 'xyosiz': (0, 0), - 'xytsiz': (128, 128), 'xytosiz': (0, 0), - 'bitdepth': (8, 8, 8), - 'signed': (False, False, False), - 'xyrsiz': [(4, 4, 4), (4, 4, 4)]} - self.verifySizSegment(c.segment[1], - glymur.codestream.SIZsegment(**kwargs)) + 'xytsiz': (128, 128), 'xytosiz': (0, 0), 'bitdepth': (8, 8, 8), + 'signed': (False, False, False), + 'xyrsiz': [(4, 4, 4), (4, 4, 4)]} + self.verifySizSegment(c.segment[1], glymur.codestream.SIZsegment(**kwargs)) # COD: Coding style default self.assertFalse(c.segment[2].scod & 2) @@ -752,7 +758,7 @@ class TestSuite(MetadataBase): self.assertEqual(tuple(c.segment[2].code_block_size), (64, 64)) # cblk 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], glymur.core.WAVELET_XFORM_5X3_REVERSIBLE) self.assertEqual(len(c.segment[2].spcod), 9) @@ -799,10 +805,9 @@ class TestSuite(MetadataBase): c = Jp2k(jfile).get_codestream(header_only=False) kwargs = {'rsiz': 1, 'xysiz': (128, 1), 'xyosiz': (0, 0), - 'xytsiz': (128, 128), 'xytosiz': (0, 0), 'bitdepth': (8,), - 'signed': (False,), 'xyrsiz': [(1,), (1,)]} - self.verifySizSegment(c.segment[1], - glymur.codestream.SIZsegment(**kwargs)) + 'xytsiz': (128, 128), 'xytosiz': (0, 0), 'bitdepth': (8,), + 'signed': (False,), 'xyrsiz': [(1,), (1,)]} + self.verifySizSegment(c.segment[1], glymur.codestream.SIZsegment(**kwargs)) # COD: Coding style default self.assertFalse(c.segment[2].scod & 2) @@ -814,7 +819,7 @@ class TestSuite(MetadataBase): self.assertEqual(tuple(c.segment[2].code_block_size), (64, 64)) # cblk self.verify_codeblock_style(c.segment[2].spcod[7], - [False, False, False, False, False, True]) + [False, False, False, False, False, True]) self.assertEqual(c.segment[2].spcod[8], glymur.core.WAVELET_XFORM_5X3_REVERSIBLE) self.assertEqual(c.segment[2].precinct_size, [(128, 2)]) @@ -827,7 +832,7 @@ class TestSuite(MetadataBase): self.assertEqual(c.segment[3].exponent, [8]) pargs = (RCME_ISO_8859_1, - "Creator: AV-J2K (c) 2000,2001 Algo Vision".encode()) + "Creator: AV-J2K (c) 2000,2001 Algo Vision".encode()) self.verifyCMEsegment(c.segment[4], CMEsegment(*pargs)) self.verifySOTsegment(c.segment[5], SOTsegment(0, 118, 0, 1)) @@ -849,11 +854,10 @@ class TestSuite(MetadataBase): c = Jp2k(jfile).get_codestream(header_only=False) kwargs = {'rsiz': 1, 'xysiz': (3, 5), 'xyosiz': (0, 0), - 'xytsiz': (3, 5), 'xytosiz': (0, 0), 'bitdepth': (8,), - 'signed': (False,), - 'xyrsiz': [(1,), (1,)]} - self.verifySizSegment(c.segment[1], - glymur.codestream.SIZsegment(**kwargs)) + 'xytsiz': (3, 5), 'xytosiz': (0, 0), 'bitdepth': (8,), + 'signed': (False,), + 'xyrsiz': [(1,), (1,)]} + self.verifySizSegment(c.segment[1], glymur.codestream.SIZsegment(**kwargs)) # COD: Coding style default self.assertTrue(c.segment[2].scod & 2) @@ -865,7 +869,7 @@ class TestSuite(MetadataBase): self.assertEqual(tuple(c.segment[2].code_block_size), (32, 32)) # cblk self.verify_codeblock_style(c.segment[2].spcod[7], - [False, False, True, False, False, False]) + [False, False, True, False, False, False]) self.assertEqual(c.segment[2].spcod[8], glymur.core.WAVELET_XFORM_5X3_REVERSIBLE) self.assertEqual(len(c.segment[2].spcod), 9) @@ -878,8 +882,7 @@ class TestSuite(MetadataBase): self.assertEqual(c.segment[3].exponent, [8, 9, 9, 10, 9, 9, 10, 9, 9, 10]) - pargs = (RCME_ISO_8859_1, - "Creator: AV-J2K (c) 2000,2001 Algo Vision".encode()) + pargs = (RCME_ISO_8859_1, "Creator: AV-J2K (c) 2000,2001 Algo Vision".encode()) self.verifyCMEsegment(c.segment[4], CMEsegment(*pargs)) self.verifySOTsegment(c.segment[5], SOTsegment(0, 162, 0, 1)) @@ -901,12 +904,10 @@ class TestSuite(MetadataBase): c = Jp2k(jfile).get_codestream(header_only=False) kwargs = {'rsiz': 1, 'xysiz': (1, 1), 'xyosiz': (0, 0), - 'xytsiz': (1, 1), 'xytosiz': (0, 0), - 'bitdepth': tuple([8] * 257), - 'signed': tuple([False] * 257), - 'xyrsiz': [tuple([1] * 257), tuple([1] * 257)]} - self.verifySizSegment(c.segment[1], - glymur.codestream.SIZsegment(**kwargs)) + 'xytsiz': (1, 1), 'xytosiz': (0, 0), 'bitdepth': tuple([8] * 257), + 'signed': tuple([False] * 257), + 'xyrsiz': [tuple([1] * 257), tuple([1] * 257)]} + self.verifySizSegment(c.segment[1], glymur.codestream.SIZsegment(**kwargs)) # COD: Coding style default self.assertFalse(c.segment[2].scod & 2) # no sop @@ -917,7 +918,7 @@ class TestSuite(MetadataBase): self.assertEqual(c.segment[2].spcod[4], 1) # levels self.assertEqual(tuple(c.segment[2].code_block_size), (32, 32)) self.verify_codeblock_style(c.segment[2].spcod[7], - [False, False, False, False, True, False]) + [False, False, False, False, True, False]) self.assertEqual(c.segment[2].spcod[8], glymur.core.WAVELET_XFORM_5X3_REVERSIBLE) self.assertEqual(len(c.segment[2].spcod), 9) @@ -927,7 +928,7 @@ class TestSuite(MetadataBase): self.assertEqual(c.segment[3].spcoc[0], 1) # levels self.assertEqual(tuple(c.segment[3].code_block_size), (64, 64)) self.verify_codeblock_style(c.segment[3].spcoc[3], - [False, False, False, False, False, False]) + [False, False, False, False, False, False]) self.assertEqual(c.segment[3].spcoc[4], glymur.core.WAVELET_XFORM_5X3_REVERSIBLE) @@ -968,8 +969,7 @@ class TestSuite(MetadataBase): self.assertEqual(c.segment[8].ppod, (glymur.core.RLCP, glymur.core.CPRL)) - pargs = (RCME_ISO_8859_1, - "Creator: AV-J2K (c) 2000,2001 Algo Vision".encode()) + pargs = (RCME_ISO_8859_1, "Creator: AV-J2K (c) 2000,2001 Algo Vision".encode()) self.verifyCMEsegment(c.segment[9], CMEsegment(*pargs)) self.verifySOTsegment(c.segment[10], SOTsegment(0, 1537, 0, 1)) @@ -985,11 +985,10 @@ class TestSuite(MetadataBase): c = Jp2k(jfile).get_codestream(header_only=False) kwargs = {'rsiz': 0, 'xysiz': (49, 49), 'xyosiz': (0, 0), - 'xytsiz': (49, 49), 'xytosiz': (0, 0), 'bitdepth': (8, 8, 8), - 'signed': (False, False, False), - 'xyrsiz': [(1, 1, 1), (1, 1, 1)]} - self.verifySizSegment(c.segment[1], - glymur.codestream.SIZsegment(**kwargs)) + 'xytsiz': (49, 49), 'xytosiz': (0, 0), 'bitdepth': (8, 8, 8), + 'signed': (False, False, False), + 'xyrsiz': [(1, 1, 1), (1, 1, 1)]} + self.verifySizSegment(c.segment[1], glymur.codestream.SIZsegment(**kwargs)) # COD: Coding style default self.assertFalse(c.segment[2].scod & 2) @@ -1000,7 +999,7 @@ class TestSuite(MetadataBase): self.assertEqual(c.segment[2].spcod[4], 5) # levels self.assertEqual(tuple(c.segment[2].code_block_size), (64, 64)) 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], glymur.core.WAVELET_XFORM_5X3_REVERSIBLE) self.assertEqual(len(c.segment[2].spcod), 9) @@ -1026,11 +1025,10 @@ class TestSuite(MetadataBase): c = Jp2k(jfile).get_codestream(header_only=False) kwargs = {'rsiz': 1, 'xysiz': (256, 256), 'xyosiz': (0, 0), - 'xytsiz': (128, 128), 'xytosiz': (0, 0), 'bitdepth': (4,), - 'signed': (True,), - 'xyrsiz': [(1,), (1,)]} - self.verifySizSegment(c.segment[1], - glymur.codestream.SIZsegment(**kwargs)) + 'xytsiz': (128, 128), 'xytosiz': (0, 0), 'bitdepth': (4,), + 'signed': (True,), + 'xyrsiz': [(1,), (1,)]} + self.verifySizSegment(c.segment[1], glymur.codestream.SIZsegment(**kwargs)) # COD: Coding style default self.assertTrue(c.segment[2].scod & 2) @@ -1041,7 +1039,7 @@ class TestSuite(MetadataBase): self.assertEqual(c.segment[2].spcod[4], 1) # levels self.assertEqual(tuple(c.segment[2].code_block_size), (64, 64)) 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], glymur.core.WAVELET_XFORM_5X3_REVERSIBLE) self.assertEqual(len(c.segment[2].spcod), 9) @@ -1074,11 +1072,11 @@ class TestSuite(MetadataBase): self.assertEqual(c.segment[6].xcrg, (65424,)) self.assertEqual(c.segment[6].ycrg, (32558,)) - pargs = (RCME_ISO_8859_1, - "Creator: AV-J2K (c) 2000,2001 Algo Vision".encode()) + pargs = (RCME_ISO_8859_1, "Creator: AV-J2K (c) 2000,2001 Algo Vision".encode()) self.verifyCMEsegment(c.segment[7], CMEsegment(*pargs)) - pargs = (RCME_ISO_8859_1, comment1.encode()) + pargs = (RCME_ISO_8859_1, + "Creator: AV-J2K (c) 2000,2001 Algo Vision Technology".encode()) self.verifyCMEsegment(c.segment[8], CMEsegment(*pargs)) pargs = (RCME_BINARY, c.segment[9].ccme) @@ -1127,11 +1125,10 @@ class TestSuite(MetadataBase): c = Jp2k(jfile).get_codestream(header_only=False) kwargs = {'rsiz': 0, 'xysiz': (128, 128), 'xyosiz': (0, 0), - 'xytsiz': (128, 128), 'xytosiz': (0, 0), 'bitdepth': (8,), - 'signed': (False,), - 'xyrsiz': [(1,), (1,)]} - self.verifySizSegment(c.segment[1], - glymur.codestream.SIZsegment(**kwargs)) + 'xytsiz': (128, 128), 'xytosiz': (0, 0), 'bitdepth': (8,), + 'signed': (False,), + 'xyrsiz': [(1,), (1,)]} + self.verifySizSegment(c.segment[1], glymur.codestream.SIZsegment(**kwargs)) # COD: Coding style default self.assertFalse(c.segment[2].scod & 2) @@ -1142,7 +1139,7 @@ class TestSuite(MetadataBase): self.assertEqual(c.segment[2].spcod[4], 3) # levels self.assertEqual(tuple(c.segment[2].code_block_size), (64, 64)) 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], glymur.core.WAVELET_XFORM_5X3_REVERSIBLE) self.assertEqual(len(c.segment[2].spcod), 9) @@ -1168,11 +1165,10 @@ class TestSuite(MetadataBase): c = Jp2k(jfile).get_codestream(header_only=False) kwargs = {'rsiz': 2, 'xysiz': (127, 227), 'xyosiz': (5, 128), - 'xytsiz': (127, 126), 'xytosiz': (1, 101), 'bitdepth': (8,), - 'signed': (False,), - 'xyrsiz': [(2,), (1,)]} - self.verifySizSegment(c.segment[1], - glymur.codestream.SIZsegment(**kwargs)) + 'xytsiz': (127, 126), 'xytosiz': (1, 101), 'bitdepth': (8,), + 'signed': (False,), + 'xyrsiz': [(2,), (1,)]} + self.verifySizSegment(c.segment[1], glymur.codestream.SIZsegment(**kwargs)) # COD: Coding style default self.assertTrue(c.segment[2].scod & 2) # SOP @@ -1183,7 +1179,7 @@ class TestSuite(MetadataBase): self.assertEqual(c.segment[2].spcod[4], 3) # level self.assertEqual(tuple(c.segment[2].code_block_size), (64, 64)) self.verify_codeblock_style(c.segment[2].spcod[7], - [False, False, True, False, True, True]) + [False, False, True, False, True, True]) self.assertEqual(c.segment[2].spcod[8], glymur.core.WAVELET_XFORM_9X7_IRREVERSIBLE) self.assertEqual(len(c.segment[2].spcod), 9) @@ -1193,7 +1189,7 @@ class TestSuite(MetadataBase): self.assertEqual(c.segment[3].spcoc[0], 3) # level self.assertEqual(tuple(c.segment[3].code_block_size), (32, 32)) self.verify_codeblock_style(c.segment[3].spcoc[3], - [False, False, True, False, True, True]) + [False, False, True, False, True, True]) self.assertEqual(c.segment[3].spcoc[4], glymur.core.WAVELET_XFORM_5X3_REVERSIBLE) @@ -1205,8 +1201,7 @@ class TestSuite(MetadataBase): self.assertEqual(c.segment[4].exponent, [8, 9, 9, 10, 9, 9, 10, 9, 9, 10]) - pargs = (RCME_ISO_8859_1, - "Creator: AV-J2K (c) 2000,2001 Algo Vision".encode()) + pargs = (RCME_ISO_8859_1, "Creator: AV-J2K (c) 2000,2001 Algo Vision".encode()) self.verifyCMEsegment(c.segment[5], CMEsegment(*pargs)) self.verifySOTsegment(c.segment[6], SOTsegment(0, 4627, 0, 1)) @@ -1228,12 +1223,10 @@ class TestSuite(MetadataBase): c = Jp2k(jfile).get_codestream(header_only=False) kwargs = {'rsiz': 2, 'xysiz': (640, 480), 'xyosiz': (0, 0), - 'xytsiz': (640, 480), 'xytosiz': (0, 0), - 'bitdepth': (8, 8, 8), - 'signed': (False, False, False), - 'xyrsiz': [(1, 1, 1), (1, 1, 1)]} - self.verifySizSegment(c.segment[1], - glymur.codestream.SIZsegment(**kwargs)) + 'xytsiz': (640, 480), 'xytosiz': (0, 0), 'bitdepth': (8, 8, 8), + 'signed': (False, False, False), + 'xyrsiz': [(1, 1, 1), (1, 1, 1)]} + self.verifySizSegment(c.segment[1], glymur.codestream.SIZsegment(**kwargs)) # COD: Coding style default self.assertFalse(c.segment[2].scod & 2) # no sop @@ -1245,7 +1238,7 @@ class TestSuite(MetadataBase): self.assertEqual(tuple(c.segment[2].code_block_size), (64, 64)) # cblk self.verify_codeblock_style(c.segment[2].spcod[7], - [False, True, False, True, False, False]) + [False, True, False, True, False, False]) self.assertEqual(c.segment[2].spcod[8], glymur.core.WAVELET_XFORM_9X7_IRREVERSIBLE) self.assertEqual(c.segment[2].precinct_size, @@ -1292,8 +1285,7 @@ class TestSuite(MetadataBase): [14, 14, 14, 14, 13, 13, 13, 12, 12, 12, 11, 11, 11, 9, 9, 9, 9, 9, 9]) - pargs = (RCME_ISO_8859_1, - "Creator: AV-J2K (c) 2000,2001 Algo Vision".encode()) + pargs = (RCME_ISO_8859_1, "Creator: AV-J2K (c) 2000,2001 Algo Vision".encode()) self.verifyCMEsegment(c.segment[6], CMEsegment(*pargs)) self.verifySOTsegment(c.segment[7], SOTsegment(0, 262838, 0, 1)) @@ -1313,12 +1305,11 @@ class TestSuite(MetadataBase): c = Jp2k(jfile).get_codestream(header_only=False) kwargs = {'rsiz': 2, 'xysiz': (1024, 1024), 'xyosiz': (0, 0), - 'xytsiz': (1024, 1024), 'xytosiz': (0, 0), - 'bitdepth': (8, 8, 8, 8), - 'signed': (False, False, False, False), - 'xyrsiz': [(1, 1, 2, 2), (1, 1, 2, 2)]} - self.verifySizSegment(c.segment[1], - glymur.codestream.SIZsegment(**kwargs)) + 'xytsiz': (1024, 1024), 'xytosiz': (0, 0), + 'bitdepth': (8, 8, 8, 8), + 'signed': (False, False, False, False), + 'xyrsiz': [(1, 1, 2, 2), (1, 1, 2, 2)]} + self.verifySizSegment(c.segment[1], glymur.codestream.SIZsegment(**kwargs)) # COD: Coding style default self.assertFalse(c.segment[2].scod & 2) # no sop @@ -1329,7 +1320,7 @@ class TestSuite(MetadataBase): self.assertEqual(c.segment[2].spcod[4], 6) # level self.assertEqual(tuple(c.segment[2].code_block_size), (32, 32)) self.verify_codeblock_style(c.segment[2].spcod[7], - [True, False, True, False, False, False]) + [True, False, True, False, False, False]) self.assertEqual(c.segment[2].spcod[8], glymur.core.WAVELET_XFORM_9X7_IRREVERSIBLE) self.assertEqual(len(c.segment[2].spcod), 9) @@ -1339,7 +1330,7 @@ class TestSuite(MetadataBase): self.assertEqual(c.segment[3].spcoc[0], 3) # level self.assertEqual(tuple(c.segment[3].code_block_size), (32, 32)) self.verify_codeblock_style(c.segment[3].spcoc[3], - [True, False, True, False, False, False]) + [True, False, True, False, False, False]) self.assertEqual(c.segment[3].spcoc[4], glymur.core.WAVELET_XFORM_9X7_IRREVERSIBLE) @@ -1348,7 +1339,7 @@ class TestSuite(MetadataBase): self.assertEqual(c.segment[4].spcoc[0], 6) # level self.assertEqual(tuple(c.segment[4].code_block_size), (32, 32)) self.verify_codeblock_style(c.segment[4].spcoc[3], - [True, False, True, False, False, False]) + [True, False, True, False, False, False]) self.assertEqual(c.segment[4].spcoc[4], glymur.core.WAVELET_XFORM_5X3_REVERSIBLE) @@ -1384,8 +1375,7 @@ class TestSuite(MetadataBase): [8, 9, 9, 10, 9, 9, 10, 9, 9, 10, 9, 9, 10, 9, 9, 10, 9, 9, 10]) - pargs = (RCME_ISO_8859_1, - "Creator: AV-J2K (c) 2000,2001 Algo Vision".encode()) + pargs = (RCME_ISO_8859_1, "Creator: AV-J2K (c) 2000,2001 Algo Vision".encode()) self.verifyCMEsegment(c.segment[8], CMEsegment(*pargs)) # PPM: packed packet headers, main header @@ -1410,11 +1400,10 @@ class TestSuite(MetadataBase): c = Jp2k(jfile).get_codestream(header_only=False) kwargs = {'rsiz': 2, 'xysiz': (1024, 1024), 'xyosiz': (0, 0), - 'xytsiz': (128, 128), 'xytosiz': (0, 0), 'bitdepth': (12,), - 'signed': (False,), - 'xyrsiz': [(1,), (1,)]} - self.verifySizSegment(c.segment[1], - glymur.codestream.SIZsegment(**kwargs)) + 'xytsiz': (128, 128), 'xytosiz': (0, 0), 'bitdepth': (12,), + 'signed': (False,), + 'xyrsiz': [(1,), (1,)]} + self.verifySizSegment(c.segment[1], glymur.codestream.SIZsegment(**kwargs)) # COD: Coding style default self.assertFalse(c.segment[2].scod & 2) # no sop @@ -1425,7 +1414,7 @@ class TestSuite(MetadataBase): self.assertEqual(c.segment[2].spcod[4], 3) # level self.assertEqual(tuple(c.segment[2].code_block_size), (64, 64)) 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], glymur.core.WAVELET_XFORM_9X7_IRREVERSIBLE) self.assertEqual(len(c.segment[2].spcod), 9) @@ -1498,12 +1487,10 @@ class TestSuite(MetadataBase): c = Jp2k(jfile).get_codestream(header_only=False) kwargs = {'rsiz': 2, 'xysiz': (529, 524), 'xyosiz': (17, 12), - 'xytsiz': (37, 37), 'xytosiz': (8, 2), - 'bitdepth': (8, 8, 8), - 'signed': (False, False, False), - 'xyrsiz': [(1, 1, 1), (1, 1, 1)]} - self.verifySizSegment(c.segment[1], - glymur.codestream.SIZsegment(**kwargs)) + 'xytsiz': (37, 37), 'xytosiz': (8, 2), 'bitdepth': (8, 8, 8), + 'signed': (False, False, False), + 'xyrsiz': [(1, 1, 1), (1, 1, 1)]} + self.verifySizSegment(c.segment[1], glymur.codestream.SIZsegment(**kwargs)) # COD: Coding style default self.assertTrue(c.segment[2].scod & 2) # sop @@ -1514,7 +1501,7 @@ class TestSuite(MetadataBase): self.assertEqual(c.segment[2].spcod[4], 7) # level self.assertEqual(tuple(c.segment[2].code_block_size), (64, 8)) # cblk self.verify_codeblock_style(c.segment[2].spcod[7], - [True, False, False, True, True, False]) + [True, False, False, True, True, False]) self.assertEqual(c.segment[2].spcod[8], glymur.core.WAVELET_XFORM_9X7_IRREVERSIBLE) self.assertEqual(c.segment[2].precinct_size, [(16, 16)] * 8) @@ -1529,8 +1516,7 @@ class TestSuite(MetadataBase): [17, 17, 17, 17, 16, 16, 16, 15, 15, 15, 14, 14, 14, 13, 13, 13, 11, 11, 11, 11, 11, 11]) - pargs = (RCME_ISO_8859_1, - "Creator: AV-J2K (c) 2000,2001 Algo Vision".encode()) + pargs = (RCME_ISO_8859_1, "Creator: AV-J2K (c) 2000,2001 Algo Vision".encode()) self.verifyCMEsegment(c.segment[4], CMEsegment(*pargs)) # 225 consecutive PPM segments. @@ -1557,11 +1543,10 @@ class TestSuite(MetadataBase): c = Jp2k(jfile).get_codestream(header_only=False) kwargs = {'rsiz': 2, 'xysiz': (12, 12), 'xyosiz': (0, 0), - 'xytsiz': (3, 3), 'xytosiz': (0, 0), 'bitdepth': (8, 8, 8), - 'signed': (False, False, False), - 'xyrsiz': [(1, 1, 1), (1, 1, 1)]} - self.verifySizSegment(c.segment[1], - glymur.codestream.SIZsegment(**kwargs)) + 'xytsiz': (3, 3), 'xytosiz': (0, 0), 'bitdepth': (8, 8, 8), + 'signed': (False, False, False), + 'xyrsiz': [(1, 1, 1), (1, 1, 1)]} + self.verifySizSegment(c.segment[1], glymur.codestream.SIZsegment(**kwargs)) # COD: Coding style default self.assertTrue(c.segment[2].scod & 2) # sop @@ -1572,7 +1557,7 @@ class TestSuite(MetadataBase): self.assertEqual(c.segment[2].spcod[4], 4) # level self.assertEqual(tuple(c.segment[2].code_block_size), (32, 64)) self.verify_codeblock_style(c.segment[2].spcod[7], - [False, False, False, True, False, True]) + [False, False, False, True, False, True]) self.assertEqual(c.segment[2].spcod[8], glymur.core.WAVELET_XFORM_9X7_IRREVERSIBLE) self.assertEqual(len(c.segment[2].spcod), 9) @@ -1588,8 +1573,7 @@ class TestSuite(MetadataBase): [14, 14, 14, 14, 13, 13, 13, 11, 11, 11, 11, 11, 11]) - pargs = (RCME_ISO_8859_1, - "Creator: AV-J2K (c) 2000,2001 Algo Vision".encode()) + pargs = (RCME_ISO_8859_1, "Creator: AV-J2K (c) 2000,2001 Algo Vision".encode()) self.verifyCMEsegment(c.segment[4], CMEsegment(*pargs)) self.verifySOTsegment(c.segment[5], SOTsegment(0, 349, 0, 1)) @@ -1620,11 +1604,10 @@ class TestSuite(MetadataBase): c = Jp2k(jfile).get_codestream(header_only=False) kwargs = {'rsiz': 2, 'xysiz': (12, 12), 'xyosiz': (4, 0), - 'xytsiz': (12, 12), 'xytosiz': (4, 0), 'bitdepth': (8, 8), - 'signed': (False, False), - 'xyrsiz': [(4, 1), (1, 1)]} - self.verifySizSegment(c.segment[1], - glymur.codestream.SIZsegment(**kwargs)) + 'xytsiz': (12, 12), 'xytosiz': (4, 0), 'bitdepth': (8, 8), + 'signed': (False, False), + 'xyrsiz': [(4, 1), (1, 1)]} + self.verifySizSegment(c.segment[1], glymur.codestream.SIZsegment(**kwargs)) # COD: Coding style default self.assertTrue(c.segment[2].scod & 2) # sop @@ -1635,7 +1618,7 @@ class TestSuite(MetadataBase): self.assertEqual(c.segment[2].spcod[4], 1) # level self.assertEqual(tuple(c.segment[2].code_block_size), (64, 64)) 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], glymur.core.WAVELET_XFORM_5X3_REVERSIBLE) self.assertEqual(c.segment[2].precinct_size, [(1, 1), (2, 2)]) @@ -1645,7 +1628,7 @@ class TestSuite(MetadataBase): self.assertEqual(c.segment[3].spcoc[0], 1) # level self.assertEqual(tuple(c.segment[3].code_block_size), (64, 64)) self.verify_codeblock_style(c.segment[3].spcoc[3], - [False, False, False, False, False, False]) + [False, False, False, False, False, False]) self.assertEqual(c.segment[3].spcoc[4], glymur.core.WAVELET_XFORM_5X3_REVERSIBLE) self.assertEqual(c.segment[3].precinct_size, [(2, 2), (4, 4)]) @@ -1657,8 +1640,7 @@ class TestSuite(MetadataBase): self.assertEqual(c.segment[4].mantissa, [0] * 4) self.assertEqual(c.segment[4].exponent, [8, 9, 9, 10]) - pargs = (RCME_ISO_8859_1, - "Creator: AV-J2K (c) 2000,2001 Algo Vision".encode()) + pargs = (RCME_ISO_8859_1, "Creator: AV-J2K (c) 2000,2001 Algo Vision".encode()) self.verifyCMEsegment(c.segment[5], CMEsegment(*pargs)) self.verifySOTsegment(c.segment[6], SOTsegment(0, 434, 0, 1)) @@ -1675,12 +1657,11 @@ class TestSuite(MetadataBase): c = jp2k.get_codestream(header_only=False) kwargs = {'rsiz': 3, 'xysiz': (1920, 1080), 'xyosiz': (0, 0), - 'xytsiz': (1920, 1080), 'xytosiz': (0, 0), - 'bitdepth': (12, 12, 12), - 'signed': (False, False, False), - 'xyrsiz': [(1, 1, 1), (1, 1, 1)]} - self.verifySizSegment(c.segment[1], - glymur.codestream.SIZsegment(**kwargs)) + 'xytsiz': (1920, 1080), 'xytosiz': (0, 0), + 'bitdepth': (12, 12, 12), + 'signed': (False, False, False), + 'xyrsiz': [(1, 1, 1), (1, 1, 1)]} + self.verifySizSegment(c.segment[1], glymur.codestream.SIZsegment(**kwargs)) # COD: Coding style default self.assertFalse(c.segment[2].scod & 2) # no sop @@ -1691,7 +1672,7 @@ class TestSuite(MetadataBase): self.assertEqual(c.segment[2].spcod[4], 5) # level self.assertEqual(tuple(c.segment[2].code_block_size), (32, 32)) 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], glymur.core.WAVELET_XFORM_9X7_IRREVERSIBLE) self.assertEqual(c.segment[2].precinct_size[0], (128, 128)) @@ -1713,7 +1694,7 @@ class TestSuite(MetadataBase): self.assertEqual(c.segment[4].spcoc[0], 5) # level self.assertEqual(tuple(c.segment[4].code_block_size), (32, 32)) self.verify_codeblock_style(c.segment[4].spcoc[3], - [False, False, False, False, False, False]) + [False, False, False, False, False, False]) self.assertEqual(c.segment[4].spcoc[4], glymur.core.WAVELET_XFORM_9X7_IRREVERSIBLE) @@ -1735,7 +1716,7 @@ class TestSuite(MetadataBase): self.assertEqual(c.segment[6].spcoc[0], 5) # level self.assertEqual(tuple(c.segment[6].code_block_size), (32, 32)) self.verify_codeblock_style(c.segment[6].spcoc[3], - [False, False, False, False, False, False]) + [False, False, False, False, False, False]) self.assertEqual(c.segment[6].spcoc[4], glymur.core.WAVELET_XFORM_9X7_IRREVERSIBLE) @@ -1780,12 +1761,10 @@ class TestSuite(MetadataBase): c = jp2k.get_codestream(header_only=False) kwargs = {'rsiz': 0, 'xysiz': (2592, 1944), 'xyosiz': (0, 0), - 'xytsiz': (640, 480), 'xytosiz': (0, 0), - 'bitdepth': (8, 8, 8), - 'signed': (False, False, False), - 'xyrsiz': [(1, 1, 1), (1, 1, 1)]} - self.verifySizSegment(c.segment[1], - glymur.codestream.SIZsegment(**kwargs)) + 'xytsiz': (640, 480), 'xytosiz': (0, 0), 'bitdepth': (8, 8, 8), + 'signed': (False, False, False), + 'xyrsiz': [(1, 1, 1), (1, 1, 1)]} + self.verifySizSegment(c.segment[1], glymur.codestream.SIZsegment(**kwargs)) # COD: Coding style default self.assertFalse(c.segment[2].scod & 2) # no sop @@ -1796,7 +1775,7 @@ class TestSuite(MetadataBase): self.assertEqual(c.segment[2].spcod[4], 5) # level self.assertEqual(tuple(c.segment[2].code_block_size), (32, 32)) 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], glymur.core.WAVELET_XFORM_5X3_REVERSIBLE) self.assertEqual(c.segment[2].precinct_size, @@ -1815,11 +1794,10 @@ class TestSuite(MetadataBase): c = jp2k.get_codestream(header_only=False) kwargs = {'rsiz': 0, 'xysiz': (512, 512), 'xyosiz': (0, 0), - 'xytsiz': (512, 512), 'xytosiz': (0, 0), 'bitdepth': (16,), - 'signed': (False,), - 'xyrsiz': [(1,), (1,)]} - self.verifySizSegment(c.segment[1], - glymur.codestream.SIZsegment(**kwargs)) + 'xytsiz': (512, 512), 'xytosiz': (0, 0), 'bitdepth': (16,), + 'signed': (False,), + 'xyrsiz': [(1,), (1,)]} + self.verifySizSegment(c.segment[1], glymur.codestream.SIZsegment(**kwargs)) # COD: Coding style default self.assertFalse(c.segment[2].scod & 2) # no sop @@ -1830,7 +1808,7 @@ class TestSuite(MetadataBase): self.assertEqual(c.segment[2].spcod[4], 5) # level self.assertEqual(tuple(c.segment[2].code_block_size), (64, 64)) 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], glymur.core.WAVELET_XFORM_9X7_IRREVERSIBLE) self.assertEqual(len(c.segment[2].spcod), 9) @@ -1845,11 +1823,10 @@ class TestSuite(MetadataBase): c = jp2k.get_codestream(header_only=False) kwargs = {'rsiz': 0, 'xysiz': (512, 512), 'xyosiz': (0, 0), - 'xytsiz': (512, 512), 'xytosiz': (0, 0), 'bitdepth': (16,), - 'signed': (False,), - 'xyrsiz': [(1,), (1,)]} - self.verifySizSegment(c.segment[1], - glymur.codestream.SIZsegment(**kwargs)) + 'xytsiz': (512, 512), 'xytosiz': (0, 0), 'bitdepth': (16,), + 'signed': (False,), + 'xyrsiz': [(1,), (1,)]} + self.verifySizSegment(c.segment[1], glymur.codestream.SIZsegment(**kwargs)) # COD: Coding style default self.assertFalse(c.segment[2].scod & 2) # no sop @@ -1860,7 +1837,7 @@ class TestSuite(MetadataBase): self.assertEqual(c.segment[2].spcod[4], 5) # level self.assertEqual(tuple(c.segment[2].code_block_size), (64, 64)) 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], glymur.core.WAVELET_XFORM_5X3_REVERSIBLE) self.assertEqual(len(c.segment[2].spcod), 9) @@ -1883,11 +1860,10 @@ class TestSuite(MetadataBase): self.assertEqual(ids, expected) kwargs = {'rsiz': 0, 'xysiz': (1420, 1416), 'xyosiz': (0, 0), - 'xytsiz': (1420, 1416), 'xytosiz': (0, 0), 'bitdepth': (16,), - 'signed': (False,), - 'xyrsiz': [(1,), (1,)]} - self.verifySizSegment(c.segment[1], - glymur.codestream.SIZsegment(**kwargs)) + 'xytsiz': (1420, 1416), 'xytosiz': (0, 0), 'bitdepth': (16,), + 'signed': (False,), + 'xyrsiz': [(1,), (1,)]} + self.verifySizSegment(c.segment[1], glymur.codestream.SIZsegment(**kwargs)) # COD: Coding style default self.assertFalse(c.segment[2].scod & 2) # no sop @@ -1898,7 +1874,7 @@ class TestSuite(MetadataBase): self.assertEqual(c.segment[2].spcod[4], 11) # level self.assertEqual(tuple(c.segment[2].code_block_size), (64, 64)) 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], glymur.core.WAVELET_XFORM_5X3_REVERSIBLE) self.assertEqual(len(c.segment[2].spcod), 9) @@ -1921,11 +1897,10 @@ class TestSuite(MetadataBase): self.assertEqual(ids, expected) kwargs = {'rsiz': 0, 'xysiz': (512, 614), 'xyosiz': (0, 0), - 'xytsiz': (512, 614), 'xytosiz': (0, 0), 'bitdepth': (12,), - 'signed': (False,), - 'xyrsiz': [(1,), (1,)]} - self.verifySizSegment(c.segment[1], - glymur.codestream.SIZsegment(**kwargs)) + 'xytsiz': (512, 614), 'xytosiz': (0, 0), 'bitdepth': (12,), + 'signed': (False,), + 'xyrsiz': [(1,), (1,)]} + self.verifySizSegment(c.segment[1], glymur.codestream.SIZsegment(**kwargs)) # COD: Coding style default self.assertFalse(c.segment[2].scod & 2) # no sop @@ -1936,7 +1911,7 @@ class TestSuite(MetadataBase): self.assertEqual(c.segment[2].spcod[4], 5) # level self.assertEqual(tuple(c.segment[2].code_block_size), (64, 64)) 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], glymur.core.WAVELET_XFORM_9X7_IRREVERSIBLE) self.assertEqual(len(c.segment[2].spcod), 9) @@ -1965,11 +1940,10 @@ class TestSuite(MetadataBase): self.assertEqual(ids, expected) kwargs = {'rsiz': 0, 'xysiz': (256, 256), 'xyosiz': (0, 0), - 'xytsiz': (256, 256), 'xytosiz': (0, 0), 'bitdepth': (8,), - 'signed': (False,), - 'xyrsiz': [(1,), (1,)]} - self.verifySizSegment(c.segment[1], - glymur.codestream.SIZsegment(**kwargs)) + 'xytsiz': (256, 256), 'xytosiz': (0, 0), 'bitdepth': (8,), + 'signed': (False,), + 'xyrsiz': [(1,), (1,)]} + self.verifySizSegment(c.segment[1], glymur.codestream.SIZsegment(**kwargs)) # COD: Coding style default self.assertFalse(c.segment[2].scod & 2) # no sop @@ -1980,7 +1954,7 @@ class TestSuite(MetadataBase): self.assertEqual(c.segment[2].spcod[4], 5) # level self.assertEqual(tuple(c.segment[2].code_block_size), (64, 64)) 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], glymur.core.WAVELET_XFORM_5X3_REVERSIBLE) self.assertEqual(len(c.segment[2].spcod), 9) @@ -2007,11 +1981,10 @@ class TestSuite(MetadataBase): self.assertEqual(ids, expected) kwargs = {'rsiz': 0, 'xysiz': (1420, 1416), 'xyosiz': (0, 0), - 'xytsiz': (1420, 1416), 'xytosiz': (0, 0), 'bitdepth': (16,), - 'signed': (False,), - 'xyrsiz': [(1,), (1,)]} - self.verifySizSegment(c.segment[1], - glymur.codestream.SIZsegment(**kwargs)) + 'xytsiz': (1420, 1416), 'xytosiz': (0, 0), 'bitdepth': (16,), + 'signed': (False,), + 'xyrsiz': [(1,), (1,)]} + self.verifySizSegment(c.segment[1], glymur.codestream.SIZsegment(**kwargs)) # COD: Coding style default self.assertFalse(c.segment[2].scod & 2) # no sop @@ -2022,7 +1995,7 @@ class TestSuite(MetadataBase): self.assertEqual(c.segment[2].spcod[4], 11) # level self.assertEqual(tuple(c.segment[2].code_block_size), (64, 64)) 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], glymur.core.WAVELET_XFORM_5X3_REVERSIBLE) self.assertEqual(len(c.segment[2].spcod), 9) @@ -2044,12 +2017,10 @@ class TestSuite(MetadataBase): self.assertEqual(ids, expected) kwargs = {'rsiz': 0, 'xysiz': (256, 256), 'xyosiz': (0, 0), - 'xytsiz': (256, 256), 'xytosiz': (0, 0), - 'bitdepth': (8, 8, 8), - 'signed': (True, True, True), - 'xyrsiz': [(1, 1, 1), (1, 1, 1)]} - self.verifySizSegment(c.segment[1], - glymur.codestream.SIZsegment(**kwargs)) + 'xytsiz': (256, 256), 'xytosiz': (0, 0), 'bitdepth': (8, 8, 8), + 'signed': (True, True, True), + 'xyrsiz': [(1, 1, 1), (1, 1, 1)]} + self.verifySizSegment(c.segment[1], glymur.codestream.SIZsegment(**kwargs)) # COD: Coding style default self.assertFalse(c.segment[2].scod & 2) # no sop @@ -2060,7 +2031,7 @@ class TestSuite(MetadataBase): self.assertEqual(c.segment[2].spcod[4], 5) # level self.assertEqual(tuple(c.segment[2].code_block_size), (64, 64)) 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], glymur.core.WAVELET_XFORM_5X3_REVERSIBLE) self.assertEqual(len(c.segment[2].spcod), 9) @@ -2083,11 +2054,10 @@ class TestSuite(MetadataBase): c = jp2k.get_codestream() kwargs = {'rsiz': 0, 'xysiz': (2048, 2500), 'xyosiz': (0, 0), - 'xytsiz': (2048, 2500), 'xytosiz': (0, 0), 'bitdepth': (16,), - 'signed': (False,), - 'xyrsiz': [(1,), (1,)]} - self.verifySizSegment(c.segment[1], - glymur.codestream.SIZsegment(**kwargs)) + 'xytsiz': (2048, 2500), 'xytosiz': (0, 0), 'bitdepth': (16,), + 'signed': (False,), + 'xyrsiz': [(1,), (1,)]} + self.verifySizSegment(c.segment[1], glymur.codestream.SIZsegment(**kwargs)) # COD: Coding style default self.assertFalse(c.segment[2].scod & 2) # no sop @@ -2098,7 +2068,7 @@ class TestSuite(MetadataBase): self.assertEqual(c.segment[2].spcod[4], 8) # level self.assertEqual(tuple(c.segment[2].code_block_size), (64, 64)) 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], glymur.core.WAVELET_XFORM_5X3_REVERSIBLE) self.assertEqual(len(c.segment[2].spcod), 9) @@ -2131,17 +2101,17 @@ class TestSuite(MetadataBase): pargs = (RCME_ISO_8859_1, ccme.encode()) self.verifyCMEsegment(c.segment[5], CMEsegment(*pargs)) + def test_NR_MarkerIsNotCompliant_j2k_dump(self): jfile = opj_data_file('input/nonregression/MarkerIsNotCompliant.j2k') jp2k = Jp2k(jfile) c = jp2k.get_codestream() kwargs = {'rsiz': 0, 'xysiz': (1420, 1416), 'xyosiz': (0, 0), - 'xytsiz': (1420, 1416), 'xytosiz': (0, 0), 'bitdepth': (16,), - 'signed': (False,), - 'xyrsiz': [(1,), (1,)]} - self.verifySizSegment(c.segment[1], - glymur.codestream.SIZsegment(**kwargs)) + 'xytsiz': (1420, 1416), 'xytosiz': (0, 0), 'bitdepth': (16,), + 'signed': (False,), + 'xyrsiz': [(1,), (1,)]} + self.verifySizSegment(c.segment[1], glymur.codestream.SIZsegment(**kwargs)) # COD: Coding style default self.assertFalse(c.segment[2].scod & 2) # no sop @@ -2152,7 +2122,7 @@ class TestSuite(MetadataBase): self.assertEqual(c.segment[2].spcod[4], 11) # level self.assertEqual(tuple(c.segment[2].code_block_size), (64, 64)) 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], glymur.core.WAVELET_XFORM_5X3_REVERSIBLE) self.assertEqual(len(c.segment[2].spcod), 9) @@ -2172,12 +2142,10 @@ class TestSuite(MetadataBase): c = jp2k.get_codestream() kwargs = {'rsiz': 0, 'xysiz': (1920, 1080), 'xyosiz': (0, 0), - 'xytsiz': (1920, 1080), 'xytosiz': (0, 0), - 'bitdepth': (8, 8, 8), - 'signed': (False, False, False), - 'xyrsiz': [(1, 1, 1), (1, 1, 1)]} - self.verifySizSegment(c.segment[1], - glymur.codestream.SIZsegment(**kwargs)) + 'xytsiz': (1920, 1080), 'xytosiz': (0, 0), 'bitdepth': (8, 8, 8), + 'signed': (False, False, False), + 'xyrsiz': [(1, 1, 1), (1, 1, 1)]} + self.verifySizSegment(c.segment[1], glymur.codestream.SIZsegment(**kwargs)) # COD: Coding style default self.assertFalse(c.segment[2].scod & 2) # no sop @@ -2188,7 +2156,7 @@ class TestSuite(MetadataBase): self.assertEqual(c.segment[2].spcod[4], 5) # level self.assertEqual(tuple(c.segment[2].code_block_size), (64, 64)) 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], glymur.core.WAVELET_XFORM_5X3_REVERSIBLE) self.assertEqual(len(c.segment[2].spcod), 9) @@ -2206,12 +2174,10 @@ class TestSuite(MetadataBase): c = jp2k.get_codestream() kwargs = {'rsiz': 0, 'xysiz': (1920, 1080), 'xyosiz': (0, 0), - 'xytsiz': (1920, 1080), 'xytosiz': (0, 0), - 'bitdepth': (8, 8, 8), - 'signed': (False, False, False), - 'xyrsiz': [(1, 1, 1), (1, 1, 1)]} - self.verifySizSegment(c.segment[1], - glymur.codestream.SIZsegment(**kwargs)) + 'xytsiz': (1920, 1080), 'xytosiz': (0, 0), 'bitdepth': (8, 8, 8), + 'signed': (False, False, False), + 'xyrsiz': [(1, 1, 1), (1, 1, 1)]} + self.verifySizSegment(c.segment[1], glymur.codestream.SIZsegment(**kwargs)) # COD: Coding style default self.assertFalse(c.segment[2].scod & 2) # no sop @@ -2222,7 +2188,7 @@ class TestSuite(MetadataBase): self.assertEqual(c.segment[2].spcod[4], 5) # level self.assertEqual(tuple(c.segment[2].code_block_size), (64, 64)) 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], glymur.core.WAVELET_XFORM_5X3_REVERSIBLE) self.assertEqual(len(c.segment[2].spcod), 9) @@ -2240,12 +2206,10 @@ class TestSuite(MetadataBase): c = jp2k.get_codestream() kwargs = {'rsiz': 0, 'xysiz': (1920, 1080), 'xyosiz': (0, 0), - 'xytsiz': (1920, 1080), 'xytosiz': (0, 0), - 'bitdepth': (8, 8, 8), - 'signed': (False, False, False), - 'xyrsiz': [(1, 1, 1), (1, 1, 1)]} - self.verifySizSegment(c.segment[1], - glymur.codestream.SIZsegment(**kwargs)) + 'xytsiz': (1920, 1080), 'xytosiz': (0, 0), 'bitdepth': (8, 8, 8), + 'signed': (False, False, False), + 'xyrsiz': [(1, 1, 1), (1, 1, 1)]} + self.verifySizSegment(c.segment[1], glymur.codestream.SIZsegment(**kwargs)) # COD: Coding style default self.assertFalse(c.segment[2].scod & 2) # no sop @@ -2256,7 +2220,7 @@ class TestSuite(MetadataBase): self.assertEqual(c.segment[2].spcod[4], 5) # level self.assertEqual(tuple(c.segment[2].code_block_size), (64, 64)) 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], glymur.core.WAVELET_XFORM_5X3_REVERSIBLE) self.assertEqual(len(c.segment[2].spcod), 9) @@ -2278,12 +2242,10 @@ class TestSuite(MetadataBase): self.assertEqual(ids, expected) kwargs = {'rsiz': 0, 'xysiz': (117, 117), 'xyosiz': (0, 0), - 'xytsiz': (117, 117), 'xytosiz': (0, 0), - 'bitdepth': (8, 8, 8, 8), - 'signed': (False, False, False, False), - 'xyrsiz': [(1, 1, 1, 1), (1, 1, 1, 1)]} - self.verifySizSegment(c.segment[1], - glymur.codestream.SIZsegment(**kwargs)) + 'xytsiz': (117, 117), 'xytosiz': (0, 0), 'bitdepth': (8, 8, 8, 8), + 'signed': (False, False, False, False), + 'xyrsiz': [(1, 1, 1, 1), (1, 1, 1, 1)]} + self.verifySizSegment(c.segment[1], glymur.codestream.SIZsegment(**kwargs)) # COD: Coding style default self.assertFalse(c.segment[2].scod & 2) # no sop @@ -2294,7 +2256,7 @@ class TestSuite(MetadataBase): self.assertEqual(c.segment[2].spcod[4], 5) # level self.assertEqual(tuple(c.segment[2].code_block_size), (64, 64)) 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], glymur.core.WAVELET_XFORM_5X3_REVERSIBLE) self.assertEqual(len(c.segment[2].spcod), 9) @@ -2316,12 +2278,10 @@ class TestSuite(MetadataBase): self.assertEqual(ids, expected) kwargs = {'rsiz': 0, 'xysiz': (117, 117), 'xyosiz': (0, 0), - 'xytsiz': (117, 117), 'xytosiz': (0, 0), - 'bitdepth': (8, 8, 8, 8), - 'signed': (False, False, False, False), - 'xyrsiz': [(1, 1, 1, 1), (1, 1, 1, 1)]} - self.verifySizSegment(c.segment[1], - glymur.codestream.SIZsegment(**kwargs)) + 'xytsiz': (117, 117), 'xytosiz': (0, 0), 'bitdepth': (8, 8, 8, 8), + 'signed': (False, False, False, False), + 'xyrsiz': [(1, 1, 1, 1), (1, 1, 1, 1)]} + self.verifySizSegment(c.segment[1], glymur.codestream.SIZsegment(**kwargs)) # COD: Coding style default self.assertFalse(c.segment[2].scod & 2) # no sop @@ -2332,7 +2292,7 @@ class TestSuite(MetadataBase): self.assertEqual(c.segment[2].spcod[4], 5) # level self.assertEqual(tuple(c.segment[2].code_block_size), (64, 64)) 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], glymur.core.WAVELET_XFORM_5X3_REVERSIBLE) self.assertEqual(len(c.segment[2].spcod), 9) @@ -2354,12 +2314,10 @@ class TestSuite(MetadataBase): self.assertEqual(ids, expected) kwargs = {'rsiz': 0, 'xysiz': (512, 512), 'xyosiz': (0, 0), - 'xytsiz': (512, 512), 'xytosiz': (0, 0), - 'bitdepth': (16,), - 'signed': (False,), - 'xyrsiz': [(1,), (1,)]} - self.verifySizSegment(c.segment[1], - glymur.codestream.SIZsegment(**kwargs)) + 'xytsiz': (512, 512), 'xytosiz': (0, 0), 'bitdepth': (16,), + 'signed': (False,), + 'xyrsiz': [(1,), (1,)]} + self.verifySizSegment(c.segment[1], glymur.codestream.SIZsegment(**kwargs)) # COD: Coding style default self.assertFalse(c.segment[2].scod & 2) # no sop @@ -2370,7 +2328,7 @@ class TestSuite(MetadataBase): self.assertEqual(c.segment[2].spcod[4], 5) # level self.assertEqual(tuple(c.segment[2].code_block_size), (64, 64)) 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], glymur.core.WAVELET_XFORM_5X3_REVERSIBLE) self.assertEqual(len(c.segment[2].spcod), 9) @@ -2396,12 +2354,10 @@ class TestSuite(MetadataBase): self.assertEqual(ids, expected) kwargs = {'rsiz': 0, 'xysiz': (1024, 1024), 'xyosiz': (0, 0), - 'xytsiz': (1024, 1024), 'xytosiz': (0, 0), - 'bitdepth': (12,), - 'signed': (False,), - 'xyrsiz': [(1,), (1,)]} - self.verifySizSegment(c.segment[1], - glymur.codestream.SIZsegment(**kwargs)) + 'xytsiz': (1024, 1024), 'xytosiz': (0, 0), 'bitdepth': (12,), + 'signed': (False,), + 'xyrsiz': [(1,), (1,)]} + self.verifySizSegment(c.segment[1], glymur.codestream.SIZsegment(**kwargs)) # COD: Coding style default self.assertFalse(c.segment[2].scod & 2) # no sop @@ -2412,7 +2368,7 @@ class TestSuite(MetadataBase): self.assertEqual(c.segment[2].spcod[4], 5) # level self.assertEqual(tuple(c.segment[2].code_block_size), (64, 64)) 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], glymur.core.WAVELET_XFORM_5X3_REVERSIBLE) self.assertEqual(len(c.segment[2].spcod), 9) @@ -2438,12 +2394,10 @@ class TestSuite(MetadataBase): self.assertEqual(ids, expected) kwargs = {'rsiz': 0, 'xysiz': (1800, 1800), 'xyosiz': (0, 0), - 'xytsiz': (1800, 1800), 'xytosiz': (0, 0), - 'bitdepth': (16,), - 'signed': (False,), - 'xyrsiz': [(1,), (1,)]} - self.verifySizSegment(c.segment[1], - glymur.codestream.SIZsegment(**kwargs)) + 'xytsiz': (1800, 1800), 'xytosiz': (0, 0), 'bitdepth': (16,), + 'signed': (False,), + 'xyrsiz': [(1,), (1,)]} + self.verifySizSegment(c.segment[1], glymur.codestream.SIZsegment(**kwargs)) # COD: Coding style default self.assertFalse(c.segment[2].scod & 2) # no sop @@ -2452,9 +2406,10 @@ class TestSuite(MetadataBase): self.assertEqual(c.segment[2].layers, 1) # layers = 1 self.assertEqual(c.segment[2].spcod[3], 1) # mct self.assertEqual(c.segment[2].spcod[4], 11) # level - self.assertEqual(tuple(c.segment[2].code_block_size), (64, 64)) + self.assertEqual(tuple(c.segment[2].code_block_size), + (64, 64)) # cblk 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], glymur.core.WAVELET_XFORM_5X3_REVERSIBLE) self.assertEqual(len(c.segment[2].spcod), 9) @@ -2476,12 +2431,10 @@ class TestSuite(MetadataBase): self.assertEqual(ids, expected) kwargs = {'rsiz': 0, 'xysiz': (1800, 1800), 'xyosiz': (0, 0), - 'xytsiz': (1800, 1800), 'xytosiz': (0, 0), - 'bitdepth': (16,), - 'signed': (False,), - 'xyrsiz': [(1,), (1,)]} - self.verifySizSegment(c.segment[1], - glymur.codestream.SIZsegment(**kwargs)) + 'xytsiz': (1800, 1800), 'xytosiz': (0, 0), 'bitdepth': (16,), + 'signed': (False,), + 'xyrsiz': [(1,), (1,)]} + self.verifySizSegment(c.segment[1], glymur.codestream.SIZsegment(**kwargs)) # COD: Coding style default self.assertFalse(c.segment[2].scod & 2) # no sop @@ -2490,9 +2443,10 @@ class TestSuite(MetadataBase): self.assertEqual(c.segment[2].layers, 1) # layers = 1 self.assertEqual(c.segment[2].spcod[3], 1) # mct self.assertEqual(c.segment[2].spcod[4], 11) # level - self.assertEqual(tuple(c.segment[2].code_block_size), (64, 64)) + self.assertEqual(tuple(c.segment[2].code_block_size), + (64, 64)) # cblk 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], glymur.core.WAVELET_XFORM_5X3_REVERSIBLE) self.assertEqual(len(c.segment[2].spcod), 9) @@ -2514,12 +2468,10 @@ class TestSuite(MetadataBase): self.assertEqual(ids, expected) kwargs = {'rsiz': 0, 'xysiz': (2048, 1556), 'xyosiz': (0, 0), - 'xytsiz': (2048, 1556), 'xytosiz': (0, 0), - 'bitdepth': (12, 12, 12), - 'signed': (False, False, False), - 'xyrsiz': [(1, 1, 1), (1, 1, 1)]} - self.verifySizSegment(c.segment[1], - glymur.codestream.SIZsegment(**kwargs)) + 'xytsiz': (2048, 1556), 'xytosiz': (0, 0), 'bitdepth': (12, 12, 12), + 'signed': (False, False, False), + 'xyrsiz': [(1, 1, 1), (1, 1, 1)]} + self.verifySizSegment(c.segment[1], glymur.codestream.SIZsegment(**kwargs)) # COD: Coding style default self.assertFalse(c.segment[2].scod & 2) # no sop @@ -2528,9 +2480,10 @@ class TestSuite(MetadataBase): self.assertEqual(c.segment[2].layers, 2) # layers = 2 self.assertEqual(c.segment[2].spcod[3], 1) # mct self.assertEqual(c.segment[2].spcod[4], 5) # level - self.assertEqual(tuple(c.segment[2].code_block_size), (32, 32)) + self.assertEqual(tuple(c.segment[2].code_block_size), + (32, 32)) # cblk 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], glymur.core.WAVELET_XFORM_9X7_IRREVERSIBLE) self.assertEqual(c.segment[2].precinct_size, @@ -2559,9 +2512,7 @@ class TestSuite(MetadataBase): self.verifySignatureBox(jp2.box[0]) self.verify_filetype_box(jp2.box[1], - FileTypeBox(compatibility_list=['jp2 ', - 'jpxb', - 'jpx '])) + FileTypeBox(compatibility_list=['jp2 ', 'jpxb', 'jpx '])) # Reader requirements talk. # unrestricted jpeg 2000 part 1 @@ -2570,9 +2521,9 @@ class TestSuite(MetadataBase): ihdr = glymur.jp2box.ImageHeaderBox(203, 479, colorspace_unknown=True) self.verifyImageHeaderBox(jp2.box[3].box[0], ihdr) - colr = glymur.jp2box.ColourSpecificationBox(colorspace=SRGB, - approximation=1, - precedence=2) + colr = glymur.jp2box.ColourSpecificationBox( + colorspace=glymur.core.SRGB, + approximation=1, precedence=2) self.verifyColourSpecificationBox(jp2.box[3].box[1], colr) # Jp2 Header @@ -2585,19 +2536,17 @@ class TestSuite(MetadataBase): self.assertEqual(jp2.box[3].box[3].mapping_type, (1, 1, 1)) self.assertEqual(jp2.box[3].box[3].palette_index, (0, 1, 2)) - c = jp2.box[4].codestream + c = jp2.box[4].main_header ids = [x.marker_id for x in c.segment] expected = ['SOC', 'SIZ', 'COD', 'QCD'] self.assertEqual(ids, expected) kwargs = {'rsiz': 0, 'xysiz': (479, 203), 'xyosiz': (0, 0), - 'xytsiz': (256, 203), 'xytosiz': (0, 0), - 'bitdepth': (8,), - 'signed': (False,), - 'xyrsiz': [(1,), (1,)]} - self.verifySizSegment(c.segment[1], - glymur.codestream.SIZsegment(**kwargs)) + 'xytsiz': (256, 203), 'xytosiz': (0, 0), 'bitdepth': (8,), + 'signed': (False,), + 'xyrsiz': [(1,), (1,)]} + self.verifySizSegment(c.segment[1], glymur.codestream.SIZsegment(**kwargs)) # COD: Coding style default self.assertFalse(c.segment[2].scod & 2) # no sop @@ -2606,9 +2555,10 @@ class TestSuite(MetadataBase): self.assertEqual(c.segment[2].layers, 1) # layers = 1 self.assertEqual(c.segment[2].spcod[3], 0) # mct self.assertEqual(c.segment[2].spcod[4], 5) # level - self.assertEqual(tuple(c.segment[2].code_block_size), (32, 32)) + self.assertEqual(tuple(c.segment[2].code_block_size), + (32, 32)) # cblk 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], glymur.core.WAVELET_XFORM_5X3_REVERSIBLE) self.assertEqual(len(c.segment[2].spcod), 9) @@ -2631,37 +2581,32 @@ class TestSuite(MetadataBase): self.verifySignatureBox(jp2.box[0]) self.verify_filetype_box(jp2.box[1], - FileTypeBox(compatibility_list=['jp2 ', - 'jpxb', - 'jpx '])) + FileTypeBox(compatibility_list=['jp2 ', 'jpxb', 'jpx '])) # Reader requirements talk. # unrestricted jpeg 2000 part 1 self.assertTrue(5 in jp2.box[2].standard_flag) ihdr = glymur.jp2box.ImageHeaderBox(326, 431, - num_components=3, - colorspace_unknown=True) + num_components=3, colorspace_unknown=True) self.verifyImageHeaderBox(jp2.box[3].box[0], ihdr) - colr = glymur.jp2box.ColourSpecificationBox(colorspace=SRGB, - approximation=1, - precedence=2) + colr = glymur.jp2box.ColourSpecificationBox( + colorspace=glymur.core.SRGB, + approximation=1, precedence=2) self.verifyColourSpecificationBox(jp2.box[3].box[1], colr) - c = jp2.box[4].codestream + c = jp2.box[4].main_header ids = [x.marker_id for x in c.segment] expected = ['SOC', 'SIZ', 'COD', 'QCD'] self.assertEqual(ids, expected) kwargs = {'rsiz': 0, 'xysiz': (431, 326), 'xyosiz': (0, 0), - 'xytsiz': (256, 256), 'xytosiz': (0, 0), - 'bitdepth': (8, 8, 8), - 'signed': (False, False, False), - 'xyrsiz': [(1, 1, 1), (1, 1, 1)]} - self.verifySizSegment(c.segment[1], - glymur.codestream.SIZsegment(**kwargs)) + 'xytsiz': (256, 256), 'xytosiz': (0, 0), 'bitdepth': (8, 8, 8), + 'signed': (False, False, False), + 'xyrsiz': [(1, 1, 1), (1, 1, 1)]} + self.verifySizSegment(c.segment[1], glymur.codestream.SIZsegment(**kwargs)) # COD: Coding style default self.assertFalse(c.segment[2].scod & 2) # no sop @@ -2670,9 +2615,10 @@ class TestSuite(MetadataBase): self.assertEqual(c.segment[2].layers, 1) # layers = 1 self.assertEqual(c.segment[2].spcod[3], 1) # mct self.assertEqual(c.segment[2].spcod[4], 5) # level - self.assertEqual(tuple(c.segment[2].code_block_size), (32, 32)) + self.assertEqual(tuple(c.segment[2].code_block_size), + (32, 32)) # cblk 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], glymur.core.WAVELET_XFORM_9X7_IRREVERSIBLE) self.assertEqual(len(c.segment[2].spcod), 9) @@ -2700,10 +2646,11 @@ class TestSuite(MetadataBase): self.verify_filetype_box(jp2.box[1], FileTypeBox()) ihdr = glymur.jp2box.ImageHeaderBox(135, 135, num_components=2, - colorspace_unknown=True) + colorspace_unknown=True) self.verifyImageHeaderBox(jp2.box[2].box[0], ihdr) - colr = glymur.jp2box.ColourSpecificationBox(colorspace=GREYSCALE) + colr = glymur.jp2box.ColourSpecificationBox( + colorspace=glymur.core.GREYSCALE) self.verifyColourSpecificationBox(jp2.box[2].box[1], colr) # Jp2 Header @@ -2712,19 +2659,17 @@ class TestSuite(MetadataBase): self.assertEqual(jp2.box[2].box[2].channel_type, (0, 1)) # opacity self.assertEqual(jp2.box[2].box[2].association, (0, 0)) # both main - c = jp2.box[3].codestream + c = jp2.box[3].main_header ids = [x.marker_id for x in c.segment] expected = ['SOC', 'SIZ', 'COD', 'QCD', 'CME'] self.assertEqual(ids, expected) kwargs = {'rsiz': 0, 'xysiz': (135, 135), 'xyosiz': (0, 0), - 'xytsiz': (135, 135), 'xytosiz': (0, 0), - 'bitdepth': (8, 8), - 'signed': (False, False), - 'xyrsiz': [(1, 1), (1, 1)]} - self.verifySizSegment(c.segment[1], - glymur.codestream.SIZsegment(**kwargs)) + 'xytsiz': (135, 135), 'xytosiz': (0, 0), 'bitdepth': (8, 8), + 'signed': (False, False), + 'xyrsiz': [(1, 1), (1, 1)]} + self.verifySizSegment(c.segment[1], glymur.codestream.SIZsegment(**kwargs)) # COD: Coding style default self.assertFalse(c.segment[2].scod & 2) # no sop @@ -2736,7 +2681,7 @@ class TestSuite(MetadataBase): self.assertEqual(tuple(c.segment[2].code_block_size), (64, 64)) # cblk 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], glymur.core.WAVELET_XFORM_9X7_IRREVERSIBLE) self.assertEqual(len(c.segment[2].spcod), 9) @@ -2765,23 +2710,20 @@ class TestSuite(MetadataBase): self.verifySignatureBox(jp2.box[0]) self.verify_filetype_box(jp2.box[1], - FileTypeBox(compatibility_list=['jp2 ', - 'jpxb', - 'jpx '])) + FileTypeBox(compatibility_list=['jp2 ', 'jpxb', 'jpx '])) # Reader requirements talk. # unrestricted jpeg 2000 part 1 self.assertTrue(5 in jp2.box[2].standard_flag) ihdr = glymur.jp2box.ImageHeaderBox(46, 124, bits_per_component=4, - colorspace_unknown=True) + colorspace_unknown=True) self.verifyImageHeaderBox(jp2.box[3].box[0], ihdr) - method = ENUMERATED_COLORSPACE - colr = glymur.jp2box.ColourSpecificationBox(colorspace=SRGB, - method=method, - approximation=1, - precedence=2) + colr = glymur.jp2box.ColourSpecificationBox( + colorspace=glymur.core.SRGB, + method=glymur.core.ENUMERATED_COLORSPACE, + approximation=1, precedence=2) self.verifyColourSpecificationBox(jp2.box[3].box[1], colr) # Jp2 Header @@ -2795,19 +2737,17 @@ class TestSuite(MetadataBase): self.assertEqual(jp2.box[3].box[3].mapping_type, (1, 1, 1)) self.assertEqual(jp2.box[3].box[3].palette_index, (0, 1, 2)) - c = jp2.box[4].codestream + c = jp2.box[4].main_header ids = [x.marker_id for x in c.segment] expected = ['SOC', 'SIZ', 'COD', 'QCD'] self.assertEqual(ids, expected) kwargs = {'rsiz': 0, 'xysiz': (124, 46), 'xyosiz': (0, 0), - 'xytsiz': (124, 46), 'xytosiz': (0, 0), - 'bitdepth': (4,), - 'signed': (False,), - 'xyrsiz': [(1,), (1,)]} - self.verifySizSegment(c.segment[1], - glymur.codestream.SIZsegment(**kwargs)) + 'xytsiz': (124, 46), 'xytosiz': (0, 0), 'bitdepth': (4,), + 'signed': (False,), + 'xyrsiz': [(1,), (1,)]} + self.verifySizSegment(c.segment[1], glymur.codestream.SIZsegment(**kwargs)) # COD: Coding style default self.assertFalse(c.segment[2].scod & 2) # no sop @@ -2819,7 +2759,7 @@ class TestSuite(MetadataBase): self.assertEqual(tuple(c.segment[2].code_block_size), (32, 32)) # cblk 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], glymur.core.WAVELET_XFORM_5X3_REVERSIBLE) self.assertEqual(len(c.segment[2].spcod), 9) @@ -2849,19 +2789,17 @@ class TestSuite(MetadataBase): colr = glymur.jp2box.ColourSpecificationBox(colorspace=glymur.core.YCC) self.verifyColourSpecificationBox(jp2.box[2].box[1], colr) - c = jp2.box[3].codestream + c = jp2.box[3].main_header ids = [x.marker_id for x in c.segment] expected = ['SOC', 'SIZ', 'COD', 'QCD', 'POD'] self.assertEqual(ids, expected) kwargs = {'rsiz': 0, 'xysiz': (766, 576), 'xyosiz': (0, 0), - 'xytsiz': (766, 576), 'xytosiz': (0, 0), - 'bitdepth': (8, 8, 8), - 'signed': (False, False, False), - 'xyrsiz': [(1, 2, 2), (1, 1, 1)]} - self.verifySizSegment(c.segment[1], - glymur.codestream.SIZsegment(**kwargs)) + 'xytsiz': (766, 576), 'xytosiz': (0, 0), 'bitdepth': (8, 8, 8), + 'signed': (False, False, False), + 'xyrsiz': [(1, 2, 2), (1, 1, 1)]} + self.verifySizSegment(c.segment[1], glymur.codestream.SIZsegment(**kwargs)) # COD: Coding style default self.assertFalse(c.segment[2].scod & 2) # no sop @@ -2873,7 +2811,7 @@ class TestSuite(MetadataBase): self.assertEqual(tuple(c.segment[2].code_block_size), (32, 128)) # cblk 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], glymur.core.WAVELET_XFORM_5X3_REVERSIBLE) self.assertEqual(len(c.segment[2].spcod), 9) @@ -2909,34 +2847,111 @@ class TestSuiteWarns(MetadataBase): relpath = 'input/nonregression/issue188_beach_64bitsbox.jp2' jfile = opj_data_file(relpath) with self.assertWarns(UserWarning): - Jp2k(jfile)[:] + d = Jp2k(jfile)[:] self.assertTrue(True) def test_NR_broken4_jp2_dump(self): jfile = opj_data_file('input/nonregression/broken4.jp2') - with warnings.catch_warnings(): - # Suppress a warning, all we really care is parsing the entire - # file. - warnings.simplefilter("ignore") - with self.assertWarns(UserWarning): - jp2 = Jp2k(jfile) - self.assertEqual(jp2.box[-1].codestream.segment[-1].marker_id, - 'QCC') + with self.assertWarns(UserWarning): + jp2 = Jp2k(jfile) + + self.assertEqual(jp2.box[-1].main_header.segment[-1].marker_id, 'QCC') + + @unittest.skipIf(sys.maxsize < 2**32, 'Do not run on 32-bit platforms') + def test_NR_broken3_jp2_dump(self): + """ + NR_broken3_jp2_dump + + The file in question here has a colr box with an erroneous box + length of over 1GB. Don't run it on 32-bit platforms. + """ + jfile = opj_data_file('input/nonregression/broken3.jp2') + with self.assertWarns(UserWarning): + # Bad box length. + jp2 = Jp2k(jfile) + + ids = [box.box_id for box in jp2.box] + self.assertEqual(ids, ['jP ', 'ftyp', 'jp2h', 'jp2c']) + + ids = [box.box_id for box in jp2.box[2].box] + self.assertEqual(ids, ['ihdr', 'colr']) + + self.verifySignatureBox(jp2.box[0]) + self.verify_filetype_box(jp2.box[1], FileTypeBox()) + + ihdr = glymur.jp2box.ImageHeaderBox(152, 203, num_components=3) + self.verifyImageHeaderBox(jp2.box[2].box[0], ihdr) + + colr = glymur.jp2box.ColourSpecificationBox(colorspace=glymur.core.SRGB) + self.verifyColourSpecificationBox(jp2.box[2].box[1], colr) + + c = jp2.box[3].main_header + + ids = [x.marker_id for x in c.segment] + expected = ['SOC', 'SIZ', 'CME', 'COD', 'QCD', 'QCC', 'QCC'] + self.assertEqual(ids, expected) + + kwargs = {'rsiz': 0, 'xysiz': (203, 152), 'xyosiz': (0, 0), + 'xytsiz': (203, 152), 'xytosiz': (0, 0), 'bitdepth': (8, 8, 8), + 'signed': (False, False, False), + 'xyrsiz': [(1, 1, 1), (1, 1, 1)]} + self.verifySizSegment(c.segment[1], glymur.codestream.SIZsegment(**kwargs)) + + pargs = RCME_ISO_8859_1, "Creator: JasPer Vers)on 1.701.0".encode() + self.verifyCMEsegment(c.segment[2], CMEsegment(*pargs)) + + # COD: Coding style default + self.assertFalse(c.segment[3].scod & 2) # no sop + self.assertFalse(c.segment[3].scod & 4) # no eph + self.assertEqual(c.segment[3].spcod[0], glymur.core.LRCP) + self.assertEqual(c.segment[3].layers, 1) # layers = 1 + self.assertEqual(c.segment[3].spcod[3], 1) # mct + self.assertEqual(c.segment[3].spcod[4], 5) # level + self.assertEqual(tuple(c.segment[3].code_block_size), + (64, 64)) # cblk + self.verify_codeblock_style(c.segment[3].spcod[7], + [False, False, False, False, False, False]) + self.assertEqual(c.segment[3].spcod[8], + glymur.core.WAVELET_XFORM_5X3_REVERSIBLE) + self.assertEqual(len(c.segment[3].spcod), 9) + + # QCD: Quantization default + self.assertEqual(c.segment[4].sqcd & 0x1f, 0) + self.assertEqual(c.segment[4].guard_bits, 2) + self.assertEqual(c.segment[4].mantissa, [0] * 16) + self.assertEqual(c.segment[4].exponent, + [8] + [9, 9, 10] * 5) + + # QCC: Quantization component + # associated component + self.assertEqual(c.segment[5].cqcc, 1) + self.assertEqual(c.segment[5].guard_bits, 2) + # quantization type + self.assertEqual(c.segment[5].sqcc & 0x1f, 0) # none + self.assertEqual(c.segment[5].mantissa, [0] * 16) + self.assertEqual(c.segment[5].exponent, + [8] + [9, 9, 10] * 5) + + # QCC: Quantization component + # associated component + self.assertEqual(c.segment[6].cqcc, 2) + self.assertEqual(c.segment[6].guard_bits, 2) + # quantization type + self.assertEqual(c.segment[6].sqcc & 0x1f, 0) # none + self.assertEqual(c.segment[6].mantissa, [0] * 16) + self.assertEqual(c.segment[6].exponent, + [8] + [9, 9, 10] * 5) def test_NR_broken2_jp2_dump(self): """ Invalid marker ID in the codestream. """ jfile = opj_data_file('input/nonregression/broken2.jp2') - with warnings.catch_warnings(): - # Suppress a warning, all we really care is parsing the entire - # file. - warnings.simplefilter("ignore") - with self.assertWarns(UserWarning): - # Invalid marker ID on codestream. - jp2 = Jp2k(jfile) - self.assertEqual(jp2.box[-1].codestream.segment[-1].marker_id, - 'QCC') + with self.assertWarns(UserWarning): + # Invalid marker ID on codestream. + jp2 = Jp2k(jfile) + + self.assertEqual(jp2.box[-1].main_header.segment[-1].marker_id, 'QCC') def test_NR_file1_dump(self): jfile = opj_data_file('input/conformance/file1.jp2') @@ -2963,8 +2978,8 @@ class TestSuiteWarns(MetadataBase): ihdr = glymur.jp2box.ImageHeaderBox(512, 768, num_components=3) self.verifyImageHeaderBox(jp2.box[3].box[0], ihdr) - colr = glymur.jp2box.ColourSpecificationBox(colorspace=SRGB, - approximation=1) + colr = glymur.jp2box.ColourSpecificationBox(colorspace=glymur.core.SRGB, + approximation=1) self.verifyColourSpecificationBox(jp2.box[3].box[1], colr) # XML box @@ -2991,7 +3006,7 @@ class TestSuiteWarns(MetadataBase): self.verifyImageHeaderBox(jp2.box[2].box[0], ihdr) colr = glymur.jp2box.ColourSpecificationBox(colorspace=glymur.core.YCC, - approximation=1) + approximation=1) self.verifyColourSpecificationBox(jp2.box[2].box[1], colr) # Jp2 Header @@ -3021,8 +3036,9 @@ class TestSuiteWarns(MetadataBase): ihdr = glymur.jp2box.ImageHeaderBox(640, 480, num_components=3) self.verifyImageHeaderBox(jp2.box[2].box[0], ihdr) - colr = glymur.jp2box.ColourSpecificationBox(colorspace=glymur.core.YCC, - approximation=1) + colr = glymur.jp2box.ColourSpecificationBox( + colorspace=glymur.core.YCC, + approximation=1) self.verifyColourSpecificationBox(jp2.box[2].box[1], colr) # sub-sampling @@ -3052,8 +3068,8 @@ class TestSuiteWarns(MetadataBase): ihdr = glymur.jp2box.ImageHeaderBox(512, 768) self.verifyImageHeaderBox(jp2.box[2].box[0], ihdr) - colr = glymur.jp2box.ColourSpecificationBox(colorspace=GREYSCALE, - approximation=1) + colr = glymur.jp2box.ColourSpecificationBox( + colorspace=glymur.core.GREYSCALE, approximation=1) self.verifyColourSpecificationBox(jp2.box[2].box[1], colr) def test_NR_file5_dump(self): @@ -3075,18 +3091,16 @@ class TestSuiteWarns(MetadataBase): self.assertEqual(ids, ['ihdr', 'colr', 'colr']) self.verifySignatureBox(jp2.box[0]) - expected = FileTypeBox(brand='jpx ', - compatibility_list=['jp2 ', 'jpx ', 'jpxb']) + expected = FileTypeBox( + brand='jpx ', compatibility_list=['jp2 ', 'jpx ', 'jpxb']) self.verify_filetype_box(jp2.box[1], expected) ihdr = glymur.jp2box.ImageHeaderBox(512, 768, num_components=3) self.verifyImageHeaderBox(jp2.box[3].box[0], ihdr) - method = RESTRICTED_ICC_PROFILE - icc_profile = bytes([0] * 546) - colr = glymur.jp2box.ColourSpecificationBox(method=method, - approximation=1, - icc_profile=icc_profile) + colr = glymur.jp2box.ColourSpecificationBox( + method=glymur.core.RESTRICTED_ICC_PROFILE, + approximation=1, icc_profile=bytes([0] * 546)) self.verifyColourSpecificationBox(jp2.box[3].box[1], colr) self.assertEqual(jp2.box[3].box[1].icc_profile['Size'], 546) @@ -3107,10 +3121,10 @@ class TestSuiteWarns(MetadataBase): ihdr = glymur.jp2box.ImageHeaderBox(512, 768, bits_per_component=12) self.verifyImageHeaderBox(jp2.box[2].box[0], ihdr) - method = ENUMERATED_COLORSPACE - colr = glymur.jp2box.ColourSpecificationBox(colorspace=GREYSCALE, - method=method, - approximation=1) + colr = glymur.jp2box.ColourSpecificationBox( + colorspace=glymur.core.GREYSCALE, + method=glymur.core.ENUMERATED_COLORSPACE, + approximation=1) self.verifyColourSpecificationBox(jp2.box[2].box[1], colr) def test_NR_file7_dump(self): @@ -3136,13 +3150,12 @@ class TestSuiteWarns(MetadataBase): self.assertEqual(jp2.box[1].compatibility_list[1], 'jp2 ') ihdr = glymur.jp2box.ImageHeaderBox(640, 480, - num_components=3, - bits_per_component=16) + num_components=3, bits_per_component=16) self.verifyImageHeaderBox(jp2.box[3].box[0], ihdr) - method = RESTRICTED_ICC_PROFILE - colr = glymur.jp2box.ColourSpecificationBox(method=method, - approximation=1) + colr = glymur.jp2box.ColourSpecificationBox( + method=glymur.core.RESTRICTED_ICC_PROFILE, + approximation=1) self.verifyColourSpecificationBox(jp2.box[3].box[1], colr) self.assertEqual(jp2.box[3].box[1].icc_profile['Size'], 13332) @@ -3166,9 +3179,9 @@ class TestSuiteWarns(MetadataBase): ihdr = glymur.jp2box.ImageHeaderBox(400, 700) self.verifyImageHeaderBox(jp2.box[2].box[0], ihdr) - method = RESTRICTED_ICC_PROFILE - colr = glymur.jp2box.ColourSpecificationBox(method=method, - approximation=1) + colr = glymur.jp2box.ColourSpecificationBox( + method=glymur.core.RESTRICTED_ICC_PROFILE, + approximation=1) self.verifyColourSpecificationBox(jp2.box[2].box[1], colr) self.assertEqual(jp2.box[2].box[1].icc_profile['Size'], 414) @@ -3221,15 +3234,16 @@ class TestSuiteWarns(MetadataBase): self.assertEqual(jp2.box[2].box[2].mapping_type, (1, 1, 1)) self.assertEqual(jp2.box[2].box[2].palette_index, (0, 1, 2)) - colr = glymur.jp2box.ColourSpecificationBox(colorspace=SRGB, - approximation=1) + colr = glymur.jp2box.ColourSpecificationBox( + colorspace=glymur.core.SRGB, + approximation=1) self.verifyColourSpecificationBox(jp2.box[2].box[3], colr) def test_NR_issue188_beach_64bitsbox(self): lst = ['input', 'nonregression', 'issue188_beach_64bitsbox.jp2'] jfile = opj_data_file('/'.join(lst)) with self.assertWarns(UserWarning): - # There's a warning for an unknown box. + # There's a warning for an unknown box. jp2 = Jp2k(jfile) ids = [box.box_id for box in jp2.box] @@ -3242,29 +3256,25 @@ class TestSuiteWarns(MetadataBase): self.verify_filetype_box(jp2.box[1], FileTypeBox()) ihdr = glymur.jp2box.ImageHeaderBox(200, 200, - num_components=3, - colorspace_unknown=True) + num_components=3, colorspace_unknown=True) self.verifyImageHeaderBox(jp2.box[2].box[0], ihdr) - cspace = glymur.core.SRGB - colr = glymur.jp2box.ColourSpecificationBox(colorspace=cspace) + colr = glymur.jp2box.ColourSpecificationBox(colorspace=glymur.core.SRGB) self.verifyColourSpecificationBox(jp2.box[2].box[1], colr) # Skip the 4th box, it is uknown. - c = jp2.box[4].codestream + c = jp2.box[4].main_header ids = [x.marker_id for x in c.segment] expected = ['SOC', 'SIZ', 'COD', 'QCD', 'CME', 'CME'] self.assertEqual(ids, expected) kwargs = {'rsiz': 0, 'xysiz': (200, 200), 'xyosiz': (0, 0), - 'xytsiz': (200, 200), 'xytosiz': (0, 0), - 'bitdepth': (8, 8, 8), - 'signed': (False, False, False), - 'xyrsiz': [(1, 1, 1), (1, 1, 1)]} - self.verifySizSegment(c.segment[1], - glymur.codestream.SIZsegment(**kwargs)) + 'xytsiz': (200, 200), 'xytosiz': (0, 0), 'bitdepth': (8, 8, 8), + 'signed': (False, False, False), + 'xyrsiz': [(1, 1, 1), (1, 1, 1)]} + self.verifySizSegment(c.segment[1], glymur.codestream.SIZsegment(**kwargs)) # COD: Coding style default self.assertFalse(c.segment[2].scod & 2) # no sop @@ -3276,7 +3286,7 @@ class TestSuiteWarns(MetadataBase): self.assertEqual(tuple(c.segment[2].code_block_size), (64, 64)) # cblk 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], glymur.core.WAVELET_XFORM_9X7_IRREVERSIBLE) self.assertEqual(len(c.segment[2].spcod), 9) @@ -3312,19 +3322,17 @@ class TestSuiteWarns(MetadataBase): self.assertIsNone(jp2.box[2].box[1].icc_profile) self.assertIsNone(jp2.box[2].box[1].colorspace) - c = jp2.box[3].codestream + c = jp2.box[3].main_header ids = [x.marker_id for x in c.segment] expected = ['SOC', 'SIZ', 'COD', 'QCD'] self.assertEqual(ids, expected) kwargs = {'rsiz': 0, 'xysiz': (117, 117), 'xyosiz': (0, 0), - 'xytsiz': (117, 117), 'xytosiz': (0, 0), - 'bitdepth': (8, 8, 8, 8), - 'signed': (False, False, False, False), - 'xyrsiz': [(1, 1, 1, 1), (1, 1, 1, 1)]} - self.verifySizSegment(c.segment[1], - glymur.codestream.SIZsegment(**kwargs)) + 'xytsiz': (117, 117), 'xytosiz': (0, 0), 'bitdepth': (8, 8, 8, 8), + 'signed': (False, False, False, False), + 'xyrsiz': [(1, 1, 1, 1), (1, 1, 1, 1)]} + self.verifySizSegment(c.segment[1], glymur.codestream.SIZsegment(**kwargs)) # COD: Coding style default self.assertFalse(c.segment[2].scod & 2) # no sop @@ -3336,7 +3344,7 @@ class TestSuiteWarns(MetadataBase): self.assertEqual(tuple(c.segment[2].code_block_size), (64, 64)) # cblk 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], glymur.core.WAVELET_XFORM_5X3_REVERSIBLE) self.assertEqual(len(c.segment[2].spcod), 9) @@ -3375,19 +3383,17 @@ class TestSuiteWarns(MetadataBase): self.assertIsNone(jp2.box[2].box[1].icc_profile) self.assertIsNone(jp2.box[2].box[1].colorspace) - c = jp2.box[3].codestream + c = jp2.box[3].main_header ids = [x.marker_id for x in c.segment] expected = ['SOC', 'SIZ', 'COD', 'QCD'] self.assertEqual(ids, expected) kwargs = {'rsiz': 0, 'xysiz': (117, 117), 'xyosiz': (0, 0), - 'xytsiz': (117, 117), 'xytosiz': (0, 0), - 'bitdepth': (8, 8, 8, 8), - 'signed': (False, False, False, False), - 'xyrsiz': [(1, 1, 1, 1), (1, 1, 1, 1)]} - self.verifySizSegment(c.segment[1], - glymur.codestream.SIZsegment(**kwargs)) + 'xytsiz': (117, 117), 'xytosiz': (0, 0), 'bitdepth': (8, 8, 8, 8), + 'signed': (False, False, False, False), + 'xyrsiz': [(1, 1, 1, 1), (1, 1, 1, 1)]} + self.verifySizSegment(c.segment[1], glymur.codestream.SIZsegment(**kwargs)) # COD: Coding style default self.assertFalse(c.segment[2].scod & 2) # no sop @@ -3399,7 +3405,7 @@ class TestSuiteWarns(MetadataBase): self.assertEqual(tuple(c.segment[2].code_block_size), (64, 64)) # cblk 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], glymur.core.WAVELET_XFORM_5X3_REVERSIBLE) self.assertEqual(len(c.segment[2].spcod), 9) diff --git a/glymur/test/test_opj_suite_neg.py b/glymur/test/test_opj_suite_neg.py index d2351a4..c7e31e5 100644 --- a/glymur/test/test_opj_suite_neg.py +++ b/glymur/test/test_opj_suite_neg.py @@ -2,8 +2,15 @@ The tests here do not correspond directly to the OpenJPEG test suite, but seem like logical negative tests to add. """ +# E1101: assertWarns introduced in python 3.2 +# pylint: disable=E1101 + +# R0904: Not too many methods in unittest. +# pylint: disable=R0904 + import os import re +import sys import tempfile import unittest @@ -81,6 +88,7 @@ class TestSuiteNegativeWrite(unittest.TestCase): 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): @@ -90,7 +98,8 @@ class TestSuiteNegativeWrite(unittest.TestCase): data = skimage.io.imread(infile) with tempfile.NamedTemporaryFile(suffix='.j2k') as tfile: with self.assertRaises(IOError): - Jp2k(tfile.name, data=data, cinema2k=36) + j = Jp2k(tfile.name, data=data, cinema2k=36) + @unittest.skipIf(NO_READ_BACKEND, NO_READ_BACKEND_MSG) def test_psnr_with_cratios(self): @@ -100,8 +109,8 @@ class TestSuiteNegativeWrite(unittest.TestCase): 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]) + j = Jp2k(tfile.name, + data=data, psnr=[30, 35, 40], cratios=[2, 3, 4]) def test_code_block_dimensions(self): """don't allow extreme codeblock sizes""" @@ -111,13 +120,13 @@ class TestSuiteNegativeWrite(unittest.TestCase): with tempfile.NamedTemporaryFile(suffix='.j2k') as tfile: # opj_compress doesn't allow code block area to exceed 4096. with self.assertRaises(IOError): - Jp2k(tfile.name, data=data, cbsize=(256, 256)) + j = Jp2k(tfile.name, data=data, cbsize=(256, 256)) # opj_compress doesn't allow either dimension to be less than 4. with self.assertRaises(IOError): - Jp2k(tfile.name, data=data, cbsize=(2048, 2)) + j = Jp2k(tfile.name, data=data, cbsize=(2048, 2)) with self.assertRaises(IOError): - Jp2k(tfile.name, data=data, cbsize=(2, 2048)) + j = Jp2k(tfile.name, data=data, cbsize=(2, 2048)) def test_precinct_size_not_p2(self): """precinct sizes should be powers of two.""" @@ -125,7 +134,7 @@ class TestSuiteNegativeWrite(unittest.TestCase): data = ifile[::4, ::4] with tempfile.NamedTemporaryFile(suffix='.jp2') as tfile: with self.assertRaises(IOError): - Jp2k(tfile.name, data=data, psizes=[(13, 13)]) + ofile = Jp2k(tfile.name, data=data, psizes=[(13, 13)]) def test_cblk_size_not_power_of_two(self): """code block sizes should be powers of two.""" @@ -133,7 +142,7 @@ class TestSuiteNegativeWrite(unittest.TestCase): data = ifile[::4, ::4] with tempfile.NamedTemporaryFile(suffix='.jp2') as tfile: with self.assertRaises(IOError): - Jp2k(tfile.name, data=data, cbsize=(13, 12)) + ofile = Jp2k(tfile.name, data=data, cbsize=(13, 12)) def test_cblk_size_precinct_size(self): """code block sizes should never exceed half that of precinct size.""" @@ -141,4 +150,6 @@ class TestSuiteNegativeWrite(unittest.TestCase): data = ifile[::4, ::4] with tempfile.NamedTemporaryFile(suffix='.jp2') as tfile: with self.assertRaises(IOError): - Jp2k(tfile.name, data=data, cbsize=(64, 64), psizes=[(64, 64)]) + ofile = Jp2k(tfile.name, + data=data, cbsize=(64, 64), psizes=[(64, 64)]) + diff --git a/glymur/test/test_opj_suite_write.py b/glymur/test/test_opj_suite_write.py index f44c7b4..01ffa8c 100644 --- a/glymur/test/test_opj_suite_write.py +++ b/glymur/test/test_opj_suite_write.py @@ -2,6 +2,10 @@ The tests defined here roughly correspond to what is in the OpenJPEG test 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 re import sys @@ -30,7 +34,6 @@ from glymur import Jp2k from glymur.codestream import SIZsegment from glymur.version import openjpeg_version - class CinemaBase(fixtures.MetadataBase): def verify_cinema_cod(self, cod_segment): @@ -41,14 +44,14 @@ class CinemaBase(fixtures.MetadataBase): self.assertEqual(cod_segment.layers, 1) self.assertEqual(cod_segment.spcod[3], 1) # mct self.assertEqual(cod_segment.spcod[4], 5) # levels - self.assertEqual(tuple(cod_segment.code_block_size), (32, 32)) + self.assertEqual(tuple(cod_segment.code_block_size), (32, 32)) # cblksz def check_cinema4k_codestream(self, codestream, image_size): kwargs = {'rsiz': 4, 'xysiz': image_size, 'xyosiz': (0, 0), - 'xytsiz': image_size, 'xytosiz': (0, 0), - 'bitdepth': (12, 12, 12), 'signed': (False, False, False), - 'xyrsiz': [(1, 1, 1), (1, 1, 1)]} + 'xytsiz': image_size, 'xytosiz': (0, 0), + 'bitdepth': (12, 12, 12), 'signed': (False, False, False), + 'xyrsiz': [(1, 1, 1), (1, 1, 1)]} self.verifySizSegment(codestream.segment[1], SIZsegment(**kwargs)) self.verify_cinema_cod(codestream.segment[2]) @@ -56,9 +59,9 @@ class CinemaBase(fixtures.MetadataBase): def check_cinema2k_codestream(self, codestream, image_size): kwargs = {'rsiz': 3, 'xysiz': image_size, 'xyosiz': (0, 0), - 'xytsiz': image_size, 'xytosiz': (0, 0), - 'bitdepth': (12, 12, 12), 'signed': (False, False, False), - 'xyrsiz': [(1, 1, 1), (1, 1, 1)]} + 'xytsiz': image_size, 'xytosiz': (0, 0), + 'bitdepth': (12, 12, 12), 'signed': (False, False, False), + 'xyrsiz': [(1, 1, 1), (1, 1, 1)]} self.verifySizSegment(codestream.segment[1], SIZsegment(**kwargs)) self.verify_cinema_cod(codestream.segment[2]) @@ -85,8 +88,8 @@ class WriteCinema(CinemaBase): data = skimage.io.imread(infile) with tempfile.NamedTemporaryFile(suffix='.j2k') as tfile: with self.assertRaises(IOError): - Jp2k(tfile.name, data=data, - cinema2k=48, cratios=[200, 100, 50]) + j = Jp2k(tfile.name, data=data, + cinema2k=48, cratios=[200, 100, 50]) def test_cinema4K_with_others(self): """Can't specify cinema4k with any other options.""" @@ -95,8 +98,8 @@ class WriteCinema(CinemaBase): data = skimage.io.imread(infile) with tempfile.NamedTemporaryFile(suffix='.j2k') as tfile: with self.assertRaises(IOError): - Jp2k(tfile.name, data=data, - cinema4k=True, cratios=[200, 100, 50]) + j = Jp2k(tfile.name, data=data, + cinema4k=True, cratios=[200, 100, 50]) @unittest.skipIf(WARNING_INFRASTRUCTURE_ISSUE, WARNING_INFRASTRUCTURE_MSG) @@ -132,8 +135,7 @@ class WriteCinemaWarns(CinemaBase): infile = opj_data_file(relfile) data = skimage.io.imread(infile) with tempfile.NamedTemporaryFile(suffix='.j2k') as tfile: - with self.assertWarnsRegex(UserWarning, - 'OpenJPEG library warning'): + with self.assertWarnsRegex(UserWarning, 'OpenJPEG library warning'): j = Jp2k(tfile.name, data=data, cinema2k=48) codestream = j.get_codestream() @@ -144,8 +146,7 @@ class WriteCinemaWarns(CinemaBase): infile = opj_data_file(relfile) data = skimage.io.imread(infile) with tempfile.NamedTemporaryFile(suffix='.j2k') as tfile: - with self.assertWarnsRegex(UserWarning, - 'OpenJPEG library warning'): + with self.assertWarnsRegex(UserWarning, 'OpenJPEG library warning'): j = Jp2k(tfile.name, data=data, cinema2k=48) codestream = j.get_codestream() @@ -156,8 +157,7 @@ class WriteCinemaWarns(CinemaBase): infile = opj_data_file(relfile) data = skimage.io.imread(infile) with tempfile.NamedTemporaryFile(suffix='.j2k') as tfile: - with self.assertWarnsRegex(UserWarning, - 'OpenJPEG library warning'): + with self.assertWarnsRegex(UserWarning, 'OpenJPEG library warning'): j = Jp2k(tfile.name, data=data, cinema2k=24) codestream = j.get_codestream() @@ -168,8 +168,7 @@ class WriteCinemaWarns(CinemaBase): infile = opj_data_file(relfile) data = skimage.io.imread(infile) with tempfile.NamedTemporaryFile(suffix='.j2k') as tfile: - with self.assertWarnsRegex(UserWarning, - 'OpenJPEG library warning'): + with self.assertWarnsRegex(UserWarning, 'OpenJPEG library warning'): # OpenJPEG library warning: The desired maximum codestream # size has limited at least one of the desired quality layers j = Jp2k(tfile.name, data=data, cinema2k=24) @@ -217,7 +216,7 @@ class TestNegative2pointzero(unittest.TestCase): with patch('glymur.version.openjpeg_version', new=version): with tempfile.NamedTemporaryFile(suffix='.j2k') as tfile: with self.assertRaises(IOError): - Jp2k(tfile.name, data=data, cinema2k=48) + j = Jp2k(tfile.name, data=data, cinema2k=48) @unittest.skipIf(re.match(r'''1.[0-4]''', openjpeg_version) is not None, @@ -249,6 +248,7 @@ class TestSuiteWrite(fixtures.MetadataBase): self.assertEqual(codestream.segment[2].spcod[8], glymur.core.WAVELET_XFORM_9X7_IRREVERSIBLE) + def test_NR_ENC_Bretagne1_ppm_1_encode(self): """NR-ENC-Bretagne1.ppm-1-encode""" infile = opj_data_file('input/nonregression/Bretagne1.ppm') @@ -260,11 +260,10 @@ class TestSuiteWrite(fixtures.MetadataBase): c = j.get_codestream() kwargs = {'rsiz': 0, 'xysiz': (640, 480), 'xyosiz': (0, 0), - 'xytsiz': (640, 480), 'xytosiz': (0, 0), - 'bitdepth': (8, 8, 8), 'signed': (False, False, False), - 'xyrsiz': [(1, 1, 1), (1, 1, 1)]} - self.verifySizSegment(c.segment[1], - glymur.codestream.SIZsegment(**kwargs)) + 'xytsiz': (640, 480), 'xytosiz': (0, 0), + 'bitdepth': (8, 8, 8), 'signed': (False, False, False), + 'xyrsiz': [(1, 1, 1), (1, 1, 1)]} + self.verifySizSegment(c.segment[1], glymur.codestream.SIZsegment(**kwargs)) # COD: Coding style default self.assertFalse(c.segment[2].scod & 2) # no sop @@ -276,7 +275,7 @@ class TestSuiteWrite(fixtures.MetadataBase): self.assertEqual(tuple(c.segment[2].code_block_size), (64, 64)) # cblksz 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], glymur.core.WAVELET_XFORM_5X3_REVERSIBLE) self.assertEqual(len(c.segment[2].spcod), 9) @@ -292,11 +291,10 @@ class TestSuiteWrite(fixtures.MetadataBase): codestream = j.get_codestream() kwargs = {'rsiz': 0, 'xysiz': (640, 480), 'xyosiz': (0, 0), - 'xytsiz': (640, 480), 'xytosiz': (0, 0), - 'bitdepth': (8, 8, 8), 'signed': (False, False, False), - 'xyrsiz': [(1, 1, 1), (1, 1, 1)]} - self.verifySizSegment(codestream.segment[1], - glymur.codestream.SIZsegment(**kwargs)) + 'xytsiz': (640, 480), 'xytosiz': (0, 0), + 'bitdepth': (8, 8, 8), 'signed': (False, False, False), + 'xyrsiz': [(1, 1, 1), (1, 1, 1)]} + self.verifySizSegment(codestream.segment[1], glymur.codestream.SIZsegment(**kwargs)) # COD: Coding style default self.assertFalse(codestream.segment[2].scod & 2) # no sop @@ -308,8 +306,7 @@ class TestSuiteWrite(fixtures.MetadataBase): self.assertEqual(tuple(codestream.segment[2].code_block_size), (64, 64)) # cblksz 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], glymur.core.WAVELET_XFORM_5X3_REVERSIBLE) self.assertEqual(len(codestream.segment[2].spcod), 9) @@ -319,19 +316,18 @@ class TestSuiteWrite(fixtures.MetadataBase): infile = opj_data_file('input/nonregression/Bretagne1.ppm') data = read_image(infile) with tempfile.NamedTemporaryFile(suffix='.j2k') as tfile: - j = Jp2k(tfile.name, - data=data, - psnr=[30, 35, 40], cbsize=(16, 16), psizes=[(64, 64)]) + j = Jp2k(tfile.name, + data=data, + psnr=[30, 35, 40], cbsize=(16, 16), psizes=[(64, 64)]) # Should be three layers. codestream = j.get_codestream() kwargs = {'rsiz': 0, 'xysiz': (640, 480), 'xyosiz': (0, 0), - 'xytsiz': (640, 480), 'xytosiz': (0, 0), - 'bitdepth': (8, 8, 8), 'signed': (False, False, False), - 'xyrsiz': [(1, 1, 1), (1, 1, 1)]} - self.verifySizSegment(codestream.segment[1], - glymur.codestream.SIZsegment(**kwargs)) + 'xytsiz': (640, 480), 'xytosiz': (0, 0), + 'bitdepth': (8, 8, 8), 'signed': (False, False, False), + 'xyrsiz': [(1, 1, 1), (1, 1, 1)]} + self.verifySizSegment(codestream.segment[1], glymur.codestream.SIZsegment(**kwargs)) # COD: Coding style default self.assertFalse(codestream.segment[2].scod & 2) # no sop @@ -343,8 +339,7 @@ class TestSuiteWrite(fixtures.MetadataBase): self.assertEqual(tuple(codestream.segment[2].code_block_size), (16, 16)) # cblksz 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], glymur.core.WAVELET_XFORM_5X3_REVERSIBLE) self.assertEqual(codestream.segment[2].precinct_size, @@ -357,21 +352,20 @@ class TestSuiteWrite(fixtures.MetadataBase): data = read_image(infile) with tempfile.NamedTemporaryFile(suffix='.j2k') as tfile: j = Jp2k(tfile.name, - data=data, - psizes=[(128, 128)] * 3, - cratios=[100, 20, 2], - tilesize=(480, 640), - cbsize=(32, 32)) + data=data, + psizes=[(128, 128)] * 3, + cratios=[100, 20, 2], + tileshape=(480, 640), + cbsize=(32, 32)) # Should be three layers. codestream = j.get_codestream() kwargs = {'rsiz': 0, 'xysiz': (2592, 1944), 'xyosiz': (0, 0), - 'xytsiz': (640, 480), 'xytosiz': (0, 0), - 'bitdepth': (8, 8, 8), 'signed': (False, False, False), - 'xyrsiz': [(1, 1, 1), (1, 1, 1)]} - self.verifySizSegment(codestream.segment[1], - glymur.codestream.SIZsegment(**kwargs)) + 'xytsiz': (640, 480), 'xytosiz': (0, 0), + 'bitdepth': (8, 8, 8), 'signed': (False, False, False), + 'xyrsiz': [(1, 1, 1), (1, 1, 1)]} + self.verifySizSegment(codestream.segment[1], glymur.codestream.SIZsegment(**kwargs)) # COD: Coding style default self.assertFalse(codestream.segment[2].scod & 2) # no sop @@ -383,8 +377,7 @@ class TestSuiteWrite(fixtures.MetadataBase): self.assertEqual(tuple(codestream.segment[2].code_block_size), (32, 32)) # cblksz 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], glymur.core.WAVELET_XFORM_5X3_REVERSIBLE) self.assertEqual(codestream.segment[2].precinct_size, @@ -395,16 +388,15 @@ class TestSuiteWrite(fixtures.MetadataBase): infile = opj_data_file('input/nonregression/Bretagne2.ppm') data = read_image(infile) with tempfile.NamedTemporaryFile(suffix='.j2k') as tfile: - j = Jp2k(tfile.name, data=data, tilesize=(127, 127), prog="PCRL") + j = Jp2k(tfile.name, data=data, tileshape=(127, 127), prog="PCRL") codestream = j.get_codestream() kwargs = {'rsiz': 0, 'xysiz': (2592, 1944), 'xyosiz': (0, 0), - 'xytsiz': (127, 127), 'xytosiz': (0, 0), - 'bitdepth': (8, 8, 8), 'signed': (False, False, False), - 'xyrsiz': [(1, 1, 1), (1, 1, 1)]} - self.verifySizSegment(codestream.segment[1], - glymur.codestream.SIZsegment(**kwargs)) + 'xytsiz': (127, 127), 'xytosiz': (0, 0), + 'bitdepth': (8, 8, 8), 'signed': (False, False, False), + 'xyrsiz': [(1, 1, 1), (1, 1, 1)]} + self.verifySizSegment(codestream.segment[1], glymur.codestream.SIZsegment(**kwargs)) # COD: Coding style default self.assertFalse(codestream.segment[2].scod & 2) # no sop @@ -416,8 +408,7 @@ class TestSuiteWrite(fixtures.MetadataBase): self.assertEqual(tuple(codestream.segment[2].code_block_size), (64, 64)) # cblksz 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], glymur.core.WAVELET_XFORM_5X3_REVERSIBLE) self.assertEqual(len(codestream.segment[2].spcod), 9) @@ -432,11 +423,10 @@ class TestSuiteWrite(fixtures.MetadataBase): codestream = j.get_codestream(header_only=False) kwargs = {'rsiz': 0, 'xysiz': (5183, 3887), 'xyosiz': (0, 0), - 'xytsiz': (5183, 3887), 'xytosiz': (0, 0), - 'bitdepth': (8, 8, 8), 'signed': (False, False, False), - 'xyrsiz': [(2, 2, 2), (2, 2, 2)]} - self.verifySizSegment(codestream.segment[1], - glymur.codestream.SIZsegment(**kwargs)) + 'xytsiz': (5183, 3887), 'xytosiz': (0, 0), + 'bitdepth': (8, 8, 8), 'signed': (False, False, False), + 'xyrsiz': [(2, 2, 2), (2, 2, 2)]} + self.verifySizSegment(codestream.segment[1], glymur.codestream.SIZsegment(**kwargs)) # COD: Coding style default self.assertTrue(codestream.segment[2].scod & 2) # sop @@ -448,8 +438,7 @@ class TestSuiteWrite(fixtures.MetadataBase): self.assertEqual(tuple(codestream.segment[2].code_block_size), (64, 64)) # cblksz 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], glymur.core.WAVELET_XFORM_5X3_REVERSIBLE) self.assertEqual(len(codestream.segment[2].spcod), 9) @@ -469,11 +458,10 @@ class TestSuiteWrite(fixtures.MetadataBase): codestream = j.get_codestream(header_only=False) kwargs = {'rsiz': 0, 'xysiz': (2592, 1944), 'xyosiz': (0, 0), - 'xytsiz': (2592, 1944), 'xytosiz': (0, 0), - 'bitdepth': (8, 8, 8), 'signed': (False, False, False), - 'xyrsiz': [(1, 1, 1), (1, 1, 1)]} - self.verifySizSegment(codestream.segment[1], - glymur.codestream.SIZsegment(**kwargs)) + 'xytsiz': (2592, 1944), 'xytosiz': (0, 0), + 'bitdepth': (8, 8, 8), 'signed': (False, False, False), + 'xyrsiz': [(1, 1, 1), (1, 1, 1)]} + self.verifySizSegment(codestream.segment[1], glymur.codestream.SIZsegment(**kwargs)) # COD: Coding style default self.assertFalse(codestream.segment[2].scod & 2) # no sop @@ -483,10 +471,9 @@ class TestSuiteWrite(fixtures.MetadataBase): self.assertEqual(codestream.segment[2].spcod[3], 1) # mct self.assertEqual(codestream.segment[2].spcod[4], 5) # levels self.assertEqual(tuple(codestream.segment[2].code_block_size), - (64, 64)) # cblksz + (64, 64)) # cblksz 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], glymur.core.WAVELET_XFORM_5X3_REVERSIBLE) self.assertEqual(len(codestream.segment[2].spcod), 9) @@ -501,16 +488,15 @@ class TestSuiteWrite(fixtures.MetadataBase): data = read_image(infile) with tempfile.NamedTemporaryFile(suffix='.j2k') as tfile: j = Jp2k(tfile.name, - data=data, grid_offset=[300, 150], cratios=[800]) + data=data, grid_offset=[300, 150], cratios=[800]) codestream = j.get_codestream(header_only=False) kwargs = {'rsiz': 0, 'xysiz': (2742, 2244), 'xyosiz': (150, 300), - 'xytsiz': (2742, 2244), 'xytosiz': (0, 0), - 'bitdepth': (8, 8, 8), 'signed': (False, False, False), - 'xyrsiz': [(1, 1, 1), (1, 1, 1)]} - self.verifySizSegment(codestream.segment[1], - glymur.codestream.SIZsegment(**kwargs)) + 'xytsiz': (2742, 2244), 'xytosiz': (0, 0), + 'bitdepth': (8, 8, 8), 'signed': (False, False, False), + 'xyrsiz': [(1, 1, 1), (1, 1, 1)]} + self.verifySizSegment(codestream.segment[1], glymur.codestream.SIZsegment(**kwargs)) # COD: Coding style default self.assertFalse(codestream.segment[2].scod & 2) # no sop @@ -522,8 +508,7 @@ class TestSuiteWrite(fixtures.MetadataBase): self.assertEqual(tuple(codestream.segment[2].code_block_size), (64, 64)) # cblksz 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], glymur.core.WAVELET_XFORM_5X3_REVERSIBLE) self.assertEqual(len(codestream.segment[2].spcod), 9) @@ -538,11 +523,10 @@ class TestSuiteWrite(fixtures.MetadataBase): codestream = j.get_codestream(header_only=False) kwargs = {'rsiz': 0, 'xysiz': (2592, 1944), 'xyosiz': (0, 0), - 'xytsiz': (2592, 1944), 'xytosiz': (0, 0), - 'bitdepth': (8, 8, 8), 'signed': (False, False, False), - 'xyrsiz': [(1, 1, 1), (1, 1, 1)]} - self.verifySizSegment(codestream.segment[1], - glymur.codestream.SIZsegment(**kwargs)) + 'xytsiz': (2592, 1944), 'xytosiz': (0, 0), + 'bitdepth': (8, 8, 8), 'signed': (False, False, False), + 'xyrsiz': [(1, 1, 1), (1, 1, 1)]} + self.verifySizSegment(codestream.segment[1], glymur.codestream.SIZsegment(**kwargs)) # COD: Coding style default self.assertFalse(codestream.segment[2].scod & 2) # no sop @@ -554,8 +538,7 @@ class TestSuiteWrite(fixtures.MetadataBase): self.assertEqual(tuple(codestream.segment[2].code_block_size), (64, 64)) # cblksz 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], glymur.core.WAVELET_XFORM_5X3_REVERSIBLE) self.assertEqual(len(codestream.segment[2].spcod), 9) @@ -570,11 +553,10 @@ class TestSuiteWrite(fixtures.MetadataBase): codestream = j.get_codestream(header_only=False) kwargs = {'rsiz': 0, 'xysiz': (640, 480), 'xyosiz': (0, 0), - 'xytsiz': (640, 480), 'xytosiz': (0, 0), - 'bitdepth': (8, 8, 8), 'signed': (False, False, False), - 'xyrsiz': [(1, 1, 1), (1, 1, 1)]} - self.verifySizSegment(codestream.segment[1], - glymur.codestream.SIZsegment(**kwargs)) + 'xytsiz': (640, 480), 'xytosiz': (0, 0), + 'bitdepth': (8, 8, 8), 'signed': (False, False, False), + 'xyrsiz': [(1, 1, 1), (1, 1, 1)]} + self.verifySizSegment(codestream.segment[1], glymur.codestream.SIZsegment(**kwargs)) # COD: Coding style default self.assertFalse(codestream.segment[2].scod & 2) # no sop @@ -586,8 +568,7 @@ class TestSuiteWrite(fixtures.MetadataBase): self.assertEqual(tuple(codestream.segment[2].code_block_size), (64, 64)) # cblksz 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], glymur.core.WAVELET_XFORM_5X3_REVERSIBLE) self.assertEqual(len(codestream.segment[2].spcod), 9) @@ -597,7 +578,7 @@ class TestSuiteWrite(fixtures.MetadataBase): data = read_image(opj_data_file('input/nonregression/Rome.bmp')) with tempfile.NamedTemporaryFile(suffix='.jp2') as tfile: jp2 = Jp2k(tfile.name, - data=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] self.assertEqual(ids, ['jP ', 'ftyp', 'jp2h', 'jp2c']) @@ -632,14 +613,13 @@ class TestSuiteWrite(fixtures.MetadataBase): self.assertIsNone(jp2.box[2].box[1].icc_profile) self.assertEqual(jp2.box[2].box[1].colorspace, glymur.core.SRGB) - codestream = jp2.box[3].codestream + codestream = jp2.box[3].main_header kwargs = {'rsiz': 0, 'xysiz': (640, 480), 'xyosiz': (0, 0), - 'xytsiz': (640, 480), 'xytosiz': (0, 0), - 'bitdepth': (8, 8, 8), 'signed': (False, False, False), - 'xyrsiz': [(1, 1, 1), (1, 1, 1)]} - self.verifySizSegment(codestream.segment[1], - glymur.codestream.SIZsegment(**kwargs)) + 'xytsiz': (640, 480), 'xytosiz': (0, 0), + 'bitdepth': (8, 8, 8), 'signed': (False, False, False), + 'xyrsiz': [(1, 1, 1), (1, 1, 1)]} + self.verifySizSegment(codestream.segment[1], glymur.codestream.SIZsegment(**kwargs)) # COD: Coding style default self.assertFalse(codestream.segment[2].scod & 2) # no sop @@ -651,8 +631,7 @@ class TestSuiteWrite(fixtures.MetadataBase): self.assertEqual(tuple(codestream.segment[2].code_block_size), (64, 64)) # cblksz 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], glymur.core.WAVELET_XFORM_5X3_REVERSIBLE) self.assertEqual(len(codestream.segment[2].spcod), 9) @@ -669,11 +648,10 @@ class TestSuiteWrite(fixtures.MetadataBase): codestream = j.get_codestream(header_only=False) kwargs = {'rsiz': 0, 'xysiz': (1024, 1024), 'xyosiz': (0, 0), - 'xytsiz': (1024, 1024), 'xytosiz': (0, 0), - 'bitdepth': (16,), 'signed': (False,), - 'xyrsiz': [(1,), (1,)]} - self.verifySizSegment(codestream.segment[1], - glymur.codestream.SIZsegment(**kwargs)) + 'xytsiz': (1024, 1024), 'xytosiz': (0, 0), + 'bitdepth': (16,), 'signed': (False,), + 'xyrsiz': [(1,), (1,)]} + self.verifySizSegment(codestream.segment[1], glymur.codestream.SIZsegment(**kwargs)) # COD: Coding style default self.assertFalse(codestream.segment[2].scod & 2) # no sop @@ -685,8 +663,7 @@ class TestSuiteWrite(fixtures.MetadataBase): self.assertEqual(tuple(codestream.segment[2].code_block_size), (64, 64)) # cblksz 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], glymur.core.WAVELET_XFORM_5X3_REVERSIBLE) self.assertEqual(len(codestream.segment[2].spcod), 9) diff --git a/glymur/test/test_printing.py b/glymur/test/test_printing.py index bccaa00..5eedfe5 100644 --- a/glymur/test/test_printing.py +++ b/glymur/test/test_printing.py @@ -1,6 +1,15 @@ # -*- coding: utf-8 -*- """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 re import struct @@ -23,12 +32,11 @@ import lxml.etree as ET import glymur from glymur import Jp2k, command_line from . import fixtures -from .fixtures import (OPJ_DATA_ROOT, opj_data_file, - WARNING_INFRASTRUCTURE_ISSUE, - WARNING_INFRASTRUCTURE_MSG, - WINDOWS_TMP_FILE_MSG, - text_gbr_27, text_gbr_33, text_gbr_34) - +from .fixtures import ( + OPJ_DATA_ROOT, opj_data_file, + WARNING_INFRASTRUCTURE_ISSUE, WARNING_INFRASTRUCTURE_MSG, + WINDOWS_TMP_FILE_MSG, text_gbr_27, text_gbr_33, text_gbr_34 +) @unittest.skipIf(os.name == "nt", WINDOWS_TMP_FILE_MSG) class TestPrinting(unittest.TestCase): @@ -42,13 +50,25 @@ class TestPrinting(unittest.TestCase): glymur.set_printoptions(short=False, xml=True, codestream=True) def tearDown(self): - glymur.set_parseoptions(full_codestream=False) + pass + + 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): """Should be able to print(glymur.version.info)""" with patch('sys.stdout', new=StringIO()) as fake_out: print(glymur.version.info) - fake_out.getvalue().strip() + actual = fake_out.getvalue().strip() self.assertTrue(True) @@ -58,7 +78,7 @@ class TestPrinting(unittest.TestCase): with tempfile.NamedTemporaryFile(suffix='.jpx') as tfile: with open(self.jpxfile, 'rb') as ifile: tfile.write(ifile.read()) - + # Add the header for an unknown superbox. write_buffer = struct.pack('>I4s', 20, 'grp '.encode()) tfile.write(write_buffer) @@ -87,8 +107,7 @@ class TestPrinting(unittest.TestCase): with self.assertRaises(TypeError): glymur.set_printoptions(hi='low') - @unittest.skipIf(re.match("1.5|2", - glymur.version.openjpeg_version) is None, + @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): """verify printing of asoc, label boxes""" @@ -96,8 +115,9 @@ class TestPrinting(unittest.TestCase): # OpenJPEG doesn't have such a file. data = glymur.Jp2k(self.jp2file)[::2, ::2] with tempfile.NamedTemporaryFile(suffix='.jp2') as tfile: + j = glymur.Jp2k(tfile.name, data=data) + with tempfile.NamedTemporaryFile(suffix='.jp2') as tfile2: - glymur.Jp2k(tfile.name, data=data) # Offset of the codestream is where we start. wbuffer = tfile.read(77) @@ -399,7 +419,7 @@ class TestPrinting(unittest.TestCase): @unittest.skipIf(sys.hexversion < 0x03000000, "Only trusting python3 for printing non-ascii chars") def test_xml_cyrrilic(self): - """Should be able to print XMLBox with utf-8 encoding (cyrrillic).""" + """Should be able to print an XMLBox with utf-8 encoding (cyrrillic).""" # Seems to be inconsistencies between different versions of python2.x # as to what gets printed. # @@ -417,8 +437,7 @@ class TestPrinting(unittest.TestCase): actual = fake_out.getvalue().strip() if sys.hexversion < 0x03000000: lines = ["XML Box (xml ) @ (-1, 0)", - (" Росс", - "ия")] + " Россия"] else: lines = ["XML Box (xml ) @ (-1, 0)", " Россия"] @@ -594,14 +613,12 @@ class TestPrinting(unittest.TestCase): lines = ["UUID Box (uuid) @ (1135519, 76)", " 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) self.assertEqual(actual, expected) - @unittest.skipIf(OPJ_DATA_ROOT is None, "OPJ_DATA_ROOT environment variable not set") @unittest.skipIf(os.name == "nt", "Temporary file issue on window.") @@ -809,7 +826,6 @@ class TestPrintingOpjDataRoot(unittest.TestCase): expected = '\n'.join(lines) self.assertEqual(actual, expected) - @unittest.skipIf(OPJ_DATA_ROOT is None, "OPJ_DATA_ROOT environment variable not set") @unittest.skipIf(os.name == "nt", "Temporary file issue on window.") @@ -831,31 +847,20 @@ class TestPrintingOpjDataRootWarns(unittest.TestCase): def tearDown(self): 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): """An invalid colorspace shouldn't cause an error.""" filename = opj_data_file('input/nonregression/edf_c2_1103421.jp2') with self.assertWarns(UserWarning): jp2 = Jp2k(filename) - with patch('sys.stdout', new=StringIO()): + with patch('sys.stdout', new=StringIO()) as fake_out: print(jp2) def test_bad_rsiz(self): """Should still be able to print if rsiz is bad, issue196""" filename = opj_data_file('input/nonregression/edf_c2_1002767.jp2') with self.assertWarns(UserWarning): - j = Jp2k(filename).get_codestream() - with patch('sys.stdout', new=StringIO()): + j = Jp2k(filename) + with patch('sys.stdout', new=StringIO()) as fake_out: print(j) def test_bad_wavelet_transform(self): @@ -863,7 +868,7 @@ class TestPrintingOpjDataRootWarns(unittest.TestCase): filename = opj_data_file('input/nonregression/edf_c2_10025.jp2') with self.assertWarns(UserWarning): jp2 = Jp2k(filename) - with patch('sys.stdout', new=StringIO()): + with patch('sys.stdout', new=StringIO()) as fake_out: print(jp2) def test_invalid_progression_order(self): @@ -1024,7 +1029,7 @@ class TestPrintingOpjDataRootWarns(unittest.TestCase): 'issue171.jp2')) with self.assertWarns(UserWarning): jp2 = Jp2k(filename) - with patch('sys.stdout', new=StringIO()): + with patch('sys.stdout', new=StringIO()) as fake_out: # No need to verify, it's enough that we don't error out. print(jp2) @@ -1040,10 +1045,9 @@ class TestJp2dump(unittest.TestCase): # Reset printoptions for every test. glymur.set_printoptions(short=False, xml=True, codestream=True) - glymur.set_parseoptions(full_codestream=False) def tearDown(self): - glymur.set_parseoptions(full_codestream=False) + pass def run_jp2dump(self, args): sys.argv = args @@ -1056,53 +1060,24 @@ class TestJp2dump(unittest.TestCase): return actual def test_default_nemo(self): - """by default one should get the main header""" + """Should be able to dump a JP2 file's metadata with no codestream.""" actual = self.run_jp2dump(['', self.jp2file]) - # shave off the non-main-header segments - lines = fixtures.nemo.split('\n') - expected = lines[0:140] - expected = '\n'.join(expected) - self.assertEqual(actual, expected) + self.assertEqual(actual, fixtures.nemo_dump_no_codestream) - def test_jp2_codestream_0(self): + def test_codestream_0(self): """Verify dumping with -c 0, supressing all codestream details.""" actual = self.run_jp2dump(['', '-c', '0', self.jp2file]) - # shave off the codestream details - lines = fixtures.nemo.split('\n') - expected = lines[0:105] - expected = '\n'.join(expected) - self.assertEqual(actual, expected) + self.assertEqual(actual, fixtures.nemo_dump_no_codestream) - def test_jp2_codestream_1(self): + def test_codestream_1(self): """Verify dumping with -c 1, print just the header.""" actual = self.run_jp2dump(['', '-c', '1', self.jp2file]) - # shave off the non-main-header segments - lines = fixtures.nemo.split('\n') - expected = lines[0:140] - expected = '\n'.join(expected) - self.assertEqual(actual, expected) + self.assertEqual(actual, fixtures.nemo_with_codestream_header) - 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): + def test_codestream_2(self): """Verify dumping with -c 2, full details.""" with patch('sys.stdout', new=StringIO()) as fake_out: sys.argv = ['', '-c', '2', self.j2kfile] @@ -1127,9 +1102,14 @@ class TestJp2dump(unittest.TestCase): """Verify dumping with -x, suppress XML.""" actual = self.run_jp2dump(['', '-x', self.jp2file]) - # 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) + self.assertEqual(actual, fixtures.nemo_dump_no_codestream_no_xml) + + @unittest.skipIf(sys.hexversion < 0x03000000, "assertRegex not in 2.7") + def test_codestream_0_with_j2k_file(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: .*") + diff --git a/glymur/version.py b/glymur/version.py index 4096ee5..55e4b88 100644 --- a/glymur/version.py +++ b/glymur/version.py @@ -18,7 +18,7 @@ from .lib import openjpeg as opj, openjp2 as opj2 # Do not change the format of this next line! Doing so risks breaking # setup.py -version = "0.8.0" +version = "0.7.2" _sv = LooseVersion(version) version_tuple = _sv.version diff --git a/setup.py b/setup.py index b49ed69..1a61dc3 100644 --- a/setup.py +++ b/setup.py @@ -1,4 +1,4 @@ -from setuptools import setup +from setuptools import setup, find_packages import os import re import sys @@ -11,20 +11,18 @@ kwargs = {'name': 'Glymur', 'url': 'https://github.com/quintusdias/glymur', 'packages': ['glymur', 'glymur.data', 'glymur.test', 'glymur.lib', 'glymur.lib.test'], - 'package_data': {'glymur': ['data/*.jp2', - 'data/*.j2k', - 'data/*.jpx']}, + 'package_data': {'glymur': ['data/*.jp2', 'data/*.j2k', 'data/*.jpx']}, 'entry_points': { 'console_scripts': ['jp2dump=glymur.command_line:main'], }, 'license': 'MIT', 'test_suite': 'glymur.test'} -install_requires = ['numpy>=1.7.0', 'lxml>=3.0.0'] +instllrqrs = ['numpy>=1.4.1', 'lxml>=2.3.2'] if sys.hexversion < 0x03030000: - install_requires.append('contextlib2>=0.4') - install_requires.append('mock>=1.0.1') -kwargs['install_requires'] = install_requires + instllrqrs.append('contextlib2>=0.4') + instllrqrs.append('mock>=1.0.1') +kwargs['install_requires'] = instllrqrs clssfrs = ["Programming Language :: Python", "Programming Language :: Python :: 2.7",