Merge branch 'devel' into issue139
This commit is contained in:
commit
569476c688
16 changed files with 676 additions and 617 deletions
|
|
@ -11,8 +11,8 @@ before_install:
|
||||||
|
|
||||||
# command to install dependencies
|
# command to install dependencies
|
||||||
install:
|
install:
|
||||||
- if [[ $TRAVIS_PYTHON_VERSION == '2.7' ]]; then pip install --use-mirrors lxml contextlib2 mock; fi
|
- if [[ $TRAVIS_PYTHON_VERSION == '2.7' ]]; then pip install lxml contextlib2 mock; fi
|
||||||
- if [[ $TRAVIS_PYTHON_VERSION == '3.3' ]]; then pip install --use-mirrors lxml numpy; fi
|
- if [[ $TRAVIS_PYTHON_VERSION == '3.3' ]]; then pip install lxml numpy; fi
|
||||||
|
|
||||||
# command to run tests
|
# command to run tests
|
||||||
script:
|
script:
|
||||||
|
|
|
||||||
|
|
@ -9,6 +9,7 @@ ChangeLog
|
||||||
* Added lxml requirement.
|
* Added lxml requirement.
|
||||||
* added set_printoptions, get_printoptions function
|
* added set_printoptions, get_printoptions function
|
||||||
* dropped support for Python 2.6, added support for Python 3.4
|
* dropped support for Python 2.6, added support for Python 3.4
|
||||||
|
* dropped support for OpenJPEG versions 1.3 and 1.4
|
||||||
* dropped windows support (it might work, it might not, I don't much care)
|
* dropped windows support (it might work, it might not, I don't much care)
|
||||||
* added write support for JP2 UUID, dataEntryURL, palette, and component mapping boxes
|
* added write support for JP2 UUID, dataEntryURL, palette, and component mapping boxes
|
||||||
* added read/write support for JPX free, number list, and data reference boxes
|
* added read/write support for JPX free, number list, and data reference boxes
|
||||||
|
|
|
||||||
|
|
@ -14,17 +14,7 @@ XMP UUIDs. There is some very limited support for reading JPX metadata.
|
||||||
Glymur 0.6 works on Python versions 2.7, 3.3 and 3.4. If you have Python 2.6,
|
Glymur 0.6 works on Python versions 2.7, 3.3 and 3.4. If you have Python 2.6,
|
||||||
you should use the 0.5 series of Glymur.
|
you should use the 0.5 series of Glymur.
|
||||||
|
|
||||||
OpenJPEG Installation
|
For more information about OpenJPEG, please consult http://www.openjpeg.org.
|
||||||
=====================
|
|
||||||
Glymur will read JPEG 2000 images with versions 1.3, 1.4, 1.5, 2.0,
|
|
||||||
and the trunk/development version of OpenJPEG. Writing images is
|
|
||||||
only supported with the 1.5 or better, however, and the trunk/development
|
|
||||||
version of OpenJPEG is strongly recommended. For more information about
|
|
||||||
OpenJPEG, please consult http://www.openjpeg.org.
|
|
||||||
|
|
||||||
If you use MacPorts or if you have a sufficiently recent version of
|
|
||||||
Linux, your package manager should already provide you with a version of
|
|
||||||
OpenJPEG 1.X which glymur can already use.
|
|
||||||
|
|
||||||
Glymur Installation
|
Glymur Installation
|
||||||
===================
|
===================
|
||||||
|
|
|
||||||
|
|
@ -17,6 +17,7 @@ codestreams.
|
||||||
# the base Segment class.
|
# the base Segment class.
|
||||||
# pylint: disable=R0903
|
# pylint: disable=R0903
|
||||||
|
|
||||||
|
import collections
|
||||||
import math
|
import math
|
||||||
import struct
|
import struct
|
||||||
import sys
|
import sys
|
||||||
|
|
@ -30,12 +31,26 @@ from .core import WAVELET_XFORM_5X3_REVERSIBLE
|
||||||
from .core import _CAPABILITIES_DISPLAY
|
from .core import _CAPABILITIES_DISPLAY
|
||||||
from .lib import openjp2 as opj2
|
from .lib import openjp2 as opj2
|
||||||
|
|
||||||
_PROGRESSION_ORDER_DISPLAY = {
|
class _keydefaultdict(collections.defaultdict):
|
||||||
LRCP: 'LRCP',
|
"""Unlisted keys help form their own error message.
|
||||||
|
|
||||||
|
Normally defaultdict uses a factory function with no input arguments, but
|
||||||
|
that's not quite the behavior we want.
|
||||||
|
"""
|
||||||
|
def __missing__(self, key):
|
||||||
|
if self.default_factory is None:
|
||||||
|
raise KeyError(key)
|
||||||
|
else:
|
||||||
|
ret = self[key] = self.default_factory(key)
|
||||||
|
return ret
|
||||||
|
|
||||||
|
_factory = lambda x: '{0} (invalid)'.format(x)
|
||||||
|
_PROGRESSION_ORDER_DISPLAY = _keydefaultdict(_factory,
|
||||||
|
{ LRCP: 'LRCP',
|
||||||
RLCP: 'RLCP',
|
RLCP: 'RLCP',
|
||||||
RPCL: 'RPCL',
|
RPCL: 'RPCL',
|
||||||
PCRL: 'PCRL',
|
PCRL: 'PCRL',
|
||||||
CPRL: 'CPRL'}
|
CPRL: 'CPRL'})
|
||||||
|
|
||||||
_WAVELET_TRANSFORM_DISPLAY = {
|
_WAVELET_TRANSFORM_DISPLAY = {
|
||||||
WAVELET_XFORM_9X7_IRREVERSIBLE: '9-7 irreversible',
|
WAVELET_XFORM_9X7_IRREVERSIBLE: '9-7 irreversible',
|
||||||
|
|
@ -371,6 +386,9 @@ class Codestream(object):
|
||||||
numbytes = offset + 2 + length - fptr.tell()
|
numbytes = offset + 2 + length - fptr.tell()
|
||||||
spcod = fptr.read(numbytes)
|
spcod = fptr.read(numbytes)
|
||||||
spcod = np.frombuffer(spcod, dtype=np.uint8)
|
spcod = np.frombuffer(spcod, dtype=np.uint8)
|
||||||
|
if spcod[0] not in [LRCP, RLCP, RPCL, PCRL, CPRL]:
|
||||||
|
msg = "Invalid progression order in COD segment: {0}."
|
||||||
|
warnings.warn(msg.format(spcod[0]))
|
||||||
|
|
||||||
sop = (scod & 2) > 0
|
sop = (scod & 2) > 0
|
||||||
eph = (scod & 4) > 0
|
eph = (scod & 4) > 0
|
||||||
|
|
@ -673,6 +691,18 @@ class Codestream(object):
|
||||||
msg = msg.format(j, subsampling[0], subsampling[1])
|
msg = msg.format(j, subsampling[0], subsampling[1])
|
||||||
warnings.warn(msg)
|
warnings.warn(msg)
|
||||||
|
|
||||||
|
try:
|
||||||
|
num_tiles_x = (xysiz[0] - xyosiz[0]) / (xytsiz[0] - xytosiz[0])
|
||||||
|
num_tiles_y = (xysiz[1] - xyosiz[1]) / (xytsiz[1] - xytosiz[1])
|
||||||
|
except ZeroDivisionError as err:
|
||||||
|
warnings.warn("Invalid tile dimensions.")
|
||||||
|
else:
|
||||||
|
numtiles = math.ceil(num_tiles_x) * math.ceil(num_tiles_y)
|
||||||
|
if numtiles > 65535:
|
||||||
|
msg = "Invalid number of tiles ({0}).".format(numtiles)
|
||||||
|
warnings.warn(msg)
|
||||||
|
|
||||||
|
|
||||||
kwargs = {'rsiz': rsiz,
|
kwargs = {'rsiz': rsiz,
|
||||||
'xysiz': xysiz,
|
'xysiz': xysiz,
|
||||||
'xyosiz': xyosiz,
|
'xyosiz': xyosiz,
|
||||||
|
|
@ -1514,14 +1544,6 @@ class SIZsegment(Segment):
|
||||||
lst.append(bitdepth - 1)
|
lst.append(bitdepth - 1)
|
||||||
self.ssiz = tuple(lst)
|
self.ssiz = tuple(lst)
|
||||||
|
|
||||||
num_tiles_x = (self.xsiz - self.xosiz) / (self.xtsiz - self.xtosiz)
|
|
||||||
num_tiles_y = (self.ysiz - self.yosiz) / (self.ytsiz - self.ytosiz)
|
|
||||||
numtiles = math.ceil(num_tiles_x) * math.ceil(num_tiles_y)
|
|
||||||
if numtiles > 65535:
|
|
||||||
msg = "Invalid number of tiles ({0}).".format(numtiles)
|
|
||||||
warnings.warn(msg)
|
|
||||||
|
|
||||||
|
|
||||||
def __repr__(self):
|
def __repr__(self):
|
||||||
msg = "glymur.codestream.SIZsegment(rsiz={rsiz}, xysiz={xysiz}, "
|
msg = "glymur.codestream.SIZsegment(rsiz={rsiz}, xysiz={xysiz}, "
|
||||||
msg += "xyosiz={xyosiz}, xytsiz={xytsiz}, xytosiz={xytosiz}, "
|
msg += "xyosiz={xyosiz}, xytsiz={xytsiz}, xytosiz={xytosiz}, "
|
||||||
|
|
|
||||||
|
|
@ -220,7 +220,13 @@ class Jp2kBox(object):
|
||||||
break
|
break
|
||||||
|
|
||||||
read_buffer = fptr.read(8)
|
read_buffer = fptr.read(8)
|
||||||
|
try:
|
||||||
(box_length, box_id) = struct.unpack('>I4s', read_buffer)
|
(box_length, box_id) = struct.unpack('>I4s', read_buffer)
|
||||||
|
except Exception as err:
|
||||||
|
msg = "Extra bytes at end of file ignored."
|
||||||
|
warnings.warn(msg)
|
||||||
|
return superbox
|
||||||
|
|
||||||
if sys.hexversion >= 0x03000000:
|
if sys.hexversion >= 0x03000000:
|
||||||
box_id = box_id.decode('utf-8')
|
box_id = box_id.decode('utf-8')
|
||||||
|
|
||||||
|
|
@ -359,6 +365,9 @@ class ColourSpecificationBox(Jp2kBox):
|
||||||
else:
|
else:
|
||||||
# 2.7 has trouble pretty-printing ordered dicts so we just have
|
# 2.7 has trouble pretty-printing ordered dicts so we just have
|
||||||
# to print as a regular dict in this case.
|
# to print as a regular dict in this case.
|
||||||
|
if self.icc_profile is None:
|
||||||
|
msg += '\n ICC Profile: None'
|
||||||
|
else:
|
||||||
if sys.hexversion < 0x03000000:
|
if sys.hexversion < 0x03000000:
|
||||||
icc_profile = dict(self.icc_profile)
|
icc_profile = dict(self.icc_profile)
|
||||||
else:
|
else:
|
||||||
|
|
@ -829,7 +838,7 @@ class ComponentMappingBox(Jp2kBox):
|
||||||
msg = msg.format(self.component_index[k],
|
msg = msg.format(self.component_index[k],
|
||||||
self.palette_index[k])
|
self.palette_index[k])
|
||||||
else:
|
else:
|
||||||
msg += '\n Component %d ==> %d'
|
msg += '\n Component {0} ==> {1}'
|
||||||
msg = msg.format(self.component_index[k], k)
|
msg = msg.format(self.component_index[k], k)
|
||||||
return msg
|
return msg
|
||||||
|
|
||||||
|
|
@ -2628,26 +2637,39 @@ class XMLBox(Jp2kBox):
|
||||||
read_buffer = fptr.read(num_bytes)
|
read_buffer = fptr.read(num_bytes)
|
||||||
try:
|
try:
|
||||||
text = read_buffer.decode('utf-8')
|
text = read_buffer.decode('utf-8')
|
||||||
except UnicodeDecodeError as ude:
|
except UnicodeDecodeError as err:
|
||||||
# Possibly bad string of bytes to begin with.
|
# Possibly bad string of bytes to begin with.
|
||||||
# Try to search for <?xml and go from there.
|
# Try to search for <?xml and go from there.
|
||||||
decl_start = read_buffer.find(b'<?xml')
|
decl_start = read_buffer.find(b'<?xml')
|
||||||
if decl_start > -1:
|
if decl_start <= -1:
|
||||||
|
msg = 'A problem was encountered while parsing an XML box:'
|
||||||
|
msg += '\n\n\t"{0}"\n\nNo XML was retrieved.'
|
||||||
|
warnings.warn(msg.format(str(err)))
|
||||||
|
return XMLBox(xml=None, length=length, offset=offset)
|
||||||
|
|
||||||
text = read_buffer[decl_start:].decode('utf-8')
|
text = read_buffer[decl_start:].decode('utf-8')
|
||||||
else:
|
|
||||||
raise
|
|
||||||
|
|
||||||
# Let the user know that the XML box was problematic.
|
# Let the user know that the XML box was problematic.
|
||||||
msg = 'A UnicodeDecodeError was encountered parsing an XML box at '
|
msg = 'A UnicodeDecodeError was encountered parsing an XML box at '
|
||||||
msg += 'byte position {0} ({1}), but the XML was still recovered.'
|
msg += 'byte position {0} ({1}), but the XML was still recovered.'
|
||||||
msg = msg.format(offset, ude.reason)
|
msg = msg.format(offset, err.reason)
|
||||||
warnings.warn(msg, UserWarning)
|
warnings.warn(msg, UserWarning)
|
||||||
|
|
||||||
# Strip out any trailing nulls, as they can foul up XML parsing.
|
# Strip out any trailing nulls, as they can foul up XML parsing.
|
||||||
|
# Remove any byte order markers.
|
||||||
text = text.rstrip(chr(0))
|
text = text.rstrip(chr(0))
|
||||||
|
if u'\ufeff' in text:
|
||||||
|
msg = 'An illegal BOM (byte order marker) was detected and '
|
||||||
|
msg += 'removed from the XML contents in the box starting at byte '
|
||||||
|
msg += 'offset {0}'.format(offset)
|
||||||
|
warnings.warn(msg)
|
||||||
|
text = text.replace(u'\ufeff', '')
|
||||||
|
# Remove any encoding declaration.
|
||||||
|
if text.startswith('<?xml version="1.0" encoding="UTF-8"?>'):
|
||||||
|
text = text[38:]
|
||||||
|
|
||||||
try:
|
try:
|
||||||
elt = ET.fromstring(text.encode('utf-8'))
|
elt = ET.fromstring(text)
|
||||||
xml = ET.ElementTree(elt)
|
xml = ET.ElementTree(elt)
|
||||||
except ET.ParseError as err:
|
except ET.ParseError as err:
|
||||||
msg = 'A problem was encountered while parsing an XML box:'
|
msg = 'A problem was encountered while parsing an XML box:'
|
||||||
|
|
|
||||||
|
|
@ -695,6 +695,8 @@ class Jp2k(Jp2kBox):
|
||||||
(first_row, first_col, last_row, last_col)
|
(first_row, first_col, last_row, last_col)
|
||||||
tile : int, optional
|
tile : int, optional
|
||||||
Number of tile to decode.
|
Number of tile to decode.
|
||||||
|
no_cxform : bool
|
||||||
|
Whether or not to apply intended color transforms.
|
||||||
verbose : bool, optional
|
verbose : bool, optional
|
||||||
Print informational messages produced by the OpenJPEG library.
|
Print informational messages produced by the OpenJPEG library.
|
||||||
|
|
||||||
|
|
@ -749,7 +751,7 @@ class Jp2k(Jp2kBox):
|
||||||
msg += "the read_bands method instead."
|
msg += "the read_bands method instead."
|
||||||
raise RuntimeError(msg)
|
raise RuntimeError(msg)
|
||||||
|
|
||||||
def _read_openjpeg(self, rlevel=0, verbose=False):
|
def _read_openjpeg(self, rlevel=0, no_cxform=False, verbose=False):
|
||||||
"""Read a JPEG 2000 image using libopenjpeg.
|
"""Read a JPEG 2000 image using libopenjpeg.
|
||||||
|
|
||||||
Parameters
|
Parameters
|
||||||
|
|
@ -757,6 +759,8 @@ class Jp2k(Jp2kBox):
|
||||||
rlevel : int, optional
|
rlevel : int, optional
|
||||||
Factor by which to rlevel output resolution. Use -1 to get the
|
Factor by which to rlevel output resolution. Use -1 to get the
|
||||||
lowest resolution thumbnail.
|
lowest resolution thumbnail.
|
||||||
|
no_cxform : bool
|
||||||
|
Whether or not to apply intended color transforms.
|
||||||
verbose : bool, optional
|
verbose : bool, optional
|
||||||
Print informational messages produced by the OpenJPEG library.
|
Print informational messages produced by the OpenJPEG library.
|
||||||
|
|
||||||
|
|
@ -772,15 +776,15 @@ class Jp2k(Jp2kBox):
|
||||||
"""
|
"""
|
||||||
self._subsampling_sanity_check()
|
self._subsampling_sanity_check()
|
||||||
|
|
||||||
|
# Must check the specified rlevel against the maximum.
|
||||||
if rlevel != 0:
|
if rlevel != 0:
|
||||||
# Must check the specified rlevel against the maximum.
|
# Must check the specified rlevel against the maximum.
|
||||||
# OpenJPEG 1.3 will segfault if rlevel is too high.
|
|
||||||
codestream = self.get_codestream()
|
codestream = self.get_codestream()
|
||||||
max_rlevel = codestream.segment[2].spcod[4]
|
max_rlevel = codestream.segment[2].spcod[4]
|
||||||
if rlevel == -1:
|
if rlevel == -1:
|
||||||
# -1 is shorthand for the largest rlevel
|
# -1 is shorthand for the largest rlevel
|
||||||
rlevel = max_rlevel
|
rlevel = max_rlevel
|
||||||
if rlevel < -1 or rlevel > max_rlevel:
|
elif rlevel < -1 or rlevel > max_rlevel:
|
||||||
msg = "rlevel must be in the range [-1, {0}] for this image."
|
msg = "rlevel must be in the range [-1, {0}] for this image."
|
||||||
msg = msg.format(max_rlevel)
|
msg = msg.format(max_rlevel)
|
||||||
raise IOError(msg)
|
raise IOError(msg)
|
||||||
|
|
@ -788,8 +792,14 @@ class Jp2k(Jp2kBox):
|
||||||
with ExitStack() as stack:
|
with ExitStack() as stack:
|
||||||
try:
|
try:
|
||||||
# Set decoding parameters.
|
# Set decoding parameters.
|
||||||
|
# TODO: look to refactor, use _populate_dparam
|
||||||
dparameters = opj.DecompressionParametersType()
|
dparameters = opj.DecompressionParametersType()
|
||||||
opj.set_default_decoder_parameters(ctypes.byref(dparameters))
|
opj.set_default_decoder_parameters(ctypes.byref(dparameters))
|
||||||
|
|
||||||
|
if no_cxform is True:
|
||||||
|
# Return raw codestream components.
|
||||||
|
dparameters.flags |= 1
|
||||||
|
|
||||||
dparameters.cp_reduce = rlevel
|
dparameters.cp_reduce = rlevel
|
||||||
dparameters.decod_format = self._codec_format
|
dparameters.decod_format = self._codec_format
|
||||||
|
|
||||||
|
|
@ -834,7 +844,7 @@ class Jp2k(Jp2kBox):
|
||||||
return data
|
return data
|
||||||
|
|
||||||
def _read_openjp2(self, rlevel=0, layer=0, area=None, tile=None,
|
def _read_openjp2(self, rlevel=0, layer=0, area=None, tile=None,
|
||||||
verbose=False):
|
verbose=False, no_cxform=False):
|
||||||
"""Read a JPEG 2000 image using libopenjp2.
|
"""Read a JPEG 2000 image using libopenjp2.
|
||||||
|
|
||||||
Parameters
|
Parameters
|
||||||
|
|
@ -864,7 +874,7 @@ class Jp2k(Jp2kBox):
|
||||||
"""
|
"""
|
||||||
self._subsampling_sanity_check()
|
self._subsampling_sanity_check()
|
||||||
|
|
||||||
dparam = self._populate_dparam(layer, rlevel, area, tile)
|
dparam = self._populate_dparam(layer, rlevel, area, tile, no_cxform)
|
||||||
|
|
||||||
with ExitStack() as stack:
|
with ExitStack() as stack:
|
||||||
if hasattr(opj2.OPENJP2,
|
if hasattr(opj2.OPENJP2,
|
||||||
|
|
@ -908,20 +918,22 @@ class Jp2k(Jp2kBox):
|
||||||
|
|
||||||
return img_array
|
return img_array
|
||||||
|
|
||||||
def _populate_dparam(self, layer, rlevel, area, tile):
|
def _populate_dparam(self, layer, rlevel, area, tile, no_cxform):
|
||||||
"""Populate decompression structure with appropriate input parameters.
|
"""Populate decompression structure with appropriate input parameters.
|
||||||
|
|
||||||
Parameters
|
Parameters
|
||||||
----------
|
----------
|
||||||
layer : int, optional
|
layer : int
|
||||||
Number of quality layer to decode.
|
Number of quality layer to decode.
|
||||||
rlevel : int, optional
|
rlevel : int
|
||||||
Factor by which to rlevel output resolution.
|
Factor by which to rlevel output resolution.
|
||||||
area : tuple, optional
|
area : tuple
|
||||||
Specifies decoding image area,
|
Specifies decoding image area,
|
||||||
(first_row, first_col, last_row, last_col)
|
(first_row, first_col, last_row, last_col)
|
||||||
tile : int, optional
|
tile : int
|
||||||
Number of tile to decode.
|
Number of tile to decode.
|
||||||
|
no_cxform : bool
|
||||||
|
Whether or not to apply intended color transforms.
|
||||||
|
|
||||||
Returns
|
Returns
|
||||||
-------
|
-------
|
||||||
|
|
@ -959,10 +971,14 @@ class Jp2k(Jp2kBox):
|
||||||
dparam.tile_index = tile
|
dparam.tile_index = tile
|
||||||
dparam.nb_tile_to_decode = 1
|
dparam.nb_tile_to_decode = 1
|
||||||
|
|
||||||
|
if no_cxform is True:
|
||||||
|
# Return raw codestream components.
|
||||||
|
dparam.flags |= 1
|
||||||
|
|
||||||
return dparam
|
return dparam
|
||||||
|
|
||||||
def read_bands(self, rlevel=0, layer=0, area=None, tile=None,
|
def read_bands(self, rlevel=0, layer=0, area=None, tile=None,
|
||||||
verbose=False):
|
verbose=False, no_cxform=False):
|
||||||
"""Read a JPEG 2000 image.
|
"""Read a JPEG 2000 image.
|
||||||
|
|
||||||
The only time you should use this method is when the image has
|
The only time you should use this method is when the image has
|
||||||
|
|
@ -980,6 +996,8 @@ class Jp2k(Jp2kBox):
|
||||||
(first_row, first_col, last_row, last_col)
|
(first_row, first_col, last_row, last_col)
|
||||||
tile : int, optional
|
tile : int, optional
|
||||||
Number of tile to decode.
|
Number of tile to decode.
|
||||||
|
no_cxform : bool
|
||||||
|
Whether or not to apply intended color transforms.
|
||||||
verbose : bool, optional
|
verbose : bool, optional
|
||||||
Print informational messages produced by the OpenJPEG library.
|
Print informational messages produced by the OpenJPEG library.
|
||||||
|
|
||||||
|
|
@ -1009,7 +1027,7 @@ class Jp2k(Jp2kBox):
|
||||||
"of OpenJP2 installed before using "
|
"of OpenJP2 installed before using "
|
||||||
"this functionality.")
|
"this functionality.")
|
||||||
|
|
||||||
dparam = self._populate_dparam(layer, rlevel, area, tile)
|
dparam = self._populate_dparam(layer, rlevel, area, tile, no_cxform)
|
||||||
|
|
||||||
with ExitStack() as stack:
|
with ExitStack() as stack:
|
||||||
if hasattr(opj2.OPENJP2,
|
if hasattr(opj2.OPENJP2,
|
||||||
|
|
|
||||||
|
|
@ -395,7 +395,7 @@ class ImageCompType(ctypes.Structure):
|
||||||
|
|
||||||
# alpha channel
|
# alpha channel
|
||||||
# TODO: exclude for 2.0, 1.5
|
# TODO: exclude for 2.0, 1.5
|
||||||
("alpha", ctypes.POINTER(ctypes.c_uint16))]
|
("alpha", ctypes.c_uint16)]
|
||||||
|
|
||||||
|
|
||||||
class ImageType(ctypes.Structure):
|
class ImageType(ctypes.Structure):
|
||||||
|
|
|
||||||
|
|
@ -577,3 +577,36 @@ file1_xml = """XML Box (xml ) @ (36, 439)
|
||||||
\t\t<IMAGE_SOURCE>Professional 120 Image</IMAGE_SOURCE>
|
\t\t<IMAGE_SOURCE>Professional 120 Image</IMAGE_SOURCE>
|
||||||
\t</GENERAL_CREATION_INFO>
|
\t</GENERAL_CREATION_INFO>
|
||||||
</IMAGE_CREATION>"""
|
</IMAGE_CREATION>"""
|
||||||
|
|
||||||
|
issue_182_cmap = """Component Mapping Box (cmap) @ (130, 24)
|
||||||
|
Component 0 ==> palette column 0
|
||||||
|
Component 1 ==> palette column 0
|
||||||
|
Component 2 ==> 2"""
|
||||||
|
|
||||||
|
issue_183_colr = """Colour Specification Box (colr) @ (62, 12)
|
||||||
|
Method: restricted ICC profile
|
||||||
|
Precedence: 0
|
||||||
|
ICC Profile: None"""
|
||||||
|
|
||||||
|
|
||||||
|
# Progression order is invalid.
|
||||||
|
issue_186_progression_order = """COD marker segment @ (174, 12)
|
||||||
|
Coding style:
|
||||||
|
Entropy coder, without partitions
|
||||||
|
SOP marker segments: False
|
||||||
|
EPH marker segments: False
|
||||||
|
Coding style parameters:
|
||||||
|
Progression order: 33 (invalid)
|
||||||
|
Number of layers: 1
|
||||||
|
Multiple component transformation usage: reversible
|
||||||
|
Number of resolutions: 6
|
||||||
|
Code block height, width: (32 x 32)
|
||||||
|
Wavelet transform: 9-7 irreversible
|
||||||
|
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"""
|
||||||
|
|
|
||||||
|
|
@ -13,17 +13,12 @@ import struct
|
||||||
import sys
|
import sys
|
||||||
import tempfile
|
import tempfile
|
||||||
import unittest
|
import unittest
|
||||||
|
import warnings
|
||||||
|
|
||||||
from glymur import Jp2k
|
from glymur import Jp2k
|
||||||
import glymur
|
import glymur
|
||||||
|
|
||||||
try:
|
from .fixtures import opj_data_file, OPJ_DATA_ROOT
|
||||||
DATA_ROOT = os.environ['OPJ_DATA_ROOT']
|
|
||||||
except KeyError:
|
|
||||||
DATA_ROOT = None
|
|
||||||
except:
|
|
||||||
raise
|
|
||||||
|
|
||||||
|
|
||||||
class TestCodestream(unittest.TestCase):
|
class TestCodestream(unittest.TestCase):
|
||||||
"""Test suite for unusual codestream cases."""
|
"""Test suite for unusual codestream cases."""
|
||||||
|
|
@ -34,8 +29,51 @@ class TestCodestream(unittest.TestCase):
|
||||||
def tearDown(self):
|
def tearDown(self):
|
||||||
pass
|
pass
|
||||||
|
|
||||||
@unittest.skipIf(DATA_ROOT is None,
|
def test_siz_segment_ssiz_unsigned(self):
|
||||||
|
"""ssiz attribute to be removed in future release"""
|
||||||
|
j = Jp2k(self.jp2file)
|
||||||
|
codestream = j.get_codestream()
|
||||||
|
|
||||||
|
# The ssiz attribute was simply a tuple of raw bytes.
|
||||||
|
# The first 7 bits are interpreted as the bitdepth, the MSB determines
|
||||||
|
# whether or not it is signed.
|
||||||
|
self.assertEqual(codestream.segment[1].ssiz, (7, 7, 7))
|
||||||
|
|
||||||
|
|
||||||
|
@unittest.skipIf(OPJ_DATA_ROOT is None,
|
||||||
"OPJ_DATA_ROOT environment variable not set")
|
"OPJ_DATA_ROOT environment variable not set")
|
||||||
|
class TestCodestreamOpjData(unittest.TestCase):
|
||||||
|
"""Test suite for unusual codestream cases. Uses OPJ_DATA_ROOT"""
|
||||||
|
|
||||||
|
def setUp(self):
|
||||||
|
self.jp2file = glymur.data.nemo()
|
||||||
|
|
||||||
|
def tearDown(self):
|
||||||
|
pass
|
||||||
|
|
||||||
|
def test_invalid_progression_order(self):
|
||||||
|
"""Should still be able to parse even if prog order is invalid."""
|
||||||
|
jfile = opj_data_file('input/nonregression/2977.pdf.asan.67.2198.jp2')
|
||||||
|
if sys.hexversion < 0x03000000:
|
||||||
|
with warnings.catch_warnings():
|
||||||
|
warnings.simplefilter("ignore")
|
||||||
|
Jp2k(jfile)
|
||||||
|
else:
|
||||||
|
with self.assertWarns(UserWarning):
|
||||||
|
Jp2k(jfile)
|
||||||
|
|
||||||
|
def test_tile_height_is_zero(self):
|
||||||
|
"""Zero tile height should not cause an exception."""
|
||||||
|
filename = opj_data_file('input/nonregression/2539.pdf.SIGFPE.706.1712.jp2')
|
||||||
|
if sys.hexversion < 0x03000000:
|
||||||
|
with warnings.catch_warnings():
|
||||||
|
warnings.simplefilter("ignore")
|
||||||
|
Jp2k(filename)
|
||||||
|
else:
|
||||||
|
with self.assertWarns(UserWarning):
|
||||||
|
Jp2k(filename)
|
||||||
|
|
||||||
|
|
||||||
@unittest.skipIf(os.name == "nt", "Temporary file issue on window.")
|
@unittest.skipIf(os.name == "nt", "Temporary file issue on window.")
|
||||||
def test_reserved_marker_segment(self):
|
def test_reserved_marker_segment(self):
|
||||||
"""Reserved marker segments are ok."""
|
"""Reserved marker segments are ok."""
|
||||||
|
|
@ -45,7 +83,7 @@ class TestCodestream(unittest.TestCase):
|
||||||
#
|
#
|
||||||
# Let's inject a reserved marker segment into a file that
|
# Let's inject a reserved marker segment into a file that
|
||||||
# we know something about to make sure we can still parse it.
|
# we know something about to make sure we can still parse it.
|
||||||
filename = os.path.join(DATA_ROOT, 'input/conformance/p0_01.j2k')
|
filename = os.path.join(OPJ_DATA_ROOT, 'input/conformance/p0_01.j2k')
|
||||||
with tempfile.NamedTemporaryFile(suffix='.j2k') as tfile:
|
with tempfile.NamedTemporaryFile(suffix='.j2k') as tfile:
|
||||||
with open(filename, 'rb') as ifile:
|
with open(filename, 'rb') as ifile:
|
||||||
# Everything up until the first QCD marker.
|
# Everything up until the first QCD marker.
|
||||||
|
|
@ -67,8 +105,6 @@ class TestCodestream(unittest.TestCase):
|
||||||
self.assertEqual(codestream.segment[2].length, 3)
|
self.assertEqual(codestream.segment[2].length, 3)
|
||||||
self.assertEqual(codestream.segment[2].data, b'\x00')
|
self.assertEqual(codestream.segment[2].data, b'\x00')
|
||||||
|
|
||||||
@unittest.skipIf(DATA_ROOT is None,
|
|
||||||
"OPJ_DATA_ROOT environment variable not set")
|
|
||||||
@unittest.skipIf(sys.hexversion < 0x03020000,
|
@unittest.skipIf(sys.hexversion < 0x03020000,
|
||||||
"Uses features introduced in 3.2.")
|
"Uses features introduced in 3.2.")
|
||||||
@unittest.skipIf(os.name == "nt", "Temporary file issue on window.")
|
@unittest.skipIf(os.name == "nt", "Temporary file issue on window.")
|
||||||
|
|
@ -77,7 +113,7 @@ class TestCodestream(unittest.TestCase):
|
||||||
# Let's inject a marker segment whose marker does not appear to
|
# Let's inject a marker segment whose marker does not appear to
|
||||||
# be valid. We still parse the file, but warn about the offending
|
# be valid. We still parse the file, but warn about the offending
|
||||||
# marker.
|
# marker.
|
||||||
filename = os.path.join(DATA_ROOT, 'input/conformance/p0_01.j2k')
|
filename = os.path.join(OPJ_DATA_ROOT, 'input/conformance/p0_01.j2k')
|
||||||
with tempfile.NamedTemporaryFile(suffix='.j2k') as tfile:
|
with tempfile.NamedTemporaryFile(suffix='.j2k') as tfile:
|
||||||
with open(filename, 'rb') as ifile:
|
with open(filename, 'rb') as ifile:
|
||||||
# Everything up until the first QCD marker.
|
# Everything up until the first QCD marker.
|
||||||
|
|
@ -100,11 +136,9 @@ class TestCodestream(unittest.TestCase):
|
||||||
self.assertEqual(codestream.segment[2].length, 3)
|
self.assertEqual(codestream.segment[2].length, 3)
|
||||||
self.assertEqual(codestream.segment[2].data, b'\x00')
|
self.assertEqual(codestream.segment[2].data, b'\x00')
|
||||||
|
|
||||||
@unittest.skipIf(DATA_ROOT is None,
|
|
||||||
"OPJ_DATA_ROOT environment variable not set")
|
|
||||||
def test_psot_is_zero(self):
|
def test_psot_is_zero(self):
|
||||||
"""Psot=0 in SOT is perfectly legal. Issue #78."""
|
"""Psot=0 in SOT is perfectly legal. Issue #78."""
|
||||||
filename = os.path.join(DATA_ROOT,
|
filename = os.path.join(OPJ_DATA_ROOT,
|
||||||
'input/nonregression/123.j2c')
|
'input/nonregression/123.j2c')
|
||||||
j = Jp2k(filename)
|
j = Jp2k(filename)
|
||||||
codestream = j.get_codestream(header_only=False)
|
codestream = j.get_codestream(header_only=False)
|
||||||
|
|
@ -114,22 +148,9 @@ class TestCodestream(unittest.TestCase):
|
||||||
self.assertEqual(codestream.segment[-1].marker_id, 'EOC')
|
self.assertEqual(codestream.segment[-1].marker_id, 'EOC')
|
||||||
|
|
||||||
|
|
||||||
def test_siz_segment_ssiz_unsigned(self):
|
|
||||||
"""ssiz attribute to be removed in future release"""
|
|
||||||
j = Jp2k(self.jp2file)
|
|
||||||
codestream = j.get_codestream()
|
|
||||||
|
|
||||||
# The ssiz attribute was simply a tuple of raw bytes.
|
|
||||||
# The first 7 bits are interpreted as the bitdepth, the MSB determines
|
|
||||||
# whether or not it is signed.
|
|
||||||
self.assertEqual(codestream.segment[1].ssiz, (7, 7, 7))
|
|
||||||
|
|
||||||
|
|
||||||
@unittest.skipIf(DATA_ROOT is None,
|
|
||||||
"OPJ_DATA_ROOT environment variable not set")
|
|
||||||
def test_siz_segment_ssiz_signed(self):
|
def test_siz_segment_ssiz_signed(self):
|
||||||
"""ssiz attribute to be removed in future release"""
|
"""ssiz attribute to be removed in future release"""
|
||||||
filename = os.path.join(DATA_ROOT, 'input/conformance/p0_03.j2k')
|
filename = os.path.join(OPJ_DATA_ROOT, 'input/conformance/p0_03.j2k')
|
||||||
j = Jp2k(filename)
|
j = Jp2k(filename)
|
||||||
codestream = j.get_codestream()
|
codestream = j.get_codestream()
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,148 +0,0 @@
|
||||||
"""
|
|
||||||
These tests deal with JPX/JP2/J2K images in the format-corpus repository.
|
|
||||||
"""
|
|
||||||
# R0904: Not too many methods in unittest.
|
|
||||||
# pylint: disable=R0904
|
|
||||||
|
|
||||||
# E1101: assertWarns introduced in python 3.2
|
|
||||||
# pylint: disable=E1101
|
|
||||||
|
|
||||||
import os
|
|
||||||
from os.path import join
|
|
||||||
import re
|
|
||||||
import sys
|
|
||||||
import tempfile
|
|
||||||
import unittest
|
|
||||||
|
|
||||||
import glymur
|
|
||||||
from glymur import Jp2k
|
|
||||||
|
|
||||||
try:
|
|
||||||
FORMAT_CORPUS_DATA_ROOT = os.environ['FORMAT_CORPUS_DATA_ROOT']
|
|
||||||
except KeyError:
|
|
||||||
FORMAT_CORPUS_DATA_ROOT = None
|
|
||||||
|
|
||||||
try:
|
|
||||||
OPJ_DATA_ROOT = os.environ['OPJ_DATA_ROOT']
|
|
||||||
except KeyError:
|
|
||||||
OPJ_DATA_ROOT = None
|
|
||||||
|
|
||||||
|
|
||||||
@unittest.skipIf(sys.hexversion < 0x03020000,
|
|
||||||
"Requires features introduced in 3.2 (assertWarns)")
|
|
||||||
class TestSuiteConformance(unittest.TestCase):
|
|
||||||
"""Test suite for conformance."""
|
|
||||||
|
|
||||||
def setUp(self):
|
|
||||||
self.j2kfile = glymur.data.goodstuff()
|
|
||||||
|
|
||||||
def tearDown(self):
|
|
||||||
pass
|
|
||||||
|
|
||||||
@unittest.skipIf(re.match(r"""1\.[0123]""",
|
|
||||||
glymur.version.openjpeg_version) is not None,
|
|
||||||
"Needs 1.3+ to catch this.")
|
|
||||||
def test_truncated_eoc(self):
|
|
||||||
"""Has one byte shaved off of EOC marker."""
|
|
||||||
with open(self.j2kfile, 'rb') as ifile:
|
|
||||||
data = ifile.read()
|
|
||||||
with tempfile.NamedTemporaryFile(suffix='.j2k') as ofile:
|
|
||||||
ofile.write(data[:-1])
|
|
||||||
ofile.flush()
|
|
||||||
|
|
||||||
j2k = Jp2k(ofile.name)
|
|
||||||
with self.assertWarns(UserWarning):
|
|
||||||
codestream = j2k.get_codestream(header_only=False)
|
|
||||||
|
|
||||||
# The last segment is truncated, so there should not be an EOC
|
|
||||||
# marker.
|
|
||||||
self.assertNotEqual(codestream.segment[-1].marker_id, 'EOC')
|
|
||||||
|
|
||||||
# The codestream is not as long as claimed.
|
|
||||||
with self.assertRaises(OSError):
|
|
||||||
j2k.read(rlevel=-1)
|
|
||||||
|
|
||||||
|
|
||||||
@unittest.skipIf(FORMAT_CORPUS_DATA_ROOT is None,
|
|
||||||
"FORMAT_CORPUS_DATA_ROOT environment variable not set")
|
|
||||||
@unittest.skipIf(sys.hexversion < 0x03020000,
|
|
||||||
"Requires features introduced in 3.2 (assertWarns)")
|
|
||||||
class TestSuiteFormatCorpus(unittest.TestCase):
|
|
||||||
"""Test suite for files in format corpus repository."""
|
|
||||||
|
|
||||||
@unittest.skipIf(re.match(r"""1\.[01234]""",
|
|
||||||
glymur.version.openjpeg_version) is not None,
|
|
||||||
"Needs 1.4+ to catch this.")
|
|
||||||
def test_balloon_trunc2(self):
|
|
||||||
"""Shortened by 5000 bytes."""
|
|
||||||
jfile = os.path.join(FORMAT_CORPUS_DATA_ROOT,
|
|
||||||
'jp2k-test/byteCorruption/balloon_trunc2.jp2')
|
|
||||||
j2k = Jp2k(jfile)
|
|
||||||
with self.assertWarns(UserWarning):
|
|
||||||
codestream = j2k.get_codestream(header_only=False)
|
|
||||||
|
|
||||||
# The last segment is truncated, so there should not be an EOC marker.
|
|
||||||
self.assertNotEqual(codestream.segment[-1].marker_id, 'EOC')
|
|
||||||
|
|
||||||
# The codestream is not as long as claimed.
|
|
||||||
with self.assertRaises(OSError):
|
|
||||||
j2k.read(rlevel=-1)
|
|
||||||
|
|
||||||
def test_balloon_trunc3(self):
|
|
||||||
"""Most of last tile is missing."""
|
|
||||||
jfile = os.path.join(FORMAT_CORPUS_DATA_ROOT,
|
|
||||||
'jp2k-test/byteCorruption/balloon_trunc3.jp2')
|
|
||||||
j2k = Jp2k(jfile)
|
|
||||||
with self.assertWarns(UserWarning):
|
|
||||||
codestream = j2k.get_codestream(header_only=False)
|
|
||||||
|
|
||||||
# The last segment is truncated, so there should not be an EOC marker.
|
|
||||||
self.assertNotEqual(codestream.segment[-1].marker_id, 'EOC')
|
|
||||||
|
|
||||||
# Should error out, it does not.
|
|
||||||
#with self.assertRaises(OSError):
|
|
||||||
# j2k.read(rlevel=-1)
|
|
||||||
|
|
||||||
def test_jp2_brand_any_icc_profile(self):
|
|
||||||
"""If 'jp2 ', then the method cannot be any icc profile."""
|
|
||||||
jfile = os.path.join(FORMAT_CORPUS_DATA_ROOT,
|
|
||||||
'jp2k-test', 'icc',
|
|
||||||
'balloon_eciRGBv2_ps_adobeplugin.jpf')
|
|
||||||
with self.assertWarns(UserWarning):
|
|
||||||
Jp2k(jfile)
|
|
||||||
|
|
||||||
def test_jp2_brand_iccpr_mult_colr(self):
|
|
||||||
"""Has colr box, one that conforms, one that does not."""
|
|
||||||
|
|
||||||
# Wrong 'brand' field; contains two versions of ICC profile: one
|
|
||||||
# embedded using "Any ICC" method; other embedded using "Restricted
|
|
||||||
# ICC" method, with description ("Modified eciRGB v2") and profileClass
|
|
||||||
# ("Input Device") changed relative to original profile.
|
|
||||||
jfile = join(FORMAT_CORPUS_DATA_ROOT, 'jp2k-test', 'icc',
|
|
||||||
'balloon_eciRGBv2_ps_adobeplugin_jp2compatible.jpf')
|
|
||||||
with self.assertWarns(UserWarning):
|
|
||||||
Jp2k(jfile)
|
|
||||||
|
|
||||||
|
|
||||||
@unittest.skipIf(OPJ_DATA_ROOT is None,
|
|
||||||
"OPJ_DATA_ROOT environment variable not set")
|
|
||||||
@unittest.skipIf(sys.hexversion < 0x03020000,
|
|
||||||
"Requires features introduced in 3.2 (assertWarns)")
|
|
||||||
class TestSuiteOpj(unittest.TestCase):
|
|
||||||
"""Test suite for files in openjpeg repository."""
|
|
||||||
|
|
||||||
def setUp(self):
|
|
||||||
pass
|
|
||||||
|
|
||||||
def tearDown(self):
|
|
||||||
pass
|
|
||||||
|
|
||||||
def test_jp2_brand_any_icc_profile(self):
|
|
||||||
"""If 'jp2 ', then the method cannot be any icc profile."""
|
|
||||||
filename = os.path.join(OPJ_DATA_ROOT,
|
|
||||||
'input/nonregression/text_GBR.jp2')
|
|
||||||
with self.assertWarns(UserWarning):
|
|
||||||
Jp2k(filename)
|
|
||||||
|
|
||||||
if __name__ == "__main__":
|
|
||||||
unittest.main()
|
|
||||||
|
|
@ -39,6 +39,7 @@ from glymur.jp2box import ColourSpecificationBox, ContiguousCodestreamBox
|
||||||
from glymur.jp2box import FileTypeBox, ImageHeaderBox, JP2HeaderBox
|
from glymur.jp2box import FileTypeBox, ImageHeaderBox, JP2HeaderBox
|
||||||
from glymur.jp2box import JPEG2000SignatureBox
|
from glymur.jp2box import JPEG2000SignatureBox
|
||||||
|
|
||||||
|
from .fixtures import OPJ_DATA_ROOT, opj_data_file
|
||||||
|
|
||||||
@unittest.skipIf(os.name == "nt", "Temporary file issue on window.")
|
@unittest.skipIf(os.name == "nt", "Temporary file issue on window.")
|
||||||
class TestXML(unittest.TestCase):
|
class TestXML(unittest.TestCase):
|
||||||
|
|
@ -286,3 +287,40 @@ class TestBadButRecoverableXmlFile(unittest.TestCase):
|
||||||
b'<test>this is a test</test>')
|
b'<test>this is a test</test>')
|
||||||
|
|
||||||
|
|
||||||
|
@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."""
|
||||||
|
|
||||||
|
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'))
|
||||||
|
if sys.hexversion < 0x03000000:
|
||||||
|
with warnings.catch_warnings():
|
||||||
|
warnings.simplefilter("ignore")
|
||||||
|
jp2 = Jp2k(filename)
|
||||||
|
else:
|
||||||
|
with self.assertWarns(UserWarning):
|
||||||
|
jp2 = Jp2k(filename)
|
||||||
|
self.assertIsNotNone(jp2.box[3].xml)
|
||||||
|
|
||||||
|
|
||||||
|
def test_invalid_utf8(self):
|
||||||
|
"""Bad byte sequence that cannot be parsed."""
|
||||||
|
filename = opj_data_file(os.path.join('input',
|
||||||
|
'nonregression',
|
||||||
|
'26ccf3651020967f7778238ef5af08af.SIGFPE.d25.527.jp2'))
|
||||||
|
if sys.hexversion < 0x03000000:
|
||||||
|
with warnings.catch_warnings():
|
||||||
|
warnings.simplefilter("ignore")
|
||||||
|
jp2 = Jp2k(filename)
|
||||||
|
else:
|
||||||
|
with self.assertWarns(UserWarning):
|
||||||
|
jp2 = Jp2k(filename)
|
||||||
|
|
||||||
|
self.assertIsNone(jp2.box[3].box[1].box[1].xml)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -37,7 +37,6 @@ if HAS_PYTHON_XMP_TOOLKIT:
|
||||||
from .fixtures import OPJ_DATA_ROOT, opj_data_file
|
from .fixtures import OPJ_DATA_ROOT, opj_data_file
|
||||||
from . import fixtures
|
from . import fixtures
|
||||||
|
|
||||||
|
|
||||||
# Doc tests should be run as well.
|
# Doc tests should be run as well.
|
||||||
def load_tests(loader, tests, ignore):
|
def load_tests(loader, tests, ignore):
|
||||||
# W0613: "loader" and "ignore" are necessary for the protocol
|
# W0613: "loader" and "ignore" are necessary for the protocol
|
||||||
|
|
@ -54,9 +53,7 @@ def load_tests(loader, tests, ignore):
|
||||||
|
|
||||||
|
|
||||||
class TestJp2k(unittest.TestCase):
|
class TestJp2k(unittest.TestCase):
|
||||||
"""Test suite for openjpeg software starting at 1.3"""
|
"""These tests should be run by just about all configuration."""
|
||||||
|
|
||||||
# These tests should be run by just about all configuration.
|
|
||||||
|
|
||||||
def setUp(self):
|
def setUp(self):
|
||||||
self.jp2file = glymur.data.nemo()
|
self.jp2file = glymur.data.nemo()
|
||||||
|
|
@ -95,6 +92,23 @@ class TestJp2k(unittest.TestCase):
|
||||||
with self.assertRaises(IOError):
|
with self.assertRaises(IOError):
|
||||||
Jp2k(filename)
|
Jp2k(filename)
|
||||||
|
|
||||||
|
def test_no_cxform_pclr_jpx(self):
|
||||||
|
"""Indices for pclr jpxfile if no color transform"""
|
||||||
|
j = Jp2k(self.jpxfile)
|
||||||
|
rgb = j.read()
|
||||||
|
idx = j.read(no_cxform=True)
|
||||||
|
self.assertEqual(rgb.shape, (1024, 1024, 3))
|
||||||
|
self.assertEqual(idx.shape, (1024, 1024))
|
||||||
|
|
||||||
|
# Should be able to manually reconstruct the RGB image from the palette
|
||||||
|
# and indices.
|
||||||
|
palette = j.box[3].box[2].palette
|
||||||
|
rgb_from_idx = np.zeros(rgb.shape, dtype=np.uint8)
|
||||||
|
for r in np.arange(1024):
|
||||||
|
for c in np.arange(1024):
|
||||||
|
rgb_from_idx[r, c] = palette[idx[r, c]]
|
||||||
|
np.testing.assert_array_equal(rgb, rgb_from_idx)
|
||||||
|
|
||||||
def test_file_not_present(self):
|
def test_file_not_present(self):
|
||||||
"""Should error out if reading from a file that does not exist"""
|
"""Should error out if reading from a file that does not exist"""
|
||||||
# Verify that we error out appropriately if not given an existing file
|
# Verify that we error out appropriately if not given an existing file
|
||||||
|
|
@ -248,19 +262,6 @@ class TestJp2k(unittest.TestCase):
|
||||||
j2k = Jp2k(self.j2kfile)
|
j2k = Jp2k(self.j2kfile)
|
||||||
j2k.read()
|
j2k.read()
|
||||||
|
|
||||||
@unittest.skipIf(OPJ_DATA_ROOT is None,
|
|
||||||
"OPJ_DATA_ROOT environment variable not set")
|
|
||||||
def test_read_differing_subsamples(self):
|
|
||||||
"""should error out with read used on differently subsampled images"""
|
|
||||||
# Verify that we error out appropriately if we use the read method
|
|
||||||
# on an image with differing subsamples
|
|
||||||
#
|
|
||||||
# Issue 86.
|
|
||||||
filename = opj_data_file('input/conformance/p0_05.j2k')
|
|
||||||
j = Jp2k(filename)
|
|
||||||
with self.assertRaises(RuntimeError):
|
|
||||||
j.read()
|
|
||||||
|
|
||||||
def test_empty_box_with_j2k(self):
|
def test_empty_box_with_j2k(self):
|
||||||
"""Verify that the list of boxes in a J2C/J2K file is present, but
|
"""Verify that the list of boxes in a J2C/J2K file is present, but
|
||||||
empty.
|
empty.
|
||||||
|
|
@ -386,15 +387,9 @@ class TestJp2k(unittest.TestCase):
|
||||||
# The file in question has multiple codestreams.
|
# The file in question has multiple codestreams.
|
||||||
jpx = Jp2k(self.jpxfile)
|
jpx = Jp2k(self.jpxfile)
|
||||||
data = jpx.read()
|
data = jpx.read()
|
||||||
if re.match(r"""1\.[0123]""", glymur.version.openjpeg_version):
|
|
||||||
# openjpeg 1.3 doesn't apply the palette, so it's a 2D image here
|
|
||||||
self.assertEqual(data.shape, (1024, 1024))
|
|
||||||
else:
|
|
||||||
self.assertEqual(data.shape, (1024, 1024, 3))
|
self.assertEqual(data.shape, (1024, 1024, 3))
|
||||||
|
|
||||||
|
|
||||||
@unittest.skipIf(re.match(r"""1\.[01234]""", glymur.version.openjpeg_version),
|
|
||||||
"Requires at least version 1.5")
|
|
||||||
class TestJp2k_write(unittest.TestCase):
|
class TestJp2k_write(unittest.TestCase):
|
||||||
"""Write tests, can be run by versions 1.5+"""
|
"""Write tests, can be run by versions 1.5+"""
|
||||||
|
|
||||||
|
|
@ -758,6 +753,67 @@ class TestJp2k_2_1(unittest.TestCase):
|
||||||
with self.assertRaisesRegex((IOError, OSError), regexp):
|
with self.assertRaisesRegex((IOError, OSError), regexp):
|
||||||
j.read(rlevel=1)
|
j.read(rlevel=1)
|
||||||
|
|
||||||
|
@unittest.skipIf(OPJ_DATA_ROOT is None,
|
||||||
|
"OPJ_DATA_ROOT environment variable not set")
|
||||||
|
class TestJp2kOpjDataRoot(unittest.TestCase):
|
||||||
|
"""These tests should be run by just about all configuration."""
|
||||||
|
|
||||||
|
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)
|
||||||
|
rgb = j.read()
|
||||||
|
idx = j.read(no_cxform=True)
|
||||||
|
self.assertEqual(rgb.shape, (512, 768, 3))
|
||||||
|
self.assertEqual(idx.shape, (512, 768))
|
||||||
|
|
||||||
|
# Should be able to manually reconstruct the RGB image from the palette
|
||||||
|
# and indices.
|
||||||
|
palette = j.box[2].box[1].palette
|
||||||
|
rgb_from_idx = np.zeros(rgb.shape, dtype=np.uint8)
|
||||||
|
for r in np.arange(rgb.shape[0]):
|
||||||
|
for c in np.arange(rgb.shape[1]):
|
||||||
|
rgb_from_idx[r, c] = palette[idx[r, c]]
|
||||||
|
np.testing.assert_array_equal(rgb, rgb_from_idx)
|
||||||
|
|
||||||
|
def test_stupid_windows_eol_at_end(self):
|
||||||
|
"""Garbage characters at the end of the file."""
|
||||||
|
filename = opj_data_file('input/nonregression/issue211.jp2')
|
||||||
|
if sys.hexversion < 0x03000000:
|
||||||
|
with warnings.catch_warnings():
|
||||||
|
warnings.simplefilter("ignore")
|
||||||
|
jp2 = Jp2k(filename)
|
||||||
|
else:
|
||||||
|
with self.assertWarns(UserWarning):
|
||||||
|
jp2 = Jp2k(filename)
|
||||||
|
|
||||||
|
def test_read_differing_subsamples(self):
|
||||||
|
"""should error out with read used on differently subsampled images"""
|
||||||
|
# Verify that we error out appropriately if we use the read method
|
||||||
|
# on an image with differing subsamples
|
||||||
|
#
|
||||||
|
# Issue 86.
|
||||||
|
filename = opj_data_file('input/conformance/p0_05.j2k')
|
||||||
|
j = Jp2k(filename)
|
||||||
|
with self.assertRaises(RuntimeError):
|
||||||
|
j.read()
|
||||||
|
|
||||||
|
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')
|
||||||
|
j = Jp2k(filename)
|
||||||
|
ycbcr = j.read()
|
||||||
|
crcby = j.read(no_cxform=True)
|
||||||
|
|
||||||
|
expected = np.zeros(ycbcr.shape, ycbcr.dtype)
|
||||||
|
for k in range(crcby.shape[2]):
|
||||||
|
expected[:,:,crcby.shape[2] - k - 1] = crcby[:,:,k]
|
||||||
|
|
||||||
|
np.testing.assert_array_equal(ycbcr, expected)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
if __name__ == "__main__":
|
if __name__ == "__main__":
|
||||||
unittest.main()
|
unittest.main()
|
||||||
|
|
|
||||||
|
|
@ -381,10 +381,6 @@ class TestSuite(unittest.TestCase):
|
||||||
jfile = opj_data_file('input/conformance/file9.jp2')
|
jfile = opj_data_file('input/conformance/file9.jp2')
|
||||||
jp2k = Jp2k(jfile)
|
jp2k = Jp2k(jfile)
|
||||||
jpdata = jp2k.read()
|
jpdata = jp2k.read()
|
||||||
if re.match(r"""1\.3""", glymur.version.openjpeg_version):
|
|
||||||
# Version 1.3 reads the indexed image as indices, not as RGB.
|
|
||||||
self.assertEqual(jpdata.shape, (512, 768))
|
|
||||||
else:
|
|
||||||
self.assertEqual(jpdata.shape, (512, 768, 3))
|
self.assertEqual(jpdata.shape, (512, 768, 3))
|
||||||
|
|
||||||
def test_NR_DEC_Bretagne2_j2k_1_decode(self):
|
def test_NR_DEC_Bretagne2_j2k_1_decode(self):
|
||||||
|
|
@ -6307,9 +6303,14 @@ class TestSuiteDump(unittest.TestCase):
|
||||||
[8, 9, 9, 10, 9, 9, 10, 9, 9, 10, 9, 9, 10, 9, 9, 10])
|
[8, 9, 9, 10, 9, 9, 10, 9, 9, 10, 9, 9, 10, 9, 9, 10])
|
||||||
|
|
||||||
def test_NR_text_GBR_dump(self):
|
def test_NR_text_GBR_dump(self):
|
||||||
jfile = opj_data_file('input/nonregression/text_GBR.jp2')
|
|
||||||
with warnings.catch_warnings():
|
|
||||||
# brand is 'jp2 ', but has any icc profile.
|
# brand is 'jp2 ', but has any icc profile.
|
||||||
|
# Verify the warning on python3, but ignore it otherwise.
|
||||||
|
jfile = opj_data_file('input/nonregression/text_GBR.jp2')
|
||||||
|
if sys.hexversion > 0x03030000:
|
||||||
|
with self.assertWarns(UserWarning):
|
||||||
|
jp2 = Jp2k(jfile)
|
||||||
|
else:
|
||||||
|
with warnings.catch_warnings():
|
||||||
warnings.simplefilter("ignore")
|
warnings.simplefilter("ignore")
|
||||||
jp2 = Jp2k(jfile)
|
jp2 = Jp2k(jfile)
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -23,33 +23,6 @@ from glymur import Jp2k
|
||||||
import glymur
|
import glymur
|
||||||
|
|
||||||
|
|
||||||
@unittest.skipIf(re.match(r"""1\.[01234]""", glymur.version.openjpeg_version),
|
|
||||||
"Functionality not implemented for 1.3, 1.4")
|
|
||||||
@unittest.skipIf(OPJ_DATA_ROOT is None,
|
|
||||||
"OPJ_OPJ_DATA_ROOT environment variable not set")
|
|
||||||
class TestSuiteNegative2pointzero(unittest.TestCase):
|
|
||||||
"""Feature set not supported for versions less than 2.0"""
|
|
||||||
|
|
||||||
def setUp(self):
|
|
||||||
self.jp2file = glymur.data.nemo()
|
|
||||||
self.j2kfile = glymur.data.goodstuff()
|
|
||||||
|
|
||||||
def tearDown(self):
|
|
||||||
pass
|
|
||||||
|
|
||||||
@unittest.skipIf(os.name == "nt", "Temporary file issue on window.")
|
|
||||||
def test_cinema_mode(self):
|
|
||||||
"""Cinema mode not supported for less than 2.0.1."""
|
|
||||||
infile = opj_data_file('input/nonregression/Bretagne1.ppm')
|
|
||||||
data = read_image(infile)
|
|
||||||
with tempfile.NamedTemporaryFile(suffix='.j2k') as tfile:
|
|
||||||
j = Jp2k(tfile.name, 'wb')
|
|
||||||
with self.assertRaises(IOError):
|
|
||||||
j.write(data, psnr=[30, 35, 40], cratios=[2, 3, 4])
|
|
||||||
|
|
||||||
|
|
||||||
@unittest.skipIf(re.match(r"""1\.[01234]""", glymur.version.openjpeg_version),
|
|
||||||
"Functionality not implemented for 1.3, 1.4")
|
|
||||||
@unittest.skipIf(OPJ_DATA_ROOT is None,
|
@unittest.skipIf(OPJ_DATA_ROOT is None,
|
||||||
"OPJ_OPJ_DATA_ROOT environment variable not set")
|
"OPJ_OPJ_DATA_ROOT environment variable not set")
|
||||||
class TestSuiteNegative(unittest.TestCase):
|
class TestSuiteNegative(unittest.TestCase):
|
||||||
|
|
|
||||||
|
|
@ -223,8 +223,10 @@ class TestSuiteWriteCinema(unittest.TestCase):
|
||||||
self.check_cinema2k_codestream(codestream, (1998, 1080))
|
self.check_cinema2k_codestream(codestream, (1998, 1080))
|
||||||
|
|
||||||
|
|
||||||
|
@unittest.skipIf(not _HAS_SKIMAGE_FREEIMAGE_SUPPORT,
|
||||||
|
"Cannot read input image without scikit-image/freeimage")
|
||||||
@unittest.skipIf(os.name == "nt", "Temporary file issue on window.")
|
@unittest.skipIf(os.name == "nt", "Temporary file issue on window.")
|
||||||
@unittest.skipIf(re.match(r"""2\.0""", glymur.version.openjpeg_version),
|
@unittest.skipIf(not re.match("(1.5|2.0)", glymur.version.openjpeg_version),
|
||||||
"Functionality implemented for 2.1")
|
"Functionality implemented for 2.1")
|
||||||
@unittest.skipIf(OPJ_DATA_ROOT is None,
|
@unittest.skipIf(OPJ_DATA_ROOT is None,
|
||||||
"OPJ_OPJ_DATA_ROOT environment variable not set")
|
"OPJ_OPJ_DATA_ROOT environment variable not set")
|
||||||
|
|
@ -249,9 +251,6 @@ class TestSuiteNegative2pointzero(unittest.TestCase):
|
||||||
|
|
||||||
|
|
||||||
@unittest.skipIf(os.name == "nt", "no write support on windows, period")
|
@unittest.skipIf(os.name == "nt", "no write support on windows, period")
|
||||||
@unittest.skipIf(re.match(r"""1\.[01234]\.\d""",
|
|
||||||
glymur.version.openjpeg_version) is not None,
|
|
||||||
"Writing only supported with openjpeg version 1.5+.")
|
|
||||||
@unittest.skipIf(NO_READ_BACKEND, NO_READ_BACKEND_MSG)
|
@unittest.skipIf(NO_READ_BACKEND, NO_READ_BACKEND_MSG)
|
||||||
@unittest.skipIf(OPJ_DATA_ROOT is None,
|
@unittest.skipIf(OPJ_DATA_ROOT is None,
|
||||||
"OPJ_DATA_ROOT environment variable not set")
|
"OPJ_DATA_ROOT environment variable not set")
|
||||||
|
|
|
||||||
|
|
@ -289,69 +289,6 @@ class TestPrinting(unittest.TestCase):
|
||||||
expected = '\n'.join(lines)
|
expected = '\n'.join(lines)
|
||||||
self.assertEqual(actual, expected)
|
self.assertEqual(actual, expected)
|
||||||
|
|
||||||
@unittest.skipIf(OPJ_DATA_ROOT is None,
|
|
||||||
"OPJ_DATA_ROOT environment variable not set")
|
|
||||||
def test_crg(self):
|
|
||||||
"""verify printing of CRG segment"""
|
|
||||||
filename = opj_data_file('input/conformance/p0_03.j2k')
|
|
||||||
j = glymur.Jp2k(filename)
|
|
||||||
codestream = j.get_codestream()
|
|
||||||
with patch('sys.stdout', new=StringIO()) as fake_out:
|
|
||||||
print(codestream.segment[-5])
|
|
||||||
actual = fake_out.getvalue().strip()
|
|
||||||
lines = ['CRG marker segment @ (87, 6)',
|
|
||||||
' Vertical, Horizontal offset: (0.50, 1.00)']
|
|
||||||
expected = '\n'.join(lines)
|
|
||||||
self.assertEqual(actual, expected)
|
|
||||||
|
|
||||||
@unittest.skipIf(OPJ_DATA_ROOT is None,
|
|
||||||
"OPJ_DATA_ROOT environment variable not set")
|
|
||||||
def test_rgn(self):
|
|
||||||
"""verify printing of RGN segment"""
|
|
||||||
filename = opj_data_file('input/conformance/p0_03.j2k')
|
|
||||||
j = glymur.Jp2k(filename)
|
|
||||||
codestream = j.get_codestream(header_only=False)
|
|
||||||
with patch('sys.stdout', new=StringIO()) as fake_out:
|
|
||||||
print(codestream.segment[12])
|
|
||||||
actual = fake_out.getvalue().strip()
|
|
||||||
lines = ['RGN marker segment @ (310, 5)',
|
|
||||||
' Associated component: 0',
|
|
||||||
' ROI style: 0',
|
|
||||||
' Parameter: 7']
|
|
||||||
expected = '\n'.join(lines)
|
|
||||||
self.assertEqual(actual, expected)
|
|
||||||
|
|
||||||
@unittest.skipIf(OPJ_DATA_ROOT is None,
|
|
||||||
"OPJ_DATA_ROOT environment variable not set")
|
|
||||||
def test_sop(self):
|
|
||||||
"""verify printing of SOP segment"""
|
|
||||||
filename = opj_data_file('input/conformance/p0_03.j2k')
|
|
||||||
j = glymur.Jp2k(filename)
|
|
||||||
codestream = j.get_codestream(header_only=False)
|
|
||||||
with patch('sys.stdout', new=StringIO()) as fake_out:
|
|
||||||
print(codestream.segment[-2])
|
|
||||||
actual = fake_out.getvalue().strip()
|
|
||||||
lines = ['SOP marker segment @ (12836, 4)',
|
|
||||||
' Nsop: 15']
|
|
||||||
expected = '\n'.join(lines)
|
|
||||||
self.assertEqual(actual, expected)
|
|
||||||
|
|
||||||
@unittest.skipIf(OPJ_DATA_ROOT is None,
|
|
||||||
"OPJ_DATA_ROOT environment variable not set")
|
|
||||||
def test_cme(self):
|
|
||||||
"""Test printing a CME or comment marker segment."""
|
|
||||||
filename = opj_data_file('input/conformance/p0_02.j2k')
|
|
||||||
j = glymur.Jp2k(filename)
|
|
||||||
codestream = j.get_codestream()
|
|
||||||
# 2nd to last segment in the main header
|
|
||||||
with patch('sys.stdout', new=StringIO()) as fake_out:
|
|
||||||
print(codestream.segment[-2])
|
|
||||||
actual = fake_out.getvalue().strip()
|
|
||||||
lines = ['CME marker segment @ (85, 45)',
|
|
||||||
' "Creator: AV-J2K (c) 2000,2001 Algo Vision"']
|
|
||||||
expected = '\n'.join(lines)
|
|
||||||
self.assertEqual(actual, expected)
|
|
||||||
|
|
||||||
def test_eoc_segment(self):
|
def test_eoc_segment(self):
|
||||||
"""verify printing of eoc segment"""
|
"""verify printing of eoc segment"""
|
||||||
j = glymur.Jp2k(self.jp2file)
|
j = glymur.Jp2k(self.jp2file)
|
||||||
|
|
@ -364,91 +301,6 @@ class TestPrinting(unittest.TestCase):
|
||||||
expected = '\n'.join(lines)
|
expected = '\n'.join(lines)
|
||||||
self.assertEqual(actual, expected)
|
self.assertEqual(actual, expected)
|
||||||
|
|
||||||
@unittest.skipIf(OPJ_DATA_ROOT is None,
|
|
||||||
"OPJ_DATA_ROOT environment variable not set")
|
|
||||||
def test_plt_segment(self):
|
|
||||||
"""verify printing of PLT segment"""
|
|
||||||
filename = opj_data_file('input/conformance/p0_07.j2k')
|
|
||||||
j = glymur.Jp2k(filename)
|
|
||||||
codestream = j.get_codestream(header_only=False)
|
|
||||||
with patch('sys.stdout', new=StringIO()) as fake_out:
|
|
||||||
print(codestream.segment[49935])
|
|
||||||
actual = fake_out.getvalue().strip()
|
|
||||||
|
|
||||||
lines = ['PLT marker segment @ (7871146, 38)',
|
|
||||||
' Index: 0',
|
|
||||||
' Iplt: [9, 122, 19, 30, 27, 9, 41, 62, 18, 29, 261,'
|
|
||||||
+ ' 55, 82, 299, 93, 941, 951, 687, 1729, 1443, 1008, 2168,'
|
|
||||||
+ ' 2188, 2223]']
|
|
||||||
expected = '\n'.join(lines)
|
|
||||||
self.assertEqual(actual, expected)
|
|
||||||
|
|
||||||
@unittest.skipIf(OPJ_DATA_ROOT is None,
|
|
||||||
"OPJ_DATA_ROOT environment variable not set")
|
|
||||||
def test_pod_segment(self):
|
|
||||||
"""verify printing of POD segment"""
|
|
||||||
filename = opj_data_file('input/conformance/p0_13.j2k')
|
|
||||||
j = glymur.Jp2k(filename)
|
|
||||||
codestream = j.get_codestream()
|
|
||||||
with patch('sys.stdout', new=StringIO()) as fake_out:
|
|
||||||
print(codestream.segment[8])
|
|
||||||
actual = fake_out.getvalue().strip()
|
|
||||||
|
|
||||||
lines = ['POD marker segment @ (878, 20)',
|
|
||||||
' Progression change 0:',
|
|
||||||
' Resolution index start: 0',
|
|
||||||
' Component index start: 0',
|
|
||||||
' Layer index end: 1',
|
|
||||||
' Resolution index end: 33',
|
|
||||||
' Component index end: 128',
|
|
||||||
' Progression order: RLCP',
|
|
||||||
' Progression change 1:',
|
|
||||||
' Resolution index start: 0',
|
|
||||||
' Component index start: 128',
|
|
||||||
' Layer index end: 1',
|
|
||||||
' Resolution index end: 33',
|
|
||||||
' Component index end: 257',
|
|
||||||
' Progression order: CPRL']
|
|
||||||
|
|
||||||
expected = '\n'.join(lines)
|
|
||||||
self.assertEqual(actual, expected)
|
|
||||||
|
|
||||||
@unittest.skipIf(OPJ_DATA_ROOT is None,
|
|
||||||
"OPJ_DATA_ROOT environment variable not set")
|
|
||||||
def test_ppm_segment(self):
|
|
||||||
"""verify printing of PPM segment"""
|
|
||||||
filename = opj_data_file('input/conformance/p1_03.j2k')
|
|
||||||
j = glymur.Jp2k(filename)
|
|
||||||
codestream = j.get_codestream()
|
|
||||||
with patch('sys.stdout', new=StringIO()) as fake_out:
|
|
||||||
print(codestream.segment[9])
|
|
||||||
actual = fake_out.getvalue().strip()
|
|
||||||
|
|
||||||
lines = ['PPM marker segment @ (213, 43712)',
|
|
||||||
' Index: 0',
|
|
||||||
' Data: 43709 uninterpreted bytes']
|
|
||||||
|
|
||||||
expected = '\n'.join(lines)
|
|
||||||
self.assertEqual(actual, expected)
|
|
||||||
|
|
||||||
@unittest.skipIf(OPJ_DATA_ROOT is None,
|
|
||||||
"OPJ_DATA_ROOT environment variable not set")
|
|
||||||
def test_ppt_segment(self):
|
|
||||||
"""verify printing of ppt segment"""
|
|
||||||
filename = opj_data_file('input/conformance/p1_06.j2k')
|
|
||||||
j = glymur.Jp2k(filename)
|
|
||||||
codestream = j.get_codestream(header_only=False)
|
|
||||||
with patch('sys.stdout', new=StringIO()) as fake_out:
|
|
||||||
print(codestream.segment[6])
|
|
||||||
actual = fake_out.getvalue().strip()
|
|
||||||
|
|
||||||
lines = ['PPT marker segment @ (155, 109)',
|
|
||||||
' Index: 0',
|
|
||||||
' Packet headers: 106 uninterpreted bytes']
|
|
||||||
|
|
||||||
expected = '\n'.join(lines)
|
|
||||||
self.assertEqual(actual, expected)
|
|
||||||
|
|
||||||
def test_qcc_segment(self):
|
def test_qcc_segment(self):
|
||||||
"""verify printing of qcc segment"""
|
"""verify printing of qcc segment"""
|
||||||
j = glymur.Jp2k(self.jp2file)
|
j = glymur.Jp2k(self.jp2file)
|
||||||
|
|
@ -543,25 +395,6 @@ class TestPrinting(unittest.TestCase):
|
||||||
expected = '\n'.join(lines)
|
expected = '\n'.join(lines)
|
||||||
self.assertEqual(actual, expected)
|
self.assertEqual(actual, expected)
|
||||||
|
|
||||||
@unittest.skipIf(OPJ_DATA_ROOT is None,
|
|
||||||
"OPJ_DATA_ROOT environment variable not set")
|
|
||||||
def test_tlm_segment(self):
|
|
||||||
"""verify printing of TLM segment"""
|
|
||||||
filename = opj_data_file('input/conformance/p0_15.j2k')
|
|
||||||
j = glymur.Jp2k(filename)
|
|
||||||
codestream = j.get_codestream()
|
|
||||||
with patch('sys.stdout', new=StringIO()) as fake_out:
|
|
||||||
print(codestream.segment[10])
|
|
||||||
actual = fake_out.getvalue().strip()
|
|
||||||
|
|
||||||
lines = ['TLM marker segment @ (268, 28)',
|
|
||||||
' Index: 0',
|
|
||||||
' Tile number: (0, 1, 2, 3)',
|
|
||||||
' Length: (4267, 2117, 4080, 2081)']
|
|
||||||
|
|
||||||
expected = '\n'.join(lines)
|
|
||||||
self.assertEqual(actual, expected)
|
|
||||||
|
|
||||||
def test_xmp(self):
|
def test_xmp(self):
|
||||||
"""Verify the printing of a UUID/XMP box."""
|
"""Verify the printing of a UUID/XMP box."""
|
||||||
j = glymur.Jp2k(self.jp2file)
|
j = glymur.Jp2k(self.jp2file)
|
||||||
|
|
@ -621,17 +454,6 @@ class TestPrinting(unittest.TestCase):
|
||||||
expected = '\n'.join(lst)
|
expected = '\n'.join(lst)
|
||||||
self.assertEqual(actual, expected)
|
self.assertEqual(actual, expected)
|
||||||
|
|
||||||
@unittest.skipIf(OPJ_DATA_ROOT is None,
|
|
||||||
"OPJ_DATA_ROOT environment variable not set")
|
|
||||||
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)
|
|
||||||
|
|
||||||
@unittest.skipIf(sys.hexversion < 0x03000000,
|
@unittest.skipIf(sys.hexversion < 0x03000000,
|
||||||
"Only trusting python3 for printing non-ascii chars")
|
"Only trusting python3 for printing non-ascii chars")
|
||||||
def test_xml_latin1(self):
|
def test_xml_latin1(self):
|
||||||
|
|
@ -689,101 +511,6 @@ class TestPrinting(unittest.TestCase):
|
||||||
expected = '\n'.join(lines)
|
expected = '\n'.join(lines)
|
||||||
self.assertEqual(actual, expected)
|
self.assertEqual(actual, expected)
|
||||||
|
|
||||||
@unittest.skipIf(OPJ_DATA_ROOT is None,
|
|
||||||
"OPJ_DATA_ROOT environment variable not set")
|
|
||||||
def test_channel_definition(self):
|
|
||||||
"""verify printing of cdef box"""
|
|
||||||
filename = opj_data_file('input/conformance/file2.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 = ['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)
|
|
||||||
|
|
||||||
@unittest.skipIf(OPJ_DATA_ROOT is None,
|
|
||||||
"OPJ_DATA_ROOT environment variable not set")
|
|
||||||
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)
|
|
||||||
|
|
||||||
@unittest.skipIf(OPJ_DATA_ROOT is None,
|
|
||||||
"OPJ_DATA_ROOT environment variable not set")
|
|
||||||
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)
|
|
||||||
|
|
||||||
@unittest.skip("file7 no longer has a rreq")
|
|
||||||
@unittest.skipIf(OPJ_DATA_ROOT is None,
|
|
||||||
"OPJ_DATA_ROOT environment variable not set")
|
|
||||||
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)
|
|
||||||
|
|
||||||
@unittest.skipIf(OPJ_DATA_ROOT is None,
|
|
||||||
"OPJ_DATA_ROOT environment variable not set")
|
|
||||||
def test_differing_subsamples(self):
|
|
||||||
"""verify printing of SIZ with different subsampling... Issue 86."""
|
|
||||||
filename = opj_data_file('input/conformance/p0_05.j2k')
|
|
||||||
j = glymur.Jp2k(filename)
|
|
||||||
codestream = j.get_codestream()
|
|
||||||
with patch('sys.stdout', new=StringIO()) as fake_out:
|
|
||||||
print(codestream.segment[1])
|
|
||||||
actual = fake_out.getvalue().strip()
|
|
||||||
lines = ['SIZ marker segment @ (2, 50)',
|
|
||||||
' Profile: 0',
|
|
||||||
' Reference Grid Height, Width: (1024 x 1024)',
|
|
||||||
' Vertical, Horizontal Reference Grid Offset: (0 x 0)',
|
|
||||||
' Reference Tile Height, Width: (1024 x 1024)',
|
|
||||||
' Vertical, Horizontal Reference Tile Offset: (0 x 0)',
|
|
||||||
' Bitdepth: (8, 8, 8, 8)',
|
|
||||||
' Signed: (False, False, False, False)',
|
|
||||||
' Vertical, Horizontal Subsampling: '
|
|
||||||
+ '((1, 1), (1, 1), (2, 2), (2, 2))']
|
|
||||||
expected = '\n'.join(lines)
|
|
||||||
self.assertEqual(actual, expected)
|
|
||||||
|
|
||||||
@unittest.skipIf(OPJ_DATA_ROOT is None,
|
|
||||||
"OPJ_DATA_ROOT environment variable not set")
|
|
||||||
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 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)
|
|
||||||
|
|
||||||
@unittest.skipIf(os.name == "nt", "Temporary file issue on window.")
|
@unittest.skipIf(os.name == "nt", "Temporary file issue on window.")
|
||||||
def test_less_common_boxes(self):
|
def test_less_common_boxes(self):
|
||||||
"""verify uinf, ulst, url, res, resd, resc box printing"""
|
"""verify uinf, ulst, url, res, resd, resc box printing"""
|
||||||
|
|
@ -861,50 +588,6 @@ class TestPrinting(unittest.TestCase):
|
||||||
expected = '\n'.join(lines)
|
expected = '\n'.join(lines)
|
||||||
self.assertEqual(actual, expected)
|
self.assertEqual(actual, expected)
|
||||||
|
|
||||||
@unittest.skipIf(OPJ_DATA_ROOT is None,
|
|
||||||
"OPJ_DATA_ROOT environment variable not set")
|
|
||||||
def test_icc_profile(self):
|
|
||||||
"""verify icc profile printing with a jpx"""
|
|
||||||
# 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():
|
|
||||||
# brand is 'jp2 ', but has any icc profile.
|
|
||||||
warnings.simplefilter("ignore")
|
|
||||||
jp2 = Jp2k(filename)
|
|
||||||
|
|
||||||
with patch('sys.stdout', new=StringIO()) as fake_out:
|
|
||||||
print(jp2.box[3].box[1])
|
|
||||||
actual = fake_out.getvalue().strip()
|
|
||||||
if sys.hexversion < 0x03000000:
|
|
||||||
expected = text_gbr_27
|
|
||||||
elif sys.hexversion < 0x03040000:
|
|
||||||
expected = text_gbr_33
|
|
||||||
else:
|
|
||||||
expected = text_gbr_34
|
|
||||||
|
|
||||||
self.assertEqual(actual, expected)
|
|
||||||
|
|
||||||
@unittest.skipIf(OPJ_DATA_ROOT is None,
|
|
||||||
"OPJ_DATA_ROOT environment variable not set")
|
|
||||||
def test_uuid(self):
|
|
||||||
"""verify printing of UUID box"""
|
|
||||||
filename = opj_data_file('input/nonregression/text_GBR.jp2')
|
|
||||||
with warnings.catch_warnings():
|
|
||||||
# brand is 'jp2 ', but has any icc profile.
|
|
||||||
warnings.simplefilter("ignore")
|
|
||||||
jp2 = Jp2k(filename)
|
|
||||||
|
|
||||||
with patch('sys.stdout', new=StringIO()) as fake_out:
|
|
||||||
print(jp2.box[4])
|
|
||||||
actual = fake_out.getvalue().strip()
|
|
||||||
lines = ['UUID Box (uuid) @ (1544, 25)',
|
|
||||||
' UUID: 3a0d0218-0ae9-4115-b376-4bca41ce0e71 (unknown)',
|
|
||||||
' UUID Data: 1 bytes']
|
|
||||||
|
|
||||||
expected = '\n'.join(lines)
|
|
||||||
self.assertEqual(actual, expected)
|
|
||||||
|
|
||||||
@unittest.skipIf(sys.hexversion < 0x03000000,
|
@unittest.skipIf(sys.hexversion < 0x03000000,
|
||||||
"Ordered dicts not printing well in 2.7")
|
"Ordered dicts not printing well in 2.7")
|
||||||
def test_exif_uuid(self):
|
def test_exif_uuid(self):
|
||||||
|
|
@ -946,5 +629,355 @@ class TestPrinting(unittest.TestCase):
|
||||||
self.assertEqual(actual, expected)
|
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.")
|
||||||
|
class TestPrintingOpjDataRoot(unittest.TestCase):
|
||||||
|
"""Tests for verifying printing. restricted to OPJ_DATA_ROOT files."""
|
||||||
|
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_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():
|
||||||
|
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')
|
||||||
|
j = glymur.Jp2k(filename)
|
||||||
|
codestream = j.get_codestream()
|
||||||
|
with patch('sys.stdout', new=StringIO()) as fake_out:
|
||||||
|
print(codestream.segment[-5])
|
||||||
|
actual = fake_out.getvalue().strip()
|
||||||
|
lines = ['CRG marker segment @ (87, 6)',
|
||||||
|
' Vertical, Horizontal offset: (0.50, 1.00)']
|
||||||
|
expected = '\n'.join(lines)
|
||||||
|
self.assertEqual(actual, expected)
|
||||||
|
|
||||||
|
def test_rgn(self):
|
||||||
|
"""verify printing of RGN segment"""
|
||||||
|
filename = opj_data_file('input/conformance/p0_03.j2k')
|
||||||
|
j = glymur.Jp2k(filename)
|
||||||
|
codestream = j.get_codestream(header_only=False)
|
||||||
|
with patch('sys.stdout', new=StringIO()) as fake_out:
|
||||||
|
print(codestream.segment[12])
|
||||||
|
actual = fake_out.getvalue().strip()
|
||||||
|
lines = ['RGN marker segment @ (310, 5)',
|
||||||
|
' Associated component: 0',
|
||||||
|
' ROI style: 0',
|
||||||
|
' Parameter: 7']
|
||||||
|
expected = '\n'.join(lines)
|
||||||
|
self.assertEqual(actual, expected)
|
||||||
|
|
||||||
|
def test_sop(self):
|
||||||
|
"""verify printing of SOP segment"""
|
||||||
|
filename = opj_data_file('input/conformance/p0_03.j2k')
|
||||||
|
j = glymur.Jp2k(filename)
|
||||||
|
codestream = j.get_codestream(header_only=False)
|
||||||
|
with patch('sys.stdout', new=StringIO()) as fake_out:
|
||||||
|
print(codestream.segment[-2])
|
||||||
|
actual = fake_out.getvalue().strip()
|
||||||
|
lines = ['SOP marker segment @ (12836, 4)',
|
||||||
|
' Nsop: 15']
|
||||||
|
expected = '\n'.join(lines)
|
||||||
|
self.assertEqual(actual, expected)
|
||||||
|
|
||||||
|
def test_cme(self):
|
||||||
|
"""Test printing a CME or comment marker segment."""
|
||||||
|
filename = opj_data_file('input/conformance/p0_02.j2k')
|
||||||
|
j = glymur.Jp2k(filename)
|
||||||
|
codestream = j.get_codestream()
|
||||||
|
# 2nd to last segment in the main header
|
||||||
|
with patch('sys.stdout', new=StringIO()) as fake_out:
|
||||||
|
print(codestream.segment[-2])
|
||||||
|
actual = fake_out.getvalue().strip()
|
||||||
|
lines = ['CME marker segment @ (85, 45)',
|
||||||
|
' "Creator: AV-J2K (c) 2000,2001 Algo Vision"']
|
||||||
|
expected = '\n'.join(lines)
|
||||||
|
self.assertEqual(actual, expected)
|
||||||
|
|
||||||
|
def test_plt_segment(self):
|
||||||
|
"""verify printing of PLT segment"""
|
||||||
|
filename = opj_data_file('input/conformance/p0_07.j2k')
|
||||||
|
j = glymur.Jp2k(filename)
|
||||||
|
codestream = j.get_codestream(header_only=False)
|
||||||
|
with patch('sys.stdout', new=StringIO()) as fake_out:
|
||||||
|
print(codestream.segment[49935])
|
||||||
|
actual = fake_out.getvalue().strip()
|
||||||
|
|
||||||
|
lines = ['PLT marker segment @ (7871146, 38)',
|
||||||
|
' Index: 0',
|
||||||
|
' Iplt: [9, 122, 19, 30, 27, 9, 41, 62, 18, 29, 261,'
|
||||||
|
+ ' 55, 82, 299, 93, 941, 951, 687, 1729, 1443, 1008, 2168,'
|
||||||
|
+ ' 2188, 2223]']
|
||||||
|
expected = '\n'.join(lines)
|
||||||
|
self.assertEqual(actual, expected)
|
||||||
|
|
||||||
|
def test_pod_segment(self):
|
||||||
|
"""verify printing of POD segment"""
|
||||||
|
filename = opj_data_file('input/conformance/p0_13.j2k')
|
||||||
|
j = glymur.Jp2k(filename)
|
||||||
|
codestream = j.get_codestream()
|
||||||
|
with patch('sys.stdout', new=StringIO()) as fake_out:
|
||||||
|
print(codestream.segment[8])
|
||||||
|
actual = fake_out.getvalue().strip()
|
||||||
|
|
||||||
|
lines = ['POD marker segment @ (878, 20)',
|
||||||
|
' Progression change 0:',
|
||||||
|
' Resolution index start: 0',
|
||||||
|
' Component index start: 0',
|
||||||
|
' Layer index end: 1',
|
||||||
|
' Resolution index end: 33',
|
||||||
|
' Component index end: 128',
|
||||||
|
' Progression order: RLCP',
|
||||||
|
' Progression change 1:',
|
||||||
|
' Resolution index start: 0',
|
||||||
|
' Component index start: 128',
|
||||||
|
' Layer index end: 1',
|
||||||
|
' Resolution index end: 33',
|
||||||
|
' Component index end: 257',
|
||||||
|
' Progression order: CPRL']
|
||||||
|
|
||||||
|
expected = '\n'.join(lines)
|
||||||
|
self.assertEqual(actual, expected)
|
||||||
|
|
||||||
|
def test_ppm_segment(self):
|
||||||
|
"""verify printing of PPM segment"""
|
||||||
|
filename = opj_data_file('input/conformance/p1_03.j2k')
|
||||||
|
j = glymur.Jp2k(filename)
|
||||||
|
codestream = j.get_codestream()
|
||||||
|
with patch('sys.stdout', new=StringIO()) as fake_out:
|
||||||
|
print(codestream.segment[9])
|
||||||
|
actual = fake_out.getvalue().strip()
|
||||||
|
|
||||||
|
lines = ['PPM marker segment @ (213, 43712)',
|
||||||
|
' Index: 0',
|
||||||
|
' Data: 43709 uninterpreted bytes']
|
||||||
|
|
||||||
|
expected = '\n'.join(lines)
|
||||||
|
self.assertEqual(actual, expected)
|
||||||
|
|
||||||
|
def test_ppt_segment(self):
|
||||||
|
"""verify printing of ppt segment"""
|
||||||
|
filename = opj_data_file('input/conformance/p1_06.j2k')
|
||||||
|
j = glymur.Jp2k(filename)
|
||||||
|
codestream = j.get_codestream(header_only=False)
|
||||||
|
with patch('sys.stdout', new=StringIO()) as fake_out:
|
||||||
|
print(codestream.segment[6])
|
||||||
|
actual = fake_out.getvalue().strip()
|
||||||
|
|
||||||
|
lines = ['PPT marker segment @ (155, 109)',
|
||||||
|
' Index: 0',
|
||||||
|
' Packet headers: 106 uninterpreted bytes']
|
||||||
|
|
||||||
|
expected = '\n'.join(lines)
|
||||||
|
self.assertEqual(actual, expected)
|
||||||
|
|
||||||
|
def test_tlm_segment(self):
|
||||||
|
"""verify printing of TLM segment"""
|
||||||
|
filename = opj_data_file('input/conformance/p0_15.j2k')
|
||||||
|
j = glymur.Jp2k(filename)
|
||||||
|
codestream = j.get_codestream()
|
||||||
|
with patch('sys.stdout', new=StringIO()) as fake_out:
|
||||||
|
print(codestream.segment[10])
|
||||||
|
actual = fake_out.getvalue().strip()
|
||||||
|
|
||||||
|
lines = ['TLM marker segment @ (268, 28)',
|
||||||
|
' Index: 0',
|
||||||
|
' Tile number: (0, 1, 2, 3)',
|
||||||
|
' Length: (4267, 2117, 4080, 2081)']
|
||||||
|
|
||||||
|
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')
|
||||||
|
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_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)
|
||||||
|
|
||||||
|
@unittest.skip("file7 no longer has a rreq")
|
||||||
|
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')
|
||||||
|
j = glymur.Jp2k(filename)
|
||||||
|
codestream = j.get_codestream()
|
||||||
|
with patch('sys.stdout', new=StringIO()) as fake_out:
|
||||||
|
print(codestream.segment[1])
|
||||||
|
actual = fake_out.getvalue().strip()
|
||||||
|
lines = ['SIZ marker segment @ (2, 50)',
|
||||||
|
' Profile: 0',
|
||||||
|
' Reference Grid Height, Width: (1024 x 1024)',
|
||||||
|
' Vertical, Horizontal Reference Grid Offset: (0 x 0)',
|
||||||
|
' Reference Tile Height, Width: (1024 x 1024)',
|
||||||
|
' Vertical, Horizontal Reference Tile Offset: (0 x 0)',
|
||||||
|
' Bitdepth: (8, 8, 8, 8)',
|
||||||
|
' Signed: (False, False, False, False)',
|
||||||
|
' Vertical, Horizontal Subsampling: '
|
||||||
|
+ '((1, 1), (1, 1), (2, 2), (2, 2))']
|
||||||
|
expected = '\n'.join(lines)
|
||||||
|
self.assertEqual(actual, expected)
|
||||||
|
|
||||||
|
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 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_icc_profile(self):
|
||||||
|
"""verify icc profile printing with a jpx"""
|
||||||
|
# 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():
|
||||||
|
# brand is 'jp2 ', but has any icc profile.
|
||||||
|
warnings.simplefilter("ignore")
|
||||||
|
jp2 = Jp2k(filename)
|
||||||
|
|
||||||
|
with patch('sys.stdout', new=StringIO()) as fake_out:
|
||||||
|
print(jp2.box[3].box[1])
|
||||||
|
actual = fake_out.getvalue().strip()
|
||||||
|
if sys.hexversion < 0x03000000:
|
||||||
|
expected = text_gbr_27
|
||||||
|
elif sys.hexversion < 0x03040000:
|
||||||
|
expected = text_gbr_33
|
||||||
|
else:
|
||||||
|
expected = text_gbr_34
|
||||||
|
|
||||||
|
self.assertEqual(actual, expected)
|
||||||
|
|
||||||
|
def test_uuid(self):
|
||||||
|
"""verify printing of UUID box"""
|
||||||
|
filename = opj_data_file('input/nonregression/text_GBR.jp2')
|
||||||
|
with warnings.catch_warnings():
|
||||||
|
# brand is 'jp2 ', but has any icc profile.
|
||||||
|
warnings.simplefilter("ignore")
|
||||||
|
jp2 = Jp2k(filename)
|
||||||
|
|
||||||
|
with patch('sys.stdout', new=StringIO()) as fake_out:
|
||||||
|
print(jp2.box[4])
|
||||||
|
actual = fake_out.getvalue().strip()
|
||||||
|
lines = ['UUID Box (uuid) @ (1544, 25)',
|
||||||
|
' UUID: 3a0d0218-0ae9-4115-b376-4bca41ce0e71 (unknown)',
|
||||||
|
' UUID Data: 1 bytes']
|
||||||
|
|
||||||
|
expected = '\n'.join(lines)
|
||||||
|
self.assertEqual(actual, expected)
|
||||||
|
|
||||||
|
def test_issue182(self):
|
||||||
|
"""Should not show the format string in output."""
|
||||||
|
# The cmap box is wildly broken, but printing was still wrong.
|
||||||
|
# Format strings like %d were showing up in the output.
|
||||||
|
filename = opj_data_file('input/nonregression/mem-b2ace68c-1381.jp2')
|
||||||
|
|
||||||
|
with warnings.catch_warnings():
|
||||||
|
# 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])
|
||||||
|
actual = fake_out.getvalue().strip()
|
||||||
|
self.assertEqual(actual, fixtures.issue_182_cmap)
|
||||||
|
|
||||||
|
def test_issue183(self):
|
||||||
|
filename = opj_data_file('input/nonregression/orb-blue10-lin-jp2.jp2')
|
||||||
|
|
||||||
|
with warnings.catch_warnings():
|
||||||
|
# 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])
|
||||||
|
actual = fake_out.getvalue().strip()
|
||||||
|
self.assertEqual(actual, fixtures.issue_183_colr)
|
||||||
|
|
||||||
|
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():
|
||||||
|
warnings.simplefilter("ignore")
|
||||||
|
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.
|
||||||
|
print(jp2)
|
||||||
|
|
||||||
|
self.assertTrue(True)
|
||||||
|
|
||||||
if __name__ == "__main__":
|
if __name__ == "__main__":
|
||||||
unittest.main()
|
unittest.main()
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue