From edde7d36b13d90a7fd399ee02cde0f1e7fd45a90 Mon Sep 17 00:00:00 2001 From: jevans Date: Fri, 17 Oct 2014 22:51:14 -0400 Subject: [PATCH 01/57] refactored private methods used by Jp2k write method, closes #269 --- glymur/jp2k.py | 357 ++++++++++++++++++++----------------------------- 1 file changed, 148 insertions(+), 209 deletions(-) diff --git a/glymur/jp2k.py b/glymur/jp2k.py index d460ea6..94a37ee 100644 --- a/glymur/jp2k.py +++ b/glymur/jp2k.py @@ -45,6 +45,11 @@ JP2_IDS = ['colr', 'cdef', 'cmap', 'jp2c', 'ftyp', 'ihdr', 'jp2h', 'jP ', 'uuid'] JPX_IDS = ['asoc', 'nlst'] +_COLORSPACE_MAP = {'rgb': opj2.CLRSPC_SRGB, + 'gray': opj2.CLRSPC_GRAY, + 'grey': opj2.CLRSPC_GRAY, + 'ycc': opj2.CLRSPC_YCC} + class Jp2k(Jp2kBox): """JPEG 2000 file. @@ -74,6 +79,7 @@ class Jp2k(Jp2kBox): self.mode = mode self.box = [] self._codec_format = None + self._colorspace = None # Parse the file for JP2/JPX contents only if we are reading it. if mode == 'rb': @@ -167,11 +173,14 @@ class Jp2k(Jp2kBox): fps : int Frames per second, should be either 24 or 48. """ - if re.match("(1.5|2.0.0)", version.openjpeg_version) is not None: + if re.match("1.5|2.0.0", version.openjpeg_version) is not None: msg = "Writing Cinema2K or Cinema4K files is not supported with " msg += 'openjpeg library versions less than 2.0.1.' raise IOError(msg) + # Cinema modes imply MCT. + cparams.tcp_mct = 1 + if cinema_mode == 'cinema2k': if fps not in [24, 48]: raise IOError('Cinema2K frame rate must be either 24 or 48.') @@ -204,52 +213,30 @@ class Jp2k(Jp2kBox): return - def _populate_cparams(self, **kwargs): - """Populate compression parameters structure from input arguments. + def _populate_cparams(self, img_array, **kwargs): + """Directs processing of write method arguments. Parameters ---------- - cbsize : tuple, optional - Code block size (DY, DX). - cratios : iterable - Compression ratios for successive layers. - eph : bool, optional - If true, write SOP marker after each header packet. - grid_offset : tuple, optional - Offset (DY, DX) of the origin of the image in the reference grid. - mct : bool, optional - Specifies usage of the multi component transform. If not - specified, defaults to True if the colorspace is RGB. - modesw : int, optional - Mode switch. - 1 = BYPASS(LAZY) - 2 = RESET - 4 = RESTART(TERMALL) - 8 = VSC - 16 = ERTERM(SEGTERM) - 32 = SEGMARK(SEGSYM) - numres : int, optional - Number of resolutions. - prog : str, optional - Progression order, one of "LRCP" "RLCP", "RPCL", "PCRL", "CPRL". - psnr : iterable, optional - Different PSNR for successive layers. - psizes : list, optional - List of precinct sizes. Each precinct size tuple is defined in - (height x width). - sop : bool, optional - If true, write SOP marker before each packet. - subsam : tuple, optional - Subsampling factors (dy, dx). - tilesize : tuple, optional - Numeric tuple specifying tile size in terms of (numrows, numcols), - not (X, Y). + img_array : ndarray + image data to be written to file + kwargs : dictionary + non-image keyword inputs provided to write method Returns ------- cparams : CompressionParametersType(ctypes.Structure) - Corresponds to cparameters_t type in openjp2 headers. + corresponds to cparameters_t openjpeg datatype """ + if (('cinema2k' in kwargs or 'cinema4k' in kwargs) and + (len(set(kwargs)) > 1)): + msg = "Cannot specify cinema2k/cinema4k along with other options." + raise IOError(msg) + + if 'cratios' in kwargs and 'psnr' in kwargs: + msg = "Cannot specify cratios and psnr together." + raise IOError(msg) + if version.openjpeg_version_tuple[0] == 1: cparams = opj.set_default_encoder_parameters() else: @@ -336,49 +323,9 @@ class Jp2k(Jp2kBox): cparams.cp_tdy = kwargs['tilesize'][0] cparams.tile_size_on = opj2.TRUE - return cparams - - def _process_write_inputs(self, img_array, colorspace=None, **kwargs): - """Directs processing of write method arguments. - - It's somewhat awkward to process all the kwargs arguments at once. - The "colorspace" is not a parameter that gets processed into the - compression parameters structure, and it unfortunately must be handled - in the middle of the compression parameter processing. - - Parameters - ---------- - img_array : ndarray - Image data to be written to file. - colorspace : str, optional - Either 'rgb' or 'gray'. - - Returns - ------- - cparams : CompressionParametersType(ctypes.Structure) - Corresponds to cparameters_t type in openjp2 headers. - colorspace : int - Either CLRSPC_SRGB or CLRSPC_GRAY - """ - if (('cinema2k' in kwargs or 'cinema4k' in kwargs) and - (len(set(kwargs)) > 1)): - msg = "Cannot specify cinema2k/cinema4k along with other options." - raise IOError(msg) - - if 'cratios' in kwargs and 'psnr' in kwargs: - msg = "Cannot specify cratios and psnr together." - raise IOError(msg) - - cparams = self._populate_cparams(**kwargs) - _validate_compression_params(img_array, cparams) - - colorspace = _unpack_colorspace(colorspace, img_array, cparams) - try: mct = kwargs['mct'] - if mct and colorspace == opj2.CLRSPC_GRAY: - # Cannot check for this in the validate routine, as we need - # to know what the target colorspace has been determined to be. + if mct and self._colorspace == opj2.CLRSPC_GRAY: msg = "Cannot specify usage of the multi component transform " msg += "if the colorspace is gray." raise IOError(msg) @@ -386,12 +333,14 @@ class Jp2k(Jp2kBox): except KeyError: # If the multi component transform was not specified, we infer # that it should be used if the color space is RGB. - if colorspace == opj2.CLRSPC_SRGB: + if self._colorspace == opj2.CLRSPC_SRGB: cparams.tcp_mct = 1 else: cparams.tcp_mct = 0 - return cparams, colorspace + self._validate_compression_params(img_array, cparams, **kwargs) + + return cparams def write(self, img_array, verbose=False, **kwargs): """Write image data to a JP2/JPX/J2k file. Intended usage of the @@ -466,21 +415,23 @@ class Jp2k(Jp2kBox): glymur.LibraryNotFoundError If glymur is unable to load the openjp2 library. """ - if opj2.OPENJP2 is not None: - self._write_openjp2(img_array, verbose=verbose, **kwargs) - elif opj.OPENJPEG is not None: - self._write_openjpeg(img_array, verbose=verbose, **kwargs) - else: + if opj2.OPENJP2 is None and opj.OPENJPEG is None: raise LibraryNotFoundError("You must have at least version 1.5 of " "OpenJPEG before using this " "functionality.") - def _write_openjpeg(self, img_array, verbose=False, **kwargs): + self._determine_colorspace(img_array, **kwargs) + cparams = self._populate_cparams(img_array, **kwargs) + + if opj2.OPENJP2 is not None: + self._write_openjp2(img_array, cparams, verbose=verbose) + else: + self._write_openjpeg(img_array, cparams, verbose=verbose) + + def _write_openjpeg(self, img_array, cparams, verbose=False): """ Write JPEG 2000 file using OpenJPEG 1.5 interface. """ - cparams, colorspace = self._process_write_inputs(img_array, **kwargs) - if img_array.ndim == 2: # Force the image to be 3D. Just makes things easier later on. img_array = img_array.reshape(img_array.shape[0], @@ -490,7 +441,7 @@ class Jp2k(Jp2kBox): comptparms = _populate_comptparms(img_array, cparams) with ExitStack() as stack: - image = opj.image_create(comptparms, colorspace) + image = opj.image_create(comptparms, self._colorspace) stack.callback(opj.image_destroy, image) numrows, numcols, numlayers = img_array.shape @@ -542,13 +493,114 @@ class Jp2k(Jp2kBox): self.parse() + def _validate_compression_params(self, img_array, cparams, **kwargs): + """Check that the compression parameters are valid. - def _write_openjp2(self, img_array, verbose=False, **kwargs): + Parameters + ---------- + img_array : ndarray + Image data to be written to file. + cparams : CompressionParametersType(ctypes.Structure) + Corresponds to cparameters_t type in openjp2 headers. """ - Write JPEG 2000 file using OpenJPEG 2.0 interface. - """ - cparams, colorspace = self._process_write_inputs(img_array, **kwargs) + # Cannot specify a colorspace with J2K. + if cparams.codec_fmt == opj2.CODEC_J2K and 'colorspace' in kwargs: + msg = 'Do not specify a colorspace when writing a raw ' + msg += 'codestream.' + raise IOError(msg) + # Code block size + code_block_specified = False + if cparams.cblockw_init != 0 and cparams.cblockh_init != 0: + # These fields ARE zero if uninitialized. + width = cparams.cblockw_init + height = cparams.cblockh_init + code_block_specified = True + if height * width > 4096 or height < 4 or width < 4: + msg = "Code block area cannot exceed 4096. " + msg += "Code block height and width must be larger than 4." + raise IOError(msg) + if ((math.log(height, 2) != math.floor(math.log(height, 2)) or + math.log(width, 2) != math.floor(math.log(width, 2)))): + msg = "Bad code block size ({0}, {1}), " + msg += "must be powers of 2." + raise IOError(msg.format(height, width)) + + # Precinct size + if cparams.res_spec != 0: + # precinct size was not specified if this field is zero. + for j in range(cparams.res_spec): + prch = cparams.prch_init[j] + prcw = cparams.prcw_init[j] + if j == 0 and code_block_specified: + height, width = cparams.cblockh_init, cparams.cblockw_init + if height * 2 > prch or width * 2 > prcw: + msg = "Highest Resolution precinct size must be at " + msg += "least twice that of the code block dimensions." + raise IOError(msg) + if ((math.log(prch, 2) != math.floor(math.log(prch, 2)) or + math.log(prcw, 2) != math.floor(math.log(prcw, 2)))): + msg = "Bad precinct sizes ({0}, {1}), " + msg += "must be powers of 2." + raise IOError(msg.format(prch, prcw)) + + # 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 images are currently supported." + raise RuntimeError(msg) + + def _determine_colorspace(self, img_array, colorspace=None, **kwargs): + """Determine the colorspace from the supplied inputs. + + Parameters + ---------- + img_array : ndarray + Image data to be written to file. + colorspace : str, optional + Either 'rgb' or 'gray'. + """ + if colorspace is None: + # Must infer the colorspace from the image dimensions. + if img_array.ndim < 3: + # A single channel image is grayscale. + self._colorspace = opj2.CLRSPC_GRAY + elif img_array.shape[2] == 1 or img_array.shape[2] == 2: + # A single channel image or an image with two channels is going + # to be greyscale. + self._colorspace = opj2.CLRSPC_GRAY + else: + # Anything else must be RGB, right? + self._colorspace = opj2.CLRSPC_SRGB + else: + if colorspace.lower() not in ('rgb', 'grey', 'gray'): + msg = 'Invalid colorspace "{0}"'.format(colorspace) + raise IOError(msg) + elif colorspace.lower() == 'rgb' and img_array.shape[2] < 3: + msg = 'RGB colorspace requires at least 3 components.' + raise IOError(msg) + + # Turn the colorspace from a string to the enumerated value that + # the library expects. + self._colorspace = _COLORSPACE_MAP[colorspace.lower()] + + + def _write_openjp2(self, img_array, cparams, verbose=False): + """ + Write JPEG 2000 file using OpenJPEG 2.x interface. + """ if img_array.ndim == 2: # Force the image to be 3D. Just makes things easier later on. numrows, numcols = img_array.shape @@ -557,7 +609,7 @@ class Jp2k(Jp2kBox): comptparms = _populate_comptparms(img_array, cparams) with ExitStack() as stack: - image = opj2.image_create(comptparms, colorspace) + image = opj2.image_create(comptparms, self._colorspace) stack.callback(opj2.image_destroy, image) _populate_image_struct(cparams, image, img_array) @@ -1674,50 +1726,6 @@ def extract_image_bands(image): return data -def _unpack_colorspace(colorspace, img_array, cparams): - """Determine the colorspace from the supplied inputs. - - Parameters - ---------- - colorspace : int - Either CLRSPC_SRGB or CLRSPC_GRAY - img_array : ndarray - Image data to be written to file. - cparams : CompressionParametersType(ctypes.Structure) - Corresponds to cparameters_t type in openjp2 headers. - """ - if colorspace is None: - # Must infer the colorspace from the image dimensions. - if img_array.ndim < 3: - # A single channel image is grayscale. - colorspace = opj2.CLRSPC_GRAY - elif img_array.shape[2] == 1 or img_array.shape[2] == 2: - # A single channel image or an image with two channels is going - # to be greyscale. - colorspace = opj2.CLRSPC_GRAY - else: - # Anything else must be RGB, right? - colorspace = opj2.CLRSPC_SRGB - else: - # Supplied a string colorspace, so we must validate it. - if cparams.codec_fmt == opj2.CODEC_J2K: - msg = 'Do not specify a colorspace when writing a raw ' - msg += 'codestream.' - raise IOError(msg) - if colorspace.lower() not in ('rgb', 'grey', 'gray'): - msg = 'Invalid colorspace "{0}"'.format(colorspace) - raise IOError(msg) - elif colorspace.lower() == 'rgb' and img_array.shape[2] < 3: - msg = 'RGB colorspace requires at least 3 components.' - raise IOError(msg) - - # Turn the colorspace from a string to the enumerated value that - # the library expects. - colorspace = _COLORSPACE_MAP[colorspace.lower()] - - return colorspace - - def _populate_comptparms(img_array, cparams): """Instantiate and populate comptparms structure. @@ -1805,75 +1813,6 @@ def _populate_image_struct(cparams, image, imgdata): return image -def _validate_compression_params(img_array, cparams): - """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. - """ - - # Code block size - code_block_specified = False - if cparams.cblockw_init != 0 and cparams.cblockh_init != 0: - # These fields ARE zero if uninitialized. - width = cparams.cblockw_init - height = cparams.cblockh_init - code_block_specified = True - if height * width > 4096 or height < 4 or width < 4: - msg = "Code block area cannot exceed 4096. " - msg += "Code block height and width must be larger than 4." - raise IOError(msg) - if ((math.log(height, 2) != math.floor(math.log(height, 2)) or - math.log(width, 2) != math.floor(math.log(width, 2)))): - msg = "Bad code block size ({0}, {1}), " - msg += "must be powers of 2." - raise IOError(msg.format(height, width)) - - # Precinct size - if cparams.res_spec != 0: - # precinct size was not specified if this field is zero. - for j in range(cparams.res_spec): - prch = cparams.prch_init[j] - prcw = cparams.prcw_init[j] - if j == 0 and code_block_specified: - height, width = cparams.cblockh_init, cparams.cblockw_init - if height * 2 > prch or width * 2 > prcw: - msg = "Highest Resolution precinct size must be at " - msg += "least twice that of the code block dimensions." - raise IOError(msg) - if ((math.log(prch, 2) != math.floor(math.log(prch, 2)) or - math.log(prcw, 2) != math.floor(math.log(prcw, 2)))): - msg = "Bad precinct sizes ({0}, {1}), " - msg += "must be powers of 2." - raise IOError(msg.format(prch, prcw)) - - # 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 images are currently supported." - raise RuntimeError(msg) - -_COLORSPACE_MAP = {'rgb': opj2.CLRSPC_SRGB, - 'gray': opj2.CLRSPC_GRAY, - 'grey': opj2.CLRSPC_GRAY, - 'ycc': opj2.CLRSPC_YCC} - # Setup the default callback handlers. See the callback functions subsection # in the ctypes section of the Python documentation for a solid explanation of # what's going on here. From b500287700e4e30df3184f7adcc0973d05abb5a0 Mon Sep 17 00:00:00 2001 From: jevans Date: Sat, 18 Oct 2014 10:45:07 -0400 Subject: [PATCH 02/57] improved LibraryNotFoundError messages, docstring information, closes #270, #272 --- glymur/jp2k.py | 25 +++++++++++-------------- 1 file changed, 11 insertions(+), 14 deletions(-) diff --git a/glymur/jp2k.py b/glymur/jp2k.py index 94a37ee..fc877f4 100644 --- a/glymur/jp2k.py +++ b/glymur/jp2k.py @@ -412,8 +412,8 @@ class Jp2k(Jp2kBox): Raises ------ - glymur.LibraryNotFoundError - If glymur is unable to load the openjp2 library. + glymur.jp2k.LibraryNotFoundError + if glymur is unable to load an openjpeg library suitable for writing """ if opj2.OPENJP2 is None and opj.OPENJPEG is None: raise LibraryNotFoundError("You must have at least version 1.5 of " @@ -963,9 +963,8 @@ class Jp2k(Jp2kBox): Raises ------ - glymur.LibraryNotFoundError - If glymur is unable to load either the openjpeg or openjp2 - libraries. + glymur.jp2k.LibraryNotFoundError + if glymur is unable to load an openjpeg library suitable for reading IOError If the image has differing subsample factors. @@ -984,15 +983,13 @@ class Jp2k(Jp2kBox): >>> thumbnail.shape (728, 1296, 3) """ + if opj2.OPENJP2 is None and opj.OPENJPEG is None: + raise LibraryNotFoundError("Cannot load the OpenJPEG library.") + if opj2.OPENJP2 is not None: img = self._read_openjp2(**kwargs) - elif opj.OPENJPEG is not None: - img = self._read_openjpeg(**kwargs) else: - raise LibraryNotFoundError("You must have either a recent version " - "of OpenJPEG or the development " - "version of OpenJP2 installed before " - "using this functionality.") + img = self._read_openjpeg(**kwargs) return img def _subsampling_sanity_check(self): @@ -1282,12 +1279,12 @@ class Jp2k(Jp2kBox): Raises ------ - glymur.LibraryNotFoundError - If glymur is unable to load the openjp2 library. + glymur.jp2k.LibraryNotFoundError + if glymur is unable to load an openjpeg library suitable for reading """ if version.openjpeg_version_tuple[0] < 2: raise LibraryNotFoundError("You must have at least version 2.0.0 " - "of OpenJP2 installed before using " + "of OpenJPEG installed before using " "this functionality.") dparam = self._populate_dparam(rlevel, ignore_pclr_cmap_cdef, From f36c169f52eb4ea2d42eb785303602135e3bb99c Mon Sep 17 00:00:00 2001 From: jevans Date: Sat, 18 Oct 2014 19:52:22 -0400 Subject: [PATCH 03/57] raise RuntimeError if writing with library version is too early, closes #273 We still raise a LibraryNotFoundError if there's no library at all --- glymur/jp2k.py | 8 +++++--- glymur/test/test_jp2k.py | 34 +++++++++++++++++++++++++--------- 2 files changed, 30 insertions(+), 12 deletions(-) diff --git a/glymur/jp2k.py b/glymur/jp2k.py index fc877f4..6b95cc1 100644 --- a/glymur/jp2k.py +++ b/glymur/jp2k.py @@ -415,10 +415,12 @@ class Jp2k(Jp2kBox): glymur.jp2k.LibraryNotFoundError if glymur is unable to load an openjpeg library suitable for writing """ + if re.match("1.[0-4]", version.openjpeg_version) is not None: + raise RuntimeError("You must have at least version 1.5 of OpenJPEG " + "in order to write images.") + if opj2.OPENJP2 is None and opj.OPENJPEG is None: - raise LibraryNotFoundError("You must have at least version 1.5 of " - "OpenJPEG before using this " - "functionality.") + raise LibraryNotFoundError("Cannot load the OpenJPEG library.") self._determine_colorspace(img_array, **kwargs) cparams = self._populate_cparams(img_array, **kwargs) diff --git a/glymur/test/test_jp2k.py b/glymur/test/test_jp2k.py index 042a681..6c92ff9 100644 --- a/glymur/test/test_jp2k.py +++ b/glymur/test/test_jp2k.py @@ -22,6 +22,11 @@ import uuid import warnings from xml.etree import cElementTree as ET +if sys.hexversion <= 0x03030000: + from mock import patch +else: + from unittest.mock import patch + import numpy as np import pkg_resources @@ -833,6 +838,17 @@ class TestJp2k_write(unittest.TestCase): def tearDown(self): pass + def test_write_with_version_too_early(self): + """Should raise a runtime error if trying to write with version 1.3""" + data = np.zeros((128, 128), dtype=np.uint8) + versions = ["1.0.0", "1.1.0", "1.2.0", "1.3.0"] + for version in versions: + with patch('glymur.version.openjpeg_version', new=version): + with tempfile.NamedTemporaryFile(suffix='.j2k') as tfile: + with self.assertRaises(RuntimeError): + j = Jp2k(tfile.name, 'wb') + j.write(data) + def test_cblkh_different_than_width(self): """Verify that we can set a code block size where height does not equal width. @@ -1158,15 +1174,15 @@ class TestJp2k_2_1(unittest.TestCase): with warnings.catch_warnings(): warnings.simplefilter('ignore') j = Jp2k(tfile.name) - regexp = re.compile(r'''OpenJPEG\slibrary\serror:\s+ - Invalid\svalues\sfor\scomp\s=\s0\s+ - :\sdx=1\sdy=0''', re.VERBOSE) - if sys.hexversion < 0x03020000: - with self.assertRaisesRegexp((IOError, OSError), regexp): - j.read(rlevel=1) - else: - with self.assertRaisesRegex((IOError, OSError), regexp): - j.read(rlevel=1) + regexp = re.compile(r'''OpenJPEG\slibrary\serror:\s+ + Invalid\svalues\sfor\scomp\s=\s0\s+ + :\sdx=1\sdy=0''', re.VERBOSE) + if sys.hexversion < 0x03020000: + with self.assertRaisesRegexp((IOError, OSError), regexp): + j.read(rlevel=1) + else: + with self.assertRaisesRegex((IOError, OSError), regexp): + j.read(rlevel=1) @unittest.skipIf(OPJ_DATA_ROOT is None, "OPJ_DATA_ROOT environment variable not set") From 378cab43504ce3f21752dece3bb34308f043b681 Mon Sep 17 00:00:00 2001 From: jevans Date: Sat, 18 Oct 2014 21:41:44 -0400 Subject: [PATCH 04/57] replaced windows temp file skip messages with a constant, closes #276 --- glymur/test/fixtures.py | 3 +++ glymur/test/test_config.py | 10 +++++++--- glymur/test/test_jp2box.py | 20 +++++++++----------- glymur/test/test_jp2box_xml.py | 5 +++-- glymur/test/test_jp2k.py | 26 +++++++++++++------------- glymur/test/test_opj_suite_write.py | 8 ++++---- 6 files changed, 39 insertions(+), 33 deletions(-) diff --git a/glymur/test/fixtures.py b/glymur/test/fixtures.py index 838756a..4b3972c 100644 --- a/glymur/test/fixtures.py +++ b/glymur/test/fixtures.py @@ -26,6 +26,9 @@ elif re.match('1.[0-6]', six.__version__) is not None: msg = "Cannot run test with version {0} of python-six" WARNING_INFRASTRUCTURE_MSG = msg.format(six.__version__) +# Cannot reopen a named temporary file in windows. +WINDOWS_TMP_FILE_MSG = "cannot use NamedTemporaryFile like this in windows" + class MetadataBase(unittest.TestCase): """ Base class for testing metadata. diff --git a/glymur/test/test_config.py b/glymur/test/test_config.py index f908272..477e2e3 100644 --- a/glymur/test/test_config.py +++ b/glymur/test/test_config.py @@ -25,7 +25,11 @@ else: import glymur from glymur import Jp2k -from .fixtures import WARNING_INFRASTRUCTURE_ISSUE, WARNING_INFRASTRUCTURE_MSG +from .fixtures import ( + WARNING_INFRASTRUCTURE_ISSUE, WARNING_INFRASTRUCTURE_MSG, + WINDOWS_TMP_FILE_MSG +) + @unittest.skipIf(sys.hexversion < 0x03020000, "TemporaryDirectory introduced in 3.2.") @@ -71,7 +75,7 @@ class TestSuite(unittest.TestCase): Jp2k(self.jp2file) @unittest.skipIf(WARNING_INFRASTRUCTURE_ISSUE, WARNING_INFRASTRUCTURE_MSG) - @unittest.skipIf(os.name == "nt", 'named temporary file issue on windows') + @unittest.skipIf(os.name == "nt", WINDOWS_TMP_FILE_MSG) def test_xdg_env_config_file_is_bad(self): """A non-existant library location should be rejected.""" with tempfile.TemporaryDirectory() as tdir: @@ -122,7 +126,7 @@ class TestConfig(unittest.TestCase): with self.assertRaises(glymur.jp2k.LibraryNotFoundError): glymur.Jp2k(self.jp2file).read_bands() - @unittest.skipIf(os.name == "nt", "NamedTemporaryFile issue on windows") + @unittest.skipIf(os.name == "nt", WINDOWS_TMP_FILE_MSG) def test_write_without_library(self): """Don't have openjpeg libraries? Must error out. """ diff --git a/glymur/test/test_jp2box.py b/glymur/test/test_jp2box.py index 061ad23..7246349 100644 --- a/glymur/test/test_jp2box.py +++ b/glymur/test/test_jp2box.py @@ -37,7 +37,7 @@ from glymur.core import RED, GREEN, BLUE, GREY, WHOLE_IMAGE from .fixtures import ( WARNING_INFRASTRUCTURE_ISSUE, WARNING_INFRASTRUCTURE_MSG, - MetadataBase + WINDOWS_TMP_FILE_MSG, MetadataBase ) try: @@ -54,7 +54,7 @@ def load_tests(loader, tests, ignore): tests.addTests(doctest.DocTestSuite('glymur.jp2box')) return tests -@unittest.skipIf(os.name == "nt", "Temporary file issue on window.") +@unittest.skipIf(os.name == "nt", WINDOWS_TMP_FILE_MSG) class TestDataEntryURL(unittest.TestCase): """Test suite for DataEntryURL boxes.""" def setUp(self): @@ -122,7 +122,7 @@ class TestDataEntryURL(unittest.TestCase): @unittest.skipIf(re.match(r'''(1|2.0.0)''', glymur.version.openjpeg_version) is not None, "Not supported until 2.1") -@unittest.skipIf(os.name == "nt", "Temporary file issue on window.") +@unittest.skipIf(os.name == "nt", WINDOWS_TMP_FILE_MSG) class TestChannelDefinition(unittest.TestCase): """Test suite for channel definition boxes.""" @@ -434,8 +434,7 @@ class TestColourSpecificationBox(unittest.TestCase): def tearDown(self): pass - @unittest.skipIf(os.name == "nt", - "Problems using NamedTemporaryFile on windows.") + @unittest.skipIf(os.name == "nt", WINDOWS_TMP_FILE_MSG) def test_colr_with_out_enum_cspace(self): """must supply an enumerated colorspace when writing""" j2k = Jp2k(self.j2kfile) @@ -446,7 +445,7 @@ class TestColourSpecificationBox(unittest.TestCase): with self.assertRaises(IOError): j2k.wrap(tfile.name, boxes=boxes) - @unittest.skipIf(os.name == "nt", "Temporary file issue on window.") + @unittest.skipIf(os.name == "nt", WINDOWS_TMP_FILE_MSG) def test_missing_colr_box(self): """jp2h must have a colr box""" j2k = Jp2k(self.j2kfile) @@ -456,7 +455,7 @@ class TestColourSpecificationBox(unittest.TestCase): with self.assertRaises(IOError): j2k.wrap(tfile.name, boxes=boxes) - @unittest.skipIf(os.name == "nt", "Temporary file issue on window.") + @unittest.skipIf(os.name == "nt", WINDOWS_TMP_FILE_MSG) def test_bad_approx_jp2_field(self): """JP2 has requirements for approx field""" j2k = Jp2k(self.j2kfile) @@ -517,8 +516,7 @@ class TestColourSpecificationBox(unittest.TestCase): colr.write(tfile) -@unittest.skipIf(os.name == "nt", - "Problems using NamedTemporaryFile on windows.") +@unittest.skipIf(os.name == "nt", WINDOWS_TMP_FILE_MSG) class TestPaletteBox(unittest.TestCase): """Test suite for pclr box instantiation.""" @@ -560,7 +558,7 @@ class TestPaletteBox(unittest.TestCase): pclr.write(tfile) -@unittest.skipIf(os.name == "nt", "Temporary file issue on window.") +@unittest.skipIf(os.name == "nt", WINDOWS_TMP_FILE_MSG) class TestAppend(unittest.TestCase): """Tests for append method.""" @@ -653,7 +651,7 @@ class TestAppend(unittest.TestCase): jp2.append(uuidbox) -@unittest.skipIf(os.name == "nt", "Temporary file issue on window.") +@unittest.skipIf(os.name == "nt", WINDOWS_TMP_FILE_MSG) class TestWrap(unittest.TestCase): """Tests for wrap method.""" diff --git a/glymur/test/test_jp2box_xml.py b/glymur/test/test_jp2box_xml.py index eeb1fa8..45d02f1 100644 --- a/glymur/test/test_jp2box_xml.py +++ b/glymur/test/test_jp2box_xml.py @@ -41,8 +41,9 @@ from glymur.jp2box import JPEG2000SignatureBox 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", "Temporary file issue on window.") +@unittest.skipIf(os.name == "nt", fixtures.WINDOWS_TMP_FILE_MSG) class TestXML(unittest.TestCase): """Test suite for XML boxes.""" @@ -219,7 +220,7 @@ class TestJp2kBadXmlFile(unittest.TestCase): self.assertIsNone(jp2k.box[3].xml) -@unittest.skipIf(os.name == "nt", "NamedTemporaryFile issue on windows") +@unittest.skipIf(os.name == "nt", fixtures.WINDOWS_TMP_FILE_MSG) class TestBadButRecoverableXmlFile(unittest.TestCase): """Test suite for XML box that is bad, but we can still recover the XML.""" diff --git a/glymur/test/test_jp2k.py b/glymur/test/test_jp2k.py index 6c92ff9..48c0fdb 100644 --- a/glymur/test/test_jp2k.py +++ b/glymur/test/test_jp2k.py @@ -73,7 +73,7 @@ class SliceProtocolBase(unittest.TestCase): self.j2k_data = self.j2k.read() -@unittest.skipIf(os.name == "nt", "NamedTemporaryFile issue on windows") +@unittest.skipIf(os.name == "nt", fixtures.WINDOWS_TMP_FILE_MSG) class TestSliceProtocolBaseWrite(SliceProtocolBase): def test_write_ellipsis(self): @@ -614,7 +614,7 @@ class TestJp2k(unittest.TestCase): jp2k = Jp2k(self.j2kfile) self.assertEqual(len(jp2k.box), 0) - @unittest.skipIf(os.name == "nt", "NamedTemporaryFile issue on windows") + @unittest.skipIf(os.name == "nt", fixtures.WINDOWS_TMP_FILE_MSG) def test_64bit_xl_field(self): """XL field should be supported""" # Verify that boxes with the XL field are properly read. @@ -648,7 +648,7 @@ class TestJp2k(unittest.TestCase): self.assertEqual(jp2k.box[4].offset, 3223) self.assertEqual(jp2k.box[4].length, 1133427 + 8) - @unittest.skipIf(os.name == "nt", "NamedTemporaryFile issue on windows") + @unittest.skipIf(os.name == "nt", fixtures.WINDOWS_TMP_FILE_MSG) def test_length_field_is_zero(self): """L=0 (length field in box header) is allowed""" # Verify that boxes with the L field as zero are correctly read. @@ -705,7 +705,7 @@ class TestJp2k(unittest.TestCase): j = Jp2k(self.j2kfile) self.assertEqual(j.box, []) - @unittest.skipIf(os.name == "nt", "NamedTemporaryFile issue on windows") + @unittest.skipIf(os.name == "nt", fixtures.WINDOWS_TMP_FILE_MSG) def test_uinf_ulst_url_boxes(self): """Verify that we can read UINF, ULST, and URL boxes""" # Verify that we can read UINF, ULST, and URL boxes. I don't have @@ -764,7 +764,7 @@ class TestJp2k(unittest.TestCase): self.assertEqual(jp2k.box[3].box[1].flag, (0, 0, 0)) self.assertEqual(jp2k.box[3].box[1].url, 'abcd') - @unittest.skipIf(os.name == "nt", "NamedTemporaryFile issue on windows") + @unittest.skipIf(os.name == "nt", fixtures.WINDOWS_TMP_FILE_MSG) def test_xml_with_trailing_nulls(self): """ElementTree doesn't like trailing null chars after valid XML text""" with tempfile.NamedTemporaryFile(suffix='.jp2') as tfile: @@ -827,7 +827,7 @@ class TestJp2k(unittest.TestCase): @unittest.skipIf(re.match('1.[0-4]', openjpeg_version) is not None, "Not supported with OpenJPEG {0}".format(openjpeg_version)) -@unittest.skipIf(os.name == "nt", "NamedTemporaryFile issue on windows") +@unittest.skipIf(os.name == "nt", fixtures.WINDOWS_TMP_FILE_MSG) class TestJp2k_write(unittest.TestCase): """Write tests, can be run by versions 1.5+""" @@ -1015,7 +1015,7 @@ class TestJp2k_1_x(unittest.TestCase): class TestJp2k_2_0_official(unittest.TestCase): """Test suite to only be run on v2.0 official.""" - @unittest.skipIf(os.name == "nt", "NamedTemporaryFile issue on windows") + @unittest.skipIf(os.name == "nt", fixtures.WINDOWS_TMP_FILE_MSG) def test_extra_components_on_v2(self): """Can only write 4 components on 2.0+, should error out otherwise.""" with tempfile.NamedTemporaryFile(suffix='.jp2') as tfile: @@ -1050,7 +1050,7 @@ class TestJp2k_2_0(unittest.TestCase): # End corner must be >= start corner j.read(area=(10, 10, 8, 8)) - @unittest.skipIf(os.name == "nt", "NamedTemporaryFile issue on windows") + @unittest.skipIf(os.name == "nt", fixtures.WINDOWS_TMP_FILE_MSG) def test_unrecognized_jp2_clrspace(self): """We only allow RGB and GRAYSCALE. Should error out with others""" with tempfile.NamedTemporaryFile(suffix='.jp2') as tfile: @@ -1059,7 +1059,7 @@ class TestJp2k_2_0(unittest.TestCase): data = np.zeros((128, 128, 3), dtype=np.uint8) j.write(data, colorspace='cmyk') - @unittest.skipIf(os.name == "nt", "NamedTemporaryFile issue on windows") + @unittest.skipIf(os.name == "nt", fixtures.WINDOWS_TMP_FILE_MSG) def test_asoc_label_box(self): """Test asoc and label box""" # Construct a fake file with an asoc and a label box, as @@ -1121,7 +1121,7 @@ class TestJp2k_2_1(unittest.TestCase): def tearDown(self): pass - @unittest.skipIf(os.name == "nt", "NamedTemporaryFile issue on windows") + @unittest.skipIf(os.name == "nt", fixtures.WINDOWS_TMP_FILE_MSG) def test_grey_with_extra_component(self): """version 2.0 cannot write gray + extra""" with tempfile.NamedTemporaryFile(suffix='.jp2') as tfile: @@ -1134,7 +1134,7 @@ class TestJp2k_2_1(unittest.TestCase): self.assertEqual(j.box[2].box[1].colorspace, glymur.core.GREYSCALE) - @unittest.skipIf(os.name == "nt", "NamedTemporaryFile issue on windows") + @unittest.skipIf(os.name == "nt", fixtures.WINDOWS_TMP_FILE_MSG) def test_rgb_with_extra_component(self): """v2.0+ should be able to write extra components""" with tempfile.NamedTemporaryFile(suffix='.jp2') as tfile: @@ -1147,7 +1147,7 @@ class TestJp2k_2_1(unittest.TestCase): self.assertEqual(j.box[2].box[1].colorspace, glymur.core.SRGB) @unittest.skipIf(WARNING_INFRASTRUCTURE_ISSUE, WARNING_INFRASTRUCTURE_MSG) - @unittest.skipIf(os.name == "nt", "NamedTemporaryFile issue on windows") + @unittest.skipIf(os.name == "nt", fixtures.WINDOWS_TMP_FILE_MSG) def test_openjpeg_library_message(self): """Verify the error message produced by the openjpeg library""" # This will confirm that the error callback mechanism is working. @@ -1269,7 +1269,7 @@ class TestJp2kOpjDataRootWarnings(unittest.TestCase): class TestJp2kOpjDataRoot(unittest.TestCase): """These tests should be run by just about all configuration.""" - @unittest.skipIf(os.name == "nt", "NamedTemporaryFile issue on windows") + @unittest.skipIf(os.name == "nt", fixtures.WINDOWS_TMP_FILE_MSG) def test_irreversible(self): """Irreversible""" filename = opj_data_file('input/nonregression/issue141.rawl') diff --git a/glymur/test/test_opj_suite_write.py b/glymur/test/test_opj_suite_write.py index 7e6357d..e0f947c 100644 --- a/glymur/test/test_opj_suite_write.py +++ b/glymur/test/test_opj_suite_write.py @@ -64,7 +64,7 @@ class CinemaBase(fixtures.MetadataBase): @unittest.skipIf(NO_SKIMAGE_FREEIMAGE_SUPPORT, "Cannot read input image without scikit-image/freeimage") -@unittest.skipIf(os.name == "nt", "no write support on windows, period") +@unittest.skipIf(os.name == "nt", fixtures.WINDOWS_TMP_FILE_MSG) @unittest.skipIf(re.match(r'''(1|2.0.0)''', glymur.version.openjpeg_version) is not None, "Uses features not supported until 2.0.1") @@ -100,7 +100,7 @@ class WriteCinema(CinemaBase): @unittest.skipIf(WARNING_INFRASTRUCTURE_ISSUE, WARNING_INFRASTRUCTURE_MSG) @unittest.skipIf(NO_SKIMAGE_FREEIMAGE_SUPPORT, "Cannot read input image without scikit-image/freeimage") -@unittest.skipIf(os.name == "nt", "no write support on windows, period") +@unittest.skipIf(os.name == "nt", fixtures.WINDOWS_TMP_FILE_MSG) @unittest.skipIf(re.match(r'''(1|2.0.0)''', glymur.version.openjpeg_version) is not None, "Uses features not supported until 2.0.1") @@ -194,7 +194,7 @@ class WriteCinemaWarns(CinemaBase): @unittest.skipIf(NO_SKIMAGE_FREEIMAGE_SUPPORT, "Cannot read input image without scikit-image/freeimage") -@unittest.skipIf(os.name == "nt", "Temporary file issue on window.") +@unittest.skipIf(os.name == "nt", fixtures.WINDOWS_TMP_FILE_MSG) @unittest.skipIf(not re.match("(1.5|2.0.0)", glymur.version.openjpeg_version), "Functionality implemented for 2.0.1") @unittest.skipIf(OPJ_DATA_ROOT is None, @@ -221,7 +221,7 @@ class TestSuiteNegative2pointzero(unittest.TestCase): @unittest.skipIf(re.match(r'''1.[0-4]''', openjpeg_version) is not None, "Writing not supported until OpenJPEG 1.5") -@unittest.skipIf(os.name == "nt", "no write support on windows, period") +@unittest.skipIf(os.name == "nt", fixtures.WINDOWS_TMP_FILE_MSG) @unittest.skipIf(NO_READ_BACKEND, NO_READ_BACKEND_MSG) @unittest.skipIf(OPJ_DATA_ROOT is None, "OPJ_DATA_ROOT environment variable not set") From 41252f54de5c7df05425cf5304b121988fe3255e Mon Sep 17 00:00:00 2001 From: jevans Date: Sat, 18 Oct 2014 23:09:15 -0400 Subject: [PATCH 05/57] tidied up top-level imports, closes #277 --- glymur/__init__.py | 6 ++++-- glymur/codestream.py | 9 +++++---- glymur/jp2box.py | 13 +++++++------ glymur/jp2k.py | 15 ++++++--------- glymur/lib/openjp2.py | 1 + glymur/lib/openjpeg.py | 1 + glymur/version.py | 3 +-- 7 files changed, 25 insertions(+), 23 deletions(-) diff --git a/glymur/__init__.py b/glymur/__init__.py index eb0139c..9a4d8b1 100644 --- a/glymur/__init__.py +++ b/glymur/__init__.py @@ -7,8 +7,10 @@ from glymur import version __version__ = version.version from .jp2k import Jp2k -from .jp2box import get_printoptions, set_printoptions -from .jp2box import get_parseoptions, set_parseoptions +from .jp2box import ( + get_printoptions, set_printoptions, + get_parseoptions, set_parseoptions +) from . import data diff --git a/glymur/codestream.py b/glymur/codestream.py index c87c2d2..c8ab00f 100644 --- a/glymur/codestream.py +++ b/glymur/codestream.py @@ -24,10 +24,11 @@ import warnings import numpy as np -from .core import LRCP, RLCP, RPCL, PCRL, CPRL -from .core import WAVELET_XFORM_9X7_IRREVERSIBLE -from .core import WAVELET_XFORM_5X3_REVERSIBLE -from .core import _Keydefaultdict +from .core import ( + LRCP, RLCP, RPCL, PCRL, CPRL, + WAVELET_XFORM_9X7_IRREVERSIBLE, WAVELET_XFORM_5X3_REVERSIBLE, + _Keydefaultdict +) from .lib import openjp2 as opj2 _factory = lambda x: '{0} (invalid)'.format(x) diff --git a/glymur/jp2box.py b/glymur/jp2box.py index c3bd8e3..a2148ae 100644 --- a/glymur/jp2box.py +++ b/glymur/jp2box.py @@ -29,12 +29,13 @@ import lxml.etree as ET import numpy as np from .codestream import Codestream -from .core import _COLORSPACE_MAP_DISPLAY -from .core import _COLOR_TYPE_MAP_DISPLAY -from .core import SRGB, GREYSCALE, YCC -from .core import ENUMERATED_COLORSPACE, RESTRICTED_ICC_PROFILE -from .core import ANY_ICC_PROFILE, VENDOR_COLOR_METHOD -from .core import _Keydefaultdict +from .core import ( + _COLORSPACE_MAP_DISPLAY, _COLOR_TYPE_MAP_DISPLAY, + SRGB, GREYSCALE, YCC, + ENUMERATED_COLORSPACE, RESTRICTED_ICC_PROFILE, + ANY_ICC_PROFILE, VENDOR_COLOR_METHOD, + _Keydefaultdict +) from . import _uuid_io diff --git a/glymur/jp2k.py b/glymur/jp2k.py index 6b95cc1..b7b699c 100644 --- a/glymur/jp2k.py +++ b/glymur/jp2k.py @@ -30,15 +30,12 @@ import warnings import numpy as np from .codestream import Codestream -from . import core -from .jp2box import Jp2kBox -from .jp2box import JPEG2000SignatureBox, FileTypeBox, JP2HeaderBox -from .jp2box import ColourSpecificationBox, ContiguousCodestreamBox -from .jp2box import ImageHeaderBox -from .lib import openjpeg as opj -from .lib import openjp2 as opj2 -from . import version -from .lib import c as libc +from . import core, version +from .jp2box import ( + Jp2kBox, JPEG2000SignatureBox, FileTypeBox, JP2HeaderBox, + ColourSpecificationBox, ContiguousCodestreamBox, ImageHeaderBox +) +from .lib import openjpeg as opj, openjp2 as opj2, c as libc JP2_IDS = ['colr', 'cdef', 'cmap', 'jp2c', 'ftyp', 'ihdr', 'jp2h', 'jP ', 'pclr', 'res ', 'resc', 'resd', 'xml ', 'ulst', 'uinf', 'url ', diff --git a/glymur/lib/openjp2.py b/glymur/lib/openjp2.py index 5b5f3c4..f3f5b5c 100644 --- a/glymur/lib/openjp2.py +++ b/glymur/lib/openjp2.py @@ -9,6 +9,7 @@ import re import sys from .config import glymur_config + OPENJP2, OPENJPEG = glymur_config() def version(): diff --git a/glymur/lib/openjpeg.py b/glymur/lib/openjpeg.py index 418e9df..d1918ad 100644 --- a/glymur/lib/openjpeg.py +++ b/glymur/lib/openjpeg.py @@ -9,6 +9,7 @@ import sys import numpy as np from .config import glymur_config + _, OPENJPEG = glymur_config() # Maximum number of tile parts expected by JPWL: increase at your will diff --git a/glymur/version.py b/glymur/version.py index 8509980..55e4b88 100644 --- a/glymur/version.py +++ b/glymur/version.py @@ -14,8 +14,7 @@ from distutils.version import LooseVersion import lxml.etree import numpy as np -from .lib import openjpeg as opj -from .lib import openjp2 as opj2 +from .lib import openjpeg as opj, openjp2 as opj2 # Do not change the format of this next line! Doing so risks breaking # setup.py From 60dcdfe9c54fe8b43ece8e9d05a97058efa48e5c Mon Sep 17 00:00:00 2001 From: jevans Date: Sat, 18 Oct 2014 23:59:32 -0400 Subject: [PATCH 06/57] refactored configuration file handling, closes #265 --- glymur/lib/config.py | 109 +++++++++++++++++++++---------------------- 1 file changed, 52 insertions(+), 57 deletions(-) diff --git a/glymur/lib/config.py b/glymur/lib/config.py index 04aece2..a475233 100644 --- a/glymur/lib/config.py +++ b/glymur/lib/config.py @@ -18,6 +18,19 @@ else: from configparser import ConfigParser from configparser import NoOptionError +# default library locations for MacPorts +_macports_default_location = { + 'openjp2': '/opt/local/lib/libopenjp2.dylib', + 'openjpeg': '/opt/local/lib/libopenjpeg.dylib' +} + +# default library locations on Windows +_windows_default_location = { + 'openjp2': os.path.join('C:\\', 'Program files', 'OpenJPEG 2.0', + 'bin', 'openjp2.dll'), + 'openjpeg': os.path.join('C:\\', 'Program files', 'OpenJPEG 1.5', + 'bin', 'openjpeg.dll') +} def glymurrc_fname(): """Return the path to the configuration file. @@ -42,30 +55,23 @@ 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) -def load_openjpeg(path): - """Load the openjpeg library, falling back on defaults if necessary. + # No location specified by the configuration file, must look for it + # elsewhere. + path = find_library(libname) - Parameters - ---------- - path : str - Path to openjpeg 1.5 library as specified by configuration file. Will - be None if no configuration file specified. - """ - if path is None: - # Let ctypes try to find it. - path = find_library('openjpeg') - - # If we could not find it, then look in some likely locations on mac - # and win. if path is None: # Could not find a library via ctypes if platform.system() == 'Darwin': # MacPorts - path = '/opt/local/lib/libopenjpeg.dylib' + path = _macports_default_location[libname] elif os.name == 'nt': - path = os.path.join('C:\\', 'Program files', 'OpenJPEG 1.5', - 'bin', 'openjpeg.dll') + path = _windows_default_location[libname] if path is not None and not os.path.exists(path): # the mac/win default location does not exist. @@ -73,29 +79,6 @@ def load_openjpeg(path): return load_library_handle(path) -def load_openjp2(path): - """Load the openjp2 library, falling back on defaults if necessary. - """ - if path is None: - # No help from the config file, try to find it via ctypes. - path = find_library('openjp2') - - if path is None: - # Could not find a library via ctypes - if platform.system() == 'Darwin': - # MacPorts - path = '/opt/local/lib/libopenjp2.dylib' - elif os.name == 'nt': - path = os.path.join('C:\\', 'Program files', 'OpenJPEG 2.0', - 'bin', 'openjp2.dll') - - if path is not None and not os.path.exists(path): - # the mac/win default location does not exist. - return None - - return load_library_handle(path) - - def load_library_handle(path): """Load the library, return the ctypes handle.""" @@ -119,36 +102,48 @@ def load_library_handle(path): return opj_lib -def read_config_file(): +def read_config_file(libname): """ - We must use a configuration file that the user must write. + Extract library locations from a configuration file. + + Parameters + ---------- + libname : str + One of either 'openjp2' or 'openjpeg' + + Returns + ------- + path : None or str + None if no location is specified, otherwise a path to the library """ - lib = {'openjp2': None, 'openjpeg': None} filename = glymurrc_fname() if filename is not None: # Read the configuration file for the library location. parser = ConfigParser() parser.read(filename) - for name in ['openjp2', 'openjpeg']: - try: - lib[name] = parser.get('library', name) - except NoOptionError: - pass - - return lib + try: + path = parser.get('library', libname) + except NoOptionError: + path = None + return path def glymur_config(): - """Try to ascertain locations of openjp2, openjpeg libraries. """ - libs = read_config_file() - libopenjp2_handle = load_openjp2(libs['openjp2']) - libopenjpeg_handle = load_openjpeg(libs['openjpeg']) - if libopenjp2_handle is None and libopenjpeg_handle is None: + Try to ascertain locations of openjp2, openjpeg libraries. + + Returns + ------- + tpl : tuple + tuple of library handles + """ + lst = [] + for libname in ['openjp2', 'openjpeg']: + lst.append(load_openjpeg_library(libname)) + if all(handle is None for handle in lst): msg = "Neither the openjp2 nor the openjpeg library could be loaded. " raise IOError(msg) - return libopenjp2_handle, libopenjpeg_handle - + return tuple(lst) def get_configdir(): """Return string representing the configuration directory. From 5de1b8b240a95fbddb31495af4dddc9a2116ed34 Mon Sep 17 00:00:00 2001 From: jevans Date: Sun, 19 Oct 2014 11:24:23 -0400 Subject: [PATCH 07/57] remove LibraryNotFoundError, use RuntimeError instead, closes #274, #278 LibraryNotFoundError isn't needed because we already error out during the import of glymur if neither openjpeg nor openjp2 can be found. When read_bands is used and the library version is not at least 2.0.0, use RuntimeError instead of LibraryNotFoundError. --- glymur/jp2k.py | 31 +++---------------------------- glymur/test/test_config.py | 33 --------------------------------- glymur/test/test_jp2k.py | 5 +++++ 3 files changed, 8 insertions(+), 61 deletions(-) diff --git a/glymur/jp2k.py b/glymur/jp2k.py index b7b699c..0bda856 100644 --- a/glymur/jp2k.py +++ b/glymur/jp2k.py @@ -406,19 +406,11 @@ class Jp2k(Jp2kBox): >>> tfile = NamedTemporaryFile(suffix='.jp2', delete=False) >>> j = Jp2k(tfile.name, mode='wb') >>> j.write(data.astype(np.uint8)) - - Raises - ------ - glymur.jp2k.LibraryNotFoundError - if glymur is unable to load an openjpeg library suitable for writing """ if re.match("1.[0-4]", version.openjpeg_version) is not None: raise RuntimeError("You must have at least version 1.5 of OpenJPEG " "in order to write images.") - if opj2.OPENJP2 is None and opj.OPENJPEG is None: - raise LibraryNotFoundError("Cannot load the OpenJPEG library.") - self._determine_colorspace(img_array, **kwargs) cparams = self._populate_cparams(img_array, **kwargs) @@ -962,8 +954,6 @@ class Jp2k(Jp2kBox): Raises ------ - glymur.jp2k.LibraryNotFoundError - if glymur is unable to load an openjpeg library suitable for reading IOError If the image has differing subsample factors. @@ -982,9 +972,6 @@ class Jp2k(Jp2kBox): >>> thumbnail.shape (728, 1296, 3) """ - if opj2.OPENJP2 is None and opj.OPENJPEG is None: - raise LibraryNotFoundError("Cannot load the OpenJPEG library.") - if opj2.OPENJP2 is not None: img = self._read_openjp2(**kwargs) else: @@ -1275,16 +1262,11 @@ class Jp2k(Jp2kBox): >>> jfile = glymur.data.nemo() >>> jp = glymur.Jp2k(jfile) >>> components_lst = jp.read_bands(rlevel=1) - - Raises - ------ - glymur.jp2k.LibraryNotFoundError - if glymur is unable to load an openjpeg library suitable for reading """ if version.openjpeg_version_tuple[0] < 2: - raise LibraryNotFoundError("You must have at least version 2.0.0 " - "of OpenJPEG installed before using " - "this functionality.") + raise RuntimeError("You must have at least version 2.0.0 of " + "OpenJPEG installed before using this " + "functionality.") dparam = self._populate_dparam(rlevel, ignore_pclr_cmap_cdef, layer=layer, tile=tile, area=area) @@ -1835,10 +1817,3 @@ def _default_warning_handler(library_msg, _): _ERROR_CALLBACK = _CMPFUNC(_default_error_handler) _INFO_CALLBACK = _CMPFUNC(_default_info_handler) _WARNING_CALLBACK = _CMPFUNC(_default_warning_handler) - - -class LibraryNotFoundError(IOError): - """Raised if functionality is requested without the necessary library. - """ - def __init__(self, msg): - IOError.__init__(self, msg) diff --git a/glymur/test/test_config.py b/glymur/test/test_config.py index 477e2e3..37db88d 100644 --- a/glymur/test/test_config.py +++ b/glymur/test/test_config.py @@ -108,36 +108,3 @@ class TestConfig(unittest.TestCase): def tearDown(self): pass - def test_read_without_library(self): - """Don't have either openjp2 or openjpeg libraries? Must error out. - """ - with patch('glymur.lib.openjp2.OPENJP2', new=None): - with patch('glymur.lib.openjpeg.OPENJPEG', new=None): - with self.assertRaises(glymur.jp2k.LibraryNotFoundError): - glymur.Jp2k(self.jp2file).read() - - def test_read_bands_without_library(self): - """Don't have openjp2 library? Must error out. - """ - with patch('glymur.lib.openjp2.OPENJP2', new=None): - with patch('glymur.lib.openjpeg.OPENJPEG', new=None): - with patch('glymur.version.openjpeg_version_tuple', - new=(0, 0, 0)): - with self.assertRaises(glymur.jp2k.LibraryNotFoundError): - glymur.Jp2k(self.jp2file).read_bands() - - @unittest.skipIf(os.name == "nt", WINDOWS_TMP_FILE_MSG) - def test_write_without_library(self): - """Don't have openjpeg libraries? Must error out. - """ - data = glymur.Jp2k(self.j2kfile).read() - with patch('glymur.lib.openjp2.OPENJP2', new=None): - with patch('glymur.lib.openjpeg.OPENJPEG', new=None): - with self.assertRaises(glymur.jp2k.LibraryNotFoundError): - with tempfile.NamedTemporaryFile(suffix='.jp2') as tfile: - ofile = Jp2k(tfile.name, 'wb') - ofile.write(data) - - -if __name__ == "__main__": - unittest.main() diff --git a/glymur/test/test_jp2k.py b/glymur/test/test_jp2k.py index 48c0fdb..3800f44 100644 --- a/glymur/test/test_jp2k.py +++ b/glymur/test/test_jp2k.py @@ -824,6 +824,11 @@ class TestJp2k(unittest.TestCase): data = jpx.read() self.assertEqual(data.shape, (1024, 1024, 3)) + def test_read_bands_without_openjp2(self): + """Don't have openjp2 library? Must error out.""" + with patch('glymur.version.openjpeg_version_tuple', new=(1, 5, 0)): + with self.assertRaises(RuntimeError): + glymur.Jp2k(self.jp2file).read_bands() @unittest.skipIf(re.match('1.[0-4]', openjpeg_version) is not None, "Not supported with OpenJPEG {0}".format(openjpeg_version)) From 185f4da07347914a94726962408f414d5b08c5c1 Mon Sep 17 00:00:00 2001 From: jevans Date: Sun, 19 Oct 2014 13:13:35 -0400 Subject: [PATCH 08/57] fix library path issue when no configuration file exists, #265 --- glymur/lib/config.py | 18 ++++++++++-------- 1 file changed, 10 insertions(+), 8 deletions(-) diff --git a/glymur/lib/config.py b/glymur/lib/config.py index a475233..431a00c 100644 --- a/glymur/lib/config.py +++ b/glymur/lib/config.py @@ -117,15 +117,17 @@ def read_config_file(libname): None if no location is specified, otherwise a path to the library """ filename = glymurrc_fname() - if filename is not None: - # Read the configuration file for the library location. - parser = ConfigParser() - parser.read(filename) - try: - path = parser.get('library', libname) - except NoOptionError: - path = None + if filename is None: + # There's no library file path to return in this case. + return None + # Read the configuration file for the library location. + parser = ConfigParser() + parser.read(filename) + try: + path = parser.get('library', libname) + except NoOptionError: + path = None return path def glymur_config(): From ff849df520d3e8f5d5d7c51875d18cd56d3e6087 Mon Sep 17 00:00:00 2001 From: jevans Date: Sun, 19 Oct 2014 13:00:45 -0400 Subject: [PATCH 09/57] add __str__ methods for openjp2 ctypes structures, refactored their use The openjp2 structures are now largely maintained as weak internal-use-only attributes where possible. This allows us to inspect (print) them from the command line after the fact. --- glymur/jp2k.py | 290 +++++++++++++++---------------- glymur/lib/openjp2.py | 92 ++++++++++ glymur/lib/test/fixtures.py | 144 +++++++++++++++ glymur/lib/test/test_printing.py | 77 ++++++++ glymur/test/fixtures.py | 1 + glymur/test/test_printing.py | 12 +- 6 files changed, 456 insertions(+), 160 deletions(-) create mode 100644 glymur/lib/test/fixtures.py create mode 100644 glymur/lib/test/test_printing.py diff --git a/glymur/jp2k.py b/glymur/jp2k.py index 0bda856..aadb5ed 100644 --- a/glymur/jp2k.py +++ b/glymur/jp2k.py @@ -157,7 +157,7 @@ class Jp2k(Jp2kBox): msg += "profile if the file type box brand is 'jp2 '." warnings.warn(msg) - def _set_cinema_params(self, cparams, cinema_mode, fps): + def _set_cinema_params(self, cinema_mode, fps): """Populate compression parameters structure for cinema2K. Parameters @@ -176,7 +176,7 @@ class Jp2k(Jp2kBox): raise IOError(msg) # Cinema modes imply MCT. - cparams.tcp_mct = 1 + self._cparams.tcp_mct = 1 if cinema_mode == 'cinema2k': if fps not in [24, 48]: @@ -185,30 +185,28 @@ class Jp2k(Jp2kBox): if re.match("2.0", version.openjpeg_version) is not None: # 2.0 API if fps == 24: - cparams.cp_cinema = core.OPJ_CINEMA2K_24 + self._cparams.cp_cinema = core.OPJ_CINEMA2K_24 else: - cparams.cp_cinema = core.OPJ_CINEMA2K_48 + self._cparams.cp_cinema = core.OPJ_CINEMA2K_48 else: # 2.1 API if fps == 24: - cparams.rsiz = core.OPJ_PROFILE_CINEMA_2K - cparams.max_comp_size = core.OPJ_CINEMA_24_COMP - cparams.max_cs_size = core.OPJ_CINEMA_24_CS + self._cparams.rsiz = core.OPJ_PROFILE_CINEMA_2K + self._cparams.max_comp_size = core.OPJ_CINEMA_24_COMP + self._cparams.max_cs_size = core.OPJ_CINEMA_24_CS else: - cparams.rsiz = core.OPJ_PROFILE_CINEMA_2K - cparams.max_comp_size = core.OPJ_CINEMA_48_COMP - cparams.max_cs_size = core.OPJ_CINEMA_48_CS + self._cparams.rsiz = core.OPJ_PROFILE_CINEMA_2K + self._cparams.max_comp_size = core.OPJ_CINEMA_48_COMP + self._cparams.max_cs_size = core.OPJ_CINEMA_48_CS else: # cinema4k if re.match("2.0", version.openjpeg_version) is not None: # 2.0 API - cparams.cp_cinema = core.OPJ_CINEMA4K_24 + self._cparams.cp_cinema = core.OPJ_CINEMA4K_24 else: # 2.1 API - cparams.rsiz = core.OPJ_PROFILE_CINEMA_4K - - return + self._cparams.rsiz = core.OPJ_PROFILE_CINEMA_4K def _populate_cparams(self, img_array, **kwargs): """Directs processing of write method arguments. @@ -219,11 +217,6 @@ class Jp2k(Jp2kBox): image data to be written to file kwargs : dictionary non-image keyword inputs provided to write method - - Returns - ------- - cparams : CompressionParametersType(ctypes.Structure) - corresponds to cparameters_t openjpeg datatype """ if (('cinema2k' in kwargs or 'cinema4k' in kwargs) and (len(set(kwargs)) > 1)): @@ -258,12 +251,14 @@ class Jp2k(Jp2kBox): cparams.irreversible = 1 if 'cinema2k' in kwargs: - self._set_cinema_params(cparams, 'cinema2k', kwargs['cinema2k']) - return cparams + self._cparams = cparams + self._set_cinema_params('cinema2k', kwargs['cinema2k']) + return if 'cinema4k' in kwargs: - self._set_cinema_params(cparams, 'cinema4k', kwargs['cinema4k']) - return cparams + self._cparams = cparams + self._set_cinema_params('cinema4k', kwargs['cinema4k']) + return if 'cbsize' in kwargs: cparams.cblockw_init = kwargs['cbsize'][1] @@ -337,7 +332,7 @@ class Jp2k(Jp2kBox): self._validate_compression_params(img_array, cparams, **kwargs) - return cparams + self._cparams = cparams def write(self, img_array, verbose=False, **kwargs): """Write image data to a JP2/JPX/J2k file. Intended usage of the @@ -412,14 +407,14 @@ class Jp2k(Jp2kBox): "in order to write images.") self._determine_colorspace(img_array, **kwargs) - cparams = self._populate_cparams(img_array, **kwargs) + self._populate_cparams(img_array, **kwargs) if opj2.OPENJP2 is not None: - self._write_openjp2(img_array, cparams, verbose=verbose) + self._write_openjp2(img_array, verbose=verbose) else: - self._write_openjpeg(img_array, cparams, verbose=verbose) + self._write_openjpeg(img_array, verbose=verbose) - def _write_openjpeg(self, img_array, cparams, verbose=False): + def _write_openjpeg(self, img_array, verbose=False): """ Write JPEG 2000 file using OpenJPEG 1.5 interface. """ @@ -429,21 +424,21 @@ class Jp2k(Jp2kBox): img_array.shape[1], 1) - comptparms = _populate_comptparms(img_array, cparams) + self._populate_comptparms(img_array) with ExitStack() as stack: - image = opj.image_create(comptparms, self._colorspace) + image = opj.image_create(self._comptparms, self._colorspace) stack.callback(opj.image_destroy, image) numrows, numcols, numlayers = img_array.shape # set image offset and reference grid - image.contents.x0 = cparams.image_offset_x0 - image.contents.y0 = cparams.image_offset_y0 + image.contents.x0 = self._cparams.image_offset_x0 + image.contents.y0 = self._cparams.image_offset_y0 image.contents.x1 = image.contents.x0 \ - + (numcols - 1) * cparams.subsampling_dx + 1 + + (numcols - 1) * self._cparams.subsampling_dx + 1 image.contents.y1 = image.contents.y0 \ - + (numrows - 1) * cparams.subsampling_dy + 1 + + (numrows - 1) * self._cparams.subsampling_dy + 1 # Stage the image data to the openjpeg data structure. for k in range(0, numlayers): @@ -453,7 +448,7 @@ class Jp2k(Jp2kBox): src = layer.ctypes.data ctypes.memmove(dest, src, layer.nbytes) - cinfo = opj.create_compress(cparams.codec_fmt) + cinfo = opj.create_compress(self._cparams.codec_fmt) stack.callback(opj.destroy_compress, cinfo) # Setup the info, warning, and error handlers. @@ -467,7 +462,7 @@ class Jp2k(Jp2kBox): event_mgr.error_handler = ctypes.cast(_ERROR_CALLBACK, ctypes.c_void_p) - opj.setup_encoder(cinfo, ctypes.byref(cparams), image) + opj.setup_encoder(cinfo, ctypes.byref(self._cparams), image) cio = opj.cio_open(cinfo) stack.callback(opj.cio_close, cio) @@ -588,7 +583,7 @@ class Jp2k(Jp2kBox): self._colorspace = _COLORSPACE_MAP[colorspace.lower()] - def _write_openjp2(self, img_array, cparams, verbose=False): + def _write_openjp2(self, img_array, verbose=False): """ Write JPEG 2000 file using OpenJPEG 2.x interface. """ @@ -597,15 +592,15 @@ class Jp2k(Jp2kBox): numrows, numcols = img_array.shape img_array = img_array.reshape(numrows, numcols, 1) - comptparms = _populate_comptparms(img_array, cparams) + self._populate_comptparms(img_array) with ExitStack() as stack: - image = opj2.image_create(comptparms, self._colorspace) + image = opj2.image_create(self._comptparms, self._colorspace) stack.callback(opj2.image_destroy, image) - _populate_image_struct(cparams, image, img_array) + self._populate_image_struct(image, img_array) - codec = opj2.create_compress(cparams.codec_fmt) + codec = opj2.create_compress(self._cparams.codec_fmt) stack.callback(opj2.destroy_codec, codec) info_handler = _INFO_CALLBACK if verbose else None @@ -613,7 +608,7 @@ class Jp2k(Jp2kBox): opj2.set_warning_handler(codec, _WARNING_CALLBACK) opj2.set_error_handler(codec, _ERROR_CALLBACK) - opj2.setup_encoder(codec, cparams, image) + opj2.setup_encoder(codec, self._cparams, image) if re.match("2.0", version.openjpeg_version) is not None: fptr = libc.fopen(self.filename, 'wb') @@ -1020,13 +1015,13 @@ class Jp2k(Jp2kBox): """ self._subsampling_sanity_check() - dparameters = self._populate_dparam(rlevel, ignore_pclr_cmap_cdef) + self._populate_dparams(rlevel, ignore_pclr_cmap_cdef) with ExitStack() as stack: try: - dparameters.decod_format = self._codec_format + self._dparams.decod_format = self._codec_format - dinfo = opj.create_decompress(dparameters.decod_format) + dinfo = opj.create_decompress(self._dparams.decod_format) event_mgr = opj.EventMgrType() info_handler = ctypes.cast(_INFO_CALLBACK, ctypes.c_void_p) @@ -1037,7 +1032,7 @@ class Jp2k(Jp2kBox): ctypes.c_void_p) opj.set_event_mgr(dinfo, ctypes.byref(event_mgr)) - opj.setup_decoder(dinfo, dparameters) + opj.setup_decoder(dinfo, self._dparams) with open(self.filename, 'rb') as fptr: src = fptr.read() @@ -1104,8 +1099,8 @@ class Jp2k(Jp2kBox): """ self._subsampling_sanity_check() - dparam = self._populate_dparam(rlevel, ignore_pclr_cmap_cdef, - layer=layer, tile=tile, area=area) + self._populate_dparams(rlevel, ignore_pclr_cmap_cdef, + layer=layer, tile=tile, area=area) with ExitStack() as stack: if re.match("2.1", version.openjpeg_version): @@ -1127,16 +1122,17 @@ class Jp2k(Jp2kBox): else: opj2.set_info_handler(codec, None) - opj2.setup_decoder(codec, dparam) + opj2.setup_decoder(codec, self._dparams) image = opj2.read_header(stream, codec) stack.callback(opj2.image_destroy, image) - if dparam.nb_tile_to_decode: - opj2.get_decoded_tile(codec, stream, image, dparam.tile_index) + if self._dparams.nb_tile_to_decode: + opj2.get_decoded_tile(codec, stream, image, + self._dparams.tile_index) else: opj2.set_decode_area(codec, image, - dparam.DA_x0, dparam.DA_y0, - dparam.DA_x1, dparam.DA_y1) + self._dparams.DA_x0, self._dparams.DA_y0, + self._dparams.DA_x1, self._dparams.DA_y1) opj2.decode(codec, stream, image) opj2.end_decompress(codec, stream) @@ -1147,8 +1143,8 @@ class Jp2k(Jp2kBox): return img_array - def _populate_dparam(self, rlevel, ignore_pclr_cmap_cdef, tile=None, - layer=None, area=None): + def _populate_dparams(self, rlevel, ignore_pclr_cmap_cdef, tile=None, + layer=None, area=None): """Populate decompression structure with appropriate input parameters. Parameters @@ -1165,11 +1161,6 @@ class Jp2k(Jp2kBox): ignore_pclr_cmap_cdef : bool Whether or not to ignore the pclr, cmap, or cdef boxes during any color transformation. Defaults to False. - - Returns - ------- - dparam : DecompressionParametersType (ctypes) - Corresponds to openjp2 decompression parameters structure. """ if opj2.OPENJP2 is not None: dparam = opj2.set_default_decoder_parameters() @@ -1220,7 +1211,7 @@ class Jp2k(Jp2kBox): # Return raw codestream components. dparam.flags |= 1 - return dparam + self._dparams = dparam def read_bands(self, rlevel=0, layer=0, area=None, tile=None, verbose=False, ignore_pclr_cmap_cdef=False): @@ -1268,8 +1259,8 @@ class Jp2k(Jp2kBox): "OpenJPEG installed before using this " "functionality.") - dparam = self._populate_dparam(rlevel, ignore_pclr_cmap_cdef, - layer=layer, tile=tile, area=area) + self._populate_dparams(rlevel, ignore_pclr_cmap_cdef, + layer=layer, tile=tile, area=area) with ExitStack() as stack: if re.match("2.1", version.openjpeg_version): @@ -1292,16 +1283,17 @@ class Jp2k(Jp2kBox): else: opj2.set_info_handler(codec, None) - opj2.setup_decoder(codec, dparam) + opj2.setup_decoder(codec, self._dparams) image = opj2.read_header(stream, codec) stack.callback(opj2.image_destroy, image) - if dparam.nb_tile_to_decode: - opj2.get_decoded_tile(codec, stream, image, dparam.tile_index) + if self._dparams.nb_tile_to_decode: + opj2.get_decoded_tile(codec, stream, image, + self._dparams.tile_index) else: opj2.set_decode_area(codec, image, - dparam.DA_x0, dparam.DA_y0, - dparam.DA_x1, dparam.DA_y1) + self._dparams.DA_x0, self._dparams.DA_y0, + self._dparams.DA_x1, self._dparams.DA_y1) opj2.decode(codec, stream, image) opj2.end_decompress(codec, stream) @@ -1362,7 +1354,83 @@ class Jp2k(Jp2kBox): return codestream + def _populate_image_struct(self, image, imgdata): + """Populates image struct needed for compression. + + Parameters + ---------- + image : ImageType(ctypes.Structure) + Corresponds to image_t type in openjp2 headers. + img_array : ndarray + Image data to be written to file. + """ + + numrows, numcols, num_comps = imgdata.shape + + # 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) + + # Stage the image data to the openjpeg data structure. + for k in range(0, num_comps): + if re.match("2.0", version.openjpeg_version) is not None: + # 2.0 API + if self._cparams.cp_cinema: + image.contents.comps[k].prec = 12 + image.contents.comps[k].bpp = 12 + else: + # 2.1 API + if self._cparams.rsiz in (core.OPJ_PROFILE_CINEMA_2K, + core.OPJ_PROFILE_CINEMA_4K): + image.contents.comps[k].prec = 12 + image.contents.comps[k].bpp = 12 + + layer = np.ascontiguousarray(imgdata[:, :, k], dtype=np.int32) + dest = image.contents.comps[k].data + src = layer.ctypes.data + ctypes.memmove(dest, src, layer.nbytes) + + return image + + def _populate_comptparms(self, img_array): + """Instantiate and populate comptparms structure. + + This structure defines the image components. + + Parameters + ---------- + img_array : ndarray + Image data to be written to file. + """ + # Only two precisions are possible. + if img_array.dtype == np.uint8: + comp_prec = 8 + else: + comp_prec = 16 + numrows, numcols, num_comps = img_array.shape + if version.openjpeg_version_tuple[0] == 1: + comptparms = (opj.ImageComptParmType * num_comps)() + else: + 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 + + def _component2dtype(component): """Take an OpenJPEG component structure and determine the numpy datatype. @@ -1704,92 +1772,6 @@ def extract_image_bands(image): return data -def _populate_comptparms(img_array, cparams): - """Instantiate and populate comptparms structure. - - This structure defines the image components. - - Parameters - ---------- - img_array : ndarray - Image data to be written to file. - cparams : CompressionParametersType(ctypes.Structure) - Corresponds to cparameters_t type in openjp2 headers. - - Returns - ------- - comptparms : ImageCompType(ctypes.Structure) - Corresponds to image_comp_t type in openjp2 headers. - """ - # Only two precisions are possible. - if img_array.dtype == np.uint8: - comp_prec = 8 - else: - comp_prec = 16 - - numrows, numcols, num_comps = img_array.shape - if version.openjpeg_version_tuple[0] == 1: - comptparms = (opj.ImageComptParmType * num_comps)() - else: - comptparms = (opj2.ImageComptParmType * num_comps)() - for j in range(num_comps): - comptparms[j].dx = cparams.subsampling_dx - comptparms[j].dy = cparams.subsampling_dy - comptparms[j].w = numcols - comptparms[j].h = numrows - comptparms[j].x0 = cparams.image_offset_x0 - comptparms[j].y0 = cparams.image_offset_y0 - comptparms[j].prec = comp_prec - comptparms[j].bpp = comp_prec - comptparms[j].sgnd = 0 - - return comptparms - - -def _populate_image_struct(cparams, image, imgdata): - """Populates image struct needed for compression. - - Parameters - ---------- - cparams : CompressionParametersType(ctypes.Structure) - Corresponds to cparameters_t type in openjp2 headers. - image : ImageType(ctypes.Structure) - Corresponds to image_t type in openjp2 headers. - imgarray : ndarray - Image data to be written to file. - """ - - numrows, numcols, num_comps = imgdata.shape - - # set image offset and reference grid - image.contents.x0 = cparams.image_offset_x0 - image.contents.y0 = cparams.image_offset_y0 - image.contents.x1 = (image.contents.x0 + - (numcols - 1) * cparams.subsampling_dx + 1) - image.contents.y1 = (image.contents.y0 + - (numrows - 1) * cparams.subsampling_dy + 1) - - # Stage the image data to the openjpeg data structure. - for k in range(0, num_comps): - if re.match("2.0", version.openjpeg_version) is not None: - # 2.0 API - if cparams.cp_cinema: - image.contents.comps[k].prec = 12 - image.contents.comps[k].bpp = 12 - else: - # 2.1 API - if cparams.rsiz in (core.OPJ_PROFILE_CINEMA_2K, - core.OPJ_PROFILE_CINEMA_4K): - image.contents.comps[k].prec = 12 - image.contents.comps[k].bpp = 12 - - layer = np.ascontiguousarray(imgdata[:, :, k], dtype=np.int32) - dest = image.contents.comps[k].data - src = layer.ctypes.data - ctypes.memmove(dest, src, layer.nbytes) - - return image - # Setup the default callback handlers. See the callback functions subsection # in the ctypes section of the Python documentation for a solid explanation of diff --git a/glymur/lib/openjp2.py b/glymur/lib/openjp2.py index f3f5b5c..f0a5f09 100644 --- a/glymur/lib/openjp2.py +++ b/glymur/lib/openjp2.py @@ -7,6 +7,7 @@ Wraps individual functions in openjp2 library. import ctypes import re import sys +import textwrap from .config import glymur_config @@ -138,6 +139,13 @@ class PocType(ctypes.Structure): ("tx0_t", ctypes.c_uint32), ("ty0_t", ctypes.c_uint32)] + def __str__(self): + msg = "{0}:\n".format(self.__class__) + for field_name, _ in self._fields_: + msg += " {0}: {1}\n".format( + field_name, getattr(self, field_name)) + return msg + class DecompressionParametersType(ctypes.Structure): """Decompression parameters. @@ -201,6 +209,13 @@ class DecompressionParametersType(ctypes.Structure): # maximum number of tiles ("flags", ctypes.c_uint32)] + def __str__(self): + msg = "{0}:\n".format(self.__class__) + for field_name, _ in self._fields_: + msg += " {0}: {1}\n".format( + field_name, getattr(self, field_name)) + return msg + class CompressionParametersType(ctypes.Structure): """Compression parameters. @@ -392,6 +407,47 @@ class CompressionParametersType(ctypes.Structure): # values. _fields_.append(("rsiz", ctypes.c_uint16)) + def __str__(self): + msg = "{0}:\n".format(self.__class__) + for field_name, _ in self._fields_: + + if field_name == 'poc': + msg += " numpocs: {0}\n".format(self.numpocs) + for j in range(self.numpocs): + msg += " [#{0}]:".format(j) + msg += " {0}".format(str(self.poc[j])) + msg += textwrap.indent(textstr, ' ' * 12) + + elif field_name in ['tcp_rates', 'tcp_distoratio']: + lst = [] + arr = getattr(self, field_name) + lst = [arr[j] for j in range(self.tcp_numlayers)] + msg += " {0}: {1}\n".format(field_name, lst) + + elif field_name in ['prcw_init', 'prch_init']: + pass + + elif field_name == 'res_spec': + prcw_init = [self.prcw_init[j] for j in range(self.res_spec)] + prch_init = [self.prch_init[j] for j in range(self.res_spec)] + msg += " res_spec: {0}\n".format(self.res_spec) + msg += " prch_init: {0}\n".format(prch_init) + msg += " prcw_init: {0}\n".format(prcw_init) + + elif field_name in [ + 'jpwl_hprot_tph_tileno', 'jpwl_hprot_tph', + 'jpwl_pprot_tileno', 'jpwl_pprot_packno', 'jpwl_pprot', + 'jpwl_sens_tph_tileno', 'jpwl_sens_tph']: + arr = getattr(self, field_name) + lst = [arr[j] for j in range(JPWL_MAX_NO_TILESPECS)] + msg += " {0}: {1}\n".format(field_name, lst) + + else: + msg += " {0}: {1}\n".format( + field_name, getattr(self, field_name)) + return msg + + class ImageCompType(ctypes.Structure): """Defines a single image component. @@ -433,6 +489,14 @@ class ImageCompType(ctypes.Structure): if _MINOR == '1': _fields_.append(("alpha", ctypes.c_uint16)) + def __str__(self): + msg = "{0}:\n".format(self.__class__) + for field_name, _ in self._fields_: + msg += " {0}: {1}\n".format( + field_name, getattr(self, field_name)) + return msg + + class ImageType(ctypes.Structure): """Defines image data and characteristics. @@ -463,6 +527,27 @@ class ImageType(ctypes.Structure): # restricted ICC profile buffer length ("icc_profile_len", ctypes.c_uint32)] + def __str__(self): + msg = "{0}:\n".format(self.__class__) + for field_name, _ in self._fields_: + + if field_name == "numcomps": + msg += " numcomps: {0}\n".format(self.numcomps) + for j in range(self.numcomps): + msg += " comps[#{0}]:\n".format(j) + msg += textwrap.indent(str(self.comps[j]), ' ' * 12) + + elif field_name == "comps": + # handled above + pass + + else: + msg += " {0}: {1}\n".format( + field_name, getattr(self, field_name)) + + return msg + + class ImageComptParmType(ctypes.Structure): """Component parameters structure used by image_create function. @@ -492,6 +577,13 @@ class ImageComptParmType(ctypes.Structure): # signed (1) / unsigned (0) ("sgnd", ctypes.c_uint32)] + def __str__(self): + msg = "{0}:\n".format(self.__class__) + for field_name, _ in self._fields_: + msg += " {0}: {1}\n".format( + field_name, getattr(self, field_name)) + return msg + class TccpInfo(ctypes.Structure): """Tile-component coding parameters information. diff --git a/glymur/lib/test/fixtures.py b/glymur/lib/test/fixtures.py new file mode 100644 index 0000000..b5b9648 --- /dev/null +++ b/glymur/lib/test/fixtures.py @@ -0,0 +1,144 @@ +decompression_parameters_type = """: + cp_reduce: 0 + cp_layer: 0 + infile: b'' + outfile: b'' + decod_format: -1 + cod_format: -1 + DA_x0: 0 + DA_x1: 0 + DA_y0: 0 + DA_y1: 0 + m_verbose: 0 + tile_index: 0 + nb_tile_to_decode: 0 + jpwl_correct: 0 + jpwl_exp_comps: 0 + jpwl_max_tiles: 0 + flags: 0""" + +default_progression_order_changes_type = """: + resno0: 0 + compno0: 0 + layno1: 0 + resno1: 0 + compno1: 0 + layno0: 0 + precno0: 0 + precno1: 0 + prg1: 0 + prg: 0 + progorder: b'' + tile: 0 + tx0: 0 + tx1: 0 + ty0: 0 + ty1: 0 + layS: 0 + resS: 0 + compS: 0 + prcS: 0 + layE: 0 + resE: 0 + compE: 0 + prcE: 0 + txS: 0 + txE: 0 + tyS: 0 + tyE: 0 + dx: 0 + dy: 0 + lay_t: 0 + res_t: 0 + comp_t: 0 + prec_t: 0 + tx0_t: 0 + ty0_t: 0""" + +default_compression_parameters_type = """: + tile_size_on: 0 + cp_tx0: 0 + cp_ty0: 0 + cp_tdx: 0 + cp_tdy: 0 + cp_disto_alloc: 0 + cp_fixed_alloc: 0 + cp_fixed_quality: 0 + cp_matrice: None + cp_comment: None + csty: 0 + prog_order: 0 + numpocs: 0 + numpocs: 0 + tcp_numlayers: 0 + tcp_rates: [] + tcp_distoratio: [] + numresolution: 6 + cblockw_init: 64 + cblockh_init: 64 + mode: 0 + irreversible: 0 + roi_compno: -1 + roi_shift: 0 + res_spec: 0 + prch_init: [] + prcw_init: [] + infile: b'' + outfile: b'' + index_on: 0 + index: b'' + image_offset_x0: 0 + image_offset_y0: 0 + subsampling_dx: 1 + subsampling_dy: 1 + decod_format: -1 + cod_format: -1 + jpwl_epc_on: 0 + jpwl_hprot_mh: 0 + jpwl_hprot_tph_tileno: [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0] + jpwl_hprot_tph: [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0] + jpwl_pprot_tileno: [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0] + jpwl_pprot_packno: [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0] + jpwl_pprot: [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0] + jpwl_sens_size: 0 + jpwl_sens_addr: 0 + jpwl_sens_range: 0 + jpwl_sens_mh: 0 + jpwl_sens_tph_tileno: [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0] + jpwl_sens_tph: [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0] + cp_cinema: 0 + max_comp_size: 0 + cp_rsiz: 0 + tp_on: 0 + tp_flag: 0 + tcp_mct: 0 + jpip_on: 0 + mct_data: None + max_cs_size: 0 + rsiz: 0""" + +default_image_component_parameters = """: + dx: 0 + dy: 0 + w: 0 + h: 0 + x0: 0 + y0: 0 + prec: 0 + bpp: 0 + sgnd: 0""" + +# The "icc_profile_buf" field is problematic as it is a pointer value, i.e. +# +# icc_profile_buf: +# +# Have to treat it as a regular expression. +default_image_type = """: + x0: 0 + y0: 0 + x1: 0 + y1: 0 + numcomps: 0 + color_space: 0 + icc_profile_buf: + icc_profile_len: 0""" diff --git a/glymur/lib/test/test_printing.py b/glymur/lib/test/test_printing.py new file mode 100644 index 0000000..3d0e2b6 --- /dev/null +++ b/glymur/lib/test/test_printing.py @@ -0,0 +1,77 @@ +# -*- coding: utf-8 -*- +"""Test suite for printing. +""" + +import re +import sys +import unittest + +if sys.hexversion < 0x03000000: + from mock import patch + from StringIO import StringIO +else: + from unittest.mock import patch + from io import StringIO + +import glymur +from . import fixtures + +@unittest.skipIf(sys.hexversion < 0x03000000, "do not care about 2.7 here") +@unittest.skipIf(re.match('1|2.0', glymur.version.openjpeg_version), + "Requires openjpeg 2.1.0 or higher") +class TestPrintingOpenjp2(unittest.TestCase): + """Tests for verifying how printing works on openjp2 library structures.""" + def setUp(self): + self.jp2file = glymur.data.nemo() + + def tearDown(self): + pass + + def test_decompression_parameters(self): + """printing DecompressionParametersType""" + dparams = glymur.lib.openjp2.set_default_decoder_parameters() + with patch('sys.stdout', new=StringIO()) as fake_out: + print(dparams) + actual = fake_out.getvalue().strip() + expected = fixtures.decompression_parameters_type + self.assertEqual(actual, expected) + + def test_progression_order_changes(self): + """printing PocType""" + ptype = glymur.lib.openjp2.PocType() + with patch('sys.stdout', new=StringIO()) as fake_out: + print(ptype) + actual = fake_out.getvalue().strip() + expected = fixtures.default_progression_order_changes_type + self.assertEqual(actual, expected) + + def test_default_compression_parameters(self): + """printing default compression parameters""" + cparams = glymur.lib.openjp2.set_default_encoder_parameters() + with patch('sys.stdout', new=StringIO()) as fake_out: + print(cparams) + actual = fake_out.getvalue().strip() + expected = fixtures.default_compression_parameters_type + self.assertEqual(actual, expected) + + def test_default_component_parameters(self): + """printing default image component parameters""" + icpt = glymur.lib.openjp2.ImageComptParmType() + with patch('sys.stdout', new=StringIO()) as fake_out: + print(icpt) + actual = fake_out.getvalue().strip() + expected = fixtures.default_image_component_parameters + self.assertEqual(actual, expected) + + def test_default_image_type(self): + """printing default image type""" + it = glymur.lib.openjp2.ImageType() + with patch('sys.stdout', new=StringIO()) as fake_out: + print(it) + actual = fake_out.getvalue().strip() + + expected = fixtures.default_image_type + self.assertRegex(actual, expected) + + + diff --git a/glymur/test/fixtures.py b/glymur/test/fixtures.py index 4b3972c..481da2d 100644 --- a/glymur/test/fixtures.py +++ b/glymur/test/fixtures.py @@ -900,3 +900,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_printing.py b/glymur/test/test_printing.py index 49bbe6d..b6eca2f 100644 --- a/glymur/test/test_printing.py +++ b/glymur/test/test_printing.py @@ -32,12 +32,13 @@ 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 -from .fixtures import WARNING_INFRASTRUCTURE_ISSUE, WARNING_INFRASTRUCTURE_MSG -from .fixtures import 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", "Temporary file issue on window.") +@unittest.skipIf(os.name == "nt", WINDOWS_TMP_FILE_MSG) class TestPrinting(unittest.TestCase): """Tests for verifying how printing works.""" def setUp(self): @@ -617,7 +618,6 @@ class TestPrinting(unittest.TestCase): 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.") From 3636939c12b604c4bc70909a13bf2f389217169d Mon Sep 17 00:00:00 2001 From: jevans Date: Tue, 21 Oct 2014 17:49:32 -0400 Subject: [PATCH 10/57] use end_decompress when decoding a tile, closes #285 had mistakenly only been using end_decompress when decoding by area --- glymur/jp2k.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/glymur/jp2k.py b/glymur/jp2k.py index aadb5ed..499fb29 100644 --- a/glymur/jp2k.py +++ b/glymur/jp2k.py @@ -1134,7 +1134,8 @@ class Jp2k(Jp2kBox): self._dparams.DA_x0, self._dparams.DA_y0, self._dparams.DA_x1, self._dparams.DA_y1) opj2.decode(codec, stream, image) - opj2.end_decompress(codec, stream) + + opj2.end_decompress(codec, stream) img_array = extract_image_cube(image) From ad423635860c93021d8dcf8ba33cc86ddd006132 Mon Sep 17 00:00:00 2001 From: jevans Date: Tue, 21 Oct 2014 18:02:16 -0400 Subject: [PATCH 11/57] fix error message when no OpenJPEG library can be found, closes #284 --- glymur/lib/config.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/glymur/lib/config.py b/glymur/lib/config.py index 431a00c..2254387 100644 --- a/glymur/lib/config.py +++ b/glymur/lib/config.py @@ -94,9 +94,9 @@ def load_library_handle(path): else: opj_lib = ctypes.CDLL(path) except (TypeError, OSError): - msg = '"Library {0}" could not be loaded. Operating in degraded mode.' - msg = msg.format(path) - warnings.warn(msg, UserWarning) + 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 From da25953de30ab2864fc413cb26dc569a195c3eb8 Mon Sep 17 00:00:00 2001 From: jevans Date: Tue, 21 Oct 2014 19:43:26 -0400 Subject: [PATCH 12/57] updated tests to run on fully loaded platform, closes #287 --- glymur/jp2k.py | 6 ++-- glymur/test/test_callbacks.py | 56 +++++++---------------------- glymur/test/test_jp2k.py | 36 +++++++++---------- glymur/test/test_opj_suite_write.py | 23 +++++++----- 4 files changed, 48 insertions(+), 73 deletions(-) diff --git a/glymur/jp2k.py b/glymur/jp2k.py index 499fb29..6817dbc 100644 --- a/glymur/jp2k.py +++ b/glymur/jp2k.py @@ -967,10 +967,10 @@ class Jp2k(Jp2kBox): >>> thumbnail.shape (728, 1296, 3) """ - if opj2.OPENJP2 is not None: - img = self._read_openjp2(**kwargs) - else: + if version.openjpeg_version_tuple[0] < 2: img = self._read_openjpeg(**kwargs) + else: + img = self._read_openjp2(**kwargs) return img def _subsampling_sanity_check(self): diff --git a/glymur/test/test_callbacks.py b/glymur/test/test_callbacks.py index e87b3af..ce3bb8c 100644 --- a/glymur/test/test_callbacks.py +++ b/glymur/test/test_callbacks.py @@ -25,8 +25,6 @@ import glymur from .fixtures import WARNING_INFRASTRUCTURE_ISSUE, WARNING_INFRASTRUCTURE_MSG -@unittest.skipIf(glymur.lib.openjp2.OPENJP2 is None, - "Missing openjp2 library.") class TestCallbacks(unittest.TestCase): """Test suite for callbacks.""" @@ -37,6 +35,8 @@ class TestCallbacks(unittest.TestCase): def tearDown(self): pass + @unittest.skipIf(glymur.version.openjpeg_version[0] != '2', + "Missing openjp2 library.") @unittest.skipIf(WARNING_INFRASTRUCTURE_ISSUE, WARNING_INFRASTRUCTURE_MSG) @unittest.skipIf(os.name == "nt", "Temporary file issue on window.") def test_info_callback_on_write(self): @@ -59,46 +59,20 @@ class TestCallbacks(unittest.TestCase): # callback handler is enabled. j = glymur.Jp2k(self.j2kfile) with patch('sys.stdout', new=StringIO()) as fake_out: - j.read(rlevel=1, verbose=True, area=(0, 0, 200, 150)) + j.read(rlevel=1, verbose=True) actual = fake_out.getvalue().strip() - lines = ['[INFO] Start to read j2k main header (0).', - '[INFO] Main header has been correctly decoded.', - '[INFO] Setting decoding area to 0,0,150,200', - '[INFO] Header of tile 0 / 0 has been read.', - '[INFO] Tile 1/1 has been decoded.', - '[INFO] Image data has been updated with tile 1.'] - - expected = '\n'.join(lines) - self.assertEqual(actual, expected) - - -@unittest.skipIf(glymur.lib.openjpeg.OPENJPEG is None, - "Missing openjpeg library.") -class TestCallbacks15(unittest.TestCase): - """This test suite is for OpenJPEG 1.5.1 properties. - """ - - def setUp(self): - self.jp2file = glymur.data.nemo() - self.j2kfile = glymur.data.goodstuff() - - def tearDown(self): - pass - - def test_info_callbacks_on_read(self): - """Verify stdout when reading. - - Verify that we get the expected stdio output when our internal info - callback handler is enabled. - """ - with patch('glymur.lib.openjp2.OPENJP2', new=None): - # Force to use OPENJPEG instead of OPENJP2. - j = glymur.Jp2k(self.j2kfile) - with patch('sys.stdout', new=StringIO()) as fake_out: - j.read(rlevel=1, verbose=True) - actual = fake_out.getvalue().strip() + if glymur.version.openjpeg_version[0] == '2': + lines = ['[INFO] Start to read j2k main header (0).', + '[INFO] Main header has been correctly decoded.', + '[INFO] No decoded area parameters, set the decoded area to the whole image', + '[INFO] Header of tile 0 / 0 has been read.', + '[INFO] Tile 1/1 has been decoded.', + '[INFO] Image data has been updated with tile 1.'] + expected = '\n'.join(lines) + self.assertEqual(actual, expected) + else: regex = re.compile(r"""\[INFO\]\stile\s1\sof\s1\s+ \[INFO\]\s-\stiers-1\stook\s [0-9]+\.[0-9]+\ss\s+ @@ -114,7 +88,3 @@ class TestCallbacks15(unittest.TestCase): self.assertRegexpMatches(actual, regex) else: self.assertRegex(actual, regex) - - -if __name__ == "__main__": - unittest.main() diff --git a/glymur/test/test_jp2k.py b/glymur/test/test_jp2k.py index 3800f44..61ebdce 100644 --- a/glymur/test/test_jp2k.py +++ b/glymur/test/test_jp2k.py @@ -987,8 +987,6 @@ class TestJp2k_write(unittest.TestCase): self.assertEqual(codestream.segment[2].spcod[0], glymur.core.CPRL) -@unittest.skipIf(glymur.version.openjpeg_version_tuple[0] >= 2, - "Negative tests only for version 1.x") class TestJp2k_1_x(unittest.TestCase): """Test suite for openjpeg 1.x, not appropriate for 2.x""" @@ -1002,32 +1000,32 @@ class TestJp2k_1_x(unittest.TestCase): def test_tile(self): """tile option not allowed for 1.x. """ - j2k = Jp2k(self.j2kfile) - with self.assertRaises(TypeError): - j2k.read(tile=0) + with patch('glymur.version.openjpeg_version_tuple', new=(1, 5, 0)): + j2k = Jp2k(self.j2kfile) + with self.assertRaises(TypeError): + j2k.read(tile=0) def test_layer(self): """layer option not allowed for 1.x. """ - j2k = Jp2k(self.j2kfile) - with self.assertRaises(TypeError): - j2k.read(layer=1) + with patch('glymur.version.openjpeg_version_tuple', new=(1, 5, 0)): + j2k = Jp2k(self.j2kfile) + with self.assertRaises(TypeError): + j2k.read(layer=1) -@unittest.skipIf(re.match(r'''2.0.0''', - glymur.version.openjpeg_version) is None, - "Tests only to be run on 2.0 official.") -class TestJp2k_2_0_official(unittest.TestCase): - """Test suite to only be run on v2.0 official.""" +@unittest.skipIf(os.name == "nt", fixtures.WINDOWS_TMP_FILE_MSG) +class Test_2p0_official(unittest.TestCase): + """Tests specific to v2.0.0""" - @unittest.skipIf(os.name == "nt", fixtures.WINDOWS_TMP_FILE_MSG) def test_extra_components_on_v2(self): """Can only write 4 components on 2.0+, should error out otherwise.""" - with tempfile.NamedTemporaryFile(suffix='.jp2') as tfile: - j = Jp2k(tfile.name, 'wb') - data = np.zeros((128, 128, 4), dtype=np.uint8) - with self.assertRaises(IOError): - j.write(data) + with patch('glymur.version.openjpeg_version', new="2.0.0"): + with tempfile.NamedTemporaryFile(suffix='.jp2') as tfile: + j = Jp2k(tfile.name, 'wb') + data = np.zeros((128, 128, 4), dtype=np.uint8) + with self.assertRaises(IOError): + j.write(data) @unittest.skipIf(glymur.version.openjpeg_version_tuple[0] < 2, diff --git a/glymur/test/test_opj_suite_write.py b/glymur/test/test_opj_suite_write.py index e0f947c..8be1cef 100644 --- a/glymur/test/test_opj_suite_write.py +++ b/glymur/test/test_opj_suite_write.py @@ -12,6 +12,11 @@ import sys import tempfile import unittest +if sys.hexversion <= 0x03030000: + from mock import patch +else: + from unittest.mock import patch + import numpy as np try: import skimage.io @@ -195,12 +200,10 @@ class WriteCinemaWarns(CinemaBase): @unittest.skipIf(NO_SKIMAGE_FREEIMAGE_SUPPORT, "Cannot read input image without scikit-image/freeimage") @unittest.skipIf(os.name == "nt", fixtures.WINDOWS_TMP_FILE_MSG) -@unittest.skipIf(not re.match("(1.5|2.0.0)", glymur.version.openjpeg_version), - "Functionality implemented for 2.0.1") @unittest.skipIf(OPJ_DATA_ROOT is None, "OPJ_OPJ_DATA_ROOT environment variable not set") -class TestSuiteNegative2pointzero(unittest.TestCase): - """Feature set not supported for versions less than 2.0""" +class TestNegative2pointzero(unittest.TestCase): + """Feature set not supported for versions less than 2.0.1""" def setUp(self): self.jp2file = glymur.data.nemo() @@ -210,13 +213,17 @@ class TestSuiteNegative2pointzero(unittest.TestCase): pass def test_cinema_mode(self): + """Cinema mode not allowed for anything less than 2.0.1""" relfile = 'input/nonregression/X_4_2K_24_185_CBR_WB_000.tif' infile = opj_data_file(relfile) data = skimage.io.imread(infile) - with tempfile.NamedTemporaryFile(suffix='.j2k') as tfile: - j = Jp2k(tfile.name, 'wb') - with self.assertRaises(IOError): - j.write(data, cinema2k=48) + versions = ["1.5.0", "2.0.0"] + for version in versions: + with patch('glymur.version.openjpeg_version', new=version): + with tempfile.NamedTemporaryFile(suffix='.j2k') as tfile: + j = Jp2k(tfile.name, 'wb') + with self.assertRaises(IOError): + j.write(data, cinema2k=48) @unittest.skipIf(re.match(r'''1.[0-4]''', openjpeg_version) is not None, From 1c87d982f8ca4c35a86cbb385b2764d7e74351df Mon Sep 17 00:00:00 2001 From: John Evans Date: Wed, 22 Oct 2014 09:44:51 -0400 Subject: [PATCH 13/57] add negative test for writing non-uint8-uint16 images, closes #281 Improved the error message. --- glymur/jp2k.py | 3 ++- glymur/test/test_jp2k.py | 8 ++++++++ 2 files changed, 10 insertions(+), 1 deletion(-) diff --git a/glymur/jp2k.py b/glymur/jp2k.py index 6817dbc..264bd43 100644 --- a/glymur/jp2k.py +++ b/glymur/jp2k.py @@ -545,7 +545,8 @@ class Jp2k(Jp2kBox): raise IOError(msg) if img_array.dtype != np.uint8 and img_array.dtype != np.uint16: - msg = "Only uint8 and uint16 images are currently supported." + msg = "Only uint8 and uint16 datatypes are currently supported " + msg += "when writing." raise RuntimeError(msg) def _determine_colorspace(self, img_array, colorspace=None, **kwargs): diff --git a/glymur/test/test_jp2k.py b/glymur/test/test_jp2k.py index 61ebdce..9df575f 100644 --- a/glymur/test/test_jp2k.py +++ b/glymur/test/test_jp2k.py @@ -843,6 +843,14 @@ class TestJp2k_write(unittest.TestCase): def tearDown(self): pass + def test_unsupported_datatype(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): + j = Jp2k(tfile.name, 'wb') + j.write(data) + def test_write_with_version_too_early(self): """Should raise a runtime error if trying to write with version 1.3""" data = np.zeros((128, 128), dtype=np.uint8) From fc4f5cec80c8a99217bd827797d68b69b1212e6f Mon Sep 17 00:00:00 2001 From: John Evans Date: Wed, 22 Oct 2014 15:34:13 -0400 Subject: [PATCH 14/57] add negative tests for bad precinct sizes, closes #280 --- glymur/test/test_jp2k.py | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/glymur/test/test_jp2k.py b/glymur/test/test_jp2k.py index 9df575f..3f3fa55 100644 --- a/glymur/test/test_jp2k.py +++ b/glymur/test/test_jp2k.py @@ -843,6 +843,22 @@ class TestJp2k_write(unittest.TestCase): def tearDown(self): pass + def test_precinct_size_too_small(self): + """first precinct size must be >= 2x that of the code block size""" + data = np.zeros((640, 480), dtype=np.uint8) + with tempfile.NamedTemporaryFile(suffix='.j2k') as tfile: + with self.assertRaises(IOError): + j = Jp2k(tfile.name, 'wb') + j.write(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): + j = Jp2k(tfile.name, 'wb') + j.write(data, cbsize=(16, 16), psizes=[(48, 48)]) + def test_unsupported_datatype(self): """Should raise a runtime error if trying to write uint32""" data = np.zeros((128, 128), dtype=np.uint32) From b9e44a4f8a09ed12f2805e05ea3975b9de0d4651 Mon Sep 17 00:00:00 2001 From: John Evans Date: Wed, 22 Oct 2014 18:58:11 -0400 Subject: [PATCH 15/57] re-enabled test_glymur_warning tests on linux/python3.3, closes #288 The origin issue was probably fixed during the whole #253, #255, #260, --- glymur/test/test_glymur_warnings.py | 2 -- 1 file changed, 2 deletions(-) diff --git a/glymur/test/test_glymur_warnings.py b/glymur/test/test_glymur_warnings.py index ebe445c..b8e5c8b 100644 --- a/glymur/test/test_glymur_warnings.py +++ b/glymur/test/test_glymur_warnings.py @@ -21,8 +21,6 @@ import glymur from .fixtures import opj_data_file, OPJ_DATA_ROOT from .fixtures import WARNING_INFRASTRUCTURE_ISSUE, WARNING_INFRASTRUCTURE_MSG -@unittest.skipIf(sys.hexversion < 0x03040000 and platform.system() == 'Linux', - "inexplicable failures on 3.3 and linux") @unittest.skipIf(OPJ_DATA_ROOT is None, "OPJ_DATA_ROOT environment variable not set") @unittest.skipIf(WARNING_INFRASTRUCTURE_ISSUE, WARNING_INFRASTRUCTURE_MSG) From 61cafc00b807fcbb7f58feeb3a814230738a63a6 Mon Sep 17 00:00:00 2001 From: jevans Date: Wed, 22 Oct 2014 20:02:55 -0400 Subject: [PATCH 16/57] remove FORMAT_CORPUS tests, closes #289 We don't lose any code coverage, so it's just one less thing to worry about. --- glymur/test/test_jp2box.py | 45 -------------------------------------- 1 file changed, 45 deletions(-) diff --git a/glymur/test/test_jp2box.py b/glymur/test/test_jp2box.py index 7246349..72daf17 100644 --- a/glymur/test/test_jp2box.py +++ b/glymur/test/test_jp2box.py @@ -40,12 +40,6 @@ from .fixtures import ( WINDOWS_TMP_FILE_MSG, MetadataBase ) -try: - FORMAT_CORPUS_DATA_ROOT = os.environ['FORMAT_CORPUS_DATA_ROOT'] -except KeyError: - FORMAT_CORPUS_DATA_ROOT = None - - def load_tests(loader, tests, ignore): """Run doc tests as well.""" if os.name == "nt": @@ -1338,42 +1332,3 @@ class TestRepr(MetadataBase): self.assertRegexpMatches(repr(box), regexp) else: self.assertRegex(repr(box), regexp) - - - -class TestJpxBoxes(unittest.TestCase): - """Tests for JPX boxes.""" - - def setUp(self): - pass - - def tearDown(self): - pass - - @unittest.skipIf(FORMAT_CORPUS_DATA_ROOT is None, - "FORMAT_CORPUS_DATA_ROOT environment variable not set") - def test_codestream_header(self): - """Should recognize codestream header box.""" - jfile = os.path.join(FORMAT_CORPUS_DATA_ROOT, - 'jp2k-formats/balloon.jpf') - jpx = Jp2k(jfile) - - # This superbox just happens to be empty. - self.assertEqual(jpx.box[4].box_id, 'jpch') - self.assertEqual(len(jpx.box[4].box), 0) - - @unittest.skipIf(FORMAT_CORPUS_DATA_ROOT is None, - "FORMAT_CORPUS_DATA_ROOT environment variable not set") - def test_compositing_layer_header(self): - """Should recognize compositing layer header box.""" - jfile = os.path.join(FORMAT_CORPUS_DATA_ROOT, - 'jp2k-formats/balloon.jpf') - jpx = Jp2k(jfile) - - # This superbox just happens to be empty. - self.assertEqual(jpx.box[5].box_id, 'jplh') - self.assertEqual(len(jpx.box[5].box), 0) - - -if __name__ == "__main__": - unittest.main() From 954e86a2abed68c43a9f97dc4df84ec2e0f492a0 Mon Sep 17 00:00:00 2001 From: jevans Date: Wed, 22 Oct 2014 20:23:45 -0400 Subject: [PATCH 17/57] added negative test for int32 imagery, closes #291 --- glymur/test/test_jp2k.py | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/glymur/test/test_jp2k.py b/glymur/test/test_jp2k.py index 3f3fa55..7c4e2a3 100644 --- a/glymur/test/test_jp2k.py +++ b/glymur/test/test_jp2k.py @@ -859,7 +859,15 @@ class TestJp2k_write(unittest.TestCase): j = Jp2k(tfile.name, 'wb') j.write(data, cbsize=(16, 16), psizes=[(48, 48)]) - def test_unsupported_datatype(self): + 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): + j = Jp2k(tfile.name, 'wb') + j.write(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: From 5aac62598130631d3a6b81ea75a7fe88f11115a4 Mon Sep 17 00:00:00 2001 From: John Evans Date: Thu, 23 Oct 2014 12:21:37 -0400 Subject: [PATCH 18/57] added test for None usage in config file, closes #293 --- glymur/lib/config.py | 4 ++-- glymur/test/test_config.py | 34 ++++++++++++++++++++-------------- 2 files changed, 22 insertions(+), 16 deletions(-) diff --git a/glymur/lib/config.py b/glymur/lib/config.py index 2254387..4b92b9d 100644 --- a/glymur/lib/config.py +++ b/glymur/lib/config.py @@ -84,8 +84,8 @@ def load_library_handle(path): 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. - # This is probably a very old linux. + # 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: diff --git a/glymur/test/test_config.py b/glymur/test/test_config.py index 37db88d..95170e7 100644 --- a/glymur/test/test_config.py +++ b/glymur/test/test_config.py @@ -94,17 +94,23 @@ class TestSuite(unittest.TestCase): with self.assertWarnsRegex(UserWarning, regex): imp.reload(glymur.lib.openjp2) - -@unittest.skipIf(glymur.lib.openjp2.OPENJP2 is None and - glymur.lib.openjpeg.OPENJPEG is None, - "Missing openjp2 library.") -class TestConfig(unittest.TestCase): - """Test suite for reading without proper library in place.""" - - def setUp(self): - self.jp2file = glymur.data.nemo() - self.j2kfile = glymur.data.goodstuff() - - def tearDown(self): - pass - + @unittest.skipIf(glymur.lib.openjp2.OPENJPEG is None, + "Needs openjp2 and openjpeg before this test make sense.") + @unittest.skipIf(os.name == "nt", WINDOWS_TMP_FILE_MSG) + def test_library_specified_as_None(self): + """Verify that we can stop a library from being loaded by using None.""" + with tempfile.TemporaryDirectory() as tdir: + configdir = os.path.join(tdir, 'glymur') + os.mkdir(configdir) + fname = os.path.join(configdir, 'glymurrc') + with open(fname, 'w') as fptr: + # Essentially comment out openjp2 and preferentially load + # openjpeg instead. + fptr.write('[library]\n') + fptr.write('openjp2: None\n') + 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) + self.assertIsNone(glymur.lib.openjp2.OPENJP2) + self.assertIsNotNone(glymur.lib.openjp2.OPENJPEG) From d36f521b6106d628fdaa6eebe4d69b36d1147180 Mon Sep 17 00:00:00 2001 From: John Evans Date: Fri, 24 Oct 2014 09:48:47 -0400 Subject: [PATCH 19/57] added test for case when config dir is empty, closes #290 --- glymur/test/test_config.py | 29 ++++++++++++++++++++++++++++- 1 file changed, 28 insertions(+), 1 deletion(-) diff --git a/glymur/test/test_config.py b/glymur/test/test_config.py index 95170e7..5246f1e 100644 --- a/glymur/test/test_config.py +++ b/glymur/test/test_config.py @@ -10,7 +10,7 @@ OPENJP2 may be present in some form or other. # unittest.mock only in Python 3.3 (python2.7/pylint import issue) # pylint: disable=E0611,F0401 - +import ctypes import imp import os import sys @@ -30,6 +30,16 @@ from .fixtures import ( 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. + """ + if ctypes.util.find_library('openjpeg') is None: + return True + else: + return False + @unittest.skipIf(sys.hexversion < 0x03020000, "TemporaryDirectory introduced in 3.2.") @@ -114,3 +124,20 @@ class TestSuite(unittest.TestCase): imp.reload(glymur.lib.openjp2) self.assertIsNone(glymur.lib.openjp2.OPENJP2) self.assertIsNotNone(glymur.lib.openjp2.OPENJPEG) + + @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 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 being empty. + imp.reload(glymur.lib.openjpeg) + self.assertIsNotNone(glymur.lib.openjp2.OPENJPEG) From 5c262025b316ab4834e9854e658d189b43523f98 Mon Sep 17 00:00:00 2001 From: jevans Date: Fri, 24 Oct 2014 19:32:21 -0400 Subject: [PATCH 20/57] fix test to pick up library on macports, closes #290 The environment DYLD_FALLBACK_LIBRARY_PATH helps to find macports libraries in /opt/local/lib --- glymur/test/test_config.py | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/glymur/test/test_config.py b/glymur/test/test_config.py index 5246f1e..ac24b89 100644 --- a/glymur/test/test_config.py +++ b/glymur/test/test_config.py @@ -35,10 +35,11 @@ def openjpeg_not_found_by_ctypes(): Need to know if openjpeg library can be picked right up by ctypes for one of the tests. """ - if ctypes.util.find_library('openjpeg') is None: - return True - else: - return False + 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 @unittest.skipIf(sys.hexversion < 0x03020000, From 351ae294d6b0fdb0c02e70ae989c14eedab9ec30 Mon Sep 17 00:00:00 2001 From: jevans Date: Fri, 24 Oct 2014 20:33:01 -0400 Subject: [PATCH 21/57] add test for config file in current directory, closes #292 --- glymur/test/test_config.py | 37 +++++++++++++++++++++++++++++++++++++ 1 file changed, 37 insertions(+) diff --git a/glymur/test/test_config.py b/glymur/test/test_config.py index ac24b89..feb3235 100644 --- a/glymur/test/test_config.py +++ b/glymur/test/test_config.py @@ -10,6 +10,7 @@ OPENJP2 may be present in some form or other. # unittest.mock only in Python 3.3 (python2.7/pylint import issue) # pylint: disable=E0611,F0401 +import contextlib import ctypes import imp import os @@ -42,6 +43,26 @@ def openjpeg_not_found_by_ctypes(): return False +@contextlib.contextmanager +def chdir(dirname=None): + """ + This context manager restores the value of the current working directory + (cwd) after the enclosed code block completes or raises an exception. If a + directory name is supplied to the context manager then the cwd is changed + prior to running the code block. + + Shamelessly lifted from + http://www.astropython.org/snippet/2009/10/chdir-context-manager + """ + curdir = os.getcwd() + try: + if dirname is not None: + os.chdir(dirname) + yield + finally: + os.chdir(curdir) + + @unittest.skipIf(sys.hexversion < 0x03020000, "TemporaryDirectory introduced in 3.2.") @unittest.skipIf(glymur.lib.openjp2.OPENJP2 is None, @@ -142,3 +163,19 @@ class TestSuite(unittest.TestCase): # configuration file being empty. imp.reload(glymur.lib.openjpeg) self.assertIsNotNone(glymur.lib.openjp2.OPENJPEG) + + @unittest.skipIf(os.name == "nt", WINDOWS_TMP_FILE_MSG) + def test_config_file_in_current_directory(self): + """A configuration file in the current directory should be honored.""" + libloc = glymur.lib.openjp2.OPENJP2._name + with tempfile.TemporaryDirectory() as tdir1: + fname = os.path.join(tdir1, 'glymurrc') + with open(fname, 'w') as fptr: + fptr.write('[library]\n') + fptr.write('openjp2: {0}\n'.format(libloc)) + fptr.flush() + with chdir(tdir1): + # Should be able to load openjp2 as before. + imp.reload(glymur.lib.openjp2) + self.assertEqual(glymur.lib.openjp2.OPENJP2._name, libloc) + From 4ffb46833fc563da9e4d32714fbffac962df039c Mon Sep 17 00:00:00 2001 From: jevans Date: Fri, 24 Oct 2014 21:21:54 -0400 Subject: [PATCH 22/57] fixed printing of j2k files with "-c 0", closes #294 It's kind of meaningless to supply that option with a raw codestream, but if it's what the user wanted to do, then it's what the user wanted to do. --- glymur/command_line.py | 14 +++++++++----- glymur/test/test_printing.py | 9 +++++++++ 2 files changed, 18 insertions(+), 5 deletions(-) diff --git a/glymur/command_line.py b/glymur/command_line.py index 62b9057..bf96293 100644 --- a/glymur/command_line.py +++ b/glymur/command_line.py @@ -2,9 +2,11 @@ Entry point for console script jp2dump. """ import argparse +import os import sys import warnings -from . import Jp2k, set_printoptions + +from . import Jp2k, set_printoptions, lib def main(): """ @@ -55,11 +57,13 @@ def main(): # JP2 metadata can be extensive, so don't print any warnings until we # are done with the metadata. - j = Jp2k(filename) - if print_full_codestream: - print(j.get_codestream(header_only=False)) + jp2 = Jp2k(filename) + 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(j) + print(jp2) # Re-emit any warnings that may have been suppressed. if len(wctx) > 0: diff --git a/glymur/test/test_printing.py b/glymur/test/test_printing.py index b6eca2f..73ded9c 100644 --- a/glymur/test/test_printing.py +++ b/glymur/test/test_printing.py @@ -1102,3 +1102,12 @@ class TestJp2dump(unittest.TestCase): actual = self.run_jp2dump(['', '-x', self.jp2file]) self.assertEqual(actual, fixtures.nemo_dump_no_codestream_no_xml) + + 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: .*") + From aef47ed318ff77903ba914a8df804b58e5e4fbe2 Mon Sep 17 00:00:00 2001 From: jevans Date: Fri, 24 Oct 2014 21:58:08 -0400 Subject: [PATCH 23/57] skip test on 2.7, closes #294 assertRegex not available --- glymur/test/test_printing.py | 1 + 1 file changed, 1 insertion(+) diff --git a/glymur/test/test_printing.py b/glymur/test/test_printing.py index 73ded9c..7a5f9b9 100644 --- a/glymur/test/test_printing.py +++ b/glymur/test/test_printing.py @@ -1103,6 +1103,7 @@ class TestJp2dump(unittest.TestCase): 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] From a713d44238a68c553eb08f35fd7b5a160e7894cd Mon Sep 17 00:00:00 2001 From: jevans Date: Sat, 25 Oct 2014 11:22:19 -0400 Subject: [PATCH 24/57] added shape attribute, closes #295 --- glymur/jp2k.py | 37 +++++++++++++++++++++++++++++ glymur/test/test_jp2k.py | 38 ++++++++++++++++++++++++++++++ glymur/test/test_opj_suite_dump.py | 2 +- 3 files changed, 76 insertions(+), 1 deletion(-) diff --git a/glymur/jp2k.py b/glymur/jp2k.py index 264bd43..b7c82ee 100644 --- a/glymur/jp2k.py +++ b/glymur/jp2k.py @@ -77,11 +77,48 @@ class Jp2k(Jp2kBox): self.box = [] self._codec_format = None self._colorspace = None + self._shape = None # Parse the file for JP2/JPX contents only if we are reading it. if mode == 'rb': self.parse() + @property + def shape(self): + if self._shape is not None: + return self._shape + + 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: + 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) + + return self._shape + + @shape.setter + def shape(self, shape): + self._shape = shape + def __repr__(self): msg = "glymur.Jp2k('{0}')".format(self.filename) return msg diff --git a/glymur/test/test_jp2k.py b/glymur/test/test_jp2k.py index 7c4e2a3..9a9fb72 100644 --- a/glymur/test/test_jp2k.py +++ b/glymur/test/test_jp2k.py @@ -476,6 +476,44 @@ class TestJp2k(unittest.TestCase): def tearDown(self): pass + def test_shape_jp2(self): + """verify shape attribute for JP2 file + """ + jp2 = Jp2k(self.jp2file) + self.assertEqual(jp2.shape, (1456, 2592, 3)) + + @unittest.skipIf(OPJ_DATA_ROOT is None, + "OPJ_DATA_ROOT environment variable not set") + def test_shape_greyscale_jp2(self): + """verify shape attribute for greyscale JP2 file + """ + with warnings.catch_warnings(): + # Suppress a warning due to bad compatibility list entry. + warnings.simplefilter("ignore") + jfile = opj_data_file('input/conformance/file4.jp2') + jp2 = Jp2k(jfile) + self.assertEqual(jp2.shape, (512, 768)) + + @unittest.skipIf(OPJ_DATA_ROOT is None, + "OPJ_DATA_ROOT environment variable not set") + def test_shape_single_channel_j2k(self): + """verify shape attribute for single channel J2K file + """ + jfile = opj_data_file('input/conformance/p0_01.j2k') + jp2 = Jp2k(jfile) + self.assertEqual(jp2.shape, (128, 128)) + + def test_shape_j2k(self): + """verify shape attribute for J2K file + """ + j2k = Jp2k(self.j2kfile) + self.assertEqual(j2k.shape, (800, 480, 3)) + + def test_shape_jpx_jp2(self): + """verify shape attribute for JPX file with JP2 compatibility + """ + jpx = Jp2k(self.jpxfile) + self.assertEqual(jpx.shape, (1024, 1024, 3)) @unittest.skipIf(os.name == "nt", "Unexplained failure on windows") def test_irreversible(self): diff --git a/glymur/test/test_opj_suite_dump.py b/glymur/test/test_opj_suite_dump.py index 76dc444..8201c9f 100644 --- a/glymur/test/test_opj_suite_dump.py +++ b/glymur/test/test_opj_suite_dump.py @@ -3052,7 +3052,7 @@ class TestSuiteWarns(MetadataBase): self.assertEqual(codestream.segment[1].yrsiz[2], 2) def test_NR_file4_dump(self): - # One 8-bit component in the sRGB-grey colourspace. + # One 8-bit component in the grey colourspace. jfile = opj_data_file('input/conformance/file4.jp2') with self.assertWarns(UserWarning): jp2 = Jp2k(jfile) From 1782cb957fa948bccccaccc6c1f98e2b172f0c3b Mon Sep 17 00:00:00 2001 From: John Evans Date: Thu, 30 Oct 2014 11:48:20 -0400 Subject: [PATCH 25/57] removed img_array from private _determine_colorspace method, closes #297 --- glymur/jp2k.py | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) diff --git a/glymur/jp2k.py b/glymur/jp2k.py index b7c82ee..f36b75e 100644 --- a/glymur/jp2k.py +++ b/glymur/jp2k.py @@ -443,7 +443,8 @@ class Jp2k(Jp2kBox): raise RuntimeError("You must have at least version 1.5 of OpenJPEG " "in order to write images.") - self._determine_colorspace(img_array, **kwargs) + self._shape = img_array.shape + self._determine_colorspace(**kwargs) self._populate_cparams(img_array, **kwargs) if opj2.OPENJP2 is not None: @@ -586,22 +587,20 @@ class Jp2k(Jp2kBox): msg += "when writing." raise RuntimeError(msg) - def _determine_colorspace(self, img_array, colorspace=None, **kwargs): + def _determine_colorspace(self, colorspace=None, **kwargs): """Determine the colorspace from the supplied inputs. Parameters ---------- - img_array : ndarray - Image data to be written to file. colorspace : str, optional Either 'rgb' or 'gray'. """ if colorspace is None: # Must infer the colorspace from the image dimensions. - if img_array.ndim < 3: + if len(self.shape) < 3: # A single channel image is grayscale. self._colorspace = opj2.CLRSPC_GRAY - elif img_array.shape[2] == 1 or img_array.shape[2] == 2: + elif self.shape[2] == 1 or self.shape[2] == 2: # A single channel image or an image with two channels is going # to be greyscale. self._colorspace = opj2.CLRSPC_GRAY @@ -612,7 +611,7 @@ class Jp2k(Jp2kBox): if colorspace.lower() not in ('rgb', 'grey', 'gray'): msg = 'Invalid colorspace "{0}"'.format(colorspace) raise IOError(msg) - elif colorspace.lower() == 'rgb' and img_array.shape[2] < 3: + elif colorspace.lower() == 'rgb' and self.shape[2] < 3: msg = 'RGB colorspace requires at least 3 components.' raise IOError(msg) From 1f0d0c37865b91f908c2a338f57f6729616dee83 Mon Sep 17 00:00:00 2001 From: jevans Date: Wed, 5 Nov 2014 20:33:10 -0500 Subject: [PATCH 26/57] deleted TccpInfo, TileInfoV2, CodestreamInvoV2 classes They are used in tests, but not in top-level glymur classes. --- glymur/lib/openjp2.py | 101 -------------------------------- glymur/lib/test/test_openjp2.py | 94 ----------------------------- 2 files changed, 195 deletions(-) diff --git a/glymur/lib/openjp2.py b/glymur/lib/openjp2.py index f0a5f09..5e58cf4 100644 --- a/glymur/lib/openjp2.py +++ b/glymur/lib/openjp2.py @@ -585,107 +585,6 @@ class ImageComptParmType(ctypes.Structure): return msg -class TccpInfo(ctypes.Structure): - """Tile-component coding parameters information. - - Corresponds to tccp_info_t type in openjp2 header file. - """ - _fields_ = [ - # component index - ("compno", ctypes.c_uint32), - - # coding style - ("csty", ctypes.c_uint32), - - # number of resolutions - ("numresolutions", ctypes.c_uint32), - - # code-blocks width - ("cblkw", ctypes.c_uint32), - - # code-blocks height - ("cblkh", ctypes.c_uint32), - - # code-block coding style - ("cblksty", ctypes.c_uint32), - - # discrete wavelet transform identifier - ("qmfbid", ctypes.c_uint32), - - # quantization style - ("qntsty", ctypes.c_uint32), - - # stepsizes used for quantization - ("stepsizes_mant", ctypes.c_uint32 * J2K_MAXBANDS), - ("stepsizes_expn", ctypes.c_uint32 * J2K_MAXBANDS), - - # stepsizes used for quantization - ("numgbits", ctypes.c_uint32), - - # region of interest shift - ("roishift", ctypes.c_int32), - - # precinct width - ("prcw", ctypes.c_uint32 * J2K_MAXRLVLS), - - # precinct width - ("prch", ctypes.c_uint32 * J2K_MAXRLVLS)] - - -class TileInfoV2(ctypes.Structure): - """Tile coding parameters information - - Corresponds to tile_info_v2_t type in openjp2 headers. - """ - _fields_ = [ - # number (index) of tile - ("tileno", ctypes.c_int32), - - # coding style - ("csty", ctypes.c_uint32), - - # progression order - ("prg", PROG_ORDER_TYPE), - - # number of layers - ("numlayers", ctypes.c_uint32), - - # multi-component transform identifier - ("mct", ctypes.c_uint32), - - # information concerning tile component parameters - ("tccp_info", ctypes.POINTER(TccpInfo))] - - -class CodestreamInfoV2(ctypes.Structure): - """information about the codestream. - - Corresponds to codestream_info_v2_t type in openjp2 header files. - """ - _fields_ = [ - # tile info - # tile origin in x, y (XTOsiz, YTOsiz) - ("tx0", ctypes.c_uint32), - ("ty0", ctypes.c_uint32), - - # tile size in x, y = XTsiz, YTsiz - ("tdx", ctypes.c_uint32), - ("tdy", ctypes.c_uint32), - - # number of tiles in X, Y - ("tw", ctypes.c_uint32), - ("th", ctypes.c_uint32), - - # number of components - ("nbcomps", ctypes.c_uint32), - - # default information regarding tiles inside of image - ("m_default_tile_info", TileInfoV2), - - # information regarding tiles inside of image - ("tile_info", ctypes.POINTER(TileInfoV2))] - - def check_error(status): """Set a generic function as the restype attribute of all OpenJPEG functions that return a BOOL_TYPE value. This way we do not have to check diff --git a/glymur/lib/test/test_openjp2.py b/glymur/lib/test/test_openjp2.py index 70ef9b6..988ace1 100644 --- a/glymur/lib/test/test_openjp2.py +++ b/glymur/lib/test/test_openjp2.py @@ -56,53 +56,6 @@ class TestOpenJP2(unittest.TestCase): self.assertEqual(dparams.DA_x1, 0) self.assertEqual(dparams.DA_y1, 0) - def tile_macro(self, codec, stream, imagep, tidx): - """called only by j2k_random_tile_access""" - openjp2.get_decoded_tile(codec, stream, imagep, tidx) - for j in range(imagep.contents.numcomps): - self.assertIsNotNone(imagep.contents.comps[j].data) - - def j2k_random_tile_access(self, filename, codec_format=None): - """fixture called by the test_rtaX methods""" - dparam = openjp2.set_default_decoder_parameters() - - infile = filename.encode() - nelts = openjp2.PATH_LEN - len(infile) - infile += b'0' * nelts - dparam.infile = infile - - dparam.decod_format = codec_format - - codec = openjp2.create_decompress(codec_format) - - openjp2.set_info_handler(codec, None) - openjp2.set_warning_handler(codec, None) - openjp2.set_error_handler(codec, None) - - stream = openjp2.stream_create_default_file_stream(filename, True) - - openjp2.setup_decoder(codec, dparam) - image = openjp2.read_header(stream, codec) - - cstr_info = openjp2.get_cstr_info(codec) - - tile_ul = 0 - tile_ur = cstr_info.contents.tw - 1 - tile_lr = cstr_info.contents.tw * cstr_info.contents.th - 1 - tile_ll = tile_lr - cstr_info.contents.tw - - self.tile_macro(codec, stream, image, tile_ul) - self.tile_macro(codec, stream, image, tile_ur) - self.tile_macro(codec, stream, image, tile_lr) - self.tile_macro(codec, stream, image, tile_ll) - - openjp2.destroy_cstr_info(cstr_info) - - openjp2.end_decompress(codec, stream) - openjp2.destroy_codec(codec) - openjp2.stream_destroy(stream) - openjp2.image_destroy(image) - def test_tte0(self): """Runs test designated tte0 in OpenJPEG test suite.""" with tempfile.NamedTemporaryFile(suffix=".j2k") as tfile: @@ -160,15 +113,6 @@ class TestOpenJP2(unittest.TestCase): tile_decoder(**kwargs) self.assertTrue(True) - def test_rta1(self): - """Runs test designated rta1 in OpenJPEG test suite.""" - with tempfile.NamedTemporaryFile(suffix=".j2k") as tfile: - self.xtx1_setup(tfile.name) - - codec_format = openjp2.CODEC_J2K - self.j2k_random_tile_access(tfile.name, codec_format) - self.assertTrue(True) - def test_tte2(self): """Runs test designated tte2 in OpenJPEG test suite.""" with tempfile.NamedTemporaryFile(suffix=".jp2") as tfile: @@ -190,62 +134,24 @@ class TestOpenJP2(unittest.TestCase): tile_decoder(**kwargs) self.assertTrue(True) - def test_rta2(self): - """Runs test designated rta2 in OpenJPEG test suite.""" - with tempfile.NamedTemporaryFile(suffix=".jp2") as tfile: - xtx2_setup(tfile.name) - - codec_format = openjp2.CODEC_JP2 - self.j2k_random_tile_access(tfile.name, codec_format) - def test_tte3(self): """Runs test designated tte3 in OpenJPEG test suite.""" with tempfile.NamedTemporaryFile(suffix=".j2k") as tfile: xtx3_setup(tfile.name) self.assertTrue(True) - def test_rta3(self): - """Runs test designated rta3 in OpenJPEG test suite.""" - with tempfile.NamedTemporaryFile(suffix=".j2k") as tfile: - xtx3_setup(tfile.name) - - codec_format = openjp2.CODEC_J2K - self.j2k_random_tile_access(tfile.name, codec_format) - self.assertTrue(True) - def test_tte4(self): """Runs test designated tte4 in OpenJPEG test suite.""" with tempfile.NamedTemporaryFile(suffix=".j2k") as tfile: xtx4_setup(tfile.name) self.assertTrue(True) - def test_rta4(self): - """Runs test designated rta4 in OpenJPEG test suite.""" - with tempfile.NamedTemporaryFile(suffix=".j2k") as tfile: - xtx4_setup(tfile.name) - - codec_format = openjp2.CODEC_J2K - self.j2k_random_tile_access(tfile.name, codec_format) - def test_tte5(self): """Runs test designated tte5 in OpenJPEG test suite.""" with tempfile.NamedTemporaryFile(suffix=".j2k") as tfile: xtx5_setup(tfile.name) self.assertTrue(True) - def test_rta5(self): - """Runs test designated rta5 in OpenJPEG test suite.""" - with tempfile.NamedTemporaryFile(suffix=".j2k") as tfile: - xtx5_setup(tfile.name) - - codec_format = openjp2.CODEC_J2K - self.j2k_random_tile_access(tfile.name, codec_format) - - -#def tile_encoder(num_comps=None, tile_width=None, tile_height=None, -# filename=None, codec=None, comp_prec=None, -# image_width=None, image_height=None, -# irreversible=None): def tile_encoder(**kwargs): """Fixture used by many tests.""" num_tiles = ((kwargs['image_width'] / kwargs['tile_width']) * From eeee8ae9dc304276cfffd403da5f399c9ff1d161 Mon Sep 17 00:00:00 2001 From: jevans Date: Wed, 5 Nov 2014 20:47:53 -0500 Subject: [PATCH 27/57] modified travis config for coveralls support --- .travis.yml | 6 ++++++ 1 file changed, 6 insertions(+) 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" From 29dfce792767624c839c7140ec31abf618a9c660 Mon Sep 17 00:00:00 2001 From: jevans Date: Mon, 17 Nov 2014 21:07:36 -0500 Subject: [PATCH 28/57] warn instead of raising IOError if openjpeg library cannot be found Improve error message when trying to read without openjpeg library. --- glymur/jp2k.py | 10 ++++------ glymur/lib/config.py | 2 +- 2 files changed, 5 insertions(+), 7 deletions(-) diff --git a/glymur/jp2k.py b/glymur/jp2k.py index d460ea6..e4a1a01 100644 --- a/glymur/jp2k.py +++ b/glymur/jp2k.py @@ -937,10 +937,8 @@ class Jp2k(Jp2kBox): elif opj.OPENJPEG is not None: img = self._read_openjpeg(**kwargs) else: - raise LibraryNotFoundError("You must have either a recent version " - "of OpenJPEG or the development " - "version of OpenJP2 installed before " - "using this functionality.") + raise LibraryNotFoundError("You must have OpenJPEG installed " + "before reading a JPEG2000 image.") return img def _subsampling_sanity_check(self): @@ -1235,8 +1233,8 @@ class Jp2k(Jp2kBox): """ if version.openjpeg_version_tuple[0] < 2: raise LibraryNotFoundError("You must have at least version 2.0.0 " - "of OpenJP2 installed before using " - "this functionality.") + "of OpenJPEG installed before using " + "read_bands.") dparam = self._populate_dparam(rlevel, ignore_pclr_cmap_cdef, layer=layer, tile=tile, area=area) diff --git a/glymur/lib/config.py b/glymur/lib/config.py index 04aece2..dc8ab29 100644 --- a/glymur/lib/config.py +++ b/glymur/lib/config.py @@ -146,7 +146,7 @@ def glymur_config(): libopenjpeg_handle = load_openjpeg(libs['openjpeg']) if libopenjp2_handle is None and libopenjpeg_handle is None: msg = "Neither the openjp2 nor the openjpeg library could be loaded. " - raise IOError(msg) + warnings.warn(msg, UserWarning) return libopenjp2_handle, libopenjpeg_handle From 5e2bfc21edf95f36640c29d2a9eef5c7c17fda7b Mon Sep 17 00:00:00 2001 From: jevans Date: Mon, 17 Nov 2014 21:07:36 -0500 Subject: [PATCH 29/57] add back read support for metadata if library not installed, 0.7.3 release --- CHANGES.txt | 3 +++ docs/source/conf.py | 2 +- docs/source/detailed_installation.rst | 5 ++++- docs/source/roadmap.rst | 9 --------- docs/source/whatsnew/0.7.rst | 16 ++++++++++++++-- docs/source/whatsnew/index.rst | 4 ++-- glymur/jp2k.py | 10 ++++------ glymur/lib/config.py | 2 +- glymur/test/fixtures.py | 9 +++++++++ glymur/test/test_jp2box.py | 5 ++++- glymur/test/test_jp2k.py | 16 +++++++++++++--- glymur/test/test_opj_suite.py | 7 +++++++ glymur/test/test_opj_suite_2p1.py | 5 +++++ glymur/test/test_printing.py | 4 ++++ glymur/version.py | 2 +- 15 files changed, 72 insertions(+), 27 deletions(-) diff --git a/CHANGES.txt b/CHANGES.txt index 758941b..a3179f6 100644 --- a/CHANGES.txt +++ b/CHANGES.txt @@ -1,3 +1,6 @@ +Nov 18, 2014 - v0.7.3 Added read support back for metadata when the + library is not installed. + 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/conf.py b/docs/source/conf.py index 8a87a64..9704a89 100644 --- a/docs/source/conf.py +++ b/docs/source/conf.py @@ -78,7 +78,7 @@ copyright = u'2013, John Evans' # The short X.Y version. version = '0.7' # The full version, including alpha/beta/rc tags. -release = '0.7.2' +release = '0.7.3' # The language for content autogenerated by Sphinx. Refer to documentation # for a list of supported languages. diff --git a/docs/source/detailed_installation.rst b/docs/source/detailed_installation.rst index 1a9281c..2401048 100644 --- a/docs/source/detailed_installation.rst +++ b/docs/source/detailed_installation.rst @@ -6,7 +6,7 @@ Advanced Installation Instructions Glymur Configuration '''''''''''''''''''''' -The default glymur installation process relies upon OpenJPEG being +The default glymur installation process expects OpenJPEG to be properly installed on your system as a shared library. If you have OpenJPEG installed through your system’s package manager on linux or if you use MacPorts on the mac, you are probably already set to @@ -50,6 +50,9 @@ installed in a non-standard place, i.e. :: [library] openjpeg: /somewhere/lib/libopenjpeg.so +If your platform is windows, it is strongly recommended that you compile the +2.1.0 version of the openjpeg library from source. + ''''''' Testing ''''''' diff --git a/docs/source/roadmap.rst b/docs/source/roadmap.rst index 503fbc4..f0d7017 100644 --- a/docs/source/roadmap.rst +++ b/docs/source/roadmap.rst @@ -1,12 +1,3 @@ -------------------------------------- -Platforms Tested (0.7.0 release only) -------------------------------------- - * Linux Mint 17 / Python 3.4.0 and 2.7.6 / OpenJPEG 2.1.0 and 1.3.0 - * MacOS 10.6.8 / MacPorts Python 3.4.1, 3.3.5,and 2.7.8 / OpenJPEG 2.1.0 - * CentOS 6.5 / Anaconda Python 3.4.1 / OpenJPEG 1.3.0 - * Fedora 20 i386 / Python 2.7.5 and 3.3.2 / OpenJPEG 1.5.1 - * Windows 7 32bit / Anaconda Python 2.7.6 and 3.4.1 / OpenJPEG 2.1.0 - ------------ Known Issues ------------ diff --git a/docs/source/whatsnew/0.7.rst b/docs/source/whatsnew/0.7.rst index 0a21d9b..e3a541d 100644 --- a/docs/source/whatsnew/0.7.rst +++ b/docs/source/whatsnew/0.7.rst @@ -2,10 +2,22 @@ Changes in glymur 0.7 ===================== +Changes in 0.7.3 +================= + * added read support back for metadata only when the OpenJPEG library is not installed + +Changes in 0.7.2 +================= + * added ellipsis support in array-style slicing + +Changes in 0.7.1 +================= + * fixed release notes regarding Python 3.4 + Changes in 0.7.0 ================= - * implemented :py:meth:`__getitem__`, :py:meth:`__setitem__` support + * implemented array-style slicing * added back windows support * box_id and longname are class attributes now instead of instance - attributes (see issue 248) + attributes diff --git a/docs/source/whatsnew/index.rst b/docs/source/whatsnew/index.rst index 2d69949..38d0435 100644 --- a/docs/source/whatsnew/index.rst +++ b/docs/source/whatsnew/index.rst @@ -8,6 +8,6 @@ These document the changes between minor (or major) versions of glymur. .. toctree:: - 0.5 - 0.6 0.7 + 0.6 + 0.5 diff --git a/glymur/jp2k.py b/glymur/jp2k.py index d460ea6..e4a1a01 100644 --- a/glymur/jp2k.py +++ b/glymur/jp2k.py @@ -937,10 +937,8 @@ class Jp2k(Jp2kBox): elif opj.OPENJPEG is not None: img = self._read_openjpeg(**kwargs) else: - raise LibraryNotFoundError("You must have either a recent version " - "of OpenJPEG or the development " - "version of OpenJP2 installed before " - "using this functionality.") + raise LibraryNotFoundError("You must have OpenJPEG installed " + "before reading a JPEG2000 image.") return img def _subsampling_sanity_check(self): @@ -1235,8 +1233,8 @@ class Jp2k(Jp2kBox): """ if version.openjpeg_version_tuple[0] < 2: raise LibraryNotFoundError("You must have at least version 2.0.0 " - "of OpenJP2 installed before using " - "this functionality.") + "of OpenJPEG installed before using " + "read_bands.") dparam = self._populate_dparam(rlevel, ignore_pclr_cmap_cdef, layer=layer, tile=tile, area=area) diff --git a/glymur/lib/config.py b/glymur/lib/config.py index 04aece2..dc8ab29 100644 --- a/glymur/lib/config.py +++ b/glymur/lib/config.py @@ -146,7 +146,7 @@ def glymur_config(): libopenjpeg_handle = load_openjpeg(libs['openjpeg']) if libopenjp2_handle is None and libopenjpeg_handle is None: msg = "Neither the openjp2 nor the openjpeg library could be loaded. " - raise IOError(msg) + warnings.warn(msg, UserWarning) return libopenjp2_handle, libopenjpeg_handle diff --git a/glymur/test/fixtures.py b/glymur/test/fixtures.py index 838756a..417797f 100644 --- a/glymur/test/fixtures.py +++ b/glymur/test/fixtures.py @@ -13,6 +13,15 @@ import six import glymur +# If openjpeg is not installed, many tests cannot be run. +if glymur.version.openjpeg_version == "0.0.0": + OPENJPEG_NOT_AVAILABLE = True + OPENJPEG_NOT_AVAILABLE_MSG = "OpenJPEG library not installed" +else: + OPENJPEG_NOT_AVAILABLE = False + OPENJPEG_NOT_AVAILABLE_MSG = None + + # Some versions of "six" on python3 cause problems when verifying warnings. # Only use when the version is 1.7 or higher. # And moreover, we only test using the 3.x infrastructure, never on 2.x. diff --git a/glymur/test/test_jp2box.py b/glymur/test/test_jp2box.py index 061ad23..bf10900 100644 --- a/glymur/test/test_jp2box.py +++ b/glymur/test/test_jp2box.py @@ -34,6 +34,7 @@ from glymur.jp2box import FileTypeBox, ImageHeaderBox, JP2HeaderBox from glymur.jp2box import JPEG2000SignatureBox from glymur.core import COLOR, OPACITY from glymur.core import RED, GREEN, BLUE, GREY, WHOLE_IMAGE +from glymur.version import openjpeg_version from .fixtures import ( WARNING_INFRASTRUCTURE_ISSUE, WARNING_INFRASTRUCTURE_MSG, @@ -54,6 +55,8 @@ def load_tests(loader, tests, ignore): tests.addTests(doctest.DocTestSuite('glymur.jp2box')) return tests +@unittest.skipIf(re.match('0|1.[0-2]', openjpeg_version) is not None, + "Not supported with OpenJPEG {0}".format(openjpeg_version)) @unittest.skipIf(os.name == "nt", "Temporary file issue on window.") class TestDataEntryURL(unittest.TestCase): """Test suite for DataEntryURL boxes.""" @@ -119,7 +122,7 @@ class TestDataEntryURL(unittest.TestCase): self.assertEqual(url + chr(0), read_url) -@unittest.skipIf(re.match(r'''(1|2.0.0)''', +@unittest.skipIf(re.match(r'''0|1|2.0.0''', glymur.version.openjpeg_version) is not None, "Not supported until 2.1") @unittest.skipIf(os.name == "nt", "Temporary file issue on window.") diff --git a/glymur/test/test_jp2k.py b/glymur/test/test_jp2k.py index 042a681..02e850a 100644 --- a/glymur/test/test_jp2k.py +++ b/glymur/test/test_jp2k.py @@ -54,6 +54,8 @@ def load_tests(loader, tests, ignore): return tests +@unittest.skipIf(fixtures.OPENJPEG_NOT_AVAILABLE, + fixtures.OPENJPEG_NOT_AVAILABLE_MSG) class SliceProtocolBase(unittest.TestCase): """ Test slice protocol, i.e. when using [ ] to read image data. @@ -309,6 +311,8 @@ class TestSliceProtocolRead(SliceProtocolBase): expected = self.j2k.read(area=(5, 27, 533, 423), rlevel=5) np.testing.assert_array_equal(actual, expected) +@unittest.skipIf(fixtures.OPENJPEG_NOT_AVAILABLE, + fixtures.OPENJPEG_NOT_AVAILABLE_MSG) @unittest.skipIf(OPJ_DATA_ROOT is None, "OPJ_DATA_ROOT environment variable not set") class TestSliceProtocolOpjData(unittest.TestCase): @@ -460,6 +464,8 @@ class TestSliceProtocolOpjData(unittest.TestCase): expected = self.j2k_quarter_data[5:13, 38:50] np.testing.assert_array_equal(actual, expected) +@unittest.skipIf(fixtures.OPENJPEG_NOT_AVAILABLE, + fixtures.OPENJPEG_NOT_AVAILABLE_MSG) class TestJp2k(unittest.TestCase): """These tests should be run by just about all configuration.""" @@ -488,7 +494,7 @@ class TestJp2k(unittest.TestCase): actdata = j2.read() self.assertTrue(fixtures.mse(actdata[0], expdata[0]) < 0.38) - @unittest.skipIf(re.match('1.[0-4]', openjpeg_version) is not None, + @unittest.skipIf(re.match('0|1.[0-4]', openjpeg_version) is not None, "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") @@ -820,7 +826,7 @@ class TestJp2k(unittest.TestCase): self.assertEqual(data.shape, (1024, 1024, 3)) -@unittest.skipIf(re.match('1.[0-4]', openjpeg_version) is not None, +@unittest.skipIf(re.match('0|1.[0-4]', openjpeg_version) is not None, "Not supported with OpenJPEG {0}".format(openjpeg_version)) @unittest.skipIf(os.name == "nt", "NamedTemporaryFile issue on windows") class TestJp2k_write(unittest.TestCase): @@ -966,6 +972,8 @@ class TestJp2k_write(unittest.TestCase): self.assertEqual(codestream.segment[2].spcod[0], glymur.core.CPRL) +@unittest.skipIf(fixtures.OPENJPEG_NOT_AVAILABLE, + fixtures.OPENJPEG_NOT_AVAILABLE_MSG) @unittest.skipIf(glymur.version.openjpeg_version_tuple[0] >= 2, "Negative tests only for version 1.x") class TestJp2k_1_x(unittest.TestCase): @@ -1092,7 +1100,7 @@ class TestJp2k_2_0(unittest.TestCase): self.assertEqual(jasoc.box[3].box[1].box_id, 'xml ') -@unittest.skipIf(re.match(r'''(1|2.0.0)''', +@unittest.skipIf(re.match(r'''0|1|2.0.0''', glymur.version.openjpeg_version) is not None, "Not to be run until unless 2.0.1 or higher is present") class TestJp2k_2_1(unittest.TestCase): @@ -1290,6 +1298,8 @@ class TestJp2kOpjDataRoot(unittest.TestCase): rgb_from_idx[r, c] = palette[idx[r, c]] np.testing.assert_array_equal(rgb, rgb_from_idx) + @unittest.skipIf(fixtures.OPENJPEG_NOT_AVAILABLE, + fixtures.OPENJPEG_NOT_AVAILABLE_MSG) def test_read_differing_subsamples(self): """should error out with read used on differently subsampled images""" # Verify that we error out appropriately if we use the read method diff --git a/glymur/test/test_opj_suite.py b/glymur/test/test_opj_suite.py index a033aae..8eb5956 100644 --- a/glymur/test/test_opj_suite.py +++ b/glymur/test/test_opj_suite.py @@ -37,6 +37,7 @@ import glymur from glymur import Jp2k from glymur.jp2box import FileTypeBox, ImageHeaderBox, ColourSpecificationBox +from . import fixtures from .fixtures import ( OPJ_DATA_ROOT, MetadataBase, WARNING_INFRASTRUCTURE_ISSUE, WARNING_INFRASTRUCTURE_MSG, @@ -44,6 +45,8 @@ from .fixtures import ( ) +@unittest.skipIf(fixtures.OPENJPEG_NOT_AVAILABLE, + fixtures.OPENJPEG_NOT_AVAILABLE_MSG) @unittest.skipIf(OPJ_DATA_ROOT is None, "OPJ_DATA_ROOT environment variable not set") class TestSuite(unittest.TestCase): @@ -479,6 +482,8 @@ class TestSuiteWarns(MetadataBase): self.assertTrue(True) +@unittest.skipIf(fixtures.OPENJPEG_NOT_AVAILABLE, + fixtures.OPENJPEG_NOT_AVAILABLE_MSG) @unittest.skipIf(OPJ_DATA_ROOT is None, "OPJ_DATA_ROOT environment variable not set") @unittest.skipIf(glymur.version.openjpeg_version_tuple[0] == 1, @@ -574,6 +579,8 @@ class TestSuiteBands(unittest.TestCase): self.assertTrue(True) +@unittest.skipIf(fixtures.OPENJPEG_NOT_AVAILABLE, + fixtures.OPENJPEG_NOT_AVAILABLE_MSG) @unittest.skipIf(OPJ_DATA_ROOT is None, "OPJ_DATA_ROOT environment variable not set") @unittest.skipIf(glymur.version.openjpeg_version_tuple[0] == 1, diff --git a/glymur/test/test_opj_suite_2p1.py b/glymur/test/test_opj_suite_2p1.py index addc48b..4977a6e 100644 --- a/glymur/test/test_opj_suite_2p1.py +++ b/glymur/test/test_opj_suite_2p1.py @@ -36,11 +36,14 @@ import numpy as np from glymur import Jp2k import glymur +from . import fixtures from .fixtures import OPJ_DATA_ROOT from .fixtures import WARNING_INFRASTRUCTURE_ISSUE, WARNING_INFRASTRUCTURE_MSG from .fixtures import mse, peak_tolerance, read_pgx, opj_data_file +@unittest.skipIf(fixtures.OPENJPEG_NOT_AVAILABLE, + fixtures.OPENJPEG_NOT_AVAILABLE_MSG) @unittest.skipIf(OPJ_DATA_ROOT is None, "OPJ_DATA_ROOT environment variable not set") @unittest.skipIf(re.match(r'''(1|2.0.0)''', @@ -163,6 +166,8 @@ class TestSuite2point1(unittest.TestCase): with self.assertRaises(IOError): j.read() +@unittest.skipIf(fixtures.OPENJPEG_NOT_AVAILABLE, + fixtures.OPENJPEG_NOT_AVAILABLE_MSG) @unittest.skipIf(OPJ_DATA_ROOT is None, "OPJ_DATA_ROOT environment variable not set") @unittest.skipIf(re.match(r'''(1|2.0.0)''', diff --git a/glymur/test/test_printing.py b/glymur/test/test_printing.py index 49bbe6d..187a15b 100644 --- a/glymur/test/test_printing.py +++ b/glymur/test/test_printing.py @@ -31,6 +31,8 @@ import lxml.etree as ET import glymur from glymur import Jp2k, command_line +from glymur.version import openjpeg_version + from . import fixtures from .fixtures import OPJ_DATA_ROOT, opj_data_file from .fixtures import WARNING_INFRASTRUCTURE_ISSUE, WARNING_INFRASTRUCTURE_MSG @@ -106,6 +108,8 @@ class TestPrinting(unittest.TestCase): with self.assertRaises(TypeError): glymur.set_printoptions(hi='low') + @unittest.skipIf(re.match('0|1.[0-4]', openjpeg_version) is not None, + "Not supported with OpenJPEG {0}".format(openjpeg_version)) def test_asoc_label_box(self): """verify printing of asoc, label boxes""" # Construct a fake file with an asoc and a label box, as diff --git a/glymur/version.py b/glymur/version.py index 8509980..1c1279f 100644 --- a/glymur/version.py +++ b/glymur/version.py @@ -19,7 +19,7 @@ from .lib import openjp2 as opj2 # Do not change the format of this next line! Doing so risks breaking # setup.py -version = "0.7.2" +version = "0.7.3" _sv = LooseVersion(version) version_tuple = _sv.version From 03cb19d22b7d1ad165fbda158f617a199dd194a8 Mon Sep 17 00:00:00 2001 From: John Evans Date: Tue, 11 Nov 2014 10:46:59 -0500 Subject: [PATCH 30/57] deprecated read method, removed write method, closes #299 use array-style slicing instead. Many former read methods are now properties. Many former write method parameters are now moved into the constructor. --- docs/source/how_do_i.rst | 27 +- docs/source/roadmap.rst | 9 - docs/source/whatsnew/0.7.rst | 18 +- docs/source/whatsnew/0.8.rst | 10 + docs/source/whatsnew/index.rst | 5 +- glymur/jp2k.py | 359 ++++++++------ glymur/test/test_callbacks.py | 26 +- glymur/test/test_codestream.py | 149 ------ glymur/test/test_jp2box.py | 18 +- glymur/test/test_jp2k.py | 744 +++++++++++++++------------- glymur/test/test_opj_suite.py | 427 ++++++++++++++-- glymur/test/test_opj_suite_2p1.py | 342 ------------- glymur/test/test_opj_suite_dump.py | 3 +- glymur/test/test_opj_suite_neg.py | 102 ++-- glymur/test/test_opj_suite_write.py | 74 ++- glymur/test/test_printing.py | 7 +- 16 files changed, 1132 insertions(+), 1188 deletions(-) create mode 100644 docs/source/whatsnew/0.8.rst delete mode 100644 glymur/test/test_codestream.py delete mode 100644 glymur/test/test_opj_suite_2p1.py diff --git a/docs/source/how_do_i.rst b/docs/source/how_do_i.rst index 5d11d67..8a62b32 100644 --- a/docs/source/how_do_i.rst +++ b/docs/source/how_do_i.rst @@ -14,27 +14,22 @@ retrieve a full resolution and first lower-resolution image :: >>> jp2file = glymur.data.nemo() # just a path to a JPEG2000 file >>> jp2 = glymur.Jp2k(jp2file) >>> fullres = jp2[:] - >>> print(fullres.shape) + >>> fullres.shape (1456, 2592, 3) >>> thumbnail = jp2[::2, ::2] - >>> print(thumbnail.shape) + >>> thumbnail.shape (728, 1296, 3) -The :py:meth:`read` method exposes many more options for other JPEG 2000 -features such as quality layers. - ... write images? ================= -So long as the image data can fit entirely into memory, array-style slicing may -also be used to write JPEG 2000 files. +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', mode='wb') - >>> jp2[:] = np.zeros((640, 480), dtype=np.uint8) + >>> data = np.zeros((640, 480), dtype=np.uint8) + >>> jp2 = glymur.Jp2k('zeros.jp2', data=data) -The :py:meth:`write` method exposes many more options for other JPEG 2000 -features. You should have OpenJPEG version 1.5 or more recent before writing -JPEG 2000 images. +You should have OpenJPEG version 1.5 or more recent before writing JPEG 2000 images. ... display metadata? ===================== @@ -354,15 +349,14 @@ image isn't square. :: >>> import numpy as np >>> import glymur >>> from glymur import Jp2k - >>> rgb = Jp2k(glymur.data.goodstuff()).read() + >>> rgb = Jp2k(glymur.data.goodstuff())[:] >>> lx, ly = rgb.shape[0:2] >>> X, Y = np.ogrid[0:lx, 0:ly] >>> mask = ly**2*(X - lx / 2) ** 2 + lx**2*(Y - ly / 2) ** 2 > (lx * ly / 2)**2 >>> alpha = 255 * np.ones((lx, ly, 1), dtype=np.uint8) >>> alpha[mask] = 0 >>> rgba = np.concatenate((rgb, alpha), axis=2) - >>> jp2 = Jp2k('tmp.jp2', 'wb') - >>> jp2[:] = rgba + >>> jp2 = Jp2k('tmp.jp2', data=rgba) Next we need to specify what types of channels we have. The first three channels are color channels, but we identify the fourth as @@ -465,8 +459,7 @@ http://photojournal.jpl.nasa.gov/tiff/PIA17145.tif info JPEG 2000:: >>> import skimage.io >>> image = skimage.io.imread('PIA17145.tif') >>> from glymur import Jp2k - >>> jp2 = Jp2k('PIA17145.jp2', 'wb') - >>> jp2[:] = image + >>> jp2 = Jp2k('PIA17145.jp2', data=image) Next you can extract the XMP metadata. diff --git a/docs/source/roadmap.rst b/docs/source/roadmap.rst index 503fbc4..f0d7017 100644 --- a/docs/source/roadmap.rst +++ b/docs/source/roadmap.rst @@ -1,12 +1,3 @@ -------------------------------------- -Platforms Tested (0.7.0 release only) -------------------------------------- - * Linux Mint 17 / Python 3.4.0 and 2.7.6 / OpenJPEG 2.1.0 and 1.3.0 - * MacOS 10.6.8 / MacPorts Python 3.4.1, 3.3.5,and 2.7.8 / OpenJPEG 2.1.0 - * CentOS 6.5 / Anaconda Python 3.4.1 / OpenJPEG 1.3.0 - * Fedora 20 i386 / Python 2.7.5 and 3.3.2 / OpenJPEG 1.5.1 - * Windows 7 32bit / Anaconda Python 2.7.6 and 3.4.1 / OpenJPEG 2.1.0 - ------------ Known Issues ------------ diff --git a/docs/source/whatsnew/0.7.rst b/docs/source/whatsnew/0.7.rst index 0a21d9b..3ed7715 100644 --- a/docs/source/whatsnew/0.7.rst +++ b/docs/source/whatsnew/0.7.rst @@ -2,10 +2,26 @@ Changes in glymur 0.7 ===================== +Changes in 0.7.3 +================= + + * added read support back for metadata only when the OpenJPEG library is + not installed + +Changes in 0.7.2 +================= + + * added ellipsis support in array-style slicing + +Changes in 0.7.1 +================= + + * fixed release notes regarding Python 3.4 + Changes in 0.7.0 ================= * implemented :py:meth:`__getitem__`, :py:meth:`__setitem__` support * added back windows support * box_id and longname are class attributes now instead of instance - attributes (see issue 248) + attributes diff --git a/docs/source/whatsnew/0.8.rst b/docs/source/whatsnew/0.8.rst new file mode 100644 index 0000000..f36b593 --- /dev/null +++ b/docs/source/whatsnew/0.8.rst @@ -0,0 +1,10 @@ +===================== +Changes in glymur 0.8 +===================== + +Changes in 0.8.0 +================= + + * Simplified writing images by moving data and options into the + constructor. This is backwards-incompatible with 0.7.x. + * Deprecated :py:meth:`read` method in favor of array-style slicing. diff --git a/docs/source/whatsnew/index.rst b/docs/source/whatsnew/index.rst index 2d69949..4569abd 100644 --- a/docs/source/whatsnew/index.rst +++ b/docs/source/whatsnew/index.rst @@ -8,6 +8,7 @@ These document the changes between minor (or major) versions of glymur. .. toctree:: - 0.5 - 0.6 + 0.8 0.7 + 0.6 + 0.5 diff --git a/glymur/jp2k.py b/glymur/jp2k.py index f36b75e..74834a9 100644 --- a/glymur/jp2k.py +++ b/glymur/jp2k.py @@ -37,16 +37,6 @@ from .jp2box import ( ) from .lib import openjpeg as opj, openjp2 as opj2, c as libc -JP2_IDS = ['colr', 'cdef', 'cmap', 'jp2c', 'ftyp', 'ihdr', 'jp2h', 'jP ', - 'pclr', 'res ', 'resc', 'resd', 'xml ', 'ulst', 'uinf', 'url ', - 'uuid'] -JPX_IDS = ['asoc', 'nlst'] - -_COLORSPACE_MAP = {'rgb': opj2.CLRSPC_SRGB, - 'gray': opj2.CLRSPC_GRAY, - 'grey': opj2.CLRSPC_GRAY, - 'ycc': opj2.CLRSPC_YCC} - class Jp2k(Jp2kBox): """JPEG 2000 file. @@ -54,34 +44,150 @@ class Jp2k(Jp2kBox): ---------- filename : str The path to the JPEG 2000 file. - mode : str - The mode used to open the file. box : sequence List of top-level boxes in the file. Each box may in turn contain its own list of boxes. Will be empty if the file consists only of a raw codestream. + shape : tuple + Size of the image. + + Properties + ---------- + ignore_pclr_cmap_cdef : bool + whether or not to ignore the pclr, cmap, or cdef boxes during any + color transformation, defaults to False. + layer : int + zero-based number of quality layer to decode + verbose : bool + whether or not to print informational messages produced by the + OpenJPEG library, defaults to false + + Examples + -------- + >>> import glymur + >>> jfile = glymur.data.nemo() + >>> jp2 = glymur.Jp2k(jfile) + >>> jp2.shape + (1456, 2592, 3) + >>> image = jp2[:] + >>> image.shape + (1456, 2592, 3) + + Read a lower resolution thumbnail. + + >>> thumbnail = jp2[::2, ::2] + >>> thumbnail.shape + (728, 1296, 3) """ - def __init__(self, filename, mode='rb'): + def __init__(self, filename, data=None, shape=None, **kwargs): """ + Only the filename parameter is required in order to read a JPEG 2000 + file. + Parameters ---------- filename : str or file - The path to JPEG 2000 file. - mode : str, optional - The mode used to open the file. + the path to JPEG 2000 file + image_data : ndarray, optional + image data to be written + shape : tuple + size of image data, only required when image_data is not provided + cbsize : tuple, optional + code block size (DY, DX) + cinema2k : int, optional + frames per second, either 24 or 48 + cinema4k : bool, optional + set to True to specify Cinema4K mode, defaults to false + colorspace : str, optional + either 'rgb' or 'gray' + cratios : iterable + compression ratios for successive layers + eph : bool, optional + if true, write SOP marker after each header packet + grid_offset : tuple, optional + offset (DY, DX) of the origin of the image in the reference grid + irreversible : bool, optional + if true, use the irreversible DWT 9-7 transform + mct : bool, optional + specifies usage of the multi component transform, if not + specified, defaults to True if the colorspace is RGB + modesw : int, optional + mode switch + 1 = BYPASS(LAZY) + 2 = RESET + 4 = RESTART(TERMALL) + 8 = VSC + 16 = ERTERM(SEGTERM) + 32 = SEGMARK(SEGSYM) + numres : int, optional + number of resolutions + prog : str, optional + progression order, one of "LRCP" "RLCP", "RPCL", "PCRL", "CPRL" + psnr : iterable, optional + different PSNR for successive layers + psizes : list, optional + list of precinct sizes, each precinct size tuple is defined in + (height x width) + sop : bool, optional + if true, write SOP marker before each packet + subsam : tuple, optional + 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 + """ Jp2kBox.__init__(self) self.filename = filename - self.mode = mode + self.box = [] self._codec_format = None self._colorspace = None - self._shape = None + self._layer = 0 + if data is not None: + self._shape = data.shape + else: + self._shape = shape + + self._ignore_pclr_cmap_cdef = False + self._verbose = False # Parse the file for JP2/JPX contents only if we are reading it. - if mode == 'rb': + if data is None and shape is None: self.parse() + elif data is not None: + self._write(data, **kwargs) + + @property + def ignore_pclr_cmap_cdef(self): + return self._ignore_pclr_cmap_cdef + + @ignore_pclr_cmap_cdef.setter + def ignore_pclr_cmap_cdef(self, ignore_pclr_cmap_cdef): + self._ignore_pclr_cmap_cdef = ignore_pclr_cmap_cdef + + @property + def layer(self): + return self._layer + + @layer.setter + def layer(self, layer): + if version.openjpeg_version_tuple[0] < 2: + msg = "Layer property not supported unless the version of OpenJPEG " + msg += "is 2.0 or higher." + raise RuntimeError(msg) + self._layer = layer + + @property + def verbose(self): + return self._verbose + + @verbose.setter + def verbose(self, verbose): + self._verbose = verbose @property def shape(self): @@ -371,79 +477,17 @@ class Jp2k(Jp2kBox): self._cparams = cparams - def write(self, img_array, verbose=False, **kwargs): + def _write(self, img_array, verbose=False, **kwargs): """Write image data to a JP2/JPX/J2k file. Intended usage of the various parameters follows that of OpenJPEG's opj_compress utility. This method can only be used to create JPEG 2000 images that can fit in memory. - - Parameters - ---------- - img_array : ndarray - Image data to be written to file. - cbsize : tuple, optional - Code block size (DY, DX). - cinema2k : int, optional - frames per second, either 24 or 48 - cinema4k : bool, optional - Set to True to specify Cinema4K mode, defaults to false. - colorspace : str, optional - Either 'rgb' or 'gray'. - cratios : iterable - Compression ratios for successive layers. - eph : bool, optional - If true, write SOP marker after each header packet. - grid_offset : tuple, optional - Offset (DY, DX) of the origin of the image in the reference grid. - irreversible : bool, optional - If true, use the irreversible DWT 9-7 transform. - mct : bool, optional - Specifies usage of the multi component transform. If not - specified, defaults to True if the colorspace is RGB. - modesw : int, optional - Mode switch. - 1 = BYPASS(LAZY) - 2 = RESET - 4 = RESTART(TERMALL) - 8 = VSC - 16 = ERTERM(SEGTERM) - 32 = SEGMARK(SEGSYM) - numres : int, optional - Number of resolutions. - prog : str, optional - Progression order, one of "LRCP" "RLCP", "RPCL", "PCRL", "CPRL". - psnr : iterable, optional - Different PSNR for successive layers. - psizes : list, optional - List of precinct sizes. Each precinct size tuple is defined in - (height x width). - sop : bool, optional - If true, write SOP marker before each packet. - subsam : tuple, optional - 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. - - Examples - -------- - >>> import glymur - >>> jfile = glymur.data.nemo() - >>> jp2 = glymur.Jp2k(jfile) - >>> data = jp2.read(rlevel=1) - >>> from tempfile import NamedTemporaryFile - >>> tfile = NamedTemporaryFile(suffix='.jp2', delete=False) - >>> j = Jp2k(tfile.name, mode='wb') - >>> j.write(data.astype(np.uint8)) """ if re.match("1.[0-4]", version.openjpeg_version) is not None: raise RuntimeError("You must have at least version 1.5 of OpenJPEG " "in order to write images.") - self._shape = img_array.shape self._determine_colorspace(**kwargs) self._populate_cparams(img_array, **kwargs) @@ -617,7 +661,12 @@ class Jp2k(Jp2kBox): # Turn the colorspace from a string to the enumerated value that # the library expects. - self._colorspace = _COLORSPACE_MAP[colorspace.lower()] + COLORSPACE_MAP = {'rgb': opj2.CLRSPC_SRGB, + 'gray': opj2.CLRSPC_GRAY, + 'grey': opj2.CLRSPC_GRAY, + 'ycc': opj2.CLRSPC_YCC} + + self._colorspace = COLORSPACE_MAP[colorspace.lower()] def _write_openjp2(self, img_array, verbose=False): @@ -640,7 +689,11 @@ class Jp2k(Jp2kBox): codec = opj2.create_compress(self._cparams.codec_fmt) stack.callback(opj2.destroy_codec, codec) - info_handler = _INFO_CALLBACK if verbose else None + if self._verbose or verbose: + info_handler = _INFO_CALLBACK + else: + info_handler = None + opj2.set_info_handler(codec, info_handler) opj2.set_warning_handler(codec, _WARNING_CALLBACK) opj2.set_error_handler(codec, _ERROR_CALLBACK) @@ -844,7 +897,7 @@ class Jp2k(Jp2kBox): # Case of jp2[:] = data, i.e. write the entire image. # # Should have a slice object where start = stop = step = None - self.write(data) + self._write(data) else: msg = "Partial write operations are currently not allowed." raise TypeError(msg) @@ -863,16 +916,16 @@ class Jp2k(Jp2kBox): # This retrieves a single row. row = pargs area = (row, 0, row + 1, numcols) - return self.read(area=area).squeeze() + return self._read(area=area).squeeze() if pargs is Ellipsis: # Case of jp2[...] - return self.read() + return self._read() if isinstance(pargs, slice): if pargs.start is None and pargs.stop is None and pargs.step is None: # Case of jp2[:] - return self.read() + return self._read() # Corner case of jp2[x] where x is a slice object with non-null # members. Just augment it with an ellipsis and let the code @@ -949,7 +1002,7 @@ class Jp2k(Jp2kBox): numrows if rows.stop is None else rows.stop, numcols if cols.stop is None else cols.stop ) - data = self.read(area=area, rlevel=rlevel) + data = self._read(area=area, rlevel=rlevel) if len(pargs) == 2: return data @@ -957,28 +1010,9 @@ class Jp2k(Jp2kBox): return data[:, :, bands] - def read(self, **kwargs): + def _read(self, **kwargs): """Read a JPEG 2000 image. - Parameters - ---------- - rlevel : int, optional - Factor by which to rlevel output resolution. Use -1 to get the - lowest resolution thumbnail. This is the only keyword option - available to use when the OpenJPEG version is 1.5 or earlier. - layer : int, optional - Number of quality layer to decode. - area : tuple, optional - Specifies decoding image area, - (first_row, first_col, last_row, last_col) - tile : int, optional - Number of tile to decode. - ignore_pclr_cmap_cdef : bool - Whether or not to ignore the pclr, cmap, or cdef boxes during any - color transformation. Defaults to False. - verbose : bool, optional - Print informational messages produced by the OpenJPEG library. - Returns ------- img_array : ndarray @@ -988,21 +1022,6 @@ class Jp2k(Jp2kBox): ------ IOError If the image has differing subsample factors. - - Examples - -------- - >>> import glymur - >>> jfile = glymur.data.nemo() - >>> jp = glymur.Jp2k(jfile) - >>> image = jp.read() - >>> image.shape - (1456, 2592, 3) - - Read the lowest resolution thumbnail. - - >>> thumbnail = jp.read(rlevel=-1) - >>> thumbnail.shape - (728, 1296, 3) """ if version.openjpeg_version_tuple[0] < 2: img = self._read_openjpeg(**kwargs) @@ -1010,6 +1029,46 @@ class Jp2k(Jp2kBox): img = self._read_openjp2(**kwargs) return img + def read(self, **kwargs): + """ + """ + #Read a JPEG 2000 image. + # + #Parameters + #---------- + #rlevel : int, optional + # Factor by which to rlevel output resolution. Use -1 to get the + # lowest resolution thumbnail. This is the only keyword option + # available to use when the OpenJPEG version is 1.5 or earlier. + #layer : int, optional + # Number of quality layer to decode. + #area : tuple, optional + # Specifies decoding image area, + # (first_row, first_col, last_row, last_col) + #tile : int, optional + # Number of tile to decode. + #verbose : bool, optional + # Print informational messages produced by the OpenJPEG library. + # + #Returns + #------- + #img_array : ndarray + # The image data. + # + #Raises + #------ + #IOError + # If the image has differing subsample factors. + + if 'ignore_pclr_cmap_cdef' in kwargs: + self.ignore_pclr_cmap_cdef = kwargs['ignore_pclr_cmap_cdef'] + warnings.warn("Use array-style slicing instead.", DeprecationWarning) + if version.openjpeg_version_tuple[0] < 2: + img = self._read_openjpeg(**kwargs) + else: + img = self._read_openjp2(**kwargs) + return img + def _subsampling_sanity_check(self): """Check for differing subsample factors. """ @@ -1022,8 +1081,7 @@ class Jp2k(Jp2kBox): msg += "the read_bands method instead." raise RuntimeError(msg) - def _read_openjpeg(self, rlevel=0, ignore_pclr_cmap_cdef=False, - verbose=False, area=None): + def _read_openjpeg(self, rlevel=0, verbose=False, area=None): """Read a JPEG 2000 image using libopenjpeg. Parameters @@ -1031,9 +1089,6 @@ class Jp2k(Jp2kBox): rlevel : int, optional Factor by which to rlevel output resolution. Use -1 to get the lowest resolution thumbnail. - ignore_pclr_cmap_cdef : bool - Whether or not to ignore the pclr, cmap, or cdef boxes during any - color transformation. Defaults to False. verbose : bool, optional Print informational messages produced by the OpenJPEG library. area : tuple, optional @@ -1052,7 +1107,7 @@ class Jp2k(Jp2kBox): """ self._subsampling_sanity_check() - self._populate_dparams(rlevel, ignore_pclr_cmap_cdef) + self._populate_dparams(rlevel) with ExitStack() as stack: try: @@ -1062,7 +1117,10 @@ class Jp2k(Jp2kBox): event_mgr = opj.EventMgrType() info_handler = ctypes.cast(_INFO_CALLBACK, ctypes.c_void_p) - event_mgr.info_handler = info_handler if verbose else None + if verbose or self._verbose: + event_mgr.info_handler = info_handler + else: + event_mgr.info_handler = None event_mgr.warning_handler = ctypes.cast(_WARNING_CALLBACK, ctypes.c_void_p) event_mgr.error_handler = ctypes.cast(_ERROR_CALLBACK, @@ -1105,8 +1163,7 @@ class Jp2k(Jp2kBox): return data - def _read_openjp2(self, rlevel=0, layer=0, area=None, tile=None, - verbose=False, ignore_pclr_cmap_cdef=False): + def _read_openjp2(self, rlevel=0, layer=None, area=None, tile=None, verbose=False): """Read a JPEG 2000 image using libopenjp2. Parameters @@ -1134,10 +1191,12 @@ class Jp2k(Jp2kBox): RuntimeError If the image has differing subsample factors. """ + if layer is not None: + self._layer = layer + self._subsampling_sanity_check() - self._populate_dparams(rlevel, ignore_pclr_cmap_cdef, - layer=layer, tile=tile, area=area) + self._populate_dparams(rlevel, tile=tile, area=area) with ExitStack() as stack: if re.match("2.1", version.openjpeg_version): @@ -1154,7 +1213,8 @@ class Jp2k(Jp2kBox): opj2.set_error_handler(codec, _ERROR_CALLBACK) opj2.set_warning_handler(codec, _WARNING_CALLBACK) - if verbose: + + if self._verbose or verbose: opj2.set_info_handler(codec, _INFO_CALLBACK) else: opj2.set_info_handler(codec, None) @@ -1181,14 +1241,11 @@ class Jp2k(Jp2kBox): return img_array - def _populate_dparams(self, rlevel, ignore_pclr_cmap_cdef, tile=None, - layer=None, area=None): + def _populate_dparams(self, rlevel, tile=None, area=None): """Populate decompression structure with appropriate input parameters. Parameters ---------- - layer : int - Number of quality layer to decode. rlevel : int Factor by which to rlevel output resolution. area : tuple @@ -1196,9 +1253,6 @@ class Jp2k(Jp2kBox): (first_row, first_col, last_row, last_col) tile : int Number of tile to decode. - ignore_pclr_cmap_cdef : bool - Whether or not to ignore the pclr, cmap, or cdef boxes during any - color transformation. Defaults to False. """ if opj2.OPENJP2 is not None: dparam = opj2.set_default_decoder_parameters() @@ -1211,10 +1265,13 @@ class Jp2k(Jp2kBox): infile += b'0' * nelts dparam.infile = infile + if self.ignore_pclr_cmap_cdef: + # Return raw codestream components. + dparam.flags |= 1 + dparam.decod_format = self._codec_format - if layer is not None: - dparam.cp_layer = layer + dparam.cp_layer = self._layer # Must check the specified rlevel against the maximum. if rlevel != 0: @@ -1245,13 +1302,13 @@ class Jp2k(Jp2kBox): dparam.tile_index = tile dparam.nb_tile_to_decode = 1 - if ignore_pclr_cmap_cdef is True: + if self.ignore_pclr_cmap_cdef: # Return raw codestream components. dparam.flags |= 1 self._dparams = dparam - def read_bands(self, rlevel=0, layer=0, area=None, tile=None, + def read_bands(self, rlevel=0, layer=None, area=None, tile=None, verbose=False, ignore_pclr_cmap_cdef=False): """Read a JPEG 2000 image. @@ -1297,8 +1354,10 @@ class Jp2k(Jp2kBox): "OpenJPEG installed before using this " "functionality.") - self._populate_dparams(rlevel, ignore_pclr_cmap_cdef, - layer=layer, tile=tile, area=area) + self.ignore_pclr_cmap_cdef = ignore_pclr_cmap_cdef + if layer is not None: + self._layer = layer + self._populate_dparams(rlevel, tile=tile, area=area) with ExitStack() as stack: if re.match("2.1", version.openjpeg_version): @@ -1710,6 +1769,8 @@ def _validate_singletons(boxes): if 'dtbl' in multiples: raise IOError('There can only be one dtbl box in a file.') +JPX_IDS = ['asoc', 'nlst'] + def _validate_jpx_brand(boxes, brand): """ If there is a JPX box then the brand must be 'jpx '. diff --git a/glymur/test/test_callbacks.py b/glymur/test/test_callbacks.py index ce3bb8c..c29f816 100644 --- a/glymur/test/test_callbacks.py +++ b/glymur/test/test_callbacks.py @@ -39,15 +39,28 @@ class TestCallbacks(unittest.TestCase): "Missing openjp2 library.") @unittest.skipIf(WARNING_INFRASTRUCTURE_ISSUE, WARNING_INFRASTRUCTURE_MSG) @unittest.skipIf(os.name == "nt", "Temporary file issue on window.") - def test_info_callback_on_write(self): + def test_info_callback_on_write_backwards_compatibility(self): """Verify messages printed when writing an image in verbose mode.""" j = glymur.Jp2k(self.jp2file) with self.assertWarns(UserWarning): tiledata = j.read(tile=0) with tempfile.NamedTemporaryFile(suffix='.jp2') as tfile: - j = glymur.Jp2k(tfile.name, 'wb') with patch('sys.stdout', new=StringIO()) as fake_out: - j.write(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) + + @unittest.skipIf(glymur.version.openjpeg_version[0] != '2', + "Missing openjp2 library.") + @unittest.skipIf(os.name == "nt", "Temporary file issue on window.") + def test_info_callback_on_write(self): + """Verify messages printed when writing an image in verbose mode.""" + j = glymur.Jp2k(self.jp2file) + tiledata = j[:] + with tempfile.NamedTemporaryFile(suffix='.jp2') as tfile: + with patch('sys.stdout', new=StringIO()) as fake_out: + jp2 = glymur.Jp2k(tfile.name, data=tiledata, verbose=True) actual = fake_out.getvalue().strip() expected = '[INFO] tile number 1 / 1' self.assertEqual(actual, expected) @@ -57,15 +70,16 @@ class TestCallbacks(unittest.TestCase): # Verify that we get the expected stdio output when our internal info # callback handler is enabled. - j = glymur.Jp2k(self.j2kfile) + jp2 = glymur.Jp2k(self.j2kfile) with patch('sys.stdout', new=StringIO()) as fake_out: - j.read(rlevel=1, verbose=True) + jp2.verbose = True + jp2[::2, ::2] actual = fake_out.getvalue().strip() if glymur.version.openjpeg_version[0] == '2': lines = ['[INFO] Start to read j2k main header (0).', '[INFO] Main header has been correctly decoded.', - '[INFO] No decoded area parameters, set the decoded area to the whole image', + '[INFO] Setting decoding area to 0,0,480,800', '[INFO] Header of tile 0 / 0 has been read.', '[INFO] Tile 1/1 has been decoded.', '[INFO] Image data has been updated with tile 1.'] diff --git a/glymur/test/test_codestream.py b/glymur/test/test_codestream.py deleted file mode 100644 index e520713..0000000 --- a/glymur/test/test_codestream.py +++ /dev/null @@ -1,149 +0,0 @@ -""" -Test suite for codestream parsing. -""" - -# unittest doesn't work well with R0904. -# pylint: disable=R0904 - -import os -import struct -import sys -import tempfile -import unittest - -from glymur import Jp2k -import glymur - -from .fixtures import opj_data_file, OPJ_DATA_ROOT - -class TestCodestream(unittest.TestCase): - """Test suite for unusual codestream cases.""" - - def setUp(self): - self.jp2file = glymur.data.nemo() - - def tearDown(self): - pass - - def test_siz_segment_ssiz_unsigned(self): - """ssiz attribute to be removed in future release""" - j = Jp2k(self.jp2file) - codestream = j.get_codestream() - - # The ssiz attribute was simply a tuple of raw bytes. - # The first 7 bits are interpreted as the bitdepth, the MSB determines - # whether or not it is signed. - self.assertEqual(codestream.segment[1].ssiz, (7, 7, 7)) - - -@unittest.skipIf(OPJ_DATA_ROOT is None, - "OPJ_DATA_ROOT environment variable not set") -class TestCodestreamOpjData(unittest.TestCase): - """Test suite for unusual codestream cases. Uses OPJ_DATA_ROOT""" - - def setUp(self): - self.jp2file = glymur.data.nemo() - - def tearDown(self): - pass - - @unittest.skipIf(os.name == "nt", "Temporary file issue on window.") - def test_reserved_marker_segment(self): - """Reserved marker segments are ok.""" - - # Some marker segments were reserved in FCD15444-1. Since that - # standard is old, some of them may have come into use. - # - # Let's inject a reserved marker segment into a file that - # we know something about to make sure we can still parse it. - filename = os.path.join(OPJ_DATA_ROOT, 'input/conformance/p0_01.j2k') - with tempfile.NamedTemporaryFile(suffix='.j2k') as tfile: - with open(filename, 'rb') as ifile: - # Everything up until the first QCD marker. - read_buffer = ifile.read(45) - tfile.write(read_buffer) - - # Write the new marker segment, 0xff6f = 65391 - read_buffer = struct.pack('>HHB', int(65391), int(3), int(0)) - tfile.write(read_buffer) - - # Get the rest of the input file. - read_buffer = ifile.read() - tfile.write(read_buffer) - tfile.flush() - - codestream = Jp2k(tfile.name).get_codestream() - - self.assertEqual(codestream.segment[2].marker_id, '0xff6f') - self.assertEqual(codestream.segment[2].length, 3) - self.assertEqual(codestream.segment[2].data, b'\x00') - - def test_psot_is_zero(self): - """Psot=0 in SOT is perfectly legal. Issue #78.""" - filename = os.path.join(OPJ_DATA_ROOT, - 'input/nonregression/123.j2c') - j = Jp2k(filename) - codestream = j.get_codestream(header_only=False) - - # The codestream is valid, so we should be able to get the entire - # codestream, so the last one is EOC. - self.assertEqual(codestream.segment[-1].marker_id, 'EOC') - - - def test_siz_segment_ssiz_signed(self): - """ssiz attribute to be removed in future release""" - filename = os.path.join(OPJ_DATA_ROOT, 'input/conformance/p0_03.j2k') - j = Jp2k(filename) - codestream = j.get_codestream() - - # The ssiz attribute was simply a tuple of raw bytes. - # The first 7 bits are interpreted as the bitdepth, the MSB determines - # whether or not it is signed. - self.assertEqual(codestream.segment[1].ssiz, (131,)) - - -class TestCodestreamRepr(unittest.TestCase): - - def setUp(self): - self.jp2file = glymur.data.nemo() - - def tearDown(self): - pass - - def test_soc(self): - """Test SOC segment repr""" - segment = glymur.codestream.SOCsegment() - newseg = eval(repr(segment)) - self.assertEqual(newseg.marker_id, 'SOC') - - def test_siz(self): - """Test SIZ segment repr""" - kwargs = {'rsiz': 0, - 'xysiz': (2592, 1456), - 'xyosiz': (0, 0), - 'xytsiz': (2592, 1456), - 'xytosiz': (0, 0), - 'Csiz': 3, - 'bitdepth': (8, 8, 8), - 'signed': (False, False, False), - 'xyrsiz': ((1, 1, 1), (1, 1, 1))} - segment = glymur.codestream.SIZsegment(**kwargs) - newseg = eval(repr(segment)) - self.assertEqual(newseg.marker_id, 'SIZ') - self.assertEqual(newseg.xsiz, 2592) - self.assertEqual(newseg.ysiz, 1456) - self.assertEqual(newseg.xosiz, 0) - self.assertEqual(newseg.yosiz, 0) - self.assertEqual(newseg.xtsiz, 2592) - self.assertEqual(newseg.ytsiz, 1456) - self.assertEqual(newseg.xtosiz, 0) - self.assertEqual(newseg.ytosiz, 0) - - self.assertEqual(newseg.xrsiz, (1, 1, 1)) - self.assertEqual(newseg.yrsiz, (1, 1, 1)) - self.assertEqual(newseg.bitdepth, (8, 8, 8)) - self.assertEqual(newseg.signed, (False, False, False)) - - -if __name__ == "__main__": - unittest.main() diff --git a/glymur/test/test_jp2box.py b/glymur/test/test_jp2box.py index 72daf17..9d1f9cf 100644 --- a/glymur/test/test_jp2box.py +++ b/glymur/test/test_jp2box.py @@ -54,16 +54,17 @@ class TestDataEntryURL(unittest.TestCase): def setUp(self): self.jp2file = glymur.data.nemo() + @unittest.skipIf(re.match("1.5|2", glymur.version.openjpeg_version) is None, + "Must have openjpeg 1.5 or higher to run") def test_wrap_greyscale(self): """A single component should be wrapped as GREYSCALE.""" j = Jp2k(self.jp2file) - data = j.read() + data = j[:] red = data[:, :, 0] # Write it back out as a raw codestream. with tempfile.NamedTemporaryFile(suffix=".j2k") as tfile1: - j2k = glymur.Jp2k(tfile1.name, 'wb') - j2k.write(data[:, :, 0]) + j2k = glymur.Jp2k(tfile1.name, data=red) # Ok, now rewrap it as JP2. The colorspace should be GREYSCALE. with tempfile.NamedTemporaryFile(suffix=".jp2") as tfile2: @@ -124,24 +125,21 @@ class TestChannelDefinition(unittest.TestCase): def setUpClass(cls): """Need a one_plane plane image for greyscale testing.""" j2k = Jp2k(glymur.data.goodstuff()) - data = j2k.read() + data = j2k[:] # Write the first component back out to file. with tempfile.NamedTemporaryFile(suffix=".j2k", delete=False) as tfile: - grey_j2k = Jp2k(tfile.name, 'wb') - grey_j2k.write(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: - grey_j2k = Jp2k(tfile.name, 'wb') - grey_j2k.write(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: - rgba_jp2 = Jp2k(tfile.name, 'wb') shape = (data.shape[0], data.shape[1], 1) alpha = np.zeros((shape), dtype=data.dtype) data4 = np.concatenate((data, alpha), axis=2) - rgba_jp2.write(data4) + rgba_jp2 = Jp2k(tfile.name, data=data4) cls.four_planes = tfile.name @classmethod diff --git a/glymur/test/test_jp2k.py b/glymur/test/test_jp2k.py index 9a9fb72..b903dda 100644 --- a/glymur/test/test_jp2k.py +++ b/glymur/test/test_jp2k.py @@ -67,12 +67,17 @@ class SliceProtocolBase(unittest.TestCase): def setUpClass(self): self.jp2 = Jp2k(glymur.data.nemo()) - self.jp2_data = self.jp2.read() + self.jp2_data = self.jp2[:] + self.jp2_data_r1 = self.jp2[::2, ::2] self.j2k = Jp2k(glymur.data.goodstuff()) - self.j2k_data = self.j2k.read() + self.j2k_data = self.j2k[:] + self.j2k_data_r1 = self.j2k[::2, ::2] + self.j2k_data_r5 = self.j2k[::32, ::32] +@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): @@ -80,9 +85,9 @@ class TestSliceProtocolBaseWrite(SliceProtocolBase): expected = self.j2k_data with tempfile.NamedTemporaryFile(suffix='.j2k') as tfile: - j = Jp2k(tfile.name, 'wb') - j[...] = self.j2k_data - actual = j.read() + j = Jp2k(tfile.name, shape=expected.shape) + j[...] = expected + actual = j[:] np.testing.assert_array_equal(actual, expected) @@ -90,15 +95,14 @@ class TestSliceProtocolBaseWrite(SliceProtocolBase): expected = self.j2k_data with tempfile.NamedTemporaryFile(suffix='.j2k') as tfile: - j = Jp2k(tfile.name, 'wb') - j[:] = self.j2k_data - actual = j.read() + j = Jp2k(tfile.name, data=self.j2k_data) + actual = j[:] np.testing.assert_array_equal(actual, expected) def test_cannot_write_with_non_default_single_slice(self): with tempfile.NamedTemporaryFile(suffix='.j2k') as tfile: - j = Jp2k(tfile.name, 'wb') + j = Jp2k(tfile.name, shape=self.j2k_data.shape) with self.assertRaises(TypeError): j[slice(None, 0)] = self.j2k_data with self.assertRaises(TypeError): @@ -110,31 +114,31 @@ class TestSliceProtocolBaseWrite(SliceProtocolBase): def test_cannot_write_a_row(self): with tempfile.NamedTemporaryFile(suffix='.j2k') as tfile: - j = Jp2k(tfile.name, 'wb') + j = Jp2k(tfile.name, shape=self.j2k_data.shape) with self.assertRaises(TypeError): j[5] = self.j2k_data def test_cannot_write_a_pixel(self): with tempfile.NamedTemporaryFile(suffix='.j2k') as tfile: - j = Jp2k(tfile.name, 'wb') + j = Jp2k(tfile.name, shape=self.j2k_data.shape) with self.assertRaises(TypeError): j[25, 35] = self.j2k_data[25, 35] def test_cannot_write_a_column(self): with tempfile.NamedTemporaryFile(suffix='.j2k') as tfile: - j = Jp2k(tfile.name, 'wb') + j = Jp2k(tfile.name, shape=self.j2k_data.shape) with self.assertRaises(TypeError): j[:, 25, :] = self.j2k_data[:, :25, :] def test_cannot_write_a_band(self): with tempfile.NamedTemporaryFile(suffix='.j2k') as tfile: - j = Jp2k(tfile.name, 'wb') + j = Jp2k(tfile.name, shape=self.j2k_data.shape) with self.assertRaises(TypeError): j[:, :, 0] = self.j2k_data[:, :, 0] def test_cannot_write_a_subarray(self): with tempfile.NamedTemporaryFile(suffix='.j2k') as tfile: - j = Jp2k(tfile.name, 'wb') + j = Jp2k(tfile.name, shape=self.j2k_data.shape) with self.assertRaises(TypeError): j[:25, :45, :] = self.j2k_data[:25, :25, :] @@ -167,9 +171,9 @@ class TestSliceProtocolRead(SliceProtocolBase): np.testing.assert_array_equal(actual, expected) def test_reduce_resolution_and_slice_in_third_dimension(self): - d = self.j2k[::2, ::2, 1:3] - all = self.j2k.read(rlevel=1) - np.testing.assert_array_equal(all[:,:,1:3], d) + actual = self.j2k[::2, ::2, 1:3] + expected = self.j2k_data_r1[:, :, 1:3] + np.testing.assert_array_equal(actual, expected) def test_retrieve_single_row(self): actual = self.jp2[0] @@ -186,71 +190,6 @@ class TestSliceProtocolRead(SliceProtocolBase): expected = self.jp2_data[20, 20, 2] np.testing.assert_array_equal(actual, expected) - def test_full_resolution_slicing_by_quarters_upper_left(self): - actual = self.jp2[:728, :1296] - expected = self.jp2_data[:728, :1296] - np.testing.assert_array_equal(actual, expected) - - def test_full_resolution_slicing_by_quarters_lower_left(self): - actual = self.jp2[728:, :1296] - expected = self.jp2_data[728:, :1296] - np.testing.assert_array_equal(actual, expected) - - def test_full_resolution_slicing_by_quarters_upper_right(self): - actual = self.jp2[:728, 1296:] - expected = self.jp2_data[:728, 1296:] - np.testing.assert_array_equal(actual, expected) - - def test_full_resolution_slicing_by_quarters_lower_right(self): - actual = self.jp2[728:, 1296:] - expected = self.jp2_data[728:, 1296:] - np.testing.assert_array_equal(actual, expected) - - def test_full_resolution_slicing_by_quarters_center(self): - actual = self.jp2[364:1092, 648:1942] - expected = self.jp2_data[364:1092, 648:1942] - np.testing.assert_array_equal(actual, expected) - - def test_full_resolution_slicing_by_halves_left(self): - actual = self.jp2[:, :1296] - expected = self.jp2_data[:, :1296] - np.testing.assert_array_equal(actual, expected) - - def test_full_resolution_slicing_by_right_half(self): - actual = self.jp2[:, 1296:] - expected = self.jp2_data[:, 1296:] - np.testing.assert_array_equal(actual, expected) - - def test_full_resolution_slicing_by_top_half(self): - actual = self.jp2[:728, :] - expected = self.jp2_data[:728, :] - np.testing.assert_array_equal(actual, expected) - - def test_full_resolution_slicing_by_bottom_half(self): - actual = self.jp2[728:, :] - expected = self.jp2_data[728:, :] - np.testing.assert_array_equal(actual, expected) - - def test_region_rlevel1(self): - actual = self.jp2[0:201:2, 0:201:2] - expected = self.jp2.read(area=(0, 0, 201, 201), rlevel=1) - np.testing.assert_array_equal(actual, expected) - - def test_region_rlevel1_slice_start_is_none(self): - actual = self.jp2[:201:2, :201:2] - expected = self.jp2.read(area=(0, 0, 201, 201), rlevel=1) - np.testing.assert_array_equal(actual, expected) - - def test_region_rlevel1_slice_stop_is_none(self): - actual = self.jp2[201::2, 201::2] - expected = self.jp2.read(area=(201, 201, 1456, 2592), rlevel=1) - np.testing.assert_array_equal(actual, expected) - - def test_region_rlevel1(self): - actual = self.jp2[0:202:2, 0:202:2] - expected = self.jp2.read(area=(0, 0, 202, 202), rlevel=1) - np.testing.assert_array_equal(actual, expected) - def test_ellipsis_full_read(self): actual = self.j2k[...] expected = self.j2k_data @@ -287,182 +226,18 @@ class TestSliceProtocolRead(SliceProtocolBase): expected = self.j2k_data[3:8, :,:] np.testing.assert_array_equal(actual, expected) - def test_slice_protocol_2d_reduce_resolution(self): - d = self.j2k[:] - self.assertEqual(d.shape, (800, 480, 3)) - - d = self.j2k[::1, ::1] - self.assertEqual(d.shape, (800, 480, 3)) - - d = self.j2k[::2, ::2] - self.assertEqual(d.shape, (400, 240, 3)) - - d = self.j2k[::4, ::4] - self.assertEqual(d.shape, (200, 120, 3)) - - d = self.j2k[::8, ::8] - self.assertEqual(d.shape, (100, 60, 3)) - - d = self.j2k[::16, ::16] - self.assertEqual(d.shape, (50, 30, 3)) - - d = self.j2k[::32, ::32] - self.assertEqual(d.shape, (25, 15, 3)) - + @unittest.skipIf(re.match("0|1", glymur.version.openjpeg_version), + "Must have openjpeg 2 or higher to run") def test_region_rlevel5(self): + """ + maximim rlevel + + 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). + """ actual = self.j2k[5:533:32, 27:423:32] - expected = self.j2k.read(area=(5, 27, 533, 423), rlevel=5) - np.testing.assert_array_equal(actual, expected) - -@unittest.skipIf(OPJ_DATA_ROOT is None, - "OPJ_DATA_ROOT environment variable not set") -class TestSliceProtocolOpjData(unittest.TestCase): - """ - Test slice protocol, i.e. when using [ ] to read image data. - These correspond to tests for the read method with the area parameter. - """ - @classmethod - def setUpClass(self): - - jfile = opj_data_file('input/conformance/p1_04.j2k') - self.j2k = Jp2k(jfile) - self.j2k_data = self.j2k.read() - self.j2k_half_data = self.j2k.read(rlevel=1) - self.j2k_quarter_data = self.j2k.read(rlevel=2) - - def test_NR_DEC_p1_04_j2k_43_decode(self): - actual = self.j2k[:1024, :1024] - expected = self.j2k_data - np.testing.assert_array_equal(actual, expected) - - def test_NR_DEC_p1_04_j2k_44_decode(self): - actual = self.j2k[640:768, 512:640] - expected = self.j2k_data[640:768, 512:640] - np.testing.assert_array_equal(actual, expected) - - def test_NR_DEC_p1_04_j2k_45_decode(self): - actual = self.j2k[896:1024, 896:1024] - expected = self.j2k_data[896:1024, 896:1024] - np.testing.assert_array_equal(actual, expected) - - def test_NR_DEC_p1_04_j2k_46_decode(self): - actual = self.j2k[500:800, 100:300] - expected = self.j2k_data[500:800, 100:300] - np.testing.assert_array_equal(actual, expected) - - def test_NR_DEC_p1_04_j2k_47_decode(self): - actual = self.j2k[520:600, 260:360] - expected = self.j2k_data[520:600, 260:360] - np.testing.assert_array_equal(actual, expected) - - def test_NR_DEC_p1_04_j2k_48_decode(self): - actual = self.j2k[520:660, 260:360] - expected = self.j2k_data[520:660, 260:360] - np.testing.assert_array_equal(actual, expected) - - def test_NR_DEC_p1_04_j2k_49_decode(self): - actual = self.j2k[520:600, 360:400] - expected = self.j2k_data[520:600, 360:400] - np.testing.assert_array_equal(actual, expected) - - def test_NR_DEC_p1_04_j2k_50_decode(self): - actual = self.j2k[:1024:4, :1024:4] - expected = self.j2k_quarter_data[:256, :256] - np.testing.assert_array_equal(actual, expected) - - def test_NR_DEC_p1_04_j2k_51_decode(self): - actual = self.j2k[640:768:4, 512:640:4] - expected = self.j2k_quarter_data[160:192, 128:160] - np.testing.assert_array_equal(actual, expected) - - def test_NR_DEC_p1_04_j2k_52_decode(self): - actual = self.j2k[896:1024:4, 896:1024:4] - expected = self.j2k_quarter_data[224:352, 224:352] - np.testing.assert_array_equal(actual, expected) - - def test_NR_DEC_p1_04_j2k_53_decode(self): - actual = self.j2k[500:800:4, 100:300:4] - expected = self.j2k_quarter_data[125:200, 25:75] - np.testing.assert_array_equal(actual, expected) - - def test_NR_DEC_p1_04_j2k_54_decode(self): - actual = self.j2k[520:600:4, 260:360:4] - expected = self.j2k_quarter_data[130:150, 65:90] - np.testing.assert_array_equal(actual, expected) - - def test_NR_DEC_p1_04_j2k_55_decode(self): - actual = self.j2k[520:660:4, 260:360:4] - expected = self.j2k_quarter_data[130:165, 65:90] - np.testing.assert_array_equal(actual, expected) - - def test_NR_DEC_p1_04_j2k_56_decode(self): - actual = self.j2k[520:600:4, 360:400:4] - expected = self.j2k_quarter_data[130:150, 90:100] - np.testing.assert_array_equal(actual, expected) - - def test_NR_DEC_p1_06_j2k_75_decode(self): - # Image size would be 0 x 0. - with self.assertRaises((IOError, OSError)): - self.j2k[9:12:4, 9:12:4] - - def test_NR_DEC_p0_04_j2k_85_decode(self): - actual = self.j2k[:256, :256] - expected = self.j2k_data[:256, :256] - np.testing.assert_array_equal(actual, expected) - - def test_NR_DEC_p0_04_j2k_86_decode(self): - actual = self.j2k[:128, 128:256] - expected = self.j2k_data[:128, 128:256] - np.testing.assert_array_equal(actual, expected) - - def test_NR_DEC_p0_04_j2k_87_decode(self): - actual = self.j2k[10:200, 50:120] - expected = self.j2k_data[10:200, 50:120] - np.testing.assert_array_equal(actual, expected) - - def test_NR_DEC_p0_04_j2k_88_decode(self): - actual = self.j2k[150:210, 10:190] - expected = self.j2k_data[150:210, 10:190] - np.testing.assert_array_equal(actual, expected) - - def test_NR_DEC_p0_04_j2k_89_decode(self): - actual = self.j2k[80:150, 100:200] - expected = self.j2k_data[80:150, 100:200] - np.testing.assert_array_equal(actual, expected) - - def test_NR_DEC_p0_04_j2k_90_decode(self): - actual = self.j2k[20:50, 150:200] - expected = self.j2k_data[20:50, 150:200] - np.testing.assert_array_equal(actual, expected) - - def test_NR_DEC_p0_04_j2k_91_decode(self): - actual = self.j2k[:256:4, :256:4] - expected = self.j2k_quarter_data[0:64, 0:64] - np.testing.assert_array_equal(actual, expected) - - def test_NR_DEC_p0_04_j2k_92_decode(self): - actual = self.j2k[:128:4, 128:256:4] - expected = self.j2k_quarter_data[:32, 32:64] - np.testing.assert_array_equal(actual, expected) - - def test_NR_DEC_p0_04_j2k_93_decode(self): - actual = self.j2k[10:200:4, 50:120:4] - expected = self.j2k_quarter_data[3:50, 13:30] - np.testing.assert_array_equal(actual, expected) - - def test_NR_DEC_p0_04_j2k_94_decode(self): - actual = self.j2k[150:210:4, 10:190:4] - expected = self.j2k_quarter_data[38:53, 3:48] - np.testing.assert_array_equal(actual, expected) - - def test_NR_DEC_p0_04_j2k_95_decode(self): - actual = self.j2k[80:150:4, 100:200:4] - expected = self.j2k_quarter_data[20:38, 25:50] - np.testing.assert_array_equal(actual, expected) - - def test_NR_DEC_p0_04_j2k_96_decode(self): - actual = self.j2k[20:50:4, 150:200:4] - expected = self.j2k_quarter_data[5:13, 38:50] + expected = self.j2k_data_r5[1:17, 1:14] np.testing.assert_array_equal(actual, expected) class TestJp2k(unittest.TestCase): @@ -476,6 +251,12 @@ class TestJp2k(unittest.TestCase): def tearDown(self): pass + @unittest.skipIf(WARNING_INFRASTRUCTURE_ISSUE, WARNING_INFRASTRUCTURE_MSG) + def test_warn_if_using_read_method(self): + """Should warn if deprecated read method is called""" + with self.assertWarns(DeprecationWarning): + Jp2k(self.jp2file).read() + def test_shape_jp2(self): """verify shape attribute for JP2 file """ @@ -515,20 +296,21 @@ class TestJp2k(unittest.TestCase): jpx = Jp2k(self.jpxfile) self.assertEqual(jpx.shape, (1024, 1024, 3)) + @unittest.skipIf(re.match("0|1.[0-4]", glymur.version.openjpeg_version), + "Must have openjpeg 1.5 or higher to run") @unittest.skipIf(os.name == "nt", "Unexplained failure on windows") def test_irreversible(self): """Irreversible""" j = Jp2k(self.jp2file) - expdata = j.read() + expdata = j[:] with tempfile.NamedTemporaryFile(suffix='.j2k') as tfile: - j2 = Jp2k(tfile.name, 'wb') - j2.write(expdata, irreversible=True) + j2 = Jp2k(tfile.name, data=expdata, irreversible=True) codestream = j2.get_codestream() self.assertEqual(codestream.segment[2].spcod[8], glymur.core.WAVELET_XFORM_9X7_IRREVERSIBLE) - actdata = j2.read() + actdata = j2[:] self.assertTrue(fixtures.mse(actdata[0], expdata[0]) < 0.38) @unittest.skipIf(re.match('1.[0-4]', openjpeg_version) is not None, @@ -538,8 +320,9 @@ class TestJp2k(unittest.TestCase): def test_no_cxform_pclr_jpx(self): """Indices for pclr jpxfile if no color transform""" j = Jp2k(self.jpxfile) - rgb = j.read() - idx = j.read(ignore_pclr_cmap_cdef=True) + rgb = j[:] + j.ignore_pclr_cmap_cdef = True + idx = j[:] nr, nc = 1024, 1024 self.assertEqual(rgb.shape, (nr, nc, 3)) self.assertEqual(idx.shape, (nr, nc)) @@ -560,14 +343,27 @@ class TestJp2k(unittest.TestCase): newjp2 = eval(repr(j)) self.assertEqual(newjp2.filename, self.j2kfile) - self.assertEqual(newjp2.mode, 'rb') self.assertEqual(len(newjp2.box), 0) - def test_rlevel_max(self): - """Verify that rlevel=-1 gets us the lowest resolution image""" + @unittest.skipIf(WARNING_INFRASTRUCTURE_ISSUE, WARNING_INFRASTRUCTURE_MSG) + def test_rlevel_max_backwards_compatibility(self): + """ + Verify that rlevel=-1 gets us the lowest resolution image + + This is an old option only available via the read method, not via + array-style slicing. + """ j = Jp2k(self.j2kfile) - thumbnail1 = j.read(rlevel=-1) - thumbnail2 = j.read(rlevel=5) + if sys.hexversion < 0x03000000: + with warnings.catch_warnings(): + # Suppress a warning due to deprecated syntax + # Not as easy to verify the warning under python2. + warnings.simplefilter("ignore") + thumbnail1 = j.read(rlevel=-1) + else: + with self.assertWarns(DeprecationWarning): + thumbnail1 = j.read(rlevel=-1) + thumbnail2 = j[::32, ::32] np.testing.assert_array_equal(thumbnail1, thumbnail2) self.assertEqual(thumbnail1.shape, (25, 15, 3)) @@ -575,7 +371,7 @@ class TestJp2k(unittest.TestCase): """Should error out appropriately if reduce level too high""" j = Jp2k(self.jp2file) with self.assertRaises(IOError): - j.read(rlevel=6) + j[::64, ::64] def test_not_jpeg2000(self): """Should error out appropriately if not given a JPEG 2000 file.""" @@ -726,7 +522,7 @@ class TestJp2k(unittest.TestCase): """Just a very basic test that reading a JP2 file does not error out. """ j2k = Jp2k(self.jp2file) - j2k.read(rlevel=1) + j2k[::2, ::2] def test_basic_j2k(self): """This test is only useful when openjp2 is not available @@ -734,7 +530,7 @@ class TestJp2k(unittest.TestCase): working J2K test. """ j2k = Jp2k(self.j2kfile) - j2k.read() + j2k[:] def test_empty_box_with_j2k(self): """Verify that the list of boxes in a J2C/J2K file is present, but @@ -859,7 +655,7 @@ class TestJp2k(unittest.TestCase): """Read JPX codestream when jp2-compatible.""" # The file in question has multiple codestreams. jpx = Jp2k(self.jpxfile) - data = jpx.read() + data = jpx[:] self.assertEqual(data.shape, (1024, 1024, 3)) def test_read_bands_without_openjp2(self): @@ -886,32 +682,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): - j = Jp2k(tfile.name, 'wb') - j.write(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): - j = Jp2k(tfile.name, 'wb') - j.write(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): - j = Jp2k(tfile.name, 'wb') - j.write(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): - j = Jp2k(tfile.name, 'wb') - j.write(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""" @@ -921,8 +715,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): - j = Jp2k(tfile.name, 'wb') - j.write(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 @@ -930,11 +723,8 @@ class TestJp2k_write(unittest.TestCase): """ data = np.zeros((128, 128), dtype=np.uint8) with tempfile.NamedTemporaryFile(suffix='.j2k') as tfile: - j = Jp2k(tfile.name, 'wb') - # The code block dimensions are given as rows x columns. - j.write(data, cbsize=(16, 32)) - + j = Jp2k(tfile.name, data=data, cbsize=(16, 32)) codestream = j.get_codestream() # Code block size is reported as XY in the codestream. @@ -943,59 +733,55 @@ class TestJp2k_write(unittest.TestCase): def test_too_many_dimensions(self): """OpenJP2 only allows 2D or 3D images.""" with tempfile.NamedTemporaryFile(suffix='.j2k') as tfile: - j = Jp2k(tfile.name, 'wb') with self.assertRaises(IOError): - data = np.zeros((128, 128, 2, 2), dtype=np.uint8) - j.write(data) + 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: - j = Jp2k(tfile.name, 'wb') with self.assertRaises(IOError): - data = np.zeros((128, 128, 2), dtype=np.uint8) - j.write(data, 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: - j = Jp2k(tfile.name, 'wb') with self.assertRaises(IOError): - data = np.zeros((128, 128, 3), dtype=np.uint8) - j.write(data, 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, 'wb') - data = np.zeros((128, 128, 3), dtype=np.uint8) - j.write(data, colorspace='rgb') + j = Jp2k(tfile.name, + 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): """test gray explicitly specified (that's GRAY, not GREY)""" with tempfile.NamedTemporaryFile(suffix='.jp2') as tfile: - j = Jp2k(tfile.name, 'wb') data = np.zeros((128, 128), dtype=np.uint8) - j.write(data, colorspace='gray') + j = Jp2k(tfile.name, data=data, colorspace='gray') self.assertEqual(j.box[2].box[1].colorspace, glymur.core.GREYSCALE) def test_specify_grey(self): """test grey explicitly specified""" with tempfile.NamedTemporaryFile(suffix='.jp2') as tfile: - j = Jp2k(tfile.name, 'wb') data = np.zeros((128, 128), dtype=np.uint8) - j.write(data, colorspace='grey') + j = Jp2k(tfile.name, data=data, colorspace='grey') self.assertEqual(j.box[2].box[1].colorspace, glymur.core.GREYSCALE) def test_grey_with_two_extra_comps(self): """should be able to write gray + two extra components""" with tempfile.NamedTemporaryFile(suffix='.jp2') as tfile: - j = Jp2k(tfile.name, 'wb') data = np.zeros((128, 128, 3), dtype=np.uint8) - j.write(data, colorspace='gray') + j = Jp2k(tfile.name, data=data, colorspace='gray') self.assertEqual(j.box[2].box[0].height, 128) self.assertEqual(j.box[2].box[0].width, 128) self.assertEqual(j.box[2].box[0].num_components, 3) @@ -1005,29 +791,26 @@ class TestJp2k_write(unittest.TestCase): def test_specify_ycc(self): """Should reject YCC""" with tempfile.NamedTemporaryFile(suffix='.jp2') as tfile: - j = Jp2k(tfile.name, 'wb') with self.assertRaises(IOError): data = np.zeros((128, 128, 3), dtype=np.uint8) - j.write(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.""" j2k = Jp2k(self.j2kfile) - expdata = j2k.read() + expdata = j2k[:] with tempfile.NamedTemporaryFile(suffix='.JP2') as tfile: - ofile = Jp2k(tfile.name, 'wb') - ofile.write(expdata) - actdata = ofile.read() + ofile = Jp2k(tfile.name, data=expdata) + actdata = ofile[:] np.testing.assert_array_equal(actdata, expdata) def test_write_srgb_without_mct(self): """should be able to write RGB without specifying mct""" j2k = Jp2k(self.j2kfile) - expdata = j2k.read() + expdata = j2k[:] with tempfile.NamedTemporaryFile(suffix='.jp2') as tfile: - ofile = Jp2k(tfile.name, 'wb') - ofile.write(expdata, mct=False) - actdata = ofile.read() + ofile = Jp2k(tfile.name, data=expdata, mct=False) + actdata = ofile[:] np.testing.assert_array_equal(actdata, expdata) codestream = ofile.get_codestream() @@ -1036,21 +819,19 @@ class TestJp2k_write(unittest.TestCase): def test_write_grayscale_with_mct(self): """MCT usage makes no sense for grayscale images.""" j2k = Jp2k(self.j2kfile) - expdata = j2k.read() + expdata = j2k[:] with tempfile.NamedTemporaryFile(suffix='.jp2') as tfile: - ofile = Jp2k(tfile.name, 'wb') with self.assertRaises(IOError): - ofile.write(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""" # Issue 17 j = Jp2k(self.jp2file) - expdata = j.read(rlevel=1) + expdata = j[::2, ::2] with tempfile.NamedTemporaryFile(suffix='.jp2') as tfile: - ofile = Jp2k(tfile.name, 'wb') - ofile.write(expdata, prog='CPRL') - actdata = ofile.read() + ofile = Jp2k(tfile.name, data=expdata, prog='CPRL') + actdata = ofile[:] np.testing.assert_array_equal(actdata, expdata) codestream = ofile.get_codestream() @@ -1072,16 +853,19 @@ class TestJp2k_1_x(unittest.TestCase): """ with patch('glymur.version.openjpeg_version_tuple', new=(1, 5, 0)): j2k = Jp2k(self.j2kfile) - with self.assertRaises(TypeError): - j2k.read(tile=0) + with warnings.catch_warnings(): + # The tile keyword is deprecated, so suppress the warning. + warnings.simplefilter('ignore') + with self.assertRaises(TypeError): + j2k.read(tile=0) def test_layer(self): """layer option not allowed for 1.x. """ with patch('glymur.version.openjpeg_version_tuple', new=(1, 5, 0)): j2k = Jp2k(self.j2kfile) - with self.assertRaises(TypeError): - j2k.read(layer=1) + with self.assertRaises(RuntimeError): + j2k.layer = 1 @unittest.skipIf(os.name == "nt", fixtures.WINDOWS_TMP_FILE_MSG) @@ -1092,10 +876,9 @@ class Test_2p0_official(unittest.TestCase): """Can only write 4 components on 2.0+, should error out otherwise.""" with patch('glymur.version.openjpeg_version', new="2.0.0"): with tempfile.NamedTemporaryFile(suffix='.jp2') as tfile: - j = Jp2k(tfile.name, 'wb') data = np.zeros((128, 128, 4), dtype=np.uint8) with self.assertRaises(IOError): - j.write(data) + Jp2k(tfile.name, data=data) @unittest.skipIf(glymur.version.openjpeg_version_tuple[0] < 2, @@ -1115,32 +898,30 @@ class TestJp2k_2_0(unittest.TestCase): j = Jp2k(self.jp2file) with self.assertRaises(IOError): # Start corner must be >= 0 - j.read(area=(-1, -1, 1, 1)) + j[-1:1, -1:1] with self.assertRaises(IOError): # End corner must be > 0 - j.read(area=(10, 10, 0, 0)) + j[10:0, 10:0] with self.assertRaises(IOError): # End corner must be >= start corner - j.read(area=(10, 10, 8, 8)) + j[10:8, 10:8] @unittest.skipIf(os.name == "nt", fixtures.WINDOWS_TMP_FILE_MSG) def test_unrecognized_jp2_clrspace(self): """We only allow RGB and GRAYSCALE. Should error out with others""" with tempfile.NamedTemporaryFile(suffix='.jp2') as tfile: - j = Jp2k(tfile.name, 'wb') + data = np.zeros((128, 128, 3), dtype=np.uint8) with self.assertRaises(IOError): - data = np.zeros((128, 128, 3), dtype=np.uint8) - j.write(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): """Test asoc and label box""" # Construct a fake file with an asoc and a label box, as # OpenJPEG doesn't have such a file. - data = Jp2k(self.jp2file).read(rlevel=1) + data = Jp2k(self.jp2file)[::2, ::2] with tempfile.NamedTemporaryFile(suffix='.jp2') as tfile: - j = Jp2k(tfile.name, 'wb') - j.write(data) + j = Jp2k(tfile.name, data=data) with tempfile.NamedTemporaryFile(suffix='.jp2') as tfile2: @@ -1198,9 +979,8 @@ class TestJp2k_2_1(unittest.TestCase): def test_grey_with_extra_component(self): """version 2.0 cannot write gray + extra""" with tempfile.NamedTemporaryFile(suffix='.jp2') as tfile: - j = Jp2k(tfile.name, 'wb') data = np.zeros((128, 128, 2), dtype=np.uint8) - j.write(data) + j = Jp2k(tfile.name, data=data) self.assertEqual(j.box[2].box[0].height, 128) self.assertEqual(j.box[2].box[0].width, 128) self.assertEqual(j.box[2].box[0].num_components, 2) @@ -1211,9 +991,8 @@ class TestJp2k_2_1(unittest.TestCase): def test_rgb_with_extra_component(self): """v2.0+ should be able to write extra components""" with tempfile.NamedTemporaryFile(suffix='.jp2') as tfile: - j = Jp2k(tfile.name, 'wb') data = np.zeros((128, 128, 4), dtype=np.uint8) - j.write(data) + j = Jp2k(tfile.name, data=data) self.assertEqual(j.box[2].box[0].height, 128) self.assertEqual(j.box[2].box[0].width, 128) self.assertEqual(j.box[2].box[0].num_components, 4) @@ -1238,11 +1017,9 @@ class TestJp2k_2_1(unittest.TestCase): tfile.write(data[offset+53:offset+55]) tfile.write(b'\x00') tfile.write(data[offset+57:offset+59]) - #tfile.write(data[3184:3186]) tfile.write(b'\x00') tfile.write(data[offset+59:]) - #tfile.write(data[3186:]) tfile.flush() with warnings.catch_warnings(): warnings.simplefilter('ignore') @@ -1252,10 +1029,10 @@ class TestJp2k_2_1(unittest.TestCase): :\sdx=1\sdy=0''', re.VERBOSE) if sys.hexversion < 0x03020000: with self.assertRaisesRegexp((IOError, OSError), regexp): - j.read(rlevel=1) + j[::2, ::2] else: with self.assertRaisesRegex((IOError, OSError), regexp): - j.read(rlevel=1) + j[::2, ::2] @unittest.skipIf(OPJ_DATA_ROOT is None, "OPJ_DATA_ROOT environment variable not set") @@ -1280,7 +1057,6 @@ class TestParsing(unittest.TestCase): with self.assertWarnsRegex(UserWarning, 'Invalid profile'): jp2 = Jp2k(filename) - #@unittest.skip('trouble is a brewing...') def test_main_header(self): """Verify that the main header is not loaded when parsing turned off.""" # The hidden _main_header attribute should show up after accessing it. @@ -1342,6 +1118,8 @@ class TestJp2kOpjDataRootWarnings(unittest.TestCase): class TestJp2kOpjDataRoot(unittest.TestCase): """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") @unittest.skipIf(os.name == "nt", fixtures.WINDOWS_TMP_FILE_MSG) def test_irreversible(self): """Irreversible""" @@ -1349,14 +1127,13 @@ class TestJp2kOpjDataRoot(unittest.TestCase): expdata = np.fromfile(filename, dtype=np.uint16) expdata.resize((2816, 2048)) with tempfile.NamedTemporaryFile(suffix='.j2k') as tfile: - j = Jp2k(tfile.name, 'wb') - j.write(expdata, irreversible=True) + j = Jp2k(tfile.name, data=expdata, irreversible=True) codestream = j.get_codestream() self.assertEqual(codestream.segment[2].spcod[8], glymur.core.WAVELET_XFORM_9X7_IRREVERSIBLE) - actdata = j.read() + actdata = j[:] self.assertTrue(fixtures.mse(actdata, expdata) < 250) @unittest.skipIf(WARNING_INFRASTRUCTURE_ISSUE, WARNING_INFRASTRUCTURE_MSG) @@ -1364,15 +1141,16 @@ class TestJp2kOpjDataRoot(unittest.TestCase): """Indices for pclr jpxfile if no color transform""" filename = opj_data_file('input/conformance/file9.jp2') with self.assertWarns(UserWarning): - j = Jp2k(filename) - rgb = j.read() - idx = j.read(ignore_pclr_cmap_cdef=True) + jp2 = Jp2k(filename) + rgb = jp2[:] + jp2.ignore_pclr_cmap_cdef = True + idx = jp2[:] self.assertEqual(rgb.shape, (512, 768, 3)) self.assertEqual(idx.shape, (512, 768)) # Should be able to manually reconstruct the RGB image from the palette # and indices. - palette = j.box[2].box[1].palette + palette = jp2.box[2].box[1].palette rgb_from_idx = np.zeros(rgb.shape, dtype=np.uint8) for r in np.arange(rgb.shape[0]): for c in np.arange(rgb.shape[1]): @@ -1388,7 +1166,7 @@ class TestJp2kOpjDataRoot(unittest.TestCase): filename = opj_data_file('input/conformance/p0_05.j2k') j = Jp2k(filename) with self.assertRaises(RuntimeError): - j.read() + j[:] @unittest.skipIf(WARNING_INFRASTRUCTURE_ISSUE, WARNING_INFRASTRUCTURE_MSG) def test_no_cxform_cmap(self): @@ -1399,8 +1177,9 @@ class TestJp2kOpjDataRoot(unittest.TestCase): with self.assertWarns(UserWarning): # The file has a bad compatibility list entry. Not important here. j = Jp2k(filename) - ycbcr = j.read() - crcby = j.read(ignore_pclr_cmap_cdef=True) + ycbcr = j[:] + j.ignore_pclr_cmap_cdef = True + crcby = j[:] expected = np.zeros(ycbcr.shape, ycbcr.dtype) for k in range(crcby.shape[2]): @@ -1409,6 +1188,259 @@ class TestJp2kOpjDataRoot(unittest.TestCase): np.testing.assert_array_equal(ycbcr, expected) +class TestCodestream(unittest.TestCase): + """Test suite for unusual codestream cases.""" -if __name__ == "__main__": - unittest.main() + def setUp(self): + self.jp2file = glymur.data.nemo() + + def tearDown(self): + pass + + def test_siz_segment_ssiz_unsigned(self): + """ssiz attribute to be removed in future release""" + j = Jp2k(self.jp2file) + codestream = j.get_codestream() + + # The ssiz attribute was simply a tuple of raw bytes. + # The first 7 bits are interpreted as the bitdepth, the MSB determines + # whether or not it is signed. + self.assertEqual(codestream.segment[1].ssiz, (7, 7, 7)) + + +@unittest.skipIf(OPJ_DATA_ROOT is None, + "OPJ_DATA_ROOT environment variable not set") +class TestCodestreamOpjData(unittest.TestCase): + """Test suite for unusual codestream cases. Uses OPJ_DATA_ROOT""" + + def setUp(self): + self.jp2file = glymur.data.nemo() + + def tearDown(self): + pass + + @unittest.skipIf(os.name == "nt", "Temporary file issue on window.") + def test_reserved_marker_segment(self): + """Reserved marker segments are ok.""" + + # Some marker segments were reserved in FCD15444-1. Since that + # standard is old, some of them may have come into use. + # + # Let's inject a reserved marker segment into a file that + # we know something about to make sure we can still parse it. + filename = os.path.join(OPJ_DATA_ROOT, 'input/conformance/p0_01.j2k') + with tempfile.NamedTemporaryFile(suffix='.j2k') as tfile: + with open(filename, 'rb') as ifile: + # Everything up until the first QCD marker. + read_buffer = ifile.read(45) + tfile.write(read_buffer) + + # Write the new marker segment, 0xff6f = 65391 + read_buffer = struct.pack('>HHB', int(65391), int(3), int(0)) + tfile.write(read_buffer) + + # Get the rest of the input file. + read_buffer = ifile.read() + tfile.write(read_buffer) + tfile.flush() + + codestream = Jp2k(tfile.name).get_codestream() + + self.assertEqual(codestream.segment[2].marker_id, '0xff6f') + self.assertEqual(codestream.segment[2].length, 3) + self.assertEqual(codestream.segment[2].data, b'\x00') + + def test_psot_is_zero(self): + """Psot=0 in SOT is perfectly legal. Issue #78.""" + filename = os.path.join(OPJ_DATA_ROOT, + 'input/nonregression/123.j2c') + j = Jp2k(filename) + codestream = j.get_codestream(header_only=False) + + # The codestream is valid, so we should be able to get the entire + # codestream, so the last one is EOC. + self.assertEqual(codestream.segment[-1].marker_id, 'EOC') + + + def test_siz_segment_ssiz_signed(self): + """ssiz attribute to be removed in future release""" + filename = os.path.join(OPJ_DATA_ROOT, 'input/conformance/p0_03.j2k') + j = Jp2k(filename) + codestream = j.get_codestream() + + # The ssiz attribute was simply a tuple of raw bytes. + # The first 7 bits are interpreted as the bitdepth, the MSB determines + # whether or not it is signed. + self.assertEqual(codestream.segment[1].ssiz, (131,)) + + +class TestCodestreamRepr(unittest.TestCase): + + def setUp(self): + self.jp2file = glymur.data.nemo() + + def tearDown(self): + pass + + def test_soc(self): + """Test SOC segment repr""" + segment = glymur.codestream.SOCsegment() + newseg = eval(repr(segment)) + self.assertEqual(newseg.marker_id, 'SOC') + + def test_siz(self): + """Test SIZ segment repr""" + kwargs = {'rsiz': 0, + 'xysiz': (2592, 1456), + 'xyosiz': (0, 0), + 'xytsiz': (2592, 1456), + 'xytosiz': (0, 0), + 'Csiz': 3, + 'bitdepth': (8, 8, 8), + 'signed': (False, False, False), + 'xyrsiz': ((1, 1, 1), (1, 1, 1))} + segment = glymur.codestream.SIZsegment(**kwargs) + newseg = eval(repr(segment)) + self.assertEqual(newseg.marker_id, 'SIZ') + self.assertEqual(newseg.xsiz, 2592) + self.assertEqual(newseg.ysiz, 1456) + self.assertEqual(newseg.xosiz, 0) + self.assertEqual(newseg.yosiz, 0) + self.assertEqual(newseg.xtsiz, 2592) + self.assertEqual(newseg.ytsiz, 1456) + self.assertEqual(newseg.xtosiz, 0) + self.assertEqual(newseg.ytosiz, 0) + + self.assertEqual(newseg.xrsiz, (1, 1, 1)) + self.assertEqual(newseg.yrsiz, (1, 1, 1)) + self.assertEqual(newseg.bitdepth, (8, 8, 8)) + self.assertEqual(newseg.signed, (False, False, False)) + + +class TestCodestream(unittest.TestCase): + """Test suite for unusual codestream cases.""" + + def setUp(self): + self.jp2file = glymur.data.nemo() + + def tearDown(self): + pass + + def test_siz_segment_ssiz_unsigned(self): + """ssiz attribute to be removed in future release""" + j = Jp2k(self.jp2file) + codestream = j.get_codestream() + + # The ssiz attribute was simply a tuple of raw bytes. + # The first 7 bits are interpreted as the bitdepth, the MSB determines + # whether or not it is signed. + self.assertEqual(codestream.segment[1].ssiz, (7, 7, 7)) + + +@unittest.skipIf(OPJ_DATA_ROOT is None, + "OPJ_DATA_ROOT environment variable not set") +class TestCodestreamOpjData(unittest.TestCase): + """Test suite for unusual codestream cases. Uses OPJ_DATA_ROOT""" + + def setUp(self): + self.jp2file = glymur.data.nemo() + + def tearDown(self): + pass + + @unittest.skipIf(os.name == "nt", "Temporary file issue on window.") + def test_reserved_marker_segment(self): + """Reserved marker segments are ok.""" + + # Some marker segments were reserved in FCD15444-1. Since that + # standard is old, some of them may have come into use. + # + # Let's inject a reserved marker segment into a file that + # we know something about to make sure we can still parse it. + filename = os.path.join(OPJ_DATA_ROOT, 'input/conformance/p0_01.j2k') + with tempfile.NamedTemporaryFile(suffix='.j2k') as tfile: + with open(filename, 'rb') as ifile: + # Everything up until the first QCD marker. + read_buffer = ifile.read(45) + tfile.write(read_buffer) + + # Write the new marker segment, 0xff6f = 65391 + read_buffer = struct.pack('>HHB', int(65391), int(3), int(0)) + tfile.write(read_buffer) + + # Get the rest of the input file. + read_buffer = ifile.read() + tfile.write(read_buffer) + tfile.flush() + + codestream = Jp2k(tfile.name).get_codestream() + + self.assertEqual(codestream.segment[2].marker_id, '0xff6f') + self.assertEqual(codestream.segment[2].length, 3) + self.assertEqual(codestream.segment[2].data, b'\x00') + + def test_psot_is_zero(self): + """Psot=0 in SOT is perfectly legal. Issue #78.""" + filename = os.path.join(OPJ_DATA_ROOT, + 'input/nonregression/123.j2c') + j = Jp2k(filename) + codestream = j.get_codestream(header_only=False) + + # The codestream is valid, so we should be able to get the entire + # codestream, so the last one is EOC. + self.assertEqual(codestream.segment[-1].marker_id, 'EOC') + + + def test_siz_segment_ssiz_signed(self): + """ssiz attribute to be removed in future release""" + filename = os.path.join(OPJ_DATA_ROOT, 'input/conformance/p0_03.j2k') + j = Jp2k(filename) + codestream = j.get_codestream() + + # The ssiz attribute was simply a tuple of raw bytes. + # The first 7 bits are interpreted as the bitdepth, the MSB determines + # whether or not it is signed. + self.assertEqual(codestream.segment[1].ssiz, (131,)) + + +class TestCodestreamRepr(unittest.TestCase): + + def setUp(self): + self.jp2file = glymur.data.nemo() + + def tearDown(self): + pass + + def test_soc(self): + """Test SOC segment repr""" + segment = glymur.codestream.SOCsegment() + newseg = eval(repr(segment)) + self.assertEqual(newseg.marker_id, 'SOC') + + def test_siz(self): + """Test SIZ segment repr""" + kwargs = {'rsiz': 0, + 'xysiz': (2592, 1456), + 'xyosiz': (0, 0), + 'xytsiz': (2592, 1456), + 'xytosiz': (0, 0), + 'Csiz': 3, + 'bitdepth': (8, 8, 8), + 'signed': (False, False, False), + 'xyrsiz': ((1, 1, 1), (1, 1, 1))} + segment = glymur.codestream.SIZsegment(**kwargs) + newseg = eval(repr(segment)) + self.assertEqual(newseg.marker_id, 'SIZ') + self.assertEqual(newseg.xsiz, 2592) + self.assertEqual(newseg.ysiz, 1456) + self.assertEqual(newseg.xosiz, 0) + self.assertEqual(newseg.yosiz, 0) + self.assertEqual(newseg.xtsiz, 2592) + self.assertEqual(newseg.ytsiz, 1456) + self.assertEqual(newseg.xtosiz, 0) + self.assertEqual(newseg.ytosiz, 0) + + self.assertEqual(newseg.xrsiz, (1, 1, 1)) + self.assertEqual(newseg.yrsiz, (1, 1, 1)) + self.assertEqual(newseg.bitdepth, (8, 8, 8)) + self.assertEqual(newseg.signed, (False, False, False)) diff --git a/glymur/test/test_opj_suite.py b/glymur/test/test_opj_suite.py index a033aae..cf44eaa 100644 --- a/glymur/test/test_opj_suite.py +++ b/glymur/test/test_opj_suite.py @@ -30,6 +30,7 @@ suite. import re import sys import unittest +import warnings import numpy as np @@ -57,7 +58,7 @@ class TestSuite(unittest.TestCase): def test_ETS_C1P0_p0_01_j2k(self): jfile = opj_data_file('input/conformance/p0_01.j2k') jp2k = Jp2k(jfile) - jpdata = jp2k.read(rlevel=0) + jpdata = jp2k[:] pgxfile = opj_data_file('baseline/conformance/c1p0_01_0.pgx') pgxdata = read_pgx(pgxfile) @@ -67,7 +68,7 @@ class TestSuite(unittest.TestCase): def test_ETS_C1P0_p0_03_j2k(self): jfile = opj_data_file('input/conformance/p0_03.j2k') jp2k = Jp2k(jfile) - jpdata = jp2k.read(rlevel=0) + jpdata = jp2k[:] pgxfile = opj_data_file('baseline/conformance/c1p0_03_0.pgx') pgxdata = read_pgx(pgxfile) @@ -77,7 +78,7 @@ class TestSuite(unittest.TestCase): def test_ETS_C1P0_p0_04_j2k(self): jfile = opj_data_file('input/conformance/p0_04.j2k') jp2k = Jp2k(jfile) - jpdata = jp2k.read(rlevel=0) + jpdata = jp2k[:] pgxfile = opj_data_file('baseline/conformance/c1p0_04_0.pgx') pgxdata = read_pgx(pgxfile) @@ -97,7 +98,7 @@ class TestSuite(unittest.TestCase): def test_ETS_C1P0_p0_08_j2k(self): jfile = opj_data_file('input/conformance/p0_08.j2k') jp2k = Jp2k(jfile) - jpdata = jp2k.read(rlevel=1) + jpdata = jp2k[::2, ::2] pgxfile = opj_data_file('baseline/conformance/c1p0_08_0.pgx') pgxdata = read_pgx(pgxfile) @@ -114,7 +115,7 @@ class TestSuite(unittest.TestCase): def test_ETS_C1P0_p0_09_j2k(self): jfile = opj_data_file('input/conformance/p0_09.j2k') jp2k = Jp2k(jfile) - jpdata = jp2k.read(rlevel=0) + jpdata = jp2k[:] pgxfile = opj_data_file('baseline/conformance/c1p0_09_0.pgx') pgxdata = read_pgx(pgxfile) @@ -123,7 +124,7 @@ class TestSuite(unittest.TestCase): def test_ETS_C1P0_p0_11_j2k(self): jfile = opj_data_file('input/conformance/p0_11.j2k') jp2k = Jp2k(jfile) - jpdata = jp2k.read(rlevel=0) + jpdata = jp2k[:] pgxfile = opj_data_file('baseline/conformance/c1p0_11_0.pgx') pgxdata = read_pgx(pgxfile) @@ -132,7 +133,7 @@ class TestSuite(unittest.TestCase): def test_ETS_C1P0_p0_14_j2k(self): jfile = opj_data_file('input/conformance/p0_14.j2k') jp2k = Jp2k(jfile) - jpdata = jp2k.read(rlevel=0) + jpdata = jp2k[:] pgxfile = opj_data_file('baseline/conformance/c1p0_14_0.pgx') pgxdata = read_pgx(pgxfile) @@ -149,7 +150,7 @@ class TestSuite(unittest.TestCase): def test_ETS_C1P0_p0_15_j2k(self): jfile = opj_data_file('input/conformance/p0_15.j2k') jp2k = Jp2k(jfile) - jpdata = jp2k.read(rlevel=0) + jpdata = jp2k[:] pgxfile = opj_data_file('baseline/conformance/c1p0_15_0.pgx') pgxdata = read_pgx(pgxfile) @@ -158,7 +159,7 @@ class TestSuite(unittest.TestCase): def test_ETS_C1P0_p0_16_j2k(self): jfile = opj_data_file('input/conformance/p0_16.j2k') jp2k = Jp2k(jfile) - jpdata = jp2k.read(rlevel=0) + jpdata = jp2k[:] pgxfile = opj_data_file('baseline/conformance/c1p0_16_0.pgx') pgxdata = read_pgx(pgxfile) @@ -167,7 +168,7 @@ class TestSuite(unittest.TestCase): def test_ETS_C1P1_p1_01_j2k(self): jfile = opj_data_file('input/conformance/p1_01.j2k') jp2k = Jp2k(jfile) - jpdata = jp2k.read(rlevel=0) + jpdata = jp2k[:] pgxfile = opj_data_file('baseline/conformance/c1p1_01_0.pgx') pgxdata = read_pgx(pgxfile) @@ -176,7 +177,7 @@ class TestSuite(unittest.TestCase): def test_ETS_C1P1_p1_02_j2k(self): jfile = opj_data_file('input/conformance/p1_02.j2k') jp2k = Jp2k(jfile) - jpdata = jp2k.read(rlevel=0) + jpdata = jp2k[:] pgxfile = opj_data_file('baseline/conformance/c1p1_02_0.pgx') pgxdata = read_pgx(pgxfile) @@ -196,7 +197,7 @@ class TestSuite(unittest.TestCase): def test_ETS_C1P1_p1_04_j2k(self): jfile = opj_data_file('input/conformance/p1_04.j2k') jp2k = Jp2k(jfile) - jpdata = jp2k.read() + jpdata = jp2k[:] pgxfile = opj_data_file('baseline/conformance/c1p1_04_0.pgx') pgxdata = read_pgx(pgxfile) @@ -206,95 +207,95 @@ class TestSuite(unittest.TestCase): def test_NR_DEC_Bretagne2_j2k_1_decode(self): jfile = opj_data_file('input/nonregression/Bretagne2.j2k') jp2 = Jp2k(jfile) - jp2.read() + jp2[:] self.assertTrue(True) def test_NR_DEC__00042_j2k_2_decode(self): jfile = opj_data_file('input/nonregression/_00042.j2k') jp2 = Jp2k(jfile) - jp2.read() + jp2[:] self.assertTrue(True) def test_NR_DEC_buxI_j2k_9_decode(self): jfile = opj_data_file('input/nonregression/buxI.j2k') - Jp2k(jfile).read() + Jp2k(jfile)[:] self.assertTrue(True) def test_NR_DEC_buxR_j2k_10_decode(self): jfile = opj_data_file('input/nonregression/buxR.j2k') - Jp2k(jfile).read() + Jp2k(jfile)[:] self.assertTrue(True) def test_NR_DEC_Cannotreaddatawithnosizeknown_j2k_11_decode(self): relpath = 'input/nonregression/Cannotreaddatawithnosizeknown.j2k' jfile = opj_data_file(relpath) - Jp2k(jfile).read() + Jp2k(jfile)[:] self.assertTrue(True) def test_NR_DEC_cthead1_j2k_12_decode(self): jfile = opj_data_file('input/nonregression/cthead1.j2k') - Jp2k(jfile).read() + Jp2k(jfile)[:] self.assertTrue(True) def test_NR_DEC_CT_Phillips_JPEG2K_Decompr_Problem_j2k_13_decode(self): relpath = 'input/nonregression/CT_Phillips_JPEG2K_Decompr_Problem.j2k' jfile = opj_data_file(relpath) - Jp2k(jfile).read() + Jp2k(jfile)[:] self.assertTrue(True) def test_NR_DEC_j2k32_j2k_15_decode(self): jfile = opj_data_file('input/nonregression/j2k32.j2k') - Jp2k(jfile).read() + Jp2k(jfile)[:] self.assertTrue(True) def test_NR_DEC_MarkerIsNotCompliant_j2k_17_decode(self): jfile = opj_data_file('input/nonregression/MarkerIsNotCompliant.j2k') - Jp2k(jfile).read() + Jp2k(jfile)[:] self.assertTrue(True) def test_NR_DEC_Marrin_jp2_18_decode(self): jfile = opj_data_file('input/nonregression/Marrin.jp2') - Jp2k(jfile).read() + Jp2k(jfile)[:] self.assertTrue(True) def test_NR_DEC_movie_00000_j2k_20_decode(self): jfile = opj_data_file('input/nonregression/movie_00000.j2k') - Jp2k(jfile).read() + Jp2k(jfile)[:] self.assertTrue(True) def test_NR_DEC_movie_00001_j2k_21_decode(self): jfile = opj_data_file('input/nonregression/movie_00001.j2k') - Jp2k(jfile).read() + Jp2k(jfile)[:] self.assertTrue(True) def test_NR_DEC_movie_00002_j2k_22_decode(self): jfile = opj_data_file('input/nonregression/movie_00002.j2k') - Jp2k(jfile).read() + Jp2k(jfile)[:] self.assertTrue(True) def test_NR_DEC_orb_blue_lin_j2k_j2k_23_decode(self): jfile = opj_data_file('input/nonregression/orb-blue10-lin-j2k.j2k') - Jp2k(jfile).read() + Jp2k(jfile)[:] self.assertTrue(True) def test_NR_DEC_orb_blue_win_j2k_j2k_24_decode(self): jfile = opj_data_file('input/nonregression/orb-blue10-win-j2k.j2k') - Jp2k(jfile).read() + Jp2k(jfile)[:] self.assertTrue(True) def test_NR_DEC_relax_jp2_27_decode(self): jfile = opj_data_file('input/nonregression/relax.jp2') - Jp2k(jfile).read() + Jp2k(jfile)[:] self.assertTrue(True) def test_NR_DEC_test_lossless_j2k_28_decode(self): jfile = opj_data_file('input/nonregression/test_lossless.j2k') - Jp2k(jfile).read() + Jp2k(jfile)[:] self.assertTrue(True) def test_NR_DEC_pacs_ge_j2k_30_decode(self): jfile = opj_data_file('input/nonregression/pacs.ge.j2k') - Jp2k(jfile).read() + Jp2k(jfile)[:] self.assertTrue(True) @@ -317,14 +318,14 @@ class TestSuiteWarns(MetadataBase): with self.assertWarns(UserWarning): # Bad compatibility list item. jp2k = Jp2k(jfile) - jpdata = jp2k.read() + jpdata = jp2k[:] self.assertEqual(jpdata.shape, (512, 768, 3)) def test_ETS_JP2_file2(self): jfile = opj_data_file('input/conformance/file2.jp2') with self.assertWarns(UserWarning): jp2k = Jp2k(jfile) - jpdata = jp2k.read() + jpdata = jp2k[:] self.assertEqual(jpdata.shape, (640, 480, 3)) @unittest.skipIf(glymur.version.openjpeg_version_tuple[0] < 2, @@ -342,7 +343,7 @@ class TestSuiteWarns(MetadataBase): jfile = opj_data_file('input/conformance/file4.jp2') with self.assertWarns(UserWarning): jp2k = Jp2k(jfile) - jpdata = jp2k.read() + jpdata = jp2k[:] self.assertEqual(jpdata.shape, (512, 768)) def test_ETS_JP2_file5(self): @@ -351,35 +352,35 @@ class TestSuiteWarns(MetadataBase): # There's a warning for an unknown compatibility entry. # Ignore it here. jp2k = Jp2k(jfile) - jpdata = jp2k.read() + jpdata = jp2k[:] self.assertEqual(jpdata.shape, (512, 768, 3)) def test_ETS_JP2_file6(self): jfile = opj_data_file('input/conformance/file6.jp2') with self.assertWarns(UserWarning): jp2k = Jp2k(jfile) - jpdata = jp2k.read() + jpdata = jp2k[:] self.assertEqual(jpdata.shape, (512, 768)) def test_ETS_JP2_file7(self): jfile = opj_data_file('input/conformance/file7.jp2') with self.assertWarns(UserWarning): jp2k = Jp2k(jfile) - jpdata = jp2k.read() + jpdata = jp2k[:] self.assertEqual(jpdata.shape, (640, 480, 3)) def test_ETS_JP2_file8(self): jfile = opj_data_file('input/conformance/file8.jp2') with self.assertWarns(UserWarning): jp2k = Jp2k(jfile) - jpdata = jp2k.read() + jpdata = jp2k[:] self.assertEqual(jpdata.shape, (400, 700)) def test_ETS_JP2_file9(self): jfile = opj_data_file('input/conformance/file9.jp2') with self.assertWarns(UserWarning): jp2k = Jp2k(jfile) - jpdata = jp2k.read() + jpdata = jp2k[:] self.assertEqual(jpdata.shape, (512, 768, 3)) def test_NR_broken_jp2_dump(self): @@ -469,13 +470,13 @@ class TestSuiteWarns(MetadataBase): jfile = opj_data_file('input/nonregression/orb-blue10-lin-jp2.jp2') with self.assertWarns(UserWarning): # This file has an invalid ICC profile - Jp2k(jfile).read() + Jp2k(jfile)[:] self.assertTrue(True) def test_NR_DEC_orb_blue_win_jp2_26_decode(self): jfile = opj_data_file('input/nonregression/orb-blue10-win-jp2.jp2') with self.assertWarns(UserWarning): - Jp2k(jfile).read() + Jp2k(jfile)[:] self.assertTrue(True) @@ -590,7 +591,7 @@ class TestSuite2point0(unittest.TestCase): def test_ETS_C1P0_p0_10_j2k(self): jfile = opj_data_file('input/conformance/p0_10.j2k') jp2k = Jp2k(jfile) - jpdata = jp2k.read(rlevel=0) + jpdata = jp2k[:] pgxfile = opj_data_file('baseline/conformance/c1p0_10_0.pgx') pgxdata = read_pgx(pgxfile) @@ -611,7 +612,7 @@ class TestSuite2point0(unittest.TestCase): with self.assertRaises(IOError): with self.assertWarns(UserWarning): # Invalid marker ID. - Jp2k(jfile).read() + Jp2k(jfile)[:] self.assertTrue(True) @unittest.skipIf(WARNING_INFRASTRUCTURE_ISSUE, WARNING_INFRASTRUCTURE_MSG) @@ -620,7 +621,7 @@ class TestSuite2point0(unittest.TestCase): with self.assertRaises(IOError): with self.assertWarns(UserWarning): # invalid number of subbands, bad marker ID - Jp2k(jfile).read() + Jp2k(jfile)[:] self.assertTrue(True) @unittest.skipIf(WARNING_INFRASTRUCTURE_ISSUE, WARNING_INFRASTRUCTURE_MSG) @@ -632,11 +633,343 @@ class TestSuite2point0(unittest.TestCase): if glymur.version.openjpeg_version_tuple[0] < 2: with self.assertWarns(UserWarning): # Incorrect warning issued about tile parts. - Jp2k(jfile).read() + Jp2k(jfile)[:] else: - Jp2k(jfile).read() + Jp2k(jfile)[:] self.assertTrue(True) -if __name__ == "__main__": - unittest.main() +@unittest.skipIf(OPJ_DATA_ROOT is None, + "OPJ_DATA_ROOT environment variable not set") +@unittest.skipIf(re.match(r'''(1|2.0.0)''', + glymur.version.openjpeg_version) is not None, + "Only supported in 2.0.1 or higher") +class TestSuite2point1(unittest.TestCase): + """Runs tests introduced in version 2.0+ or that pass only in 2.0+""" + + def setUp(self): + pass + + def tearDown(self): + pass + + @unittest.skipIf(WARNING_INFRASTRUCTURE_ISSUE, WARNING_INFRASTRUCTURE_MSG) + def test_NR_DEC_text_GBR_jp2_29_decode(self): + jfile = opj_data_file('input/nonregression/text_GBR.jp2') + with self.assertWarns(UserWarning): + # brand is 'jp2 ', but has any icc profile. + jp2 = Jp2k(jfile) + jp2[:] + self.assertTrue(True) + + def test_NR_DEC_kodak_2layers_lrcp_j2c_31_decode(self): + jfile = opj_data_file('input/nonregression/kodak_2layers_lrcp.j2c') + Jp2k(jfile)[:] + self.assertTrue(True) + + def test_NR_DEC_kodak_2layers_lrcp_j2c_32_decode(self): + jfile = opj_data_file('input/nonregression/kodak_2layers_lrcp.j2c') + Jp2k(jfile)[::4, ::4] + self.assertTrue(True) + + def test_NR_DEC_issue104_jpxstream_jp2_33_decode(self): + jfile = opj_data_file('input/nonregression/issue104_jpxstream.jp2') + Jp2k(jfile)[:] + self.assertTrue(True) + + def test_NR_DEC_mem_b2b86b74_2753_jp2_35_decode(self): + jfile = opj_data_file('input/nonregression/mem-b2b86b74-2753.jp2') + Jp2k(jfile)[:] + self.assertTrue(True) + + @unittest.skipIf(WARNING_INFRASTRUCTURE_ISSUE, WARNING_INFRASTRUCTURE_MSG) + def test_NR_DEC_gdal_fuzzer_unchecked_num_resolutions_jp2_36_decode(self): + f = 'input/nonregression/gdal_fuzzer_unchecked_numresolutions.jp2' + jfile = opj_data_file(f) + with self.assertWarns(UserWarning): + # Invalid number of resolutions. + j = Jp2k(jfile) + with self.assertRaises(IOError): + j[:] + + @unittest.skipIf(WARNING_INFRASTRUCTURE_ISSUE, WARNING_INFRASTRUCTURE_MSG) + def test_NR_DEC_gdal_fuzzer_check_number_of_tiles_jp2_38_decode(self): + relpath = 'input/nonregression/gdal_fuzzer_check_number_of_tiles.jp2' + jfile = opj_data_file(relpath) + with self.assertWarns(UserWarning): + # Invalid number of tiles. + j = Jp2k(jfile) + with self.assertRaises(IOError): + j[:] + + @unittest.skipIf(WARNING_INFRASTRUCTURE_ISSUE, WARNING_INFRASTRUCTURE_MSG) + def test_NR_DEC_gdal_fuzzer_check_comp_dx_dy_jp2_39_decode(self): + relpath = 'input/nonregression/gdal_fuzzer_check_comp_dx_dy.jp2' + jfile = opj_data_file(relpath) + with self.assertWarns(UserWarning): + # Invalid subsampling value + with self.assertRaises(IOError): + Jp2k(jfile)[:] + + def test_NR_DEC_file_409752_jp2_40_decode(self): + jfile = opj_data_file('input/nonregression/file409752.jp2') + with self.assertRaises(RuntimeError): + Jp2k(jfile)[:] + + def test_NR_DEC_issue206_image_000_jp2_42_decode(self): + jfile = opj_data_file('input/nonregression/issue206_image-000.jp2') + Jp2k(jfile)[:] + self.assertTrue(True) + + def test_NR_DEC_p1_04_j2k_57_decode(self): + jfile = opj_data_file('input/conformance/p1_04.j2k') + jp2k = Jp2k(jfile) + tdata = jp2k[896:1024, 896:1024] # last tile + odata = jp2k[:] + np.testing.assert_array_equal(tdata, odata[896:1024, 896:1024]) + + @unittest.skipIf(WARNING_INFRASTRUCTURE_ISSUE, WARNING_INFRASTRUCTURE_MSG) + def test_NR_DEC_p1_04_j2k_57_decode_0p7_backwards_compatibility(self): + """ + 0.7.x usage deprecated + """ + jfile = opj_data_file('input/conformance/p1_04.j2k') + jp2k = Jp2k(jfile) + if sys.hexversion < 0x03000000: + with warnings.catch_warnings(): + # Suppress a warning due to deprecated syntax + warnings.simplefilter("ignore") + tdata = jp2k.read(tile=63) # last tile + else: + with self.assertWarns(DeprecationWarning): + tdata = jp2k.read(tile=63) # last tile + odata = jp2k[:] + np.testing.assert_array_equal(tdata, odata[896:1024, 896:1024]) + + @unittest.skipIf(WARNING_INFRASTRUCTURE_ISSUE, WARNING_INFRASTRUCTURE_MSG) + def test_NR_DEC_p1_04_j2k_58_decode_0p7_backwards_compatibility(self): + """ + 0.7.x usage deprecated + """ + jfile = opj_data_file('input/conformance/p1_04.j2k') + jp2k = Jp2k(jfile) + if sys.hexversion < 0x03000000: + with warnings.catch_warnings(): + # Suppress a warning due to deprecated syntax + tdata = jp2k.read(tile=63, rlevel=2) # last tile + else: + with self.assertWarns(DeprecationWarning): + tdata = jp2k.read(tile=63, rlevel=2) # last tile + odata = jp2k[::4, ::4] + np.testing.assert_array_equal(tdata, odata[224:256, 224:256]) + + def test_NR_DEC_p1_04_j2k_58_decode(self): + jfile = opj_data_file('input/conformance/p1_04.j2k') + jp2k = Jp2k(jfile) + tdata = jp2k[896:1024:4, 896:1024:4] # last tile + odata = jp2k[::4, ::4] + np.testing.assert_array_equal(tdata, odata[224:256, 224:256]) + + def test_NR_DEC_p1_04_j2k_59_decode(self): + jfile = opj_data_file('input/conformance/p1_04.j2k') + jp2k = Jp2k(jfile) + tdata = jp2k[128:256, 512:640] # 2nd row, 5th column + odata = jp2k[:] + np.testing.assert_array_equal(tdata, odata[128:256, 512:640]) + + def test_NR_DEC_p1_04_j2k_60_decode(self): + jfile = opj_data_file('input/conformance/p1_04.j2k') + jp2k = Jp2k(jfile) + tdata = jp2k[128:256:2, 512:640:2] # 2nd row, 5th column + odata = jp2k[::2, ::2] + np.testing.assert_array_equal(tdata, odata[64:128, 256:320]) + + @unittest.skipIf(WARNING_INFRASTRUCTURE_ISSUE, WARNING_INFRASTRUCTURE_MSG) + def test_NR_DEC_jp2_36_decode(self): + lst = ('input', + 'nonregression', + 'gdal_fuzzer_assert_in_opj_j2k_read_SQcd_SQcc.patch.jp2') + jfile = opj_data_file('/'.join(lst)) + with self.assertWarns(UserWarning): + # Invalid component number. + j = Jp2k(jfile) + with self.assertRaises(IOError): + j[:] + +@unittest.skipIf(OPJ_DATA_ROOT is None, + "OPJ_DATA_ROOT environment variable not set") +@unittest.skipIf(re.match(r'''(1|2.0.0)''', + glymur.version.openjpeg_version) is not None, + "Only supported in 2.0.1 or higher") +class TestReadArea(unittest.TestCase): + """ + Runs tests introduced in version 2.0+ or that pass only in 2.0+ + + Specifically for read method with area parameter. + """ + @classmethod + def setUpClass(self): + + jfile = opj_data_file('input/conformance/p1_04.j2k') + self.j2k = Jp2k(jfile) + self.j2k_data = self.j2k[:] + self.j2k_half_data = self.j2k[::2, ::2] + self.j2k_quarter_data = self.j2k[::4, ::4] + + jfile = opj_data_file('input/conformance/p1_06.j2k') + self.j2k_p1_06 = Jp2k(jfile) + + def test_NR_DEC_p1_04_j2k_43_decode(self): + actual = self.j2k[:1024, :1024] + expected = self.j2k_data + np.testing.assert_array_equal(actual, expected) + + def test_NR_DEC_p1_04_j2k_44_decode(self): + actual = self.j2k[640:768, 512:640] + expected = self.j2k_data[640:768, 512:640] + np.testing.assert_array_equal(actual, expected) + + def test_NR_DEC_p1_04_j2k_45_decode(self): + actual = self.j2k[896:1024, 896:1024] + expected = self.j2k_data[896:1024, 896:1024] + np.testing.assert_array_equal(actual, expected) + + def test_NR_DEC_p1_04_j2k_46_decode(self): + actual = self.j2k[500:800, 100:300] + expected = self.j2k_data[500:800, 100:300] + np.testing.assert_array_equal(actual, expected) + + def test_NR_DEC_p1_04_j2k_47_decode(self): + actual = self.j2k[520:600, 260:360] + expected = self.j2k_data[520:600, 260:360] + np.testing.assert_array_equal(actual, expected) + + def test_NR_DEC_p1_04_j2k_48_decode(self): + actual = self.j2k[520:660, 260:360] + expected = self.j2k_data[520:660, 260:360] + np.testing.assert_array_equal(actual, expected) + + def test_NR_DEC_p1_04_j2k_49_decode(self): + actual = self.j2k[520:600, 360:400] + expected = self.j2k_data[520:600, 360:400] + np.testing.assert_array_equal(actual, expected) + + def test_NR_DEC_p1_04_j2k_50_decode(self): + actual = self.j2k[:1024:4, :1024:4] + expected = self.j2k_quarter_data + np.testing.assert_array_equal(actual, expected) + + def test_NR_DEC_p1_04_j2k_51_decode(self): + actual = self.j2k[640:768:4, 512:640:4] + expected = self.j2k_quarter_data[160:192, 128:160] + np.testing.assert_array_equal(actual, expected) + + def test_NR_DEC_p1_04_j2k_52_decode(self): + actual = self.j2k[896:1024:4, 896:1024:4] + expected = self.j2k_quarter_data[224:352, 224:352] + np.testing.assert_array_equal(actual, expected) + + def test_NR_DEC_p1_04_j2k_53_decode(self): + actual = self.j2k[500:800:4, 100:300:4] + expected = self.j2k_quarter_data[125:200, 25:75] + np.testing.assert_array_equal(actual, expected) + + def test_NR_DEC_p1_04_j2k_54_decode(self): + actual = self.j2k[520:600:4, 260:360:4] + expected = self.j2k_quarter_data[130:150, 65:90] + np.testing.assert_array_equal(actual, expected) + + def test_NR_DEC_p1_04_j2k_55_decode(self): + actual = self.j2k[520:660:4, 260:360:4] + expected = self.j2k_quarter_data[130:165, 65:90] + np.testing.assert_array_equal(actual, expected) + + def test_NR_DEC_p1_04_j2k_56_decode(self): + actual = self.j2k[520:600:4, 360:400:4] + expected = self.j2k_quarter_data[130:150, 90:100] + np.testing.assert_array_equal(actual, expected) + + def test_NR_DEC_p1_06_j2k_70_decode(self): + actual = self.j2k_p1_06[9:12:2, 9:12:2] + self.assertEqual(actual.shape, (1, 1, 3)) + + def test_NR_DEC_p1_06_j2k_71_decode(self): + actual = self.j2k_p1_06[10:12:2, 4:10:2] + self.assertEqual(actual.shape, (1, 3, 3)) + + def test_NR_DEC_p1_06_j2k_72_decode(self): + ssdata = self.j2k_p1_06[3:9:2, 3:9:2] + self.assertEqual(ssdata.shape, (3, 3, 3)) + + def test_NR_DEC_p1_06_j2k_73_decode(self): + ssdata = self.j2k_p1_06[4:7:2, 4:7:2] + self.assertEqual(ssdata.shape, (2, 2, 3)) + + def test_NR_DEC_p1_06_j2k_74_decode(self): + ssdata = self.j2k_p1_06[4:5:2, 4:5:2] + self.assertEqual(ssdata.shape, (1, 1, 3)) + + def test_NR_DEC_p1_06_j2k_75_decode(self): + # Image size would be 0 x 0. + with self.assertRaises((IOError, OSError)): + self.j2k_p1_06[9:12:4, 9:12:4] + + def test_NR_DEC_p0_04_j2k_85_decode(self): + actual = self.j2k[:256, :256] + expected = self.j2k_data[:256, :256] + np.testing.assert_array_equal(actual, expected) + + def test_NR_DEC_p0_04_j2k_86_decode(self): + actual = self.j2k[:128, 128:256] + expected = self.j2k_data[:128, 128:256] + np.testing.assert_array_equal(actual, expected) + + def test_NR_DEC_p0_04_j2k_87_decode(self): + actual = self.j2k[10:200, 50:120] + expected = self.j2k_data[10:200, 50:120] + np.testing.assert_array_equal(actual, expected) + + def test_NR_DEC_p0_04_j2k_88_decode(self): + actual = self.j2k[150:210, 10:190] + expected = self.j2k_data[150:210, 10:190] + np.testing.assert_array_equal(actual, expected) + + def test_NR_DEC_p0_04_j2k_89_decode(self): + actual = self.j2k[80:150, 100:200] + expected = self.j2k_data[80:150, 100:200] + np.testing.assert_array_equal(actual, expected) + + def test_NR_DEC_p0_04_j2k_90_decode(self): + actual = self.j2k[20:50, 150:200] + expected = self.j2k_data[20:50, 150:200] + np.testing.assert_array_equal(actual, expected) + + def test_NR_DEC_p0_04_j2k_91_decode(self): + actual = self.j2k[:256:4, :256:4] + expected = self.j2k_quarter_data[0:64, 0:64] + np.testing.assert_array_equal(actual, expected) + + def test_NR_DEC_p0_04_j2k_92_decode(self): + actual = self.j2k[:128:4, 128:256:4] + expected = self.j2k_quarter_data[:32, 32:64] + np.testing.assert_array_equal(actual, expected) + + def test_NR_DEC_p0_04_j2k_93_decode(self): + actual = self.j2k[10:200:4, 50:120:4] + expected = self.j2k_quarter_data[3:50, 13:30] + np.testing.assert_array_equal(actual, expected) + + def test_NR_DEC_p0_04_j2k_94_decode(self): + actual = self.j2k[150:210:4, 10:190:4] + expected = self.j2k_quarter_data[38:53, 3:48] + np.testing.assert_array_equal(actual, expected) + + def test_NR_DEC_p0_04_j2k_95_decode(self): + actual = self.j2k[80:150:4, 100:200:4] + expected = self.j2k_quarter_data[20:38, 25:50] + np.testing.assert_array_equal(actual, expected) + + def test_NR_DEC_p0_04_j2k_96_decode(self): + actual = self.j2k[20:50:4, 150:200:4] + expected = self.j2k_quarter_data[5:13, 38:50] + np.testing.assert_array_equal(actual, expected) diff --git a/glymur/test/test_opj_suite_2p1.py b/glymur/test/test_opj_suite_2p1.py deleted file mode 100644 index addc48b..0000000 --- a/glymur/test/test_opj_suite_2p1.py +++ /dev/null @@ -1,342 +0,0 @@ -""" -The tests defined here roughly correspond to what is in the OpenJPEG test -suite. -""" - -# Some test names correspond with openjpeg tests. Long names are ok in this -# case. -# pylint: disable=C0103 - -# All of these tests correspond to tests in openjpeg, so no docstring is really -# needed. -# pylint: disable=C0111 - -# This module is very long, cannot be helped. -# pylint: disable=C0302 - -# unittest fools pylint with "too many public methods" -# pylint: disable=R0904 - -# Some tests use numpy test infrastructure, which means the tests never -# reference "self", so pylint claims it should be a function. No, no, no. -# pylint: disable=R0201 - -# Many tests are pretty long and that can't be helped. -# pylint: disable=R0915 - -# asserWarns introduced in python 3.2 (python2.7/pylint issue) -# pylint: disable=E1101 - -import re -import sys -import unittest - -import numpy as np - -from glymur import Jp2k -import glymur - -from .fixtures import OPJ_DATA_ROOT -from .fixtures import WARNING_INFRASTRUCTURE_ISSUE, WARNING_INFRASTRUCTURE_MSG -from .fixtures import mse, peak_tolerance, read_pgx, opj_data_file - - -@unittest.skipIf(OPJ_DATA_ROOT is None, - "OPJ_DATA_ROOT environment variable not set") -@unittest.skipIf(re.match(r'''(1|2.0.0)''', - glymur.version.openjpeg_version) is not None, - "Only supported in 2.0.1 or higher") -class TestSuite2point1(unittest.TestCase): - """Runs tests introduced in version 2.0+ or that pass only in 2.0+""" - - def setUp(self): - pass - - def tearDown(self): - pass - - @unittest.skipIf(WARNING_INFRASTRUCTURE_ISSUE, WARNING_INFRASTRUCTURE_MSG) - def test_NR_DEC_text_GBR_jp2_29_decode(self): - jfile = opj_data_file('input/nonregression/text_GBR.jp2') - with self.assertWarns(UserWarning): - # brand is 'jp2 ', but has any icc profile. - jp2 = Jp2k(jfile) - jp2.read() - self.assertTrue(True) - - def test_NR_DEC_kodak_2layers_lrcp_j2c_31_decode(self): - jfile = opj_data_file('input/nonregression/kodak_2layers_lrcp.j2c') - Jp2k(jfile).read() - self.assertTrue(True) - - def test_NR_DEC_kodak_2layers_lrcp_j2c_32_decode(self): - jfile = opj_data_file('input/nonregression/kodak_2layers_lrcp.j2c') - Jp2k(jfile).read(layer=2) - self.assertTrue(True) - - def test_NR_DEC_issue104_jpxstream_jp2_33_decode(self): - jfile = opj_data_file('input/nonregression/issue104_jpxstream.jp2') - Jp2k(jfile).read() - self.assertTrue(True) - - def test_NR_DEC_mem_b2b86b74_2753_jp2_35_decode(self): - jfile = opj_data_file('input/nonregression/mem-b2b86b74-2753.jp2') - Jp2k(jfile).read() - self.assertTrue(True) - - @unittest.skipIf(WARNING_INFRASTRUCTURE_ISSUE, WARNING_INFRASTRUCTURE_MSG) - def test_NR_DEC_gdal_fuzzer_unchecked_num_resolutions_jp2_36_decode(self): - f = 'input/nonregression/gdal_fuzzer_unchecked_numresolutions.jp2' - jfile = opj_data_file(f) - with self.assertWarns(UserWarning): - # Invalid number of resolutions. - j = Jp2k(jfile) - with self.assertRaises(IOError): - j.read() - - @unittest.skipIf(WARNING_INFRASTRUCTURE_ISSUE, WARNING_INFRASTRUCTURE_MSG) - def test_NR_DEC_gdal_fuzzer_check_number_of_tiles_jp2_38_decode(self): - relpath = 'input/nonregression/gdal_fuzzer_check_number_of_tiles.jp2' - jfile = opj_data_file(relpath) - with self.assertWarns(UserWarning): - # Invalid number of tiles. - j = Jp2k(jfile) - with self.assertRaises(IOError): - j.read() - - @unittest.skipIf(WARNING_INFRASTRUCTURE_ISSUE, WARNING_INFRASTRUCTURE_MSG) - def test_NR_DEC_gdal_fuzzer_check_comp_dx_dy_jp2_39_decode(self): - relpath = 'input/nonregression/gdal_fuzzer_check_comp_dx_dy.jp2' - jfile = opj_data_file(relpath) - with self.assertWarns(UserWarning): - # Invalid subsampling value - with self.assertRaises(IOError): - Jp2k(jfile).read() - - def test_NR_DEC_file_409752_jp2_40_decode(self): - jfile = opj_data_file('input/nonregression/file409752.jp2') - with self.assertRaises(RuntimeError): - Jp2k(jfile).read() - - def test_NR_DEC_issue206_image_000_jp2_42_decode(self): - jfile = opj_data_file('input/nonregression/issue206_image-000.jp2') - Jp2k(jfile).read() - self.assertTrue(True) - - def test_NR_DEC_p1_04_j2k_57_decode(self): - jfile = opj_data_file('input/conformance/p1_04.j2k') - jp2k = Jp2k(jfile) - tdata = jp2k.read(tile=63) # last tile - odata = jp2k.read() - np.testing.assert_array_equal(tdata, odata[896:1024, 896:1024]) - - def test_NR_DEC_p1_04_j2k_58_decode(self): - jfile = opj_data_file('input/conformance/p1_04.j2k') - jp2k = Jp2k(jfile) - tdata = jp2k.read(tile=63, rlevel=2) # last tile - odata = jp2k.read(rlevel=2) - np.testing.assert_array_equal(tdata, odata[224:256, 224:256]) - - def test_NR_DEC_p1_04_j2k_59_decode(self): - jfile = opj_data_file('input/conformance/p1_04.j2k') - jp2k = Jp2k(jfile) - tdata = jp2k.read(tile=12) # 2nd row, 5th column - odata = jp2k.read() - np.testing.assert_array_equal(tdata, odata[128:256, 512:640]) - - def test_NR_DEC_p1_04_j2k_60_decode(self): - jfile = opj_data_file('input/conformance/p1_04.j2k') - jp2k = Jp2k(jfile) - tdata = jp2k.read(tile=12, rlevel=1) # 2nd row, 5th column - odata = jp2k.read(rlevel=1) - np.testing.assert_array_equal(tdata, odata[64:128, 256:320]) - - @unittest.skipIf(WARNING_INFRASTRUCTURE_ISSUE, WARNING_INFRASTRUCTURE_MSG) - def test_NR_DEC_jp2_36_decode(self): - lst = ('input', - 'nonregression', - 'gdal_fuzzer_assert_in_opj_j2k_read_SQcd_SQcc.patch.jp2') - jfile = opj_data_file('/'.join(lst)) - with self.assertWarns(UserWarning): - # Invalid component number. - j = Jp2k(jfile) - with self.assertRaises(IOError): - j.read() - -@unittest.skipIf(OPJ_DATA_ROOT is None, - "OPJ_DATA_ROOT environment variable not set") -@unittest.skipIf(re.match(r'''(1|2.0.0)''', - glymur.version.openjpeg_version) is not None, - "Only supported in 2.0.1 or higher") -class TestReadArea(unittest.TestCase): - """ - Runs tests introduced in version 2.0+ or that pass only in 2.0+ - - Specifically for read method with area parameter. - """ - @classmethod - def setUpClass(self): - - jfile = opj_data_file('input/conformance/p1_04.j2k') - self.j2k = Jp2k(jfile) - self.j2k_data = self.j2k.read() - self.j2k_half_data = self.j2k.read(rlevel=1) - self.j2k_quarter_data = self.j2k.read(rlevel=2) - - jfile = opj_data_file('input/conformance/p1_06.j2k') - self.j2k_p1_06 = Jp2k(jfile) - - def test_NR_DEC_p1_04_j2k_43_decode(self): - actual = self.j2k.read(area=(0, 0, 1024, 1024)) - expected = self.j2k_data - np.testing.assert_array_equal(actual, expected) - - def test_NR_DEC_p1_04_j2k_44_decode(self): - actual = self.j2k.read(area=(640, 512, 768, 640)) - expected = self.j2k_data[640:768, 512:640] - np.testing.assert_array_equal(actual, expected) - - def test_NR_DEC_p1_04_j2k_45_decode(self): - actual = self.j2k.read(area=(896, 896, 1024, 1024)) - expected = self.j2k_data[896:1024, 896:1024] - np.testing.assert_array_equal(actual, expected) - - def test_NR_DEC_p1_04_j2k_46_decode(self): - actual = self.j2k.read(area=(500, 100, 800, 300)) - expected = self.j2k_data[500:800, 100:300] - np.testing.assert_array_equal(actual, expected) - - def test_NR_DEC_p1_04_j2k_47_decode(self): - actual = self.j2k.read(area=(520, 260, 600, 360)) - expected = self.j2k_data[520:600, 260:360] - np.testing.assert_array_equal(actual, expected) - - def test_NR_DEC_p1_04_j2k_48_decode(self): - actual = self.j2k.read(area=(520, 260, 660, 360)) - expected = self.j2k_data[520:660, 260:360] - np.testing.assert_array_equal(actual, expected) - - def test_NR_DEC_p1_04_j2k_49_decode(self): - actual = self.j2k.read(area=(520, 360, 600, 400)) - expected = self.j2k_data[520:600, 360:400] - np.testing.assert_array_equal(actual, expected) - - def test_NR_DEC_p1_04_j2k_50_decode(self): - actual = self.j2k.read(area=(0, 0, 1024, 1024), rlevel=2) - expected = self.j2k_quarter_data - np.testing.assert_array_equal(actual, expected) - - def test_NR_DEC_p1_04_j2k_51_decode(self): - actual = self.j2k.read(area=(640, 512, 768, 640), rlevel=2) - expected = self.j2k_quarter_data[160:192, 128:160] - np.testing.assert_array_equal(actual, expected) - - def test_NR_DEC_p1_04_j2k_52_decode(self): - actual = self.j2k.read(area=(896, 896, 1024, 1024), rlevel=2) - expected = self.j2k_quarter_data[224:352, 224:352] - np.testing.assert_array_equal(actual, expected) - - def test_NR_DEC_p1_04_j2k_53_decode(self): - actual = self.j2k.read(area=(500, 100, 800, 300), rlevel=2) - expected = self.j2k_quarter_data[125:200, 25:75] - np.testing.assert_array_equal(actual, expected) - - def test_NR_DEC_p1_04_j2k_54_decode(self): - actual = self.j2k.read(area=(520, 260, 600, 360), rlevel=2) - expected = self.j2k_quarter_data[130:150, 65:90] - np.testing.assert_array_equal(actual, expected) - - def test_NR_DEC_p1_04_j2k_55_decode(self): - actual = self.j2k.read(area=(520, 260, 660, 360), rlevel=2) - expected = self.j2k_quarter_data[130:165, 65:90] - np.testing.assert_array_equal(actual, expected) - - def test_NR_DEC_p1_04_j2k_56_decode(self): - actual = self.j2k.read(area=(520, 360, 600, 400), rlevel=2) - expected = self.j2k_quarter_data[130:150, 90:100] - np.testing.assert_array_equal(actual, expected) - - def test_NR_DEC_p1_06_j2k_70_decode(self): - actual = self.j2k_p1_06.read(area=(9, 9, 12, 12), rlevel=1) - self.assertEqual(actual.shape, (1, 1, 3)) - - def test_NR_DEC_p1_06_j2k_71_decode(self): - actual = self.j2k_p1_06.read(area=(10, 4, 12, 10), rlevel=1) - self.assertEqual(actual.shape, (1, 3, 3)) - - def test_NR_DEC_p1_06_j2k_72_decode(self): - ssdata = self.j2k_p1_06.read(area=(3, 3, 9, 9), rlevel=1) - self.assertEqual(ssdata.shape, (3, 3, 3)) - - def test_NR_DEC_p1_06_j2k_73_decode(self): - ssdata = self.j2k_p1_06.read(area=(4, 4, 7, 7), rlevel=1) - self.assertEqual(ssdata.shape, (2, 2, 3)) - - def test_NR_DEC_p1_06_j2k_74_decode(self): - ssdata = self.j2k_p1_06.read(area=(4, 4, 5, 5), rlevel=1) - self.assertEqual(ssdata.shape, (1, 1, 3)) - - def test_NR_DEC_p1_06_j2k_75_decode(self): - # Image size would be 0 x 0. - with self.assertRaises((IOError, OSError)): - self.j2k_p1_06.read(area=(9, 9, 12, 12), rlevel=2) - - def test_NR_DEC_p0_04_j2k_85_decode(self): - actual = self.j2k.read(area=(0, 0, 256, 256)) - expected = self.j2k_data[:256, :256] - np.testing.assert_array_equal(actual, expected) - - def test_NR_DEC_p0_04_j2k_86_decode(self): - actual = self.j2k.read(area=(0, 128, 128, 256)) - expected = self.j2k_data[:128, 128:256] - np.testing.assert_array_equal(actual, expected) - - def test_NR_DEC_p0_04_j2k_87_decode(self): - actual = self.j2k.read(area=(10, 50, 200, 120)) - expected = self.j2k_data[10:200, 50:120] - np.testing.assert_array_equal(actual, expected) - - def test_NR_DEC_p0_04_j2k_88_decode(self): - actual = self.j2k.read(area=(150, 10, 210, 190)) - expected = self.j2k_data[150:210, 10:190] - np.testing.assert_array_equal(actual, expected) - - def test_NR_DEC_p0_04_j2k_89_decode(self): - actual = self.j2k.read(area=(80, 100, 150, 200)) - expected = self.j2k_data[80:150, 100:200] - np.testing.assert_array_equal(actual, expected) - - def test_NR_DEC_p0_04_j2k_90_decode(self): - actual = self.j2k.read(area=(20, 150, 50, 200)) - expected = self.j2k_data[20:50, 150:200] - np.testing.assert_array_equal(actual, expected) - - def test_NR_DEC_p0_04_j2k_91_decode(self): - actual = self.j2k.read(area=(0, 0, 256, 256), rlevel=2) - expected = self.j2k_quarter_data[0:64, 0:64] - np.testing.assert_array_equal(actual, expected) - - def test_NR_DEC_p0_04_j2k_92_decode(self): - actual = self.j2k.read(area=(0, 128, 128, 256), rlevel=2) - expected = self.j2k_quarter_data[:32, 32:64] - np.testing.assert_array_equal(actual, expected) - - def test_NR_DEC_p0_04_j2k_93_decode(self): - actual = self.j2k.read(area=(10, 50, 200, 120), rlevel=2) - expected = self.j2k_quarter_data[3:50, 13:30] - np.testing.assert_array_equal(actual, expected) - - def test_NR_DEC_p0_04_j2k_94_decode(self): - actual = self.j2k.read(area=(150, 10, 210, 190), rlevel=2) - expected = self.j2k_quarter_data[38:53, 3:48] - np.testing.assert_array_equal(actual, expected) - - def test_NR_DEC_p0_04_j2k_95_decode(self): - actual = self.j2k.read(area=(80, 100, 150, 200), rlevel=2) - expected = self.j2k_quarter_data[20:38, 25:50] - np.testing.assert_array_equal(actual, expected) - - def test_NR_DEC_p0_04_j2k_96_decode(self): - actual = self.j2k.read(area=(20, 150, 50, 200), rlevel=2) - expected = self.j2k_quarter_data[5:13, 38:50] - np.testing.assert_array_equal(actual, expected) diff --git a/glymur/test/test_opj_suite_dump.py b/glymur/test/test_opj_suite_dump.py index 8201c9f..ee1838b 100644 --- a/glymur/test/test_opj_suite_dump.py +++ b/glymur/test/test_opj_suite_dump.py @@ -2847,8 +2847,7 @@ class TestSuiteWarns(MetadataBase): relpath = 'input/nonregression/issue188_beach_64bitsbox.jp2' jfile = opj_data_file(relpath) with self.assertWarns(UserWarning): - j = Jp2k(jfile) - d = j.read() + d = Jp2k(jfile)[:] self.assertTrue(True) def test_NR_broken4_jp2_dump(self): diff --git a/glymur/test/test_opj_suite_neg.py b/glymur/test/test_opj_suite_neg.py index 058be42..c7e31e5 100644 --- a/glymur/test/test_opj_suite_neg.py +++ b/glymur/test/test_opj_suite_neg.py @@ -24,6 +24,7 @@ from .fixtures import OPJ_DATA_ROOT, opj_data_file, read_image from .fixtures import NO_READ_BACKEND, NO_READ_BACKEND_MSG from .fixtures import NO_SKIMAGE_FREEIMAGE_SUPPORT from .fixtures import WARNING_INFRASTRUCTURE_ISSUE, WARNING_INFRASTRUCTURE_MSG +from . import fixtures from glymur import Jp2k import glymur @@ -31,7 +32,7 @@ import glymur @unittest.skipIf(OPJ_DATA_ROOT is None, "OPJ_OPJ_DATA_ROOT environment variable not set") -class TestSuiteNegative(unittest.TestCase): +class TestSuiteNegativeRead(unittest.TestCase): """Test suite for certain negative tests from openjpeg suite.""" def setUp(self): @@ -41,33 +42,6 @@ class TestSuiteNegative(unittest.TestCase): def tearDown(self): pass - - @unittest.skipIf(NO_SKIMAGE_FREEIMAGE_SUPPORT, - "Cannot read input image without scikit-image/freeimage") - @unittest.skipIf(os.name == "nt", "Temporary file issue on window.") - def test_cinema2K_bad_frame_rate(self): - """Cinema2k frame rate must be either 24 or 48.""" - relfile = 'input/nonregression/X_5_2K_24_235_CBR_STEM24_000.tif' - infile = opj_data_file(relfile) - data = skimage.io.imread(infile) - with tempfile.NamedTemporaryFile(suffix='.j2k') as tfile: - j = Jp2k(tfile.name, 'wb') - with self.assertRaises(IOError): - j.write(data, cinema2k=36) - - - @unittest.skipIf(NO_READ_BACKEND, NO_READ_BACKEND_MSG) - @unittest.skipIf(os.name == "nt", "Temporary file issue on window.") - def test_psnr_with_cratios(self): - """Using psnr with cratios options is not allowed.""" - # Not an OpenJPEG test, but close. - infile = opj_data_file('input/nonregression/Bretagne1.ppm') - data = read_image(infile) - with tempfile.NamedTemporaryFile(suffix='.j2k') as tfile: - j = Jp2k(tfile.name, 'wb') - with self.assertRaises(IOError): - j.write(data, psnr=[30, 35, 40], cratios=[2, 3, 4]) - def test_nr_marker_not_compliant(self): """non-compliant marker, should still be able to read""" relpath = 'input/nonregression/MarkerIsNotCompliant.j2k' @@ -98,56 +72,84 @@ class TestSuiteNegative(unittest.TestCase): jp2k.get_codestream(header_only=False) self.assertTrue(True) - @unittest.skipIf(os.name == "nt", "Temporary file issue on window.") + +@unittest.skipIf(re.match("1.5|2", glymur.version.openjpeg_version) is None, + "Must have openjpeg 1.5 or higher to run") +@unittest.skipIf(os.name == "nt", fixtures.WINDOWS_TMP_FILE_MSG) +@unittest.skipIf(OPJ_DATA_ROOT is None, + "OPJ_OPJ_DATA_ROOT environment variable not set") +class TestSuiteNegativeWrite(unittest.TestCase): + """Test suite for certain negative tests from openjpeg suite.""" + + def setUp(self): + self.jp2file = glymur.data.nemo() + self.j2kfile = glymur.data.goodstuff() + + def tearDown(self): + pass + + + @unittest.skipIf(NO_SKIMAGE_FREEIMAGE_SUPPORT, + "Cannot read input image without scikit-image/freeimage") + def test_cinema2K_bad_frame_rate(self): + """Cinema2k frame rate must be either 24 or 48.""" + relfile = 'input/nonregression/X_5_2K_24_235_CBR_STEM24_000.tif' + infile = opj_data_file(relfile) + data = skimage.io.imread(infile) + with tempfile.NamedTemporaryFile(suffix='.j2k') as tfile: + with self.assertRaises(IOError): + j = Jp2k(tfile.name, data=data, cinema2k=36) + + + @unittest.skipIf(NO_READ_BACKEND, NO_READ_BACKEND_MSG) + def test_psnr_with_cratios(self): + """Using psnr with cratios options is not allowed.""" + # Not an OpenJPEG test, but close. + infile = opj_data_file('input/nonregression/Bretagne1.ppm') + data = read_image(infile) + with tempfile.NamedTemporaryFile(suffix='.j2k') as tfile: + with self.assertRaises(IOError): + 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""" # opj_compress doesn't allow the dimensions of a codeblock # to be too small or too big, so neither will we. data = np.zeros((256, 256), dtype=np.uint8) with tempfile.NamedTemporaryFile(suffix='.j2k') as tfile: - j = Jp2k(tfile.name, 'wb') - # opj_compress doesn't allow code block area to exceed 4096. with self.assertRaises(IOError): - j.write(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): - j.write(data, cbsize=(2048, 2)) + j = Jp2k(tfile.name, data=data, cbsize=(2048, 2)) with self.assertRaises(IOError): - j.write(data, cbsize=(2, 2048)) + j = Jp2k(tfile.name, data=data, cbsize=(2, 2048)) - @unittest.skipIf(os.name == "nt", "Temporary file issue on window.") def test_precinct_size_not_p2(self): """precinct sizes should be powers of two.""" ifile = Jp2k(self.j2kfile) - data = ifile.read(rlevel=2) + data = ifile[::4, ::4] with tempfile.NamedTemporaryFile(suffix='.jp2') as tfile: - ofile = Jp2k(tfile.name, 'wb') with self.assertRaises(IOError): - ofile.write(data, psizes=[(13, 13)]) + ofile = Jp2k(tfile.name, data=data, psizes=[(13, 13)]) - @unittest.skipIf(os.name == "nt", "Temporary file issue on window.") def test_cblk_size_not_power_of_two(self): """code block sizes should be powers of two.""" ifile = Jp2k(self.j2kfile) - data = ifile.read(rlevel=2) + data = ifile[::4, ::4] with tempfile.NamedTemporaryFile(suffix='.jp2') as tfile: - ofile = Jp2k(tfile.name, 'wb') with self.assertRaises(IOError): - ofile.write(data, cbsize=(13, 12)) + ofile = Jp2k(tfile.name, data=data, cbsize=(13, 12)) - @unittest.skipIf(os.name == "nt", "Temporary file issue on window.") def test_cblk_size_precinct_size(self): """code block sizes should never exceed half that of precinct size.""" ifile = Jp2k(self.j2kfile) - data = ifile.read(rlevel=2) + data = ifile[::4, ::4] with tempfile.NamedTemporaryFile(suffix='.jp2') as tfile: - ofile = Jp2k(tfile.name, 'wb') with self.assertRaises(IOError): - ofile.write(data, - cbsize=(64, 64), - psizes=[(64, 64)]) + ofile = Jp2k(tfile.name, + data=data, cbsize=(64, 64), psizes=[(64, 64)]) -if __name__ == "__main__": - unittest.main() diff --git a/glymur/test/test_opj_suite_write.py b/glymur/test/test_opj_suite_write.py index 8be1cef..ecb7a7d 100644 --- a/glymur/test/test_opj_suite_write.py +++ b/glymur/test/test_opj_suite_write.py @@ -87,9 +87,9 @@ class WriteCinema(CinemaBase): infile = opj_data_file(relfile) data = skimage.io.imread(infile) with tempfile.NamedTemporaryFile(suffix='.j2k') as tfile: - j = Jp2k(tfile.name, 'wb') with self.assertRaises(IOError): - j.write(data, cinema2k=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.""" @@ -97,9 +97,9 @@ class WriteCinema(CinemaBase): infile = opj_data_file(relfile) data = skimage.io.imread(infile) with tempfile.NamedTemporaryFile(suffix='.j2k') as tfile: - j = Jp2k(tfile.name, 'wb') with self.assertRaises(IOError): - j.write(data, 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) @@ -123,10 +123,9 @@ class WriteCinemaWarns(CinemaBase): infile = opj_data_file(relfile) data = skimage.io.imread(infile) with tempfile.NamedTemporaryFile(suffix='.j2k') as tfile: - j = Jp2k(tfile.name, 'wb') regex = 'OpenJPEG library warning:.*' with self.assertWarnsRegex(UserWarning, re.compile(regex)): - j.write(data, cinema4k=True) + j = Jp2k(tfile.name, data=data, cinema4k=True) codestream = j.get_codestream() self.check_cinema4k_codestream(codestream, (4096, 2160)) @@ -136,9 +135,8 @@ class WriteCinemaWarns(CinemaBase): infile = opj_data_file(relfile) data = skimage.io.imread(infile) with tempfile.NamedTemporaryFile(suffix='.j2k') as tfile: - j = Jp2k(tfile.name, 'wb') with self.assertWarnsRegex(UserWarning, 'OpenJPEG library warning'): - j.write(data, cinema2k=48) + j = Jp2k(tfile.name, data=data, cinema2k=48) codestream = j.get_codestream() self.check_cinema2k_codestream(codestream, (2048, 857)) @@ -148,9 +146,8 @@ class WriteCinemaWarns(CinemaBase): infile = opj_data_file(relfile) data = skimage.io.imread(infile) with tempfile.NamedTemporaryFile(suffix='.j2k') as tfile: - j = Jp2k(tfile.name, 'wb') with self.assertWarnsRegex(UserWarning, 'OpenJPEG library warning'): - j.write(data, cinema2k=48) + j = Jp2k(tfile.name, data=data, cinema2k=48) codestream = j.get_codestream() self.check_cinema2k_codestream(codestream, (2048, 1080)) @@ -160,9 +157,8 @@ class WriteCinemaWarns(CinemaBase): infile = opj_data_file(relfile) data = skimage.io.imread(infile) with tempfile.NamedTemporaryFile(suffix='.j2k') as tfile: - j = Jp2k(tfile.name, 'wb') with self.assertWarnsRegex(UserWarning, 'OpenJPEG library warning'): - j.write(data, cinema2k=24) + j = Jp2k(tfile.name, data=data, cinema2k=24) codestream = j.get_codestream() self.check_cinema2k_codestream(codestream, (2048, 1080)) @@ -172,11 +168,10 @@ class WriteCinemaWarns(CinemaBase): infile = opj_data_file(relfile) data = skimage.io.imread(infile) with tempfile.NamedTemporaryFile(suffix='.j2k') as tfile: - j = Jp2k(tfile.name, 'wb') 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.write(data, cinema2k=24) + j = Jp2k(tfile.name, data=data, cinema2k=24) codestream = j.get_codestream() self.check_cinema2k_codestream(codestream, (2048, 857)) @@ -186,12 +181,11 @@ class WriteCinemaWarns(CinemaBase): infile = opj_data_file(relfile) data = skimage.io.imread(infile) with tempfile.NamedTemporaryFile(suffix='.j2k') as tfile: - j = Jp2k(tfile.name, 'wb') regex = 'OpenJPEG library warning' with self.assertWarnsRegex(UserWarning, regex): # OpenJPEG library warning: The desired maximum codestream # size has limited at least one of the desired quality layers - j.write(data, cinema2k=48) + j = Jp2k(tfile.name, data=data, cinema2k=48) codestream = j.get_codestream() self.check_cinema2k_codestream(codestream, (1998, 1080)) @@ -221,9 +215,8 @@ class TestNegative2pointzero(unittest.TestCase): for version in versions: with patch('glymur.version.openjpeg_version', new=version): with tempfile.NamedTemporaryFile(suffix='.j2k') as tfile: - j = Jp2k(tfile.name, 'wb') with self.assertRaises(IOError): - j.write(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,8 +242,7 @@ class TestSuiteWrite(fixtures.MetadataBase): expdata = np.fromfile(filename, dtype=np.uint16) expdata.resize((2816, 2048)) with tempfile.NamedTemporaryFile(suffix='.j2k') as tfile: - j = Jp2k(tfile.name, 'wb') - j.write(expdata, irreversible=True) + j = Jp2k(tfile.name, data=expdata, irreversible=True) codestream = j.get_codestream() self.assertEqual(codestream.segment[2].spcod[8], @@ -262,8 +254,7 @@ 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, 'wb') - j.write(data, cratios=[200, 100, 50]) + j = Jp2k(tfile.name, data=data, cratios=[200, 100, 50]) # Should be three layers. c = j.get_codestream() @@ -294,8 +285,7 @@ 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, 'wb') - j.write(data, psnr=[30, 35, 40], numres=2) + j = Jp2k(tfile.name, data=data, psnr=[30, 35, 40], numres=2) # Should be three layers. codestream = j.get_codestream() @@ -326,9 +316,9 @@ 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, 'wb') - j.write(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() @@ -361,8 +351,8 @@ 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, 'wb') - j.write(data, + j = Jp2k(tfile.name, + data=data, psizes=[(128, 128)] * 3, cratios=[100, 20, 2], tilesize=(480, 640), @@ -398,8 +388,7 @@ 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, 'wb') - j.write(data, tilesize=(127, 127), prog="PCRL") + j = Jp2k(tfile.name, data=data, tilesize=(127, 127), prog="PCRL") codestream = j.get_codestream() @@ -429,8 +418,7 @@ 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, 'wb') - j.write(data, subsam=(2, 2), sop=True) + j = Jp2k(tfile.name, data=data, subsam=(2, 2), sop=True) codestream = j.get_codestream(header_only=False) @@ -465,8 +453,7 @@ 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, 'wb') - j.write(data, modesw=38, eph=True) + j = Jp2k(tfile.name, data=data, modesw=38, eph=True) codestream = j.get_codestream(header_only=False) @@ -500,8 +487,8 @@ 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, 'wb') - j.write(data, grid_offset=[300, 150], cratios=[800]) + j = Jp2k(tfile.name, + data=data, grid_offset=[300, 150], cratios=[800]) codestream = j.get_codestream(header_only=False) @@ -531,8 +518,7 @@ class TestSuiteWrite(fixtures.MetadataBase): infile = opj_data_file('input/nonregression/Cevennes1.bmp') data = read_image(infile) with tempfile.NamedTemporaryFile(suffix='.j2k') as tfile: - j = Jp2k(tfile.name, 'wb') - j.write(data, cratios=[800]) + j = Jp2k(tfile.name, data=data, cratios=[800]) codestream = j.get_codestream(header_only=False) @@ -562,8 +548,7 @@ class TestSuiteWrite(fixtures.MetadataBase): infile = opj_data_file('input/nonregression/Cevennes2.ppm') data = read_image(infile) with tempfile.NamedTemporaryFile(suffix='.j2k') as tfile: - j = Jp2k(tfile.name, 'wb') - j.write(data, cratios=[50]) + j = Jp2k(tfile.name, data=data, cratios=[50]) codestream = j.get_codestream(header_only=False) @@ -592,8 +577,8 @@ class TestSuiteWrite(fixtures.MetadataBase): """NR-ENC-Rome.bmp-11-encode""" data = read_image(opj_data_file('input/nonregression/Rome.bmp')) with tempfile.NamedTemporaryFile(suffix='.jp2') as tfile: - jp2 = Jp2k(tfile.name, 'wb') - jp2.write(data, psnr=[30, 35, 50], prog='LRCP', numres=3) + jp2 = Jp2k(tfile.name, + 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']) @@ -658,8 +643,7 @@ class TestSuiteWrite(fixtures.MetadataBase): infile = opj_data_file('input/nonregression/random-issue-0005.tif') data = read_image(infile) with tempfile.NamedTemporaryFile(suffix='.j2k') as tfile: - j = Jp2k(tfile.name, 'wb') - j.write(data) + j = Jp2k(tfile.name, data=data) codestream = j.get_codestream(header_only=False) diff --git a/glymur/test/test_printing.py b/glymur/test/test_printing.py index 7a5f9b9..5eedfe5 100644 --- a/glymur/test/test_printing.py +++ b/glymur/test/test_printing.py @@ -107,14 +107,15 @@ 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, + "Must have openjpeg 1.5 or higher to run") def test_asoc_label_box(self): """verify printing of asoc, label boxes""" # Construct a fake file with an asoc and a label box, as # OpenJPEG doesn't have such a file. - data = glymur.Jp2k(self.jp2file).read(rlevel=1) + data = glymur.Jp2k(self.jp2file)[::2, ::2] with tempfile.NamedTemporaryFile(suffix='.jp2') as tfile: - j = glymur.Jp2k(tfile.name, 'wb') - j.write(data) + j = glymur.Jp2k(tfile.name, data=data) with tempfile.NamedTemporaryFile(suffix='.jp2') as tfile2: From 6a59e38aede9a3246d00c206d6d8d2ad6fafba93 Mon Sep 17 00:00:00 2001 From: John Evans Date: Fri, 21 Nov 2014 17:56:52 -0500 Subject: [PATCH 31/57] reading metadata still works if library not installed, closes #304 --- glymur/jp2k.py | 2 +- glymur/lib/config.py | 2 +- glymur/lib/test/test_printing.py | 2 +- glymur/test/fixtures.py | 8 ++++++++ glymur/test/test_callbacks.py | 2 ++ glymur/test/test_jp2box.py | 2 +- glymur/test/test_jp2k.py | 15 ++++++++++++++- glymur/test/test_opj_suite.py | 12 +++++++----- 8 files changed, 35 insertions(+), 10 deletions(-) diff --git a/glymur/jp2k.py b/glymur/jp2k.py index 74834a9..097bb07 100644 --- a/glymur/jp2k.py +++ b/glymur/jp2k.py @@ -484,7 +484,7 @@ class Jp2k(Jp2kBox): This method can only be used to create JPEG 2000 images that can fit in memory. """ - if re.match("1.[0-4]", version.openjpeg_version) is not None: + if re.match("0|1.[0-4]", version.openjpeg_version) is not None: raise RuntimeError("You must have at least version 1.5 of OpenJPEG " "in order to write images.") diff --git a/glymur/lib/config.py b/glymur/lib/config.py index 4b92b9d..3aca5aa 100644 --- a/glymur/lib/config.py +++ b/glymur/lib/config.py @@ -144,7 +144,7 @@ def glymur_config(): lst.append(load_openjpeg_library(libname)) if all(handle is None for handle in lst): msg = "Neither the openjp2 nor the openjpeg library could be loaded. " - raise IOError(msg) + warnings.warn(msg) return tuple(lst) def get_configdir(): diff --git a/glymur/lib/test/test_printing.py b/glymur/lib/test/test_printing.py index 3d0e2b6..fb78676 100644 --- a/glymur/lib/test/test_printing.py +++ b/glymur/lib/test/test_printing.py @@ -17,7 +17,7 @@ import glymur from . import fixtures @unittest.skipIf(sys.hexversion < 0x03000000, "do not care about 2.7 here") -@unittest.skipIf(re.match('1|2.0', glymur.version.openjpeg_version), +@unittest.skipIf(re.match('0|1|2.0', glymur.version.openjpeg_version), "Requires openjpeg 2.1.0 or higher") class TestPrintingOpenjp2(unittest.TestCase): """Tests for verifying how printing works on openjp2 library structures.""" diff --git a/glymur/test/fixtures.py b/glymur/test/fixtures.py index 481da2d..113a47b 100644 --- a/glymur/test/fixtures.py +++ b/glymur/test/fixtures.py @@ -13,6 +13,14 @@ import six import glymur +# If openjpeg is not installed, many tests cannot be run. +if glymur.version.openjpeg_version == '0.0.0': + OPENJPEG_NOT_AVAILABLE = True + OPENJPEG_NOT_AVAILABLE_MSG = 'OpenJPEG library not installed' +else: + OPENJPEG_NOT_AVAILABLE = False + OPENJPEG_NOT_AVAILABLE_MSG = None + # Some versions of "six" on python3 cause problems when verifying warnings. # Only use when the version is 1.7 or higher. # And moreover, we only test using the 3.x infrastructure, never on 2.x. diff --git a/glymur/test/test_callbacks.py b/glymur/test/test_callbacks.py index c29f816..849d987 100644 --- a/glymur/test/test_callbacks.py +++ b/glymur/test/test_callbacks.py @@ -65,6 +65,8 @@ class TestCallbacks(unittest.TestCase): expected = '[INFO] tile number 1 / 1' self.assertEqual(actual, expected) + @unittest.skipIf(glymur.version.openjpeg_version[0] == '0', + "Missing openjpeg/openjp2 library.") def test_info_callbacks_on_read(self): """stdio output when info callback handler is enabled""" diff --git a/glymur/test/test_jp2box.py b/glymur/test/test_jp2box.py index 9d1f9cf..28ae4fe 100644 --- a/glymur/test/test_jp2box.py +++ b/glymur/test/test_jp2box.py @@ -114,7 +114,7 @@ class TestDataEntryURL(unittest.TestCase): self.assertEqual(url + chr(0), read_url) -@unittest.skipIf(re.match(r'''(1|2.0.0)''', +@unittest.skipIf(re.match(r'''0|1|2.0.0''', glymur.version.openjpeg_version) is not None, "Not supported until 2.1") @unittest.skipIf(os.name == "nt", WINDOWS_TMP_FILE_MSG) diff --git a/glymur/test/test_jp2k.py b/glymur/test/test_jp2k.py index b903dda..edb19a1 100644 --- a/glymur/test/test_jp2k.py +++ b/glymur/test/test_jp2k.py @@ -36,6 +36,7 @@ from glymur.version import openjpeg_version from .fixtures import HAS_PYTHON_XMP_TOOLKIT from .fixtures import WARNING_INFRASTRUCTURE_ISSUE, WARNING_INFRASTRUCTURE_MSG +from .fixtures import OPENJPEG_NOT_AVAILABLE, OPENJPEG_NOT_AVAILABLE_MSG if HAS_PYTHON_XMP_TOOLKIT: import libxmp @@ -76,6 +77,7 @@ 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) @@ -143,6 +145,7 @@ class TestSliceProtocolBaseWrite(SliceProtocolBase): j[:25, :45, :] = self.j2k_data[:25, :25, :] +@unittest.skipIf(OPENJPEG_NOT_AVAILABLE, OPENJPEG_NOT_AVAILABLE_MSG) class TestSliceProtocolRead(SliceProtocolBase): def test_resolution_strides_cannot_differ(self): @@ -251,6 +254,7 @@ class TestJp2k(unittest.TestCase): def tearDown(self): pass + @unittest.skipIf(OPENJPEG_NOT_AVAILABLE, OPENJPEG_NOT_AVAILABLE_MSG) @unittest.skipIf(WARNING_INFRASTRUCTURE_ISSUE, WARNING_INFRASTRUCTURE_MSG) def test_warn_if_using_read_method(self): """Should warn if deprecated read method is called""" @@ -313,6 +317,7 @@ class TestJp2k(unittest.TestCase): actdata = j2[:] self.assertTrue(fixtures.mse(actdata[0], expdata[0]) < 0.38) + @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)) @unittest.skipIf(re.match('1.5.(1|2)', openjpeg_version) is not None, @@ -345,6 +350,7 @@ class TestJp2k(unittest.TestCase): self.assertEqual(newjp2.filename, self.j2kfile) self.assertEqual(len(newjp2.box), 0) + @unittest.skipIf(OPENJPEG_NOT_AVAILABLE, OPENJPEG_NOT_AVAILABLE_MSG) @unittest.skipIf(WARNING_INFRASTRUCTURE_ISSUE, WARNING_INFRASTRUCTURE_MSG) def test_rlevel_max_backwards_compatibility(self): """ @@ -367,6 +373,7 @@ class TestJp2k(unittest.TestCase): np.testing.assert_array_equal(thumbnail1, thumbnail2) self.assertEqual(thumbnail1.shape, (25, 15, 3)) + @unittest.skipIf(OPENJPEG_NOT_AVAILABLE, OPENJPEG_NOT_AVAILABLE_MSG) def test_rlevel_too_high(self): """Should error out appropriately if reduce level too high""" j = Jp2k(self.jp2file) @@ -518,12 +525,14 @@ class TestJp2k(unittest.TestCase): self.assertEqual(new_jp2.box[j].length, baseline_jp2.box[j].length) + @unittest.skipIf(OPENJPEG_NOT_AVAILABLE, OPENJPEG_NOT_AVAILABLE_MSG) def test_basic_jp2(self): """Just a very basic test that reading a JP2 file does not error out. """ j2k = Jp2k(self.jp2file) j2k[::2, ::2] + @unittest.skipIf(OPENJPEG_NOT_AVAILABLE, OPENJPEG_NOT_AVAILABLE_MSG) def test_basic_j2k(self): """This test is only useful when openjp2 is not available and OPJ_DATA_ROOT is not set. We need at least one @@ -648,6 +657,7 @@ class TestJp2k(unittest.TestCase): 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)''', glymur.version.openjpeg_version) is not None, "Not supported until 2.0.1") @@ -664,6 +674,7 @@ 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)) @unittest.skipIf(os.name == "nt", fixtures.WINDOWS_TMP_FILE_MSG) @@ -869,6 +880,7 @@ class TestJp2k_1_x(unittest.TestCase): @unittest.skipIf(os.name == "nt", fixtures.WINDOWS_TMP_FILE_MSG) +@unittest.skipIf(OPENJPEG_NOT_AVAILABLE, OPENJPEG_NOT_AVAILABLE_MSG) class Test_2p0_official(unittest.TestCase): """Tests specific to v2.0.0""" @@ -962,6 +974,7 @@ class TestJp2k_2_0(unittest.TestCase): self.assertEqual(jasoc.box[3].box[1].box_id, 'xml ') +@unittest.skipIf(OPENJPEG_NOT_AVAILABLE, OPENJPEG_NOT_AVAILABLE_MSG) @unittest.skipIf(re.match(r'''(1|2.0.0)''', glymur.version.openjpeg_version) is not None, "Not to be run until unless 2.0.1 or higher is present") @@ -1135,7 +1148,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""" diff --git a/glymur/test/test_opj_suite.py b/glymur/test/test_opj_suite.py index cf44eaa..028734d 100644 --- a/glymur/test/test_opj_suite.py +++ b/glymur/test/test_opj_suite.py @@ -41,10 +41,12 @@ 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 + mse, peak_tolerance, read_pgx, opj_data_file, + OPENJPEG_NOT_AVAILABLE, OPENJPEG_NOT_AVAILABLE_MSG ) +@unittest.skipIf(OPENJPEG_NOT_AVAILABLE, OPENJPEG_NOT_AVAILABLE_MSG) @unittest.skipIf(OPJ_DATA_ROOT is None, "OPJ_DATA_ROOT environment variable not set") class TestSuite(unittest.TestCase): @@ -482,7 +484,7 @@ class TestSuiteWarns(MetadataBase): @unittest.skipIf(OPJ_DATA_ROOT is None, "OPJ_DATA_ROOT environment variable not set") -@unittest.skipIf(glymur.version.openjpeg_version_tuple[0] == 1, +@unittest.skipIf(glymur.version.openjpeg_version_tuple[0] != 2, "Feature not supported in glymur until openjpeg 2.0") class TestSuiteBands(unittest.TestCase): """ @@ -577,7 +579,7 @@ class TestSuiteBands(unittest.TestCase): @unittest.skipIf(OPJ_DATA_ROOT is None, "OPJ_DATA_ROOT environment variable not set") -@unittest.skipIf(glymur.version.openjpeg_version_tuple[0] == 1, +@unittest.skipIf(glymur.version.openjpeg_version_tuple[0] < 2, "Tests not passing until 2.0") class TestSuite2point0(unittest.TestCase): """Runs tests introduced in version 2.0 or that pass only in 2.0""" @@ -641,7 +643,7 @@ class TestSuite2point0(unittest.TestCase): @unittest.skipIf(OPJ_DATA_ROOT is None, "OPJ_DATA_ROOT environment variable not set") -@unittest.skipIf(re.match(r'''(1|2.0.0)''', +@unittest.skipIf(re.match(r'''0|1|2.0.0''', glymur.version.openjpeg_version) is not None, "Only supported in 2.0.1 or higher") class TestSuite2point1(unittest.TestCase): @@ -798,7 +800,7 @@ class TestSuite2point1(unittest.TestCase): @unittest.skipIf(OPJ_DATA_ROOT is None, "OPJ_DATA_ROOT environment variable not set") -@unittest.skipIf(re.match(r'''(1|2.0.0)''', +@unittest.skipIf(re.match(r'''0|1|2.0.0''', glymur.version.openjpeg_version) is not None, "Only supported in 2.0.1 or higher") class TestReadArea(unittest.TestCase): From c39661b586626d9a819fbd7e25f6d89bd53eb48a Mon Sep 17 00:00:00 2001 From: jevans Date: Fri, 21 Nov 2014 21:53:39 -0500 Subject: [PATCH 32/57] pep8 cleanup --- glymur/_uuid_io.py | 9 +-- glymur/codestream.py | 13 ++- glymur/command_line.py | 28 ++++--- glymur/core.py | 24 +++--- glymur/jp2box.py | 119 ++++++++++++++-------------- glymur/jp2k.py | 152 +++++++++++++++++++---------------- glymur/lib/openjp2.py | 14 +--- glymur/lib/openjpeg.py | 176 +++++++++++++++++++---------------------- 8 files changed, 267 insertions(+), 268 deletions(-) diff --git a/glymur/_uuid_io.py b/glymur/_uuid_io.py index bf9960a..7bcf2cb 100644 --- a/glymur/_uuid_io.py +++ b/glymur/_uuid_io.py @@ -11,6 +11,7 @@ import warnings import lxml.etree as ET + def xml(raw_data): """ XMP data to be parsed as XML. @@ -23,6 +24,7 @@ def xml(raw_data): return ET.ElementTree(elt) + def tiff_header(read_buffer): """ Interpret the uuid raw data as a tiff header. @@ -37,8 +39,8 @@ def tiff_header(read_buffer): # big endian endian = '>' else: - msg = "The byte order indication in the TIFF header ({0}) is invalid. " - msg += "It should be either {1} or {2}." + msg = "The byte order indication in the TIFF header ({0}) is " + msg += "invalid. It should be either {1} or {2}." msg = msg.format(read_buffer[6:8], bytes([73, 73]), bytes([77, 77])) raise IOError(msg) @@ -503,6 +505,3 @@ class _ExifInteroperabilityIfd(_Ifd): def __init__(self, endian, read_buffer, offset): _Ifd.__init__(self, endian, read_buffer, offset) self.post_process(self.tagnum2name) - - - diff --git a/glymur/codestream.py b/glymur/codestream.py index c8ab00f..aa12bd7 100644 --- a/glymur/codestream.py +++ b/glymur/codestream.py @@ -24,11 +24,10 @@ import warnings import numpy as np -from .core import ( - LRCP, RLCP, RPCL, PCRL, CPRL, - WAVELET_XFORM_9X7_IRREVERSIBLE, WAVELET_XFORM_5X3_REVERSIBLE, - _Keydefaultdict -) +from .core import (LRCP, RLCP, RPCL, PCRL, CPRL, + WAVELET_XFORM_9X7_IRREVERSIBLE, + WAVELET_XFORM_5X3_REVERSIBLE, + _Keydefaultdict) from .lib import openjp2 as opj2 _factory = lambda x: '{0} (invalid)'.format(x) @@ -57,7 +56,7 @@ _CAPABILITIES_DISPLAY = _Keydefaultdict(_factory, _PROFILE_0: '0', _PROFILE_1: '1', _PROFILE_3: 'Cinema 2K', - _PROFILE_4: 'Cinema 4K'} ) + _PROFILE_4: 'Cinema 4K'}) # Need a catch-all list of valid markers. # See table A-1 in ISO/IEC FCD15444-1. @@ -703,7 +702,6 @@ class Codestream(object): msg = "Invalid number of tiles ({0}).".format(numtiles) warnings.warn(msg) - kwargs = {'rsiz': rsiz, 'xysiz': xysiz, 'xyosiz': xyosiz, @@ -1614,6 +1612,7 @@ class SOCsegment(Segment): msg = "glymur.codestream.SOCsegment()" return msg + class SODsegment(Segment): """Container for Start of Data (SOD) segment information. diff --git a/glymur/command_line.py b/glymur/command_line.py index bf96293..5f0d357 100644 --- a/glymur/command_line.py +++ b/glymur/command_line.py @@ -8,28 +8,29 @@ import warnings from . import Jp2k, set_printoptions, lib + def main(): """ Entry point for console script jp2dump. """ - description='Print JPEG2000 metadata.' + description = 'Print JPEG2000 metadata.' parser = argparse.ArgumentParser(description=description) parser.add_argument('-x', '--noxml', - help='Suppress XML.', - action='store_true') + help='Suppress XML.', + action='store_true') parser.add_argument('-s', '--short', - help='Only print box id, offset, and length.', - action='store_true') + help='Only print box id, offset, and length.', + action='store_true') 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, - nargs=1, - type=int, - default=[0]) + help=chelp, + nargs=1, + type=int, + default=[0]) parser.add_argument('filename') @@ -38,7 +39,7 @@ def main(): set_printoptions(xml=False) if args.short: set_printoptions(short=True) - + codestream_level = args.codestream[0] if codestream_level not in [0, 1, 2]: raise ValueError("Invalid level of codestream information specified.") @@ -50,15 +51,16 @@ def main(): print_full_codestream = False else: print_full_codestream = True - + filename = args.filename - + with warnings.catch_warnings(record=True) as wctx: # 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 and codestream_level == 0: + 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)) diff --git a/glymur/core.py b/glymur/core.py index 4d9a3af..3327253 100644 --- a/glymur/core.py +++ b/glymur/core.py @@ -4,6 +4,7 @@ import collections import copy import lxml.etree as ET + class _Keydefaultdict(collections.defaultdict): """Unlisted keys help form their own error message. @@ -121,12 +122,12 @@ ROMM_RGB = 21 _factory = lambda x: '{0} (unrecognized)'.format(x) _COLORSPACE_MAP_DISPLAY = _Keydefaultdict(_factory, - { CMYK: 'CMYK', - SRGB: 'sRGB', - GREYSCALE: 'greyscale', - YCC: 'YCC', - E_SRGB: 'e-sRGB', - ROMM_RGB: 'ROMM-RGB'} ) + {CMYK: 'CMYK', + SRGB: 'sRGB', + GREYSCALE: 'greyscale', + YCC: 'YCC', + E_SRGB: 'e-sRGB', + ROMM_RGB: 'ROMM-RGB'}) # enumerated color channel types COLOR = 0 @@ -134,11 +135,11 @@ OPACITY = 1 PRE_MULTIPLIED_OPACITY = 2 _UNSPECIFIED = 65535 _factory = lambda x: '{0} (invalid)'.format(x) -_COLOR_TYPE_MAP_DISPLAY = _Keydefaultdict(_factory, - { COLOR: 'color', - OPACITY: 'opacity', - PRE_MULTIPLIED_OPACITY: 'pre-multiplied opacity', - _UNSPECIFIED: 'unspecified'}) +_dict = {COLOR: 'color', + OPACITY: 'opacity', + PRE_MULTIPLIED_OPACITY: 'pre-multiplied opacity', + _UNSPECIFIED: 'unspecified'} +_COLOR_TYPE_MAP_DISPLAY = _Keydefaultdict(_factory, _dict) # color channel definitions. RED = 1 @@ -153,4 +154,3 @@ _COLORSPACE = {SRGB: {"R": 1, "G": 2, "B": 3}, YCC: {"Y": 1, "Cb": 2, "Cr": 3}, E_SRGB: {"R": 1, "G": 2, "B": 3}, ROMM_RGB: {"R": 1, "G": 2, "B": 3}} - diff --git a/glymur/jp2box.py b/glymur/jp2box.py index a2148ae..39e1f6a 100644 --- a/glymur/jp2box.py +++ b/glymur/jp2box.py @@ -29,13 +29,11 @@ import lxml.etree as ET import numpy as np from .codestream import Codestream -from .core import ( - _COLORSPACE_MAP_DISPLAY, _COLOR_TYPE_MAP_DISPLAY, - SRGB, GREYSCALE, YCC, - ENUMERATED_COLORSPACE, RESTRICTED_ICC_PROFILE, - ANY_ICC_PROFILE, VENDOR_COLOR_METHOD, - _Keydefaultdict -) +from .core import (_COLORSPACE_MAP_DISPLAY, _COLOR_TYPE_MAP_DISPLAY, + SRGB, GREYSCALE, YCC, + ENUMERATED_COLORSPACE, RESTRICTED_ICC_PROFILE, + ANY_ICC_PROFILE, VENDOR_COLOR_METHOD, + _Keydefaultdict) from . import _uuid_io @@ -52,6 +50,7 @@ _APPROX_DISPLAY = _Keydefaultdict(_factory, 3: 'approximates correct colorspace definition, reasonable quality', 4: 'approximates correct colorspace definition, poor quality'}) + class Jp2kBox(object): """Superclass for JPEG 2000 boxes. @@ -109,7 +108,6 @@ class Jp2kBox(object): msg += '\n' + self._indent(boxstr) return msg - def _indent(self, textstr, indent_level=4): """ Indent a string. @@ -135,7 +133,6 @@ class Jp2kBox(object): lst = [(' ' * indent_level + x) for x in textstr.split('\n')] return '\n'.join(lst) - def _write_superbox(self, fptr, box_id): """Write a superbox. @@ -191,13 +188,14 @@ class Jp2kBox(object): try: box = parser(fptr, start, num_bytes) except ValueError as err: - msg = "Encountered an unrecoverable ValueError while parsing a {0} " - msg += "box at byte offset {1}. The original error message was " - msg += "\"{2}\"" + msg = "Encountered an unrecoverable ValueError while parsing a " + msg += "{0} box at byte offset {1}. The original error message " + msg += "was \"{2}\"" msg = msg.format(_BOX_WITH_ID[box_id].longname, start, str(err)) warnings.warn(msg, UserWarning) box = UnknownBox(box_id.decode('utf-8'), - length=num_bytes, offset=start, longname='Unknown') + length=num_bytes, + offset=start, longname='Unknown') return box @@ -299,6 +297,7 @@ class ColourSpecificationBox(Jp2kBox): """ longname = 'Colour Specification' box_id = 'colr' + def __init__(self, method=ENUMERATED_COLORSPACE, precedence=0, approximation=0, colorspace=None, icc_profile=None, length=0, offset=-1): @@ -337,16 +336,16 @@ class ColourSpecificationBox(Jp2kBox): if self.icc_profile is None: if self.colorspace not in [SRGB, GREYSCALE, YCC]: - msg = "Colorspace should correspond to one of SRGB, GREYSCALE, " - msg += "or YCC." + msg = "Colorspace should correspond to one of SRGB, " + msg += "GREYSCALE, or YCC." self._dispatch_validation_error(msg, writing=True) self._validate(writing=True) - def __repr__(self): msg = "glymur.jp2box.ColourSpecificationBox(" - msg += "method={0}, precedence={1}, approximation={2}, colorspace={3}, " + msg += "method={0}, precedence={1}, approximation={2}, " + msg += "colorspace={3}, " msg += "icc_profile={4})" msg = msg.format(self.method, self.precedence, @@ -357,7 +356,7 @@ class ColourSpecificationBox(Jp2kBox): def __str__(self): msg = Jp2kBox.__str__(self) - if _printoptions['short'] == True: + if _printoptions['short'] is True: return msg msg += '\n Method: {0}'.format(_METHOD_DISPLAY[self.method]) @@ -619,10 +618,9 @@ class ChannelDefinitionBox(Jp2kBox): msg += " 65535 - unspecified" self._dispatch_validation_error(msg, writing=writing) - def __str__(self): msg = Jp2kBox.__str__(self) - if _printoptions['short'] == True: + if _printoptions['short'] is True: return msg for j in range(len(self.association)): @@ -842,7 +840,7 @@ class CompositingLayerHeaderBox(Jp2kBox): List of boxes contained in this superbox. """ box_id = 'jplh' - longname='Compositing Layer Header' + longname = 'Compositing Layer Header' def __init__(self, box=None, length=0, offset=-1): Jp2kBox.__init__(self) @@ -931,7 +929,7 @@ class ComponentMappingBox(Jp2kBox): def __str__(self): msg = Jp2kBox.__str__(self) - if _printoptions['short'] == True: + if _printoptions['short'] is True: return msg for k in range(len(self.component_index)): @@ -1027,7 +1025,9 @@ class ContiguousCodestreamBox(Jp2kBox): if self._filename is not None: with open(self._filename, 'rb') as fptr: fptr.seek(self.main_header_offset) - main_header = Codestream(fptr, self._length, header_only=True) + main_header = Codestream(fptr, + self._length, + header_only=True) self._main_header = main_header return self._main_header @@ -1037,9 +1037,9 @@ class ContiguousCodestreamBox(Jp2kBox): def __str__(self): msg = Jp2kBox.__str__(self) - if _printoptions['short'] == True: + if _printoptions['short'] is True: return msg - if _printoptions['codestream'] == False: + if _printoptions['codestream'] is False: return msg msg += '\n Main header:' @@ -1118,7 +1118,8 @@ class DataReferenceBox(Jp2kBox): """Verify that the box obeys the specifications for writing. """ if len(self.DR) == 0: - msg = "A data reference box cannot be empty when written to a file." + msg = "A data reference box cannot be empty when written to a " + msg += "file." self._dispatch_validation_error(msg, writing=True) self._validate(writing=True) @@ -1145,7 +1146,7 @@ class DataReferenceBox(Jp2kBox): def __str__(self): msg = Jp2kBox.__str__(self) - if _printoptions['short'] == True: + if _printoptions['short'] is True: return msg for box in self.DR: @@ -1248,7 +1249,7 @@ class FileTypeBox(Jp2kBox): def __str__(self): msg = Jp2kBox.__str__(self) - if _printoptions['short'] == True: + if _printoptions['short'] is True: return msg lst = [msg, @@ -1311,7 +1312,7 @@ class FileTypeBox(Jp2kBox): brand = brand.decode('utf-8') # Extract the compatibility list. Each entry has 4 bytes. - num_entries = int((length - 16)/ 4) + num_entries = int((length - 16) / 4) compatibility_list = [] for j in range(int(num_entries)): entry, = struct.unpack_from('>4s', read_buffer, 8 + j * 4) @@ -1374,7 +1375,7 @@ class FragmentListBox(Jp2kBox): def __str__(self): msg = Jp2kBox.__str__(self) - if _printoptions['short'] == True: + if _printoptions['short'] is True: return msg for j in range(len(self.fragment_offset)): @@ -1458,7 +1459,10 @@ class FragmentTableBox(Jp2kBox): def __repr__(self): msg = "glymur.jp2box.FragmentTableBox(box={0})" - msg = msg.format(None) if (len(self.box) == 0) else msg.format(self.box) + if len(self.box) == 0: + msg = msg.format(None) + else: + msg = msg.format(self.box) return msg def __str__(self): @@ -1505,7 +1509,6 @@ class FragmentTableBox(Jp2kBox): self._write_superbox(fptr, b'ftbl') - class FreeBox(Jp2kBox): """Container for JPX free box information. @@ -1534,7 +1537,7 @@ class FreeBox(Jp2kBox): def __str__(self): msg = Jp2kBox.__str__(self) - if _printoptions['short'] == True: + if _printoptions['short'] is True: return msg return msg @@ -1630,7 +1633,7 @@ class ImageHeaderBox(Jp2kBox): def __str__(self): msg = Jp2kBox.__str__(self) - if _printoptions['short'] == True: + if _printoptions['short'] is True: return msg msg = "{0}" @@ -1861,7 +1864,7 @@ class JPEG2000SignatureBox(Jp2kBox): def __str__(self): msg = Jp2kBox.__str__(self) - if _printoptions['short'] == True: + if _printoptions['short'] is True: return msg msg += '\n Signature: {0:02x}{1:02x}{2:02x}{3:02x}' @@ -1950,7 +1953,7 @@ class PaletteBox(Jp2kBox): def __str__(self): msg = Jp2kBox.__str__(self) - if _printoptions['short'] == True: + if _printoptions['short'] is True: return msg msg += '\n Size: ({0} x {1})'.format(*self.palette.shape) @@ -2203,7 +2206,7 @@ class ReaderRequirementsBox(Jp2kBox): def __str__(self): msg = Jp2kBox.__str__(self) - if _printoptions['short'] == True: + if _printoptions['short'] is True: return msg msg += '\n Fully Understands Aspect Mask: 0x{0:x}'.format(self.fuam) @@ -2262,7 +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 @@ -2348,14 +2352,11 @@ def _parse_standard_flag(read_buffer, mask_length): # from the buffer read from file. mask_format = {1: 'B', 2: 'H', 4: 'I'}[mask_length] - #read_buffer = fptr.read(2) num_standard_flags, = struct.unpack_from('>H', read_buffer, offset=0) # Read in standard flags and standard masks. Each standard flag should # be two bytes, but the standard mask flag is as long as specified by # the mask length. - #read_buffer = fptr.read(num_standard_flags * (2 + mask_length)) - fmt = '>' + ('H' + mask_format) * num_standard_flags data = struct.unpack_from(fmt, read_buffer, offset=2) @@ -2386,7 +2387,6 @@ def _parse_vendor_features(read_buffer, mask_length): # Each vendor feature consists of a 16-byte UUID plus a mask whose # length is specified by, you guessed it, "mask_length". entry_length = 16 + mask_length - #read_buffer = fptr.read(num_vendor_features * entry_length) vendor_feature = [] vendor_mask = [] for j in range(num_vendor_features): @@ -2494,7 +2494,7 @@ class CaptureResolutionBox(Jp2kBox): def __str__(self): msg = Jp2kBox.__str__(self) - if _printoptions['short'] == True: + if _printoptions['short'] is True: return msg msg += '\n VCR: {0}'.format(self.vertical_resolution) @@ -2560,7 +2560,7 @@ class DisplayResolutionBox(Jp2kBox): def __str__(self): msg = Jp2kBox.__str__(self) - if _printoptions['short'] == True: + if _printoptions['short'] is True: return msg msg += '\n VDR: {0}'.format(self.vertical_resolution) @@ -2620,7 +2620,7 @@ class LabelBox(Jp2kBox): def __str__(self): msg = Jp2kBox.__str__(self) - if _printoptions['short'] == True: + if _printoptions['short'] is True: return msg msg += '\n Label: {0}'.format(self.label) @@ -2688,7 +2688,7 @@ class NumberListBox(Jp2kBox): def __str__(self): msg = Jp2kBox.__str__(self) - if _printoptions['short'] == True: + if _printoptions['short'] is True: return msg for j, association in enumerate(self.associations): @@ -2738,7 +2738,8 @@ class NumberListBox(Jp2kBox): def write(self, fptr): """Write a NumberList box to file. """ - fptr.write(struct.pack('>I4s', len(self.associations) * 4 + 8, b'nlst')) + fptr.write(struct.pack('>I4s', + len(self.associations) * 4 + 8, b'nlst')) fmt = '>' + 'I' * len(self.associations) write_buffer = struct.pack(fmt, *self.associations) @@ -2790,9 +2791,9 @@ class XMLBox(Jp2kBox): def __str__(self): msg = Jp2kBox.__str__(self) - if _printoptions['short'] == True: + if _printoptions['short'] is True: return msg - if _printoptions['xml'] == False: + if _printoptions['xml'] is False: return msg msg += '\n' @@ -2911,7 +2912,7 @@ class UUIDListBox(Jp2kBox): def __str__(self): msg = Jp2kBox.__str__(self) - if _printoptions['short'] == True: + if _printoptions['short'] is True: return msg for j, uuid_item in enumerate(self.ulst): @@ -2942,7 +2943,7 @@ class UUIDListBox(Jp2kBox): ulst = [] for j in range(num_uuids): - uuid_buffer = read_buffer[2 + j * 16 : 2 + (j + 1) * 16] + uuid_buffer = read_buffer[2 + j * 16:2 + (j + 1) * 16] ulst.append(uuid.UUID(bytes=uuid_buffer)) return cls(ulst, length=length, offset=offset) @@ -3056,7 +3057,6 @@ class DataEntryURLBox(Jp2kBox): fptr.write(write_buffer) fptr.write(url) - def __repr__(self): msg = "glymur.jp2box.DataEntryURLBox({0}, {1}, '{2}')" msg = msg.format(self.version, self.flag, self.url) @@ -3064,7 +3064,7 @@ class DataEntryURLBox(Jp2kBox): def __str__(self): msg = Jp2kBox.__str__(self) - if _printoptions['short'] == True: + if _printoptions['short'] is True: return msg msg += '\n ' @@ -3216,7 +3216,7 @@ class UUIDBox(Jp2kBox): def __str__(self): msg = Jp2kBox.__str__(self) - if _printoptions['short'] == True: + if _printoptions['short'] is True: return msg msg = '{0}\n UUID: {1}'.format(msg, self.uuid) @@ -3227,7 +3227,7 @@ class UUIDBox(Jp2kBox): else: msg += ' (unknown)' - if (((_printoptions['xml'] == False) and + if (((_printoptions['xml'] is False) and (self.uuid == uuid.UUID('be7acfcb-97a9-42e8-9c71-999491e3afac')))): # If it's an XMP UUID, don't print the XML contents. return msg @@ -3312,6 +3312,7 @@ _BOX_WITH_ID = { _parseoptions = {'codestream': True} + def set_parseoptions(codestream=True): """Set parsing options. @@ -3336,6 +3337,7 @@ def set_parseoptions(codestream=True): """ _parseoptions['codestream'] = codestream + def get_parseoptions(): """Return the current parsing options. @@ -3356,6 +3358,7 @@ def get_parseoptions(): _printoptions = {'short': False, 'xml': True, 'codestream': True} + def set_printoptions(**kwargs): """Set printing options. @@ -3365,7 +3368,8 @@ def set_printoptions(**kwargs): ---------- short : bool, optional When True, only the box ID, offset, and length are displayed. Useful - for displaying only the basic structure or skeleton of a JPEG 2000 file. + for displaying only the basic structure or skeleton of a JPEG 2000 + file. xml : bool, optional When False, printing of the XML contents of any XML boxes or UUID XMP boxes is suppressed. @@ -3388,6 +3392,7 @@ def set_printoptions(**kwargs): raise TypeError('"{0}" not a valid keyword parameter.'.format(key)) _printoptions[key] = value + def get_printoptions(): """Return the current print options. @@ -3407,5 +3412,3 @@ def get_printoptions(): set_printoptions """ return _printoptions - - diff --git a/glymur/jp2k.py b/glymur/jp2k.py index 097bb07..b1e5c60 100644 --- a/glymur/jp2k.py +++ b/glymur/jp2k.py @@ -31,12 +31,12 @@ import numpy as np from .codestream import Codestream from . import core, version -from .jp2box import ( - Jp2kBox, JPEG2000SignatureBox, FileTypeBox, JP2HeaderBox, - ColourSpecificationBox, ContiguousCodestreamBox, ImageHeaderBox -) +from .jp2box import (Jp2kBox, JPEG2000SignatureBox, FileTypeBox, + JP2HeaderBox, ColourSpecificationBox, + ContiguousCodestreamBox, ImageHeaderBox) from .lib import openjpeg as opj, openjp2 as opj2, c as libc + class Jp2k(Jp2kBox): """JPEG 2000 file. @@ -138,7 +138,6 @@ class Jp2k(Jp2kBox): not (X, Y) verbose : bool, optional print informational messages produced by the OpenJPEG library - """ Jp2kBox.__init__(self) self.filename = filename @@ -176,8 +175,8 @@ class Jp2k(Jp2kBox): @layer.setter def layer(self, layer): if version.openjpeg_version_tuple[0] < 2: - msg = "Layer property not supported unless the version of OpenJPEG " - msg += "is 2.0 or higher." + msg = "Layer property not supported unless the version of " + msg += "OpenJPEG is 2.0 or higher." raise RuntimeError(msg) self._layer = layer @@ -361,8 +360,8 @@ class Jp2k(Jp2kBox): kwargs : dictionary non-image keyword inputs provided to write method """ - if (('cinema2k' in kwargs or 'cinema4k' in kwargs) and - (len(set(kwargs)) > 1)): + if ((('cinema2k' in kwargs or 'cinema4k' in kwargs) and + (len(set(kwargs)) > 1))): msg = "Cannot specify cinema2k/cinema4k along with other options." raise IOError(msg) @@ -485,8 +484,9 @@ class Jp2k(Jp2kBox): in memory. """ if re.match("0|1.[0-4]", version.openjpeg_version) is not None: - raise RuntimeError("You must have at least version 1.5 of OpenJPEG " - "in order to write images.") + msg = "You must have at least version 1.5 of OpenJPEG " + msg += "in order to write images." + raise RuntimeError(msg) self._determine_colorspace(**kwargs) self._populate_cparams(img_array, **kwargs) @@ -518,9 +518,11 @@ class Jp2k(Jp2kBox): 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 + + (numcols - 1) * self._cparams.subsampling_dx \ + + 1 image.contents.y1 = image.contents.y0 \ - + (numrows - 1) * self._cparams.subsampling_dy + 1 + + (numrows - 1) * self._cparams.subsampling_dy \ + + 1 # Stage the image data to the openjpeg data structure. for k in range(0, numlayers): @@ -633,7 +635,7 @@ class Jp2k(Jp2kBox): def _determine_colorspace(self, colorspace=None, **kwargs): """Determine the colorspace from the supplied inputs. - + Parameters ---------- colorspace : str, optional @@ -658,7 +660,7 @@ class Jp2k(Jp2kBox): elif colorspace.lower() == 'rgb' and self.shape[2] < 3: msg = 'RGB colorspace requires at least 3 components.' raise IOError(msg) - + # Turn the colorspace from a string to the enumerated value that # the library expects. COLORSPACE_MAP = {'rgb': opj2.CLRSPC_SRGB, @@ -667,8 +669,7 @@ class Jp2k(Jp2kBox): 'ycc': opj2.CLRSPC_YCC} self._colorspace = COLORSPACE_MAP[colorspace.lower()] - - + def _write_openjp2(self, img_array, verbose=False): """ Write JPEG 2000 file using OpenJPEG 2.x interface. @@ -734,7 +735,8 @@ class Jp2k(Jp2kBox): if not ((box.box_id == 'xml ') or (box.box_id == 'uuid' and box.uuid == UUID('be7acfcb-97a9-42e8-9c71-999491e3afac'))): - msg = "Only XML boxes and XMP UUID boxes can currently be appended." + msg = "Only XML boxes and XMP UUID boxes can currently be " + msg += "appended." raise IOError(msg) # Check the last box. If the length field is zero, then rewrite @@ -891,9 +893,9 @@ class Jp2k(Jp2kBox): Slicing protocol. """ if ((isinstance(index, slice) and - (index.start == None and - index.stop == None and - index.step == None)) or (index is Ellipsis)): + (index.start is None and + index.stop is None and + index.step is None)) or (index is Ellipsis)): # Case of jp2[:] = data, i.e. write the entire image. # # Should have a slice object where start = stop = step = None @@ -923,12 +925,14 @@ class Jp2k(Jp2kBox): return self._read() if isinstance(pargs, slice): - if pargs.start is None and pargs.stop is None and pargs.step is None: + if (((pargs.start is None) and + (pargs.stop is None) and + (pargs.step is None))): # Case of jp2[:] return self._read() # Corner case of jp2[x] where x is a slice object with non-null - # members. Just augment it with an ellipsis and let the code + # members. Just augment it with an ellipsis and let the code # below handle it. pargs = (pargs, Ellipsis) @@ -971,8 +975,7 @@ class Jp2k(Jp2kBox): # Reduce dimensionality in the scalar dimension. return np.squeeze(data, axis=idx) - - # Assuming pargs is a tuple of slices from now on. + # Assuming pargs is a tuple of slices from now on. rows = pargs[0] cols = pargs[1] if len(pargs) == 2: @@ -989,15 +992,14 @@ class Jp2k(Jp2kBox): # Ok, reduce layer step is the same in both xy directions, so just take # one of them. step = rows_step - + # Check if the step size is a power of 2. if np.abs(np.log2(step) - np.round(np.log2(step))) > 1e-6: msg = "Row and column strides must be powers of 2." raise IndexError(msg) rlevel = np.int(np.round(np.log2(step))) - area = ( - 0 if rows.start is None else rows.start, + area = (0 if rows.start is None else rows.start, 0 if cols.start is None else cols.start, numrows if rows.stop is None else rows.stop, numcols if cols.stop is None else cols.stop @@ -1009,7 +1011,6 @@ class Jp2k(Jp2kBox): # Ok, 3 arguments in pargs. return data[:, :, bands] - def _read(self, **kwargs): """Read a JPEG 2000 image. @@ -1032,34 +1033,34 @@ class Jp2k(Jp2kBox): def read(self, **kwargs): """ """ - #Read a JPEG 2000 image. + # Read a JPEG 2000 image. # - #Parameters - #---------- - #rlevel : int, optional - # Factor by which to rlevel output resolution. Use -1 to get the - # lowest resolution thumbnail. This is the only keyword option - # available to use when the OpenJPEG version is 1.5 or earlier. - #layer : int, optional - # Number of quality layer to decode. - #area : tuple, optional - # Specifies decoding image area, - # (first_row, first_col, last_row, last_col) - #tile : int, optional - # Number of tile to decode. - #verbose : bool, optional - # Print informational messages produced by the OpenJPEG library. + # Parameters + # ---------- + # rlevel : int, optional + # Factor by which to rlevel output resolution. Use -1 to get the + # lowest resolution thumbnail. This is the only keyword option + # available to use when the OpenJPEG version is 1.5 or earlier. + # layer : int, optional + # Number of quality layer to decode. + # area : tuple, optional + # Specifies decoding image area, + # (first_row, first_col, last_row, last_col) + # tile : int, optional + # Number of tile to decode. + # verbose : bool, optional + # Print informational messages produced by the OpenJPEG library. # - #Returns - #------- - #img_array : ndarray - # The image data. + # Returns + # ------- + # img_array : ndarray + # The image data. # - #Raises - #------ - #IOError - # If the image has differing subsample factors. - + # Raises + # ------ + # IOError + # If the image has differing subsample factors. + if 'ignore_pclr_cmap_cdef' in kwargs: self.ignore_pclr_cmap_cdef = kwargs['ignore_pclr_cmap_cdef'] warnings.warn("Use array-style slicing instead.", DeprecationWarning) @@ -1163,7 +1164,8 @@ class Jp2k(Jp2kBox): return data - def _read_openjp2(self, rlevel=0, layer=None, area=None, tile=None, verbose=False): + def _read_openjp2(self, rlevel=0, layer=None, area=None, tile=None, + verbose=False): """Read a JPEG 2000 image using libopenjp2. Parameters @@ -1453,7 +1455,7 @@ class Jp2k(Jp2kBox): def _populate_image_struct(self, image, imgdata): """Populates image struct needed for compression. - + Parameters ---------- image : ImageType(ctypes.Structure) @@ -1461,9 +1463,9 @@ class Jp2k(Jp2kBox): img_array : ndarray Image data to be written to file. """ - + numrows, numcols, num_comps = imgdata.shape - + # set image offset and reference grid image.contents.x0 = self._cparams.image_offset_x0 image.contents.y0 = self._cparams.image_offset_y0 @@ -1471,7 +1473,7 @@ class Jp2k(Jp2kBox): (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, num_comps): if re.match("2.0", version.openjpeg_version) is not None: @@ -1485,19 +1487,19 @@ class Jp2k(Jp2kBox): core.OPJ_PROFILE_CINEMA_4K): image.contents.comps[k].prec = 12 image.contents.comps[k].bpp = 12 - + layer = np.ascontiguousarray(imgdata[:, :, k], dtype=np.int32) dest = image.contents.comps[k].data src = layer.ctypes.data ctypes.memmove(dest, src, layer.nbytes) - + return image - + def _populate_comptparms(self, img_array): """Instantiate and populate comptparms structure. - + This structure defines the image components. - + Parameters ---------- img_array : ndarray @@ -1526,8 +1528,8 @@ class Jp2k(Jp2kBox): comptparms[j].sgnd = 0 self._comptparms = comptparms - - + + def _component2dtype(component): """Take an OpenJPEG component structure and determine the numpy datatype. @@ -1573,6 +1575,7 @@ JP2_IDS = ['colr', 'cdef', 'cmap', 'jp2c', 'ftyp', 'ihdr', 'jp2h', 'jP ', 'pclr', 'res ', 'resc', 'resd', 'xml ', 'ulst', 'uinf', 'url ', 'uuid'] + def _validate_jp2_box_sequence(boxes): """Run through series of tests for JP2 box legality. @@ -1588,12 +1591,13 @@ def _validate_jp2_box_sequence(boxes): count = _collect_box_count(boxes) for box_id in count.keys(): if box_id not in JP2_IDS: - msg = "The presence of a '{0}' box requires that the file type " - msg += "brand be set to 'jpx '." + msg = "The presence of a '{0}' box requires that the file " + msg += "type brand be set to 'jpx '." raise IOError(msg.format(box_id)) _validate_jp2_colr(boxes) + def _validate_jp2_colr(boxes): """ Validate JP2 requirements on colour specification boxes. @@ -1605,6 +1609,7 @@ def _validate_jp2_colr(boxes): msg = "A JP2 colr box cannot have a non-zero approximation field." raise IOError(msg) + def _validate_jpx_box_sequence(boxes): """Run through series of tests for JPX box legality.""" _validate_label(boxes) @@ -1613,6 +1618,7 @@ def _validate_jpx_box_sequence(boxes): _validate_singletons(boxes) _validate_top_level(boxes) + def _validate_signature_compatibility(boxes): """Validate the file signature and compatibility status.""" # Check for a bad sequence of boxes. @@ -1700,6 +1706,8 @@ def _validate_channel_definition(jp2h, colr): JP2H_CHILDREN = set(['bpcc', 'cdef', 'cmap', 'ihdr', 'pclr']) + + def _check_jp2h_child_boxes(boxes, parent_box_name): """Certain boxes can only reside in the JP2 header.""" box_ids = set([box.box_id for box in boxes]) @@ -1727,6 +1735,7 @@ def _collect_box_count(boxes): TOP_LEVEL_ONLY_BOXES = set(['dtbl']) + def _check_superbox_for_top_levels(boxes): """Several boxes can only occur at the top level.""" # We are only looking at the boxes contained in a superbox, so if any of @@ -1742,6 +1751,7 @@ def _check_superbox_for_top_levels(boxes): if hasattr(box, 'box'): _check_superbox_for_top_levels(box.box) + def _validate_top_level(boxes): """Several boxes can only occur at the top level.""" # Add the counts in the superboxes. @@ -1761,6 +1771,7 @@ def _validate_top_level(boxes): msg += 'a fragment table box as well.' raise IOError(msg) + def _validate_singletons(boxes): """Several boxes can only occur once.""" count = _collect_box_count(boxes) @@ -1771,6 +1782,7 @@ def _validate_singletons(boxes): JPX_IDS = ['asoc', 'nlst'] + def _validate_jpx_brand(boxes, brand): """ If there is a JPX box then the brand must be 'jpx '. @@ -1785,6 +1797,7 @@ def _validate_jpx_brand(boxes, brand): # Same set of checks on any child boxes. _validate_jpx_brand(box.box, brand) + def _validate_jpx_compatibility(boxes, compatibility_list): """ If there is a JPX box then the compatibility list must also contain 'jpx '. @@ -1800,6 +1813,7 @@ def _validate_jpx_compatibility(boxes, compatibility_list): # Same set of checks on any child boxes. _validate_jpx_compatibility(box.box, compatibility_list) + def _validate_label(boxes): """ Label boxes can only be inside association, codestream headers, or @@ -1816,6 +1830,7 @@ def _validate_label(boxes): # Same set of checks on any child boxes. _validate_label(box.box) + def extract_image_cube(image): """Extract 3D image from openjpeg data structure. """ @@ -1871,7 +1886,6 @@ def extract_image_bands(image): return data - # Setup the default callback handlers. See the callback functions subsection # in the ctypes section of the Python documentation for a solid explanation of # what's going on here. diff --git a/glymur/lib/openjp2.py b/glymur/lib/openjp2.py index 5e58cf4..24122b9 100644 --- a/glymur/lib/openjp2.py +++ b/glymur/lib/openjp2.py @@ -13,6 +13,7 @@ from .config import glymur_config OPENJP2, OPENJPEG = glymur_config() + def version(): """Wrapper for opj_version library routine.""" try: @@ -50,13 +51,6 @@ JPWL_MAX_NO_TILESPECS = 16 TRUE = 1 FALSE = 0 -#PROFILE = {'none': 0, # No profile -# 0: 1, # Profile 0 -# 1: 2, # Profile 1 -# 'part2': 0x8000, # At least one extension -# 'Cinema2K': 0x0003, # 2K cinema profile -# 'Cinema4K': 0x0004, # 4K cinema profile - # supported color spaces CLRSPC_UNKNOWN = -1 CLRSPC_UNSPECIFIED = 0 @@ -548,7 +542,6 @@ class ImageType(ctypes.Structure): return msg - class ImageComptParmType(ctypes.Structure): """Component parameters structure used by image_create function. @@ -958,7 +951,7 @@ def read_header(stream, codec): ARGTYPES = [STREAM_TYPE_P, CODEC_TYPE, ctypes.POINTER(ctypes.POINTER(ImageType))] OPENJP2.opj_read_header.argtypes = ARGTYPES - OPENJP2.opj_read_header.restype = check_error + OPENJP2.opj_read_header.restype = check_error imagep = ctypes.POINTER(ImageType)() OPENJP2.opj_read_header(stream, codec, ctypes.byref(imagep)) @@ -1317,6 +1310,7 @@ def _stream_create_default_file_stream_2p0(fptr, isa_read_stream): stream = OPENJP2.opj_stream_create_default_file_stream(fptr, read_stream) return stream + def _stream_create_default_file_stream_2p1(fname, isa_read_stream): """Wraps openjp2 library function opj_stream_create_default_vile_stream. @@ -1343,7 +1337,7 @@ def _stream_create_default_file_stream_2p1(fname, isa_read_stream): stream = OPENJP2.opj_stream_create_default_file_stream(file_argument, read_stream) return stream - + if re.match(r'''2.0''', version()): stream_create_default_file_stream = _stream_create_default_file_stream_2p0 else: diff --git a/glymur/lib/openjpeg.py b/glymur/lib/openjpeg.py index d1918ad..924cac5 100644 --- a/glymur/lib/openjpeg.py +++ b/glymur/lib/openjpeg.py @@ -59,8 +59,10 @@ class CommonStructType(ctypes.Structure): ("mj2_handle", ctypes.c_void_p)] -STREAM_READ = 0x0001 # The stream was opened for reading. -STREAM_WRITE = 0x0002 # The stream was opened for writing. +STREAM_READ = 0x0001 # The stream was opened for reading. +STREAM_WRITE = 0x0002 # The stream was opened for writing. + + class CioType(ctypes.Structure): """Byte input-output stream (CIO) @@ -91,70 +93,57 @@ class CompressionInfoType(CommonStructType): class PocType(ctypes.Structure): """Progression order changes.""" _fields_ = [("resno", ctypes.c_int), - # Resolution num start, Component num start, given by POC - ("compno0", ctypes.c_int), + # Resolution num start, Component num start, given by POC + ("compno0", ctypes.c_int), - # Layer num end,Resolution num end, Component num end, given by POC - ("layno1", ctypes.c_int), - ("resno1", ctypes.c_int), - ("compno1", ctypes.c_int), + # Layer num end,Resolution num end, Component num end, given + # by POC + ("layno1", ctypes.c_int), + ("resno1", ctypes.c_int), + ("compno1", ctypes.c_int), - # Layer num start,Precinct num start, Precinct num end - ("layno0", ctypes.c_int), - ("precno0", ctypes.c_int), - ("precno1", ctypes.c_int), + # Layer num start,Precinct num start, Precinct num end + ("layno0", ctypes.c_int), + ("precno0", ctypes.c_int), + ("precno1", ctypes.c_int), - # Progression order enum - # OPJ_PROG_ORDER prg1,prg; - ("prg1", ctypes.c_int), - ("prg", ctypes.c_int), + # Progression order enum + # OPJ_PROG_ORDER prg1,prg; + ("prg1", ctypes.c_int), + ("prg", ctypes.c_int), - # Progression order string - # char progorder[5]; - ("progorder", ctypes.c_char * 5), + # Progression order string + # char progorder[5]; + ("progorder", ctypes.c_char * 5), - # Tile number - # int tile; - ("tile", ctypes.c_int), + # Tile number + # int tile; + ("tile", ctypes.c_int), - # /** Start and end values for Tile width and height*/ - # int tx0,tx1,ty0,ty1; - ("tx0", ctypes.c_int), - ("tx1", ctypes.c_int), - ("ty0", ctypes.c_int), - ("ty1", ctypes.c_int), - - # /** Start value, initialised in pi_initialise_encode*/ - # int layS, resS, compS, prcS; - ("layS", ctypes.c_int), - ("resS", ctypes.c_int), - ("compS", ctypes.c_int), - ("prcS", ctypes.c_int), - - # /** End value, initialised in pi_initialise_encode */ - # int layE, resE, compE, prcE; - ("layE", ctypes.c_int), - ("resE", ctypes.c_int), - ("compE", ctypes.c_int), - ("prcE", ctypes.c_int), - - # Start and end values of Tile width and height, initialised in - # pi_initialise_encode int txS,txE,tyS,tyE,dx,dy; - ("txS", ctypes.c_int), - ("txE", ctypes.c_int), - ("tyS", ctypes.c_int), - ("tyE", ctypes.c_int), - ("dx", ctypes.c_int), - ("dy", ctypes.c_int), - - # Temporary values for Tile parts, initialised in pi_create_encode - # int lay_t, res_t, comp_t, prc_t,tx0_t,ty0_t; - ("lay_t", ctypes.c_int), - ("res_t", ctypes.c_int), - ("comp_t", ctypes.c_int), - ("prc_t", ctypes.c_int), - ("tx0_t", ctypes.c_int), - ("ty0_t", ctypes.c_int)] + ("tx0", ctypes.c_int), + ("tx1", ctypes.c_int), + ("ty0", ctypes.c_int), + ("ty1", ctypes.c_int), + ("layS", ctypes.c_int), + ("resS", ctypes.c_int), + ("compS", ctypes.c_int), + ("prcS", ctypes.c_int), + ("layE", ctypes.c_int), + ("resE", ctypes.c_int), + ("compE", ctypes.c_int), + ("prcE", ctypes.c_int), + ("txS", ctypes.c_int), + ("txE", ctypes.c_int), + ("tyS", ctypes.c_int), + ("tyE", ctypes.c_int), + ("dx", ctypes.c_int), + ("dy", ctypes.c_int), + ("lay_t", ctypes.c_int), + ("res_t", ctypes.c_int), + ("comp_t", ctypes.c_int), + ("prc_t", ctypes.c_int), + ("tx0_t", ctypes.c_int), + ("ty0_t", ctypes.c_int)] class CompressionParametersType(ctypes.Structure): @@ -375,48 +364,47 @@ class DecompressionParametersType(ctypes.Structure): class ImageComptParmType(ctypes.Structure): """Component parameters structure used by the opj_image_create function. """ - _fields_ = [ - # XRsiz: horizontal separation of a sample of ith component with - # respect to the reference grid - ("dx", ctypes.c_int), + _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 */ - ("dy", ctypes.c_int), + # YRsiz: vertical separation of a sample of ith component with + # respect to the reference grid */ + ("dy", ctypes.c_int), - # data width, height - ("w", ctypes.c_int), - ("h", ctypes.c_int), + # data width, height + ("w", ctypes.c_int), + ("h", ctypes.c_int), - # x component offset compared to the whole image - # y component offset compared to the whole image - ("x0", ctypes.c_int), - ("y0", ctypes.c_int), + # x component offset compared to the whole image + # y component offset compared to the whole image + ("x0", ctypes.c_int), + ("y0", ctypes.c_int), - # precision - ('prec', ctypes.c_int), + # precision + ('prec', ctypes.c_int), - # image depth in bits - ('bpp', ctypes.c_int), + # image depth in bits + ('bpp', ctypes.c_int), - # signed (1) / unsigned (0) - ('sgnd', ctypes.c_int)] + # signed (1) / unsigned (0) + ('sgnd', ctypes.c_int)] class ImageCompType(ctypes.Structure): """Defines a single image component. """ _fields_ = [("dx", ctypes.c_int), - ("dy", ctypes.c_int), - ("w", ctypes.c_int), - ("h", ctypes.c_int), - ("x0", ctypes.c_int), - ("y0", ctypes.c_int), - ("prec", ctypes.c_int), - ("bpp", ctypes.c_int), - ("sgnd", ctypes.c_int), - ("resno_decoded", ctypes.c_int), - ("factor", ctypes.c_int), - ("data", ctypes.POINTER(ctypes.c_int))] + ("dy", ctypes.c_int), + ("w", ctypes.c_int), + ("h", ctypes.c_int), + ("x0", ctypes.c_int), + ("y0", ctypes.c_int), + ("prec", ctypes.c_int), + ("bpp", ctypes.c_int), + ("sgnd", ctypes.c_int), + ("resno_decoded", ctypes.c_int), + ("factor", ctypes.c_int), + ("data", ctypes.POINTER(ctypes.c_int))] class ImageType(ctypes.Structure): @@ -468,6 +456,7 @@ def cio_tell(cio): pos = OPENJPEG.cio_tell(cio) return pos + def create_compress(fmt): """Wrapper for openjpeg library function opj_create_compress. @@ -585,9 +574,8 @@ def image_cmptparm_t_from_np(np_image): def image_create(cmptparms, cspace): """Wrapper for openjpeg library function opj_image_create. """ - OPENJPEG.opj_image_create.argtypes = [ctypes.c_int, - ctypes.POINTER(ImageComptParmType), - ctypes.c_int] + lst = [ctypes.c_int, ctypes.POINTER(ImageComptParmType), ctypes.c_int] + OPENJPEG.opj_image_create.argtypes = lst OPENJPEG.opj_image_create.restype = ctypes.POINTER(ImageType) image = OPENJPEG.opj_image_create(len(cmptparms), cmptparms, cspace) From 4527c774fad978b0105209783df7eb0f034de5b6 Mon Sep 17 00:00:00 2001 From: John Evans Date: Sun, 23 Nov 2014 22:20:15 -0500 Subject: [PATCH 33/57] Failures on windows are due to named temp file issue, closes #306 --- glymur/test/test_jp2box_uuid.py | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) diff --git a/glymur/test/test_jp2box_uuid.py b/glymur/test/test_jp2box_uuid.py index 8ec35a2..0e6619a 100644 --- a/glymur/test/test_jp2box_uuid.py +++ b/glymur/test/test_jp2box_uuid.py @@ -35,8 +35,10 @@ else: import lxml.etree -from .fixtures import HAS_PYTHON_XMP_TOOLKIT, OPJ_DATA_ROOT -from .fixtures import WARNING_INFRASTRUCTURE_ISSUE, WARNING_INFRASTRUCTURE_MSG +from .fixtures import (HAS_PYTHON_XMP_TOOLKIT, OPJ_DATA_ROOT, + WARNING_INFRASTRUCTURE_ISSUE, + WARNING_INFRASTRUCTURE_MSG, + WINDOWS_TMP_FILE_MSG) if HAS_PYTHON_XMP_TOOLKIT: from libxmp import XMPMeta @@ -46,7 +48,7 @@ from glymur import Jp2k from .fixtures import OPJ_DATA_ROOT, opj_data_file, SimpleRDF -@unittest.skipIf(os.name == "nt", "Unexplained failure on windows") +@unittest.skipIf(os.name == "nt", WINDOWS_TMP_FILE_MSG) class TestSuite(unittest.TestCase): """Tests for XMP, Exif UUIDs.""" @@ -102,7 +104,7 @@ class TestSuite(unittest.TestCase): self.assertEqual(jp2.box[-1].data['Make'], "HTC") @unittest.skipIf(WARNING_INFRASTRUCTURE_ISSUE, WARNING_INFRASTRUCTURE_MSG) -@unittest.skipIf(os.name == "nt", "Unexplained failure on windows") +@unittest.skipIf(os.name == "nt", WINDOWS_TMP_FILE_MSG) class TestSuiteWarns(unittest.TestCase): """Tests for XMP, Exif UUIDs, issues warnings.""" @@ -191,6 +193,3 @@ class TestSuiteWarns(unittest.TestCase): jp2 = glymur.Jp2k(tfile.name) self.assertEqual(jp2.box[-1].box_id, 'uuid') - -if __name__ == "__main__": - unittest.main() From 02ff73078426b152a43e294c3b0a89f191618212 Mon Sep 17 00:00:00 2001 From: jevans Date: Mon, 22 Dec 2014 23:20:48 -0500 Subject: [PATCH 34/57] pep8 work --- glymur/lib/__init__.py | 2 + glymur/lib/config.py | 44 +- glymur/lib/openjp2.py | 40 -- glymur/lib/openjpeg.py | 50 +- glymur/test/fixtures.py | 28 +- glymur/test/test_callbacks.py | 5 +- glymur/test/test_config.py | 47 +- glymur/test/test_glymur_warnings.py | 21 +- glymur/test/test_icc.py | 2 - glymur/test/test_jp2box.py | 64 ++- glymur/test/test_jp2box_jpx.py | 11 +- glymur/test/test_jp2box_uuid.py | 24 +- glymur/test/test_jp2box_xml.py | 22 +- glymur/test/test_jp2k.py | 243 +++----- glymur/test/test_opj_suite.py | 31 +- glymur/test/test_opj_suite_dump.py | 838 ++++++++++++++++------------ glymur/test/test_opj_suite_neg.py | 23 +- glymur/test/test_opj_suite_write.py | 203 ++++--- glymur/test/test_printing.py | 52 +- 19 files changed, 823 insertions(+), 927 deletions(-) diff --git a/glymur/lib/__init__.py b/glymur/lib/__init__.py index a283f7f..ddce813 100644 --- a/glymur/lib/__init__.py +++ b/glymur/lib/__init__.py @@ -2,3 +2,5 @@ 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 3aca5aa..a639b38 100644 --- a/glymur/lib/config.py +++ b/glymur/lib/config.py @@ -19,18 +19,21 @@ 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,8 +58,9 @@ 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) @@ -79,13 +83,15 @@ 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: @@ -94,10 +100,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 be ' - msg += 'loaded.' - warnings.warn(msg.format(path), UserWarning) - opj_lib = None + msg = 'The library specified by configuration file at {0} could not ' + msg += 'be loaded.' + warnings.warn(msg.format(path), UserWarning) + opj_lib = None return opj_lib @@ -130,6 +136,7 @@ def read_config_file(libname): path = None return path + def glymur_config(): """ Try to ascertain locations of openjp2, openjpeg libraries. @@ -147,6 +154,7 @@ 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 24122b9..d398fb2 100644 --- a/glymur/lib/openjp2.py +++ b/glymur/lib/openjp2.py @@ -410,7 +410,6 @@ 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 = [] @@ -740,28 +739,6 @@ 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 @@ -792,23 +769,6 @@ 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 924cac5..602f3b9 100644 --- a/glymur/lib/openjpeg.py +++ b/glymur/lib/openjpeg.py @@ -6,8 +6,6 @@ import ctypes import sys -import numpy as np - from .config import glymur_config _, OPENJPEG = glymur_config() @@ -364,9 +362,9 @@ class DecompressionParametersType(ctypes.Structure): class ImageComptParmType(ctypes.Structure): """Component parameters structure used by the opj_image_create function. """ - _fields_ = [# XRsiz: horizontal separation of a sample of ith component + _fields_ = [("dx", ctypes.c_int), + # 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 */ @@ -527,50 +525,6 @@ 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/test/fixtures.py b/glymur/test/fixtures.py index 113a47b..5666514 100644 --- a/glymur/test/fixtures.py +++ b/glymur/test/fixtures.py @@ -37,6 +37,7 @@ 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. @@ -101,8 +102,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): @@ -125,8 +126,9 @@ 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): @@ -153,7 +155,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. @@ -183,7 +185,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 @@ -211,7 +213,7 @@ def _indent(textstr): String to be indented. indent_level : str Number of spaces of indentation to add. - + Returns ------- indented_string : str @@ -544,7 +546,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) @@ -600,7 +602,6 @@ 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 +614,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 +670,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) @@ -692,7 +693,7 @@ 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 + Brand: jp2 Compatibility: ['jp2 '] JP2 Header Box (jp2h) @ (32, 45) Image Header Box (ihdr) @ (40, 22) @@ -743,7 +744,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) @@ -908,4 +909,3 @@ 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 849d987..269a816 100644 --- a/glymur/test/test_callbacks.py +++ b/glymur/test/test_callbacks.py @@ -25,6 +25,7 @@ import glymur from .fixtures import WARNING_INFRASTRUCTURE_ISSUE, WARNING_INFRASTRUCTURE_MSG + class TestCallbacks(unittest.TestCase): """Test suite for callbacks.""" @@ -46,7 +47,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: - j = glymur.Jp2k(tfile.name, data=tiledata, verbose=True) + glymur.Jp2k(tfile.name, data=tiledata, verbose=True) actual = fake_out.getvalue().strip() expected = '[INFO] tile number 1 / 1' self.assertEqual(actual, expected) @@ -60,7 +61,7 @@ class TestCallbacks(unittest.TestCase): tiledata = j[:] with tempfile.NamedTemporaryFile(suffix='.jp2') as tfile: with patch('sys.stdout', new=StringIO()) as fake_out: - jp2 = glymur.Jp2k(tfile.name, data=tiledata, verbose=True) + glymur.Jp2k(tfile.name, data=tiledata, verbose=True) actual = fake_out.getvalue().strip() expected = '[INFO] tile number 1 / 1' self.assertEqual(actual, expected) diff --git a/glymur/test/test_config.py b/glymur/test/test_config.py index feb3235..28a41cc 100644 --- a/glymur/test/test_config.py +++ b/glymur/test/test_config.py @@ -10,7 +10,7 @@ OPENJP2 may be present in some form or other. # unittest.mock only in Python 3.3 (python2.7/pylint import issue) # pylint: disable=E0611,F0401 -import contextlib +import contextlib import ctypes import imp import os @@ -26,41 +26,42 @@ 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, @@ -130,7 +131,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 a library from being loaded by using None.""" + """Verify that we can stop library from being loaded by using None.""" with tempfile.TemporaryDirectory() as tdir: configdir = os.path.join(tdir, 'glymur') os.mkdir(configdir) @@ -140,7 +141,9 @@ class TestSuite(unittest.TestCase): # openjpeg instead. fptr.write('[library]\n') fptr.write('openjp2: None\n') - fptr.write('openjpeg: {0}\n'.format(glymur.lib.openjp2.OPENJPEG._name)) + msg = 'openjpeg: {0}\n' + msg = msg.format(glymur.lib.openjp2.OPENJPEG._name) + fptr.write(msg) fptr.flush() with patch.dict('os.environ', {'XDG_CONFIG_HOME': tdir}): imp.reload(glymur.lib.openjp2) @@ -149,18 +152,17 @@ 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 easily found before this test can work.") + @unittest.skipIf(openjpeg_not_found_by_ctypes(), + "OpenJPEG must be 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 being empty. + # configuration file not being there imp.reload(glymur.lib.openjpeg) self.assertIsNotNone(glymur.lib.openjp2.OPENJPEG) @@ -178,4 +180,3 @@ 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 b8e5c8b..fa0c832 100644 --- a/glymur/test/test_glymur_warnings.py +++ b/glymur/test/test_glymur_warnings.py @@ -5,22 +5,19 @@ 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) @@ -53,12 +50,11 @@ class TestWarnings(unittest.TestCase): """ relpath = 'input/nonregression/issue188_beach_64bitsbox.jp2' jfile = opj_data_file(relpath) - regex = re.compile(r"""Unrecognized\sbox\s\(b'XML\s'\)\sencountered.""", - re.VERBOSE) + pattern = r"""Unrecognized\sbox\s\(b'XML\s'\)\sencountered.""" + regex = re.compile(pattern, re.VERBOSE) with self.assertWarnsRegex(UserWarning, regex): Jp2k(jfile) - def test_NR_gdal_fuzzer_unchecked_numresolutions_dump(self): """ Has an invalid number of resolutions. @@ -119,7 +115,7 @@ class TestWarnings(unittest.TestCase): \(\d+\)''', re.VERBOSE) with self.assertWarnsRegex(UserWarning, regex): - jp2 = Jp2k(jfile) + Jp2k(jfile) def test_NR_broken2_jp2_dump(self): """ @@ -127,7 +123,7 @@ class TestWarnings(unittest.TestCase): """ 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}"''', + \d+\sin\scodestream:\s*"0x[a-fA-F0-9]{4}"''', re.VERBOSE) with self.assertWarnsRegex(UserWarning, regex): Jp2k(jfile) @@ -152,7 +148,8 @@ class TestWarnings(unittest.TestCase): def test_tile_height_is_zero(self): """Zero tile height should not cause an exception.""" - filename = opj_data_file('input/nonregression/2539.pdf.SIGFPE.706.1712.jp2') + filename = 'input/nonregression/2539.pdf.SIGFPE.706.1712.jp2' + filename = opj_data_file(filename) with self.assertWarnsRegex(UserWarning, 'Invalid tile dimensions'): Jp2k(filename) @@ -177,9 +174,9 @@ class TestWarnings(unittest.TestCase): read_buffer = ifile.read() tfile.write(read_buffer) tfile.flush() - + with self.assertWarnsRegex(UserWarning, 'Unrecognized marker'): - codestream = Jp2k(tfile.name).get_codestream() + Jp2k(tfile.name).get_codestream() if __name__ == "__main__": diff --git a/glymur/test/test_icc.py b/glymur/test/test_icc.py index c6b63e8..90ffc11 100644 --- a/glymur/test/test_icc.py +++ b/glymur/test/test_icc.py @@ -6,8 +6,6 @@ ICC profile tests. # pylint: disable=R0904 import datetime -import os -import sys import unittest import numpy as np diff --git a/glymur/test/test_jp2box.py b/glymur/test/test_jp2box.py index 28ae4fe..9843b94 100644 --- a/glymur/test/test_jp2box.py +++ b/glymur/test/test_jp2box.py @@ -35,10 +35,10 @@ 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 -) +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.""" @@ -48,13 +48,15 @@ def load_tests(loader, tests, ignore): 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.""" @@ -70,7 +72,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.""" @@ -92,7 +94,7 @@ class TestDataEntryURL(unittest.TestCase): self.assertEqual(jp22.box[4].url, url) def test_null_termination(self): - """I.9.3.2 specifies that the location field must be null terminated.""" + """I.9.3.2 specifies that location field must be null terminated.""" jp2 = Jp2k(self.jp2file) url = 'http://glymur.readthedocs.org' @@ -103,12 +105,15 @@ 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) @@ -128,18 +133,18 @@ class TestChannelDefinition(unittest.TestCase): data = j2k[:] # Write the first component back out to file. with tempfile.NamedTemporaryFile(suffix=".j2k", delete=False) as tfile: - grey_j2k = Jp2k(tfile.name, data=data[:, :, 0]) + 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: - grey_j2k = Jp2k(tfile.name, data=data[:, :, 0:1]) + 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) - rgba_jp2 = Jp2k(tfile.name, data=data4) + Jp2k(tfile.name, data=data4) cls.four_planes = tfile.name @classmethod @@ -392,7 +397,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): @@ -402,7 +407,8 @@ 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.""" @@ -525,8 +531,8 @@ class TestPaletteBox(unittest.TestCase): bps = (8, 8, 8) signed = (False, False) with self.assertWarns(UserWarning): - pclr = glymur.jp2box.PaletteBox(palette, bits_per_component=bps, - signed=signed) + glymur.jp2box.PaletteBox(palette, bits_per_component=bps, + signed=signed) @unittest.skipIf(WARNING_INFRASTRUCTURE_ISSUE, WARNING_INFRASTRUCTURE_MSG) def test_mismatched_signed_palette(self): @@ -535,8 +541,8 @@ class TestPaletteBox(unittest.TestCase): bps = (8, 8, 8, 8) signed = (False, False, False, False) with self.assertWarns(UserWarning): - pclr = glymur.jp2box.PaletteBox(palette, bits_per_component=bps, - signed=signed) + glymur.jp2box.PaletteBox(palette, bits_per_component=bps, + signed=signed) def test_writing_with_different_bitdepths(self): """Bitdepths must be the same when writing.""" @@ -792,7 +798,7 @@ class TestWrap(unittest.TestCase): # list to trigger the error. boxes[2].box = [] with self.assertRaises(IOError): - jp22 = jp2.wrap(tfile.name, boxes=boxes) + jp2.wrap(tfile.name, boxes=boxes) def test_default_layout_with_boxes(self): """basic test for rewrapping a jp2 file, boxes specified""" @@ -857,8 +863,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) - signed = (True, False, True) - pclr = glymur.jp2box.PaletteBox(palette=palette, bits_per_component=bps, + pclr = glymur.jp2box.PaletteBox(palette=palette, + bits_per_component=bps, signed=(True, False, True)) j2k = Jp2k(self.j2kfile) @@ -970,7 +976,8 @@ 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] @@ -1026,7 +1033,7 @@ class TestJp2Boxes(unittest.TestCase): 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) @@ -1240,7 +1247,6 @@ 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)) @@ -1290,7 +1296,8 @@ 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=UUID\('00000000-0000-0000-0000-000000000000'\),\s""" + regexp += """the_uuid=""" + regexp += """UUID\('00000000-0000-0000-0000-000000000000'\),\s""" regexp += """raw_data=\)""" if sys.hexversion < 0x03000000: @@ -1307,7 +1314,8 @@ 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=UUID\('be7acfcb-97a9-42e8-9c71-999491e3afac'\),\s""" + regexp += """the_uuid=""" + regexp += """UUID\('be7acfcb-97a9-42e8-9c71-999491e3afac'\),\s""" regexp += """raw_data=\)""" if sys.hexversion < 0x03000000: diff --git a/glymur/test/test_jp2box_jpx.py b/glymur/test/test_jp2box_jpx.py index ce676f3..3ee4d31 100644 --- a/glymur/test/test_jp2box_jpx.py +++ b/glymur/test/test_jp2box_jpx.py @@ -6,7 +6,6 @@ Test suite specifically targeting JPX box layout. import ctypes import os import struct -import sys import tempfile import unittest @@ -20,6 +19,7 @@ from glymur.jp2box import ColourSpecificationBox from .fixtures import WARNING_INFRASTRUCTURE_ISSUE, WARNING_INFRASTRUCTURE_MSG + @unittest.skipIf(os.name == "nt", "Temporary file issue on window.") class TestJPXWrap(unittest.TestCase): """Test suite for wrapping JPX files.""" @@ -184,7 +184,7 @@ class TestJPXWrap(unittest.TestCase): with tempfile.NamedTemporaryFile(suffix=".jpx") as tfile: with self.assertRaises(IOError): - jpx = jp2.wrap(tfile.name, boxes=boxes) + jp2.wrap(tfile.name, boxes=boxes) def test_cgrp_neg(self): """Can't write a cgrp with anything but colr sub boxes""" @@ -204,7 +204,7 @@ class TestJPXWrap(unittest.TestCase): with tempfile.NamedTemporaryFile(suffix=".jpx") as tfile: with self.assertRaises(IOError): - jpx = jp2.wrap(tfile.name, boxes=boxes) + jp2.wrap(tfile.name, boxes=boxes) def test_ftbl(self): """Write a fragment table box.""" @@ -484,7 +484,7 @@ class TestJPX(unittest.TestCase): ftbl.write(tfile) def test_data_reference_requires_dtbl(self): - """The existance of a data reference box requires a ftbl box as well.""" + """The existance of data reference box requires a ftbl box as well.""" flag = 0 version = (0, 0, 0) url1 = 'file:////usr/local/bin' @@ -574,7 +574,7 @@ class TestJPX(unittest.TestCase): 131072, 65536, 32768, 16384, 8192] for j in range(len(standard_flags)): mask = (standard_masks[j] >> 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,7 +599,6 @@ 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 0e6619a..409e43b 100644 --- a/glymur/test/test_jp2box_uuid.py +++ b/glymur/test/test_jp2box_uuid.py @@ -11,7 +11,6 @@ # pylint: disable=R0904 import os -import re import shutil import struct import sys @@ -23,29 +22,15 @@ 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 (HAS_PYTHON_XMP_TOOLKIT, OPJ_DATA_ROOT, - WARNING_INFRASTRUCTURE_ISSUE, +from .fixtures import (WARNING_INFRASTRUCTURE_ISSUE, WARNING_INFRASTRUCTURE_MSG, WINDOWS_TMP_FILE_MSG) -if HAS_PYTHON_XMP_TOOLKIT: - from libxmp import XMPMeta - import glymur from glymur import Jp2k -from .fixtures import OPJ_DATA_ROOT, opj_data_file, SimpleRDF +from .fixtures import SimpleRDF @unittest.skipIf(os.name == "nt", WINDOWS_TMP_FILE_MSG) @@ -103,6 +88,7 @@ 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) class TestSuiteWarns(unittest.TestCase): @@ -113,7 +99,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: @@ -137,7 +123,7 @@ class TestSuiteWarns(unittest.TestCase): tfile.flush() with self.assertWarnsRegex(UserWarning, 'Unrecognized Exif tag'): - j = glymur.Jp2k(tfile.name) + glymur.Jp2k(tfile.name) def test_bad_tag_datatype(self): """Only certain datatypes are allowable""" diff --git a/glymur/test/test_jp2box_xml.py b/glymur/test/test_jp2box_xml.py index 45d02f1..84a63f3 100644 --- a/glymur/test/test_jp2box_xml.py +++ b/glymur/test/test_jp2box_xml.py @@ -17,20 +17,9 @@ Test suite specifically targeting JP2 box layout. 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 @@ -43,6 +32,7 @@ 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.""" @@ -167,7 +157,6 @@ class TestXML(unittest.TestCase): u'Россия') - class TestJp2kBadXmlFile(unittest.TestCase): """Test suite for bad XML box situations""" @@ -293,22 +282,19 @@ 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', - '26ccf3651020967f7778238ef5af08af.SIGFPE.d25.527.jp2')) + relname)) 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 edb19a1..cb3a9e7 100644 --- a/glymur/test/test_jp2k.py +++ b/glymur/test/test_jp2k.py @@ -13,7 +13,6 @@ Tests for general glymur functionality. import doctest import os import re -import shutil import struct import sys import tempfile @@ -45,6 +44,7 @@ if HAS_PYTHON_XMP_TOOLKIT: from .fixtures import OPJ_DATA_ROOT, opj_data_file from . import fixtures + # Doc tests should be run as well. def load_tests(loader, tests, ignore): # W0613: "loader" and "ignore" are necessary for the protocol @@ -77,6 +77,7 @@ 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") @@ -148,11 +149,6 @@ 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. @@ -169,8 +165,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): @@ -184,12 +180,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) @@ -226,7 +222,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), @@ -235,7 +231,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). """ @@ -243,6 +239,7 @@ 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.""" @@ -319,7 +316,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 with OpenJPEG {0}".format(openjpeg_version)) + "Not supported on 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): @@ -638,7 +635,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.""" @@ -654,8 +651,9 @@ 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)''', @@ -674,6 +672,7 @@ 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)) @@ -693,30 +692,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): - j = Jp2k(tfile.name, data=data, - cbsize=(16, 16), psizes=[(16, 16)]) + 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): - j = Jp2k(tfile.name, data=data, - cbsize=(16, 16), psizes=[(48, 48)]) + 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): - j = Jp2k(tfile.name, data=data) + 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): - j = Jp2k(tfile.name, data=data) + 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""" @@ -726,7 +725,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): - j = Jp2k(tfile.name, data=data) + 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 @@ -745,31 +744,31 @@ class TestJp2k_write(unittest.TestCase): """OpenJP2 only allows 2D or 3D images.""" with tempfile.NamedTemporaryFile(suffix='.j2k') as tfile: with self.assertRaises(IOError): - j = Jp2k(tfile.name, - data=np.zeros((128, 128, 2, 2), dtype=np.uint8)) + 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): - j = Jp2k(tfile.name, - data=np.zeros((128, 128, 2), dtype=np.uint8), - colorspace='rgb') + 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): - j = Jp2k(tfile.name, - data=np.zeros((128, 128, 3), dtype=np.uint8), - colorspace='rgb') + 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): @@ -804,7 +803,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) - j = Jp2k(tfile.name, data=data, colorspace='ycc') + Jp2k(tfile.name, data=data, colorspace='ycc') def test_write_with_jp2_in_caps(self): """should be able to write with JP2 suffix.""" @@ -833,7 +832,7 @@ class TestJp2k_write(unittest.TestCase): expdata = j2k[:] with tempfile.NamedTemporaryFile(suffix='.jp2') as tfile: with self.assertRaises(IOError): - ofile = Jp2k(tfile.name, data=expdata[:, :, 0], mct=True) + Jp2k(tfile.name, data=expdata[:, :, 0], mct=True) def test_write_cprl(self): """Must be able to write a CPRL progression order file""" @@ -924,7 +923,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): - j = Jp2k(tfile.name, data=data, colorspace='cmyk') + Jp2k(tfile.name, data=data, colorspace='cmyk') @unittest.skipIf(os.name == "nt", fixtures.WINDOWS_TMP_FILE_MSG) def test_asoc_label_box(self): @@ -933,7 +932,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: - j = Jp2k(tfile.name, data=data) + Jp2k(tfile.name, data=data) with tempfile.NamedTemporaryFile(suffix='.jp2') as tfile2: @@ -1041,12 +1040,15 @@ 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): @@ -1064,22 +1066,23 @@ class TestParsing(unittest.TestCase): """Should not warn if RSIZ when parsing is turned off.""" filename = opj_data_file('input/nonregression/edf_c2_1002767.jp2') glymur.set_parseoptions(codestream=False) - j = Jp2k(filename) + Jp2k(filename) glymur.set_parseoptions(codestream=True) with self.assertWarnsRegex(UserWarning, 'Invalid profile'): - jp2 = Jp2k(filename) + Jp2k(filename) def test_main_header(self): - """Verify that the main header is not loaded when parsing turned off.""" + """Verify that the main header isn't 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._main_header) - main_header = jp2c.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, "OPJ_DATA_ROOT environment variable not set") @@ -1101,13 +1104,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): - jp2 = Jp2k(filename) + 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'): - jp2 = Jp2k(filename) + Jp2k(filename) def test_invalid_colorspace(self): """ @@ -1117,13 +1120,13 @@ class TestJp2kOpjDataRootWarnings(unittest.TestCase): """ filename = opj_data_file('input/nonregression/edf_c2_1103421.jp2') with self.assertWarns(UserWarning): - jp2 = Jp2k(filename) + 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): - jp2 = Jp2k(filename) + Jp2k(filename) @unittest.skipIf(OPJ_DATA_ROOT is None, @@ -1148,7 +1151,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""" @@ -1180,7 +1183,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""" @@ -1196,31 +1199,11 @@ 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): @@ -1274,7 +1257,6 @@ 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') @@ -1329,6 +1311,16 @@ 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.""" @@ -1348,112 +1340,3 @@ 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 028734d..f512dfd 100644 --- a/glymur/test/test_opj_suite.py +++ b/glymur/test/test_opj_suite.py @@ -38,12 +38,11 @@ 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) @@ -415,16 +414,17 @@ class TestSuiteWarns(MetadataBase): 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 @@ -436,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) @@ -726,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]) @@ -798,6 +798,7 @@ 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''', @@ -806,7 +807,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 ee1838b..6b198c1 100644 --- a/glymur/test/test_opj_suite_dump.py +++ b/glymur/test/test_opj_suite_dump.py @@ -36,14 +36,17 @@ 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 +from glymur.core import (RCME_ISO_8859_1, RCME_BINARY, SRGB, + GREYSCALE, RESTRICTED_ICC_PROFILE, + ENUMERATED_COLORSPACE) from glymur.jp2box import FileTypeBox -from .fixtures import ( - MetadataBase, OPJ_DATA_ROOT, - WARNING_INFRASTRUCTURE_ISSUE, WARNING_INFRASTRUCTURE_MSG, - mse, peak_tolerance, read_pgx, opj_data_file -) +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" @unittest.skipIf(OPJ_DATA_ROOT is None, @@ -82,10 +85,12 @@ class TestSuite(MetadataBase): 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 @@ -97,7 +102,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) @@ -121,9 +126,10 @@ 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) @@ -143,7 +149,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) @@ -154,9 +160,10 @@ 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 @@ -168,7 +175,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) @@ -178,7 +185,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) @@ -191,7 +198,8 @@ 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 @@ -217,9 +225,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) @@ -231,7 +240,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) @@ -263,11 +272,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, - "Creator: AV-J2K (c) 2000,2001 Algo Vision Technology".encode()) + pargs = (RCME_ISO_8859_1, comment1.encode()) self.verifyCMEsegment(c.segment[8], CMEsegment(*pargs)) pargs = (RCME_BINARY, c.segment[9].ccme) @@ -290,10 +299,12 @@ 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) @@ -305,7 +316,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, @@ -353,7 +364,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)) @@ -367,11 +378,12 @@ 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) @@ -383,7 +395,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) @@ -394,7 +406,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) @@ -404,7 +416,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) @@ -441,7 +453,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) @@ -460,11 +472,12 @@ 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) @@ -476,7 +489,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) @@ -535,7 +548,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) @@ -552,10 +565,12 @@ 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) @@ -567,7 +582,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) @@ -595,7 +610,6 @@ 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') @@ -605,10 +619,12 @@ 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) @@ -620,7 +636,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) @@ -631,7 +647,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) @@ -641,7 +657,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) @@ -651,7 +667,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) @@ -696,9 +712,10 @@ 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) @@ -710,7 +727,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) @@ -743,10 +760,12 @@ 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) @@ -758,7 +777,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) @@ -805,9 +824,10 @@ 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) @@ -819,7 +839,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)]) @@ -832,7 +852,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)) @@ -854,10 +874,11 @@ 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) @@ -869,7 +890,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) @@ -882,7 +903,8 @@ 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)) @@ -904,10 +926,12 @@ 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 @@ -918,7 +942,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) @@ -928,7 +952,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) @@ -969,7 +993,8 @@ 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,10 +1010,11 @@ 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) @@ -999,7 +1025,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) @@ -1025,10 +1051,11 @@ 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) @@ -1039,7 +1066,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) @@ -1072,11 +1099,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, - "Creator: AV-J2K (c) 2000,2001 Algo Vision Technology".encode()) + pargs = (RCME_ISO_8859_1, comment1.encode()) self.verifyCMEsegment(c.segment[8], CMEsegment(*pargs)) pargs = (RCME_BINARY, c.segment[9].ccme) @@ -1125,10 +1152,11 @@ 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) @@ -1139,7 +1167,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) @@ -1165,10 +1193,11 @@ 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 @@ -1179,7 +1208,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) @@ -1189,7 +1218,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) @@ -1201,7 +1230,8 @@ 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)) @@ -1223,10 +1253,12 @@ 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 @@ -1238,7 +1270,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, @@ -1285,7 +1317,8 @@ 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)) @@ -1305,11 +1338,12 @@ 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 @@ -1320,7 +1354,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) @@ -1330,7 +1364,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) @@ -1339,7 +1373,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) @@ -1375,7 +1409,8 @@ 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 @@ -1400,10 +1435,11 @@ 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 @@ -1414,7 +1450,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) @@ -1487,10 +1523,12 @@ 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 @@ -1501,7 +1539,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) @@ -1516,7 +1554,8 @@ 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. @@ -1543,10 +1582,11 @@ 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 @@ -1557,7 +1597,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) @@ -1573,7 +1613,8 @@ 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)) @@ -1604,10 +1645,11 @@ 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 @@ -1618,7 +1660,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)]) @@ -1628,7 +1670,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)]) @@ -1640,7 +1682,8 @@ 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)) @@ -1657,11 +1700,12 @@ 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 @@ -1672,7 +1716,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)) @@ -1694,7 +1738,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) @@ -1716,7 +1760,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) @@ -1761,10 +1805,12 @@ 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 @@ -1775,7 +1821,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, @@ -1794,10 +1840,11 @@ 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 @@ -1808,7 +1855,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) @@ -1823,10 +1870,11 @@ 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 @@ -1837,7 +1885,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) @@ -1860,10 +1908,11 @@ 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 @@ -1874,7 +1923,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) @@ -1897,10 +1946,11 @@ 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 @@ -1911,7 +1961,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) @@ -1940,10 +1990,11 @@ 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 @@ -1954,7 +2005,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) @@ -1981,10 +2032,11 @@ 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 @@ -1995,7 +2047,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) @@ -2017,10 +2069,12 @@ 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 @@ -2031,7 +2085,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) @@ -2054,10 +2108,11 @@ 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 @@ -2068,7 +2123,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) @@ -2101,17 +2156,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 @@ -2122,7 +2177,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) @@ -2142,10 +2197,12 @@ 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 @@ -2156,7 +2213,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) @@ -2174,10 +2231,12 @@ 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 +2247,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,10 +2265,12 @@ 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 @@ -2220,7 +2281,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) @@ -2242,10 +2303,12 @@ 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 @@ -2256,7 +2319,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,10 +2341,12 @@ 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 @@ -2292,7 +2357,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) @@ -2314,10 +2379,12 @@ 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 @@ -2328,7 +2395,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,10 +2421,12 @@ 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 @@ -2368,7 +2437,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) @@ -2394,10 +2463,12 @@ 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 @@ -2406,10 +2477,9 @@ 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)) # cblk + 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) @@ -2431,10 +2501,12 @@ 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 @@ -2443,10 +2515,9 @@ 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)) # cblk + 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) @@ -2468,10 +2539,12 @@ 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 @@ -2480,10 +2553,9 @@ 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)) # cblk + 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, @@ -2512,7 +2584,9 @@ 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 @@ -2521,9 +2595,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=glymur.core.SRGB, - approximation=1, precedence=2) + colr = glymur.jp2box.ColourSpecificationBox(colorspace=SRGB, + approximation=1, + precedence=2) self.verifyColourSpecificationBox(jp2.box[3].box[1], colr) # Jp2 Header @@ -2543,10 +2617,12 @@ class TestSuite(MetadataBase): 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 @@ -2555,10 +2631,9 @@ 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)) # cblk + 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(len(c.segment[2].spcod), 9) @@ -2581,19 +2656,22 @@ 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=glymur.core.SRGB, - approximation=1, precedence=2) + colr = glymur.jp2box.ColourSpecificationBox(colorspace=SRGB, + approximation=1, + precedence=2) self.verifyColourSpecificationBox(jp2.box[3].box[1], colr) c = jp2.box[4].main_header @@ -2603,10 +2681,12 @@ class TestSuite(MetadataBase): 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 @@ -2615,10 +2695,9 @@ 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)) # cblk + 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(len(c.segment[2].spcod), 9) @@ -2646,11 +2725,10 @@ 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=glymur.core.GREYSCALE) + colr = glymur.jp2box.ColourSpecificationBox(colorspace=GREYSCALE) self.verifyColourSpecificationBox(jp2.box[2].box[1], colr) # Jp2 Header @@ -2666,10 +2744,12 @@ class TestSuite(MetadataBase): 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 @@ -2681,7 +2761,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) @@ -2710,20 +2790,23 @@ 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) - colr = glymur.jp2box.ColourSpecificationBox( - colorspace=glymur.core.SRGB, - method=glymur.core.ENUMERATED_COLORSPACE, - approximation=1, precedence=2) + method = ENUMERATED_COLORSPACE + colr = glymur.jp2box.ColourSpecificationBox(colorspace=SRGB, + method=method, + approximation=1, + precedence=2) self.verifyColourSpecificationBox(jp2.box[3].box[1], colr) # Jp2 Header @@ -2744,10 +2827,12 @@ class TestSuite(MetadataBase): 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 @@ -2759,7 +2844,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) @@ -2796,10 +2881,12 @@ class TestSuite(MetadataBase): 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 @@ -2811,7 +2898,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) @@ -2847,7 +2934,7 @@ class TestSuiteWarns(MetadataBase): relpath = 'input/nonregression/issue188_beach_64bitsbox.jp2' jfile = opj_data_file(relpath) with self.assertWarns(UserWarning): - d = Jp2k(jfile)[:] + Jp2k(jfile)[:] self.assertTrue(True) def test_NR_broken4_jp2_dump(self): @@ -2882,7 +2969,7 @@ class TestSuiteWarns(MetadataBase): 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) + colr = glymur.jp2box.ColourSpecificationBox(colorspace=SRGB) self.verifyColourSpecificationBox(jp2.box[2].box[1], colr) c = jp2.box[3].main_header @@ -2892,10 +2979,12 @@ class TestSuiteWarns(MetadataBase): 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)) + '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)) @@ -2910,7 +2999,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) @@ -2950,7 +3039,7 @@ class TestSuiteWarns(MetadataBase): 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): @@ -2978,8 +3067,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=glymur.core.SRGB, - approximation=1) + colr = glymur.jp2box.ColourSpecificationBox(colorspace=SRGB, + approximation=1) self.verifyColourSpecificationBox(jp2.box[3].box[1], colr) # XML box @@ -3006,7 +3095,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 @@ -3036,9 +3125,8 @@ 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 @@ -3068,8 +3156,8 @@ class TestSuiteWarns(MetadataBase): ihdr = glymur.jp2box.ImageHeaderBox(512, 768) self.verifyImageHeaderBox(jp2.box[2].box[0], ihdr) - colr = glymur.jp2box.ColourSpecificationBox( - colorspace=glymur.core.GREYSCALE, approximation=1) + colr = glymur.jp2box.ColourSpecificationBox(colorspace=GREYSCALE, + approximation=1) self.verifyColourSpecificationBox(jp2.box[2].box[1], colr) def test_NR_file5_dump(self): @@ -3091,16 +3179,18 @@ 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) - colr = glymur.jp2box.ColourSpecificationBox( - method=glymur.core.RESTRICTED_ICC_PROFILE, - approximation=1, icc_profile=bytes([0] * 546)) + method = RESTRICTED_ICC_PROFILE + icc_profile = bytes([0] * 546) + colr = glymur.jp2box.ColourSpecificationBox(method=method, + approximation=1, + icc_profile=icc_profile) self.verifyColourSpecificationBox(jp2.box[3].box[1], colr) self.assertEqual(jp2.box[3].box[1].icc_profile['Size'], 546) @@ -3121,10 +3211,10 @@ class TestSuiteWarns(MetadataBase): ihdr = glymur.jp2box.ImageHeaderBox(512, 768, bits_per_component=12) self.verifyImageHeaderBox(jp2.box[2].box[0], ihdr) - colr = glymur.jp2box.ColourSpecificationBox( - colorspace=glymur.core.GREYSCALE, - method=glymur.core.ENUMERATED_COLORSPACE, - approximation=1) + method = ENUMERATED_COLORSPACE + colr = glymur.jp2box.ColourSpecificationBox(colorspace=GREYSCALE, + method=method, + approximation=1) self.verifyColourSpecificationBox(jp2.box[2].box[1], colr) def test_NR_file7_dump(self): @@ -3150,12 +3240,13 @@ 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) - colr = glymur.jp2box.ColourSpecificationBox( - method=glymur.core.RESTRICTED_ICC_PROFILE, - approximation=1) + method = RESTRICTED_ICC_PROFILE + colr = glymur.jp2box.ColourSpecificationBox(method=method, + approximation=1) self.verifyColourSpecificationBox(jp2.box[3].box[1], colr) self.assertEqual(jp2.box[3].box[1].icc_profile['Size'], 13332) @@ -3179,9 +3270,9 @@ class TestSuiteWarns(MetadataBase): ihdr = glymur.jp2box.ImageHeaderBox(400, 700) self.verifyImageHeaderBox(jp2.box[2].box[0], ihdr) - colr = glymur.jp2box.ColourSpecificationBox( - method=glymur.core.RESTRICTED_ICC_PROFILE, - approximation=1) + method = RESTRICTED_ICC_PROFILE + colr = glymur.jp2box.ColourSpecificationBox(method=method, + approximation=1) self.verifyColourSpecificationBox(jp2.box[2].box[1], colr) self.assertEqual(jp2.box[2].box[1].icc_profile['Size'], 414) @@ -3234,16 +3325,15 @@ 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=glymur.core.SRGB, - approximation=1) + colr = glymur.jp2box.ColourSpecificationBox(colorspace=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] @@ -3256,10 +3346,12 @@ 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) - colr = glymur.jp2box.ColourSpecificationBox(colorspace=glymur.core.SRGB) + cspace = glymur.core.SRGB + colr = glymur.jp2box.ColourSpecificationBox(colorspace=cspace) self.verifyColourSpecificationBox(jp2.box[2].box[1], colr) # Skip the 4th box, it is uknown. @@ -3271,10 +3363,12 @@ class TestSuiteWarns(MetadataBase): 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 @@ -3286,7 +3380,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) @@ -3329,10 +3423,12 @@ class TestSuiteWarns(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 @@ -3344,7 +3440,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) @@ -3390,10 +3486,12 @@ class TestSuiteWarns(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 @@ -3405,7 +3503,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 c7e31e5..1d3ec6e 100644 --- a/glymur/test/test_opj_suite_neg.py +++ b/glymur/test/test_opj_suite_neg.py @@ -10,7 +10,6 @@ seem like logical negative tests to add. import os import re -import sys import tempfile import unittest @@ -88,7 +87,6 @@ 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): @@ -98,8 +96,7 @@ class TestSuiteNegativeWrite(unittest.TestCase): data = skimage.io.imread(infile) with tempfile.NamedTemporaryFile(suffix='.j2k') as tfile: with self.assertRaises(IOError): - j = Jp2k(tfile.name, data=data, cinema2k=36) - + Jp2k(tfile.name, data=data, cinema2k=36) @unittest.skipIf(NO_READ_BACKEND, NO_READ_BACKEND_MSG) def test_psnr_with_cratios(self): @@ -109,8 +106,8 @@ class TestSuiteNegativeWrite(unittest.TestCase): data = read_image(infile) with tempfile.NamedTemporaryFile(suffix='.j2k') as tfile: with self.assertRaises(IOError): - j = Jp2k(tfile.name, - data=data, psnr=[30, 35, 40], cratios=[2, 3, 4]) + 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""" @@ -120,13 +117,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): - j = Jp2k(tfile.name, data=data, cbsize=(256, 256)) + Jp2k(tfile.name, data=data, cbsize=(256, 256)) # opj_compress doesn't allow either dimension to be less than 4. with self.assertRaises(IOError): - j = Jp2k(tfile.name, data=data, cbsize=(2048, 2)) + Jp2k(tfile.name, data=data, cbsize=(2048, 2)) with self.assertRaises(IOError): - j = Jp2k(tfile.name, data=data, cbsize=(2, 2048)) + Jp2k(tfile.name, data=data, cbsize=(2, 2048)) def test_precinct_size_not_p2(self): """precinct sizes should be powers of two.""" @@ -134,7 +131,7 @@ class TestSuiteNegativeWrite(unittest.TestCase): data = ifile[::4, ::4] with tempfile.NamedTemporaryFile(suffix='.jp2') as tfile: with self.assertRaises(IOError): - ofile = Jp2k(tfile.name, data=data, psizes=[(13, 13)]) + 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.""" @@ -142,7 +139,7 @@ class TestSuiteNegativeWrite(unittest.TestCase): data = ifile[::4, ::4] with tempfile.NamedTemporaryFile(suffix='.jp2') as tfile: with self.assertRaises(IOError): - ofile = Jp2k(tfile.name, data=data, cbsize=(13, 12)) + 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.""" @@ -150,6 +147,4 @@ class TestSuiteNegativeWrite(unittest.TestCase): data = ifile[::4, ::4] with tempfile.NamedTemporaryFile(suffix='.jp2') as tfile: with self.assertRaises(IOError): - ofile = Jp2k(tfile.name, - data=data, cbsize=(64, 64), psizes=[(64, 64)]) - + 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 ecb7a7d..7f0fd4b 100644 --- a/glymur/test/test_opj_suite_write.py +++ b/glymur/test/test_opj_suite_write.py @@ -34,6 +34,7 @@ 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): @@ -44,14 +45,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)) # cblksz + self.assertEqual(tuple(cod_segment.code_block_size), (32, 32)) 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]) @@ -59,9 +60,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]) @@ -88,8 +89,8 @@ class WriteCinema(CinemaBase): data = skimage.io.imread(infile) with tempfile.NamedTemporaryFile(suffix='.j2k') as tfile: with self.assertRaises(IOError): - j = Jp2k(tfile.name, data=data, - cinema2k=48, cratios=[200, 100, 50]) + 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.""" @@ -98,8 +99,8 @@ class WriteCinema(CinemaBase): data = skimage.io.imread(infile) with tempfile.NamedTemporaryFile(suffix='.j2k') as tfile: with self.assertRaises(IOError): - j = Jp2k(tfile.name, data=data, - cinema4k=True, cratios=[200, 100, 50]) + Jp2k(tfile.name, data=data, + cinema4k=True, cratios=[200, 100, 50]) @unittest.skipIf(WARNING_INFRASTRUCTURE_ISSUE, WARNING_INFRASTRUCTURE_MSG) @@ -135,7 +136,8 @@ 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() @@ -146,7 +148,8 @@ 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() @@ -157,7 +160,8 @@ 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,7 +172,8 @@ 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) @@ -216,7 +221,7 @@ class TestNegative2pointzero(unittest.TestCase): with patch('glymur.version.openjpeg_version', new=version): with tempfile.NamedTemporaryFile(suffix='.j2k') as tfile: with self.assertRaises(IOError): - j = Jp2k(tfile.name, data=data, cinema2k=48) + Jp2k(tfile.name, data=data, cinema2k=48) @unittest.skipIf(re.match(r'''1.[0-4]''', openjpeg_version) is not None, @@ -248,7 +253,6 @@ 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,10 +264,11 @@ 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 @@ -275,7 +280,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) @@ -291,10 +296,11 @@ 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 @@ -306,7 +312,8 @@ 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) @@ -316,18 +323,19 @@ 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 @@ -339,7 +347,8 @@ 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, @@ -352,20 +361,21 @@ 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], + tilesize=(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 @@ -377,7 +387,8 @@ 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, @@ -393,10 +404,11 @@ class TestSuiteWrite(fixtures.MetadataBase): 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 @@ -408,7 +420,8 @@ 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) @@ -423,10 +436,11 @@ 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 @@ -438,7 +452,8 @@ 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) @@ -458,10 +473,11 @@ 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 @@ -471,9 +487,10 @@ 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) @@ -488,15 +505,16 @@ 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 @@ -508,7 +526,8 @@ 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) @@ -523,10 +542,11 @@ 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 @@ -538,7 +558,8 @@ 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) @@ -553,10 +574,11 @@ 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 @@ -568,7 +590,8 @@ 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) @@ -578,7 +601,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']) @@ -616,10 +639,11 @@ class TestSuiteWrite(fixtures.MetadataBase): 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 @@ -631,7 +655,8 @@ 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) @@ -648,10 +673,11 @@ 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 @@ -663,7 +689,8 @@ 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 5eedfe5..8b7b194 100644 --- a/glymur/test/test_printing.py +++ b/glymur/test/test_printing.py @@ -32,11 +32,12 @@ 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): @@ -52,23 +53,11 @@ class TestPrinting(unittest.TestCase): def tearDown(self): 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) - actual = fake_out.getvalue().strip() + fake_out.getvalue().strip() self.assertTrue(True) @@ -78,7 +67,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) @@ -107,7 +96,8 @@ 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""" @@ -115,9 +105,8 @@ 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: + j = glymur.Jp2k(tfile.name, data=data) # Offset of the codestream is where we start. wbuffer = tfile.read(77) @@ -419,7 +408,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 an XMLBox with utf-8 encoding (cyrrillic).""" + """Should be able to print XMLBox with utf-8 encoding (cyrrillic).""" # Seems to be inconsistencies between different versions of python2.x # as to what gets printed. # @@ -437,7 +426,8 @@ 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)", " Россия"] @@ -613,12 +603,14 @@ 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.") @@ -826,6 +818,7 @@ 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.") @@ -852,7 +845,7 @@ class TestPrintingOpjDataRootWarns(unittest.TestCase): filename = opj_data_file('input/nonregression/edf_c2_1103421.jp2') with self.assertWarns(UserWarning): jp2 = Jp2k(filename) - with patch('sys.stdout', new=StringIO()) as fake_out: + with patch('sys.stdout', new=StringIO()): print(jp2) def test_bad_rsiz(self): @@ -860,7 +853,7 @@ class TestPrintingOpjDataRootWarns(unittest.TestCase): filename = opj_data_file('input/nonregression/edf_c2_1002767.jp2') with self.assertWarns(UserWarning): j = Jp2k(filename) - with patch('sys.stdout', new=StringIO()) as fake_out: + with patch('sys.stdout', new=StringIO()): print(j) def test_bad_wavelet_transform(self): @@ -868,7 +861,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()) as fake_out: + with patch('sys.stdout', new=StringIO()): print(jp2) def test_invalid_progression_order(self): @@ -1029,7 +1022,7 @@ class TestPrintingOpjDataRootWarns(unittest.TestCase): 'issue171.jp2')) with self.assertWarns(UserWarning): jp2 = Jp2k(filename) - with patch('sys.stdout', new=StringIO()) as fake_out: + with patch('sys.stdout', new=StringIO()): # No need to verify, it's enough that we don't error out. print(jp2) @@ -1112,4 +1105,3 @@ class TestJp2dump(unittest.TestCase): command_line.main() actual = fake_out.getvalue().strip() self.assertRegex(actual, "File: .*") - From 13cc6aa7e5a774a5428d5f9968197923790ee728 Mon Sep 17 00:00:00 2001 From: jevans Date: Mon, 22 Dec 2014 23:20:48 -0500 Subject: [PATCH 35/57] pep8 work --- glymur/lib/__init__.py | 2 + glymur/lib/config.py | 44 +- glymur/lib/openjp2.py | 40 -- glymur/lib/openjpeg.py | 50 +- glymur/test/fixtures.py | 22 +- glymur/test/test_callbacks.py | 5 +- glymur/test/test_config.py | 47 +- glymur/test/test_glymur_warnings.py | 21 +- glymur/test/test_icc.py | 2 - glymur/test/test_jp2box.py | 64 ++- glymur/test/test_jp2box_jpx.py | 11 +- glymur/test/test_jp2box_uuid.py | 24 +- glymur/test/test_jp2box_xml.py | 22 +- glymur/test/test_jp2k.py | 243 +++----- glymur/test/test_opj_suite.py | 31 +- glymur/test/test_opj_suite_dump.py | 838 ++++++++++++++++------------ glymur/test/test_opj_suite_neg.py | 23 +- glymur/test/test_opj_suite_write.py | 203 ++++--- glymur/test/test_printing.py | 55 +- 19 files changed, 822 insertions(+), 925 deletions(-) diff --git a/glymur/lib/__init__.py b/glymur/lib/__init__.py index a283f7f..ddce813 100644 --- a/glymur/lib/__init__.py +++ b/glymur/lib/__init__.py @@ -2,3 +2,5 @@ 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 3aca5aa..a639b38 100644 --- a/glymur/lib/config.py +++ b/glymur/lib/config.py @@ -19,18 +19,21 @@ 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,8 +58,9 @@ 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) @@ -79,13 +83,15 @@ 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: @@ -94,10 +100,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 be ' - msg += 'loaded.' - warnings.warn(msg.format(path), UserWarning) - opj_lib = None + msg = 'The library specified by configuration file at {0} could not ' + msg += 'be loaded.' + warnings.warn(msg.format(path), UserWarning) + opj_lib = None return opj_lib @@ -130,6 +136,7 @@ def read_config_file(libname): path = None return path + def glymur_config(): """ Try to ascertain locations of openjp2, openjpeg libraries. @@ -147,6 +154,7 @@ 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 24122b9..d398fb2 100644 --- a/glymur/lib/openjp2.py +++ b/glymur/lib/openjp2.py @@ -410,7 +410,6 @@ 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 = [] @@ -740,28 +739,6 @@ 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 @@ -792,23 +769,6 @@ 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 924cac5..602f3b9 100644 --- a/glymur/lib/openjpeg.py +++ b/glymur/lib/openjpeg.py @@ -6,8 +6,6 @@ import ctypes import sys -import numpy as np - from .config import glymur_config _, OPENJPEG = glymur_config() @@ -364,9 +362,9 @@ class DecompressionParametersType(ctypes.Structure): class ImageComptParmType(ctypes.Structure): """Component parameters structure used by the opj_image_create function. """ - _fields_ = [# XRsiz: horizontal separation of a sample of ith component + _fields_ = [("dx", ctypes.c_int), + # 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 */ @@ -527,50 +525,6 @@ 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/test/fixtures.py b/glymur/test/fixtures.py index 113a47b..cf78051 100644 --- a/glymur/test/fixtures.py +++ b/glymur/test/fixtures.py @@ -37,6 +37,7 @@ 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. @@ -101,8 +102,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): @@ -125,8 +126,9 @@ 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): @@ -153,7 +155,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. @@ -183,7 +185,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 @@ -211,7 +213,7 @@ def _indent(textstr): String to be indented. indent_level : str Number of spaces of indentation to add. - + Returns ------- indented_string : str @@ -600,7 +602,6 @@ 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 +614,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) @@ -743,7 +744,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) @@ -908,4 +909,3 @@ 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 849d987..269a816 100644 --- a/glymur/test/test_callbacks.py +++ b/glymur/test/test_callbacks.py @@ -25,6 +25,7 @@ import glymur from .fixtures import WARNING_INFRASTRUCTURE_ISSUE, WARNING_INFRASTRUCTURE_MSG + class TestCallbacks(unittest.TestCase): """Test suite for callbacks.""" @@ -46,7 +47,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: - j = glymur.Jp2k(tfile.name, data=tiledata, verbose=True) + glymur.Jp2k(tfile.name, data=tiledata, verbose=True) actual = fake_out.getvalue().strip() expected = '[INFO] tile number 1 / 1' self.assertEqual(actual, expected) @@ -60,7 +61,7 @@ class TestCallbacks(unittest.TestCase): tiledata = j[:] with tempfile.NamedTemporaryFile(suffix='.jp2') as tfile: with patch('sys.stdout', new=StringIO()) as fake_out: - jp2 = glymur.Jp2k(tfile.name, data=tiledata, verbose=True) + glymur.Jp2k(tfile.name, data=tiledata, verbose=True) actual = fake_out.getvalue().strip() expected = '[INFO] tile number 1 / 1' self.assertEqual(actual, expected) diff --git a/glymur/test/test_config.py b/glymur/test/test_config.py index feb3235..28a41cc 100644 --- a/glymur/test/test_config.py +++ b/glymur/test/test_config.py @@ -10,7 +10,7 @@ OPENJP2 may be present in some form or other. # unittest.mock only in Python 3.3 (python2.7/pylint import issue) # pylint: disable=E0611,F0401 -import contextlib +import contextlib import ctypes import imp import os @@ -26,41 +26,42 @@ 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, @@ -130,7 +131,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 a library from being loaded by using None.""" + """Verify that we can stop library from being loaded by using None.""" with tempfile.TemporaryDirectory() as tdir: configdir = os.path.join(tdir, 'glymur') os.mkdir(configdir) @@ -140,7 +141,9 @@ class TestSuite(unittest.TestCase): # openjpeg instead. fptr.write('[library]\n') fptr.write('openjp2: None\n') - fptr.write('openjpeg: {0}\n'.format(glymur.lib.openjp2.OPENJPEG._name)) + msg = 'openjpeg: {0}\n' + msg = msg.format(glymur.lib.openjp2.OPENJPEG._name) + fptr.write(msg) fptr.flush() with patch.dict('os.environ', {'XDG_CONFIG_HOME': tdir}): imp.reload(glymur.lib.openjp2) @@ -149,18 +152,17 @@ 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 easily found before this test can work.") + @unittest.skipIf(openjpeg_not_found_by_ctypes(), + "OpenJPEG must be 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 being empty. + # configuration file not being there imp.reload(glymur.lib.openjpeg) self.assertIsNotNone(glymur.lib.openjp2.OPENJPEG) @@ -178,4 +180,3 @@ 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 b8e5c8b..fa0c832 100644 --- a/glymur/test/test_glymur_warnings.py +++ b/glymur/test/test_glymur_warnings.py @@ -5,22 +5,19 @@ 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) @@ -53,12 +50,11 @@ class TestWarnings(unittest.TestCase): """ relpath = 'input/nonregression/issue188_beach_64bitsbox.jp2' jfile = opj_data_file(relpath) - regex = re.compile(r"""Unrecognized\sbox\s\(b'XML\s'\)\sencountered.""", - re.VERBOSE) + pattern = r"""Unrecognized\sbox\s\(b'XML\s'\)\sencountered.""" + regex = re.compile(pattern, re.VERBOSE) with self.assertWarnsRegex(UserWarning, regex): Jp2k(jfile) - def test_NR_gdal_fuzzer_unchecked_numresolutions_dump(self): """ Has an invalid number of resolutions. @@ -119,7 +115,7 @@ class TestWarnings(unittest.TestCase): \(\d+\)''', re.VERBOSE) with self.assertWarnsRegex(UserWarning, regex): - jp2 = Jp2k(jfile) + Jp2k(jfile) def test_NR_broken2_jp2_dump(self): """ @@ -127,7 +123,7 @@ class TestWarnings(unittest.TestCase): """ 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}"''', + \d+\sin\scodestream:\s*"0x[a-fA-F0-9]{4}"''', re.VERBOSE) with self.assertWarnsRegex(UserWarning, regex): Jp2k(jfile) @@ -152,7 +148,8 @@ class TestWarnings(unittest.TestCase): def test_tile_height_is_zero(self): """Zero tile height should not cause an exception.""" - filename = opj_data_file('input/nonregression/2539.pdf.SIGFPE.706.1712.jp2') + filename = 'input/nonregression/2539.pdf.SIGFPE.706.1712.jp2' + filename = opj_data_file(filename) with self.assertWarnsRegex(UserWarning, 'Invalid tile dimensions'): Jp2k(filename) @@ -177,9 +174,9 @@ class TestWarnings(unittest.TestCase): read_buffer = ifile.read() tfile.write(read_buffer) tfile.flush() - + with self.assertWarnsRegex(UserWarning, 'Unrecognized marker'): - codestream = Jp2k(tfile.name).get_codestream() + Jp2k(tfile.name).get_codestream() if __name__ == "__main__": diff --git a/glymur/test/test_icc.py b/glymur/test/test_icc.py index c6b63e8..90ffc11 100644 --- a/glymur/test/test_icc.py +++ b/glymur/test/test_icc.py @@ -6,8 +6,6 @@ ICC profile tests. # pylint: disable=R0904 import datetime -import os -import sys import unittest import numpy as np diff --git a/glymur/test/test_jp2box.py b/glymur/test/test_jp2box.py index 28ae4fe..9843b94 100644 --- a/glymur/test/test_jp2box.py +++ b/glymur/test/test_jp2box.py @@ -35,10 +35,10 @@ 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 -) +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.""" @@ -48,13 +48,15 @@ def load_tests(loader, tests, ignore): 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.""" @@ -70,7 +72,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.""" @@ -92,7 +94,7 @@ class TestDataEntryURL(unittest.TestCase): self.assertEqual(jp22.box[4].url, url) def test_null_termination(self): - """I.9.3.2 specifies that the location field must be null terminated.""" + """I.9.3.2 specifies that location field must be null terminated.""" jp2 = Jp2k(self.jp2file) url = 'http://glymur.readthedocs.org' @@ -103,12 +105,15 @@ 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) @@ -128,18 +133,18 @@ class TestChannelDefinition(unittest.TestCase): data = j2k[:] # Write the first component back out to file. with tempfile.NamedTemporaryFile(suffix=".j2k", delete=False) as tfile: - grey_j2k = Jp2k(tfile.name, data=data[:, :, 0]) + 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: - grey_j2k = Jp2k(tfile.name, data=data[:, :, 0:1]) + 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) - rgba_jp2 = Jp2k(tfile.name, data=data4) + Jp2k(tfile.name, data=data4) cls.four_planes = tfile.name @classmethod @@ -392,7 +397,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): @@ -402,7 +407,8 @@ 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.""" @@ -525,8 +531,8 @@ class TestPaletteBox(unittest.TestCase): bps = (8, 8, 8) signed = (False, False) with self.assertWarns(UserWarning): - pclr = glymur.jp2box.PaletteBox(palette, bits_per_component=bps, - signed=signed) + glymur.jp2box.PaletteBox(palette, bits_per_component=bps, + signed=signed) @unittest.skipIf(WARNING_INFRASTRUCTURE_ISSUE, WARNING_INFRASTRUCTURE_MSG) def test_mismatched_signed_palette(self): @@ -535,8 +541,8 @@ class TestPaletteBox(unittest.TestCase): bps = (8, 8, 8, 8) signed = (False, False, False, False) with self.assertWarns(UserWarning): - pclr = glymur.jp2box.PaletteBox(palette, bits_per_component=bps, - signed=signed) + glymur.jp2box.PaletteBox(palette, bits_per_component=bps, + signed=signed) def test_writing_with_different_bitdepths(self): """Bitdepths must be the same when writing.""" @@ -792,7 +798,7 @@ class TestWrap(unittest.TestCase): # list to trigger the error. boxes[2].box = [] with self.assertRaises(IOError): - jp22 = jp2.wrap(tfile.name, boxes=boxes) + jp2.wrap(tfile.name, boxes=boxes) def test_default_layout_with_boxes(self): """basic test for rewrapping a jp2 file, boxes specified""" @@ -857,8 +863,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) - signed = (True, False, True) - pclr = glymur.jp2box.PaletteBox(palette=palette, bits_per_component=bps, + pclr = glymur.jp2box.PaletteBox(palette=palette, + bits_per_component=bps, signed=(True, False, True)) j2k = Jp2k(self.j2kfile) @@ -970,7 +976,8 @@ 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] @@ -1026,7 +1033,7 @@ class TestJp2Boxes(unittest.TestCase): 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) @@ -1240,7 +1247,6 @@ 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)) @@ -1290,7 +1296,8 @@ 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=UUID\('00000000-0000-0000-0000-000000000000'\),\s""" + regexp += """the_uuid=""" + regexp += """UUID\('00000000-0000-0000-0000-000000000000'\),\s""" regexp += """raw_data=\)""" if sys.hexversion < 0x03000000: @@ -1307,7 +1314,8 @@ 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=UUID\('be7acfcb-97a9-42e8-9c71-999491e3afac'\),\s""" + regexp += """the_uuid=""" + regexp += """UUID\('be7acfcb-97a9-42e8-9c71-999491e3afac'\),\s""" regexp += """raw_data=\)""" if sys.hexversion < 0x03000000: diff --git a/glymur/test/test_jp2box_jpx.py b/glymur/test/test_jp2box_jpx.py index ce676f3..3ee4d31 100644 --- a/glymur/test/test_jp2box_jpx.py +++ b/glymur/test/test_jp2box_jpx.py @@ -6,7 +6,6 @@ Test suite specifically targeting JPX box layout. import ctypes import os import struct -import sys import tempfile import unittest @@ -20,6 +19,7 @@ from glymur.jp2box import ColourSpecificationBox from .fixtures import WARNING_INFRASTRUCTURE_ISSUE, WARNING_INFRASTRUCTURE_MSG + @unittest.skipIf(os.name == "nt", "Temporary file issue on window.") class TestJPXWrap(unittest.TestCase): """Test suite for wrapping JPX files.""" @@ -184,7 +184,7 @@ class TestJPXWrap(unittest.TestCase): with tempfile.NamedTemporaryFile(suffix=".jpx") as tfile: with self.assertRaises(IOError): - jpx = jp2.wrap(tfile.name, boxes=boxes) + jp2.wrap(tfile.name, boxes=boxes) def test_cgrp_neg(self): """Can't write a cgrp with anything but colr sub boxes""" @@ -204,7 +204,7 @@ class TestJPXWrap(unittest.TestCase): with tempfile.NamedTemporaryFile(suffix=".jpx") as tfile: with self.assertRaises(IOError): - jpx = jp2.wrap(tfile.name, boxes=boxes) + jp2.wrap(tfile.name, boxes=boxes) def test_ftbl(self): """Write a fragment table box.""" @@ -484,7 +484,7 @@ class TestJPX(unittest.TestCase): ftbl.write(tfile) def test_data_reference_requires_dtbl(self): - """The existance of a data reference box requires a ftbl box as well.""" + """The existance of data reference box requires a ftbl box as well.""" flag = 0 version = (0, 0, 0) url1 = 'file:////usr/local/bin' @@ -574,7 +574,7 @@ class TestJPX(unittest.TestCase): 131072, 65536, 32768, 16384, 8192] for j in range(len(standard_flags)): mask = (standard_masks[j] >> 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,7 +599,6 @@ 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 0e6619a..409e43b 100644 --- a/glymur/test/test_jp2box_uuid.py +++ b/glymur/test/test_jp2box_uuid.py @@ -11,7 +11,6 @@ # pylint: disable=R0904 import os -import re import shutil import struct import sys @@ -23,29 +22,15 @@ 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 (HAS_PYTHON_XMP_TOOLKIT, OPJ_DATA_ROOT, - WARNING_INFRASTRUCTURE_ISSUE, +from .fixtures import (WARNING_INFRASTRUCTURE_ISSUE, WARNING_INFRASTRUCTURE_MSG, WINDOWS_TMP_FILE_MSG) -if HAS_PYTHON_XMP_TOOLKIT: - from libxmp import XMPMeta - import glymur from glymur import Jp2k -from .fixtures import OPJ_DATA_ROOT, opj_data_file, SimpleRDF +from .fixtures import SimpleRDF @unittest.skipIf(os.name == "nt", WINDOWS_TMP_FILE_MSG) @@ -103,6 +88,7 @@ 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) class TestSuiteWarns(unittest.TestCase): @@ -113,7 +99,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: @@ -137,7 +123,7 @@ class TestSuiteWarns(unittest.TestCase): tfile.flush() with self.assertWarnsRegex(UserWarning, 'Unrecognized Exif tag'): - j = glymur.Jp2k(tfile.name) + glymur.Jp2k(tfile.name) def test_bad_tag_datatype(self): """Only certain datatypes are allowable""" diff --git a/glymur/test/test_jp2box_xml.py b/glymur/test/test_jp2box_xml.py index 45d02f1..84a63f3 100644 --- a/glymur/test/test_jp2box_xml.py +++ b/glymur/test/test_jp2box_xml.py @@ -17,20 +17,9 @@ Test suite specifically targeting JP2 box layout. 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 @@ -43,6 +32,7 @@ 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.""" @@ -167,7 +157,6 @@ class TestXML(unittest.TestCase): u'Россия') - class TestJp2kBadXmlFile(unittest.TestCase): """Test suite for bad XML box situations""" @@ -293,22 +282,19 @@ 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', - '26ccf3651020967f7778238ef5af08af.SIGFPE.d25.527.jp2')) + relname)) 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 edb19a1..cb3a9e7 100644 --- a/glymur/test/test_jp2k.py +++ b/glymur/test/test_jp2k.py @@ -13,7 +13,6 @@ Tests for general glymur functionality. import doctest import os import re -import shutil import struct import sys import tempfile @@ -45,6 +44,7 @@ if HAS_PYTHON_XMP_TOOLKIT: from .fixtures import OPJ_DATA_ROOT, opj_data_file from . import fixtures + # Doc tests should be run as well. def load_tests(loader, tests, ignore): # W0613: "loader" and "ignore" are necessary for the protocol @@ -77,6 +77,7 @@ 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") @@ -148,11 +149,6 @@ 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. @@ -169,8 +165,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): @@ -184,12 +180,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) @@ -226,7 +222,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), @@ -235,7 +231,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). """ @@ -243,6 +239,7 @@ 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.""" @@ -319,7 +316,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 with OpenJPEG {0}".format(openjpeg_version)) + "Not supported on 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): @@ -638,7 +635,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.""" @@ -654,8 +651,9 @@ 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)''', @@ -674,6 +672,7 @@ 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)) @@ -693,30 +692,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): - j = Jp2k(tfile.name, data=data, - cbsize=(16, 16), psizes=[(16, 16)]) + 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): - j = Jp2k(tfile.name, data=data, - cbsize=(16, 16), psizes=[(48, 48)]) + 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): - j = Jp2k(tfile.name, data=data) + 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): - j = Jp2k(tfile.name, data=data) + 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""" @@ -726,7 +725,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): - j = Jp2k(tfile.name, data=data) + 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 @@ -745,31 +744,31 @@ class TestJp2k_write(unittest.TestCase): """OpenJP2 only allows 2D or 3D images.""" with tempfile.NamedTemporaryFile(suffix='.j2k') as tfile: with self.assertRaises(IOError): - j = Jp2k(tfile.name, - data=np.zeros((128, 128, 2, 2), dtype=np.uint8)) + 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): - j = Jp2k(tfile.name, - data=np.zeros((128, 128, 2), dtype=np.uint8), - colorspace='rgb') + 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): - j = Jp2k(tfile.name, - data=np.zeros((128, 128, 3), dtype=np.uint8), - colorspace='rgb') + 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): @@ -804,7 +803,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) - j = Jp2k(tfile.name, data=data, colorspace='ycc') + Jp2k(tfile.name, data=data, colorspace='ycc') def test_write_with_jp2_in_caps(self): """should be able to write with JP2 suffix.""" @@ -833,7 +832,7 @@ class TestJp2k_write(unittest.TestCase): expdata = j2k[:] with tempfile.NamedTemporaryFile(suffix='.jp2') as tfile: with self.assertRaises(IOError): - ofile = Jp2k(tfile.name, data=expdata[:, :, 0], mct=True) + Jp2k(tfile.name, data=expdata[:, :, 0], mct=True) def test_write_cprl(self): """Must be able to write a CPRL progression order file""" @@ -924,7 +923,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): - j = Jp2k(tfile.name, data=data, colorspace='cmyk') + Jp2k(tfile.name, data=data, colorspace='cmyk') @unittest.skipIf(os.name == "nt", fixtures.WINDOWS_TMP_FILE_MSG) def test_asoc_label_box(self): @@ -933,7 +932,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: - j = Jp2k(tfile.name, data=data) + Jp2k(tfile.name, data=data) with tempfile.NamedTemporaryFile(suffix='.jp2') as tfile2: @@ -1041,12 +1040,15 @@ 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): @@ -1064,22 +1066,23 @@ class TestParsing(unittest.TestCase): """Should not warn if RSIZ when parsing is turned off.""" filename = opj_data_file('input/nonregression/edf_c2_1002767.jp2') glymur.set_parseoptions(codestream=False) - j = Jp2k(filename) + Jp2k(filename) glymur.set_parseoptions(codestream=True) with self.assertWarnsRegex(UserWarning, 'Invalid profile'): - jp2 = Jp2k(filename) + Jp2k(filename) def test_main_header(self): - """Verify that the main header is not loaded when parsing turned off.""" + """Verify that the main header isn't 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._main_header) - main_header = jp2c.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, "OPJ_DATA_ROOT environment variable not set") @@ -1101,13 +1104,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): - jp2 = Jp2k(filename) + 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'): - jp2 = Jp2k(filename) + Jp2k(filename) def test_invalid_colorspace(self): """ @@ -1117,13 +1120,13 @@ class TestJp2kOpjDataRootWarnings(unittest.TestCase): """ filename = opj_data_file('input/nonregression/edf_c2_1103421.jp2') with self.assertWarns(UserWarning): - jp2 = Jp2k(filename) + 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): - jp2 = Jp2k(filename) + Jp2k(filename) @unittest.skipIf(OPJ_DATA_ROOT is None, @@ -1148,7 +1151,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""" @@ -1180,7 +1183,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""" @@ -1196,31 +1199,11 @@ 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): @@ -1274,7 +1257,6 @@ 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') @@ -1329,6 +1311,16 @@ 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.""" @@ -1348,112 +1340,3 @@ 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 028734d..f512dfd 100644 --- a/glymur/test/test_opj_suite.py +++ b/glymur/test/test_opj_suite.py @@ -38,12 +38,11 @@ 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) @@ -415,16 +414,17 @@ class TestSuiteWarns(MetadataBase): 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 @@ -436,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) @@ -726,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]) @@ -798,6 +798,7 @@ 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''', @@ -806,7 +807,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 ee1838b..6b198c1 100644 --- a/glymur/test/test_opj_suite_dump.py +++ b/glymur/test/test_opj_suite_dump.py @@ -36,14 +36,17 @@ 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 +from glymur.core import (RCME_ISO_8859_1, RCME_BINARY, SRGB, + GREYSCALE, RESTRICTED_ICC_PROFILE, + ENUMERATED_COLORSPACE) from glymur.jp2box import FileTypeBox -from .fixtures import ( - MetadataBase, OPJ_DATA_ROOT, - WARNING_INFRASTRUCTURE_ISSUE, WARNING_INFRASTRUCTURE_MSG, - mse, peak_tolerance, read_pgx, opj_data_file -) +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" @unittest.skipIf(OPJ_DATA_ROOT is None, @@ -82,10 +85,12 @@ class TestSuite(MetadataBase): 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 @@ -97,7 +102,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) @@ -121,9 +126,10 @@ 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) @@ -143,7 +149,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) @@ -154,9 +160,10 @@ 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 @@ -168,7 +175,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) @@ -178,7 +185,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) @@ -191,7 +198,8 @@ 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 @@ -217,9 +225,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) @@ -231,7 +240,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) @@ -263,11 +272,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, - "Creator: AV-J2K (c) 2000,2001 Algo Vision Technology".encode()) + pargs = (RCME_ISO_8859_1, comment1.encode()) self.verifyCMEsegment(c.segment[8], CMEsegment(*pargs)) pargs = (RCME_BINARY, c.segment[9].ccme) @@ -290,10 +299,12 @@ 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) @@ -305,7 +316,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, @@ -353,7 +364,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)) @@ -367,11 +378,12 @@ 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) @@ -383,7 +395,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) @@ -394,7 +406,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) @@ -404,7 +416,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) @@ -441,7 +453,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) @@ -460,11 +472,12 @@ 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) @@ -476,7 +489,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) @@ -535,7 +548,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) @@ -552,10 +565,12 @@ 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) @@ -567,7 +582,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) @@ -595,7 +610,6 @@ 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') @@ -605,10 +619,12 @@ 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) @@ -620,7 +636,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) @@ -631,7 +647,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) @@ -641,7 +657,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) @@ -651,7 +667,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) @@ -696,9 +712,10 @@ 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) @@ -710,7 +727,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) @@ -743,10 +760,12 @@ 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) @@ -758,7 +777,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) @@ -805,9 +824,10 @@ 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) @@ -819,7 +839,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)]) @@ -832,7 +852,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)) @@ -854,10 +874,11 @@ 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) @@ -869,7 +890,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) @@ -882,7 +903,8 @@ 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)) @@ -904,10 +926,12 @@ 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 @@ -918,7 +942,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) @@ -928,7 +952,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) @@ -969,7 +993,8 @@ 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,10 +1010,11 @@ 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) @@ -999,7 +1025,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) @@ -1025,10 +1051,11 @@ 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) @@ -1039,7 +1066,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) @@ -1072,11 +1099,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, - "Creator: AV-J2K (c) 2000,2001 Algo Vision Technology".encode()) + pargs = (RCME_ISO_8859_1, comment1.encode()) self.verifyCMEsegment(c.segment[8], CMEsegment(*pargs)) pargs = (RCME_BINARY, c.segment[9].ccme) @@ -1125,10 +1152,11 @@ 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) @@ -1139,7 +1167,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) @@ -1165,10 +1193,11 @@ 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 @@ -1179,7 +1208,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) @@ -1189,7 +1218,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) @@ -1201,7 +1230,8 @@ 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)) @@ -1223,10 +1253,12 @@ 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 @@ -1238,7 +1270,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, @@ -1285,7 +1317,8 @@ 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)) @@ -1305,11 +1338,12 @@ 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 @@ -1320,7 +1354,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) @@ -1330,7 +1364,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) @@ -1339,7 +1373,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) @@ -1375,7 +1409,8 @@ 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 @@ -1400,10 +1435,11 @@ 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 @@ -1414,7 +1450,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) @@ -1487,10 +1523,12 @@ 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 @@ -1501,7 +1539,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) @@ -1516,7 +1554,8 @@ 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. @@ -1543,10 +1582,11 @@ 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 @@ -1557,7 +1597,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) @@ -1573,7 +1613,8 @@ 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)) @@ -1604,10 +1645,11 @@ 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 @@ -1618,7 +1660,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)]) @@ -1628,7 +1670,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)]) @@ -1640,7 +1682,8 @@ 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)) @@ -1657,11 +1700,12 @@ 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 @@ -1672,7 +1716,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)) @@ -1694,7 +1738,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) @@ -1716,7 +1760,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) @@ -1761,10 +1805,12 @@ 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 @@ -1775,7 +1821,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, @@ -1794,10 +1840,11 @@ 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 @@ -1808,7 +1855,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) @@ -1823,10 +1870,11 @@ 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 @@ -1837,7 +1885,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) @@ -1860,10 +1908,11 @@ 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 @@ -1874,7 +1923,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) @@ -1897,10 +1946,11 @@ 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 @@ -1911,7 +1961,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) @@ -1940,10 +1990,11 @@ 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 @@ -1954,7 +2005,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) @@ -1981,10 +2032,11 @@ 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 @@ -1995,7 +2047,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) @@ -2017,10 +2069,12 @@ 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 @@ -2031,7 +2085,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) @@ -2054,10 +2108,11 @@ 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 @@ -2068,7 +2123,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) @@ -2101,17 +2156,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 @@ -2122,7 +2177,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) @@ -2142,10 +2197,12 @@ 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 @@ -2156,7 +2213,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) @@ -2174,10 +2231,12 @@ 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 +2247,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,10 +2265,12 @@ 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 @@ -2220,7 +2281,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) @@ -2242,10 +2303,12 @@ 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 @@ -2256,7 +2319,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,10 +2341,12 @@ 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 @@ -2292,7 +2357,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) @@ -2314,10 +2379,12 @@ 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 @@ -2328,7 +2395,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,10 +2421,12 @@ 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 @@ -2368,7 +2437,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) @@ -2394,10 +2463,12 @@ 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 @@ -2406,10 +2477,9 @@ 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)) # cblk + 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) @@ -2431,10 +2501,12 @@ 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 @@ -2443,10 +2515,9 @@ 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)) # cblk + 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) @@ -2468,10 +2539,12 @@ 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 @@ -2480,10 +2553,9 @@ 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)) # cblk + 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, @@ -2512,7 +2584,9 @@ 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 @@ -2521,9 +2595,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=glymur.core.SRGB, - approximation=1, precedence=2) + colr = glymur.jp2box.ColourSpecificationBox(colorspace=SRGB, + approximation=1, + precedence=2) self.verifyColourSpecificationBox(jp2.box[3].box[1], colr) # Jp2 Header @@ -2543,10 +2617,12 @@ class TestSuite(MetadataBase): 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 @@ -2555,10 +2631,9 @@ 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)) # cblk + 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(len(c.segment[2].spcod), 9) @@ -2581,19 +2656,22 @@ 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=glymur.core.SRGB, - approximation=1, precedence=2) + colr = glymur.jp2box.ColourSpecificationBox(colorspace=SRGB, + approximation=1, + precedence=2) self.verifyColourSpecificationBox(jp2.box[3].box[1], colr) c = jp2.box[4].main_header @@ -2603,10 +2681,12 @@ class TestSuite(MetadataBase): 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 @@ -2615,10 +2695,9 @@ 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)) # cblk + 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(len(c.segment[2].spcod), 9) @@ -2646,11 +2725,10 @@ 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=glymur.core.GREYSCALE) + colr = glymur.jp2box.ColourSpecificationBox(colorspace=GREYSCALE) self.verifyColourSpecificationBox(jp2.box[2].box[1], colr) # Jp2 Header @@ -2666,10 +2744,12 @@ class TestSuite(MetadataBase): 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 @@ -2681,7 +2761,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) @@ -2710,20 +2790,23 @@ 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) - colr = glymur.jp2box.ColourSpecificationBox( - colorspace=glymur.core.SRGB, - method=glymur.core.ENUMERATED_COLORSPACE, - approximation=1, precedence=2) + method = ENUMERATED_COLORSPACE + colr = glymur.jp2box.ColourSpecificationBox(colorspace=SRGB, + method=method, + approximation=1, + precedence=2) self.verifyColourSpecificationBox(jp2.box[3].box[1], colr) # Jp2 Header @@ -2744,10 +2827,12 @@ class TestSuite(MetadataBase): 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 @@ -2759,7 +2844,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) @@ -2796,10 +2881,12 @@ class TestSuite(MetadataBase): 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 @@ -2811,7 +2898,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) @@ -2847,7 +2934,7 @@ class TestSuiteWarns(MetadataBase): relpath = 'input/nonregression/issue188_beach_64bitsbox.jp2' jfile = opj_data_file(relpath) with self.assertWarns(UserWarning): - d = Jp2k(jfile)[:] + Jp2k(jfile)[:] self.assertTrue(True) def test_NR_broken4_jp2_dump(self): @@ -2882,7 +2969,7 @@ class TestSuiteWarns(MetadataBase): 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) + colr = glymur.jp2box.ColourSpecificationBox(colorspace=SRGB) self.verifyColourSpecificationBox(jp2.box[2].box[1], colr) c = jp2.box[3].main_header @@ -2892,10 +2979,12 @@ class TestSuiteWarns(MetadataBase): 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)) + '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)) @@ -2910,7 +2999,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) @@ -2950,7 +3039,7 @@ class TestSuiteWarns(MetadataBase): 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): @@ -2978,8 +3067,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=glymur.core.SRGB, - approximation=1) + colr = glymur.jp2box.ColourSpecificationBox(colorspace=SRGB, + approximation=1) self.verifyColourSpecificationBox(jp2.box[3].box[1], colr) # XML box @@ -3006,7 +3095,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 @@ -3036,9 +3125,8 @@ 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 @@ -3068,8 +3156,8 @@ class TestSuiteWarns(MetadataBase): ihdr = glymur.jp2box.ImageHeaderBox(512, 768) self.verifyImageHeaderBox(jp2.box[2].box[0], ihdr) - colr = glymur.jp2box.ColourSpecificationBox( - colorspace=glymur.core.GREYSCALE, approximation=1) + colr = glymur.jp2box.ColourSpecificationBox(colorspace=GREYSCALE, + approximation=1) self.verifyColourSpecificationBox(jp2.box[2].box[1], colr) def test_NR_file5_dump(self): @@ -3091,16 +3179,18 @@ 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) - colr = glymur.jp2box.ColourSpecificationBox( - method=glymur.core.RESTRICTED_ICC_PROFILE, - approximation=1, icc_profile=bytes([0] * 546)) + method = RESTRICTED_ICC_PROFILE + icc_profile = bytes([0] * 546) + colr = glymur.jp2box.ColourSpecificationBox(method=method, + approximation=1, + icc_profile=icc_profile) self.verifyColourSpecificationBox(jp2.box[3].box[1], colr) self.assertEqual(jp2.box[3].box[1].icc_profile['Size'], 546) @@ -3121,10 +3211,10 @@ class TestSuiteWarns(MetadataBase): ihdr = glymur.jp2box.ImageHeaderBox(512, 768, bits_per_component=12) self.verifyImageHeaderBox(jp2.box[2].box[0], ihdr) - colr = glymur.jp2box.ColourSpecificationBox( - colorspace=glymur.core.GREYSCALE, - method=glymur.core.ENUMERATED_COLORSPACE, - approximation=1) + method = ENUMERATED_COLORSPACE + colr = glymur.jp2box.ColourSpecificationBox(colorspace=GREYSCALE, + method=method, + approximation=1) self.verifyColourSpecificationBox(jp2.box[2].box[1], colr) def test_NR_file7_dump(self): @@ -3150,12 +3240,13 @@ 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) - colr = glymur.jp2box.ColourSpecificationBox( - method=glymur.core.RESTRICTED_ICC_PROFILE, - approximation=1) + method = RESTRICTED_ICC_PROFILE + colr = glymur.jp2box.ColourSpecificationBox(method=method, + approximation=1) self.verifyColourSpecificationBox(jp2.box[3].box[1], colr) self.assertEqual(jp2.box[3].box[1].icc_profile['Size'], 13332) @@ -3179,9 +3270,9 @@ class TestSuiteWarns(MetadataBase): ihdr = glymur.jp2box.ImageHeaderBox(400, 700) self.verifyImageHeaderBox(jp2.box[2].box[0], ihdr) - colr = glymur.jp2box.ColourSpecificationBox( - method=glymur.core.RESTRICTED_ICC_PROFILE, - approximation=1) + method = RESTRICTED_ICC_PROFILE + colr = glymur.jp2box.ColourSpecificationBox(method=method, + approximation=1) self.verifyColourSpecificationBox(jp2.box[2].box[1], colr) self.assertEqual(jp2.box[2].box[1].icc_profile['Size'], 414) @@ -3234,16 +3325,15 @@ 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=glymur.core.SRGB, - approximation=1) + colr = glymur.jp2box.ColourSpecificationBox(colorspace=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] @@ -3256,10 +3346,12 @@ 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) - colr = glymur.jp2box.ColourSpecificationBox(colorspace=glymur.core.SRGB) + cspace = glymur.core.SRGB + colr = glymur.jp2box.ColourSpecificationBox(colorspace=cspace) self.verifyColourSpecificationBox(jp2.box[2].box[1], colr) # Skip the 4th box, it is uknown. @@ -3271,10 +3363,12 @@ class TestSuiteWarns(MetadataBase): 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 @@ -3286,7 +3380,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) @@ -3329,10 +3423,12 @@ class TestSuiteWarns(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 @@ -3344,7 +3440,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) @@ -3390,10 +3486,12 @@ class TestSuiteWarns(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 @@ -3405,7 +3503,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 c7e31e5..1d3ec6e 100644 --- a/glymur/test/test_opj_suite_neg.py +++ b/glymur/test/test_opj_suite_neg.py @@ -10,7 +10,6 @@ seem like logical negative tests to add. import os import re -import sys import tempfile import unittest @@ -88,7 +87,6 @@ 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): @@ -98,8 +96,7 @@ class TestSuiteNegativeWrite(unittest.TestCase): data = skimage.io.imread(infile) with tempfile.NamedTemporaryFile(suffix='.j2k') as tfile: with self.assertRaises(IOError): - j = Jp2k(tfile.name, data=data, cinema2k=36) - + Jp2k(tfile.name, data=data, cinema2k=36) @unittest.skipIf(NO_READ_BACKEND, NO_READ_BACKEND_MSG) def test_psnr_with_cratios(self): @@ -109,8 +106,8 @@ class TestSuiteNegativeWrite(unittest.TestCase): data = read_image(infile) with tempfile.NamedTemporaryFile(suffix='.j2k') as tfile: with self.assertRaises(IOError): - j = Jp2k(tfile.name, - data=data, psnr=[30, 35, 40], cratios=[2, 3, 4]) + 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""" @@ -120,13 +117,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): - j = Jp2k(tfile.name, data=data, cbsize=(256, 256)) + Jp2k(tfile.name, data=data, cbsize=(256, 256)) # opj_compress doesn't allow either dimension to be less than 4. with self.assertRaises(IOError): - j = Jp2k(tfile.name, data=data, cbsize=(2048, 2)) + Jp2k(tfile.name, data=data, cbsize=(2048, 2)) with self.assertRaises(IOError): - j = Jp2k(tfile.name, data=data, cbsize=(2, 2048)) + Jp2k(tfile.name, data=data, cbsize=(2, 2048)) def test_precinct_size_not_p2(self): """precinct sizes should be powers of two.""" @@ -134,7 +131,7 @@ class TestSuiteNegativeWrite(unittest.TestCase): data = ifile[::4, ::4] with tempfile.NamedTemporaryFile(suffix='.jp2') as tfile: with self.assertRaises(IOError): - ofile = Jp2k(tfile.name, data=data, psizes=[(13, 13)]) + 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.""" @@ -142,7 +139,7 @@ class TestSuiteNegativeWrite(unittest.TestCase): data = ifile[::4, ::4] with tempfile.NamedTemporaryFile(suffix='.jp2') as tfile: with self.assertRaises(IOError): - ofile = Jp2k(tfile.name, data=data, cbsize=(13, 12)) + 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.""" @@ -150,6 +147,4 @@ class TestSuiteNegativeWrite(unittest.TestCase): data = ifile[::4, ::4] with tempfile.NamedTemporaryFile(suffix='.jp2') as tfile: with self.assertRaises(IOError): - ofile = Jp2k(tfile.name, - data=data, cbsize=(64, 64), psizes=[(64, 64)]) - + 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 ecb7a7d..7f0fd4b 100644 --- a/glymur/test/test_opj_suite_write.py +++ b/glymur/test/test_opj_suite_write.py @@ -34,6 +34,7 @@ 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): @@ -44,14 +45,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)) # cblksz + self.assertEqual(tuple(cod_segment.code_block_size), (32, 32)) 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]) @@ -59,9 +60,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]) @@ -88,8 +89,8 @@ class WriteCinema(CinemaBase): data = skimage.io.imread(infile) with tempfile.NamedTemporaryFile(suffix='.j2k') as tfile: with self.assertRaises(IOError): - j = Jp2k(tfile.name, data=data, - cinema2k=48, cratios=[200, 100, 50]) + 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.""" @@ -98,8 +99,8 @@ class WriteCinema(CinemaBase): data = skimage.io.imread(infile) with tempfile.NamedTemporaryFile(suffix='.j2k') as tfile: with self.assertRaises(IOError): - j = Jp2k(tfile.name, data=data, - cinema4k=True, cratios=[200, 100, 50]) + Jp2k(tfile.name, data=data, + cinema4k=True, cratios=[200, 100, 50]) @unittest.skipIf(WARNING_INFRASTRUCTURE_ISSUE, WARNING_INFRASTRUCTURE_MSG) @@ -135,7 +136,8 @@ 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() @@ -146,7 +148,8 @@ 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() @@ -157,7 +160,8 @@ 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,7 +172,8 @@ 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) @@ -216,7 +221,7 @@ class TestNegative2pointzero(unittest.TestCase): with patch('glymur.version.openjpeg_version', new=version): with tempfile.NamedTemporaryFile(suffix='.j2k') as tfile: with self.assertRaises(IOError): - j = Jp2k(tfile.name, data=data, cinema2k=48) + Jp2k(tfile.name, data=data, cinema2k=48) @unittest.skipIf(re.match(r'''1.[0-4]''', openjpeg_version) is not None, @@ -248,7 +253,6 @@ 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,10 +264,11 @@ 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 @@ -275,7 +280,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) @@ -291,10 +296,11 @@ 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 @@ -306,7 +312,8 @@ 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) @@ -316,18 +323,19 @@ 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 @@ -339,7 +347,8 @@ 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, @@ -352,20 +361,21 @@ 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], + tilesize=(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 @@ -377,7 +387,8 @@ 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, @@ -393,10 +404,11 @@ class TestSuiteWrite(fixtures.MetadataBase): 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 @@ -408,7 +420,8 @@ 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) @@ -423,10 +436,11 @@ 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 @@ -438,7 +452,8 @@ 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) @@ -458,10 +473,11 @@ 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 @@ -471,9 +487,10 @@ 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) @@ -488,15 +505,16 @@ 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 @@ -508,7 +526,8 @@ 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) @@ -523,10 +542,11 @@ 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 @@ -538,7 +558,8 @@ 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) @@ -553,10 +574,11 @@ 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 @@ -568,7 +590,8 @@ 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) @@ -578,7 +601,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']) @@ -616,10 +639,11 @@ class TestSuiteWrite(fixtures.MetadataBase): 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 @@ -631,7 +655,8 @@ 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) @@ -648,10 +673,11 @@ 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 @@ -663,7 +689,8 @@ 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 5eedfe5..ab3e9fd 100644 --- a/glymur/test/test_printing.py +++ b/glymur/test/test_printing.py @@ -32,11 +32,12 @@ 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): @@ -52,23 +53,11 @@ class TestPrinting(unittest.TestCase): def tearDown(self): 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) - actual = fake_out.getvalue().strip() + fake_out.getvalue().strip() self.assertTrue(True) @@ -78,7 +67,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) @@ -107,7 +96,8 @@ 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""" @@ -115,9 +105,8 @@ 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: + j = glymur.Jp2k(tfile.name, data=data) # Offset of the codestream is where we start. wbuffer = tfile.read(77) @@ -419,7 +408,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 an XMLBox with utf-8 encoding (cyrrillic).""" + """Should be able to print XMLBox with utf-8 encoding (cyrrillic).""" # Seems to be inconsistencies between different versions of python2.x # as to what gets printed. # @@ -437,7 +426,8 @@ 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)", " Россия"] @@ -613,12 +603,14 @@ 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.") @@ -826,6 +818,7 @@ 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.") @@ -852,7 +845,7 @@ class TestPrintingOpjDataRootWarns(unittest.TestCase): filename = opj_data_file('input/nonregression/edf_c2_1103421.jp2') with self.assertWarns(UserWarning): jp2 = Jp2k(filename) - with patch('sys.stdout', new=StringIO()) as fake_out: + with patch('sys.stdout', new=StringIO()): print(jp2) def test_bad_rsiz(self): @@ -860,7 +853,7 @@ class TestPrintingOpjDataRootWarns(unittest.TestCase): filename = opj_data_file('input/nonregression/edf_c2_1002767.jp2') with self.assertWarns(UserWarning): j = Jp2k(filename) - with patch('sys.stdout', new=StringIO()) as fake_out: + with patch('sys.stdout', new=StringIO()): print(j) def test_bad_wavelet_transform(self): @@ -868,7 +861,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()) as fake_out: + with patch('sys.stdout', new=StringIO()): print(jp2) def test_invalid_progression_order(self): @@ -1029,7 +1022,7 @@ class TestPrintingOpjDataRootWarns(unittest.TestCase): 'issue171.jp2')) with self.assertWarns(UserWarning): jp2 = Jp2k(filename) - with patch('sys.stdout', new=StringIO()) as fake_out: + with patch('sys.stdout', new=StringIO()): # No need to verify, it's enough that we don't error out. print(jp2) @@ -1069,7 +1062,8 @@ class TestJp2dump(unittest.TestCase): """Verify dumping with -c 0, supressing all codestream details.""" actual = self.run_jp2dump(['', '-c', '0', self.jp2file]) - self.assertEqual(actual, fixtures.nemo_dump_no_codestream) + expected = fixtures.nemo_dump_no_codestream + self.assertEqual(actual, expected) def test_codestream_1(self): """Verify dumping with -c 1, print just the header.""" @@ -1112,4 +1106,3 @@ class TestJp2dump(unittest.TestCase): command_line.main() actual = fake_out.getvalue().strip() self.assertRegex(actual, "File: .*") - From 6f697526f24c865e3e57de090e7d8f1d08a79895 Mon Sep 17 00:00:00 2001 From: John Evans Date: Wed, 31 Dec 2014 22:41:02 -0500 Subject: [PATCH 36/57] pep8 work, closes #307 --- docs/source/conf.py | 83 ++++++------ glymur/__init__.py | 14 +- glymur/_uuid_io.py | 2 - glymur/codestream.py | 35 ++--- glymur/command_line.py | 1 - glymur/core.py | 2 - glymur/data/__init__.py | 1 - glymur/jp2box.py | 193 ++++++++++++++-------------- glymur/jp2k.py | 20 ++- glymur/lib/config.py | 3 - glymur/lib/openjp2.py | 2 - glymur/lib/openjpeg.py | 2 - glymur/lib/test/test_openjp2.py | 23 ++-- glymur/lib/test/test_openjpeg.py | 3 +- glymur/lib/test/test_printing.py | 4 +- glymur/test/fixtures.py | 1 - glymur/test/test_callbacks.py | 8 -- glymur/test/test_config.py | 10 -- glymur/test/test_glymur_warnings.py | 4 - glymur/test/test_icc.py | 9 -- glymur/test/test_jp2box.py | 21 +-- glymur/test/test_jp2box_uuid.py | 9 -- glymur/test/test_jp2box_xml.py | 12 -- glymur/test/test_jp2k.py | 13 -- glymur/test/test_opj_suite.py | 25 ---- glymur/test/test_opj_suite_dump.py | 25 ---- glymur/test/test_opj_suite_neg.py | 6 - glymur/test/test_opj_suite_write.py | 4 - glymur/test/test_printing.py | 11 +- setup.py | 6 +- 30 files changed, 190 insertions(+), 362 deletions(-) diff --git a/docs/source/conf.py b/docs/source/conf.py index 8a87a64..e9387f4 100644 --- a/docs/source/conf.py +++ b/docs/source/conf.py @@ -13,7 +13,6 @@ # serve to show the default. import sys -import os class Mock(object): @@ -42,12 +41,12 @@ for mod_name in MOCK_MODULES: # If extensions (or modules to document with autodoc) are in another directory, # 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. @@ -62,7 +61,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' @@ -82,13 +81,13 @@ 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. @@ -96,24 +95,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 -------------------------------------------------- @@ -125,26 +124,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, @@ -153,44 +152,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' @@ -199,13 +198,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 @@ -216,23 +215,23 @@ latex_documents = [('index', 'glymur.tex', u'glymur Documentation', # The name of an image file (relative to this directory) to place at the top of # the 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 ------------------------------------------- @@ -245,7 +244,7 @@ man_pages = [ ] # If true, show URL addresses after external links. -#man_show_urls = False +# man_show_urls = False # -- Options for Texinfo output ----------------------------------------------- @@ -258,13 +257,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/glymur/__init__.py b/glymur/__init__.py index 9a4d8b1..d8971b2 100644 --- a/glymur/__init__.py +++ b/glymur/__init__.py @@ -1,21 +1,25 @@ """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 7bcf2cb..3c63b0a 100644 --- a/glymur/_uuid_io.py +++ b/glymur/_uuid_io.py @@ -3,8 +3,6 @@ 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 aa12bd7..ea94afd 100644 --- a/glymur/codestream.py +++ b/glymur/codestream.py @@ -6,16 +6,13 @@ 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 @@ -31,16 +28,15 @@ 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'}) -_WAVELET_TRANSFORM_DISPLAY = _Keydefaultdict(_factory, - { WAVELET_XFORM_9X7_IRREVERSIBLE: '9-7 irreversible', - WAVELET_XFORM_5X3_REVERSIBLE: '5-3 reversible'}) +_keysvalues = {WAVELET_XFORM_9X7_IRREVERSIBLE: '9-7 irreversible', + WAVELET_XFORM_5X3_REVERSIBLE: '5-3 reversible'} +_WAVELET_TRANSFORM_DISPLAY = _Keydefaultdict(_factory, _keysvalues) _NO_PROFILE = 0 _PROFILE_0 = 1 @@ -51,12 +47,11 @@ _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. @@ -298,7 +293,6 @@ class Codestream(object): msg += ''.join(strs) return msg - # pylint: disable=R0201 def _parse_cme_segment(self, fptr): """Parse the CME marker segment. @@ -694,7 +688,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 as err: + except ZeroDivisionError: warnings.warn("Invalid tile dimensions.") else: numtiles = math.ceil(num_tiles_x) * math.ceil(num_tiles_y) @@ -828,7 +822,6 @@ 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 5f0d357..ff442f3 100644 --- a/glymur/command_line.py +++ b/glymur/command_line.py @@ -3,7 +3,6 @@ Entry point for console script jp2dump. """ import argparse import os -import sys import warnings from . import Jp2k, set_printoptions, lib diff --git a/glymur/core.py b/glymur/core.py index 3327253..644dcfd 100644 --- a/glymur/core.py +++ b/glymur/core.py @@ -1,8 +1,6 @@ """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 de1e62a..066edd2 100644 --- a/glymur/data/__init__.py +++ b/glymur/data/__init__.py @@ -43,4 +43,3 @@ def jpxfile(): """ filename = pkg_resources.resource_filename(__name__, "heliov.jpx") return filename - diff --git a/glymur/jp2box.py b/glymur/jp2box.py index 39e1f6a..4a390a5 100644 --- a/glymur/jp2box.py +++ b/glymur/jp2box.py @@ -11,8 +11,6 @@ References Extensions """ -# pylint: disable=C0302,R0903,R0913,W0142 - from collections import OrderedDict import datetime import io @@ -22,7 +20,7 @@ import pprint import struct import sys import textwrap -import uuid +from uuid import UUID import warnings import lxml.etree as ET @@ -44,11 +42,13 @@ _METHOD_DISPLAY = { VENDOR_COLOR_METHOD: 'vendor color method'} _factory = lambda x: '{0} (invalid)'.format(x) -_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'}) +_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) class Jp2kBox(object): @@ -1983,7 +1983,6 @@ 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)) @@ -2023,13 +2022,10 @@ 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) @@ -2073,80 +2069,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): @@ -2209,7 +2205,8 @@ class ReaderRequirementsBox(Jp2kBox): if _printoptions['short'] is True: return msg - msg += '\n Fully Understands Aspect Mask: 0x{0:x}'.format(self.fuam) + msg += '\n Fully Understands Aspect Mask: 0x{0:x}' + msg = msg.format(self.fuam) msg += '\n Display Completely Mask: 0x{0:x}'.format(self.dcm) msg += '\n Standard Features and Masks:' @@ -2265,8 +2262,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 @@ -2323,8 +2320,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[slice] - vendor_feature.append(uuid.UUID(bytes=ubuffer[0:16])) + ubuffer = read_buffer[uslice] + vendor_feature.append(UUID(bytes=ubuffer[0:16])) lst = struct.unpack('>BBB', ubuffer[16:]) vmask = lst[0] << 16 | lst[1] << 8 | lst[2] @@ -2392,7 +2389,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.UUID(bytes=ubuffer[0:16])) + vendor_feature.append(UUID(bytes=ubuffer[0:16])) vmask = struct.unpack('>' + mask_format, ubuffer[16:]) vendor_mask.append(vmask) @@ -2944,7 +2941,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.UUID(bytes=uuid_buffer)) + ulst.append(UUID(bytes=uuid_buffer)) return cls(ulst, length=length, offset=offset) @@ -3202,7 +3199,7 @@ class UUIDBox(Jp2kBox): """ Private function for parsing UUID payloads if possible. """ - if self.uuid == uuid.UUID('be7acfcb-97a9-42e8-9c71-999491e3afac'): + if self.uuid == UUID('be7acfcb-97a9-42e8-9c71-999491e3afac'): self.data = _uuid_io.xml(self.raw_data) elif self.uuid.bytes == b'JpgTiffExif->JP2': self.data = _uuid_io.tiff_header(self.raw_data) @@ -3220,7 +3217,7 @@ class UUIDBox(Jp2kBox): return msg msg = '{0}\n UUID: {1}'.format(msg, self.uuid) - if self.uuid == uuid.UUID('be7acfcb-97a9-42e8-9c71-999491e3afac'): + if self.uuid == UUID('be7acfcb-97a9-42e8-9c71-999491e3afac'): msg += ' (XMP)' elif self.uuid.bytes == b'JpgTiffExif->JP2': msg += ' (EXIF)' @@ -3228,11 +3225,11 @@ class UUIDBox(Jp2kBox): msg += ' (unknown)' if (((_printoptions['xml'] is False) and - (self.uuid == uuid.UUID('be7acfcb-97a9-42e8-9c71-999491e3afac')))): + (self.uuid == UUID('be7acfcb-97a9-42e8-9c71-999491e3afac')))): # If it's an XMP UUID, don't print the XML contents. return msg - if self.uuid == uuid.UUID('be7acfcb-97a9-42e8-9c71-999491e3afac'): + if self.uuid == UUID('be7acfcb-97a9-42e8-9c71-999491e3afac'): line = '\n UUID Data:\n{0}' xmlstring = ET.tostring(self.data, encoding='utf-8', @@ -3275,7 +3272,7 @@ class UUIDBox(Jp2kBox): """ num_bytes = offset + length - fptr.tell() read_buffer = fptr.read(num_bytes) - the_uuid = uuid.UUID(bytes=read_buffer[0:16]) + the_uuid = UUID(bytes=read_buffer[0:16]) return cls(the_uuid, read_buffer[16:], length=length, offset=offset) diff --git a/glymur/jp2k.py b/glymur/jp2k.py index b1e5c60..b5d61a2 100644 --- a/glymur/jp2k.py +++ b/glymur/jp2k.py @@ -10,13 +10,12 @@ 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 compress, filterfalse + from itertools import filterfalse else: from contextlib2 import ExitStack - from itertools import compress, ifilterfalse as filterfalse + from itertools import ifilterfalse as filterfalse from collections import Counter import ctypes @@ -517,12 +516,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): @@ -832,7 +831,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. @@ -1435,7 +1434,6 @@ 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/config.py b/glymur/lib/config.py index a639b38..8af038a 100644 --- a/glymur/lib/config.py +++ b/glymur/lib/config.py @@ -1,9 +1,6 @@ """ 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 diff --git a/glymur/lib/openjp2.py b/glymur/lib/openjp2.py index d398fb2..aed4db6 100644 --- a/glymur/lib/openjp2.py +++ b/glymur/lib/openjp2.py @@ -2,8 +2,6 @@ Wraps individual functions in openjp2 library. """ -# pylint: disable=C0302,R0903,W0201 - import ctypes import re import sys diff --git a/glymur/lib/openjpeg.py b/glymur/lib/openjpeg.py index 602f3b9..d2f156b 100644 --- a/glymur/lib/openjpeg.py +++ b/glymur/lib/openjpeg.py @@ -1,8 +1,6 @@ """Wraps library calls to openjpeg. """ -# pylint: disable=R0903 - import ctypes import sys diff --git a/glymur/lib/test/test_openjp2.py b/glymur/lib/test/test_openjp2.py index 988ace1..c32ee89 100644 --- a/glymur/lib/test/test_openjp2.py +++ b/glymur/lib/test/test_openjp2.py @@ -1,13 +1,8 @@ """ 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 @@ -21,8 +16,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. @@ -152,6 +147,7 @@ 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']) * @@ -215,7 +211,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): @@ -226,13 +222,14 @@ 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'] @@ -270,6 +267,7 @@ def tile_decoder(**kwargs): openjp2.stream_destroy(stream) openjp2.image_destroy(image) + def ttx0_setup(filename): """Runs tests tte0, tte0.""" kwargs = {'filename': filename, @@ -283,6 +281,7 @@ def ttx0_setup(filename): 'tile_width': 100} tile_encoder(**kwargs) + def xtx2_setup(filename): """Runs tests rta2, tte2, ttd2.""" kwargs = {'filename': filename, @@ -296,6 +295,7 @@ def xtx2_setup(filename): 'tile_width': 128} tile_encoder(**kwargs) + def xtx3_setup(filename): """Runs tests tte3, rta3.""" kwargs = {'filename': filename, @@ -309,6 +309,7 @@ def xtx3_setup(filename): 'tile_width': 128} tile_encoder(**kwargs) + def xtx4_setup(filename): """Runs tests rta4, tte4.""" kwargs = {'filename': filename, @@ -322,6 +323,7 @@ def xtx4_setup(filename): 'tile_width': 128} tile_encoder(**kwargs) + def xtx5_setup(filename): """Runs tests rta5, tte5.""" kwargs = {'filename': filename, @@ -334,6 +336,3 @@ 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 f28656c..449083f 100644 --- a/glymur/lib/test/test_openjpeg.py +++ b/glymur/lib/test/test_openjpeg.py @@ -1,8 +1,6 @@ """ Tests for OpenJPEG module. """ -# pylint: disable=E1101,R0904 - import ctypes import re import sys @@ -10,6 +8,7 @@ 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 fb78676..c7be21c 100644 --- a/glymur/lib/test/test_printing.py +++ b/glymur/lib/test/test_printing.py @@ -16,6 +16,7 @@ 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") @@ -72,6 +73,3 @@ 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 cf78051..c7bab78 100644 --- a/glymur/test/fixtures.py +++ b/glymur/test/fixtures.py @@ -236,7 +236,6 @@ 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 diff --git a/glymur/test/test_callbacks.py b/glymur/test/test_callbacks.py index 269a816..cc30de8 100644 --- a/glymur/test/test_callbacks.py +++ b/glymur/test/test_callbacks.py @@ -1,12 +1,6 @@ """ 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 @@ -99,8 +93,6 @@ 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 28a41cc..59a8ef3 100644 --- a/glymur/test/test_config.py +++ b/glymur/test/test_config.py @@ -1,15 +1,6 @@ """These tests are for edge cases where OPENJPEG does not exist, but OPENJP2 may be present in some form or other. """ -# 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 @@ -98,7 +89,6 @@ 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) diff --git a/glymur/test/test_glymur_warnings.py b/glymur/test/test_glymur_warnings.py index fa0c832..24d0413 100644 --- a/glymur/test/test_glymur_warnings.py +++ b/glymur/test/test_glymur_warnings.py @@ -1,10 +1,6 @@ """ Test suite for warnings issued by glymur. """ - -# unittest doesn't work well with R0904. -# pylint: disable=R0904 - import os import re import struct diff --git a/glymur/test/test_icc.py b/glymur/test/test_icc.py index 90ffc11..e18775c 100644 --- a/glymur/test/test_icc.py +++ b/glymur/test/test_icc.py @@ -1,10 +1,6 @@ """ ICC profile tests. """ - -# unittest doesn't work well with R0904. -# pylint: disable=R0904 - import datetime import unittest @@ -64,11 +60,6 @@ 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 9843b94..9ccd75b 100644 --- a/glymur/test/test_jp2box.py +++ b/glymur/test/test_jp2box.py @@ -1,18 +1,6 @@ """ 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 @@ -20,7 +8,6 @@ import shutil import struct import sys import tempfile -import uuid from uuid import UUID import unittest @@ -642,7 +629,7 @@ class TestAppend(unittest.TestCase): jp2 = Jp2k(tfile.name) # Make a UUID box. Only XMP UUID boxes can currently be appended. - uuid_instance = uuid.UUID('00000000-0000-0000-0000-000000000000') + uuid_instance = UUID('00000000-0000-0000-0000-000000000000') data = b'0123456789' uuidbox = glymur.jp2box.UUIDBox(uuid_instance, data) with self.assertRaises(IOError): @@ -1234,8 +1221,8 @@ class TestRepr(MetadataBase): def test_uuidlist_box(self): """Verify __repr__ method on ulst box.""" - uuid1 = uuid.UUID('00000000-0000-0000-0000-000000000001') - uuid2 = uuid.UUID('00000000-0000-0000-0000-000000000002') + uuid1 = UUID('00000000-0000-0000-0000-000000000001') + uuid2 = UUID('00000000-0000-0000-0000-000000000002') uuids = [uuid1, uuid2] ulst = glymur.jp2box.UUIDListBox(ulst=uuids) newbox = eval(repr(ulst)) @@ -1289,7 +1276,7 @@ class TestRepr(MetadataBase): def test_uuid_box_generic(self): """Verify uuid repr method.""" - uuid_instance = uuid.UUID('00000000-0000-0000-0000-000000000000') + uuid_instance = UUID('00000000-0000-0000-0000-000000000000') data = b'0123456789' box = glymur.jp2box.UUIDBox(the_uuid=uuid_instance, raw_data=data) diff --git a/glymur/test/test_jp2box_uuid.py b/glymur/test/test_jp2box_uuid.py index 409e43b..6886c30 100644 --- a/glymur/test/test_jp2box_uuid.py +++ b/glymur/test/test_jp2box_uuid.py @@ -1,15 +1,6 @@ # -*- 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 shutil import struct diff --git a/glymur/test/test_jp2box_xml.py b/glymur/test/test_jp2box_xml.py index 84a63f3..87bdd38 100644 --- a/glymur/test/test_jp2box_xml.py +++ b/glymur/test/test_jp2box_xml.py @@ -2,18 +2,6 @@ """ 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 diff --git a/glymur/test/test_jp2k.py b/glymur/test/test_jp2k.py index cb3a9e7..8827f83 100644 --- a/glymur/test/test_jp2k.py +++ b/glymur/test/test_jp2k.py @@ -1,15 +1,6 @@ """ 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 @@ -47,10 +38,6 @@ from . import fixtures # 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. diff --git a/glymur/test/test_opj_suite.py b/glymur/test/test_opj_suite.py index f512dfd..a121071 100644 --- a/glymur/test/test_opj_suite.py +++ b/glymur/test/test_opj_suite.py @@ -2,31 +2,6 @@ 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 diff --git a/glymur/test/test_opj_suite_dump.py b/glymur/test/test_opj_suite_dump.py index 6b198c1..0090ee3 100644 --- a/glymur/test/test_opj_suite_dump.py +++ b/glymur/test/test_opj_suite_dump.py @@ -2,31 +2,6 @@ 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 diff --git a/glymur/test/test_opj_suite_neg.py b/glymur/test/test_opj_suite_neg.py index 1d3ec6e..d2351a4 100644 --- a/glymur/test/test_opj_suite_neg.py +++ b/glymur/test/test_opj_suite_neg.py @@ -2,12 +2,6 @@ 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 tempfile diff --git a/glymur/test/test_opj_suite_write.py b/glymur/test/test_opj_suite_write.py index 7f0fd4b..eabb4bc 100644 --- a/glymur/test/test_opj_suite_write.py +++ b/glymur/test/test_opj_suite_write.py @@ -2,10 +2,6 @@ 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 diff --git a/glymur/test/test_printing.py b/glymur/test/test_printing.py index ab3e9fd..f9fcd73 100644 --- a/glymur/test/test_printing.py +++ b/glymur/test/test_printing.py @@ -1,15 +1,6 @@ # -*- 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 @@ -106,7 +97,7 @@ class TestPrinting(unittest.TestCase): data = glymur.Jp2k(self.jp2file)[::2, ::2] with tempfile.NamedTemporaryFile(suffix='.jp2') as tfile: with tempfile.NamedTemporaryFile(suffix='.jp2') as tfile2: - j = glymur.Jp2k(tfile.name, data=data) + glymur.Jp2k(tfile.name, data=data) # Offset of the codestream is where we start. wbuffer = tfile.read(77) diff --git a/setup.py b/setup.py index 1a61dc3..474b6c8 100644 --- a/setup.py +++ b/setup.py @@ -1,4 +1,4 @@ -from setuptools import setup, find_packages +from setuptools import setup import os import re import sys @@ -11,7 +11,9 @@ 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'], }, From 20f2c0c291dce90822d4f21581aa4c3a7a275418 Mon Sep 17 00:00:00 2001 From: John Evans Date: Wed, 31 Dec 2014 22:45:34 -0500 Subject: [PATCH 37/57] remove coverall changes, closes #298 no further action planned --- .travis.yml | 6 ------ 1 file changed, 6 deletions(-) diff --git a/.travis.yml b/.travis.yml index 822c717..406e470 100644 --- a/.travis.yml +++ b/.travis.yml @@ -9,7 +9,6 @@ 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: @@ -20,11 +19,6 @@ 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" From 8440d69222385f3300892485bc6b4d2a33cef067 Mon Sep 17 00:00:00 2001 From: John Evans Date: Wed, 31 Dec 2014 23:29:39 -0500 Subject: [PATCH 38/57] codestream now a property of Jp2k object, closes #275 repeated calls to get_codestream removed --- docs/source/how_do_i.rst | 4 ++-- glymur/jp2k.py | 40 ++++++++++++++++++++++++---------------- 2 files changed, 26 insertions(+), 18 deletions(-) diff --git a/docs/source/how_do_i.rst b/docs/source/how_do_i.rst index 8a62b32..33366b5 100644 --- a/docs/source/how_do_i.rst +++ b/docs/source/how_do_i.rst @@ -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 print all the gory codestream details as well, i.e. :: +It is possible to easily print the codestream header details as well, i.e. :: - >>> print(j.get_codestream()) # details not shown + >>> print(j.codestream) # details not show ... add XML metadata? ===================== diff --git a/glymur/jp2k.py b/glymur/jp2k.py index b5d61a2..de386dc 100644 --- a/glymur/jp2k.py +++ b/glymur/jp2k.py @@ -60,6 +60,8 @@ 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 -------- @@ -145,6 +147,7 @@ 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: @@ -179,6 +182,16 @@ 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 @@ -192,7 +205,7 @@ class Jp2k(Jp2kBox): if self._shape is not None: return self._shape - cstr = self.get_codestream(header_only=True) + cstr = self.codestream height = cstr.segment[1].ysiz width = cstr.segment[1].xsiz num_components = len(cstr.segment[1].xrsiz) @@ -233,8 +246,7 @@ class Jp2k(Jp2kBox): for box in self.box: metadata.append(str(box)) else: - codestream = self.get_codestream() - metadata.append(str(codestream)) + metadata.append(str(self.codestream)) return '\n'.join(metadata) def parse(self): @@ -865,10 +877,9 @@ class Jp2k(Jp2kBox): FileTypeBox(), JP2HeaderBox(), ContiguousCodestreamBox()] - codestream = self.get_codestream() - height = codestream.segment[1].ysiz - width = codestream.segment[1].xsiz - num_components = len(codestream.segment[1].xrsiz) + height = self.codestream.segment[1].ysiz + width = self.codestream.segment[1].xsiz + num_components = len(self.codestream.segment[1].xrsiz) if num_components < 3: colorspace = core.GREYSCALE else: @@ -907,10 +918,9 @@ class Jp2k(Jp2kBox): """ Slicing protocol. """ - codestream = self.get_codestream(header_only=True) - numrows = codestream.segment[1].ysiz - numcols = codestream.segment[1].xsiz - numbands = codestream.segment[1].Csiz + numrows = self.codestream.segment[1].ysiz + numcols = self.codestream.segment[1].xsiz + numbands = self.codestream.segment[1].Csiz if isinstance(pargs, int): # Not a very good use of this protocol, but technically legal. @@ -1072,9 +1082,8 @@ class Jp2k(Jp2kBox): def _subsampling_sanity_check(self): """Check for differing subsample factors. """ - codestream = self.get_codestream(header_only=True) - dxs = np.array(codestream.segment[1].xrsiz) - dys = np.array(codestream.segment[1].yrsiz) + dxs = np.array(self.codestream.segment[1].xrsiz) + dys = np.array(self.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 " @@ -1277,8 +1286,7 @@ class Jp2k(Jp2kBox): # Must check the specified rlevel against the maximum. if rlevel != 0: # Must check the specified rlevel against the maximum. - codestream = self.get_codestream() - max_rlevel = codestream.segment[2].spcod[4] + max_rlevel = self.codestream.segment[2].spcod[4] if rlevel == -1: # -1 is shorthand for the largest rlevel rlevel = max_rlevel From acf6b28bc96804b175b5c6ef62af17418d7c15f4 Mon Sep 17 00:00:00 2001 From: John Evans Date: Thu, 1 Jan 2015 09:07:19 -0500 Subject: [PATCH 39/57] fix broken test due to upstream openjpeg test suite changes, closes #308 removed test_NR_broken3_jp2_dump, it is mostly just an extreme duplicate case of test_NR_broken_jp2_dump. It must be skipped on 32bit platforms anyway. --- glymur/test/test_opj_suite.py | 2 +- glymur/test/test_opj_suite_dump.py | 87 ------------------------------ 2 files changed, 1 insertion(+), 88 deletions(-) diff --git a/glymur/test/test_opj_suite.py b/glymur/test/test_opj_suite.py index a121071..f5298f8 100644 --- a/glymur/test/test_opj_suite.py +++ b/glymur/test/test_opj_suite.py @@ -360,7 +360,7 @@ class TestSuiteWarns(MetadataBase): self.assertEqual(jpdata.shape, (512, 768, 3)) def test_NR_broken_jp2_dump(self): - jfile = opj_data_file('input/nonregression/broken.jp2') + jfile = opj_data_file('input/nonregression/broken1.jp2') with self.assertWarns(UserWarning): # colr box has bad length. diff --git a/glymur/test/test_opj_suite_dump.py b/glymur/test/test_opj_suite_dump.py index 0090ee3..f13b128 100644 --- a/glymur/test/test_opj_suite_dump.py +++ b/glymur/test/test_opj_suite_dump.py @@ -2919,93 +2919,6 @@ class TestSuiteWarns(MetadataBase): 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=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. From 3e723605b9aa72d13cab28f2960882d45537a887 Mon Sep 17 00:00:00 2001 From: John Evans Date: Thu, 1 Jan 2015 09:07:19 -0500 Subject: [PATCH 40/57] fix broken test due to upstream openjpeg test suite changes, closes #308 removed test_NR_broken3_jp2_dump, it is mostly just an extreme duplicate case of test_NR_broken_jp2_dump. It must be skipped on 32bit platforms anyway. refactored some NR_broken tests, consolidating them --- glymur/test/test_glymur_warnings.py | 22 -------- glymur/test/test_opj_suite.py | 22 +++++--- glymur/test/test_opj_suite_dump.py | 87 ----------------------------- 3 files changed, 14 insertions(+), 117 deletions(-) diff --git a/glymur/test/test_glymur_warnings.py b/glymur/test/test_glymur_warnings.py index 24d0413..ff18c6e 100644 --- a/glymur/test/test_glymur_warnings.py +++ b/glymur/test/test_glymur_warnings.py @@ -102,28 +102,6 @@ class TestWarnings(unittest.TestCase): with self.assertWarnsRegex(UserWarning, regex): 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): - 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') diff --git a/glymur/test/test_opj_suite.py b/glymur/test/test_opj_suite.py index a121071..431b480 100644 --- a/glymur/test/test_opj_suite.py +++ b/glymur/test/test_opj_suite.py @@ -359,11 +359,14 @@ class TestSuiteWarns(MetadataBase): jpdata = jp2k[:] self.assertEqual(jpdata.shape, (512, 768, 3)) - def test_NR_broken_jp2_dump(self): - jfile = opj_data_file('input/nonregression/broken.jp2') + def test_NR_broken1_jp2_dump(self): + jfile = opj_data_file('input/nonregression/broken1.jp2') - with self.assertWarns(UserWarning): - # colr box has bad length. + # 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): jp2 = Jp2k(jfile) ids = [box.box_id for box in jp2.box] @@ -584,13 +587,16 @@ class TestSuite2point0(unittest.TestCase): @unittest.skipIf(WARNING_INFRASTRUCTURE_ISSUE, WARNING_INFRASTRUCTURE_MSG) def test_NR_DEC_broken2_jp2_5_decode(self): - # Null pointer access + """ + Invalid marker ID on codestream, Null pointer access upon read. + """ jfile = opj_data_file('input/nonregression/broken2.jp2') + 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.assertWarns(UserWarning): - # Invalid marker ID. + with self.assertWarnsRegex(UserWarning, regex): Jp2k(jfile)[:] - self.assertTrue(True) @unittest.skipIf(WARNING_INFRASTRUCTURE_ISSUE, WARNING_INFRASTRUCTURE_MSG) def test_NR_DEC_broken4_jp2_7_decode(self): diff --git a/glymur/test/test_opj_suite_dump.py b/glymur/test/test_opj_suite_dump.py index 0090ee3..f13b128 100644 --- a/glymur/test/test_opj_suite_dump.py +++ b/glymur/test/test_opj_suite_dump.py @@ -2919,93 +2919,6 @@ class TestSuiteWarns(MetadataBase): 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=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. From 80f696c6002aa2c2209df2808529eeac12ec6d7e Mon Sep 17 00:00:00 2001 From: John Evans Date: Thu, 1 Jan 2015 15:14:54 -0500 Subject: [PATCH 41/57] fixed irreversible test to match upstream, closes #309 --- glymur/test/test_jp2k.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/glymur/test/test_jp2k.py b/glymur/test/test_jp2k.py index 8827f83..4dc4df4 100644 --- a/glymur/test/test_jp2k.py +++ b/glymur/test/test_jp2k.py @@ -1119,7 +1119,7 @@ class TestJp2kOpjDataRootWarnings(unittest.TestCase): @unittest.skipIf(OPJ_DATA_ROOT is None, "OPJ_DATA_ROOT environment variable not set") class TestJp2kOpjDataRoot(unittest.TestCase): - """These tests should be run by just about all configuration.""" + """These tests should be run by just about all configurations.""" @unittest.skipIf(re.match("0|1.[0-4]", glymur.version.openjpeg_version), "Must have openjpeg 1.5 or higher to run") @@ -1128,9 +1128,9 @@ class TestJp2kOpjDataRoot(unittest.TestCase): """Irreversible""" filename = opj_data_file('input/nonregression/issue141.rawl') expdata = np.fromfile(filename, dtype=np.uint16) - expdata.resize((2816, 2048)) + expdata.resize((32, 2048)) with tempfile.NamedTemporaryFile(suffix='.j2k') as tfile: - j = Jp2k(tfile.name, data=expdata, irreversible=True) + j = Jp2k(tfile.name, data=expdata, irreversible=True, numres=5) codestream = j.get_codestream() self.assertEqual(codestream.segment[2].spcod[8], From a921b1101df33a3a43c0510aede1c000ea4bab04 Mon Sep 17 00:00:00 2001 From: John Evans Date: Thu, 1 Jan 2015 22:17:55 -0500 Subject: [PATCH 42/57] refactor install_requires list, closes #310 split into install_requires and test_requires --- setup.py | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/setup.py b/setup.py index 474b6c8..0a62827 100644 --- a/setup.py +++ b/setup.py @@ -20,11 +20,13 @@ kwargs = {'name': 'Glymur', 'license': 'MIT', 'test_suite': 'glymur.test'} -instllrqrs = ['numpy>=1.4.1', 'lxml>=2.3.2'] +install_requires = ['numpy>=1.7.0', 'lxml>=3.0.0'] +test_requires = ['six>=1.7.0'] if sys.hexversion < 0x03030000: - instllrqrs.append('contextlib2>=0.4') - instllrqrs.append('mock>=1.0.1') -kwargs['install_requires'] = instllrqrs + install_requires.append('contextlib2>=0.4') + test_requires.append('mock>=1.0.1') +kwargs['install_requires'] = install_requires +kwargs['test_requires'] = test_requires clssfrs = ["Programming Language :: Python", "Programming Language :: Python :: 2.7", From 43da1824b6a18107251be579ecb15caed89de15a Mon Sep 17 00:00:00 2001 From: John Evans Date: Sun, 4 Jan 2015 20:21:33 -0500 Subject: [PATCH 43/57] don't error out on bad ftyp entry or colr method, closes #312 --- glymur/jp2box.py | 19 +++++++++++++------ glymur/test/test_jp2k.py | 9 +++++++++ glymur/test/test_opj_suite_dump.py | 1 - glymur/test/test_printing.py | 11 +++++++++++ 4 files changed, 33 insertions(+), 7 deletions(-) diff --git a/glymur/jp2box.py b/glymur/jp2box.py index 4a390a5..e29df28 100644 --- a/glymur/jp2box.py +++ b/glymur/jp2box.py @@ -35,11 +35,12 @@ from .core import (_COLORSPACE_MAP_DISPLAY, _COLOR_TYPE_MAP_DISPLAY, from . import _uuid_io -_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 = {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) _factory = lambda x: '{0} (invalid)'.format(x) _keysvalues = {1: 'accurately represents correct colorspace definition', @@ -1317,7 +1318,13 @@ class FileTypeBox(Jp2kBox): for j in range(int(num_entries)): entry, = struct.unpack_from('>4s', read_buffer, 8 + j * 4) if sys.hexversion >= 0x03000000: - entry = entry.decode('utf-8') + try: + entry = entry.decode('utf-8') + except UnicodeDecodeError as err: + # The entry is invalid, but we've got code to catch this + # later on. + pass + compatibility_list.append(entry) return cls(brand=brand, minor_version=minor_version, diff --git a/glymur/test/test_jp2k.py b/glymur/test/test_jp2k.py index 4dc4df4..4bc928b 100644 --- a/glymur/test/test_jp2k.py +++ b/glymur/test/test_jp2k.py @@ -272,6 +272,15 @@ class TestJp2k(unittest.TestCase): jp2 = Jp2k(jfile) self.assertEqual(jp2.shape, (128, 128)) + @unittest.skipIf(OPJ_DATA_ROOT is None, + "OPJ_DATA_ROOT environment variable not set") + 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_shape_j2k(self): """verify shape attribute for J2K file """ diff --git a/glymur/test/test_opj_suite_dump.py b/glymur/test/test_opj_suite_dump.py index f13b128..844ce9c 100644 --- a/glymur/test/test_opj_suite_dump.py +++ b/glymur/test/test_opj_suite_dump.py @@ -3,7 +3,6 @@ The tests defined here roughly correspond to what is in the OpenJPEG test suite. """ import re -import sys import unittest import numpy as np diff --git a/glymur/test/test_printing.py b/glymur/test/test_printing.py index f9fcd73..49fec57 100644 --- a/glymur/test/test_printing.py +++ b/glymur/test/test_printing.py @@ -831,6 +831,17 @@ 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') From dc2b2bda15447c89dc3a693f703bc4edaa5defc9 Mon Sep 17 00:00:00 2001 From: John Evans Date: Sun, 4 Jan 2015 21:39:14 -0500 Subject: [PATCH 44/57] the main header will be printed by default --- glymur/command_line.py | 16 +++++++++------- glymur/jp2box.py | 13 ++++++++----- 2 files changed, 17 insertions(+), 12 deletions(-) diff --git a/glymur/command_line.py b/glymur/command_line.py index ff442f3..0836108 100644 --- a/glymur/command_line.py +++ b/glymur/command_line.py @@ -13,23 +13,25 @@ def main(): Entry point for console script jp2dump. """ - description = 'Print JPEG2000 metadata.' - parser = argparse.ArgumentParser(description=description) + kwargs = {'description': 'Print JPEG2000 metadata.', + 'formatter_class': argparse.ArgumentDefaultsHelpFormatter} + parser = argparse.ArgumentParser(**kwargs) 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 suppressed all details, ' - chelp += '1 prints headers, 2 prints the full codestream' + chelp = 'Level of codestream information. 0 suppresses all details, ' + chelp += '1 prints the main header, 2 prints the full codestream.' parser.add_argument('-c', '--codestream', help=chelp, + metavar='LEVEL', nargs=1, type=int, - default=[0]) + default=[1]) parser.add_argument('filename') diff --git a/glymur/jp2box.py b/glymur/jp2box.py index e29df28..ba204a4 100644 --- a/glymur/jp2box.py +++ b/glymur/jp2box.py @@ -1040,10 +1040,11 @@ class ContiguousCodestreamBox(Jp2kBox): msg = Jp2kBox.__str__(self) if _printoptions['short'] is True: return msg - if _printoptions['codestream'] is False: + if _printoptions['siz']: + msg += '\n' + self._indent(str(self.main_header.segment[1]), + indent_level=4) return msg - msg += '\n Main header:' for segment in self.main_header.segment: msg += '\n' + self._indent(str(segment), indent_level=8) @@ -3360,7 +3361,7 @@ def get_parseoptions(): """ return _parseoptions -_printoptions = {'short': False, 'xml': True, 'codestream': True} +_printoptions = {'short': False, 'xml': True, 'siz': True} def set_printoptions(**kwargs): @@ -3377,8 +3378,10 @@ def set_printoptions(**kwargs): xml : bool, optional When False, printing of the XML contents of any XML boxes or UUID XMP boxes is suppressed. - codestream : bool, optional - When False, printing of the codestream contents is suppressed. + siz : bool, optional + When True, only the SIZ segment is printed. When False, the entire + codestream is printed. This option has no effect when the 'short' + option is set to True. See also -------- From e93392a10e8ec0f9c849aa129d86d5a81fd3f509 Mon Sep 17 00:00:00 2001 From: John Evans Date: Mon, 5 Jan 2015 08:13:31 -0500 Subject: [PATCH 45/57] print the main header by default --- glymur/jp2box.py | 10 +- glymur/test/fixtures.py | 184 +++++++++++++++++++++++++++++++++++ glymur/test/test_printing.py | 7 +- 3 files changed, 194 insertions(+), 7 deletions(-) diff --git a/glymur/jp2box.py b/glymur/jp2box.py index ba204a4..4307f48 100644 --- a/glymur/jp2box.py +++ b/glymur/jp2box.py @@ -1040,13 +1040,11 @@ class ContiguousCodestreamBox(Jp2kBox): msg = Jp2kBox.__str__(self) if _printoptions['short'] is True: return msg - if _printoptions['siz']: - msg += '\n' + self._indent(str(self.main_header.segment[1]), - indent_level=4) + if _printoptions['codestream'] is False: return msg for segment in self.main_header.segment: - msg += '\n' + self._indent(str(segment), indent_level=8) + msg += '\n' + self._indent(str(segment), indent_level=4) return msg @@ -1321,7 +1319,7 @@ class FileTypeBox(Jp2kBox): if sys.hexversion >= 0x03000000: try: entry = entry.decode('utf-8') - except UnicodeDecodeError as err: + except UnicodeDecodeError: # The entry is invalid, but we've got code to catch this # later on. pass @@ -3361,7 +3359,7 @@ def get_parseoptions(): """ return _parseoptions -_printoptions = {'short': False, 'xml': True, 'siz': True} +_printoptions = {'short': False, 'xml': True, 'codestream': True} def set_printoptions(**kwargs): diff --git a/glymur/test/fixtures.py b/glymur/test/fixtures.py index c7bab78..12b0c71 100644 --- a/glymur/test/fixtures.py +++ b/glymur/test/fixtures.py @@ -709,6 +709,190 @@ 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 '] +JP2 Header Box (jp2h) @ (32, 45) + Image Header Box (ihdr) @ (40, 22) + Size: [1456 2592 3] + Bitdepth: 8 + Signed: False + Compression: wavelet + Colorspace Unknown: False + Colour Specification Box (colr) @ (62, 15) + Method: enumerated colorspace + Precedence: 0 + Colorspace: sRGB +UUID Box (uuid) @ (77, 3146) + UUID: be7acfcb-97a9-42e8-9c71-999491e3afac (XMP) + UUID Data: + + + + + 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)""" + # Output of reader requirements printing for text_GBR.jp2 text_GBR_rreq = r"""Reader Requirements Box (rreq) @ (40, 109) Fully Understands Aspect Mask: 0xffff diff --git a/glymur/test/test_printing.py b/glymur/test/test_printing.py index 49fec57..55e3018 100644 --- a/glymur/test/test_printing.py +++ b/glymur/test/test_printing.py @@ -1098,7 +1098,12 @@ class TestJp2dump(unittest.TestCase): """Verify dumping with -x, suppress XML.""" actual = self.run_jp2dump(['', '-x', self.jp2file]) - self.assertEqual(actual, fixtures.nemo_dump_no_codestream_no_xml) + # shave off the XML and non-main-header segments + lines = fixtures.nemo.split('\n') + expected = lines[0:18] + expected.extend(lines[104:140]) + expected = '\n'.join(expected) + self.assertEqual(actual, expected) @unittest.skipIf(sys.hexversion < 0x03000000, "assertRegex not in 2.7") def test_codestream_0_with_j2k_file(self): From 2755e8edd439765acedc7fb11cac7bbfeeae9591 Mon Sep 17 00:00:00 2001 From: jevans Date: Mon, 5 Jan 2015 20:23:52 -0500 Subject: [PATCH 46/57] Jp2dump tests passing, more need to be written --- glymur/command_line.py | 16 +++++++++---- glymur/jp2box.py | 45 ++++++++++++++++++++++++++++-------- glymur/test/test_printing.py | 40 ++++++++++++++++++++------------ 3 files changed, 72 insertions(+), 29 deletions(-) diff --git a/glymur/command_line.py b/glymur/command_line.py index 0836108..4cd080d 100644 --- a/glymur/command_line.py +++ b/glymur/command_line.py @@ -60,11 +60,19 @@ 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) and - (codestream_level == 0))): - print('File: {0}'.format(os.path.basename(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)) elif print_full_codestream: - print(jp2.get_codestream(header_only=False)) + for box in jp2.box: + if box.box_id == 'jp2c': + box._get_codestream(header_only=False) + print(jp2) else: print(jp2) diff --git a/glymur/jp2box.py b/glymur/jp2box.py index 4307f48..bd60c30 100644 --- a/glymur/jp2box.py +++ b/glymur/jp2box.py @@ -1001,18 +1001,19 @@ class ContiguousCodestreamBox(Jp2kBox): offset of the box from the start of the file. longname : str more verbose description of the box. - main_header : Codestream object - contains list of main header marker/segments + codestream : Codestream object + Contains list of codestream marker/segments. By default, only the main + header is retrieved. main_header_offset : int offset of main header from start of file """ box_id = 'jp2c' longname = 'Contiguous Codestream' - def __init__(self, main_header=None, main_header_offset=None, length=0, + def __init__(self, codestream=None, main_header_offset=None, length=0, offset=-1): Jp2kBox.__init__(self) - self._main_header = main_header + self._codestream = codestream self.length = length self.offset = offset self.main_header_offset = main_header_offset @@ -1021,16 +1022,16 @@ class ContiguousCodestreamBox(Jp2kBox): self._filename = None @property - def main_header(self): - if self._main_header is None: + def codestream(self): + if self._codestream is None: if self._filename is not None: with open(self._filename, 'rb') as fptr: fptr.seek(self.main_header_offset) - main_header = Codestream(fptr, + codestream = Codestream(fptr, self._length, header_only=True) - self._main_header = main_header - return self._main_header + self._codestream = codestream + return self._codestream def __repr__(self): msg = "glymur.jp2box.ContiguousCodeStreamBox(main_header={0})" @@ -1043,7 +1044,7 @@ class ContiguousCodestreamBox(Jp2kBox): if _printoptions['codestream'] is False: return msg - for segment in self.main_header.segment: + for segment in self.codestream.segment: msg += '\n' + self._indent(str(segment), indent_level=4) return msg @@ -1076,6 +1077,30 @@ class ContiguousCodestreamBox(Jp2kBox): box._length = length return box + def _get_codestream(self, header_only=True): + """retrieve codestream + + Parameters + ---------- + header_only : bool, optional + If True, only marker segments in the main header are parsed. + Supplying False may impose a large performance penalty. + """ + with open(self.filename, 'rb') as fptr: + fptr.seek(self.offset) + read_buffer = fptr.read(8) + (box_length, _) = struct.unpack('>I4s', read_buffer) + if box_length == 0: + # The length of the box is presumed to last until the end + # of the file. Compute the effective length of the box. + box_length = os.path.getsize(fptr.name) - fptr.tell() + 8 + elif box_length == 1: + # Seek past the XL field. + read_buffer = fptr.read(8) + box_length, = struct.unpack('>Q', read_buffer) + self._codestream = Codestream(fptr, box_length - 8, + header_only=header_only) + class DataReferenceBox(Jp2kBox): """Container for Data Reference box information. diff --git a/glymur/test/test_printing.py b/glymur/test/test_printing.py index 55e3018..bef59ad 100644 --- a/glymur/test/test_printing.py +++ b/glymur/test/test_printing.py @@ -1055,25 +1055,44 @@ class TestJp2dump(unittest.TestCase): return actual def test_default_nemo(self): - """Should be able to dump a JP2 file's metadata with no codestream.""" + """by default one should get the main header""" actual = self.run_jp2dump(['', self.jp2file]) - self.assertEqual(actual, fixtures.nemo_dump_no_codestream) + # shave off the non-main-header segments + lines = fixtures.nemo.split('\n') + expected = lines[0:140] + expected = '\n'.join(expected) + self.assertEqual(actual, expected) - def test_codestream_0(self): + @unittest.skipIf(sys.hexversion < 0x03000000, "assertRegex not in 2.7") + + def test_jp2_codestream_0(self): """Verify dumping with -c 0, supressing all codestream details.""" actual = self.run_jp2dump(['', '-c', '0', self.jp2file]) expected = fixtures.nemo_dump_no_codestream self.assertEqual(actual, expected) - def test_codestream_1(self): + def test_jp2_codestream_1(self): """Verify dumping with -c 1, print just the header.""" actual = self.run_jp2dump(['', '-c', '1', self.jp2file]) - self.assertEqual(actual, fixtures.nemo_with_codestream_header) + # shave off the non-main-header segments + lines = fixtures.nemo.split('\n') + expected = lines[0:140] + expected = '\n'.join(expected) + self.assertEqual(actual, expected) - def test_codestream_2(self): + @unittest.skipIf(sys.hexversion < 0x03000000, "assertRegex not in 2.7") + def test_j2k_codestream_0(self): + """-c 0 should print just a single line when used on a codestream.""" + sys.argv = ['', '-c', '0', self.j2kfile] + with patch('sys.stdout', new=StringIO()) as fake_out: + command_line.main() + actual = fake_out.getvalue().strip() + self.assertRegex(actual, "File: .*") + + def test_j2k_codestream_2(self): """Verify dumping with -c 2, full details.""" with patch('sys.stdout', new=StringIO()) as fake_out: sys.argv = ['', '-c', '2', self.j2kfile] @@ -1104,12 +1123,3 @@ class TestJp2dump(unittest.TestCase): expected.extend(lines[104:140]) expected = '\n'.join(expected) self.assertEqual(actual, expected) - - @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: .*") From 7dfcc0fd7c77f7f90c1c44fe84ae23f10b026157 Mon Sep 17 00:00:00 2001 From: jevans Date: Mon, 5 Jan 2015 21:10:02 -0500 Subject: [PATCH 47/57] documented rename of ContiguousCodestream attribute codesream. --- docs/source/whatsnew/0.8.rst | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/docs/source/whatsnew/0.8.rst b/docs/source/whatsnew/0.8.rst index f36b593..5c87f5a 100644 --- a/docs/source/whatsnew/0.8.rst +++ b/docs/source/whatsnew/0.8.rst @@ -6,5 +6,7 @@ Changes in 0.8.0 ================= * Simplified writing images by moving data and options into the - constructor. This is backwards-incompatible with 0.7.x. + constructor. + * The main_header attribute of the ContiguousCodestream class is now called + codestream. * Deprecated :py:meth:`read` method in favor of array-style slicing. From aeec03c82986e9b0f796c8ed5978a8052fb74947 Mon Sep 17 00:00:00 2001 From: John Evans Date: Tue, 6 Jan 2015 09:23:23 -0500 Subject: [PATCH 48/57] blah --- glymur/test/test_printing.py | 18 ++++++++++++++---- 1 file changed, 14 insertions(+), 4 deletions(-) diff --git a/glymur/test/test_printing.py b/glymur/test/test_printing.py index 55e3018..3e5eefb 100644 --- a/glymur/test/test_printing.py +++ b/glymur/test/test_printing.py @@ -1055,10 +1055,15 @@ class TestJp2dump(unittest.TestCase): return actual def test_default_nemo(self): - """Should be able to dump a JP2 file's metadata with no codestream.""" + """should dump everything but non-main-header codestream segments""" actual = self.run_jp2dump(['', self.jp2file]) - self.assertEqual(actual, fixtures.nemo_dump_no_codestream) + # shave off the non-main-header segments + lines = fixtures.nemo.split('\n') + expected = lines[0:140] + expected = '\n'.join(expected) + + self.assertEqual(actual, expected) def test_codestream_0(self): """Verify dumping with -c 0, supressing all codestream details.""" @@ -1068,10 +1073,15 @@ class TestJp2dump(unittest.TestCase): self.assertEqual(actual, expected) def test_codestream_1(self): - """Verify dumping with -c 1, print just the header.""" + """Verify dumping with -c 1, same as default""" actual = self.run_jp2dump(['', '-c', '1', self.jp2file]) - self.assertEqual(actual, fixtures.nemo_with_codestream_header) + # shave off the non-main-header segments + lines = fixtures.nemo.split('\n') + expected = lines[0:140] + expected = '\n'.join(expected) + + self.assertEqual(actual, expected) def test_codestream_2(self): """Verify dumping with -c 2, full details.""" From fe5e784b585131b615c8cace4866b06e5841c8a3 Mon Sep 17 00:00:00 2001 From: John Evans Date: Tue, 6 Jan 2015 11:00:08 -0500 Subject: [PATCH 49/57] get all tests passing --- glymur/jp2box.py | 4 ++-- glymur/test/fixtures.py | 9 +++++++++ glymur/test/test_glymur_warnings.py | 7 +++++++ glymur/test/test_jp2box.py | 4 ++-- glymur/test/test_jp2k.py | 15 +++------------ glymur/test/test_opj_suite.py | 2 +- glymur/test/test_opj_suite_dump.py | 22 +++++++++++----------- glymur/test/test_opj_suite_write.py | 2 +- 8 files changed, 36 insertions(+), 29 deletions(-) diff --git a/glymur/jp2box.py b/glymur/jp2box.py index bd60c30..c946e6b 100644 --- a/glymur/jp2box.py +++ b/glymur/jp2box.py @@ -1034,8 +1034,8 @@ class ContiguousCodestreamBox(Jp2kBox): return self._codestream def __repr__(self): - msg = "glymur.jp2box.ContiguousCodeStreamBox(main_header={0})" - return msg.format(repr(self.main_header)) + msg = "glymur.jp2box.ContiguousCodeStreamBox(codestream={0})" + return msg.format(repr(self.codestream)) def __str__(self): msg = Jp2kBox.__str__(self) diff --git a/glymur/test/fixtures.py b/glymur/test/fixtures.py index 12b0c71..dc27b0e 100644 --- a/glymur/test/fixtures.py +++ b/glymur/test/fixtures.py @@ -2,6 +2,7 @@ Test fixtures common to more than one test point. """ import os +import platform import re import sys import textwrap @@ -33,6 +34,14 @@ elif re.match('1.[0-6]', six.__version__) is not None: WARNING_INFRASTRUCTURE_ISSUE = True msg = "Cannot run test with version {0} of python-six" WARNING_INFRASTRUCTURE_MSG = msg.format(six.__version__) +elif ((re.match('1.8', six.__version__) is not None) and + (sys.platform.startswith('linux')) and + (platform.linux_distribution() == ('LinuxMint', '17', 'qiana'))): + WARNING_INFRASTRUCTURE_ISSUE = True + linux_distribution = platform.linux_distribution() + msg = "Cannot run test with version {0} of python-six on {1}" + WARNING_INFRASTRUCTURE_MSG = msg.format(six.__version__, + platform.linux_distribution) # Cannot reopen a named temporary file in windows. WINDOWS_TMP_FILE_MSG = "cannot use NamedTemporaryFile like this in windows" diff --git a/glymur/test/test_glymur_warnings.py b/glymur/test/test_glymur_warnings.py index ff18c6e..1d3dc2e 100644 --- a/glymur/test/test_glymur_warnings.py +++ b/glymur/test/test_glymur_warnings.py @@ -20,6 +20,13 @@ from .fixtures import 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 diff --git a/glymur/test/test_jp2box.py b/glymur/test/test_jp2box.py index 9ccd75b..e43eae6 100644 --- a/glymur/test/test_jp2box.py +++ b/glymur/test/test_jp2box.py @@ -1016,7 +1016,7 @@ class TestJp2Boxes(unittest.TestCase): """Raw instantiation should not produce a main_header.""" box = ContiguousCodestreamBox() self.assertEqual(box.box_id, 'jp2c') - self.assertIsNone(box.main_header) + self.assertIsNone(box.codestream) def test_codestream_main_header_offset(self): """main_header_offset is an attribute of the CCS box""" @@ -1318,7 +1318,7 @@ class TestRepr(MetadataBase): # Difficult to eval(repr()) this, so just match the general pattern. regexp = "glymur.jp2box.ContiguousCodeStreamBox" - regexp += "[(]main_header= Date: Tue, 6 Jan 2015 16:35:38 -0500 Subject: [PATCH 50/57] replaced main_header codestream attribute with codestream changed "codestream" parameter of set_parseoptions to "full_codestream" --- glymur/command_line.py | 14 ++------- glymur/jp2box.py | 61 +++++++++++++----------------------- glymur/test/test_jp2k.py | 13 ++++---- glymur/test/test_printing.py | 11 ++++++- 4 files changed, 40 insertions(+), 59 deletions(-) diff --git a/glymur/command_line.py b/glymur/command_line.py index 4cd080d..3d1d57e 100644 --- a/glymur/command_line.py +++ b/glymur/command_line.py @@ -5,7 +5,7 @@ import argparse import os import warnings -from . import Jp2k, set_printoptions, lib +from . import Jp2k, set_printoptions, set_parseoptions, lib def main(): @@ -47,11 +47,8 @@ def main(): if codestream_level == 0: set_printoptions(codestream=False) - print_full_codestream = False - elif codestream_level == 1: - print_full_codestream = False - else: - print_full_codestream = True + elif codestream_level == 2: + set_parseoptions(full_codestream=True) filename = args.filename @@ -68,11 +65,6 @@ def main(): elif codestream_level == 2: print('File: {0}'.format(os.path.basename(filename))) print(jp2.get_codestream(header_only=False)) - elif print_full_codestream: - for box in jp2.box: - if box.box_id == 'jp2c': - box._get_codestream(header_only=False) - print(jp2) else: print(jp2) diff --git a/glymur/jp2box.py b/glymur/jp2box.py index c946e6b..1cbd53a 100644 --- a/glymur/jp2box.py +++ b/glymur/jp2box.py @@ -1023,13 +1023,17 @@ class ContiguousCodestreamBox(Jp2kBox): @property def codestream(self): + if _parseoptions['full_codestream'] is True: + header_only = False + else: + header_only = True if self._codestream 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=True) + header_only=header_only) self._codestream = codestream return self._codestream @@ -1067,40 +1071,16 @@ class ContiguousCodestreamBox(Jp2kBox): ContiguousCodestreamBox instance """ main_header_offset = fptr.tell() - if _parseoptions['codestream'] is True: - main_header = Codestream(fptr, length, header_only=True) + if _parseoptions['full_codestream'] is True: + codestream = Codestream(fptr, length, header_only=False) else: - main_header = None - box = cls(main_header, main_header_offset=main_header_offset, + codestream = None + box = cls(codestream, main_header_offset=main_header_offset, length=length, offset=offset) box._filename = fptr.name box._length = length return box - def _get_codestream(self, header_only=True): - """retrieve codestream - - Parameters - ---------- - header_only : bool, optional - If True, only marker segments in the main header are parsed. - Supplying False may impose a large performance penalty. - """ - with open(self.filename, 'rb') as fptr: - fptr.seek(self.offset) - read_buffer = fptr.read(8) - (box_length, _) = struct.unpack('>I4s', read_buffer) - if box_length == 0: - # The length of the box is presumed to last until the end - # of the file. Compute the effective length of the box. - box_length = os.path.getsize(fptr.name) - fptr.tell() + 8 - elif box_length == 1: - # Seek past the XL field. - read_buffer = fptr.read(8) - box_length, = struct.unpack('>Q', read_buffer) - self._codestream = Codestream(fptr, box_length - 8, - header_only=header_only) - class DataReferenceBox(Jp2kBox): """Container for Data Reference box information. @@ -3338,19 +3318,20 @@ _BOX_WITH_ID = { b'uuid': UUIDBox, b'xml ': XMLBox} -_parseoptions = {'codestream': True} +_parseoptions = {'full_codestream': False} -def set_parseoptions(codestream=True): +def set_parseoptions(full_codestream=True): """Set parsing options. These options determine the way JPEG 2000 boxes are parsed. Parameters ---------- - codestream : bool, defaults to True - When False, the codestream header is only parsed when accessed. This - can results in faster JP2/JPX parsing. + 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. See also -------- @@ -3361,9 +3342,9 @@ def set_parseoptions(codestream=True): To put back the default options, you can use: >>> import glymur - >>> glymur.set_parseoptions(codestream=True) + >>> glymur.set_parseoptions(full_codestream=True) """ - _parseoptions['codestream'] = codestream + _parseoptions['full_codestream'] = full_codestream def get_parseoptions(): @@ -3401,10 +3382,10 @@ def set_printoptions(**kwargs): xml : bool, optional When False, printing of the XML contents of any XML boxes or UUID XMP boxes is suppressed. - siz : bool, optional - When True, only the SIZ segment is printed. When False, the entire - codestream is printed. This option has no effect when the 'short' - option is set to True. + 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. See also -------- diff --git a/glymur/test/test_jp2k.py b/glymur/test/test_jp2k.py index 53f174a..fe18022 100644 --- a/glymur/test/test_jp2k.py +++ b/glymur/test/test_jp2k.py @@ -1043,26 +1043,25 @@ class TestParsing(unittest.TestCase): def setUp(self): self.jp2file = glymur.data.nemo() # Reset parseoptions for every test. - glymur.set_parseoptions(codestream=True) + glymur.set_parseoptions(full_codestream=False) def tearDown(self): - glymur.set_parseoptions(codestream=True) + glymur.set_parseoptions(full_codestream=False) @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(codestream=False) - Jp2k(filename) + glymur.set_parseoptions(full_codestream=False) + jp2 = Jp2k(filename) - glymur.set_parseoptions(codestream=True) + glymur.set_parseoptions(full_codestream=True) with self.assertWarnsRegex(UserWarning, 'Invalid profile'): Jp2k(filename) def test_main_header(self): - """Verify that the main header isn't loaded when parsing turned off.""" + """verify that the main header isn't loaded during normal parsing""" # 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) diff --git a/glymur/test/test_printing.py b/glymur/test/test_printing.py index bef59ad..c141d65 100644 --- a/glymur/test/test_printing.py +++ b/glymur/test/test_printing.py @@ -1040,9 +1040,10 @@ 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): - pass + glymur.set_parseoptions(full_codestream=False) def run_jp2dump(self, args): sys.argv = args @@ -1083,6 +1084,14 @@ class TestJp2dump(unittest.TestCase): expected = '\n'.join(expected) self.assertEqual(actual, expected) + 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.""" From 4ceb4dce61b0f69719d5cdacdf4cc24e2ee3da86 Mon Sep 17 00:00:00 2001 From: John Evans Date: Tue, 6 Jan 2015 16:37:55 -0500 Subject: [PATCH 51/57] pep8 work --- glymur/jp2box.py | 3 +-- glymur/test/test_jp2k.py | 2 +- glymur/test/test_printing.py | 1 - 3 files changed, 2 insertions(+), 4 deletions(-) diff --git a/glymur/jp2box.py b/glymur/jp2box.py index 1cbd53a..bc23ebe 100644 --- a/glymur/jp2box.py +++ b/glymur/jp2box.py @@ -1031,8 +1031,7 @@ class ContiguousCodestreamBox(Jp2kBox): if self._filename is not None: with open(self._filename, 'rb') as fptr: fptr.seek(self.main_header_offset) - codestream = Codestream(fptr, - self._length, + codestream = Codestream(fptr, self._length, header_only=header_only) self._codestream = codestream return self._codestream diff --git a/glymur/test/test_jp2k.py b/glymur/test/test_jp2k.py index fe18022..8affe7d 100644 --- a/glymur/test/test_jp2k.py +++ b/glymur/test/test_jp2k.py @@ -1053,7 +1053,7 @@ class TestParsing(unittest.TestCase): """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) - jp2 = Jp2k(filename) + Jp2k(filename) glymur.set_parseoptions(full_codestream=True) with self.assertWarnsRegex(UserWarning, 'Invalid profile'): diff --git a/glymur/test/test_printing.py b/glymur/test/test_printing.py index c141d65..dfdd505 100644 --- a/glymur/test/test_printing.py +++ b/glymur/test/test_printing.py @@ -1066,7 +1066,6 @@ class TestJp2dump(unittest.TestCase): self.assertEqual(actual, expected) @unittest.skipIf(sys.hexversion < 0x03000000, "assertRegex not in 2.7") - def test_jp2_codestream_0(self): """Verify dumping with -c 0, supressing all codestream details.""" actual = self.run_jp2dump(['', '-c', '0', self.jp2file]) From 059bee50e2bd9a3a5b69f6b87f1cb868c27af31b Mon Sep 17 00:00:00 2001 From: John Evans Date: Tue, 6 Jan 2015 19:55:59 -0500 Subject: [PATCH 52/57] all tests passing on opensuse --- glymur/test/test_glymur_warnings.py | 16 ++++++++-------- glymur/test/test_jp2k.py | 9 ++++++++- glymur/test/test_opj_suite_dump.py | 27 ++++++++++++++++++--------- glymur/test/test_printing.py | 4 ++-- 4 files changed, 36 insertions(+), 20 deletions(-) diff --git a/glymur/test/test_glymur_warnings.py b/glymur/test/test_glymur_warnings.py index 1d3dc2e..8086004 100644 --- a/glymur/test/test_glymur_warnings.py +++ b/glymur/test/test_glymur_warnings.py @@ -69,7 +69,7 @@ class TestWarnings(unittest.TestCase): \(\d+\)\.""", re.VERBOSE) with self.assertWarnsRegex(UserWarning, regex): - Jp2k(jfile) + Jp2k(jfile).get_codestream() @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 +84,7 @@ class TestWarnings(unittest.TestCase): \(\d+\)\.""", re.VERBOSE) with self.assertWarnsRegex(UserWarning, regex): - Jp2k(jfile) + Jp2k(jfile).get_codestream() def test_NR_gdal_fuzzer_check_comp_dx_dy_jp2_dump(self): """ @@ -97,7 +97,7 @@ class TestWarnings(unittest.TestCase): dx=\d+,\s*dy=\d+""", re.VERBOSE) with self.assertWarnsRegex(UserWarning, regex): - Jp2k(jfile) + Jp2k(jfile).get_codestream() def test_NR_gdal_fuzzer_assert_in_opj_j2k_read_SQcd_SQcc_patch_jp2(self): lst = ['input', 'nonregression', @@ -107,32 +107,32 @@ class TestWarnings(unittest.TestCase): number\sof\scomponents\sis\sonly\s\d+""", re.VERBOSE) with self.assertWarnsRegex(UserWarning, regex): - Jp2k(jfile) + Jp2k(jfile).get_codestream() 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) + Jp2k(filename).get_codestream() 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) + Jp2k(filename).get_codestream() 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) + Jp2k(jfile).get_codestream() 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) with self.assertWarnsRegex(UserWarning, 'Invalid tile dimensions'): - Jp2k(filename) + Jp2k(filename).get_codestream() @unittest.skipIf(os.name == "nt", "Temporary file issue on window.") def test_unknown_marker_segment(self): diff --git a/glymur/test/test_jp2k.py b/glymur/test/test_jp2k.py index 8affe7d..668f8d5 100644 --- a/glymur/test/test_jp2k.py +++ b/glymur/test/test_jp2k.py @@ -36,6 +36,9 @@ 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): """Should run doc tests as well""" @@ -43,7 +46,8 @@ def load_tests(loader, tests, ignore): # 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')) + tests.addTests(doctest.DocTestSuite('glymur.jp2k', + tearDown=docTearDown)) return tests @@ -1075,6 +1079,9 @@ class TestParsing(unittest.TestCase): class TestJp2kOpjDataRootWarnings(unittest.TestCase): """These tests should be run by just about all configuration.""" + def tearDown(self): + glymur.set_parseoptions(full_codestream=False) + def test_undecodeable_box_id(self): """Should warn in case of undecodeable box ID but not error out.""" filename = opj_data_file('input/nonregression/edf_c2_1013627.jp2') diff --git a/glymur/test/test_opj_suite_dump.py b/glymur/test/test_opj_suite_dump.py index 8920473..7ac513f 100644 --- a/glymur/test/test_opj_suite_dump.py +++ b/glymur/test/test_opj_suite_dump.py @@ -4,6 +4,7 @@ suite. """ import re import unittest +import warnings import numpy as np @@ -2913,21 +2914,29 @@ class TestSuiteWarns(MetadataBase): def test_NR_broken4_jp2_dump(self): jfile = opj_data_file('input/nonregression/broken4.jp2') - with self.assertWarns(UserWarning): - jp2 = Jp2k(jfile) - - self.assertEqual(jp2.box[-1].codestream.segment[-1].marker_id, 'QCC') + 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') def test_NR_broken2_jp2_dump(self): """ Invalid marker ID in the codestream. """ jfile = opj_data_file('input/nonregression/broken2.jp2') - with self.assertWarns(UserWarning): - # Invalid marker ID on codestream. - jp2 = Jp2k(jfile) - - self.assertEqual(jp2.box[-1].codestream.segment[-1].marker_id, 'QCC') + 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') def test_NR_file1_dump(self): jfile = opj_data_file('input/conformance/file1.jp2') diff --git a/glymur/test/test_printing.py b/glymur/test/test_printing.py index dfdd505..5310fa9 100644 --- a/glymur/test/test_printing.py +++ b/glymur/test/test_printing.py @@ -42,7 +42,7 @@ class TestPrinting(unittest.TestCase): glymur.set_printoptions(short=False, xml=True, codestream=True) def tearDown(self): - pass + glymur.set_parseoptions(full_codestream=False) def test_version_info(self): """Should be able to print(glymur.version.info)""" @@ -854,7 +854,7 @@ class TestPrintingOpjDataRootWarns(unittest.TestCase): """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) + j = Jp2k(filename).get_codestream() with patch('sys.stdout', new=StringIO()): print(j) From 4d680cf90ba561e20f688edc7beb30aa4a2c1a98 Mon Sep 17 00:00:00 2001 From: John Evans Date: Wed, 7 Jan 2015 08:40:08 -0500 Subject: [PATCH 53/57] refactor shape property to be less dependent on property, closes #315 --- docs/source/detailed_installation.rst | 5 ++- glymur/jp2k.py | 50 +++++++++++++++------------ 2 files changed, 31 insertions(+), 24 deletions(-) diff --git a/docs/source/detailed_installation.rst b/docs/source/detailed_installation.rst index 1a9281c..7068b56 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,6 +50,9 @@ 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/glymur/jp2k.py b/glymur/jp2k.py index de386dc..d45f0db 100644 --- a/glymur/jp2k.py +++ b/glymur/jp2k.py @@ -205,28 +205,30 @@ class Jp2k(Jp2kBox): if self._shape is not None: return self._shape - cstr = self.codestream - height = cstr.segment[1].ysiz - width = cstr.segment[1].xsiz - num_components = len(cstr.segment[1].xrsiz) + 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) - # If JP2 and a palette box is present, then determine the shape from - # that. if num_components == 1: - 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)) + self.shape = (height, width) else: self.shape = (height, width, num_components) @@ -918,9 +920,11 @@ class Jp2k(Jp2kBox): """ Slicing protocol. """ - numrows = self.codestream.segment[1].ysiz - numcols = self.codestream.segment[1].xsiz - numbands = self.codestream.segment[1].Csiz + if len(self.shape) == 2: + numrows, numcols = self.shape + numbands = 1 + else: + numrows, numcols, numbands = self.shape if isinstance(pargs, int): # Not a very good use of this protocol, but technically legal. From 4686c40c57a7fcd4b643496eb0714cbc629f5dee Mon Sep 17 00:00:00 2001 From: John Evans Date: Thu, 8 Jan 2015 12:07:10 -0500 Subject: [PATCH 54/57] fix test failure, not a real bug, closes #316 Had assumed that the error was due to parse_options not being properly reset, but that was not the case. Seems to have just been bad expected data. --- glymur/jp2box.py | 2 +- glymur/jp2k.py | 22 +++++++++++----------- glymur/test/fixtures.py | 4 ++-- glymur/test/test_jp2k.py | 4 +--- glymur/test/test_printing.py | 6 ++++-- 5 files changed, 19 insertions(+), 19 deletions(-) diff --git a/glymur/jp2box.py b/glymur/jp2box.py index bc23ebe..98b0e6a 100644 --- a/glymur/jp2box.py +++ b/glymur/jp2box.py @@ -1032,7 +1032,7 @@ class ContiguousCodestreamBox(Jp2kBox): with open(self._filename, 'rb') as fptr: fptr.seek(self.main_header_offset) codestream = Codestream(fptr, self._length, - header_only=header_only) + header_only=header_only) self._codestream = codestream return self._codestream diff --git a/glymur/jp2k.py b/glymur/jp2k.py index d45f0db..ee6eedc 100644 --- a/glymur/jp2k.py +++ b/glymur/jp2k.py @@ -213,19 +213,19 @@ class Jp2k(Jp2kBox): 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] + 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 + 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) + 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) if num_components == 1: self.shape = (height, width) diff --git a/glymur/test/fixtures.py b/glymur/test/fixtures.py index 8d6165e..f6b8ef8 100644 --- a/glymur/test/fixtures.py +++ b/glymur/test/fixtures.py @@ -34,8 +34,8 @@ elif re.match('1.[0-6]', six.__version__) is not None: WARNING_INFRASTRUCTURE_ISSUE = True msg = "Cannot run test with version {0} of python-six" WARNING_INFRASTRUCTURE_MSG = msg.format(six.__version__) -elif ((re.match('1.8', six.__version__) is not None) and - (sys.platform.startswith('linux')) and +elif ((re.match('1.8', six.__version__) is not None) and + (sys.platform.startswith('linux')) and (platform.linux_distribution() == ('LinuxMint', '17', 'qiana'))): WARNING_INFRASTRUCTURE_ISSUE = True linux_distribution = platform.linux_distribution() diff --git a/glymur/test/test_jp2k.py b/glymur/test/test_jp2k.py index 668f8d5..52945f9 100644 --- a/glymur/test/test_jp2k.py +++ b/glymur/test/test_jp2k.py @@ -39,6 +39,7 @@ 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): """Should run doc tests as well""" @@ -1079,9 +1080,6 @@ class TestParsing(unittest.TestCase): class TestJp2kOpjDataRootWarnings(unittest.TestCase): """These tests should be run by just about all configuration.""" - def tearDown(self): - glymur.set_parseoptions(full_codestream=False) - def test_undecodeable_box_id(self): """Should warn in case of undecodeable box ID but not error out.""" filename = opj_data_file('input/nonregression/edf_c2_1013627.jp2') diff --git a/glymur/test/test_printing.py b/glymur/test/test_printing.py index 5310fa9..bccaa00 100644 --- a/glymur/test/test_printing.py +++ b/glymur/test/test_printing.py @@ -1065,12 +1065,14 @@ class TestJp2dump(unittest.TestCase): expected = '\n'.join(expected) self.assertEqual(actual, expected) - @unittest.skipIf(sys.hexversion < 0x03000000, "assertRegex not in 2.7") def test_jp2_codestream_0(self): """Verify dumping with -c 0, supressing all codestream details.""" actual = self.run_jp2dump(['', '-c', '0', self.jp2file]) - expected = fixtures.nemo_dump_no_codestream + # shave off the codestream details + lines = fixtures.nemo.split('\n') + expected = lines[0:105] + expected = '\n'.join(expected) self.assertEqual(actual, expected) def test_jp2_codestream_1(self): From 8cc11552522f08f79427d17fc6c99bfac1bad807 Mon Sep 17 00:00:00 2001 From: John Evans Date: Thu, 8 Jan 2015 13:23:55 -0500 Subject: [PATCH 55/57] removed check for six version 1.8.0, closes #314 Not sure how this issue came about as it no longer seems to exist. The version of six installed on Linux Mint 17 is 1.5.2, not 1.8.0 as thought when the issue was filed. All seems ok. --- glymur/test/fixtures.py | 9 --------- 1 file changed, 9 deletions(-) diff --git a/glymur/test/fixtures.py b/glymur/test/fixtures.py index f6b8ef8..34327fc 100644 --- a/glymur/test/fixtures.py +++ b/glymur/test/fixtures.py @@ -2,7 +2,6 @@ Test fixtures common to more than one test point. """ import os -import platform import re import sys import textwrap @@ -34,14 +33,6 @@ elif re.match('1.[0-6]', six.__version__) is not None: WARNING_INFRASTRUCTURE_ISSUE = True msg = "Cannot run test with version {0} of python-six" WARNING_INFRASTRUCTURE_MSG = msg.format(six.__version__) -elif ((re.match('1.8', six.__version__) is not None) and - (sys.platform.startswith('linux')) and - (platform.linux_distribution() == ('LinuxMint', '17', 'qiana'))): - WARNING_INFRASTRUCTURE_ISSUE = True - linux_distribution = platform.linux_distribution() - msg = "Cannot run test with version {0} of python-six on {1}" - WARNING_INFRASTRUCTURE_MSG = msg.format(six.__version__, - platform.linux_distribution) # Cannot reopen a named temporary file in windows. WINDOWS_TMP_FILE_MSG = "cannot use NamedTemporaryFile like this in windows" From 2ffdf716c062f78e68bb81afd10973965fd1caaa Mon Sep 17 00:00:00 2001 From: John Evans Date: Thu, 8 Jan 2015 15:30:10 -0500 Subject: [PATCH 56/57] remove test requirement for six, doc modifications, doctest fix The test requirement for six was problematic, as some versions cause problems with assertWarns and some do not. We are already filtering out versions that we know cause problems and it can unintentionally cause an upgrade superceding the system version if it remains as a "test_requires" option, so best to get rid of it. Additionally, the "test_requires" option was entirely removed as pip doesn't recognize it upon install, so "mock" would not be installed on Python2.7 via pip. The doctest fix was the real fix for #316, not sure why this did not show up when testing on linux mint --- CHANGES.txt | 5 ++ docs/source/api.rst | 116 ----------------------------------- docs/source/conf.py | 4 +- docs/source/how_do_i.rst | 8 +-- docs/source/index.rst | 1 - docs/source/whatsnew/0.8.rst | 16 ++++- glymur/test/test_jp2box.py | 7 ++- glymur/version.py | 2 +- setup.py | 4 +- 9 files changed, 33 insertions(+), 130 deletions(-) delete mode 100644 docs/source/api.rst diff --git a/CHANGES.txt b/CHANGES.txt index 758941b..98e6730 100644 --- a/CHANGES.txt +++ b/CHANGES.txt @@ -1,3 +1,8 @@ +Jan 08, 2015 - v0.8.0rc1 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 deleted file mode 100644 index 7584718..0000000 --- a/docs/source/api.rst +++ /dev/null @@ -1,116 +0,0 @@ ---- -API ---- - -Jp2k ----- -.. autoclass:: glymur.Jp2k - :members: read, write, wrap, read_bands, get_codestream - -Individual Boxes ----------------- -Jp2kbox -''''''' -.. autoclass:: glymur.jp2box.Jp2kBox - :members: - -AssociationBox -'''''''''''''' -.. autoclass:: glymur.jp2box.AssociationBox - :members: - -ColourSpecificationBox -'''''''''''''''''''''' -.. autoclass:: glymur.jp2box.ColourSpecificationBox - :members: - -ChannelDefinitionBox -'''''''''''''''''''''' -.. autoclass:: glymur.jp2box.ChannelDefinitionBox - :members: - -ComponentMappingBox -''''''''''''''''''' -.. autoclass:: glymur.jp2box.ComponentMappingBox - :members: - -ContiguousCodestreamBox -''''''''''''''''''''''' -.. autoclass:: glymur.jp2box.ContiguousCodestreamBox - :members: - -DataEntryURLBox -''''''''''''''' -.. autoclass:: glymur.jp2box.DataEntryURLBox - :members: - -FileTypeBox -''''''''''' -.. autoclass:: glymur.jp2box.FileTypeBox - :members: - -ImageHeaderBox -'''''''''''''' -.. autoclass:: glymur.jp2box.ImageHeaderBox - :members: - -JP2HeaderBox -'''''''''''' -.. autoclass:: glymur.jp2box.JP2HeaderBox - :members: - -JPEG2000SignatureBox -'''''''''''''''''''' -.. autoclass:: glymur.jp2box.JPEG2000SignatureBox - :members: - -LabelBox -'''''''' -.. autoclass:: glymur.jp2box.LabelBox - :members: - -PaletteBox -'''''''''' -.. autoclass:: glymur.jp2box.PaletteBox - :members: - -ReaderRequirementsBox -''''''''''''''''''''' -.. autoclass:: glymur.jp2box.ReaderRequirementsBox - :members: - -ResolutionBox -''''''''''''' -.. autoclass:: glymur.jp2box.ResolutionBox - :members: - -CaptureResolutionBox -'''''''''''''''''''' -.. autoclass:: glymur.jp2box.CaptureResolutionBox - :members: - -DisplayResolutionBox -'''''''''''''''''''' -.. autoclass:: glymur.jp2box.DisplayResolutionBox - :members: - -UUIDBox -''''''' -.. autoclass:: glymur.jp2box.UUIDBox - :members: - -UUIDInfoBox -''''''''''' -.. autoclass:: glymur.jp2box.UUIDInfoBox - :members: - -UUIDListBox -''''''''''' -.. autoclass:: glymur.jp2box.UUIDListBox - :members: - -XMLBox -'''''' -.. autoclass:: glymur.jp2box.XMLBox - :members: - diff --git a/docs/source/conf.py b/docs/source/conf.py index e9387f4..f90815d 100644 --- a/docs/source/conf.py +++ b/docs/source/conf.py @@ -75,9 +75,9 @@ copyright = u'2013, John Evans' # built documents. # # The short X.Y version. -version = '0.7' +version = '0.8' # The full version, including alpha/beta/rc tags. -release = '0.7.2' +release = '0.8.0rc2' # The language for content autogenerated by Sphinx. Refer to documentation # for a list of supported languages. diff --git a/docs/source/how_do_i.rst b/docs/source/how_do_i.rst index 33366b5..88d94fa 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 - >>> data = np.zeros((640, 480), dtype=np.uint8) - >>> jp2 = glymur.Jp2k('zeros.jp2', data=data) + >>> jp2 = glymur.Jp2k('zeros.jp2', data=np.zeros((640, 480), dtype=np.uint8) -You should have OpenJPEG version 1.5 or more recent before writing JPEG 2000 images. +You must have OpenJPEG version 1.5 or more recent in order to write JPEG 2000 +images with glymur. ... display 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 version 2.0):: +Toolkit (make sure it is at least 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 8c1fb03..62e118d 100644 --- a/docs/source/index.rst +++ b/docs/source/index.rst @@ -17,7 +17,6 @@ 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 5c87f5a..e7215ad 100644 --- a/docs/source/whatsnew/0.8.rst +++ b/docs/source/whatsnew/0.8.rst @@ -7,6 +7,18 @@ Changes in 0.8.0 * Simplified writing images by moving data and options into the constructor. - * The main_header attribute of the ContiguousCodestream class is now called - codestream. * 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/test/test_jp2box.py b/glymur/test/test_jp2box.py index e43eae6..f9e7c5c 100644 --- a/glymur/test/test_jp2box.py +++ b/glymur/test/test_jp2box.py @@ -27,12 +27,17 @@ from .fixtures import (WARNING_INFRASTRUCTURE_ISSUE, WINDOWS_TMP_FILE_MSG, MetadataBase) +def docTearDown(doctest_obj): + glymur.set_parseoptions(full_codestream=False) + + 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')) + tests.addTests(doctest.DocTestSuite('glymur.jp2box', + tearDown=docTearDown)) return tests diff --git a/glymur/version.py b/glymur/version.py index 55e4b88..28d068e 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.7.2" +version = "0.8.0rc2" _sv = LooseVersion(version) version_tuple = _sv.version diff --git a/setup.py b/setup.py index 0a62827..b49ed69 100644 --- a/setup.py +++ b/setup.py @@ -21,12 +21,10 @@ kwargs = {'name': 'Glymur', 'test_suite': 'glymur.test'} install_requires = ['numpy>=1.7.0', 'lxml>=3.0.0'] -test_requires = ['six>=1.7.0'] if sys.hexversion < 0x03030000: install_requires.append('contextlib2>=0.4') - test_requires.append('mock>=1.0.1') + install_requires.append('mock>=1.0.1') kwargs['install_requires'] = install_requires -kwargs['test_requires'] = test_requires clssfrs = ["Programming Language :: Python", "Programming Language :: Python :: 2.7", From 3c7205038faed770c226f17cb7d7b8779232b98e Mon Sep 17 00:00:00 2001 From: jevans Date: Sat, 10 Jan 2015 19:58:00 -0500 Subject: [PATCH 57/57] releasing 0.8.0 --- CHANGES.txt | 6 +++--- docs/source/conf.py | 2 +- glymur/version.py | 2 +- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/CHANGES.txt b/CHANGES.txt index 98e6730..042e351 100644 --- a/CHANGES.txt +++ b/CHANGES.txt @@ -1,6 +1,6 @@ -Jan 08, 2015 - v0.8.0rc1 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, +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. diff --git a/docs/source/conf.py b/docs/source/conf.py index f90815d..76f96f6 100644 --- a/docs/source/conf.py +++ b/docs/source/conf.py @@ -77,7 +77,7 @@ copyright = u'2013, John Evans' # The short X.Y version. version = '0.8' # The full version, including alpha/beta/rc tags. -release = '0.8.0rc2' +release = '0.8.0' # The language for content autogenerated by Sphinx. Refer to documentation # for a list of supported languages. diff --git a/glymur/version.py b/glymur/version.py index 28d068e..4096ee5 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.0rc2" +version = "0.8.0" _sv = LooseVersion(version) version_tuple = _sv.version