Merge branch 'devel' into issue248
This commit is contained in:
commit
a45e653a0a
29 changed files with 2737 additions and 4707 deletions
1
.gitignore
vendored
1
.gitignore
vendored
|
|
@ -1 +1,2 @@
|
|||
*.pyc
|
||||
*.swp
|
||||
|
|
|
|||
|
|
@ -12,9 +12,9 @@ before_install:
|
|||
|
||||
# command to install dependencies
|
||||
install:
|
||||
- if [[ $TRAVIS_PYTHON_VERSION == '2.7' ]]; then pip install lxml contextlib2 mock; fi
|
||||
- if [[ $TRAVIS_PYTHON_VERSION == '3.3' ]]; then pip install lxml numpy; fi
|
||||
- if [[ $TRAVIS_PYTHON_VERSION == '3.4' ]]; then pip install lxml numpy; fi
|
||||
- if [[ $TRAVIS_PYTHON_VERSION == '2.7' ]]; then pip install lxml contextlib2 mock six; fi
|
||||
- if [[ $TRAVIS_PYTHON_VERSION == '3.3' ]]; then pip install lxml numpy six; fi
|
||||
- if [[ $TRAVIS_PYTHON_VERSION == '3.4' ]]; then pip install lxml numpy six; fi
|
||||
|
||||
# command to run tests
|
||||
script:
|
||||
|
|
|
|||
34
bin/jp2dump
34
bin/jp2dump
|
|
@ -1,34 +0,0 @@
|
|||
#!/usr/bin/env python
|
||||
|
||||
import argparse
|
||||
import sys
|
||||
import glymur
|
||||
|
||||
description='Print JPEG2000 metadata.'
|
||||
parser = argparse.ArgumentParser(description=description)
|
||||
parser.add_argument('-x', '--noxml', help='Suppress XML.',
|
||||
action='store_true')
|
||||
parser.add_argument('-s', '--short', help='Only print box id, offset, and length.',
|
||||
action='store_true')
|
||||
chelp='Level of codestream information. 0 suppressed all details, 1 prints headers, 2 prints the full codestream'
|
||||
parser.add_argument('-c', '--codestream',
|
||||
help=chelp,
|
||||
nargs=1,
|
||||
type=int,
|
||||
default=[0])
|
||||
parser.add_argument('filename')
|
||||
args = parser.parse_args()
|
||||
if args.noxml:
|
||||
glymur.set_printoptions(xml=False)
|
||||
if args.short:
|
||||
glymur.set_printoptions(short=True)
|
||||
if args.codestream[0] == 0:
|
||||
glymur.set_printoptions(codestream=False)
|
||||
print_full_codestream = False
|
||||
elif args.codestream[0] == 1:
|
||||
print_full_codestream = False
|
||||
else:
|
||||
print_full_codestream = True
|
||||
|
||||
filename = args.filename
|
||||
glymur.jp2dump(args.filename, codestream=print_full_codestream)
|
||||
|
|
@ -3,21 +3,28 @@ How do I...?
|
|||
------------
|
||||
|
||||
|
||||
... read the lowest resolution thumbnail?
|
||||
=========================================
|
||||
Printing the Jp2k object should reveal the number of resolutions
|
||||
(look in the COD segment section of the codestream), but you can
|
||||
take a shortcut by supplying -1 as the
|
||||
resolution level. ::
|
||||
... read the lower resolution images?
|
||||
=====================================
|
||||
Jp2k implements slicing via the :py:meth:`__getitem__` method so
|
||||
any lower resolution images in a JPEG 2000 file can easily be
|
||||
accessed, for example here's how to retrieve the first sub-image ::
|
||||
|
||||
>>> import glymur
|
||||
>>> jp2file = glymur.data.nemo()
|
||||
>>> jp2 = glymur.Jp2k(jp2file)
|
||||
>>> thumbnail = jp2.read(rlevel=-1)
|
||||
>>> fullres = jp2[:]
|
||||
>>> print(fullres.shape)
|
||||
(1456, 2592, 3)
|
||||
>>> thumbnail = jp2[::2, ::2]
|
||||
>>> print(thumbnail.shape)
|
||||
(728, 1296, 3)
|
||||
|
||||
The :py:meth:`read` method gives many more options for other JPEG 2000 features
|
||||
such as quality layers.
|
||||
|
||||
... display metadata?
|
||||
=====================
|
||||
There are two ways. From the unix command line, the script **jp2dump** is
|
||||
There are two ways. From the command line, the script **jp2dump** is
|
||||
available. ::
|
||||
|
||||
$ jp2dump /path/to/glymur/installation/data/nemo.jp2
|
||||
|
|
@ -340,7 +347,7 @@ image isn't square. ::
|
|||
>>> alpha[mask] = 0
|
||||
>>> rgba = np.concatenate((rgb, alpha), axis=2)
|
||||
>>> jp2 = Jp2k('tmp.jp2', 'wb')
|
||||
>>> jp2.write(rgba)
|
||||
>>> jp2[:] = 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
|
||||
|
|
@ -440,7 +447,7 @@ http://photojournal.jpl.nasa.gov/tiff/PIA17145.tif info JPEG 2000::
|
|||
>>> image = skimage.io.imread('PIA17145.tif')
|
||||
>>> from glymur import Jp2k
|
||||
>>> jp2 = Jp2k('PIA17145.jp2', 'wb')
|
||||
>>> jp2.write(image)
|
||||
>>> jp2[:] = image
|
||||
|
||||
Next you can extract the XMP metadata.
|
||||
|
||||
|
|
|
|||
|
|
@ -27,10 +27,5 @@ but you should also be able to install Glymur via pip ::
|
|||
|
||||
$ pip install glymur
|
||||
|
||||
This will install a script **jp2dump** that can be used from the unix command
|
||||
line for dumping JP2 metadata, so you should adjust your **$PATH**
|
||||
environment variable to take advantage of it. For example, if you install
|
||||
with pip's `--user` option on linux ::
|
||||
|
||||
$ export PATH=$HOME/.local/bin:$PATH
|
||||
|
||||
In addition to the package, this also gives you a script **jp2dump** that can
|
||||
be used from the command line line to print JPEG 2000 metadata.
|
||||
|
|
|
|||
|
|
@ -7,7 +7,6 @@ from glymur import version
|
|||
__version__ = version.version
|
||||
|
||||
from .jp2k import Jp2k
|
||||
from .jp2dump import jp2dump
|
||||
from .jp2box import get_printoptions, set_printoptions
|
||||
from .jp2box import get_parseoptions, set_parseoptions
|
||||
|
||||
|
|
|
|||
|
|
@ -642,7 +642,7 @@ class Codestream(object):
|
|||
srgn = data[1]
|
||||
sprgn = data[2]
|
||||
|
||||
return RGNsegment(length, offset, crgn, srgn, sprgn)
|
||||
return RGNsegment(crgn, srgn, sprgn, length, offset)
|
||||
|
||||
def _parse_siz_segment(self, fptr):
|
||||
"""Parse the SIZ segment.
|
||||
|
|
@ -1074,7 +1074,7 @@ class CMEsegment(Segment):
|
|||
15444-1:2004 - Information technology -- JPEG 2000 image coding system:
|
||||
Core coding system
|
||||
"""
|
||||
def __init__(self, rcme, ccme, length, offset):
|
||||
def __init__(self, rcme, ccme, length=-1, offset=-1):
|
||||
Segment.__init__(self, marker_id='CME')
|
||||
self.rcme = rcme
|
||||
self.ccme = ccme
|
||||
|
|
@ -1463,7 +1463,7 @@ class RGNsegment(Segment):
|
|||
15444-1:2004 - Information technology -- JPEG 2000 image coding system:
|
||||
Core coding system
|
||||
"""
|
||||
def __init__(self, length, offset, crgn, srgn, sprgn):
|
||||
def __init__(self, crgn, srgn, sprgn, length=-1, offset=-1):
|
||||
Segment.__init__(self, marker_id='RGN')
|
||||
self.length = length
|
||||
self.offset = offset
|
||||
|
|
@ -1726,7 +1726,7 @@ class SOTsegment(Segment):
|
|||
15444-1:2004 - Information technology -- JPEG 2000 image coding system:
|
||||
Core coding system
|
||||
"""
|
||||
def __init__(self, isot, psot, tpsot, tnsot, length, offset):
|
||||
def __init__(self, isot, psot, tpsot, tnsot, length=-1, offset=-1):
|
||||
Segment.__init__(self, marker_id='SOT')
|
||||
self.isot = isot
|
||||
self.psot = psot
|
||||
|
|
|
|||
71
glymur/command_line.py
Normal file
71
glymur/command_line.py
Normal file
|
|
@ -0,0 +1,71 @@
|
|||
"""
|
||||
Entry point for console script jp2dump.
|
||||
"""
|
||||
import argparse
|
||||
import sys
|
||||
import warnings
|
||||
from . import Jp2k, set_printoptions
|
||||
|
||||
def main():
|
||||
"""
|
||||
Entry point for console script jp2dump.
|
||||
"""
|
||||
|
||||
description='Print JPEG2000 metadata.'
|
||||
parser = argparse.ArgumentParser(description=description)
|
||||
|
||||
parser.add_argument('-x', '--noxml',
|
||||
help='Suppress XML.',
|
||||
action='store_true')
|
||||
parser.add_argument('-s', '--short',
|
||||
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])
|
||||
|
||||
parser.add_argument('filename')
|
||||
|
||||
args = parser.parse_args()
|
||||
if args.noxml:
|
||||
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.")
|
||||
|
||||
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
|
||||
|
||||
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.
|
||||
j = Jp2k(filename)
|
||||
if print_full_codestream:
|
||||
print(j.get_codestream(header_only=False))
|
||||
else:
|
||||
print(j)
|
||||
|
||||
# Re-emit any warnings that may have been suppressed.
|
||||
if len(wctx) > 0:
|
||||
print("\n")
|
||||
for warning in wctx:
|
||||
print("{0}:{1}: {2}: {3}".format(warning.filename,
|
||||
warning.lineno,
|
||||
warning.category.__name__,
|
||||
warning.message))
|
||||
|
|
@ -1,36 +0,0 @@
|
|||
"""
|
||||
Entry point for jp2dump script.
|
||||
"""
|
||||
import warnings
|
||||
|
||||
from .jp2k import Jp2k
|
||||
|
||||
|
||||
def jp2dump(filename, codestream=False):
|
||||
"""Prints JPEG2000 metadata.
|
||||
|
||||
Parameters
|
||||
----------
|
||||
filename : string
|
||||
The input JPEG2000 file.
|
||||
codestream : optional, logical scalar
|
||||
Whether or not to dump codestream contents.
|
||||
"""
|
||||
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.
|
||||
j = Jp2k(filename)
|
||||
if codestream:
|
||||
print(j.get_codestream(header_only=False))
|
||||
else:
|
||||
print(j)
|
||||
|
||||
# Re-emit any warnings that may have been suppressed.
|
||||
if len(wctx) > 0:
|
||||
print("\n")
|
||||
for warning in wctx:
|
||||
print("{0}:{1}: {2}: {3}".format(warning.filename,
|
||||
warning.lineno,
|
||||
warning.category.__name__,
|
||||
warning.message))
|
||||
123
glymur/jp2k.py
123
glymur/jp2k.py
|
|
@ -759,6 +759,112 @@ class Jp2k(Jp2kBox):
|
|||
|
||||
return boxes
|
||||
|
||||
def __setitem__(self, index, data):
|
||||
"""
|
||||
Slicing protocol.
|
||||
"""
|
||||
if isinstance(index, slice) and (
|
||||
index.start == None and
|
||||
index.stop == None and
|
||||
index.step == None):
|
||||
# Case of jp2[:] = data, i.e. write the entire image.
|
||||
#
|
||||
# Should have a slice object where start = stop = step = None
|
||||
self.write(data)
|
||||
else:
|
||||
msg = "Images currently must be written entirely at once."
|
||||
raise TypeError(msg)
|
||||
|
||||
def __getitem__(self, pargs):
|
||||
"""
|
||||
Slicing protocol.
|
||||
"""
|
||||
codestream = self.get_codestream(header_only=True)
|
||||
if isinstance(pargs, int):
|
||||
# Not a very good use of this protocol, but technically legal.
|
||||
# This retrieves a single row.
|
||||
row = pargs
|
||||
area = (row, 0, row + 1, codestream.segment[1].xsiz)
|
||||
return self.read(area=area).squeeze()
|
||||
|
||||
if isinstance(pargs, slice):
|
||||
# Case of jp2[:], i.e. retrieve the entire image.
|
||||
#
|
||||
# Should have a slice object where start = stop = step = None
|
||||
return self.read()
|
||||
|
||||
if isinstance(pargs, tuple) and all(isinstance(x, int) for x in pargs):
|
||||
# Retrieve a single pixel.
|
||||
# Something like jp2[r, c]
|
||||
row = pargs[0]
|
||||
col = pargs[1]
|
||||
area = (row, col, row + 1, col + 1)
|
||||
pixel = self.read(area=area).squeeze()
|
||||
|
||||
if len(pargs) == 2:
|
||||
return pixel
|
||||
elif len(pargs) == 3:
|
||||
return pixel[pargs[2]]
|
||||
|
||||
# Assuming pargs is a tuple of slices from now on.
|
||||
rows = pargs[0]
|
||||
cols = pargs[1]
|
||||
if len(pargs) == 2:
|
||||
bands = slice(None, None, None)
|
||||
else:
|
||||
bands = pargs[2]
|
||||
|
||||
if rows.step is None:
|
||||
rows_step = 1
|
||||
else:
|
||||
rows_step = rows.step
|
||||
|
||||
if cols.step is None:
|
||||
cols_step = 1
|
||||
else:
|
||||
cols_step = cols.step
|
||||
|
||||
if rows_step != cols_step:
|
||||
msg = "Row and column strides must be the same."
|
||||
raise IndexError(msg)
|
||||
|
||||
# Ok, reduce layer step is the same in both xy directions, so just take
|
||||
# one of them.
|
||||
step = rows_step
|
||||
|
||||
if np.log2(step) != np.floor(np.log2(step)):
|
||||
msg = "Row and column strides must be powers of 2."
|
||||
raise IndexError(msg)
|
||||
|
||||
if rows.start is None:
|
||||
rows_start = 0
|
||||
else:
|
||||
rows_start = rows.start
|
||||
|
||||
if rows.stop is None:
|
||||
rows_stop = codestream.segment[1].ysiz
|
||||
else:
|
||||
rows_stop = rows.stop
|
||||
|
||||
if cols.start is None:
|
||||
cols_start = 0
|
||||
else:
|
||||
cols_start = cols.start
|
||||
|
||||
if cols.stop is None:
|
||||
cols_stop = codestream.segment[1].xsiz
|
||||
else:
|
||||
cols_stop = cols.stop
|
||||
|
||||
area = (rows_start, cols_start, rows_stop, cols_stop)
|
||||
data = self.read(area=area, rlevel=np.int(np.log2(step)))
|
||||
if len(pargs) == 2:
|
||||
return data
|
||||
|
||||
# Ok, 3 arguments in pargs.
|
||||
return data[:, :, bands]
|
||||
|
||||
|
||||
def read(self, **kwargs):
|
||||
"""Read a JPEG 2000 image.
|
||||
|
||||
|
|
@ -833,7 +939,7 @@ class Jp2k(Jp2kBox):
|
|||
raise RuntimeError(msg)
|
||||
|
||||
def _read_openjpeg(self, rlevel=0, ignore_pclr_cmap_cdef=False,
|
||||
verbose=False):
|
||||
verbose=False, area=None):
|
||||
"""Read a JPEG 2000 image using libopenjpeg.
|
||||
|
||||
Parameters
|
||||
|
|
@ -846,6 +952,9 @@ class Jp2k(Jp2kBox):
|
|||
color transformation. Defaults to False.
|
||||
verbose : bool, optional
|
||||
Print informational messages produced by the OpenJPEG library.
|
||||
area : tuple, optional
|
||||
Specifies decoding image area,
|
||||
(first_row, first_col, last_row, last_col)
|
||||
|
||||
Returns
|
||||
-------
|
||||
|
|
@ -898,6 +1007,18 @@ class Jp2k(Jp2kBox):
|
|||
# data 2D instead of 3D.
|
||||
data.shape = data.shape[0:2]
|
||||
|
||||
if area is not None:
|
||||
x0, y0, x1, y1 = area
|
||||
extent = 2 ** rlevel
|
||||
if x1 - x0 < extent or y1 - y0 < extent:
|
||||
msg = "Decoded area is too small."
|
||||
raise IOError(msg)
|
||||
|
||||
area = [int(round(float(x)/extent + 2 ** -20)) for x in area]
|
||||
rows = slice(area[0], area[2], None)
|
||||
cols = slice(area[1], area[3], None)
|
||||
data = data[rows, cols]
|
||||
|
||||
return data
|
||||
|
||||
def _read_openjp2(self, rlevel=0, layer=0, area=None, tile=None,
|
||||
|
|
|
|||
|
|
@ -73,7 +73,6 @@ def load_openjpeg(path):
|
|||
|
||||
return load_library_handle(path)
|
||||
|
||||
|
||||
def load_openjp2(path):
|
||||
"""Load the openjp2 library, falling back on defaults if necessary.
|
||||
"""
|
||||
|
|
@ -100,7 +99,7 @@ def load_openjp2(path):
|
|||
def load_library_handle(path):
|
||||
"""Load the library, return the ctypes handle."""
|
||||
|
||||
if path is None:
|
||||
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.
|
||||
|
|
@ -130,14 +129,11 @@ def read_config_file():
|
|||
# Read the configuration file for the library location.
|
||||
parser = ConfigParser()
|
||||
parser.read(filename)
|
||||
try:
|
||||
lib['openjp2'] = parser.get('library', 'openjp2')
|
||||
except NoOptionError:
|
||||
pass
|
||||
try:
|
||||
lib['openjpeg'] = parser.get('library', 'openjpeg')
|
||||
except NoOptionError:
|
||||
pass
|
||||
for name in ['openjp2', 'openjpeg']:
|
||||
try:
|
||||
lib[name] = parser.get('library', name)
|
||||
except NoOptionError:
|
||||
pass
|
||||
|
||||
return lib
|
||||
|
||||
|
|
@ -150,8 +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. "
|
||||
msg += "Operating in severely degraded mode."
|
||||
warnings.warn(msg, UserWarning)
|
||||
raise IOError(msg)
|
||||
return libopenjp2_handle, libopenjpeg_handle
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -5,12 +5,143 @@ import os
|
|||
import re
|
||||
import sys
|
||||
import textwrap
|
||||
import unittest
|
||||
import warnings
|
||||
|
||||
import numpy as np
|
||||
import six
|
||||
|
||||
import glymur
|
||||
|
||||
# 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.
|
||||
WARNING_INFRASTRUCTURE_ISSUE = False
|
||||
WARNING_INFRASTRUCTURE_MSG = ""
|
||||
if sys.hexversion < 0x03000000:
|
||||
WARNING_INFRASTRUCTURE_ISSUE = True
|
||||
WARNING_INFRASTRUCTURE_MSG = "3.x warning infrastructure only"
|
||||
elif re.match('1.[0-6]', six.__version__) is not None:
|
||||
WARNING_INFRASTRUCTURE_ISSUE = True
|
||||
WARNING_INFRASTRUCTURE_MSG = "Cannot use with this version of six"
|
||||
|
||||
class MetadataBase(unittest.TestCase):
|
||||
"""
|
||||
Base class for testing metadata.
|
||||
|
||||
This class has helper routines defined for testing metadata so that it can
|
||||
be subclassed and used easily.
|
||||
"""
|
||||
|
||||
def setUp(self):
|
||||
pass
|
||||
|
||||
def tearDown(self):
|
||||
pass
|
||||
|
||||
def verify_codeblock_style(self, actual, style):
|
||||
"""
|
||||
Verify the code-block style for SPcod and SPcoc parameters.
|
||||
|
||||
This information is stored in a single byte. Please reference
|
||||
Table A-17 in FCD15444-1
|
||||
"""
|
||||
expected = 0
|
||||
if style[0]:
|
||||
# Selective arithmetic coding bypass
|
||||
expected |= 0x01
|
||||
if style[1]:
|
||||
# Reset context probabilities
|
||||
expected |= 0x02
|
||||
if style[2]:
|
||||
# Termination on each coding pass
|
||||
expected |= 0x04
|
||||
if style[3]:
|
||||
# Vertically causal context
|
||||
expected |= 0x08
|
||||
if style[4]:
|
||||
# Predictable termination
|
||||
expected |= 0x10
|
||||
if style[5]:
|
||||
# Segmentation symbols
|
||||
expected |= 0x20
|
||||
self.assertEqual(actual, expected)
|
||||
|
||||
def verifySignatureBox(self, box):
|
||||
"""
|
||||
The signature box is a constant.
|
||||
"""
|
||||
self.assertEqual(box.signature, (13, 10, 135, 10))
|
||||
|
||||
def verify_filetype_box(self, actual, expected):
|
||||
"""
|
||||
All JP2 files should have a brand reading 'jp2 ' and just a single
|
||||
entry in the compatibility list, also 'jp2 '. JPX files can have more
|
||||
compatibility items.
|
||||
"""
|
||||
self.assertEqual(actual.brand, expected.brand)
|
||||
self.assertEqual(actual.minor_version, expected.minor_version)
|
||||
self.assertEqual(actual.minor_version, 0)
|
||||
for cl in expected.compatibility_list:
|
||||
self.assertIn(cl, actual.compatibility_list)
|
||||
|
||||
def verifyRGNsegment(self, actual, expected):
|
||||
"""
|
||||
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.sprgn, expected.sprgn)
|
||||
|
||||
def verifySOTsegment(self, actual, expected):
|
||||
"""
|
||||
verify the fields of a SOT (start of tile) segment
|
||||
"""
|
||||
self.assertEqual(actual.isot, expected.isot)
|
||||
self.assertEqual(actual.psot, expected.psot)
|
||||
self.assertEqual(actual.tpsot, expected.tpsot)
|
||||
self.assertEqual(actual.tnsot, expected.tnsot)
|
||||
|
||||
def verifyCMEsegment(self, actual, expected):
|
||||
"""
|
||||
verify the fields of a CME (comment) segment
|
||||
"""
|
||||
self.assertEqual(actual.rcme, expected.rcme)
|
||||
self.assertEqual(actual.ccme, expected.ccme)
|
||||
|
||||
def verifySizSegment(self, actual, expected):
|
||||
"""
|
||||
Verify the fields of the SIZ segment.
|
||||
"""
|
||||
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):
|
||||
self.assertEqual(box1.height, box2.height)
|
||||
self.assertEqual(box1.width, box2.width)
|
||||
self.assertEqual(box1.num_components, box2.num_components)
|
||||
self.assertEqual(box1.bits_per_component, box2.bits_per_component)
|
||||
self.assertEqual(box1.signed, box2.signed)
|
||||
self.assertEqual(box1.compression, box2.compression)
|
||||
self.assertEqual(box1.colorspace_unknown, box2.colorspace_unknown)
|
||||
self.assertEqual(box1.ip_provided, box2.ip_provided)
|
||||
|
||||
def verifyColourSpecificationBox(self, actual, expected):
|
||||
"""
|
||||
Does not currently check icc profiles.
|
||||
"""
|
||||
self.assertEqual(actual.method, expected.method)
|
||||
self.assertEqual(actual.precedence, expected.precedence)
|
||||
self.assertEqual(actual.approximation, expected.approximation)
|
||||
|
||||
if expected.colorspace is None:
|
||||
self.assertIsNone(actual.colorspace)
|
||||
self.assertIsNotNone(actual.icc_profile)
|
||||
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.
|
||||
|
|
@ -37,6 +168,24 @@ except:
|
|||
raise
|
||||
|
||||
|
||||
# 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.
|
||||
NO_SKIMAGE_FREEIMAGE_SUPPORT = False
|
||||
try:
|
||||
import skimage
|
||||
import skimage.io
|
||||
if (((sys.hexversion >= 0x03000000) and
|
||||
('Anaconda' in sys.version) and
|
||||
(re.match('0.10', skimage.__version__)))):
|
||||
NO_SKIMAGE_FREEIMAGE_SUPPORT = True
|
||||
else:
|
||||
skimage.io.use_plugin('freeimage', 'imread')
|
||||
except ((ImportError, RuntimeError)):
|
||||
NO_SKIMAGE_FREEIMAGE_SUPPORT = True
|
||||
|
||||
|
||||
def _indent(textstr):
|
||||
"""
|
||||
Indent a string.
|
||||
|
|
@ -437,7 +586,9 @@ Contiguous Codestream Box (jp2c) @ (3223, 1132296)
|
|||
Step size: [(0, 8), (0, 9), (0, 9), (0, 10)]
|
||||
CME marker segment @ (3305, 37)
|
||||
"Created by OpenJPEG version 2.0.0"'''
|
||||
nemo_dump_full = dump.format(_indent(nemo_xmp))
|
||||
|
||||
nemo_with_codestream_header = dump.format(_indent(nemo_xmp))
|
||||
#nemo_dump_full = dump.format(_indent(nemo_xmp))
|
||||
|
||||
nemo_dump_short = r"""JPEG 2000 Signature Box (jP ) @ (0, 12)
|
||||
File Type Box (ftyp) @ (12, 20)
|
||||
|
|
@ -633,7 +784,7 @@ number_list_box = r"""Number List Box (nlst) @ (-1, 0)
|
|||
Association[2]: compositing layer 0"""
|
||||
|
||||
|
||||
goodstuff = r"""Codestream:
|
||||
goodstuff_codestream_header = r"""Codestream:
|
||||
SOC marker segment @ (0, 0)
|
||||
SIZ marker segment @ (2, 47)
|
||||
Profile: no profile
|
||||
|
|
@ -668,3 +819,80 @@ goodstuff = r"""Codestream:
|
|||
Quantization style: no quantization, 2 guard bits
|
||||
Step size: [(0, 8), (0, 9), (0, 9), (0, 10), (0, 9), (0, 9), (0, 10), (0, 9), (0, 9), (0, 10), (0, 9), (0, 9), (0, 10), (0, 9), (0, 9), (0, 10)]"""
|
||||
|
||||
goodstuff_with_full_header = r"""Codestream:
|
||||
SOC marker segment @ (0, 0)
|
||||
SIZ marker segment @ (2, 47)
|
||||
Profile: no profile
|
||||
Reference Grid Height, Width: (800 x 480)
|
||||
Vertical, Horizontal Reference Grid Offset: (0 x 0)
|
||||
Reference Tile Height, Width: (800 x 480)
|
||||
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 @ (51, 12)
|
||||
Coding style:
|
||||
Entropy coder, without partitions
|
||||
SOP marker segments: False
|
||||
EPH marker segments: False
|
||||
Coding style parameters:
|
||||
Progression order: LRCP
|
||||
Number of layers: 1
|
||||
Multiple component transformation usage: reversible
|
||||
Number of resolutions: 6
|
||||
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 @ (65, 19)
|
||||
Quantization style: no quantization, 2 guard bits
|
||||
Step size: [(0, 8), (0, 9), (0, 9), (0, 10), (0, 9), (0, 9), (0, 10), (0, 9), (0, 9), (0, 10), (0, 9), (0, 9), (0, 10), (0, 9), (0, 9), (0, 10)]
|
||||
SOT marker segment @ (86, 10)
|
||||
Tile part index: 0
|
||||
Tile part length: 115132
|
||||
Tile part instance: 0
|
||||
Number of tile parts: 1
|
||||
COC marker segment @ (98, 9)
|
||||
Associated component: 1
|
||||
Coding style for this component: Entropy coder, PARTITION = 0
|
||||
Coding style parameters:
|
||||
Number of resolutions: 6
|
||||
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 @ (109, 20)
|
||||
Associated Component: 1
|
||||
Quantization style: no quantization, 2 guard bits
|
||||
Step size: [(0, 8), (0, 9), (0, 9), (0, 10), (0, 9), (0, 9), (0, 10), (0, 9), (0, 9), (0, 10), (0, 9), (0, 9), (0, 10), (0, 9), (0, 9), (0, 10)]
|
||||
COC marker segment @ (131, 9)
|
||||
Associated component: 2
|
||||
Coding style for this component: Entropy coder, PARTITION = 0
|
||||
Coding style parameters:
|
||||
Number of resolutions: 6
|
||||
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 @ (142, 20)
|
||||
Associated Component: 2
|
||||
Quantization style: no quantization, 2 guard bits
|
||||
Step size: [(0, 8), (0, 9), (0, 9), (0, 10), (0, 9), (0, 9), (0, 10), (0, 9), (0, 9), (0, 10), (0, 9), (0, 9), (0, 10), (0, 9), (0, 9), (0, 10)]
|
||||
SOD marker segment @ (164, 0)
|
||||
EOC marker segment @ (115218, 0)"""
|
||||
|
|
|
|||
|
|
@ -11,7 +11,6 @@ import os
|
|||
import re
|
||||
import sys
|
||||
import tempfile
|
||||
import warnings
|
||||
|
||||
import unittest
|
||||
|
||||
|
|
@ -24,6 +23,7 @@ else:
|
|||
|
||||
import glymur
|
||||
|
||||
from .fixtures import WARNING_INFRASTRUCTURE_ISSUE, WARNING_INFRASTRUCTURE_MSG
|
||||
|
||||
@unittest.skipIf(glymur.lib.openjp2.OPENJP2 is None,
|
||||
"Missing openjp2 library.")
|
||||
|
|
@ -37,12 +37,12 @@ class TestCallbacks(unittest.TestCase):
|
|||
def tearDown(self):
|
||||
pass
|
||||
|
||||
@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):
|
||||
"""Verify messages printed when writing an image in verbose mode."""
|
||||
j = glymur.Jp2k(self.jp2file)
|
||||
with warnings.catch_warnings():
|
||||
warnings.simplefilter("ignore")
|
||||
with self.assertWarns(UserWarning):
|
||||
tiledata = j.read(tile=0)
|
||||
with tempfile.NamedTemporaryFile(suffix='.jp2') as tfile:
|
||||
j = glymur.Jp2k(tfile.name, 'wb')
|
||||
|
|
|
|||
|
|
@ -5,15 +5,11 @@ Test suite for codestream parsing.
|
|||
# unittest doesn't work well with R0904.
|
||||
# pylint: disable=R0904
|
||||
|
||||
# tempfile.TemporaryDirectory, unittest.assertWarns introduced in 3.2
|
||||
# pylint: disable=E1101
|
||||
|
||||
import os
|
||||
import struct
|
||||
import sys
|
||||
import tempfile
|
||||
import unittest
|
||||
import warnings
|
||||
|
||||
from glymur import Jp2k
|
||||
import glymur
|
||||
|
|
|
|||
|
|
@ -16,7 +16,6 @@ import os
|
|||
import sys
|
||||
import tempfile
|
||||
import unittest
|
||||
import warnings
|
||||
|
||||
if sys.hexversion <= 0x03030000:
|
||||
from mock import patch
|
||||
|
|
@ -26,6 +25,7 @@ else:
|
|||
import glymur
|
||||
from glymur import Jp2k
|
||||
|
||||
from .fixtures import WARNING_INFRASTRUCTURE_ISSUE, WARNING_INFRASTRUCTURE_MSG
|
||||
|
||||
@unittest.skipIf(sys.hexversion < 0x03020000,
|
||||
"TemporaryDirectory introduced in 3.2.")
|
||||
|
|
@ -70,6 +70,7 @@ class TestSuite(unittest.TestCase):
|
|||
imp.reload(glymur.lib.openjp2)
|
||||
Jp2k(self.jp2file)
|
||||
|
||||
@unittest.skipIf(WARNING_INFRASTRUCTURE_ISSUE, WARNING_INFRASTRUCTURE_MSG)
|
||||
def test_xdg_env_config_file_is_bad(self):
|
||||
"""A non-existant library location should be rejected."""
|
||||
with tempfile.TemporaryDirectory() as tdir:
|
||||
|
|
@ -84,11 +85,9 @@ class TestSuite(unittest.TestCase):
|
|||
with patch.dict('os.environ', {'XDG_CONFIG_HOME': tdir}):
|
||||
# Misconfigured new configuration file should
|
||||
# be rejected.
|
||||
with warnings.catch_warnings(record=True) as w:
|
||||
warnings.simplefilter('always')
|
||||
regex = 'could not be loaded'
|
||||
with self.assertWarnsRegex(UserWarning, regex):
|
||||
imp.reload(glymur.lib.openjp2)
|
||||
self.assertTrue(issubclass(w[0].category,UserWarning))
|
||||
self.assertTrue('could not be loaded' in str(w[0].message))
|
||||
|
||||
|
||||
@unittest.skipIf(glymur.lib.openjp2.OPENJP2 is None and
|
||||
|
|
|
|||
|
|
@ -5,23 +5,27 @@ 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 warnings
|
||||
|
||||
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(sys.hexversion < 0x03030000,
|
||||
"assertWarn methods introduced in 3.x")
|
||||
@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)
|
||||
class TestWarnings(unittest.TestCase):
|
||||
"""Test suite for warnings issued by glymur."""
|
||||
|
||||
|
|
@ -130,29 +134,6 @@ class TestWarnings(unittest.TestCase):
|
|||
with self.assertWarnsRegex(UserWarning, regex):
|
||||
Jp2k(jfile)
|
||||
|
||||
def test_NR_broken4_jp2_dump(self):
|
||||
"""
|
||||
Has an invalid marker in the main header
|
||||
"""
|
||||
jfile = opj_data_file('input/nonregression/broken4.jp2')
|
||||
regex = r'Invalid marker id encountered at byte \d+ in codestream'
|
||||
with self.assertWarnsRegex(UserWarning, regex):
|
||||
jp2 = Jp2k(jfile)
|
||||
|
||||
@unittest.skipIf(sys.maxsize < 2**32, 'Do not run on 32-bit platforms')
|
||||
def test_NR_broken3_jp2_dump(self):
|
||||
"""
|
||||
Has an impossibly large box length.
|
||||
|
||||
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')
|
||||
regex = re.compile(r'''b'colr'\sbox\shas\sincorrect\sbox\slength\s
|
||||
\(\d+\)''', 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')
|
||||
|
|
|
|||
|
|
@ -9,14 +9,15 @@ import datetime
|
|||
import os
|
||||
import sys
|
||||
import unittest
|
||||
import warnings
|
||||
|
||||
import numpy as np
|
||||
|
||||
from glymur import Jp2k
|
||||
from .fixtures import OPJ_DATA_ROOT, opj_data_file
|
||||
from .fixtures import WARNING_INFRASTRUCTURE_ISSUE, WARNING_INFRASTRUCTURE_MSG
|
||||
|
||||
|
||||
@unittest.skipIf(WARNING_INFRASTRUCTURE_ISSUE, WARNING_INFRASTRUCTURE_MSG)
|
||||
@unittest.skipIf(OPJ_DATA_ROOT is None,
|
||||
"OPJ_DATA_ROOT environment variable not set")
|
||||
class TestICC(unittest.TestCase):
|
||||
|
|
@ -31,9 +32,8 @@ class TestICC(unittest.TestCase):
|
|||
def test_file5(self):
|
||||
"""basic ICC profile"""
|
||||
filename = opj_data_file('input/conformance/file5.jp2')
|
||||
with warnings.catch_warnings():
|
||||
with self.assertWarns(UserWarning):
|
||||
# The file has a bad compatibility list entry. Not important here.
|
||||
warnings.simplefilter("ignore")
|
||||
j = Jp2k(filename)
|
||||
profile = j.box[3].box[1].icc_profile
|
||||
self.assertEqual(profile['Size'], 546)
|
||||
|
|
@ -62,18 +62,15 @@ class TestICC(unittest.TestCase):
|
|||
|
||||
self.assertEqual(profile['Creator'], 'JPEG')
|
||||
|
||||
@unittest.skipIf(sys.platform.startswith('linux'), 'Failing on linux')
|
||||
def test_invalid_profile_header(self):
|
||||
"""invalid ICC header data should cause UserWarning"""
|
||||
jfile = opj_data_file('input/nonregression/orb-blue10-lin-jp2.jp2')
|
||||
|
||||
# assertWarns in Python 3.3 (python2.7/pylint issue)
|
||||
# pylint: disable=E1101
|
||||
with warnings.catch_warnings(record=True) as w:
|
||||
warnings.simplefilter('always')
|
||||
regex = 'ICC profile header is corrupt'
|
||||
with self.assertWarnsRegex(UserWarning, regex):
|
||||
Jp2k(jfile)
|
||||
self.assertTrue(issubclass(w[0].category,UserWarning))
|
||||
self.assertTrue('ICC profile header is corrupt' in str(w[0].message))
|
||||
|
||||
if __name__ == "__main__":
|
||||
unittest.main()
|
||||
|
|
|
|||
|
|
@ -23,7 +23,6 @@ import tempfile
|
|||
import uuid
|
||||
from uuid import UUID
|
||||
import unittest
|
||||
import warnings
|
||||
|
||||
import lxml.etree as ET
|
||||
import numpy as np
|
||||
|
|
@ -36,7 +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 opj_data_file
|
||||
from .fixtures import (
|
||||
WARNING_INFRASTRUCTURE_ISSUE, WARNING_INFRASTRUCTURE_MSG,
|
||||
MetadataBase
|
||||
)
|
||||
|
||||
try:
|
||||
FORMAT_CORPUS_DATA_ROOT = os.environ['FORMAT_CORPUS_DATA_ROOT']
|
||||
|
|
@ -357,6 +359,7 @@ class TestChannelDefinition(unittest.TestCase):
|
|||
with self.assertRaises((IOError, OSError)):
|
||||
j2k.wrap(tfile.name, boxes=boxes)
|
||||
|
||||
@unittest.skipIf(WARNING_INFRASTRUCTURE_ISSUE, WARNING_INFRASTRUCTURE_MSG)
|
||||
def test_bad_type(self):
|
||||
"""Channel types are limited to 0, 1, 2, 65535
|
||||
Should reject if not all of index, channel_type, association the
|
||||
|
|
@ -365,25 +368,20 @@ class TestChannelDefinition(unittest.TestCase):
|
|||
channel_type = (COLOR, COLOR, 3)
|
||||
association = (RED, GREEN, BLUE)
|
||||
|
||||
with warnings.catch_warnings(record=True) as w:
|
||||
warnings.simplefilter('always')
|
||||
with self.assertWarns(UserWarning):
|
||||
glymur.jp2box.ChannelDefinitionBox(channel_type=channel_type,
|
||||
association=association)
|
||||
self.assertEqual(len(w), 1)
|
||||
self.assertTrue(issubclass(w[0].category, UserWarning))
|
||||
|
||||
@unittest.skipIf(WARNING_INFRASTRUCTURE_ISSUE, WARNING_INFRASTRUCTURE_MSG)
|
||||
def test_wrong_lengths(self):
|
||||
"""Should reject if not all of index, channel_type, association the
|
||||
same length.
|
||||
"""
|
||||
channel_type = (COLOR, COLOR)
|
||||
association = (RED, GREEN, BLUE)
|
||||
with warnings.catch_warnings(record=True) as w:
|
||||
warnings.simplefilter('always')
|
||||
with self.assertWarns(UserWarning):
|
||||
glymur.jp2box.ChannelDefinitionBox(channel_type=channel_type,
|
||||
association=association)
|
||||
self.assertEqual(len(w), 1)
|
||||
self.assertTrue(issubclass(w[0].category, UserWarning))
|
||||
|
||||
|
||||
class TestFileTypeBox(unittest.TestCase):
|
||||
|
|
@ -395,20 +393,20 @@ class TestFileTypeBox(unittest.TestCase):
|
|||
def tearDown(self):
|
||||
pass
|
||||
|
||||
@unittest.skipIf(WARNING_INFRASTRUCTURE_ISSUE, WARNING_INFRASTRUCTURE_MSG)
|
||||
def test_brand_unknown(self):
|
||||
"""A ftyp box brand must be 'jp2 ' or 'jpx '."""
|
||||
with warnings.catch_warnings():
|
||||
warnings.simplefilter("ignore")
|
||||
with self.assertWarns(UserWarning):
|
||||
ftyp = glymur.jp2box.FileTypeBox(brand='jp3')
|
||||
with self.assertRaises(IOError):
|
||||
with tempfile.TemporaryFile() as tfile:
|
||||
ftyp.write(tfile)
|
||||
|
||||
@unittest.skipIf(WARNING_INFRASTRUCTURE_ISSUE, WARNING_INFRASTRUCTURE_MSG)
|
||||
def test_cl_entry_unknown(self):
|
||||
"""A ftyp box cl list can only contain 'jp2 ', 'jpx ', or 'jpxb'."""
|
||||
with warnings.catch_warnings():
|
||||
with self.assertWarns(UserWarning):
|
||||
# Bad compatibility list item.
|
||||
warnings.simplefilter("ignore")
|
||||
ftyp = glymur.jp2box.FileTypeBox(compatibility_list=['jp3'])
|
||||
with self.assertRaises(IOError):
|
||||
with tempfile.TemporaryFile() as tfile:
|
||||
|
|
@ -479,41 +477,34 @@ class TestColourSpecificationBox(unittest.TestCase):
|
|||
self.assertEqual(colr.colorspace, glymur.core.SRGB)
|
||||
self.assertIsNone(colr.icc_profile)
|
||||
|
||||
@unittest.skipIf(WARNING_INFRASTRUCTURE_ISSUE, WARNING_INFRASTRUCTURE_MSG)
|
||||
def test_colr_with_cspace_and_icc(self):
|
||||
"""Colour specification boxes can't have both."""
|
||||
with warnings.catch_warnings(record=True) as w:
|
||||
warnings.simplefilter('always')
|
||||
regex = 'Colorspace and icc_profile cannot both be set'
|
||||
with self.assertWarnsRegex(UserWarning, regex):
|
||||
colorspace = glymur.core.SRGB
|
||||
rawb = b'\x01\x02\x03\x04'
|
||||
glymur.jp2box.ColourSpecificationBox(colorspace=colorspace,
|
||||
icc_profile=rawb)
|
||||
self.assertTrue(issubclass(w[0].category,UserWarning))
|
||||
msg = 'Colorspace and icc_profile cannot both be set'
|
||||
self.assertTrue(msg in str(w[0].message))
|
||||
|
||||
@unittest.skipIf(WARNING_INFRASTRUCTURE_ISSUE, WARNING_INFRASTRUCTURE_MSG)
|
||||
def test_colr_with_bad_method(self):
|
||||
"""colr must have a valid method field"""
|
||||
colorspace = glymur.core.SRGB
|
||||
method = -1
|
||||
with warnings.catch_warnings(record=True) as w:
|
||||
warnings.simplefilter('always')
|
||||
regex = 'Invalid method'
|
||||
with self.assertWarnsRegex(UserWarning, regex):
|
||||
glymur.jp2box.ColourSpecificationBox(colorspace=colorspace,
|
||||
method=method)
|
||||
self.assertTrue(issubclass(w[0].category,UserWarning))
|
||||
msg = 'Invalid method'
|
||||
self.assertTrue(msg in str(w[0].message))
|
||||
|
||||
@unittest.skipIf(WARNING_INFRASTRUCTURE_ISSUE, WARNING_INFRASTRUCTURE_MSG)
|
||||
def test_colr_with_bad_approx(self):
|
||||
"""colr should have a valid approximation field"""
|
||||
colorspace = glymur.core.SRGB
|
||||
approx = -1
|
||||
with warnings.catch_warnings(record=True) as w:
|
||||
warnings.simplefilter('always')
|
||||
with self.assertWarnsRegex(UserWarning, 'Invalid approximation'):
|
||||
glymur.jp2box.ColourSpecificationBox(colorspace=colorspace,
|
||||
approximation=approx)
|
||||
self.assertTrue(issubclass(w[0].category,UserWarning))
|
||||
msg = 'Invalid approximation'
|
||||
self.assertTrue(msg in str(w[0].message))
|
||||
|
||||
def test_colr_with_bad_color(self):
|
||||
"""colr must have a valid color, strange as though that may sound."""
|
||||
|
|
@ -537,29 +528,25 @@ class TestPaletteBox(unittest.TestCase):
|
|||
def tearDown(self):
|
||||
pass
|
||||
|
||||
@unittest.skipIf(WARNING_INFRASTRUCTURE_ISSUE, WARNING_INFRASTRUCTURE_MSG)
|
||||
def test_mismatched_bitdepth_signed(self):
|
||||
"""bitdepth and signed arguments must have equal length"""
|
||||
palette = np.array([[255, 0, 255], [0, 255, 0]], dtype=np.uint8)
|
||||
bps = (8, 8, 8)
|
||||
signed = (False, False)
|
||||
with warnings.catch_warnings(record=True) as w:
|
||||
warnings.simplefilter('always')
|
||||
with self.assertWarns(UserWarning):
|
||||
pclr = glymur.jp2box.PaletteBox(palette, bits_per_component=bps,
|
||||
signed=signed)
|
||||
self.assertEqual(len(w), 1)
|
||||
self.assertTrue(issubclass(w[0].category, UserWarning))
|
||||
|
||||
@unittest.skipIf(WARNING_INFRASTRUCTURE_ISSUE, WARNING_INFRASTRUCTURE_MSG)
|
||||
def test_mismatched_signed_palette(self):
|
||||
"""bitdepth and signed arguments must have equal length"""
|
||||
palette = np.array([[255, 0, 255], [0, 255, 0]], dtype=np.uint8)
|
||||
bps = (8, 8, 8, 8)
|
||||
signed = (False, False, False, False)
|
||||
with warnings.catch_warnings(record=True) as w:
|
||||
warnings.simplefilter('always')
|
||||
with self.assertWarns(UserWarning):
|
||||
pclr = glymur.jp2box.PaletteBox(palette, bits_per_component=bps,
|
||||
signed=signed)
|
||||
self.assertEqual(len(w), 1)
|
||||
self.assertTrue(issubclass(w[0].category, UserWarning))
|
||||
|
||||
def test_writing_with_different_bitdepths(self):
|
||||
"""Bitdepths must be the same when writing."""
|
||||
|
|
@ -1054,7 +1041,7 @@ class TestJp2Boxes(unittest.TestCase):
|
|||
j.box[5].offset + 8)
|
||||
|
||||
|
||||
class TestRepr(unittest.TestCase):
|
||||
class TestRepr(MetadataBase):
|
||||
"""Tests for __repr__ methods."""
|
||||
def test_default_jp2k(self):
|
||||
"""Should be able to eval a JPEG2000SignatureBox"""
|
||||
|
|
@ -1124,10 +1111,7 @@ class TestRepr(unittest.TestCase):
|
|||
|
||||
# Test the representation instantiation.
|
||||
newbox = eval(repr(ftyp))
|
||||
self.assertTrue(isinstance(newbox, glymur.jp2box.FileTypeBox))
|
||||
self.assertEqual(newbox.brand, 'jp2 ')
|
||||
self.assertEqual(newbox.minor_version, 0)
|
||||
self.assertEqual(newbox.compatibility_list, ['jp2 '])
|
||||
self.verify_filetype_box(newbox, FileTypeBox())
|
||||
|
||||
def test_colourspecification_box(self):
|
||||
"""Verify __repr__ method on colr box."""
|
||||
|
|
|
|||
|
|
@ -9,7 +9,6 @@ import struct
|
|||
import sys
|
||||
import tempfile
|
||||
import unittest
|
||||
import warnings
|
||||
|
||||
import lxml.etree as ET
|
||||
|
||||
|
|
@ -19,6 +18,8 @@ from glymur.jp2box import DataEntryURLBox, FileTypeBox, JPEG2000SignatureBox
|
|||
from glymur.jp2box import DataReferenceBox, FragmentListBox, FragmentTableBox
|
||||
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."""
|
||||
|
|
@ -305,17 +306,15 @@ class TestJPXWrap(unittest.TestCase):
|
|||
with self.assertRaises(IOError):
|
||||
jp2.wrap(tfile.name, boxes=boxes)
|
||||
|
||||
@unittest.skipIf(WARNING_INFRASTRUCTURE_ISSUE, WARNING_INFRASTRUCTURE_MSG)
|
||||
def test_deurl_child_of_dtbl(self):
|
||||
"""Data reference boxes can only contain data entry url boxes."""
|
||||
jp2 = Jp2k(self.jp2file)
|
||||
boxes = [jp2.box[idx] for idx in [0, 1, 2, 4]]
|
||||
|
||||
ftyp = glymur.jp2box.FileTypeBox()
|
||||
with warnings.catch_warnings(record=True) as w:
|
||||
warnings.simplefilter('always')
|
||||
with self.assertWarns(UserWarning):
|
||||
dref = glymur.jp2box.DataReferenceBox([ftyp])
|
||||
self.assertEqual(len(w), 1)
|
||||
self.assertTrue(issubclass(w[0].category, UserWarning))
|
||||
|
||||
# Try to get around it by appending the ftyp box after creation.
|
||||
dref = glymur.jp2box.DataReferenceBox()
|
||||
|
|
@ -433,37 +432,37 @@ class TestJPX(unittest.TestCase):
|
|||
def tearDown(self):
|
||||
pass
|
||||
|
||||
@unittest.skipIf(WARNING_INFRASTRUCTURE_ISSUE, WARNING_INFRASTRUCTURE_MSG)
|
||||
def test_flst_lens_not_the_same(self):
|
||||
"""A fragment list box items must be the same length."""
|
||||
offset = [89]
|
||||
length = [1132288]
|
||||
reference = [0, 0]
|
||||
with warnings.catch_warnings():
|
||||
warnings.simplefilter("ignore")
|
||||
with self.assertWarns(UserWarning):
|
||||
flst = glymur.jp2box.FragmentListBox(offset, length, reference)
|
||||
with self.assertRaises(IOError):
|
||||
with tempfile.TemporaryFile() as tfile:
|
||||
flst.write(tfile)
|
||||
|
||||
@unittest.skipIf(WARNING_INFRASTRUCTURE_ISSUE, WARNING_INFRASTRUCTURE_MSG)
|
||||
def test_flst_offsets_not_positive(self):
|
||||
"""A fragment list box offsets must be positive."""
|
||||
offset = [0]
|
||||
length = [1132288]
|
||||
reference = [0]
|
||||
with warnings.catch_warnings():
|
||||
warnings.simplefilter("ignore")
|
||||
with self.assertWarns(UserWarning):
|
||||
flst = glymur.jp2box.FragmentListBox(offset, length, reference)
|
||||
with self.assertRaises((IOError, OSError)):
|
||||
with tempfile.TemporaryFile() as tfile:
|
||||
flst.write(tfile)
|
||||
|
||||
@unittest.skipIf(WARNING_INFRASTRUCTURE_ISSUE, WARNING_INFRASTRUCTURE_MSG)
|
||||
def test_flst_lengths_not_positive(self):
|
||||
"""A fragment list box lengths must be positive."""
|
||||
offset = [89]
|
||||
length = [0]
|
||||
reference = [0]
|
||||
with warnings.catch_warnings():
|
||||
warnings.simplefilter("ignore")
|
||||
with self.assertWarns(UserWarning):
|
||||
flst = glymur.jp2box.FragmentListBox(offset, length, reference)
|
||||
with self.assertRaises(IOError):
|
||||
with tempfile.TemporaryFile() as tfile:
|
||||
|
|
@ -471,9 +470,7 @@ class TestJPX(unittest.TestCase):
|
|||
|
||||
def test_ftbl_boxes_empty(self):
|
||||
"""A fragment table box must have at least one child box."""
|
||||
with warnings.catch_warnings():
|
||||
warnings.simplefilter("ignore")
|
||||
ftbl = glymur.jp2box.FragmentTableBox()
|
||||
ftbl = glymur.jp2box.FragmentTableBox()
|
||||
with self.assertRaises(IOError):
|
||||
with tempfile.TemporaryFile() as tfile:
|
||||
ftbl.write(tfile)
|
||||
|
|
|
|||
|
|
@ -17,7 +17,6 @@ import struct
|
|||
import sys
|
||||
import tempfile
|
||||
import uuid
|
||||
import warnings
|
||||
|
||||
if sys.hexversion < 0x02070000:
|
||||
import unittest2 as unittest
|
||||
|
|
@ -37,6 +36,8 @@ else:
|
|||
import lxml.etree
|
||||
|
||||
from .fixtures import HAS_PYTHON_XMP_TOOLKIT, OPJ_DATA_ROOT
|
||||
from .fixtures import WARNING_INFRASTRUCTURE_ISSUE, WARNING_INFRASTRUCTURE_MSG
|
||||
|
||||
if HAS_PYTHON_XMP_TOOLKIT:
|
||||
from libxmp import XMPMeta
|
||||
|
||||
|
|
@ -46,8 +47,8 @@ from .fixtures import OPJ_DATA_ROOT, opj_data_file, SimpleRDF
|
|||
|
||||
|
||||
@unittest.skipIf(os.name == "nt", "Unexplained failure on windows")
|
||||
class TestUUIDXMP(unittest.TestCase):
|
||||
"""Tests for UUIDs of XMP type."""
|
||||
class TestSuite(unittest.TestCase):
|
||||
"""Tests for XMP, Exif UUIDs."""
|
||||
|
||||
def setUp(self):
|
||||
self.jp2file = glymur.data.nemo()
|
||||
|
|
@ -55,7 +56,7 @@ class TestUUIDXMP(unittest.TestCase):
|
|||
def tearDown(self):
|
||||
pass
|
||||
|
||||
def test_append(self):
|
||||
def test_append_xmp_uuid(self):
|
||||
"""Should be able to append an XMP UUID box."""
|
||||
the_uuid = uuid.UUID('be7acfcb-97a9-42e8-9c71-999491e3afac')
|
||||
raw_data = SimpleRDF.encode('utf-8')
|
||||
|
|
@ -75,16 +76,42 @@ class TestUUIDXMP(unittest.TestCase):
|
|||
self.assertTrue(isinstance(jp2.box[-1].data,
|
||||
lxml.etree._ElementTree))
|
||||
|
||||
def test_big_endian_exif(self):
|
||||
"""Verify read of Exif big-endian IFD."""
|
||||
with tempfile.NamedTemporaryFile(suffix='.jp2', mode='wb') as tfile:
|
||||
|
||||
with open(self.jp2file, 'rb') as ifptr:
|
||||
tfile.write(ifptr.read())
|
||||
|
||||
# Write L, T, UUID identifier.
|
||||
tfile.write(struct.pack('>I4s', 52, b'uuid'))
|
||||
tfile.write(b'JpgTiffExif->JP2')
|
||||
|
||||
tfile.write(b'Exif\x00\x00')
|
||||
xbuffer = struct.pack('>BBHI', 77, 77, 42, 8)
|
||||
tfile.write(xbuffer)
|
||||
|
||||
# We will write just a single tag.
|
||||
tfile.write(struct.pack('>H', 1))
|
||||
|
||||
# The "Make" tag is tag no. 271.
|
||||
tfile.write(struct.pack('>HHI4s', 271, 2, 3, b'HTC\x00'))
|
||||
tfile.flush()
|
||||
|
||||
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", "Unexplained failure on windows")
|
||||
class TestUUIDExif(unittest.TestCase):
|
||||
"""Tests for UUIDs of Exif type."""
|
||||
class TestSuiteWarns(unittest.TestCase):
|
||||
"""Tests for XMP, Exif UUIDs, issues warnings."""
|
||||
|
||||
def setUp(self):
|
||||
self.jp2file = glymur.data.nemo()
|
||||
|
||||
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:
|
||||
|
|
@ -107,12 +134,8 @@ class TestUUIDExif(unittest.TestCase):
|
|||
tfile.write(struct.pack('<HHI4s', 171, 2, 3, b'HTC\x00'))
|
||||
tfile.flush()
|
||||
|
||||
with warnings.catch_warnings(record=True) as w:
|
||||
warnings.simplefilter('always')
|
||||
with self.assertWarnsRegex(UserWarning, 'Unrecognized Exif tag'):
|
||||
j = glymur.Jp2k(tfile.name)
|
||||
self.assertTrue(issubclass(w[0].category, UserWarning))
|
||||
msg = 'Unrecognized Exif tag'
|
||||
self.assertTrue(msg in str(w[0].message))
|
||||
|
||||
def test_bad_tag_datatype(self):
|
||||
"""Only certain datatypes are allowable"""
|
||||
|
|
@ -136,12 +159,8 @@ class TestUUIDExif(unittest.TestCase):
|
|||
tfile.write(struct.pack('<HHI4s', 271, 2000, 3, b'HTC\x00'))
|
||||
tfile.flush()
|
||||
|
||||
with warnings.catch_warnings(record=True) as w:
|
||||
warnings.simplefilter('always')
|
||||
with self.assertWarnsRegex(UserWarning, 'Invalid TIFF tag'):
|
||||
j = glymur.Jp2k(tfile.name)
|
||||
self.assertTrue(issubclass(w[0].category, UserWarning))
|
||||
msg = 'Invalid TIFF tag'
|
||||
self.assertTrue(msg in str(w[0].message))
|
||||
|
||||
self.assertEqual(j.box[-1].box_id, 'uuid')
|
||||
|
||||
|
|
@ -167,45 +186,11 @@ class TestUUIDExif(unittest.TestCase):
|
|||
tfile.write(struct.pack('<HHI4s', 271, 2, 3, b'HTC\x00'))
|
||||
tfile.flush()
|
||||
|
||||
with warnings.catch_warnings(record=True) as w:
|
||||
warnings.simplefilter('always')
|
||||
j = glymur.Jp2k(tfile.name)
|
||||
self.assertTrue(issubclass(w[0].category, UserWarning))
|
||||
msg = 'The byte order indication in the TIFF header '
|
||||
if sys.hexversion < 0x03000000:
|
||||
msg += "(JI) is invalid. "
|
||||
msg += "It should be either [73, 73] or [77, 77]."
|
||||
else:
|
||||
msg += "(b'JI') is invalid. "
|
||||
msg += "It should be either b'II' or b'MM'."
|
||||
self.assertTrue(msg in str(w[0].message))
|
||||
regex = 'The byte order indication in the TIFF header '
|
||||
with self.assertWarnsRegex(UserWarning, regex):
|
||||
jp2 = glymur.Jp2k(tfile.name)
|
||||
|
||||
self.assertEqual(j.box[-1].box_id, 'uuid')
|
||||
|
||||
def test_big_endian(self):
|
||||
"""Verify read of big-endian IFD."""
|
||||
with tempfile.NamedTemporaryFile(suffix='.jp2', mode='wb') as tfile:
|
||||
|
||||
with open(self.jp2file, 'rb') as ifptr:
|
||||
tfile.write(ifptr.read())
|
||||
|
||||
# Write L, T, UUID identifier.
|
||||
tfile.write(struct.pack('>I4s', 52, b'uuid'))
|
||||
tfile.write(b'JpgTiffExif->JP2')
|
||||
|
||||
tfile.write(b'Exif\x00\x00')
|
||||
xbuffer = struct.pack('>BBHI', 77, 77, 42, 8)
|
||||
tfile.write(xbuffer)
|
||||
|
||||
# We will write just a single tag.
|
||||
tfile.write(struct.pack('>H', 1))
|
||||
|
||||
# The "Make" tag is tag no. 271.
|
||||
tfile.write(struct.pack('>HHI4s', 271, 2, 3, b'HTC\x00'))
|
||||
tfile.flush()
|
||||
|
||||
jp2 = glymur.Jp2k(tfile.name)
|
||||
self.assertEqual(jp2.box[-1].data['Make'], "HTC")
|
||||
self.assertEqual(jp2.box[-1].box_id, 'uuid')
|
||||
|
||||
if __name__ == "__main__":
|
||||
unittest.main()
|
||||
|
|
|
|||
|
|
@ -15,11 +15,11 @@ Test suite specifically targeting JP2 box layout.
|
|||
# pylint: disable=W0613
|
||||
|
||||
import os
|
||||
import re
|
||||
import struct
|
||||
import sys
|
||||
import tempfile
|
||||
import unittest
|
||||
import warnings
|
||||
|
||||
if sys.hexversion < 0x03000000:
|
||||
from StringIO import StringIO
|
||||
|
|
@ -40,6 +40,7 @@ from glymur.jp2box import FileTypeBox, ImageHeaderBox, JP2HeaderBox
|
|||
from glymur.jp2box import JPEG2000SignatureBox
|
||||
|
||||
from .fixtures import OPJ_DATA_ROOT, opj_data_file
|
||||
from .fixtures import WARNING_INFRASTRUCTURE_ISSUE, WARNING_INFRASTRUCTURE_MSG
|
||||
|
||||
@unittest.skipIf(os.name == "nt", "Temporary file issue on window.")
|
||||
class TestXML(unittest.TestCase):
|
||||
|
|
@ -166,7 +167,6 @@ class TestXML(unittest.TestCase):
|
|||
|
||||
|
||||
|
||||
@unittest.skipIf(os.name == "nt", "NamedTemporaryFile issue on windows")
|
||||
class TestJp2kBadXmlFile(unittest.TestCase):
|
||||
"""Test suite for bad XML box situations"""
|
||||
|
||||
|
|
@ -207,14 +207,11 @@ class TestJp2kBadXmlFile(unittest.TestCase):
|
|||
def tearDown(self):
|
||||
pass
|
||||
|
||||
@unittest.skipIf(WARNING_INFRASTRUCTURE_ISSUE, WARNING_INFRASTRUCTURE_MSG)
|
||||
def test_invalid_xml_box(self):
|
||||
"""Should be able to recover info from xml box with bad xml."""
|
||||
with warnings.catch_warnings(record=True) as w:
|
||||
warnings.simplefilter("always")
|
||||
with self.assertWarns(UserWarning):
|
||||
jp2k = Jp2k(self._bad_xml_file)
|
||||
self.assertTrue(issubclass(w[0].category, UserWarning))
|
||||
msg = 'No XML was retrieved'
|
||||
self.assertTrue(msg in str(w[0].message))
|
||||
|
||||
self.assertEqual(jp2k.box[3].box_id, 'xml ')
|
||||
self.assertEqual(jp2k.box[3].offset, 77)
|
||||
|
|
@ -263,19 +260,17 @@ class TestBadButRecoverableXmlFile(unittest.TestCase):
|
|||
def tearDownClass(cls):
|
||||
os.unlink(cls._bad_xml_file)
|
||||
|
||||
@unittest.skipIf(WARNING_INFRASTRUCTURE_ISSUE, WARNING_INFRASTRUCTURE_MSG)
|
||||
def test_bad_xml_box_warning(self):
|
||||
"""Should warn in case of bad XML"""
|
||||
with warnings.catch_warnings(record=True) as w:
|
||||
warnings.simplefilter('always')
|
||||
regex = 'A UnicodeDecodeError was encountered parsing an XML box'
|
||||
with self.assertWarnsRegex(UserWarning, regex):
|
||||
Jp2k(self._bad_xml_file)
|
||||
self.assertTrue(issubclass(w[0].category, UserWarning))
|
||||
msg = 'A UnicodeDecodeError was encountered parsing an XML box'
|
||||
self.assertTrue(msg in str(w[0].message))
|
||||
|
||||
@unittest.skipIf(WARNING_INFRASTRUCTURE_ISSUE, WARNING_INFRASTRUCTURE_MSG)
|
||||
def test_recover_from_bad_xml(self):
|
||||
"""Should be able to recover info from xml box with bad xml."""
|
||||
with warnings.catch_warnings():
|
||||
warnings.simplefilter("ignore")
|
||||
with self.assertWarns(UserWarning):
|
||||
jp2 = Jp2k(self._bad_xml_file)
|
||||
|
||||
self.assertEqual(jp2.box[3].box_id, 'xml ')
|
||||
|
|
@ -285,23 +280,21 @@ class TestBadButRecoverableXmlFile(unittest.TestCase):
|
|||
b'<test>this is a test</test>')
|
||||
|
||||
|
||||
@unittest.skipIf(WARNING_INFRASTRUCTURE_ISSUE, WARNING_INFRASTRUCTURE_MSG)
|
||||
@unittest.skipIf(OPJ_DATA_ROOT is None,
|
||||
"OPJ_DATA_ROOT environment variable not set")
|
||||
class TestXML_OpjDataRoot(unittest.TestCase):
|
||||
"""Test suite for XML boxes, requires OPJ_DATA_ROOT."""
|
||||
|
||||
@unittest.skipIf(sys.platform.startswith('linux'), 'Failing on linux')
|
||||
def test_bom(self):
|
||||
"""Byte order markers are illegal in UTF-8. Issue 185"""
|
||||
filename = opj_data_file(os.path.join('input',
|
||||
'nonregression',
|
||||
'issue171.jp2'))
|
||||
with warnings.catch_warnings(record=True) as w:
|
||||
warnings.simplefilter("always")
|
||||
msg = 'An illegal BOM \(byte order marker\) was detected and removed '
|
||||
msg += 'from the XML contents in the box starting at byte offset \d+'
|
||||
with self.assertWarnsRegex(UserWarning, re.compile(msg)):
|
||||
jp2 = Jp2k(filename)
|
||||
self.assertTrue(issubclass(w[0].category, UserWarning))
|
||||
msg = 'An illegal BOM (byte order marker) was detected and removed'
|
||||
self.assertTrue(msg in str(w[0].message))
|
||||
|
||||
self.assertIsNotNone(jp2.box[3].xml)
|
||||
|
||||
|
|
@ -311,10 +304,8 @@ class TestXML_OpjDataRoot(unittest.TestCase):
|
|||
filename = opj_data_file(os.path.join('input',
|
||||
'nonregression',
|
||||
'26ccf3651020967f7778238ef5af08af.SIGFPE.d25.527.jp2'))
|
||||
with warnings.catch_warnings(record=True) as w:
|
||||
warnings.simplefilter("always")
|
||||
with self.assertWarns((UserWarning, UserWarning)):
|
||||
jp2 = Jp2k(filename)
|
||||
self.assertTrue(issubclass(w[0].category, UserWarning))
|
||||
|
||||
self.assertIsNone(jp2.box[3].box[1].box[1].xml)
|
||||
|
||||
|
|
|
|||
|
|
@ -21,8 +21,6 @@ import unittest
|
|||
import uuid
|
||||
from xml.etree import cElementTree as ET
|
||||
|
||||
import warnings
|
||||
|
||||
import numpy as np
|
||||
import pkg_resources
|
||||
|
||||
|
|
@ -30,6 +28,8 @@ import glymur
|
|||
from glymur import Jp2k
|
||||
|
||||
from .fixtures import HAS_PYTHON_XMP_TOOLKIT
|
||||
from .fixtures import WARNING_INFRASTRUCTURE_ISSUE, WARNING_INFRASTRUCTURE_MSG
|
||||
|
||||
if HAS_PYTHON_XMP_TOOLKIT:
|
||||
import libxmp
|
||||
from libxmp import XMPMeta
|
||||
|
|
@ -52,6 +52,366 @@ def load_tests(loader, tests, ignore):
|
|||
return tests
|
||||
|
||||
|
||||
class SliceProtocolBase(unittest.TestCase):
|
||||
"""
|
||||
Test slice protocol, i.e. when using [ ] to read image data.
|
||||
"""
|
||||
@classmethod
|
||||
def setUpClass(self):
|
||||
|
||||
self.jp2 = Jp2k(glymur.data.nemo())
|
||||
self.jp2_data = self.jp2.read()
|
||||
|
||||
self.j2k = Jp2k(glymur.data.goodstuff())
|
||||
self.j2k_data = self.j2k.read()
|
||||
|
||||
|
||||
@unittest.skipIf(os.name == "nt", "NamedTemporaryFile issue on windows")
|
||||
class TestSliceProtocolBaseWrite(SliceProtocolBase):
|
||||
|
||||
def test_basic_write(self):
|
||||
expected = self.j2k_data
|
||||
|
||||
with tempfile.NamedTemporaryFile(suffix='.j2k') as tfile:
|
||||
j = Jp2k(tfile.name, 'wb')
|
||||
j[:] = self.j2k_data
|
||||
actual = j.read()
|
||||
|
||||
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')
|
||||
with self.assertRaises(TypeError):
|
||||
j[slice(None, 0)] = self.j2k_data
|
||||
with self.assertRaises(TypeError):
|
||||
j[slice(0, None)] = self.j2k_data
|
||||
with self.assertRaises(TypeError):
|
||||
j[slice(0, 0, None)] = self.j2k_data
|
||||
with self.assertRaises(TypeError):
|
||||
j[slice(0, 640)] = self.j2k_data
|
||||
|
||||
def test_cannot_write_a_row(self):
|
||||
with tempfile.NamedTemporaryFile(suffix='.j2k') as tfile:
|
||||
j = Jp2k(tfile.name, 'wb')
|
||||
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')
|
||||
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')
|
||||
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')
|
||||
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')
|
||||
with self.assertRaises(TypeError):
|
||||
j[:25, :45, :] = self.j2k_data[:25, :25, :]
|
||||
|
||||
|
||||
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.
|
||||
self.j2k[::2, ::3]
|
||||
|
||||
def test_resolution_strides_must_be_powers_of_two(self):
|
||||
with self.assertRaises(IndexError):
|
||||
self.j2k[::3, ::3]
|
||||
|
||||
def test_integer_index_in_3d(self):
|
||||
|
||||
for j in [0, 1, 2]:
|
||||
band = self.j2k[:, :, j]
|
||||
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]
|
||||
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)
|
||||
|
||||
def test_retrieve_single_row(self):
|
||||
actual = self.jp2[0]
|
||||
expected = self.jp2_data[0]
|
||||
np.testing.assert_array_equal(actual, expected)
|
||||
|
||||
def test_retrieve_single_pixel(self):
|
||||
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]
|
||||
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_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))
|
||||
|
||||
def test_region_rlevel5(self):
|
||||
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]
|
||||
np.testing.assert_array_equal(actual, expected)
|
||||
|
||||
class TestJp2k(unittest.TestCase):
|
||||
"""These tests should be run by just about all configuration."""
|
||||
|
||||
|
|
@ -63,6 +423,7 @@ class TestJp2k(unittest.TestCase):
|
|||
def tearDown(self):
|
||||
pass
|
||||
|
||||
|
||||
@unittest.skipIf(os.name == "nt", "Unexplained failure on windows")
|
||||
def test_irreversible(self):
|
||||
"""Irreversible"""
|
||||
|
|
@ -566,13 +927,6 @@ class TestJp2k_1_x(unittest.TestCase):
|
|||
def tearDown(self):
|
||||
pass
|
||||
|
||||
def test_area(self):
|
||||
"""Area option not allowed for 1.x.
|
||||
"""
|
||||
j2k = Jp2k(self.j2kfile)
|
||||
with self.assertRaises(TypeError):
|
||||
j2k.read(area=(0, 0, 100, 100))
|
||||
|
||||
def test_tile(self):
|
||||
"""tile option not allowed for 1.x.
|
||||
"""
|
||||
|
|
@ -725,6 +1079,7 @@ class TestJp2k_2_1(unittest.TestCase):
|
|||
self.assertEqual(j.box[2].box[0].num_components, 4)
|
||||
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")
|
||||
def test_openjpeg_library_message(self):
|
||||
"""Verify the error message produced by the openjpeg library"""
|
||||
|
|
@ -749,8 +1104,7 @@ class TestJp2k_2_1(unittest.TestCase):
|
|||
tfile.write(data[offset+59:])
|
||||
#tfile.write(data[3186:])
|
||||
tfile.flush()
|
||||
with warnings.catch_warnings():
|
||||
warnings.simplefilter("ignore")
|
||||
with self.assertWarns(UserWarning):
|
||||
j = Jp2k(tfile.name)
|
||||
regexp = re.compile(r'''OpenJPEG\slibrary\serror:\s+
|
||||
Invalid\svalues\sfor\scomp\s=\s0\s+
|
||||
|
|
@ -774,21 +1128,16 @@ class TestParsing(unittest.TestCase):
|
|||
def tearDown(self):
|
||||
pass
|
||||
|
||||
@unittest.skipIf(sys.platform.startswith('linux'), 'Failing on linux')
|
||||
@unittest.skipIf(WARNING_INFRASTRUCTURE_ISSUE, WARNING_INFRASTRUCTURE_MSG)
|
||||
def test_bad_rsiz(self):
|
||||
"""Should not warn if RSIZ when parsing is turned off."""
|
||||
# Actually there are three warning triggered by this codestream.
|
||||
filename = opj_data_file('input/nonregression/edf_c2_1002767.jp2')
|
||||
glymur.set_parseoptions(codestream=False)
|
||||
with warnings.catch_warnings(record=True) as w:
|
||||
j = Jp2k(filename)
|
||||
self.assertEqual(len(w), 0)
|
||||
j = Jp2k(filename)
|
||||
|
||||
glymur.set_parseoptions(codestream=True)
|
||||
with warnings.catch_warnings(record=True) as w:
|
||||
with self.assertWarnsRegex(UserWarning, 'Invalid profile'):
|
||||
jp2 = Jp2k(filename)
|
||||
self.assertTrue(issubclass(w[0].category, UserWarning))
|
||||
self.assertTrue('Invalid profile' in str(w[0].message))
|
||||
|
||||
def test_main_header(self):
|
||||
"""Verify that the main header is not loaded when parsing turned off."""
|
||||
|
|
@ -800,6 +1149,7 @@ class TestParsing(unittest.TestCase):
|
|||
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")
|
||||
class TestJp2kOpjDataRootWarnings(unittest.TestCase):
|
||||
|
|
@ -808,11 +1158,8 @@ class TestJp2kOpjDataRootWarnings(unittest.TestCase):
|
|||
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')
|
||||
with warnings.catch_warnings(record=True) as w:
|
||||
warnings.simplefilter('always')
|
||||
with self.assertWarnsRegex(UserWarning, 'Unrecognized box'):
|
||||
jp2 = Jp2k(filename)
|
||||
self.assertTrue(issubclass(w[0].category, UserWarning))
|
||||
self.assertTrue('Unrecognized box' in str(w[0].message))
|
||||
|
||||
# Now make sure we got all of the boxes. Ignore the last, which was
|
||||
# bad.
|
||||
|
|
@ -822,37 +1169,30 @@ class TestJp2kOpjDataRootWarnings(unittest.TestCase):
|
|||
def test_bad_ftyp_brand(self):
|
||||
"""Should warn in case of bad ftyp brand."""
|
||||
filename = opj_data_file('input/nonregression/edf_c2_1000290.jp2')
|
||||
with warnings.catch_warnings(record=True) as w:
|
||||
warnings.simplefilter('always')
|
||||
with self.assertWarns(UserWarning):
|
||||
jp2 = Jp2k(filename)
|
||||
self.assertTrue(issubclass(w[0].category, UserWarning))
|
||||
|
||||
def test_invalid_approximation(self):
|
||||
"""Should warn in case of invalid approximation."""
|
||||
filename = opj_data_file('input/nonregression/edf_c2_1015644.jp2')
|
||||
with warnings.catch_warnings(record=True) as w:
|
||||
warnings.simplefilter('always')
|
||||
with self.assertWarnsRegex(UserWarning, 'Invalid approximation'):
|
||||
jp2 = Jp2k(filename)
|
||||
self.assertTrue(issubclass(w[0].category, UserWarning))
|
||||
self.assertTrue('Invalid approximation' in str(w[0].message))
|
||||
|
||||
@unittest.skipIf(sys.platform.startswith('linux'), 'Failing on linux')
|
||||
def test_invalid_colorspace(self):
|
||||
"""Should warn in case of invalid colorspace."""
|
||||
"""
|
||||
Should warn in case of invalid colorspace.
|
||||
|
||||
There are multiple warnings, so there's no good way to regex them all.
|
||||
"""
|
||||
filename = opj_data_file('input/nonregression/edf_c2_1103421.jp2')
|
||||
with warnings.catch_warnings(record=True) as w:
|
||||
warnings.simplefilter('always')
|
||||
with self.assertWarns(UserWarning):
|
||||
jp2 = Jp2k(filename)
|
||||
self.assertTrue(issubclass(w[1].category, UserWarning))
|
||||
self.assertTrue('Unrecognized colorspace' in str(w[1].message))
|
||||
|
||||
def test_stupid_windows_eol_at_end(self):
|
||||
"""Garbage characters at the end of the file."""
|
||||
filename = opj_data_file('input/nonregression/issue211.jp2')
|
||||
with warnings.catch_warnings(record=True) as w:
|
||||
warnings.simplefilter('always')
|
||||
with self.assertWarns(UserWarning):
|
||||
jp2 = Jp2k(filename)
|
||||
self.assertTrue(issubclass(w[1].category, UserWarning))
|
||||
|
||||
|
||||
@unittest.skipIf(OPJ_DATA_ROOT is None,
|
||||
|
|
@ -877,10 +1217,12 @@ class TestJp2kOpjDataRoot(unittest.TestCase):
|
|||
actdata = j.read()
|
||||
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"""
|
||||
filename = opj_data_file('input/conformance/file9.jp2')
|
||||
j = Jp2k(filename)
|
||||
with self.assertWarns(UserWarning):
|
||||
j = Jp2k(filename)
|
||||
rgb = j.read()
|
||||
idx = j.read(ignore_pclr_cmap_cdef=True)
|
||||
self.assertEqual(rgb.shape, (512, 768, 3))
|
||||
|
|
@ -905,15 +1247,15 @@ class TestJp2kOpjDataRoot(unittest.TestCase):
|
|||
j = Jp2k(filename)
|
||||
with self.assertRaises(RuntimeError):
|
||||
j.read()
|
||||
|
||||
|
||||
@unittest.skipIf(WARNING_INFRASTRUCTURE_ISSUE, WARNING_INFRASTRUCTURE_MSG)
|
||||
def test_no_cxform_cmap(self):
|
||||
"""Bands as physically ordered, not as physically intended"""
|
||||
# This file has the components physically reversed. The cmap box
|
||||
# tells the decoder how to order them, but this flag prevents that.
|
||||
filename = opj_data_file('input/conformance/file2.jp2')
|
||||
with warnings.catch_warnings():
|
||||
with self.assertWarns(UserWarning):
|
||||
# The file has a bad compatibility list entry. Not important here.
|
||||
warnings.simplefilter("ignore")
|
||||
j = Jp2k(filename)
|
||||
ycbcr = j.read()
|
||||
crcby = j.read(ignore_pclr_cmap_cdef=True)
|
||||
|
|
|
|||
|
|
@ -31,20 +31,19 @@ import re
|
|||
import sys
|
||||
import unittest
|
||||
|
||||
import warnings
|
||||
|
||||
import numpy as np
|
||||
|
||||
from glymur import Jp2k
|
||||
import glymur
|
||||
from glymur import Jp2k
|
||||
from glymur.jp2box import FileTypeBox, ImageHeaderBox, ColourSpecificationBox
|
||||
|
||||
from .fixtures import OPJ_DATA_ROOT
|
||||
from .fixtures import mse, peak_tolerance, read_pgx, opj_data_file
|
||||
from .fixtures import (
|
||||
OPJ_DATA_ROOT, MetadataBase,
|
||||
WARNING_INFRASTRUCTURE_ISSUE, WARNING_INFRASTRUCTURE_MSG,
|
||||
mse, peak_tolerance, read_pgx, opj_data_file
|
||||
)
|
||||
|
||||
|
||||
@unittest.skipIf(glymur.lib.openjp2.OPENJP2 is None and
|
||||
glymur.lib.openjpeg.OPENJPEG is None,
|
||||
"Missing openjpeg libraries.")
|
||||
@unittest.skipIf(OPJ_DATA_ROOT is None,
|
||||
"OPJ_DATA_ROOT environment variable not set")
|
||||
class TestSuite(unittest.TestCase):
|
||||
|
|
@ -95,24 +94,6 @@ class TestSuite(unittest.TestCase):
|
|||
self.assertTrue(peak_tolerance(jpdata[:, :, 2], pgxdata) < 6)
|
||||
self.assertTrue(mse(jpdata[:, :, 2], pgxdata) < 1.07)
|
||||
|
||||
@unittest.skip("Known failure in OPENJPEG test suite operation.")
|
||||
def test_ETS_C1P0_p0_07_j2k(self):
|
||||
jfile = opj_data_file('input/conformance/p0_07.j2k')
|
||||
jp2k = Jp2k(jfile)
|
||||
jpdata = jp2k.read()
|
||||
|
||||
pgxfile = opj_data_file('baseline/conformance/c1p0_07_0.pgx')
|
||||
pgxdata = read_pgx(pgxfile)
|
||||
np.testing.assert_array_equal(jpdata[:, :, 0], pgxdata)
|
||||
|
||||
pgxfile = opj_data_file('baseline/conformance/c1p0_07_1.pgx')
|
||||
pgxdata = read_pgx(pgxfile)
|
||||
np.testing.assert_array_equal(jpdata[:, : 1], pgxdata)
|
||||
|
||||
pgxfile = opj_data_file('baseline/conformance/c1p0_07_2.pgx')
|
||||
pgxdata = read_pgx(pgxfile)
|
||||
np.testing.assert_array_equal(jpdata[:, : 2], pgxdata)
|
||||
|
||||
def test_ETS_C1P0_p0_08_j2k(self):
|
||||
jfile = opj_data_file('input/conformance/p0_08.j2k')
|
||||
jp2k = Jp2k(jfile)
|
||||
|
|
@ -222,197 +203,6 @@ class TestSuite(unittest.TestCase):
|
|||
self.assertTrue(peak_tolerance(jpdata, pgxdata) < 624)
|
||||
self.assertTrue(mse(jpdata, pgxdata) < 3080)
|
||||
|
||||
def test_ETS_JP2_file1(self):
|
||||
jfile = opj_data_file('input/conformance/file1.jp2')
|
||||
with warnings.catch_warnings():
|
||||
# Bad compatibility list item.
|
||||
warnings.simplefilter("ignore")
|
||||
jp2k = Jp2k(jfile)
|
||||
jpdata = jp2k.read()
|
||||
self.assertEqual(jpdata.shape, (512, 768, 3))
|
||||
|
||||
def test_ETS_JP2_file2(self):
|
||||
jfile = opj_data_file('input/conformance/file2.jp2')
|
||||
jp2k = Jp2k(jfile)
|
||||
jpdata = jp2k.read()
|
||||
self.assertEqual(jpdata.shape, (640, 480, 3))
|
||||
|
||||
@unittest.skipIf(glymur.version.openjpeg_version_tuple[0] < 2,
|
||||
"Functionality not implemented for 1.x")
|
||||
def test_ETS_JP2_file3(self):
|
||||
jfile = opj_data_file('input/conformance/file3.jp2')
|
||||
jp2k = Jp2k(jfile)
|
||||
jpdata = jp2k.read_bands()
|
||||
self.assertEqual(jpdata[0].shape, (640, 480))
|
||||
self.assertEqual(jpdata[1].shape, (320, 240))
|
||||
self.assertEqual(jpdata[2].shape, (320, 240))
|
||||
|
||||
def test_ETS_JP2_file4(self):
|
||||
jfile = opj_data_file('input/conformance/file4.jp2')
|
||||
jp2k = Jp2k(jfile)
|
||||
jpdata = jp2k.read()
|
||||
self.assertEqual(jpdata.shape, (512, 768))
|
||||
|
||||
def test_ETS_JP2_file5(self):
|
||||
jfile = opj_data_file('input/conformance/file5.jp2')
|
||||
with warnings.catch_warnings():
|
||||
# There's a warning for an unknown compatibility entry.
|
||||
# Ignore it here.
|
||||
warnings.simplefilter("ignore")
|
||||
jp2k = Jp2k(jfile)
|
||||
jpdata = jp2k.read()
|
||||
self.assertEqual(jpdata.shape, (512, 768, 3))
|
||||
|
||||
def test_ETS_JP2_file6(self):
|
||||
jfile = opj_data_file('input/conformance/file6.jp2')
|
||||
jp2k = Jp2k(jfile)
|
||||
jpdata = jp2k.read()
|
||||
self.assertEqual(jpdata.shape, (512, 768))
|
||||
|
||||
def test_ETS_JP2_file7(self):
|
||||
jfile = opj_data_file('input/conformance/file7.jp2')
|
||||
jp2k = Jp2k(jfile)
|
||||
jpdata = jp2k.read()
|
||||
self.assertEqual(jpdata.shape, (640, 480, 3))
|
||||
|
||||
def test_ETS_JP2_file8(self):
|
||||
jfile = opj_data_file('input/conformance/file8.jp2')
|
||||
jp2k = Jp2k(jfile)
|
||||
jpdata = jp2k.read()
|
||||
self.assertEqual(jpdata.shape, (400, 700))
|
||||
|
||||
def test_ETS_JP2_file9(self):
|
||||
jfile = opj_data_file('input/conformance/file9.jp2')
|
||||
jp2k = Jp2k(jfile)
|
||||
jpdata = jp2k.read()
|
||||
self.assertEqual(jpdata.shape, (512, 768, 3))
|
||||
|
||||
def test_NR_broken_jp2_dump(self):
|
||||
jfile = opj_data_file('input/nonregression/broken.jp2')
|
||||
|
||||
with warnings.catch_warnings():
|
||||
# colr box has bad length.
|
||||
warnings.simplefilter("ignore")
|
||||
jp2 = Jp2k(jfile)
|
||||
|
||||
ids = [box.box_id for box in jp2.box]
|
||||
self.assertEqual(ids, ['jP ', 'ftyp', 'jp2h', 'jp2c'])
|
||||
|
||||
ids = [box.box_id for box in jp2.box[2].box]
|
||||
self.assertEqual(ids, ['ihdr', 'colr'])
|
||||
|
||||
# Signature box. Check for corruption.
|
||||
self.assertEqual(jp2.box[0].signature, (13, 10, 135, 10))
|
||||
|
||||
# File type box.
|
||||
self.assertEqual(jp2.box[1].brand, 'jp2 ')
|
||||
self.assertEqual(jp2.box[1].minor_version, 0)
|
||||
self.assertEqual(jp2.box[1].compatibility_list[0], 'jp2 ')
|
||||
|
||||
# Jp2 Header
|
||||
# Image header
|
||||
self.assertEqual(jp2.box[2].box[0].height, 152)
|
||||
self.assertEqual(jp2.box[2].box[0].width, 203)
|
||||
self.assertEqual(jp2.box[2].box[0].num_components, 3)
|
||||
self.assertEqual(jp2.box[2].box[0].bits_per_component, 8)
|
||||
self.assertEqual(jp2.box[2].box[0].signed, False)
|
||||
self.assertEqual(jp2.box[2].box[0].compression, 7) # wavelet
|
||||
self.assertEqual(jp2.box[2].box[0].colorspace_unknown, False)
|
||||
self.assertEqual(jp2.box[2].box[0].ip_provided, False)
|
||||
|
||||
# Jp2 Header
|
||||
# Colour specification
|
||||
self.assertEqual(jp2.box[2].box[1].method,
|
||||
glymur.core.ENUMERATED_COLORSPACE)
|
||||
self.assertEqual(jp2.box[2].box[1].precedence, 0)
|
||||
self.assertEqual(jp2.box[2].box[1].approximation, 0) # not allowed?
|
||||
self.assertEqual(jp2.box[2].box[1].colorspace, glymur.core.SRGB)
|
||||
|
||||
c = jp2.box[3].main_header
|
||||
|
||||
ids = [x.marker_id for x in c.segment]
|
||||
expected = ['SOC', 'SIZ', 'CME', 'COD', 'QCD', 'QCC', 'QCC']
|
||||
self.assertEqual(ids, expected)
|
||||
|
||||
# SIZ: Image and tile size
|
||||
# Profile:
|
||||
self.assertEqual(c.segment[1].rsiz, 0)
|
||||
# Reference grid size
|
||||
self.assertEqual(c.segment[1].xsiz, 203)
|
||||
self.assertEqual(c.segment[1].ysiz, 152)
|
||||
# Reference grid offset
|
||||
self.assertEqual((c.segment[1].xosiz, c.segment[1].yosiz), (0, 0))
|
||||
# Tile size
|
||||
self.assertEqual((c.segment[1].xtsiz, c.segment[1].ytsiz), (203, 152))
|
||||
# Tile offset
|
||||
self.assertEqual((c.segment[1].xtosiz, c.segment[1].ytosiz), (0, 0))
|
||||
# bitdepth
|
||||
self.assertEqual(c.segment[1].bitdepth, (8, 8, 8))
|
||||
# signed
|
||||
self.assertEqual(c.segment[1].signed, (False, False, False))
|
||||
# subsampling
|
||||
self.assertEqual(list(zip(c.segment[1].xrsiz, c.segment[1].yrsiz)),
|
||||
[(1, 1)] * 3)
|
||||
|
||||
# COM: comment
|
||||
# Registration
|
||||
self.assertEqual(c.segment[2].rcme, glymur.core.RCME_ISO_8859_1)
|
||||
# Comment value
|
||||
self.assertEqual(c.segment[2].ccme.decode('latin-1'),
|
||||
"Creator: JasPer Version 1.701.0")
|
||||
|
||||
# COD: Coding style default
|
||||
self.assertFalse(c.segment[3].scod & 2) # no sop
|
||||
self.assertFalse(c.segment[3].scod & 4) # no eph
|
||||
self.assertEqual(c.segment[3].spcod[0], glymur.core.LRCP)
|
||||
self.assertEqual(c.segment[3].layers, 1) # layers = 1
|
||||
self.assertEqual(c.segment[3].spcod[3], 1) # mct
|
||||
self.assertEqual(c.segment[3].spcod[4], 5) # level
|
||||
self.assertEqual(tuple(c.segment[3].code_block_size),
|
||||
(64, 64)) # cblk
|
||||
# Selective arithmetic coding bypass
|
||||
self.assertFalse(c.segment[3].spcod[7] & 0x01)
|
||||
# Reset context probabilities
|
||||
self.assertFalse(c.segment[3].spcod[7] & 0x02)
|
||||
# Termination on each coding pass
|
||||
self.assertFalse(c.segment[3].spcod[7] & 0x04)
|
||||
# Vertically causal context
|
||||
self.assertFalse(c.segment[3].spcod[7] & 0x08)
|
||||
# Predictable termination
|
||||
self.assertFalse(c.segment[3].spcod[7] & 0x0010)
|
||||
# Segmentation symbols
|
||||
self.assertFalse(c.segment[3].spcod[7] & 0x0020)
|
||||
self.assertEqual(c.segment[3].spcod[8],
|
||||
glymur.core.WAVELET_XFORM_5X3_REVERSIBLE)
|
||||
self.assertEqual(len(c.segment[3].spcod), 9)
|
||||
|
||||
# QCD: Quantization default
|
||||
self.assertEqual(c.segment[4].sqcd & 0x1f, 0)
|
||||
self.assertEqual(c.segment[4].guard_bits, 2)
|
||||
self.assertEqual(c.segment[4].mantissa, [0] * 16)
|
||||
self.assertEqual(c.segment[4].exponent,
|
||||
[8] + [9, 9, 10] * 5)
|
||||
|
||||
# QCC: Quantization component
|
||||
# associated component
|
||||
self.assertEqual(c.segment[5].cqcc, 1)
|
||||
self.assertEqual(c.segment[5].guard_bits, 2)
|
||||
# quantization type
|
||||
self.assertEqual(c.segment[5].sqcc & 0x1f, 0) # none
|
||||
self.assertEqual(c.segment[5].mantissa, [0] * 16)
|
||||
self.assertEqual(c.segment[5].exponent,
|
||||
[8] + [9, 9, 10] * 5)
|
||||
|
||||
# QCC: Quantization component
|
||||
# associated component
|
||||
self.assertEqual(c.segment[6].cqcc, 2)
|
||||
self.assertEqual(c.segment[6].guard_bits, 2)
|
||||
# quantization type
|
||||
self.assertEqual(c.segment[6].sqcc & 0x1f, 0) # none
|
||||
self.assertEqual(c.segment[6].mantissa, [0] * 16)
|
||||
self.assertEqual(c.segment[6].exponent,
|
||||
[8] + [9, 9, 10] * 5)
|
||||
|
||||
def test_NR_DEC_Bretagne2_j2k_1_decode(self):
|
||||
jfile = opj_data_file('input/nonregression/Bretagne2.j2k')
|
||||
jp2 = Jp2k(jfile)
|
||||
|
|
@ -492,19 +282,6 @@ class TestSuite(unittest.TestCase):
|
|||
Jp2k(jfile).read()
|
||||
self.assertTrue(True)
|
||||
|
||||
def test_NR_DEC_orb_blue_lin_jp2_25_decode(self):
|
||||
jfile = opj_data_file('input/nonregression/orb-blue10-lin-jp2.jp2')
|
||||
with warnings.catch_warnings():
|
||||
# This file has an invalid ICC profile
|
||||
warnings.simplefilter("ignore")
|
||||
Jp2k(jfile).read()
|
||||
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')
|
||||
Jp2k(jfile).read()
|
||||
self.assertTrue(True)
|
||||
|
||||
def test_NR_DEC_relax_jp2_27_decode(self):
|
||||
jfile = opj_data_file('input/nonregression/relax.jp2')
|
||||
Jp2k(jfile).read()
|
||||
|
|
@ -521,15 +298,194 @@ class TestSuite(unittest.TestCase):
|
|||
self.assertTrue(True)
|
||||
|
||||
|
||||
@unittest.skipIf(OPJ_DATA_ROOT is None,
|
||||
"OPJ_DATA_ROOT environment variable not set")
|
||||
@unittest.skipIf(WARNING_INFRASTRUCTURE_ISSUE, WARNING_INFRASTRUCTURE_MSG)
|
||||
class TestSuiteWarns(MetadataBase):
|
||||
"""
|
||||
Identical setup to above, but these tests issue warnings.
|
||||
"""
|
||||
|
||||
def setUp(self):
|
||||
pass
|
||||
|
||||
def tearDown(self):
|
||||
pass
|
||||
|
||||
def test_ETS_JP2_file1(self):
|
||||
jfile = opj_data_file('input/conformance/file1.jp2')
|
||||
with self.assertWarns(UserWarning):
|
||||
# Bad compatibility list item.
|
||||
jp2k = Jp2k(jfile)
|
||||
jpdata = jp2k.read()
|
||||
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()
|
||||
self.assertEqual(jpdata.shape, (640, 480, 3))
|
||||
|
||||
@unittest.skipIf(glymur.version.openjpeg_version_tuple[0] < 2,
|
||||
"Functionality not implemented for 1.x")
|
||||
def test_ETS_JP2_file3(self):
|
||||
jfile = opj_data_file('input/conformance/file3.jp2')
|
||||
with self.assertWarns(UserWarning):
|
||||
jp2k = Jp2k(jfile)
|
||||
jpdata = jp2k.read_bands()
|
||||
self.assertEqual(jpdata[0].shape, (640, 480))
|
||||
self.assertEqual(jpdata[1].shape, (320, 240))
|
||||
self.assertEqual(jpdata[2].shape, (320, 240))
|
||||
|
||||
def test_ETS_JP2_file4(self):
|
||||
jfile = opj_data_file('input/conformance/file4.jp2')
|
||||
with self.assertWarns(UserWarning):
|
||||
jp2k = Jp2k(jfile)
|
||||
jpdata = jp2k.read()
|
||||
self.assertEqual(jpdata.shape, (512, 768))
|
||||
|
||||
def test_ETS_JP2_file5(self):
|
||||
jfile = opj_data_file('input/conformance/file5.jp2')
|
||||
with self.assertWarns(UserWarning):
|
||||
# There's a warning for an unknown compatibility entry.
|
||||
# Ignore it here.
|
||||
jp2k = Jp2k(jfile)
|
||||
jpdata = jp2k.read()
|
||||
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()
|
||||
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()
|
||||
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()
|
||||
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()
|
||||
self.assertEqual(jpdata.shape, (512, 768, 3))
|
||||
|
||||
def test_NR_broken_jp2_dump(self):
|
||||
jfile = opj_data_file('input/nonregression/broken.jp2')
|
||||
|
||||
with self.assertWarns(UserWarning):
|
||||
# colr box has bad length.
|
||||
jp2 = Jp2k(jfile)
|
||||
|
||||
ids = [box.box_id for box in jp2.box]
|
||||
self.assertEqual(ids, ['jP ', 'ftyp', 'jp2h', 'jp2c'])
|
||||
|
||||
ids = [box.box_id for box in jp2.box[2].box]
|
||||
self.assertEqual(ids, ['ihdr', 'colr'])
|
||||
|
||||
# Signature box. Check for corruption.
|
||||
self.assertEqual(jp2.box[0].signature, (13, 10, 135, 10))
|
||||
self.verify_filetype_box(jp2.box[1], FileTypeBox())
|
||||
|
||||
expected = ImageHeaderBox(152, 203, num_components=3)
|
||||
self.verifyImageHeaderBox(jp2.box[2].box[0], expected)
|
||||
|
||||
expected = ColourSpecificationBox(colorspace=glymur.core.SRGB)
|
||||
self.verifyColourSpecificationBox(jp2.box[2].box[1], expected)
|
||||
|
||||
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 = (glymur.core.RCME_ISO_8859_1,
|
||||
"Creator: JasPer Version 1.701.0".encode())
|
||||
self.verifyCMEsegment(c.segment[2],
|
||||
glymur.codestream.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_DEC_orb_blue_lin_jp2_25_decode(self):
|
||||
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()
|
||||
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()
|
||||
self.assertTrue(True)
|
||||
|
||||
|
||||
@unittest.skipIf(OPJ_DATA_ROOT is None,
|
||||
"OPJ_DATA_ROOT environment variable not set")
|
||||
@unittest.skipIf(glymur.version.openjpeg_version_tuple[0] == 1,
|
||||
"Feature not supported in glymur until openjpeg 2.0")
|
||||
class TestSuite_bands(unittest.TestCase):
|
||||
"""Runs tests introduced in version 1.x but only pass in glymur with 2.0
|
||||
|
||||
The deal here is that the feature works with 1.x, but glymur only supports
|
||||
it with version 2.0.
|
||||
class TestSuiteBands(unittest.TestCase):
|
||||
"""
|
||||
Test the read_bands method.
|
||||
"""
|
||||
|
||||
def setUp(self):
|
||||
|
|
@ -648,34 +604,34 @@ class TestSuite2point0(unittest.TestCase):
|
|||
pgxdata = read_pgx(pgxfile)
|
||||
np.testing.assert_array_equal(jpdata[:, :, 2], pgxdata)
|
||||
|
||||
@unittest.skipIf(WARNING_INFRASTRUCTURE_ISSUE, WARNING_INFRASTRUCTURE_MSG)
|
||||
def test_NR_DEC_broken2_jp2_5_decode(self):
|
||||
# Null pointer access
|
||||
jfile = opj_data_file('input/nonregression/broken2.jp2')
|
||||
with self.assertRaises(IOError):
|
||||
with warnings.catch_warnings():
|
||||
with self.assertWarns(UserWarning):
|
||||
# Invalid marker ID.
|
||||
warnings.simplefilter("ignore")
|
||||
Jp2k(jfile).read()
|
||||
self.assertTrue(True)
|
||||
|
||||
@unittest.skipIf(WARNING_INFRASTRUCTURE_ISSUE, WARNING_INFRASTRUCTURE_MSG)
|
||||
def test_NR_DEC_broken4_jp2_7_decode(self):
|
||||
jfile = opj_data_file('input/nonregression/broken4.jp2')
|
||||
with self.assertRaises(IOError):
|
||||
with warnings.catch_warnings():
|
||||
with self.assertWarns(UserWarning):
|
||||
# invalid number of subbands, bad marker ID
|
||||
warnings.simplefilter("ignore")
|
||||
Jp2k(jfile).read()
|
||||
self.assertTrue(True)
|
||||
|
||||
@unittest.skipIf(WARNING_INFRASTRUCTURE_ISSUE, WARNING_INFRASTRUCTURE_MSG)
|
||||
def test_NR_DEC_kakadu_v4_4_openjpegv2_broken_j2k_16_decode(self):
|
||||
# This test actually passes in 1.5, but produces unpleasant warning
|
||||
# messages that cannot be turned off?
|
||||
relpath = 'input/nonregression/kakadu_v4-4_openjpegv2_broken.j2k'
|
||||
jfile = opj_data_file(relpath)
|
||||
if glymur.version.openjpeg_version_tuple[0] < 2:
|
||||
with warnings.catch_warnings():
|
||||
with self.assertWarns(UserWarning):
|
||||
# Incorrect warning issued about tile parts.
|
||||
warnings.simplefilter("ignore")
|
||||
Jp2k(jfile).read()
|
||||
else:
|
||||
Jp2k(jfile).read()
|
||||
|
|
|
|||
|
|
@ -31,14 +31,13 @@ import re
|
|||
import sys
|
||||
import unittest
|
||||
|
||||
import warnings
|
||||
|
||||
import numpy as np
|
||||
|
||||
from glymur import Jp2k
|
||||
import glymur
|
||||
|
||||
from .fixtures import OPJ_DATA_ROOT
|
||||
from .fixtures import WARNING_INFRASTRUCTURE_ISSUE, WARNING_INFRASTRUCTURE_MSG
|
||||
from .fixtures import mse, peak_tolerance, read_pgx, opj_data_file
|
||||
|
||||
|
||||
|
|
@ -56,11 +55,11 @@ class TestSuite2point1(unittest.TestCase):
|
|||
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 warnings.catch_warnings():
|
||||
with self.assertWarns(UserWarning):
|
||||
# brand is 'jp2 ', but has any icc profile.
|
||||
warnings.simplefilter("ignore")
|
||||
jp2 = Jp2k(jfile)
|
||||
jp2.read()
|
||||
self.assertTrue(True)
|
||||
|
|
@ -85,32 +84,32 @@ class TestSuite2point1(unittest.TestCase):
|
|||
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 warnings.catch_warnings():
|
||||
with self.assertWarns(UserWarning):
|
||||
# Invalid number of resolutions.
|
||||
warnings.simplefilter("ignore")
|
||||
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 warnings.catch_warnings():
|
||||
with self.assertWarns(UserWarning):
|
||||
# Invalid number of tiles.
|
||||
warnings.simplefilter("ignore")
|
||||
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 warnings.catch_warnings():
|
||||
with self.assertWarns(UserWarning):
|
||||
# Invalid subsampling value
|
||||
warnings.simplefilter("ignore")
|
||||
with self.assertRaises(IOError):
|
||||
Jp2k(jfile).read()
|
||||
|
||||
|
|
@ -124,105 +123,6 @@ class TestSuite2point1(unittest.TestCase):
|
|||
Jp2k(jfile).read()
|
||||
self.assertTrue(True)
|
||||
|
||||
def test_NR_DEC_p1_04_j2k_43_decode(self):
|
||||
jfile = opj_data_file('input/conformance/p1_04.j2k')
|
||||
jp2k = Jp2k(jfile)
|
||||
ssdata = jp2k.read(area=(0, 0, 1024, 1024))
|
||||
odata = jp2k.read()
|
||||
np.testing.assert_array_equal(ssdata, odata)
|
||||
|
||||
def test_NR_DEC_p1_04_j2k_44_decode(self):
|
||||
jfile = opj_data_file('input/conformance/p1_04.j2k')
|
||||
jp2k = Jp2k(jfile)
|
||||
ssdata = jp2k.read(area=(640, 512, 768, 640))
|
||||
odata = jp2k.read()
|
||||
np.testing.assert_array_equal(ssdata, odata[640:768, 512:640])
|
||||
|
||||
def test_NR_DEC_p1_04_j2k_45_decode(self):
|
||||
jfile = opj_data_file('input/conformance/p1_04.j2k')
|
||||
jp2k = Jp2k(jfile)
|
||||
ssdata = jp2k.read(area=(896, 896, 1024, 1024))
|
||||
odata = jp2k.read()
|
||||
np.testing.assert_array_equal(ssdata, odata[896:1024, 896:1024])
|
||||
|
||||
def test_NR_DEC_p1_04_j2k_46_decode(self):
|
||||
jfile = opj_data_file('input/conformance/p1_04.j2k')
|
||||
jp2k = Jp2k(jfile)
|
||||
ssdata = jp2k.read(area=(500, 100, 800, 300))
|
||||
odata = jp2k.read()
|
||||
np.testing.assert_array_equal(ssdata, odata[500:800, 100:300])
|
||||
|
||||
def test_NR_DEC_p1_04_j2k_47_decode(self):
|
||||
jfile = opj_data_file('input/conformance/p1_04.j2k')
|
||||
jp2k = Jp2k(jfile)
|
||||
ssdata = jp2k.read(area=(520, 260, 600, 360))
|
||||
odata = jp2k.read()
|
||||
np.testing.assert_array_equal(ssdata, odata[520:600, 260:360])
|
||||
|
||||
def test_NR_DEC_p1_04_j2k_48_decode(self):
|
||||
jfile = opj_data_file('input/conformance/p1_04.j2k')
|
||||
jp2k = Jp2k(jfile)
|
||||
ssdata = jp2k.read(area=(520, 260, 660, 360))
|
||||
odata = jp2k.read()
|
||||
np.testing.assert_array_equal(ssdata, odata[520:660, 260:360])
|
||||
|
||||
def test_NR_DEC_p1_04_j2k_49_decode(self):
|
||||
jfile = opj_data_file('input/conformance/p1_04.j2k')
|
||||
jp2k = Jp2k(jfile)
|
||||
ssdata = jp2k.read(area=(520, 360, 600, 400))
|
||||
odata = jp2k.read()
|
||||
np.testing.assert_array_equal(ssdata, odata[520:600, 360:400])
|
||||
|
||||
def test_NR_DEC_p1_04_j2k_50_decode(self):
|
||||
jfile = opj_data_file('input/conformance/p1_04.j2k')
|
||||
jp2k = Jp2k(jfile)
|
||||
ssdata = jp2k.read(area=(0, 0, 1024, 1024), rlevel=2)
|
||||
odata = jp2k.read(rlevel=2)
|
||||
|
||||
np.testing.assert_array_equal(ssdata, odata[0:256, 0:256])
|
||||
|
||||
def test_NR_DEC_p1_04_j2k_51_decode(self):
|
||||
jfile = opj_data_file('input/conformance/p1_04.j2k')
|
||||
jp2k = Jp2k(jfile)
|
||||
ssdata = jp2k.read(area=(640, 512, 768, 640), rlevel=2)
|
||||
odata = jp2k.read(rlevel=2)
|
||||
np.testing.assert_array_equal(ssdata, odata[160:192, 128:160])
|
||||
|
||||
def test_NR_DEC_p1_04_j2k_52_decode(self):
|
||||
jfile = opj_data_file('input/conformance/p1_04.j2k')
|
||||
jp2k = Jp2k(jfile)
|
||||
ssdata = jp2k.read(area=(896, 896, 1024, 1024), rlevel=2)
|
||||
odata = jp2k.read(rlevel=2)
|
||||
np.testing.assert_array_equal(ssdata, odata[224:352, 224:352])
|
||||
|
||||
def test_NR_DEC_p1_04_j2k_53_decode(self):
|
||||
jfile = opj_data_file('input/conformance/p1_04.j2k')
|
||||
jp2k = Jp2k(jfile)
|
||||
ssdata = jp2k.read(area=(500, 100, 800, 300), rlevel=2)
|
||||
odata = jp2k.read(rlevel=2)
|
||||
np.testing.assert_array_equal(ssdata, odata[125:200, 25:75])
|
||||
|
||||
def test_NR_DEC_p1_04_j2k_54_decode(self):
|
||||
jfile = opj_data_file('input/conformance/p1_04.j2k')
|
||||
jp2k = Jp2k(jfile)
|
||||
ssdata = jp2k.read(area=(520, 260, 600, 360), rlevel=2)
|
||||
odata = jp2k.read(rlevel=2)
|
||||
np.testing.assert_array_equal(ssdata, odata[130:150, 65:90])
|
||||
|
||||
def test_NR_DEC_p1_04_j2k_55_decode(self):
|
||||
jfile = opj_data_file('input/conformance/p1_04.j2k')
|
||||
jp2k = Jp2k(jfile)
|
||||
ssdata = jp2k.read(area=(520, 260, 660, 360), rlevel=2)
|
||||
odata = jp2k.read(rlevel=2)
|
||||
np.testing.assert_array_equal(ssdata, odata[130:165, 65:90])
|
||||
|
||||
def test_NR_DEC_p1_04_j2k_56_decode(self):
|
||||
jfile = opj_data_file('input/conformance/p1_04.j2k')
|
||||
jp2k = Jp2k(jfile)
|
||||
ssdata = jp2k.read(area=(520, 360, 600, 400), rlevel=2)
|
||||
odata = jp2k.read(rlevel=2)
|
||||
np.testing.assert_array_equal(ssdata, odata[130:150, 90:100])
|
||||
|
||||
def test_NR_DEC_p1_04_j2k_57_decode(self):
|
||||
jfile = opj_data_file('input/conformance/p1_04.j2k')
|
||||
jp2k = Jp2k(jfile)
|
||||
|
|
@ -251,139 +151,192 @@ class TestSuite2point1(unittest.TestCase):
|
|||
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 warnings.catch_warnings():
|
||||
with self.assertWarns(UserWarning):
|
||||
# Invalid component number.
|
||||
warnings.simplefilter("ignore")
|
||||
j = Jp2k(jfile)
|
||||
with self.assertRaises(IOError):
|
||||
j.read()
|
||||
|
||||
def test_NR_DEC_p1_06_j2k_70_decode(self):
|
||||
@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')
|
||||
jp2k = Jp2k(jfile)
|
||||
ssdata = jp2k.read(area=(9, 9, 12, 12), rlevel=1)
|
||||
self.assertEqual(ssdata.shape, (1, 1, 3))
|
||||
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):
|
||||
jfile = opj_data_file('input/conformance/p1_06.j2k')
|
||||
jp2k = Jp2k(jfile)
|
||||
ssdata = jp2k.read(area=(10, 4, 12, 10), rlevel=1)
|
||||
self.assertEqual(ssdata.shape, (1, 3, 3))
|
||||
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):
|
||||
jfile = opj_data_file('input/conformance/p1_06.j2k')
|
||||
jp2k = Jp2k(jfile)
|
||||
ssdata = jp2k.read(area=(3, 3, 9, 9), rlevel=1)
|
||||
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):
|
||||
jfile = opj_data_file('input/conformance/p1_06.j2k')
|
||||
jp2k = Jp2k(jfile)
|
||||
ssdata = jp2k.read(area=(4, 4, 7, 7), rlevel=1)
|
||||
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):
|
||||
jfile = opj_data_file('input/conformance/p1_06.j2k')
|
||||
jp2k = Jp2k(jfile)
|
||||
ssdata = jp2k.read(area=(4, 4, 5, 5), rlevel=1)
|
||||
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.
|
||||
jfile = opj_data_file('input/conformance/p1_06.j2k')
|
||||
jp2k = Jp2k(jfile)
|
||||
with self.assertRaises((IOError, OSError)):
|
||||
jp2k.read(area=(9, 9, 12, 12), rlevel=2)
|
||||
self.j2k_p1_06.read(area=(9, 9, 12, 12), rlevel=2)
|
||||
|
||||
def test_NR_DEC_p0_04_j2k_85_decode(self):
|
||||
jfile = opj_data_file('input/conformance/p0_04.j2k')
|
||||
jp2k = Jp2k(jfile)
|
||||
ssdata = jp2k.read(area=(0, 0, 256, 256))
|
||||
fulldata = jp2k.read()
|
||||
np.testing.assert_array_equal(fulldata[0:256, 0:256], ssdata)
|
||||
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):
|
||||
jfile = opj_data_file('input/conformance/p0_04.j2k')
|
||||
jp2k = Jp2k(jfile)
|
||||
ssdata = jp2k.read(area=(0, 128, 128, 256))
|
||||
fulldata = jp2k.read()
|
||||
np.testing.assert_array_equal(fulldata[0:128, 128:256], ssdata)
|
||||
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):
|
||||
jfile = opj_data_file('input/conformance/p0_04.j2k')
|
||||
jp2k = Jp2k(jfile)
|
||||
ssdata = jp2k.read(area=(10, 50, 200, 120))
|
||||
fulldata = jp2k.read()
|
||||
np.testing.assert_array_equal(fulldata[10:200, 50:120], ssdata)
|
||||
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):
|
||||
jfile = opj_data_file('input/conformance/p0_04.j2k')
|
||||
jp2k = Jp2k(jfile)
|
||||
ssdata = jp2k.read(area=(150, 10, 210, 190))
|
||||
fulldata = jp2k.read()
|
||||
np.testing.assert_array_equal(fulldata[150:210, 10:190], ssdata)
|
||||
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):
|
||||
jfile = opj_data_file('input/conformance/p0_04.j2k')
|
||||
jp2k = Jp2k(jfile)
|
||||
ssdata = jp2k.read(area=(80, 100, 150, 200))
|
||||
fulldata = jp2k.read()
|
||||
np.testing.assert_array_equal(fulldata[80:150, 100:200], ssdata)
|
||||
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):
|
||||
jfile = opj_data_file('input/conformance/p0_04.j2k')
|
||||
jp2k = Jp2k(jfile)
|
||||
ssdata = jp2k.read(area=(20, 150, 50, 200))
|
||||
fulldata = jp2k.read()
|
||||
np.testing.assert_array_equal(fulldata[20:50, 150:200], ssdata)
|
||||
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):
|
||||
jfile = opj_data_file('input/conformance/p0_04.j2k')
|
||||
jp2k = Jp2k(jfile)
|
||||
ssdata = jp2k.read(area=(0, 0, 256, 256), rlevel=2)
|
||||
fulldata = jp2k.read(rlevel=2)
|
||||
np.testing.assert_array_equal(fulldata[0:64, 0:64], ssdata)
|
||||
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):
|
||||
jfile = opj_data_file('input/conformance/p0_04.j2k')
|
||||
jp2k = Jp2k(jfile)
|
||||
ssdata = jp2k.read(area=(0, 128, 128, 256), rlevel=2)
|
||||
fulldata = jp2k.read(rlevel=2)
|
||||
np.testing.assert_array_equal(fulldata[0:32, 32:64], ssdata)
|
||||
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):
|
||||
jfile = opj_data_file('input/conformance/p0_04.j2k')
|
||||
jp2k = Jp2k(jfile)
|
||||
ssdata = jp2k.read(area=(10, 50, 200, 120), rlevel=2)
|
||||
fulldata = jp2k.read(rlevel=2)
|
||||
np.testing.assert_array_equal(fulldata[3:50, 13:30], ssdata)
|
||||
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):
|
||||
jfile = opj_data_file('input/conformance/p0_04.j2k')
|
||||
jp2k = Jp2k(jfile)
|
||||
ssdata = jp2k.read(area=(150, 10, 210, 190), rlevel=2)
|
||||
fulldata = jp2k.read(rlevel=2)
|
||||
np.testing.assert_array_equal(fulldata[38:53, 3:48], ssdata)
|
||||
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):
|
||||
jfile = opj_data_file('input/conformance/p0_04.j2k')
|
||||
jp2k = Jp2k(jfile)
|
||||
ssdata = jp2k.read(area=(80, 100, 150, 200), rlevel=2)
|
||||
fulldata = jp2k.read(rlevel=2)
|
||||
np.testing.assert_array_equal(fulldata[20:38, 25:50], ssdata)
|
||||
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):
|
||||
jfile = opj_data_file('input/conformance/p0_04.j2k')
|
||||
jp2k = Jp2k(jfile)
|
||||
ssdata = jp2k.read(area=(20, 150, 50, 200), rlevel=2)
|
||||
fulldata = jp2k.read(rlevel=2)
|
||||
np.testing.assert_array_equal(fulldata[5:13, 38:50], ssdata)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
unittest.main()
|
||||
actual = self.j2k.read(area=(20, 150, 50, 200), rlevel=2)
|
||||
expected = self.j2k_quarter_data[5:13, 38:50]
|
||||
np.testing.assert_array_equal(actual, expected)
|
||||
|
|
|
|||
File diff suppressed because it is too large
Load diff
|
|
@ -13,19 +13,17 @@ import re
|
|||
import sys
|
||||
import tempfile
|
||||
import unittest
|
||||
import warnings
|
||||
|
||||
import numpy as np
|
||||
|
||||
try:
|
||||
import skimage.io
|
||||
skimage.io.use_plugin('freeimage', 'imread')
|
||||
_HAS_SKIMAGE_FREEIMAGE_SUPPORT = True
|
||||
except ((ImportError, RuntimeError)):
|
||||
_HAS_SKIMAGE_FREEIMAGE_SUPPORT = False
|
||||
except ImportError:
|
||||
pass
|
||||
|
||||
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 glymur import Jp2k
|
||||
import glymur
|
||||
|
|
@ -44,7 +42,7 @@ class TestSuiteNegative(unittest.TestCase):
|
|||
pass
|
||||
|
||||
|
||||
@unittest.skipIf(not _HAS_SKIMAGE_FREEIMAGE_SUPPORT,
|
||||
@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):
|
||||
|
|
@ -78,13 +76,13 @@ class TestSuiteNegative(unittest.TestCase):
|
|||
jp2k.get_codestream(header_only=False)
|
||||
self.assertTrue(True)
|
||||
|
||||
@unittest.skipIf(WARNING_INFRASTRUCTURE_ISSUE, WARNING_INFRASTRUCTURE_MSG)
|
||||
def test_nr_illegalclrtransform(self):
|
||||
"""EOC marker is bad"""
|
||||
relpath = 'input/nonregression/illegalcolortransform.j2k'
|
||||
jfile = opj_data_file(relpath)
|
||||
jp2k = Jp2k(jfile)
|
||||
with warnings.catch_warnings():
|
||||
warnings.simplefilter('ignore')
|
||||
with self.assertWarns(UserWarning):
|
||||
codestream = jp2k.get_codestream(header_only=False)
|
||||
|
||||
# Verify that the last segment returned in the codestream is SOD,
|
||||
|
|
|
|||
File diff suppressed because it is too large
Load diff
|
|
@ -15,7 +15,6 @@ import re
|
|||
import struct
|
||||
import sys
|
||||
import tempfile
|
||||
import warnings
|
||||
import unittest
|
||||
|
||||
if sys.hexversion < 0x03000000:
|
||||
|
|
@ -31,9 +30,10 @@ else:
|
|||
import lxml.etree as ET
|
||||
|
||||
import glymur
|
||||
from glymur import Jp2k
|
||||
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
|
||||
|
||||
|
||||
|
|
@ -71,6 +71,7 @@ class TestPrinting(unittest.TestCase):
|
|||
|
||||
self.assertTrue(True)
|
||||
|
||||
@unittest.skipIf(WARNING_INFRASTRUCTURE_ISSUE, WARNING_INFRASTRUCTURE_MSG)
|
||||
def test_unknown_superbox(self):
|
||||
"""Verify that we can handle an unknown superbox."""
|
||||
with tempfile.NamedTemporaryFile(suffix='.jpx') as tfile:
|
||||
|
|
@ -87,9 +88,7 @@ class TestPrinting(unittest.TestCase):
|
|||
tfile.write(write_buffer)
|
||||
tfile.flush()
|
||||
|
||||
with warnings.catch_warnings():
|
||||
# Suppress the warning about the unrecognized box.
|
||||
warnings.simplefilter("ignore")
|
||||
with self.assertWarns(UserWarning):
|
||||
jpx = Jp2k(tfile.name)
|
||||
|
||||
glymur.set_printoptions(short=True)
|
||||
|
|
@ -107,74 +106,6 @@ class TestPrinting(unittest.TestCase):
|
|||
with self.assertRaises(TypeError):
|
||||
glymur.set_printoptions(hi='low')
|
||||
|
||||
def test_propts_no_codestream_then_no_xml(self):
|
||||
"""Verify printed output when codestream=False and xml=False, #162"""
|
||||
# The print options should be persistent across invocations.
|
||||
glymur.set_printoptions(codestream=False)
|
||||
glymur.set_printoptions(xml=False)
|
||||
with patch('sys.stdout', new=StringIO()) as fake_out:
|
||||
glymur.jp2dump(self.jp2file)
|
||||
actual = fake_out.getvalue().strip()
|
||||
|
||||
# Get rid of the filename line, as it is not set in stone.
|
||||
lst = actual.split('\n')
|
||||
lst = lst[1:]
|
||||
actual = '\n'.join(lst)
|
||||
self.assertEqual(actual, fixtures.nemo_dump_no_codestream_no_xml)
|
||||
|
||||
def test_printopt_no_codestr_or_xml(self):
|
||||
"""Verify printed output when codestream=False and xml=False"""
|
||||
glymur.set_printoptions(codestream=False, xml=False)
|
||||
with patch('sys.stdout', new=StringIO()) as fake_out:
|
||||
glymur.jp2dump(self.jp2file)
|
||||
actual = fake_out.getvalue().strip()
|
||||
|
||||
# Get rid of the filename line, as it is not set in stone.
|
||||
lst = actual.split('\n')
|
||||
lst = lst[1:]
|
||||
actual = '\n'.join(lst)
|
||||
self.assertEqual(actual, fixtures.nemo_dump_no_codestream_no_xml)
|
||||
|
||||
def test_printoptions_no_codestream(self):
|
||||
"""Verify printed output when codestream=False"""
|
||||
glymur.set_printoptions(codestream=False)
|
||||
with patch('sys.stdout', new=StringIO()) as fake_out:
|
||||
glymur.jp2dump(self.jp2file)
|
||||
actual = fake_out.getvalue().strip()
|
||||
|
||||
# Get rid of the filename line, as it is not set in stone.
|
||||
lst = actual.split('\n')
|
||||
lst = lst[1:]
|
||||
actual = '\n'.join(lst)
|
||||
self.assertEqual(actual, fixtures.nemo_dump_no_codestream)
|
||||
|
||||
def test_printoptions_no_xml(self):
|
||||
"""Verify printed output when xml=False"""
|
||||
glymur.set_printoptions(xml=False)
|
||||
with patch('sys.stdout', new=StringIO()) as fake_out:
|
||||
glymur.jp2dump(self.jp2file)
|
||||
actual = fake_out.getvalue().strip()
|
||||
|
||||
# Get rid of the filename line, as it is not set in stone.
|
||||
lst = actual.split('\n')
|
||||
lst = lst[1:]
|
||||
actual = '\n'.join(lst)
|
||||
expected = fixtures.nemo_dump_no_xml
|
||||
self.assertEqual(actual, expected)
|
||||
|
||||
def test_printoptions_short(self):
|
||||
"""Verify printed output when short=True"""
|
||||
glymur.set_printoptions(short=True)
|
||||
with patch('sys.stdout', new=StringIO()) as fake_out:
|
||||
glymur.jp2dump(self.jp2file)
|
||||
actual = fake_out.getvalue().strip()
|
||||
|
||||
# Get rid of the filename line, as it is not set in stone.
|
||||
lst = actual.split('\n')
|
||||
lst = lst[1:]
|
||||
actual = '\n'.join(lst)
|
||||
self.assertEqual(actual, fixtures.nemo_dump_short)
|
||||
|
||||
def test_asoc_label_box(self):
|
||||
"""verify printing of asoc, label boxes"""
|
||||
# Construct a fake file with an asoc and a label box, as
|
||||
|
|
@ -228,32 +159,6 @@ class TestPrinting(unittest.TestCase):
|
|||
expected = '\n'.join(lines)
|
||||
self.assertEqual(actual, expected)
|
||||
|
||||
def test_jp2dump(self):
|
||||
"""basic jp2dump test"""
|
||||
with patch('sys.stdout', new=StringIO()) as fake_out:
|
||||
glymur.jp2dump(self.jp2file)
|
||||
actual = fake_out.getvalue().strip()
|
||||
|
||||
# Get rid of the filename line, as it is not set in stone.
|
||||
lst = actual.split('\n')
|
||||
lst = lst[1:]
|
||||
actual = '\n'.join(lst)
|
||||
self.assertEqual(actual, fixtures.nemo_dump_full)
|
||||
|
||||
def test_entire_file(self):
|
||||
"""verify output from printing entire file"""
|
||||
j = glymur.Jp2k(self.jp2file)
|
||||
with patch('sys.stdout', new=StringIO()) as fake_out:
|
||||
print(j)
|
||||
actual = fake_out.getvalue().strip()
|
||||
|
||||
# Get rid of the filename line, as it is not set in stone.
|
||||
lst = actual.split('\n')
|
||||
lst = lst[1:]
|
||||
actual = '\n'.join(lst)
|
||||
|
||||
self.assertEqual(actual, fixtures.nemo_dump_full)
|
||||
|
||||
def test_coc_segment(self):
|
||||
"""verify printing of COC segment"""
|
||||
j = glymur.Jp2k(self.jp2file)
|
||||
|
|
@ -739,48 +644,6 @@ class TestPrintingOpjDataRoot(unittest.TestCase):
|
|||
actual = fake_out.getvalue().strip()
|
||||
self.assertEqual(actual, fixtures.cinema2k_profile)
|
||||
|
||||
def test_invalid_colorspace(self):
|
||||
"""An invalid colorspace shouldn't cause an error."""
|
||||
filename = opj_data_file('input/nonregression/edf_c2_1103421.jp2')
|
||||
with warnings.catch_warnings():
|
||||
# Bad compatibility list item and bad colorspace warnings. Just
|
||||
# suppress the warnings.
|
||||
warnings.simplefilter("ignore")
|
||||
jp2 = Jp2k(filename)
|
||||
with patch('sys.stdout', new=StringIO()) as fake_out:
|
||||
print(jp2)
|
||||
|
||||
def test_bad_rsiz(self):
|
||||
"""Should still be able to print if rsiz is bad, issue196"""
|
||||
filename = opj_data_file('input/nonregression/edf_c2_1002767.jp2')
|
||||
with warnings.catch_warnings():
|
||||
warnings.simplefilter("ignore")
|
||||
j = Jp2k(filename)
|
||||
with patch('sys.stdout', new=StringIO()) as fake_out:
|
||||
print(j)
|
||||
|
||||
def test_bad_wavelet_transform(self):
|
||||
"""Should still be able to print if wavelet xform is bad, issue195"""
|
||||
filename = opj_data_file('input/nonregression/edf_c2_10025.jp2')
|
||||
with warnings.catch_warnings():
|
||||
warnings.simplefilter("ignore")
|
||||
jp2 = Jp2k(filename)
|
||||
with patch('sys.stdout', new=StringIO()) as fake_out:
|
||||
print(jp2)
|
||||
|
||||
def test_invalid_progression_order(self):
|
||||
"""Should still be able to print even if prog order is invalid."""
|
||||
jfile = opj_data_file('input/nonregression/2977.pdf.asan.67.2198.jp2')
|
||||
with warnings.catch_warnings():
|
||||
# Multiple warnings, actually.
|
||||
warnings.simplefilter("ignore")
|
||||
jp2 = Jp2k(jfile)
|
||||
codestream = jp2.get_codestream()
|
||||
with patch('sys.stdout', new=StringIO()) as fake_out:
|
||||
print(codestream.segment[2])
|
||||
actual = fake_out.getvalue().strip()
|
||||
self.assertEqual(actual, fixtures.issue_186_progression_order)
|
||||
|
||||
def test_crg(self):
|
||||
"""verify printing of CRG segment"""
|
||||
filename = opj_data_file('input/conformance/p0_03.j2k')
|
||||
|
|
@ -930,46 +793,6 @@ class TestPrintingOpjDataRoot(unittest.TestCase):
|
|||
expected = '\n'.join(lines)
|
||||
self.assertEqual(actual, expected)
|
||||
|
||||
def test_xml(self):
|
||||
"""verify printing of XML box"""
|
||||
filename = opj_data_file('input/conformance/file1.jp2')
|
||||
j = glymur.Jp2k(filename)
|
||||
with patch('sys.stdout', new=StringIO()) as fake_out:
|
||||
print(j.box[2])
|
||||
actual = fake_out.getvalue().strip()
|
||||
self.assertEqual(actual, fixtures.file1_xml)
|
||||
|
||||
def test_channel_definition(self):
|
||||
"""verify printing of cdef box"""
|
||||
filename = opj_data_file('input/conformance/file2.jp2')
|
||||
with warnings.catch_warnings():
|
||||
# Bad compatibility list item.
|
||||
warnings.simplefilter("ignore")
|
||||
j = glymur.Jp2k(filename)
|
||||
with patch('sys.stdout', new=StringIO()) as fake_out:
|
||||
print(j.box[2].box[2])
|
||||
actual = fake_out.getvalue().strip()
|
||||
lines = ['Channel Definition Box (cdef) @ (81, 28)',
|
||||
' Channel 0 (color) ==> (3)',
|
||||
' Channel 1 (color) ==> (2)',
|
||||
' Channel 2 (color) ==> (1)']
|
||||
expected = '\n'.join(lines)
|
||||
self.assertEqual(actual, expected)
|
||||
|
||||
def test_component_mapping(self):
|
||||
"""verify printing of cmap box"""
|
||||
filename = opj_data_file('input/conformance/file9.jp2')
|
||||
j = glymur.Jp2k(filename)
|
||||
with patch('sys.stdout', new=StringIO()) as fake_out:
|
||||
print(j.box[2].box[2])
|
||||
actual = fake_out.getvalue().strip()
|
||||
lines = ['Component Mapping Box (cmap) @ (848, 20)',
|
||||
' Component 0 ==> palette column 0',
|
||||
' Component 0 ==> palette column 1',
|
||||
' Component 0 ==> palette column 2']
|
||||
expected = '\n'.join(lines)
|
||||
self.assertEqual(actual, expected)
|
||||
|
||||
def test_componentmapping_box_alpha(self):
|
||||
"""Verify __repr__ method on cmap box."""
|
||||
cmap = glymur.jp2box.ComponentMappingBox(component_index=(0, 0, 0),
|
||||
|
|
@ -981,27 +804,6 @@ class TestPrintingOpjDataRoot(unittest.TestCase):
|
|||
self.assertEqual(newbox.mapping_type, (1, 1, 1))
|
||||
self.assertEqual(newbox.palette_index, (0, 1, 2))
|
||||
|
||||
def test_palette7(self):
|
||||
"""verify printing of pclr box"""
|
||||
filename = opj_data_file('input/conformance/file9.jp2')
|
||||
j = glymur.Jp2k(filename)
|
||||
with patch('sys.stdout', new=StringIO()) as fake_out:
|
||||
print(j.box[2].box[1])
|
||||
actual = fake_out.getvalue().strip()
|
||||
lines = ['Palette Box (pclr) @ (66, 782)',
|
||||
' Size: (256 x 3)']
|
||||
expected = '\n'.join(lines)
|
||||
self.assertEqual(actual, expected)
|
||||
|
||||
def test_rreq(self):
|
||||
"""verify printing of reader requirements box"""
|
||||
filename = opj_data_file('input/nonregression/text_GBR.jp2')
|
||||
j = glymur.Jp2k(filename)
|
||||
with patch('sys.stdout', new=StringIO()) as fake_out:
|
||||
print(j.box[2])
|
||||
actual = fake_out.getvalue().strip()
|
||||
self.assertEqual(actual, fixtures.text_GBR_rreq)
|
||||
|
||||
def test_differing_subsamples(self):
|
||||
"""verify printing of SIZ with different subsampling... Issue 86."""
|
||||
filename = opj_data_file('input/conformance/p0_05.j2k')
|
||||
|
|
@ -1023,10 +825,133 @@ 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.")
|
||||
@unittest.skipIf(WARNING_INFRASTRUCTURE_ISSUE, WARNING_INFRASTRUCTURE_MSG)
|
||||
class TestPrintingOpjDataRootWarns(unittest.TestCase):
|
||||
"""
|
||||
Tests for verifying printing. restricted to OPJ_DATA_ROOT files.
|
||||
|
||||
These tests issue warnings.
|
||||
"""
|
||||
def setUp(self):
|
||||
self.jpxfile = glymur.data.jpxfile()
|
||||
self.jp2file = glymur.data.nemo()
|
||||
self.j2kfile = glymur.data.goodstuff()
|
||||
|
||||
# Reset printoptions for every test.
|
||||
glymur.set_printoptions(short=False, xml=True, codestream=True)
|
||||
|
||||
def tearDown(self):
|
||||
pass
|
||||
|
||||
def test_invalid_colorspace(self):
|
||||
"""An invalid colorspace shouldn't cause an error."""
|
||||
filename = opj_data_file('input/nonregression/edf_c2_1103421.jp2')
|
||||
with self.assertWarns(UserWarning):
|
||||
jp2 = Jp2k(filename)
|
||||
with patch('sys.stdout', new=StringIO()) as fake_out:
|
||||
print(jp2)
|
||||
|
||||
@unittest.skip("unexplained failure")
|
||||
def test_bad_rsiz(self):
|
||||
"""Should still be able to print if rsiz is bad, issue196"""
|
||||
filename = opj_data_file('input/nonregression/edf_c2_1002767.jp2')
|
||||
with self.assertWarns(UserWarning):
|
||||
j = Jp2k(filename)
|
||||
with patch('sys.stdout', new=StringIO()) as fake_out:
|
||||
print(j)
|
||||
|
||||
def test_bad_wavelet_transform(self):
|
||||
"""Should still be able to print if wavelet xform is bad, issue195"""
|
||||
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:
|
||||
print(jp2)
|
||||
|
||||
def test_invalid_progression_order(self):
|
||||
"""Should still be able to print even if prog order is invalid."""
|
||||
jfile = opj_data_file('input/nonregression/2977.pdf.asan.67.2198.jp2')
|
||||
with self.assertWarns(UserWarning):
|
||||
# Multiple warnings, actually.
|
||||
jp2 = Jp2k(jfile)
|
||||
codestream = jp2.get_codestream()
|
||||
with patch('sys.stdout', new=StringIO()) as fake_out:
|
||||
print(codestream.segment[2])
|
||||
actual = fake_out.getvalue().strip()
|
||||
self.assertEqual(actual, fixtures.issue_186_progression_order)
|
||||
|
||||
def test_xml(self):
|
||||
"""verify printing of XML box"""
|
||||
filename = opj_data_file('input/conformance/file1.jp2')
|
||||
with self.assertWarns(UserWarning):
|
||||
j = glymur.Jp2k(filename)
|
||||
with patch('sys.stdout', new=StringIO()) as fake_out:
|
||||
print(j.box[2])
|
||||
actual = fake_out.getvalue().strip()
|
||||
self.assertEqual(actual, fixtures.file1_xml)
|
||||
|
||||
def test_channel_definition(self):
|
||||
"""verify printing of cdef box"""
|
||||
filename = opj_data_file('input/conformance/file2.jp2')
|
||||
with self.assertWarns(UserWarning):
|
||||
# Bad compatibility list item.
|
||||
j = glymur.Jp2k(filename)
|
||||
with patch('sys.stdout', new=StringIO()) as fake_out:
|
||||
print(j.box[2].box[2])
|
||||
actual = fake_out.getvalue().strip()
|
||||
lines = ['Channel Definition Box (cdef) @ (81, 28)',
|
||||
' Channel 0 (color) ==> (3)',
|
||||
' Channel 1 (color) ==> (2)',
|
||||
' Channel 2 (color) ==> (1)']
|
||||
expected = '\n'.join(lines)
|
||||
self.assertEqual(actual, expected)
|
||||
|
||||
def test_component_mapping(self):
|
||||
"""verify printing of cmap box"""
|
||||
filename = opj_data_file('input/conformance/file9.jp2')
|
||||
with self.assertWarns(UserWarning):
|
||||
j = glymur.Jp2k(filename)
|
||||
with patch('sys.stdout', new=StringIO()) as fake_out:
|
||||
print(j.box[2].box[2])
|
||||
actual = fake_out.getvalue().strip()
|
||||
lines = ['Component Mapping Box (cmap) @ (848, 20)',
|
||||
' Component 0 ==> palette column 0',
|
||||
' Component 0 ==> palette column 1',
|
||||
' Component 0 ==> palette column 2']
|
||||
expected = '\n'.join(lines)
|
||||
self.assertEqual(actual, expected)
|
||||
|
||||
def test_palette7(self):
|
||||
"""verify printing of pclr box"""
|
||||
filename = opj_data_file('input/conformance/file9.jp2')
|
||||
with self.assertWarns(UserWarning):
|
||||
j = glymur.Jp2k(filename)
|
||||
with patch('sys.stdout', new=StringIO()) as fake_out:
|
||||
print(j.box[2].box[1])
|
||||
actual = fake_out.getvalue().strip()
|
||||
lines = ['Palette Box (pclr) @ (66, 782)',
|
||||
' Size: (256 x 3)']
|
||||
expected = '\n'.join(lines)
|
||||
self.assertEqual(actual, expected)
|
||||
|
||||
def test_rreq(self):
|
||||
"""verify printing of reader requirements box"""
|
||||
filename = opj_data_file('input/nonregression/text_GBR.jp2')
|
||||
with self.assertWarns(UserWarning):
|
||||
j = glymur.Jp2k(filename)
|
||||
with patch('sys.stdout', new=StringIO()) as fake_out:
|
||||
print(j.box[2])
|
||||
actual = fake_out.getvalue().strip()
|
||||
self.assertEqual(actual, fixtures.text_GBR_rreq)
|
||||
|
||||
def test_palette_box(self):
|
||||
"""Verify that palette (pclr) boxes are printed without error."""
|
||||
filename = opj_data_file('input/conformance/file9.jp2')
|
||||
j = glymur.Jp2k(filename)
|
||||
with self.assertWarns(UserWarning):
|
||||
j = glymur.Jp2k(filename)
|
||||
with patch('sys.stdout', new=StringIO()) as fake_out:
|
||||
print(j.box[2].box[1])
|
||||
actual = fake_out.getvalue().strip()
|
||||
|
|
@ -1040,9 +965,8 @@ class TestPrintingOpjDataRoot(unittest.TestCase):
|
|||
# ICC profiles may be used in JP2, but the approximation field should
|
||||
# be zero unless we have jpx. This file does both.
|
||||
filename = opj_data_file('input/nonregression/text_GBR.jp2')
|
||||
with warnings.catch_warnings():
|
||||
with self.assertWarns(UserWarning):
|
||||
# brand is 'jp2 ', but has any icc profile.
|
||||
warnings.simplefilter("ignore")
|
||||
jp2 = Jp2k(filename)
|
||||
|
||||
with patch('sys.stdout', new=StringIO()) as fake_out:
|
||||
|
|
@ -1060,7 +984,8 @@ class TestPrintingOpjDataRoot(unittest.TestCase):
|
|||
def test_uuid(self):
|
||||
"""verify printing of UUID box"""
|
||||
filename = opj_data_file('input/nonregression/text_GBR.jp2')
|
||||
jp2 = Jp2k(filename)
|
||||
with self.assertWarns(UserWarning):
|
||||
jp2 = Jp2k(filename)
|
||||
|
||||
with patch('sys.stdout', new=StringIO()) as fake_out:
|
||||
print(jp2.box[4])
|
||||
|
|
@ -1078,9 +1003,8 @@ class TestPrintingOpjDataRoot(unittest.TestCase):
|
|||
# Format strings like %d were showing up in the output.
|
||||
filename = opj_data_file('input/nonregression/mem-b2ace68c-1381.jp2')
|
||||
|
||||
with warnings.catch_warnings():
|
||||
with self.assertWarns(UserWarning):
|
||||
# Ignore warning about bad pclr box.
|
||||
warnings.simplefilter("ignore")
|
||||
jp2 = Jp2k(filename)
|
||||
with patch('sys.stdout', new=StringIO()) as fake_out:
|
||||
print(jp2.box[3].box[3])
|
||||
|
|
@ -1090,9 +1014,8 @@ class TestPrintingOpjDataRoot(unittest.TestCase):
|
|||
def test_issue183(self):
|
||||
filename = opj_data_file('input/nonregression/orb-blue10-lin-jp2.jp2')
|
||||
|
||||
with warnings.catch_warnings():
|
||||
with self.assertWarns(UserWarning):
|
||||
# Ignore warning about bad pclr box.
|
||||
warnings.simplefilter("ignore")
|
||||
jp2 = Jp2k(filename)
|
||||
with patch('sys.stdout', new=StringIO()) as fake_out:
|
||||
print(jp2.box[2].box[1])
|
||||
|
|
@ -1104,8 +1027,7 @@ class TestPrintingOpjDataRoot(unittest.TestCase):
|
|||
filename = opj_data_file(os.path.join('input',
|
||||
'nonregression',
|
||||
'issue171.jp2'))
|
||||
with warnings.catch_warnings():
|
||||
warnings.simplefilter("ignore")
|
||||
with self.assertWarns(UserWarning):
|
||||
jp2 = Jp2k(filename)
|
||||
with patch('sys.stdout', new=StringIO()) as fake_out:
|
||||
# No need to verify, it's enough that we don't error out.
|
||||
|
|
@ -1113,5 +1035,71 @@ class TestPrintingOpjDataRoot(unittest.TestCase):
|
|||
|
||||
self.assertTrue(True)
|
||||
|
||||
if __name__ == "__main__":
|
||||
unittest.main()
|
||||
|
||||
class TestJp2dump(unittest.TestCase):
|
||||
"""Tests for verifying how jp2dump console script works."""
|
||||
def setUp(self):
|
||||
self.jpxfile = glymur.data.jpxfile()
|
||||
self.jp2file = glymur.data.nemo()
|
||||
self.j2kfile = glymur.data.goodstuff()
|
||||
|
||||
# Reset printoptions for every test.
|
||||
glymur.set_printoptions(short=False, xml=True, codestream=True)
|
||||
|
||||
def tearDown(self):
|
||||
pass
|
||||
|
||||
def run_jp2dump(self, args):
|
||||
sys.argv = args
|
||||
with patch('sys.stdout', new=StringIO()) as fake_out:
|
||||
command_line.main()
|
||||
actual = fake_out.getvalue().strip()
|
||||
# Remove the file line, as that is filesystem-dependent.
|
||||
lines = actual.split('\n')
|
||||
actual = '\n'.join(lines[1:])
|
||||
return actual
|
||||
|
||||
def test_default_nemo(self):
|
||||
"""Should be able to dump a JP2 file's metadata with no codestream."""
|
||||
actual = self.run_jp2dump(['', self.jp2file])
|
||||
|
||||
self.assertEqual(actual, fixtures.nemo_dump_no_codestream)
|
||||
|
||||
def test_codestream_0(self):
|
||||
"""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)
|
||||
|
||||
def test_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)
|
||||
|
||||
def test_codestream_2(self):
|
||||
"""Verify dumping with -c 2, full details."""
|
||||
with patch('sys.stdout', new=StringIO()) as fake_out:
|
||||
sys.argv = ['', '-c', '2', self.j2kfile]
|
||||
command_line.main()
|
||||
actual = fake_out.getvalue().strip()
|
||||
|
||||
self.assertIn(fixtures.goodstuff_with_full_header, actual)
|
||||
|
||||
def test_codestream_invalid(self):
|
||||
"""Verify dumping with -c 3, not allowd."""
|
||||
with self.assertRaises(ValueError):
|
||||
sys.argv = ['', '-c', '3', self.jp2file]
|
||||
command_line.main()
|
||||
|
||||
def test_short(self):
|
||||
"""Verify dumping with -s, short option."""
|
||||
actual = self.run_jp2dump(['', '-s', self.jp2file])
|
||||
|
||||
self.assertEqual(actual, fixtures.nemo_dump_short)
|
||||
|
||||
def test_suppress_xml(self):
|
||||
"""Verify dumping with -x, suppress XML."""
|
||||
actual = self.run_jp2dump(['', '-x', self.jp2file])
|
||||
|
||||
self.assertEqual(actual, fixtures.nemo_dump_no_codestream_no_xml)
|
||||
|
|
|
|||
4
setup.py
4
setup.py
|
|
@ -12,7 +12,9 @@ kwargs = {'name': 'glymur',
|
|||
'packages': ['glymur', 'glymur.data', 'glymur.test', 'glymur.lib',
|
||||
'glymur.lib.test'],
|
||||
'package_data': {'glymur': ['data/*.jp2', 'data/*.j2k', 'data/*.jpx']},
|
||||
'scripts': ['bin/jp2dump'],
|
||||
'entry_points': {
|
||||
'console_scripts': ['jp2dump=glymur.command_line:main'],
|
||||
},
|
||||
'license': 'MIT',
|
||||
'test_suite': 'glymur.test'}
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue