Merge branch 'issue71' into devel

This commit is contained in:
jevans 2013-07-09 20:23:27 -04:00
commit 37cf486719
21 changed files with 4945 additions and 4871 deletions

View file

@ -6,13 +6,13 @@ How do I...?
Read the lowest resolution thumbnail? Read the lowest resolution thumbnail?
===================================== =====================================
Printing the Jp2k object should reveal the number of resolutions (look in the Printing the Jp2k object should reveal the number of resolutions (look in the
COD segment section), but you can take a shortcut by supplying -1 as the reduce COD segment section), but you can take a shortcut by supplying -1 as the
level. :: resolution level. ::
>>> import glymur >>> import glymur
>>> file = glymur.data.nemo() >>> file = glymur.data.nemo()
>>> j = glymur.Jp2k(file) >>> j = glymur.Jp2k(file)
>>> thumbnail = j.read(reduce=-1) >>> thumbnail = j.read(rlevel=-1)
Display metadata? Display metadata?
================= =================

File diff suppressed because it is too large Load diff

View file

@ -1,3 +1,5 @@
"""Core definitions to be shared amongst the modules.
"""
# Progression order # Progression order
LRCP = 0 LRCP = 0
RLCP = 1 RLCP = 1
@ -5,44 +7,21 @@ RPCL = 2
PCRL = 3 PCRL = 3
CPRL = 4 CPRL = 4
_progression_order_display = { PROGRESSION_ORDER = {
LRCP: 'LRCP',
RLCP: 'RLCP',
RPCL: 'RPCL',
PCRL: 'PCRL',
CPRL: 'CPRL'}
progression_order = {
'LRCP': LRCP, 'LRCP': LRCP,
'RLCP': RLCP, 'RLCP': RLCP,
'RPCL': RPCL, 'RPCL': RPCL,
'PCRL': PCRL, 'PCRL': PCRL,
'CPRL': CPRL} 'CPRL': CPRL}
WAVELET_TRANSFORM_9x7_IRREVERSIBLE = 0 WAVELET_XFORM_9X7_IRREVERSIBLE = 0
WAVELET_TRANSFORM_5x3_REVERSIBLE = 1 WAVELET_XFORM_5X3_REVERSIBLE = 1
_wavelet_transform_display = {
WAVELET_TRANSFORM_9x7_IRREVERSIBLE: '9-7 irreversible',
WAVELET_TRANSFORM_5x3_REVERSIBLE: '5-3 reversible'}
ENUMERATED_COLORSPACE = 1 ENUMERATED_COLORSPACE = 1
RESTRICTED_ICC_PROFILE = 2 RESTRICTED_ICC_PROFILE = 2
ANY_ICC_PROFILE = 3 ANY_ICC_PROFILE = 3
VENDOR_COLOR_METHOD = 4 VENDOR_COLOR_METHOD = 4
_method_display = {
ENUMERATED_COLORSPACE: 'enumerated colorspace',
RESTRICTED_ICC_PROFILE: 'restricted ICC profile',
ANY_ICC_PROFILE: 'any ICC profile',
VENDOR_COLOR_METHOD: 'vendor color method'}
_ = {1: 'accurately represents correct colorspace definition',
2: 'approximates correct colorspace definition, exceptional quality',
3: 'approximates correct colorspace definition, reasonable quality',
4: 'approximates correct colorspace definition, poor quality'}
_approximation_display = _
# Registration values for comment markers. # Registration values for comment markers.
RCME_BINARY = 0 # binary value comments RCME_BINARY = 0 # binary value comments
RCME_ISO_8859_1 = 1 # comments in latin-1 codec RCME_ISO_8859_1 = 1 # comments in latin-1 codec
@ -55,7 +34,7 @@ YCC = 18
E_SRGB = 20 E_SRGB = 20
ROMM_RGB = 21 ROMM_RGB = 21
_colorspace_map_display = { _COLORSPACE_MAP_DISPLAY = {
CMYK: 'CMYK', CMYK: 'CMYK',
SRGB: 'sRGB', SRGB: 'sRGB',
GREYSCALE: 'greyscale', GREYSCALE: 'greyscale',
@ -68,7 +47,7 @@ _COLOR = 0
_OPACITY = 1 _OPACITY = 1
_PRE_MULTIPLIED_OPACITY = 2 _PRE_MULTIPLIED_OPACITY = 2
_UNSPECIFIED = 65535 _UNSPECIFIED = 65535
_color_type_map_display = { _COLOR_TYPE_MAP_DISPLAY = {
_COLOR: 'color', _COLOR: 'color',
_OPACITY: 'opacity', _OPACITY: 'opacity',
_PRE_MULTIPLIED_OPACITY: 'pre-multiplied opacity', _PRE_MULTIPLIED_OPACITY: 'pre-multiplied opacity',
@ -81,108 +60,15 @@ BLUE = 3
GREY = 1 GREY = 1
# enumerated color channel associations # enumerated color channel associations
_rgb_colorspace = {"R": 1, "G": 2, "B": 3} _COLORSPACE = {SRGB: {"R": 1, "G": 2, "B": 3},
_greyscale_colorspace = {"Y": 1} GREYSCALE: {"Y": 1},
_ycbcr_colorspace = {"Y": 1, "Cb": 2, "Cr": 3} YCC: {"Y": 1, "Cb": 2, "Cr": 3},
_colorspace = {SRGB: _rgb_colorspace, E_SRGB: {"R": 1, "G": 2, "B": 3},
GREYSCALE: _greyscale_colorspace, ROMM_RGB: {"R": 1, "G": 2, "B": 3}}
YCC: _ycbcr_colorspace,
E_SRGB: _rgb_colorspace,
ROMM_RGB: _rgb_colorspace}
# How to display the codestream profile. # How to display the codestream profile.
_capabilities_display = { _CAPABILITIES_DISPLAY = {
0: '2', 0: '2',
1: '0', 1: '0',
2: '1', 2: '1',
3: '3'} 3: '3'}
# Reader requirements
#RREQ_UNRESTRICTED_JPEG2000_PART_1 = 5
#RREQ_UNRESTRICTED_JPEG2000_PART_2 = 6
#RREQ_CMYK_ENUMERATED_COLORSPACE = 55
#RREQ_E_SRGB_ENUMERATED_COLORSPACE = 60
#RREQ_ROMM_RGB_ENUMERATED_COLORSPACE = 61
_reader_requirements_display = {
0: 'File not completely understood',
1: 'Deprecated',
2: 'Contains multiple composition layers',
3: 'Deprecated',
4: 'JPEG 2000 Part 1 Profile 1 codestream',
5: 'Unrestricted JPEG 2000 Part 1 codestream, ITU-T Rec. T.800 '
+ '| ISO/IEC 15444-1',
6: 'Unrestricted JPEG 2000 Part 2 codestream',
7: 'JPEG codestream as defined in ISO/IEC 10918-1',
8: 'Deprecated',
9: 'Non-premultiplied opacity channel',
10: 'Premultiplied opacity channel',
11: 'Chroma-key based opacity',
12: 'Deprecated',
13: 'Fragmented codestream where all fragments are in file and in order',
14: 'Fragmented codestream where all fragments are in file '
+ 'but are out of order',
15: 'Fragmented codestream where not all fragments are within the file '
+ 'but are all in locally accessible files',
16: 'Fragmented codestream where some fragments may be accessible '
+ 'only through a URL specified network connection',
17: 'Compositing required to produce rendered result from multiple '
+ 'compositing layers',
18: 'Deprecated',
19: 'Deprecated',
20: 'Deprecated',
21: 'At least one compositing layer consists of multiple codestreams',
22: 'Deprecated',
23: 'Colourspace transformations are required to combine compositing '
+ 'layers; not all compositing layers are in the same colourspace',
24: 'Deprecated',
25: 'Deprecated',
26: 'First animation layer does not cover entire rendered result',
27: 'Deprecated',
28: 'Reuse of animation layers',
29: 'Deprecated',
30: 'Some animated frames are non-persistent',
31: 'Deprecated',
32: 'Rendered result involves scaling within a layer',
33: 'Rendered result involves scaling between layers',
34: 'ROI metadata',
35: 'IPR metadata',
36: 'Content metadata',
37: 'History metadata',
38: 'Creation metadata',
39: 'JPX digital signatures',
40: 'JPX checksums',
41: 'Desires Graphics Arts Reproduction specified',
42: 'Deprecated',
43: '(Deprecated) compositing layer uses restricted ICC profile',
44: 'Compositing layer uses Any ICC profile',
45: 'Deprecated',
46: 'Deprecated',
47: 'BiLevel 1 enumerated colourspace',
48: 'BiLevel 2 enumerated colourspace',
49: 'YCbCr 1 enumerated colourspace',
50: 'YCbCr 2 enumerated colourspace',
51: 'YCbCr 3 enumerated colourspace',
52: 'PhotoYCC enumerated colourspace',
53: 'YCCK enumerated colourspace',
54: 'CMY enumerated colourspace',
55: 'CMYK enumerated colorspace',
56: 'CIELab enumerated colourspace with default parameters',
57: 'CIELab enumerated colourspace with non-default parameters',
58: 'CIEJab enumerated colourspace with default parameters',
59: 'CIEJab enumerated colourspace with non-default parameters',
60: 'e-sRGB enumerated colorspace',
61: 'ROMM_RGB enumerated colorspace',
62: 'Non-square samples',
63: 'Deprecated',
64: 'Deprecated',
65: 'Deprecated',
66: 'Deprecated',
67: 'GIS metadata XML box',
68: 'JPSEC extensions in codestream as specified by ISO/IEC 15444-8',
69: 'JP3D extensions in codestream as specified by ISO/IEC 15444-10',
70: 'Deprecated',
71: 'e-sYCC enumerated colourspace',
72: 'JPEG 2000 Part 2 codestream as restricted by baseline conformance '
+ 'requirements in M.9.2.3',
73: 'YPbPr(1125/60) enumerated colourspace',
74: 'YPbPr(1250/50) enumerated colourspace'}

File diff suppressed because it is too large Load diff

View file

@ -2,6 +2,9 @@
License: MIT License: MIT
""" """
# pylint: disable=C0302
import sys import sys
if sys.hexversion >= 0x03030000: if sys.hexversion >= 0x03030000:
from contextlib import ExitStack from contextlib import ExitStack
@ -16,15 +19,23 @@ import warnings
import numpy as np import numpy as np
from .codestream import Codestream from .codestream import Codestream
from .core import * from .core import SRGB
from .jp2box import * from .core import GREYSCALE
from .lib import openjpeg as opj from .core import PROGRESSION_ORDER
from .lib import openjp2 as opj2 from .jp2box import Jp2kBox
from .jp2box import JPEG2000SignatureBox
from .jp2box import FileTypeBox
from .jp2box import JP2HeaderBox
from .jp2box import ContiguousCodestreamBox
from .jp2box import ImageHeaderBox
from .jp2box import ColourSpecificationBox
from .lib import _openjpeg as _opj
from .lib import _openjp2 as _opj2
_cspace_map = {'rgb': opj2._CLRSPC_SRGB, _COLORSPACE_MAP = {'rgb': _opj2.CLRSPC_SRGB,
'gray': opj2._CLRSPC_GRAY, 'gray': _opj2.CLRSPC_GRAY,
'grey': opj2._CLRSPC_GRAY, 'grey': _opj2.CLRSPC_GRAY,
'ycc': opj2._CLRSPC_YCC} 'ycc': _opj2.CLRSPC_YCC}
# Setup the default callback handlers. See the callback functions subsection # Setup the default callback handlers. See the callback functions subsection
# in the ctypes section of the Python documentation for a solid explanation of # in the ctypes section of the Python documentation for a solid explanation of
@ -32,23 +43,26 @@ _cspace_map = {'rgb': opj2._CLRSPC_SRGB,
_CMPFUNC = ctypes.CFUNCTYPE(ctypes.c_void_p, ctypes.c_char_p, ctypes.c_void_p) _CMPFUNC = ctypes.CFUNCTYPE(ctypes.c_void_p, ctypes.c_char_p, ctypes.c_void_p)
def _default_error_handler(msg, client_data): def _default_error_handler(msg, _):
"""Default error handler callback for openjpeg library."""
msg = "OpenJPEG library error: {0}".format(msg.decode('utf-8').rstrip()) msg = "OpenJPEG library error: {0}".format(msg.decode('utf-8').rstrip())
opj2._set_error_message(msg) _opj2.set_error_message(msg)
def _default_info_handler(msg, client_data): def _default_info_handler(msg, _):
"""Default info handler callback for openjpeg library."""
print("[INFO] {0}".format(msg.decode('utf-8').rstrip())) print("[INFO] {0}".format(msg.decode('utf-8').rstrip()))
def _default_warning_handler(library_msg, client_data): def _default_warning_handler(library_msg, _):
"""Default warning handler callback for openjpeg library."""
library_msg = library_msg.decode('utf-8').rstrip() library_msg = library_msg.decode('utf-8').rstrip()
msg = "OpenJPEG library warning: {0}".format(library_msg) msg = "OpenJPEG library warning: {0}".format(library_msg)
warnings.warn(msg) warnings.warn(msg)
_error_callback = _CMPFUNC(_default_error_handler) _ERROR_CALLBACK = _CMPFUNC(_default_error_handler)
_info_callback = _CMPFUNC(_default_info_handler) _INFO_CALLBACK = _CMPFUNC(_default_info_handler)
_warning_callback = _CMPFUNC(_default_warning_handler) _WARNING_CALLBACK = _CMPFUNC(_default_warning_handler)
class Jp2k(Jp2kBox): class Jp2k(Jp2kBox):
@ -75,10 +89,12 @@ class Jp2k(Jp2kBox):
mode : str, optional mode : str, optional
The mode used to open the file. The mode used to open the file.
""" """
Jp2kBox.__init__(self)
self.filename = filename self.filename = filename
self.mode = mode self.mode = mode
self.box = [] self.box = []
self.offset = 0 self._codec_format = None
self._file_size = 0
# Parse the file for JP2/JPX contents only if we are reading it. # Parse the file for JP2/JPX contents only if we are reading it.
if mode == 'rb': if mode == 'rb':
@ -90,8 +106,8 @@ class Jp2k(Jp2kBox):
for box in self.box: for box in self.box:
metadata.append(str(box)) metadata.append(str(box))
else: else:
c = self.get_codestream() codestream = self.get_codestream()
metadata.append(str(c)) metadata.append(str(codestream))
return '\n'.join(metadata) return '\n'.join(metadata)
def _parse(self): def _parse(self):
@ -106,39 +122,41 @@ class Jp2k(Jp2kBox):
self.length = stat.st_size self.length = stat.st_size
self._file_size = stat.st_size self._file_size = stat.st_size
with open(self.filename, 'rb') as f: with open(self.filename, 'rb') as fptr:
# Make sure we have a JPEG2000 file. It could be either JP2 or # Make sure we have a JPEG2000 file. It could be either JP2 or
# J2C. Check for J2C first, single box in that case. # J2C. Check for J2C first, single box in that case.
buffer = f.read(2) read_buffer = fptr.read(2)
signature, = struct.unpack('>H', buffer) signature, = struct.unpack('>H', read_buffer)
if signature == 0xff4f: if signature == 0xff4f:
self._codec_format = opj2._CODEC_J2K self._codec_format = _opj2.CODEC_J2K
# That's it, we're done. The codestream object is only # That's it, we're done. The codestream object is only
# produced upon explicit request. # produced upon explicit request.
return return
self._codec_format = opj2._CODEC_JP2 self._codec_format = _opj2.CODEC_JP2
# Should be JP2. # Should be JP2.
# First 4 bytes should be 12, the length of the 'jP ' box. # First 4 bytes should be 12, the length of the 'jP ' box.
# 2nd 4 bytes should be the box ID ('jP '). # 2nd 4 bytes should be the box ID ('jP ').
# 3rd 4 bytes should be the box signature (13, 10, 135, 10). # 3rd 4 bytes should be the box signature (13, 10, 135, 10).
f.seek(0) fptr.seek(0)
buffer = f.read(12) read_buffer = fptr.read(12)
values = struct.unpack('>I4s4B', buffer) values = struct.unpack('>I4s4B', read_buffer)
L = values[0] box_length = values[0]
T = values[1] box_id = values[1]
signature = values[2:] signature = values[2:]
if L != 12 or T != b'jP ' or signature != (13, 10, 135, 10): if (((box_length != 12) or (box_id != b'jP ') or
(signature != (13, 10, 135, 10)))):
msg = '{0} is not a JPEG 2000 file.'.format(self.filename) msg = '{0} is not a JPEG 2000 file.'.format(self.filename)
raise IOError(msg) raise IOError(msg)
# Back up and start again, we know we have a superbox (box of # Back up and start again, we know we have a superbox (box of
# boxes) here. # boxes) here.
f.seek(0) fptr.seek(0)
self.box = self._parse_superbox(f) self.box = self.parse_superbox(fptr)
# pylint: disable-msg=W0221
def write(self, img_array, cratios=None, eph=False, psnr=None, numres=None, def write(self, img_array, cratios=None, eph=False, psnr=None, numres=None,
cbsize=None, psizes=None, grid_offset=None, sop=False, cbsize=None, psizes=None, grid_offset=None, sop=False,
subsam=None, tilesize=None, prog=None, modesw=None, subsam=None, tilesize=None, prog=None, modesw=None,
@ -203,24 +221,24 @@ class Jp2k(Jp2kBox):
>>> import glymur >>> import glymur
>>> jfile = glymur.data.nemo() >>> jfile = glymur.data.nemo()
>>> jp2 = glymur.Jp2k(jfile) >>> jp2 = glymur.Jp2k(jfile)
>>> data = jp2.read(reduce=1) >>> data = jp2.read(rlevel=1)
>>> from tempfile import NamedTemporaryFile >>> from tempfile import NamedTemporaryFile
>>> tfile = NamedTemporaryFile(suffix='.jp2', delete=False) >>> tfile = NamedTemporaryFile(suffix='.jp2', delete=False)
>>> j = Jp2k(tfile.name, mode='wb') >>> j = Jp2k(tfile.name, mode='wb')
>>> j.write(data.astype(np.uint8)) >>> j.write(data.astype(np.uint8))
""" """
cparams = opj2._set_default_encoder_parameters() cparams = _opj2.set_default_encoder_parameters()
outfile = self.filename.encode() outfile = self.filename.encode()
n = opj2._PATH_LEN - len(outfile) num_pad_bytes = _opj2.PATH_LEN - len(outfile)
outfile += b'0' * n outfile += b'0' * num_pad_bytes
cparams.outfile = outfile cparams.outfile = outfile
if self.filename[-4:].lower() == '.jp2': if self.filename[-4:].lower() == '.jp2':
codec_fmt = opj2._CODEC_JP2 codec_fmt = _opj2.CODEC_JP2
else: else:
codec_fmt = opj2._CODEC_J2K codec_fmt = _opj2.CODEC_J2K
cparams.cod_format = codec_fmt cparams.cod_format = codec_fmt
@ -230,19 +248,19 @@ class Jp2k(Jp2kBox):
cparams.cp_disto_alloc = 1 cparams.cp_disto_alloc = 1
if cbsize is not None: if cbsize is not None:
w = cbsize[1] width = cbsize[1]
h = cbsize[0] height = cbsize[0]
if h * w > 4096 or h < 4 or w < 4: if height * width > 4096 or height < 4 or width < 4:
msg = "Code block area cannot exceed 4096. " msg = "Code block area cannot exceed 4096. "
msg += "Code block height and width must be larger than 4." msg += "Code block height and width must be larger than 4."
raise RuntimeError(msg) raise RuntimeError(msg)
if ((math.log(h, 2) != math.floor(math.log(h, 2)) or if ((math.log(height, 2) != math.floor(math.log(height, 2)) or
math.log(w, 2) != math.floor(math.log(w, 2)))): math.log(width, 2) != math.floor(math.log(width, 2)))):
msg = "Bad code block size ({0}, {1}), " msg = "Bad code block size ({0}, {1}), "
msg += "must be powers of 2." msg += "must be powers of 2."
raise IOError(msg.format(h, w)) raise IOError(msg.format(height, width))
cparams.cblockw_init = w cparams.cblockw_init = width
cparams.cblockh_init = h cparams.cblockh_init = height
if cratios is not None: if cratios is not None:
cparams.tcp_numlayers = len(cratios) cparams.tcp_numlayers = len(cratios)
@ -258,16 +276,17 @@ class Jp2k(Jp2kBox):
cparams.image_offset_y0 = grid_offset[0] cparams.image_offset_y0 = grid_offset[0]
if modesw is not None: if modesw is not None:
for x in range(6): for shift in range(6):
if modesw & (1 << x): power_of_two = 1 << shift
cparams.mode |= (1 << x) if modesw & power_of_two:
cparams.mode |= power_of_two
if numres is not None: if numres is not None:
cparams.numresolution = numres cparams.numresolution = numres
if prog is not None: if prog is not None:
prog = prog.upper() prog = prog.upper()
cparams.prog_order = progression_order[prog] cparams.prog_order = PROGRESSION_ORDER[prog]
if psnr is not None: if psnr is not None:
cparams.tcp_numlayers = len(psnr) cparams.tcp_numlayers = len(psnr)
@ -304,7 +323,7 @@ class Jp2k(Jp2kBox):
if tilesize is not None: if tilesize is not None:
cparams.cp_tdx = tilesize[1] cparams.cp_tdx = tilesize[1]
cparams.cp_tdy = tilesize[0] cparams.cp_tdy = tilesize[0]
cparams.tile_size_on = opj2._TRUE cparams.tile_size_on = _opj2.TRUE
if cratios is not None and psnr is not None: if cratios is not None and psnr is not None:
msg = "Cannot specify cratios and psnr together." msg = "Cannot specify cratios and psnr together."
@ -323,12 +342,12 @@ class Jp2k(Jp2kBox):
if colorspace is None: if colorspace is None:
if img_array.shape[2] == 1 or img_array.shape[2] == 2: if img_array.shape[2] == 1 or img_array.shape[2] == 2:
colorspace = opj2._CLRSPC_GRAY colorspace = _opj2.CLRSPC_GRAY
else: else:
# No YCC unless specifically told to do so. # No YCC unless specifically told to do so.
colorspace = opj2._CLRSPC_SRGB colorspace = _opj2.CLRSPC_SRGB
else: else:
if codec_fmt == opj2._CODEC_J2K: if codec_fmt == _opj2.CODEC_J2K:
raise IOError('Do not specify a colorspace with J2K.') raise IOError('Do not specify a colorspace with J2K.')
colorspace = colorspace.lower() colorspace = colorspace.lower()
if colorspace not in ('rgb', 'grey', 'gray'): if colorspace not in ('rgb', 'grey', 'gray'):
@ -338,15 +357,15 @@ class Jp2k(Jp2kBox):
msg = 'RGB colorspace requires at least 3 components.' msg = 'RGB colorspace requires at least 3 components.'
raise IOError(msg) raise IOError(msg)
else: else:
colorspace = _cspace_map[colorspace] colorspace = _COLORSPACE_MAP[colorspace]
if mct is None: if mct is None:
if colorspace == opj2._CLRSPC_SRGB: if colorspace == _opj2.CLRSPC_SRGB:
cparams.tcp_mct = 1 cparams.tcp_mct = 1
else: else:
cparams.tcp_mct = 0 cparams.tcp_mct = 0
else: else:
if mct and colorspace == opj2._CLRSPC_GRAY: if mct and colorspace == _opj2.CLRSPC_GRAY:
msg = "Cannot specify usage of the multi component transform " msg = "Cannot specify usage of the multi component transform "
msg += "if the colorspace is gray." msg += "if the colorspace is gray."
raise IOError(msg) raise IOError(msg)
@ -359,7 +378,7 @@ class Jp2k(Jp2kBox):
else: else:
raise RuntimeError("unhandled datatype") raise RuntimeError("unhandled datatype")
comptparms = (opj2._image_comptparm_t * num_comps)() comptparms = (_opj2.ImageComptParmType * num_comps)()
for j in range(num_comps): for j in range(num_comps):
comptparms[j].dx = cparams.subsampling_dx comptparms[j].dx = cparams.subsampling_dx
comptparms[j].dy = cparams.subsampling_dy comptparms[j].dy = cparams.subsampling_dy
@ -371,7 +390,7 @@ class Jp2k(Jp2kBox):
comptparms[j].bpp = comp_prec comptparms[j].bpp = comp_prec
comptparms[j].sgnd = 0 comptparms[j].sgnd = 0
image = opj2._image_create(comptparms, colorspace) image = _opj2.image_create(comptparms, colorspace)
# set image offset and reference grid # set image offset and reference grid
image.contents.x0 = cparams.image_offset_x0 image.contents.x0 = cparams.image_offset_x0
@ -388,23 +407,23 @@ class Jp2k(Jp2kBox):
src = layer.ctypes.data src = layer.ctypes.data
ctypes.memmove(dest, src, layer.nbytes) ctypes.memmove(dest, src, layer.nbytes)
codec = opj2._create_compress(codec_fmt) codec = _opj2.create_compress(codec_fmt)
if verbose: if verbose:
opj2._set_info_handler(codec, _info_callback) _opj2.set_info_handler(codec, _INFO_CALLBACK)
else: else:
opj2._set_info_handler(codec, None) _opj2.set_info_handler(codec, None)
opj2._set_warning_handler(codec, _warning_callback) _opj2.set_warning_handler(codec, _WARNING_CALLBACK)
opj2._set_error_handler(codec, _error_callback) _opj2.set_error_handler(codec, _ERROR_CALLBACK)
opj2._setup_encoder(codec, cparams, image) _opj2.setup_encoder(codec, cparams, image)
strm = opj2._stream_create_default_file_stream_v3(self.filename, False) strm = _opj2.stream_create_default_file_stream_v3(self.filename, False)
opj2._start_compress(codec, image, strm) _opj2.start_compress(codec, image, strm)
opj2._encode(codec, strm) _opj2.encode(codec, strm)
opj2._end_compress(codec, strm) _opj2.end_compress(codec, strm)
opj2._stream_destroy_v3(strm) _opj2.stream_destroy_v3(strm)
opj2._destroy_codec(codec) _opj2.destroy_codec(codec)
opj2._image_destroy(image) _opj2.image_destroy(image)
self._parse() self._parse()
@ -439,10 +458,10 @@ class Jp2k(Jp2kBox):
FileTypeBox(), FileTypeBox(),
JP2HeaderBox(), JP2HeaderBox(),
ContiguousCodestreamBox()] ContiguousCodestreamBox()]
c = self.get_codestream() codestream = self.get_codestream()
height = c.segment[1].Ysiz height = codestream.segment[1].ysiz
width = c.segment[1].Xsiz width = codestream.segment[1].xsiz
num_components = len(c.segment[1].XRsiz) num_components = len(codestream.segment[1].xrsiz)
boxes[2].box = [ImageHeaderBox(height=height, boxes[2].box = [ImageHeaderBox(height=height,
width=width, width=width,
num_components=num_components), num_components=num_components),
@ -450,15 +469,17 @@ class Jp2k(Jp2kBox):
# Check for a bad sequence of boxes. # Check for a bad sequence of boxes.
# 1st two boxes must be 'jP ' and 'ftyp' # 1st two boxes must be 'jP ' and 'ftyp'
if boxes[0].id != 'jP ' or boxes[1].id != 'ftyp': if boxes[0].box_id != 'jP ' or boxes[1].box_id != 'ftyp':
msg = "The first box must be the signature box and the second " msg = "The first box must be the signature box and the second "
msg += "must be the file type box." msg += "must be the file type box."
raise IOError(msg) raise IOError(msg)
# jp2c must be preceeded by jp2h # jp2c must be preceeded by jp2h
jp2h_lst = [idx for (idx, box) in enumerate(boxes) if box.id == 'jp2h'] jp2h_lst = [idx for (idx, box) in enumerate(boxes)
if box.box_id == 'jp2h']
jp2h_idx = jp2h_lst[0] jp2h_idx = jp2h_lst[0]
jp2c_lst = [idx for (idx, box) in enumerate(boxes) if box.id == 'jp2c'] jp2c_lst = [idx for (idx, box) in enumerate(boxes)
if box.box_id == 'jp2c']
if len(jp2c_lst) == 0: if len(jp2c_lst) == 0:
msg = "A codestream box must be defined in the outermost " msg = "A codestream box must be defined in the outermost "
msg += "list of boxes." msg += "list of boxes."
@ -471,27 +492,28 @@ class Jp2k(Jp2kBox):
# 1st jp2 header box must be ihdr # 1st jp2 header box must be ihdr
jp2h = boxes[jp2h_idx] jp2h = boxes[jp2h_idx]
if jp2h.box[0].id != 'ihdr': if jp2h.box[0].box_id != 'ihdr':
msg = "The first box in the jp2 header box must be the image " msg = "The first box in the jp2 header box must be the image "
msg += "header box." msg += "header box."
raise IOError(msg) raise IOError(msg)
# colr must be present in jp2 header box. # colr must be present in jp2 header box.
jp2hb = jp2h.box colr_lst = [j for (j, box) in enumerate(jp2h.box)
colr_lst = [j for (j, box) in enumerate(jp2h.box) if box.id == 'colr'] if box.box_id == 'colr']
if len(colr_lst) == 0: if len(colr_lst) == 0:
msg = "The jp2 header box must contain a color definition box." msg = "The jp2 header box must contain a color definition box."
raise IOError(msg) raise IOError(msg)
colr = jp2h.box[colr_lst[0]] colr = jp2h.box[colr_lst[0]]
# Any cdef box must be in the jp2 header following the image header. # Any cdef box must be in the jp2 header following the image header.
cdef_lst = [j for (j, box) in enumerate(boxes) if box.id == 'cdef'] cdef_lst = [j for (j, box) in enumerate(boxes) if box.box_id == 'cdef']
if len(cdef_lst) != 0: if len(cdef_lst) != 0:
msg = "Any channel defintion box must be in the JP2 header " msg = "Any channel defintion box must be in the JP2 header "
msg += "following the image header." msg += "following the image header."
raise IOError(msg) raise IOError(msg)
cdef_lst = [j for (j, box) in enumerate(jp2h.box) if box.id == 'cdef'] cdef_lst = [j for (j, box) in enumerate(jp2h.box)
if box.box_id == 'cdef']
if len(cdef_lst) > 1: if len(cdef_lst) > 1:
msg = "Only one channel definition box is allowed in the " msg = "Only one channel definition box is allowed in the "
msg += "JP2 header." msg += "JP2 header."
@ -500,7 +522,6 @@ class Jp2k(Jp2kBox):
cdef = jp2h.box[cdef_lst[0]] cdef = jp2h.box[cdef_lst[0]]
assn = cdef.association assn = cdef.association
typ = cdef.channel_type typ = cdef.channel_type
index = cdef.index
if colr.colorspace == SRGB: if colr.colorspace == SRGB:
if any([chan + 1 not in assn or typ[chan] != 0 if any([chan + 1 not in assn or typ[chan] != 0
for chan in [0, 1, 2]]): for chan in [0, 1, 2]]):
@ -515,8 +536,8 @@ class Jp2k(Jp2kBox):
with open(filename, 'wb') as ofile: with open(filename, 'wb') as ofile:
for box in boxes: for box in boxes:
if box.id != 'jp2c': if box.box_id != 'jp2c':
box._write(ofile) box.write(ofile)
else: else:
# The codestream gets written last. # The codestream gets written last.
if len(self.box) == 0: if len(self.box) == 0:
@ -530,7 +551,8 @@ class Jp2k(Jp2kBox):
else: else:
# OK, I'm a jp2 file. Need to find out where the # OK, I'm a jp2 file. Need to find out where the
# raw codestream actually starts. # raw codestream actually starts.
jp2c = [box for box in self.box if box.id == 'jp2c'] jp2c = [box for box in self.box
if box.box_id == 'jp2c']
jp2c = jp2c[0] jp2c = jp2c[0]
ofile.write(struct.pack('>I', jp2c.length + 8)) ofile.write(struct.pack('>I', jp2c.length + 8))
ofile.write('jp2c'.encode()) ofile.write('jp2c'.encode())
@ -550,8 +572,8 @@ class Jp2k(Jp2kBox):
Parameters Parameters
---------- ----------
reduce : int, optional rlevel : int, optional
Factor by which to reduce output resolution. Use -1 to get the Factor by which to rlevel output resolution. Use -1 to get the
lowest resolution thumbnail. This is the only keyword option lowest resolution thumbnail. This is the only keyword option
available to use when only OpenJPEG version 1.5.1 is present. available to use when only OpenJPEG version 1.5.1 is present.
layer : int, optional layer : int, optional
@ -585,23 +607,23 @@ class Jp2k(Jp2kBox):
Read the lowest resolution thumbnail. Read the lowest resolution thumbnail.
>>> thumbnail = jp.read(reduce=-1) >>> thumbnail = jp.read(rlevel=-1)
>>> thumbnail.shape >>> thumbnail.shape
(728, 1296, 3) (728, 1296, 3)
""" """
if opj2._OPENJP2 is not None: if _opj2.OPENJP2 is not None:
img = self._read_openjp2(**kwargs) img = self._read_openjp2(**kwargs)
else: else:
img = self._read_openjpeg(**kwargs) img = self._read_openjpeg(**kwargs)
return img return img
def _read_openjpeg(self, reduce=0, verbose=False): def _read_openjpeg(self, rlevel=0, verbose=False):
"""Read a JPEG 2000 image using libopenjpeg. """Read a JPEG 2000 image using libopenjpeg.
Parameters Parameters
---------- ----------
reduce : int, optional rlevel : int, optional
Factor by which to reduce 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.
verbose : bool, optional verbose : bool, optional
Print informational messages produced by the OpenJPEG library. Print informational messages produced by the OpenJPEG library.
@ -618,49 +640,48 @@ class Jp2k(Jp2kBox):
""" """
# Check for differing subsample factors. # Check for differing subsample factors.
codestream = self.get_codestream(header_only=True) codestream = self.get_codestream(header_only=True)
dxs = np.array(codestream.segment[1].XRsiz) dxs = np.array(codestream.segment[1].xrsiz)
dys = np.array(codestream.segment[1].YRsiz) dys = np.array(codestream.segment[1].yrsiz)
if np.any(dxs - dxs[0]) or np.any(dys - dys[0]): if np.any(dxs - dxs[0]) or np.any(dys - dys[0]):
msg = "Components must all have the same subsampling factors " msg = "Components must all have the same subsampling factors "
msg += "to use this method with OpenJPEG 1.5.1. Please consider " msg += "to use this method with OpenJPEG 1.5.1. Please consider "
msg += "using OPENJP2 instead." msg += "using OPENJP2 instead."
raise RuntimeError(msg) raise RuntimeError(msg)
with ExitStack() as stack: with ExitStack() as stack:
# Set decoding parameters. # Set decoding parameters.
dparameters = opj.dparameters_t() dparameters = _opj.DecompressionParametersType()
opj._set_default_decoder_parameters(ctypes.byref(dparameters)) _opj.set_default_decoder_parameters(ctypes.byref(dparameters))
dparameters.cp_reduce = reduce dparameters.cp_reduce = rlevel
dparameters.decod_format = self._codec_format dparameters.decod_format = self._codec_format
infile = self.filename.encode() infile = self.filename.encode()
nelts = opj._PATH_LEN - len(infile) nelts = _opj.PATH_LEN - len(infile)
infile += b'0' * nelts infile += b'0' * nelts
dparameters.infile = infile dparameters.infile = infile
dinfo = opj._create_decompress(dparameters.decod_format) dinfo = _opj.create_decompress(dparameters.decod_format)
event_mgr = opj.event_mgr_t() event_mgr = _opj.EventMgrType()
info_handler = ctypes.cast(_info_callback, ctypes.c_void_p) info_handler = ctypes.cast(_INFO_CALLBACK, ctypes.c_void_p)
event_mgr.info_handler = info_handler if verbose else None event_mgr.info_handler = info_handler if verbose else None
event_mgr.warning_handler = ctypes.cast(_warning_callback, event_mgr.warning_handler = ctypes.cast(_WARNING_CALLBACK,
ctypes.c_void_p) ctypes.c_void_p)
event_mgr.error_handler = ctypes.cast(_error_callback, event_mgr.error_handler = ctypes.cast(_ERROR_CALLBACK,
ctypes.c_void_p) ctypes.c_void_p)
opj._set_event_mgr(dinfo, ctypes.byref(event_mgr)) _opj.set_event_mgr(dinfo, ctypes.byref(event_mgr))
opj._setup_decoder(dinfo, dparameters) _opj.setup_decoder(dinfo, dparameters)
with open(self.filename, 'rb') as fp: with open(self.filename, 'rb') as fptr:
src = fp.read() src = fptr.read()
cio = opj._cio_open(dinfo, src) cio = _opj.cio_open(dinfo, src)
image = opj._decode(dinfo, cio) image = _opj.decode(dinfo, cio)
stack.callback(opj._image_destroy, image) stack.callback(_opj.image_destroy, image)
stack.callback(opj._destroy_decompress, dinfo) stack.callback(_opj.destroy_decompress, dinfo)
stack.callback(opj._cio_close, cio) stack.callback(_opj.cio_close, cio)
ncomps = image.contents.numcomps ncomps = image.contents.numcomps
component = image.contents.comps[0] component = image.contents.comps[0]
@ -700,8 +721,10 @@ class Jp2k(Jp2kBox):
with warnings.catch_warnings(): with warnings.catch_warnings():
warnings.simplefilter("ignore") warnings.simplefilter("ignore")
nelts = nrows * ncols nelts = nrows * ncols
x = np.ctypeslib.as_array((ctypes.c_int32 * nelts).from_address(addr)) band = np.ctypeslib.as_array(
data[:, :, k] = np.reshape(x.astype(dtype), (nrows, ncols)) (ctypes.c_int32 * nelts).from_address(addr))
data[:, :, k] = np.reshape(band.astype(dtype),
(nrows, ncols))
if data.shape[2] == 1: if data.shape[2] == 1:
data = data.view() data = data.view()
@ -709,7 +732,7 @@ class Jp2k(Jp2kBox):
return data return data
def _read_openjp2(self, reduce=0, layer=0, area=None, tile=None, def _read_openjp2(self, rlevel=0, layer=0, area=None, tile=None,
verbose=False): verbose=False):
"""Read a JPEG 2000 image using libopenjp2. """Read a JPEG 2000 image using libopenjp2.
@ -717,8 +740,8 @@ class Jp2k(Jp2kBox):
---------- ----------
layer : int, optional layer : int, optional
Number of quality layer to decode. Number of quality layer to decode.
reduce : int, optional rlevel : int, optional
Factor by which to reduce 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.
area : tuple, optional area : tuple, optional
Specifies decoding image area, Specifies decoding image area,
@ -740,13 +763,13 @@ class Jp2k(Jp2kBox):
""" """
# Check for differing subsample factors. # Check for differing subsample factors.
codestream = self.get_codestream(header_only=True) codestream = self.get_codestream(header_only=True)
dxs = np.array(codestream.segment[1].XRsiz) dxs = np.array(codestream.segment[1].xrsiz)
dys = np.array(codestream.segment[1].YRsiz) dys = np.array(codestream.segment[1].yrsiz)
if np.any(dxs - dxs[0]) or np.any(dys - dys[0]): if np.any(dxs - dxs[0]) or np.any(dys - dys[0]):
msg = "Components must all have the same subsampling factors." msg = "Components must all have the same subsampling factors."
raise RuntimeError(msg) raise RuntimeError(msg)
img_array = self._read_common(reduce=reduce, img_array = self._read_common(rlevel=rlevel,
layer=layer, layer=layer,
area=area, area=area,
tile=tile, tile=tile,
@ -759,7 +782,7 @@ class Jp2k(Jp2kBox):
return img_array return img_array
def _read_common(self, reduce=0, layer=0, area=None, tile=None, def _read_common(self, rlevel=0, layer=0, area=None, tile=None,
verbose=False, as_bands=False): verbose=False, as_bands=False):
"""Read a JPEG 2000 image. """Read a JPEG 2000 image.
@ -767,8 +790,8 @@ class Jp2k(Jp2kBox):
---------- ----------
layer : int, optional layer : int, optional
Number of quality layer to decode. Number of quality layer to decode.
reduce : int, optional rlevel : int, optional
Factor by which to reduce output resolution. Factor by which to rlevel output resolution.
area : tuple, optional area : tuple, optional
Specifies decoding image area, Specifies decoding image area,
(first_row, first_col, last_row, last_col) (first_row, first_col, last_row, last_col)
@ -784,10 +807,10 @@ class Jp2k(Jp2kBox):
img_array : ndarray img_array : ndarray
The individual image components or a single array. The individual image components or a single array.
""" """
dparam = opj2._set_default_decoder_parameters() dparam = _opj2.set_default_decoder_parameters()
infile = self.filename.encode() infile = self.filename.encode()
nelts = opj2._PATH_LEN - len(infile) nelts = _opj2.PATH_LEN - len(infile)
infile += b'0' * nelts infile += b'0' * nelts
dparam.infile = infile dparam.infile = infile
@ -795,12 +818,12 @@ class Jp2k(Jp2kBox):
dparam.cp_layer = layer dparam.cp_layer = layer
if reduce == -1: if rlevel == -1:
# Get the lowest resolution thumbnail. # Get the lowest resolution thumbnail.
codestream = self.get_codestream() codestream = self.get_codestream()
reduce = codestream.segment[2].SPcod[4] rlevel = codestream.segment[2].spcod[4]
dparam.cp_reduce = reduce dparam.cp_reduce = rlevel
if area is not None: if area is not None:
if area[0] < 0 or area[1] < 0: if area[0] < 0 or area[1] < 0:
msg = "Upper left corner coordinates must be nonnegative: {0}" msg = "Upper left corner coordinates must be nonnegative: {0}"
@ -820,31 +843,31 @@ class Jp2k(Jp2kBox):
dparam.nb_tile_to_decode = 1 dparam.nb_tile_to_decode = 1
with ExitStack() as stack: with ExitStack() as stack:
stream = opj2._stream_create_default_file_stream_v3(self.filename, stream = _opj2.stream_create_default_file_stream_v3(self.filename,
True) True)
stack.callback(opj2._stream_destroy_v3, stream) stack.callback(_opj2.stream_destroy_v3, stream)
codec = opj2._create_decompress(self._codec_format) codec = _opj2.create_decompress(self._codec_format)
stack.callback(opj2._destroy_codec, codec) stack.callback(_opj2.destroy_codec, codec)
opj2._set_error_handler(codec, _error_callback) _opj2.set_error_handler(codec, _ERROR_CALLBACK)
opj2._set_warning_handler(codec, _warning_callback) _opj2.set_warning_handler(codec, _WARNING_CALLBACK)
if verbose: if verbose:
opj2._set_info_handler(codec, _info_callback) _opj2.set_info_handler(codec, _INFO_CALLBACK)
else: else:
opj2._set_info_handler(codec, None) _opj2.set_info_handler(codec, None)
opj2._setup_decoder(codec, dparam) _opj2.setup_decoder(codec, dparam)
image = opj2._read_header(stream, codec) image = _opj2.read_header(stream, codec)
stack.callback(opj2._image_destroy, image) stack.callback(_opj2.image_destroy, image)
if dparam.nb_tile_to_decode: if dparam.nb_tile_to_decode:
opj2._get_decoded_tile(codec, stream, image, dparam.tile_index) _opj2.get_decoded_tile(codec, stream, image, dparam.tile_index)
else: else:
opj2._set_decode_area(codec, image, _opj2.set_decode_area(codec, image,
dparam.DA_x0, dparam.DA_y0, dparam.DA_x0, dparam.DA_y0,
dparam.DA_x1, dparam.DA_y1) dparam.DA_x1, dparam.DA_y1)
opj2._decode(codec, stream, image) _opj2.decode(codec, stream, image)
opj2._end_decompress(codec, stream) _opj2.end_decompress(codec, stream)
component = image.contents.comps[0] component = image.contents.comps[0]
if component.sgnd: if component.sgnd:
@ -885,16 +908,17 @@ class Jp2k(Jp2kBox):
addr = ctypes.addressof(component.data.contents) addr = ctypes.addressof(component.data.contents)
with warnings.catch_warnings(): with warnings.catch_warnings():
warnings.simplefilter("ignore") warnings.simplefilter("ignore")
x = np.ctypeslib.as_array( band = np.ctypeslib.as_array(
(ctypes.c_int32 * nrows * ncols).from_address(addr)) (ctypes.c_int32 * nrows * ncols).from_address(addr))
if as_bands: if as_bands:
data.append(np.reshape(x.astype(dtype), (nrows, ncols))) data.append(np.reshape(band.astype(dtype), (nrows, ncols)))
else: else:
data[:, :, k] = np.reshape(x.astype(dtype), (nrows, ncols)) data[:, :, k] = np.reshape(band.astype(dtype),
(nrows, ncols))
return data return data
def read_bands(self, reduce=0, layer=0, area=None, tile=None, def read_bands(self, rlevel=0, layer=0, area=None, tile=None,
verbose=False): verbose=False):
"""Read a JPEG 2000 image. """Read a JPEG 2000 image.
@ -906,8 +930,8 @@ class Jp2k(Jp2kBox):
---------- ----------
layer : int, optional layer : int, optional
Number of quality layer to decode. Number of quality layer to decode.
reduce : int, optional rlevel : int, optional
Factor by which to reduce output resolution. Factor by which to rlevel output resolution.
area : tuple, optional area : tuple, optional
Specifies decoding image area, Specifies decoding image area,
(first_row, first_col, last_row, last_col) (first_row, first_col, last_row, last_col)
@ -930,18 +954,18 @@ class Jp2k(Jp2kBox):
>>> import glymur >>> import glymur
>>> jfile = glymur.data.nemo() >>> jfile = glymur.data.nemo()
>>> jp = glymur.Jp2k(jfile) >>> jp = glymur.Jp2k(jfile)
>>> components_lst = jp.read_bands(reduce=1) >>> components_lst = jp.read_bands(rlevel=1)
Raises Raises
------ ------
NotImplementedError NotImplementedError
If the openjp2 library is not available. If the openjp2 library is not available.
""" """
if opj2._OPENJP2 is None: if _opj2.OPENJP2 is None:
msg = "Requires openjp2 library." msg = "Requires openjp2 library."
raise NotImplementedError(msg) raise NotImplementedError(msg)
lst = self._read_common(reduce=reduce, lst = self._read_common(rlevel=rlevel,
layer=layer, layer=layer,
area=area, area=area,
tile=tile, tile=tile,
@ -985,20 +1009,20 @@ class Jp2k(Jp2kBox):
IOError IOError
If the file is JPX with more than one codestream. If the file is JPX with more than one codestream.
""" """
with open(self.filename, 'rb') as fp: with open(self.filename, 'rb') as fptr:
if self._codec_format == opj2._CODEC_J2K: if self._codec_format == _opj2.CODEC_J2K:
codestream = Codestream(fp, header_only=header_only) codestream = Codestream(fptr, header_only=header_only)
else: else:
box = [x for x in self.box if x.id == 'jp2c'] box = [x for x in self.box if x.box_id == 'jp2c']
if len(box) != 1: if len(box) != 1:
msg = "JP2 files must have a single codestream." msg = "JP2 files must have a single codestream."
raise RuntimeError(msg) raise RuntimeError(msg)
fp.seek(box[0].offset) fptr.seek(box[0].offset)
buffer = fp.read(8) read_buffer = fptr.read(8)
(L, T) = struct.unpack('>I4s', buffer) (box_length, _) = struct.unpack('>I4s', read_buffer)
if L == 1: if box_length == 1:
# Seek past the XL field. # Seek past the XL field.
buffer = fp.read(8) read_buffer = fptr.read(8)
codestream = Codestream(fp, header_only=header_only) codestream = Codestream(fptr, header_only=header_only)
return codestream return codestream

View file

@ -1,4 +1,4 @@
"""This package organizes individual libraries employed by glymur.""" """This package organizes individual libraries employed by glymur."""
from . import openjp2 from . import openjp2 as _openjp2
from . import openjpeg from . import openjpeg as _openjpeg
#from . import test #from . import test

133
glymur/lib/config.py Normal file
View file

@ -0,0 +1,133 @@
"""
Configure glymur to use installed libraries if possible.
"""
import ctypes
from ctypes.util import find_library
import os
import platform
import warnings
import sys
if sys.hexversion <= 0x03000000:
from ConfigParser import SafeConfigParser as ConfigParser
else:
from configparser import ConfigParser
def glymurrc_fname():
"""Return the path to the configuration file.
Search order:
1) current working directory
2) environ var XDG_CONFIG_HOME
3) $HOME/.config/glymur/glymurrc
"""
# Current directory.
fname = os.path.join(os.getcwd(), 'glymurrc')
if os.path.exists(fname):
return fname
# Either GLYMURCONFIGDIR/glymurrc or $HOME/.glymur/glymurrc
confdir = get_configdir()
if confdir is not None:
fname = os.path.join(confdir, 'glymurrc')
if os.path.exists(fname):
return fname
# didn't find a configuration file.
return None
def get_openjpeg_config():
""" Try to find openjpeg library on the system path first.
"""
libopenjpeg_path = find_library('openjpeg')
# If we could not find it, then look in some likely locations.
if libopenjpeg_path is None:
if platform.system() == 'Darwin':
path = '/opt/local/lib/libopenjpeg.dylib'
if os.path.exists(path):
libopenjpeg_path = path
elif os.name == 'nt':
path = os.path.join('C:\\', 'Program files', 'OpenJPEG 1.5',
'bin', 'openjpeg.dll')
if os.path.exists(path):
libopenjpeg_path = path
try:
if os.name == "nt":
openjpeg_lib = ctypes.windll.LoadLibrary(libopenjpeg_path)
else:
openjpeg_lib = ctypes.CDLL(libopenjpeg_path)
except OSError:
openjpeg_lib = None
if openjpeg_lib is not None:
# Must be at least 1.5.0
openjpeg_lib.opj_version.restype = ctypes.c_char_p
version = openjpeg_lib.opj_version().decode('utf-8')
_, minor, _ = version.split('.')
if minor != '5':
openjpeg_lib = None
return openjpeg_lib
def get_openjp2_config():
"""
We expect to not find openjp2 on the system path since the only version
that we currently care about is still in the svn trunk at openjpeg.org.
We must use a configuration file that the user must write.
"""
filename = glymurrc_fname()
if filename is not None:
# Read the configuration file for the library location.
parser = ConfigParser()
parser.read(filename)
libopenjp2_path = parser.get('library', 'openjp2')
else:
# No help from the config file, try to find it ourselves.
libopenjp2_path = find_library('openjp2')
if libopenjp2_path is None:
return None
try:
if os.name == "nt":
openjp2_lib = ctypes.windll.LoadLibrary(libopenjp2_path)
else:
openjp2_lib = ctypes.CDLL(libopenjp2_path)
except OSError:
msg = '"Library {0}" could not be loaded. Operating in degraded mode.'
msg = msg.format(libopenjp2_path)
warnings.warn(msg, UserWarning)
openjp2_lib = None
return openjp2_lib
def glymur_config():
"""Try to ascertain locations of openjp2, openjpeg libraries.
"""
openjp2_lib = get_openjp2_config()
openjpeg_lib = get_openjpeg_config()
return openjp2_lib, openjpeg_lib
def get_configdir():
"""Return string representing the configuration directory.
Default is $HOME/.config/glymur. You can override this with the
XDG_CONFIG_HOME environment variable.
"""
if 'XDG_CONFIG_HOME' in os.environ:
return os.path.join(os.environ['XDG_CONFIG_HOME'], 'glymur')
if 'HOME' in os.environ:
return os.path.join(os.environ['HOME'], '.config', 'glymur')
if 'USERPROFILE' in os.environ:
# Windows?
return os.path.join(os.environ['USERPROFILE'], 'Application Data',
'glymur')

File diff suppressed because it is too large Load diff

View file

@ -1,35 +1,30 @@
"""Wraps library calls to openjpeg. """Wraps library calls to openjpeg.
""" """
# pylint: disable=R0903
import ctypes import ctypes
from ctypes.util import find_library
import platform
import os
if os.name == "nt": from .config import glymur_config
path = os.path.join('C:\\', 'Program files', 'OpenJPEG 1.5', _, OPENJPEG = glymur_config()
'bin', 'openjpeg.dll')
_OPENJPEG = ctypes.windll.LoadLibrary(path)
else:
if platform.system() == 'Darwin':
_OPENJPEG = ctypes.CDLL('/opt/local/lib/libopenjpeg.dylib')
elif platform.system() == 'Linux':
_OPENJPEG = ctypes.CDLL(find_library('openjpeg'))
_PATH_LEN = 4096 # maximum allowed size for filenames PATH_LEN = 4096 # maximum allowed size for filenames
class event_mgr_t(ctypes.Structure): class EventMgrType(ctypes.Structure):
"""Message handler object. """Message handler object.
Corresponds to event_mgr_t type in openjpeg headers.
""" """
_fields_ = [("error_handler", ctypes.c_void_p), _fields_ = [("error_handler", ctypes.c_void_p),
("warning_handler", ctypes.c_void_p), ("warning_handler", ctypes.c_void_p),
("info_handler", ctypes.c_void_p)] ("info_handler", ctypes.c_void_p)]
class common_struct_t(ctypes.Structure):
class CommonStructType(ctypes.Structure):
"""Common fields between JPEG 2000 compression and decompression contextx. """Common fields between JPEG 2000 compression and decompression contextx.
""" """
_fields_ = [("event_mgr", ctypes.POINTER(event_mgr_t)), _fields_ = [("event_mgr", ctypes.POINTER(EventMgrType)),
("client_data", ctypes.c_void_p), ("client_data", ctypes.c_void_p),
("is_decompressor", ctypes.c_bool), ("is_decompressor", ctypes.c_bool),
("codec_format", ctypes.c_int), ("codec_format", ctypes.c_int),
@ -38,16 +33,20 @@ class common_struct_t(ctypes.Structure):
("mj2_handle", ctypes.c_void_p)] ("mj2_handle", ctypes.c_void_p)]
class dinfo_t(ctypes.Structure): class DecompressionInfoType(ctypes.Structure):
"""Common fields between JPEG 2000 compression and decompression contextx. """This is for decompression contexts.
This is for decompression contexts.
Corresponds to dinfo_t type in openjpeg headers.
""" """
pass pass
class cio_t(ctypes.Structure): class CioType(ctypes.Structure):
_fields_ = [# codec context """Byte input-output stream (CIO)
("cinfo", ctypes.POINTER(common_struct_t)),
Corresponds to cio_t in openjpeg headers.
"""
_fields_ = [("cinfo", ctypes.POINTER(CommonStructType)), # codec context
# STREAM_READ or STREAM_WRITE # STREAM_READ or STREAM_WRITE
("openmode", ctypes.c_int), ("openmode", ctypes.c_int),
# pointer to start of buffer # pointer to start of buffer
@ -62,15 +61,19 @@ class cio_t(ctypes.Structure):
("bp", ctypes.c_char_p)] ("bp", ctypes.c_char_p)]
class dparameters_t(ctypes.Structure): class DecompressionParametersType(ctypes.Structure):
"""Decompression parameters.
Corresponds to dparameters_t type in openjpeg headers.
"""
# cp_reduce: the number of highest resolution levels to be discarded # cp_reduce: the number of highest resolution levels to be discarded
_fields_ = [("cp_reduce", ctypes.c_int), _fields_ = [("cp_reduce", ctypes.c_int),
# cp_layer: the maximum number of quality layers to decode # cp_layer: the maximum number of quality layers to decode
("cp_layer", ctypes.c_int), ("cp_layer", ctypes.c_int),
# infile: input file name # infile: input file name
("infile", ctypes.c_char * _PATH_LEN), ("infile", ctypes.c_char * PATH_LEN),
# outfile: output file name # outfile: output file name
("outfile", ctypes.c_char * _PATH_LEN), ("outfile", ctypes.c_char * PATH_LEN),
# decod_format: input file format 0: J2K, 1: JP2, 2: JPT # decod_format: input file format 0: J2K, 1: JP2, 2: JPT
("decod_format", ctypes.c_int), ("decod_format", ctypes.c_int),
# cod_format: output file format 0: PGX, 1: PxM, 2: BMP # cod_format: output file format 0: PGX, 1: PxM, 2: BMP
@ -87,8 +90,11 @@ class dparameters_t(ctypes.Structure):
("flags", ctypes.c_uint)] ("flags", ctypes.c_uint)]
class image_comp_t(ctypes.Structure): class ImageCompType(ctypes.Structure):
"""Defines a single image component. """ """Defines a single image component.
Corresponds to image_comp_t type in openjpeg.
"""
_fields_ = [("dx", ctypes.c_int), _fields_ = [("dx", ctypes.c_int),
("dy", ctypes.c_int), ("dy", ctypes.c_int),
("w", ctypes.c_int), ("w", ctypes.c_int),
@ -103,87 +109,105 @@ class image_comp_t(ctypes.Structure):
("data", ctypes.POINTER(ctypes.c_int))] ("data", ctypes.POINTER(ctypes.c_int))]
class image_t(ctypes.Structure): class ImageType(ctypes.Structure):
"""Defines image data and characteristics.""" """Defines image data and characteristics.
Corresponds to image_t type in openjpeg headers.
"""
_fields_ = [("x0", ctypes.c_int), _fields_ = [("x0", ctypes.c_int),
("y0", ctypes.c_int), ("y0", ctypes.c_int),
("x1", ctypes.c_int), ("x1", ctypes.c_int),
("y1", ctypes.c_int), ("y1", ctypes.c_int),
("numcomps", ctypes.c_int), ("numcomps", ctypes.c_int),
("color_space", ctypes.c_int), ("color_space", ctypes.c_int),
("comps", ctypes.POINTER(image_comp_t)), ("comps", ctypes.POINTER(ImageCompType)),
("icc_profile_buf", ctypes.c_char_p), ("icc_profile_buf", ctypes.c_char_p),
("icc_profile_len", ctypes.c_int)] ("icc_profile_len", ctypes.c_int)]
def _cio_open(cinfo, src):
"""Wrapper for openjpeg library function opj_cio_open."""
argtypes = [ctypes.POINTER(common_struct_t), ctypes.c_char_p, ctypes.c_int]
_OPENJPEG.opj_cio_open.argtypes = argtypes
_OPENJPEG.opj_cio_open.restype = ctypes.POINTER(cio_t)
cio = _OPENJPEG.opj_cio_open(ctypes.cast(cinfo, ctypes.POINTER(common_struct_t)), def cio_open(cinfo, src):
src, len(src)) """Wrapper for openjpeg library function opj_cio_open."""
argtypes = [ctypes.POINTER(CommonStructType), ctypes.c_char_p,
ctypes.c_int]
OPENJPEG.opj_cio_open.argtypes = argtypes
OPENJPEG.opj_cio_open.restype = ctypes.POINTER(CioType)
cio = OPENJPEG.opj_cio_open(ctypes.cast(cinfo,
ctypes.POINTER(CommonStructType)),
src, len(src))
return cio return cio
def _cio_close(cio):
def cio_close(cio):
"""Wraps openjpeg library function cio_close. """Wraps openjpeg library function cio_close.
""" """
_OPENJPEG.opj_cio_close.argtypes = [ctypes.POINTER(cio_t)] OPENJPEG.opj_cio_close.argtypes = [ctypes.POINTER(CioType)]
_OPENJPEG.opj_cio_close(cio) OPENJPEG.opj_cio_close(cio)
def _create_decompress(fmt):
def create_decompress(fmt):
"""Wraps openjpeg library function opj_create_decompress. """Wraps openjpeg library function opj_create_decompress.
""" """
_OPENJPEG.opj_create_decompress.argtypes = [ctypes.c_int] OPENJPEG.opj_create_decompress.argtypes = [ctypes.c_int]
_OPENJPEG.opj_create_decompress.restype = ctypes.POINTER(dinfo_t) restype = ctypes.POINTER(DecompressionInfoType)
dinfo = _OPENJPEG.opj_create_decompress(fmt) OPENJPEG.opj_create_decompress.restype = restype
dinfo = OPENJPEG.opj_create_decompress(fmt)
return dinfo return dinfo
def _decode(dinfo, cio):
def decode(dinfo, cio):
"""Wrapper for opj_decode. """Wrapper for opj_decode.
""" """
argtypes = [ctypes.POINTER(dinfo_t), ctypes.POINTER(cio_t)] argtypes = [ctypes.POINTER(DecompressionInfoType), ctypes.POINTER(CioType)]
_OPENJPEG.opj_decode.argtypes = argtypes OPENJPEG.opj_decode.argtypes = argtypes
_OPENJPEG.opj_decode.restype = ctypes.POINTER(image_t) OPENJPEG.opj_decode.restype = ctypes.POINTER(ImageType)
image = _OPENJPEG.opj_decode(dinfo, cio) image = OPENJPEG.opj_decode(dinfo, cio)
return image return image
def _destroy_decompress(dinfo):
def destroy_decompress(dinfo):
"""Wraps openjpeg library function opj_destroy_decompress.""" """Wraps openjpeg library function opj_destroy_decompress."""
_OPENJPEG.opj_destroy_decompress.argtypes = [ctypes.POINTER(dinfo_t)] argtypes = [ctypes.POINTER(DecompressionInfoType)]
_OPENJPEG.opj_destroy_decompress(dinfo) OPENJPEG.opj_destroy_decompress.argtypes = argtypes
OPENJPEG.opj_destroy_decompress(dinfo)
def _image_destroy(image):
def image_destroy(image):
"""Wraps openjpeg library function opj_image_destroy.""" """Wraps openjpeg library function opj_image_destroy."""
_OPENJPEG.opj_image_destroy.argtypes = [ctypes.POINTER(image_t)] OPENJPEG.opj_image_destroy.argtypes = [ctypes.POINTER(ImageType)]
_OPENJPEG.opj_image_destroy(image) OPENJPEG.opj_image_destroy(image)
def _set_default_decoder_parameters(dparams_p):
def set_default_decoder_parameters(dparams_p):
"""Wrapper for opj_set_default_decoder_parameters. """Wrapper for opj_set_default_decoder_parameters.
""" """
argtypes = [ctypes.POINTER(dparameters_t)] argtypes = [ctypes.POINTER(DecompressionParametersType)]
_OPENJPEG.opj_set_default_decoder_parameters.argtypes = argtypes OPENJPEG.opj_set_default_decoder_parameters.argtypes = argtypes
_OPENJPEG.opj_set_default_decoder_parameters(dparams_p) OPENJPEG.opj_set_default_decoder_parameters(dparams_p)
def _set_event_mgr(dinfo, event_mgr, context=None): def set_event_mgr(dinfo, event_mgr, context=None):
"""Wrapper for openjpeg library function opj_set_event_mgr. """Wrapper for openjpeg library function opj_set_event_mgr.
""" """
argtypes = [ctypes.POINTER(common_struct_t), argtypes = [ctypes.POINTER(CommonStructType),
ctypes.POINTER(event_mgr_t), ctypes.POINTER(EventMgrType),
ctypes.c_void_p] ctypes.c_void_p]
_OPENJPEG.opj_set_event_mgr(ctypes.cast(dinfo, OPENJPEG.opj_set_event_mgr.argtypes = argtypes
ctypes.POINTER(common_struct_t)), OPENJPEG.opj_set_event_mgr(ctypes.cast(dinfo,
event_mgr, context) ctypes.POINTER(CommonStructType)),
event_mgr, context)
def _setup_decoder(dinfo, dparams):
def setup_decoder(dinfo, dparams):
"""Wrapper for openjpeg library function opj_setup_decoder.""" """Wrapper for openjpeg library function opj_setup_decoder."""
argtypes = [ctypes.POINTER(dinfo_t), ctypes.POINTER(dparameters_t)] argtypes = [ctypes.POINTER(DecompressionInfoType),
_OPENJPEG.opj_setup_decoder.argtypes = argtypes ctypes.POINTER(DecompressionParametersType)]
_OPENJPEG.opj_setup_decoder(dinfo, dparams) OPENJPEG.opj_setup_decoder.argtypes = argtypes
OPENJPEG.opj_setup_decoder(dinfo, dparams)
def _version():
def version():
"""Wrapper for opj_version library routine.""" """Wrapper for opj_version library routine."""
_OPENJPEG.opj_version.restype = ctypes.c_char_p OPENJPEG.opj_version.restype = ctypes.c_char_p
v = _OPENJPEG.opj_version() library_version = OPENJPEG.opj_version()
return v.decode('utf-8') return library_version.decode('utf-8')

View file

@ -12,13 +12,7 @@ import numpy as np
import glymur import glymur
def load_tests(loader, tests, ignore): @unittest.skipIf(glymur.lib._openjp2.OPENJP2 is None,
if glymur.lib.openjp2._OPENJP2 is not None:
tests.addTests(doctest.DocTestSuite('glymur.lib.openjp2'))
return tests
@unittest.skipIf(glymur.lib.openjp2._OPENJP2 is None,
"Missing openjp2 library.") "Missing openjp2 library.")
class TestOpenJP2(unittest.TestCase): class TestOpenJP2(unittest.TestCase):
@ -29,7 +23,7 @@ class TestOpenJP2(unittest.TestCase):
pass pass
def test_set_default_encoder_parameters(self): def test_set_default_encoder_parameters(self):
cparams = glymur.lib.openjp2._set_default_encoder_parameters() cparams = glymur.lib._openjp2.set_default_encoder_parameters()
self.assertEqual(cparams.res_spec, 0) self.assertEqual(cparams.res_spec, 0)
self.assertEqual(cparams.cblockw_init, 64) self.assertEqual(cparams.cblockw_init, 64)
@ -38,7 +32,7 @@ class TestOpenJP2(unittest.TestCase):
self.assertEqual(cparams.subsampling_dx, 1) self.assertEqual(cparams.subsampling_dx, 1)
self.assertEqual(cparams.subsampling_dy, 1) self.assertEqual(cparams.subsampling_dy, 1)
self.assertEqual(cparams.mode, 0) self.assertEqual(cparams.mode, 0)
self.assertEqual(cparams.prog_order, glymur.lib.openjp2.LRCP) self.assertEqual(cparams.prog_order, glymur.core.LRCP)
self.assertEqual(cparams.roi_shift, 0) self.assertEqual(cparams.roi_shift, 0)
self.assertEqual(cparams.cp_tx0, 0) self.assertEqual(cparams.cp_tx0, 0)
self.assertEqual(cparams.cp_ty0, 0) self.assertEqual(cparams.cp_ty0, 0)
@ -46,7 +40,7 @@ class TestOpenJP2(unittest.TestCase):
self.assertEqual(cparams.irreversible, 0) self.assertEqual(cparams.irreversible, 0)
def test_set_default_decoder_parameters(self): def test_set_default_decoder_parameters(self):
dparams = glymur.lib.openjp2._set_default_decoder_parameters() dparams = glymur.lib._openjp2.set_default_decoder_parameters()
self.assertEqual(dparams.DA_x0, 0) self.assertEqual(dparams.DA_x0, 0)
self.assertEqual(dparams.DA_y0, 0) self.assertEqual(dparams.DA_y0, 0)
@ -55,34 +49,34 @@ class TestOpenJP2(unittest.TestCase):
def tile_macro(self, codec, stream, imagep, tidx): def tile_macro(self, codec, stream, imagep, tidx):
# called only by j2k_random_tile_access # called only by j2k_random_tile_access
glymur.lib.openjp2._get_decoded_tile(codec, stream, imagep, tidx) glymur.lib._openjp2.get_decoded_tile(codec, stream, imagep, tidx)
for j in range(imagep.contents.numcomps): for j in range(imagep.contents.numcomps):
self.assertIsNotNone(imagep.contents.comps[j].data) self.assertIsNotNone(imagep.contents.comps[j].data)
def j2k_random_tile_access(self, filename, codec_format=None): def j2k_random_tile_access(self, filename, codec_format=None):
# called by the test_rtaX methods # called by the test_rtaX methods
dparam = glymur.lib.openjp2._set_default_decoder_parameters() dparam = glymur.lib._openjp2.set_default_decoder_parameters()
infile = filename.encode() infile = filename.encode()
nelts = glymur.lib.openjp2._PATH_LEN - len(infile) nelts = glymur.lib._openjp2.PATH_LEN - len(infile)
infile += b'0' * nelts infile += b'0' * nelts
dparam.infile = infile dparam.infile = infile
dparam.decod_format = codec_format dparam.decod_format = codec_format
codec = glymur.lib.openjp2._create_decompress(codec_format) codec = glymur.lib._openjp2.create_decompress(codec_format)
glymur.lib.openjp2._set_info_handler(codec, None) glymur.lib._openjp2.set_info_handler(codec, None)
glymur.lib.openjp2._set_warning_handler(codec, None) glymur.lib._openjp2.set_warning_handler(codec, None)
glymur.lib.openjp2._set_error_handler(codec, None) glymur.lib._openjp2.set_error_handler(codec, None)
x = (filename, True) x = (filename, True)
stream = glymur.lib.openjp2._stream_create_default_file_stream_v3(*x) stream = glymur.lib._openjp2.stream_create_default_file_stream_v3(*x)
glymur.lib.openjp2._setup_decoder(codec, dparam) glymur.lib._openjp2.setup_decoder(codec, dparam)
image = glymur.lib.openjp2._read_header(stream, codec) image = glymur.lib._openjp2.read_header(stream, codec)
cstr_info = glymur.lib.openjp2._get_cstr_info(codec) cstr_info = glymur.lib._openjp2.get_cstr_info(codec)
tile_ul = 0 tile_ul = 0
tile_ur = cstr_info.contents.tw - 1 tile_ur = cstr_info.contents.tw - 1
@ -94,18 +88,18 @@ class TestOpenJP2(unittest.TestCase):
self.tile_macro(codec, stream, image, tile_lr) self.tile_macro(codec, stream, image, tile_lr)
self.tile_macro(codec, stream, image, tile_ll) self.tile_macro(codec, stream, image, tile_ll)
glymur.lib.openjp2._destroy_cstr_info(cstr_info) glymur.lib._openjp2.destroy_cstr_info(cstr_info)
glymur.lib.openjp2._end_decompress(codec, stream) glymur.lib._openjp2.end_decompress(codec, stream)
glymur.lib.openjp2._destroy_codec(codec) glymur.lib._openjp2.destroy_codec(codec)
glymur.lib.openjp2._stream_destroy_v3(stream) glymur.lib._openjp2.stream_destroy_v3(stream)
glymur.lib.openjp2._image_destroy(image) glymur.lib._openjp2.image_destroy(image)
def tile_decoder(self, x0=None, y0=None, x1=None, y1=None, filename=None, def tile_decoder(self, x0=None, y0=None, x1=None, y1=None, filename=None,
codec_format=None): codec_format=None):
x = (filename, True) x = (filename, True)
stream = glymur.lib.openjp2._stream_create_default_file_stream_v3(*x) stream = glymur.lib._openjp2.stream_create_default_file_stream_v3(*x)
dparam = glymur.lib.openjp2._set_default_decoder_parameters() dparam = glymur.lib._openjp2.set_default_decoder_parameters()
dparam.decod_format = codec_format dparam.decod_format = codec_format
@ -115,30 +109,30 @@ class TestOpenJP2(unittest.TestCase):
# do not use resolution reductions. # do not use resolution reductions.
dparam.cp_reduce = 0 dparam.cp_reduce = 0
codec = glymur.lib.openjp2._create_decompress(codec_format) codec = glymur.lib._openjp2.create_decompress(codec_format)
glymur.lib.openjp2._set_info_handler(codec, None) glymur.lib._openjp2.set_info_handler(codec, None)
glymur.lib.openjp2._set_warning_handler(codec, None) glymur.lib._openjp2.set_warning_handler(codec, None)
glymur.lib.openjp2._set_error_handler(codec, None) glymur.lib._openjp2.set_error_handler(codec, None)
glymur.lib.openjp2._setup_decoder(codec, dparam) glymur.lib._openjp2.setup_decoder(codec, dparam)
image = glymur.lib.openjp2._read_header(stream, codec) image = glymur.lib._openjp2.read_header(stream, codec)
glymur.lib.openjp2._set_decode_area(codec, image, x0, y0, x1, y1) glymur.lib._openjp2.set_decode_area(codec, image, x0, y0, x1, y1)
data = np.zeros((1150, 2048, 3), dtype=np.uint8) data = np.zeros((1150, 2048, 3), dtype=np.uint8)
while True: while True:
rargs = glymur.lib.openjp2._read_tile_header(codec, stream) rargs = glymur.lib._openjp2.read_tile_header(codec, stream)
tidx = rargs[0] tidx = rargs[0]
sz = rargs[1] sz = rargs[1]
go_on = rargs[-1] go_on = rargs[-1]
if not go_on: if not go_on:
break break
glymur.lib.openjp2._decode_tile_data(codec, tidx, data, sz, stream) glymur.lib._openjp2.decode_tile_data(codec, tidx, data, sz, stream)
glymur.lib.openjp2._end_decompress(codec, stream) glymur.lib._openjp2.end_decompress(codec, stream)
glymur.lib.openjp2._destroy_codec(codec) glymur.lib._openjp2.destroy_codec(codec)
glymur.lib.openjp2._stream_destroy_v3(stream) glymur.lib._openjp2.stream_destroy_v3(stream)
glymur.lib.openjp2._image_destroy(image) glymur.lib._openjp2.image_destroy(image)
def tile_encoder(self, num_comps=None, tile_width=None, tile_height=None, def tile_encoder(self, num_comps=None, tile_width=None, tile_height=None,
filename=None, codec=None, comp_prec=None, filename=None, codec=None, comp_prec=None,
@ -150,7 +144,7 @@ class TestOpenJP2(unittest.TestCase):
data = np.random.random((tile_height, tile_width, num_comps)) data = np.random.random((tile_height, tile_width, num_comps))
data = (data * 255).astype(np.uint8) data = (data * 255).astype(np.uint8)
l_param = glymur.lib.openjp2._set_default_encoder_parameters() l_param = glymur.lib._openjp2.set_default_encoder_parameters()
l_param.tcp_numlayers = 1 l_param.tcp_numlayers = 1
l_param.cp_fixed_quality = 1 l_param.cp_fixed_quality = 1
@ -170,9 +164,9 @@ class TestOpenJP2(unittest.TestCase):
l_param.numresolution = 6 l_param.numresolution = 6
l_param.prog_order = glymur.lib.openjp2.LRCP l_param.prog_order = glymur.core.LRCP
l_params = (glymur.lib.openjp2._image_comptparm_t * num_comps)() l_params = (glymur.lib._openjp2.ImageComptParmType * num_comps)()
for j in range(num_comps): for j in range(num_comps):
l_params[j].dx = 1 l_params[j].dx = 1
l_params[j].dy = 1 l_params[j].dy = 1
@ -183,38 +177,38 @@ class TestOpenJP2(unittest.TestCase):
l_params[j].x0 = 0 l_params[j].x0 = 0
l_params[j].y0 = 0 l_params[j].y0 = 0
codec = glymur.lib.openjp2._create_compress(codec) codec = glymur.lib._openjp2.create_compress(codec)
glymur.lib.openjp2._set_info_handler(codec, None) glymur.lib._openjp2.set_info_handler(codec, None)
glymur.lib.openjp2._set_warning_handler(codec, None) glymur.lib._openjp2.set_warning_handler(codec, None)
glymur.lib.openjp2._set_error_handler(codec, None) glymur.lib._openjp2.set_error_handler(codec, None)
cspace = glymur.lib.openjp2._CLRSPC_SRGB cspace = glymur.lib._openjp2.CLRSPC_SRGB
l_image = glymur.lib.openjp2._image_tile_create(l_params, cspace) l_image = glymur.lib._openjp2.image_tile_create(l_params, cspace)
l_image.contents.x0 = 0 l_image.contents.x0 = 0
l_image.contents.y0 = 0 l_image.contents.y0 = 0
l_image.contents.x1 = image_width l_image.contents.x1 = image_width
l_image.contents.y1 = image_height l_image.contents.y1 = image_height
l_image.contents.color_space = glymur.lib.openjp2._CLRSPC_SRGB l_image.contents.color_space = glymur.lib._openjp2.CLRSPC_SRGB
glymur.lib.openjp2._setup_encoder(codec, l_param, l_image) glymur.lib._openjp2.setup_encoder(codec, l_param, l_image)
x = (filename, False) x = (filename, False)
stream = glymur.lib.openjp2._stream_create_default_file_stream_v3(*x) stream = glymur.lib._openjp2.stream_create_default_file_stream_v3(*x)
glymur.lib.openjp2._start_compress(codec, l_image, stream) glymur.lib._openjp2.start_compress(codec, l_image, stream)
for j in np.arange(num_tiles): for j in np.arange(num_tiles):
glymur.lib.openjp2._write_tile(codec, j, data, tile_size, stream) glymur.lib._openjp2.write_tile(codec, j, data, tile_size, stream)
glymur.lib.openjp2._end_compress(codec, stream) glymur.lib._openjp2.end_compress(codec, stream)
glymur.lib.openjp2._stream_destroy_v3(stream) glymur.lib._openjp2.stream_destroy_v3(stream)
glymur.lib.openjp2._destroy_codec(codec) glymur.lib._openjp2.destroy_codec(codec)
glymur.lib.openjp2._image_destroy(l_image) glymur.lib._openjp2.image_destroy(l_image)
def tte0_setup(self, filename): def tte0_setup(self, filename):
kwargs = {'filename': filename, kwargs = {'filename': filename,
'codec': glymur.lib.openjp2._CODEC_J2K, 'codec': glymur.lib._openjp2.CODEC_J2K,
'comp_prec': 8, 'comp_prec': 8,
'irreversible': 1, 'irreversible': 1,
'num_comps': 3, 'num_comps': 3,
@ -241,12 +235,12 @@ class TestOpenJP2(unittest.TestCase):
'x1': 1000, 'x1': 1000,
'y1': 1000, 'y1': 1000,
'filename': tfile.name, 'filename': tfile.name,
'codec_format': glymur.lib.openjp2._CODEC_J2K} 'codec_format': glymur.lib._openjp2.CODEC_J2K}
self.tile_decoder(**kwargs) self.tile_decoder(**kwargs)
def tte1_setup(self, filename): def tte1_setup(self, filename):
kwargs = {'filename': filename, kwargs = {'filename': filename,
'codec': glymur.lib.openjp2._CODEC_J2K, 'codec': glymur.lib._openjp2.CODEC_J2K,
'comp_prec': 8, 'comp_prec': 8,
'irreversible': 1, 'irreversible': 1,
'num_comps': 3, 'num_comps': 3,
@ -273,7 +267,7 @@ class TestOpenJP2(unittest.TestCase):
'x1': 128, 'x1': 128,
'y1': 128, 'y1': 128,
'filename': tfile.name, 'filename': tfile.name,
'codec_format': glymur.lib.openjp2._CODEC_J2K} 'codec_format': glymur.lib._openjp2.CODEC_J2K}
self.tile_decoder(**kwargs) self.tile_decoder(**kwargs)
def test_rta1(self): def test_rta1(self):
@ -281,12 +275,12 @@ class TestOpenJP2(unittest.TestCase):
# Runs test designated rta1 in OpenJPEG test suite. # Runs test designated rta1 in OpenJPEG test suite.
self.tte1_setup(tfile.name) self.tte1_setup(tfile.name)
kwargs = {'codec_format': glymur.lib.openjp2._CODEC_J2K} kwargs = {'codec_format': glymur.lib._openjp2.CODEC_J2K}
self.j2k_random_tile_access(tfile.name, **kwargs) self.j2k_random_tile_access(tfile.name, **kwargs)
def tte2_setup(self, filename): def tte2_setup(self, filename):
kwargs = {'filename': filename, kwargs = {'filename': filename,
'codec': glymur.lib.openjp2._CODEC_JP2, 'codec': glymur.lib._openjp2.CODEC_JP2,
'comp_prec': 8, 'comp_prec': 8,
'irreversible': 1, 'irreversible': 1,
'num_comps': 3, 'num_comps': 3,
@ -312,7 +306,7 @@ class TestOpenJP2(unittest.TestCase):
'x1': 128, 'x1': 128,
'y1': 128, 'y1': 128,
'filename': tfile.name, 'filename': tfile.name,
'codec_format': glymur.lib.openjp2._CODEC_JP2} 'codec_format': glymur.lib._openjp2.CODEC_JP2}
self.tile_decoder(**kwargs) self.tile_decoder(**kwargs)
def test_rta2(self): def test_rta2(self):
@ -320,12 +314,12 @@ class TestOpenJP2(unittest.TestCase):
# Runs test designated rta2 in OpenJPEG test suite. # Runs test designated rta2 in OpenJPEG test suite.
self.tte2_setup(tfile.name) self.tte2_setup(tfile.name)
kwargs = {'codec_format': glymur.lib.openjp2._CODEC_JP2} kwargs = {'codec_format': glymur.lib._openjp2.CODEC_JP2}
self.j2k_random_tile_access(tfile.name, **kwargs) self.j2k_random_tile_access(tfile.name, **kwargs)
def tte3_setup(self, filename): def tte3_setup(self, filename):
kwargs = {'filename': filename, kwargs = {'filename': filename,
'codec': glymur.lib.openjp2._CODEC_J2K, 'codec': glymur.lib._openjp2.CODEC_J2K,
'comp_prec': 8, 'comp_prec': 8,
'irreversible': 1, 'irreversible': 1,
'num_comps': 1, 'num_comps': 1,
@ -345,12 +339,12 @@ class TestOpenJP2(unittest.TestCase):
with tempfile.NamedTemporaryFile(suffix=".j2k") as tfile: with tempfile.NamedTemporaryFile(suffix=".j2k") as tfile:
self.tte3_setup(tfile.name) self.tte3_setup(tfile.name)
kwargs = {'codec_format': glymur.lib.openjp2._CODEC_J2K} kwargs = {'codec_format': glymur.lib._openjp2.CODEC_J2K}
self.j2k_random_tile_access(tfile.name, **kwargs) self.j2k_random_tile_access(tfile.name, **kwargs)
def tte4_setup(self, filename): def tte4_setup(self, filename):
kwargs = {'filename': filename, kwargs = {'filename': filename,
'codec': glymur.lib.openjp2._CODEC_J2K, 'codec': glymur.lib._openjp2.CODEC_J2K,
'comp_prec': 8, 'comp_prec': 8,
'irreversible': 0, 'irreversible': 0,
'num_comps': 1, 'num_comps': 1,
@ -370,12 +364,12 @@ class TestOpenJP2(unittest.TestCase):
with tempfile.NamedTemporaryFile(suffix=".j2k") as tfile: with tempfile.NamedTemporaryFile(suffix=".j2k") as tfile:
self.tte4_setup(tfile.name) self.tte4_setup(tfile.name)
kwargs = {'codec_format': glymur.lib.openjp2._CODEC_J2K} kwargs = {'codec_format': glymur.lib._openjp2.CODEC_J2K}
self.j2k_random_tile_access(tfile.name, **kwargs) self.j2k_random_tile_access(tfile.name, **kwargs)
def tte5_setup(self, filename): def tte5_setup(self, filename):
kwargs = {'filename': filename, kwargs = {'filename': filename,
'codec': glymur.lib.openjp2._CODEC_J2K, 'codec': glymur.lib._openjp2.CODEC_J2K,
'comp_prec': 8, 'comp_prec': 8,
'irreversible': 0, 'irreversible': 0,
'num_comps': 1, 'num_comps': 1,
@ -395,7 +389,7 @@ class TestOpenJP2(unittest.TestCase):
with tempfile.NamedTemporaryFile(suffix=".j2k") as tfile: with tempfile.NamedTemporaryFile(suffix=".j2k") as tfile:
self.tte5_setup(tfile.name) self.tte5_setup(tfile.name)
kwargs = {'codec_format': glymur.lib.openjp2._CODEC_J2K} kwargs = {'codec_format': glymur.lib._openjp2.CODEC_J2K}
self.j2k_random_tile_access(tfile.name, **kwargs) self.j2k_random_tile_access(tfile.name, **kwargs)
if __name__ == "__main__": if __name__ == "__main__":

View file

@ -3,7 +3,7 @@ import unittest
import glymur import glymur
@unittest.skipIf(glymur.lib.openjpeg._OPENJPEG is None, @unittest.skipIf(glymur.lib._openjpeg.OPENJPEG is None,
"Missing openjpeg library.") "Missing openjpeg library.")
class TestOpenJPEG(unittest.TestCase): class TestOpenJPEG(unittest.TestCase):
@ -14,15 +14,15 @@ class TestOpenJPEG(unittest.TestCase):
pass pass
def test_version(self): def test_version(self):
v = glymur.lib.openjpeg._version() v = glymur.lib._openjpeg.version()
parts = v.split('.') parts = v.split('.')
self.assertEqual(parts[0], '1') self.assertEqual(parts[0], '1')
self.assertEqual(parts[1], '5') self.assertEqual(parts[1], '5')
def test_set_default_decoder_parameters(self): def test_set_default_decoder_parameters(self):
# Verify that we properly set the default decode parameters. # Verify that we properly set the default decode parameters.
dp = glymur.lib.openjpeg.dparameters_t() dp = glymur.lib._openjpeg.DecompressionParametersType()
glymur.lib.openjpeg._set_default_decoder_parameters(ctypes.byref(dp)) glymur.lib._openjpeg.set_default_decoder_parameters(ctypes.byref(dp))
self.assertEqual(dp.cp_reduce, 0) self.assertEqual(dp.cp_reduce, 0)
self.assertEqual(dp.cp_layer, 0) self.assertEqual(dp.cp_layer, 0)

View file

@ -5,6 +5,7 @@ from .test_jp2k import TestJp2k as jp2k
from .test_icc import TestICC as icc from .test_icc import TestICC as icc
from .test_printing import TestPrinting as printing from .test_printing import TestPrinting as printing
from .test_opj_suite import TestSuite as suite from .test_opj_suite import TestSuite as suite
from .test_opj_suite import TestSuiteDump as suitedump
from .test_opj_suite_write import TestSuiteWrite as suitew from .test_opj_suite_write import TestSuiteWrite as suitew
from .test_opj_suite_neg import TestSuiteNegative as suiteneg from .test_opj_suite_neg import TestSuiteNegative as suiteneg
from .test_jp2box import TestJp2Boxes as box from .test_jp2box import TestJp2Boxes as box

View file

@ -14,7 +14,7 @@ else:
import glymur import glymur
@unittest.skipIf(glymur.lib.openjp2._OPENJP2 is None, @unittest.skipIf(glymur.lib.openjp2.OPENJP2 is None,
"Missing openjp2 library.") "Missing openjp2 library.")
class TestCallbacks(unittest.TestCase): class TestCallbacks(unittest.TestCase):
@ -46,7 +46,7 @@ class TestCallbacks(unittest.TestCase):
# Verify that we get the expected stdio output when our internal info # Verify that we get the expected stdio output when our internal info
# callback handler is enabled. # callback handler is enabled.
j = glymur.Jp2k(self.j2kfile) j = glymur.Jp2k(self.j2kfile)
d = j.read(reduce=1, verbose=True, area=(0, 0, 200, 150)) d = j.read(rlevel=1, verbose=True, area=(0, 0, 200, 150))
actual = sys.stdout.getvalue().strip() actual = sys.stdout.getvalue().strip()
lines = ['[INFO] Start to read j2k main header (0).', lines = ['[INFO] Start to read j2k main header (0).',
@ -60,7 +60,7 @@ class TestCallbacks(unittest.TestCase):
self.assertEqual(actual, expected) self.assertEqual(actual, expected)
@unittest.skipIf(glymur.lib.openjp2._OPENJPEG is None, @unittest.skipIf(glymur.lib.openjp2.OPENJPEG is None,
"Missing openjpeg library.") "Missing openjpeg library.")
class TestCallbacks15(unittest.TestCase): class TestCallbacks15(unittest.TestCase):
"""This test suite is for OpenJPEG 1.5.1 properties. """This test suite is for OpenJPEG 1.5.1 properties.
@ -69,13 +69,13 @@ class TestCallbacks15(unittest.TestCase):
@classmethod @classmethod
def setUpClass(cls): def setUpClass(cls):
# Monkey patch the package so as to use OPENJPEG instead of OPENJP2 # Monkey patch the package so as to use OPENJPEG instead of OPENJP2
cls.openjp2 = glymur.lib.openjp2._OPENJP2 cls.openjp2 = glymur.lib.openjp2.OPENJP2
glymur.lib.openjp2._OPENJP2 = None glymur.lib.openjp2.OPENJP2 = None
@classmethod @classmethod
def tearDownClass(cls): def tearDownClass(cls):
# Restore OPENJP2 # Restore OPENJP2
glymur.lib.openjp2._OPENJP2 = cls.openjp2 glymur.lib.openjp2.OPENJP2 = cls.openjp2
def setUp(self): def setUp(self):
# Save sys.stdout. # Save sys.stdout.
@ -92,7 +92,7 @@ class TestCallbacks15(unittest.TestCase):
# Verify that we get the expected stdio output when our internal info # Verify that we get the expected stdio output when our internal info
# callback handler is enabled. # callback handler is enabled.
j = glymur.Jp2k(self.j2kfile) j = glymur.Jp2k(self.j2kfile)
d = j.read(reduce=1, verbose=True) d = j.read(rlevel=1, verbose=True)
actual = sys.stdout.getvalue().strip() actual = sys.stdout.getvalue().strip()
regex = re.compile(r"""\[INFO\]\stile\s1\sof\s1\s+ regex = re.compile(r"""\[INFO\]\stile\s1\sof\s1\s+

View file

@ -54,9 +54,9 @@ class TestCodestream(unittest.TestCase):
j = Jp2k(tfile.name) j = Jp2k(tfile.name)
c = j.get_codestream() c = j.get_codestream()
self.assertEqual(c.segment[2].id, '0xff6f') self.assertEqual(c.segment[2].marker_id, '0xff6f')
self.assertEqual(c.segment[2].length, 3) self.assertEqual(c.segment[2].length, 3)
self.assertEqual(c.segment[2].data, b'\x00') self.assertEqual(c.segment[2]._data, b'\x00')
@unittest.skipIf(sys.hexversion < 0x03020000, @unittest.skipIf(sys.hexversion < 0x03020000,
"Uses features introduced in 3.2.") "Uses features introduced in 3.2.")
@ -84,9 +84,9 @@ class TestCodestream(unittest.TestCase):
j = Jp2k(tfile.name) j = Jp2k(tfile.name)
c = j.get_codestream() c = j.get_codestream()
self.assertEqual(c.segment[2].id, '0xff79') self.assertEqual(c.segment[2].marker_id, '0xff79')
self.assertEqual(c.segment[2].length, 3) self.assertEqual(c.segment[2].length, 3)
self.assertEqual(c.segment[2].data, b'\x00') self.assertEqual(c.segment[2]._data, b'\x00')
if __name__ == "__main__": if __name__ == "__main__":
unittest.main() unittest.main()

View file

@ -21,7 +21,7 @@ from glymur.lib import openjp2 as opj2
@unittest.skip("Cannot work when both OPENJPEG and OPENJP2 are both present.") @unittest.skip("Cannot work when both OPENJPEG and OPENJP2 are both present.")
@unittest.skipIf(glymur.lib.openjp2._OPENJP2 is None, @unittest.skipIf(glymur.lib.openjp2.OPENJP2 is None,
"Needs openjp2 library first before these tests make sense.") "Needs openjp2 library first before these tests make sense.")
@unittest.skipIf(sys.hexversion < 0x03020000, @unittest.skipIf(sys.hexversion < 0x03020000,
"Uses features introduced in 3.2.") "Uses features introduced in 3.2.")
@ -55,7 +55,7 @@ class TestSuite(unittest.TestCase):
filename = os.path.join(configdir, 'glymurrc') filename = os.path.join(configdir, 'glymurrc')
with open(filename, 'wb') as tfile: with open(filename, 'wb') as tfile:
tfile.write('[library]\n'.encode()) tfile.write('[library]\n'.encode())
libloc = glymur.lib.openjp2._OPENJP2._name libloc = glymur.lib.openjp2.OPENJP2._name
line = 'openjp2: {0}\n'.format(libloc) line = 'openjp2: {0}\n'.format(libloc)
tfile.write(line.encode()) tfile.write(line.encode())
tfile.flush() tfile.flush()

View file

@ -18,7 +18,7 @@ def load_tests(loader, tests, ignore):
return tests return tests
@unittest.skipIf(glymur.lib.openjp2._OPENJP2 is None, @unittest.skipIf(glymur.lib.openjp2.OPENJP2 is None,
"Missing openjp2 library.") "Missing openjp2 library.")
class TestChannelDefinition(unittest.TestCase): class TestChannelDefinition(unittest.TestCase):
@ -58,9 +58,9 @@ class TestChannelDefinition(unittest.TestCase):
j2k = Jp2k(self.j2kfile) j2k = Jp2k(self.j2kfile)
c = j2k.get_codestream() c = j2k.get_codestream()
height = c.segment[1].Ysiz height = c.segment[1].ysiz
width = c.segment[1].Xsiz width = c.segment[1].xsiz
num_components = len(c.segment[1].XRsiz) num_components = len(c.segment[1].xrsiz)
self.jP = JPEG2000SignatureBox() self.jP = JPEG2000SignatureBox()
self.ftyp = FileTypeBox() self.ftyp = FileTypeBox()
@ -88,7 +88,7 @@ class TestChannelDefinition(unittest.TestCase):
jp2 = Jp2k(tfile.name) jp2 = Jp2k(tfile.name)
jp2h = jp2.box[2] jp2h = jp2.box[2]
boxes = [box.id for box in jp2h.box] boxes = [box.box_id for box in jp2h.box]
self.assertEqual(boxes, ['ihdr', 'colr', 'cdef']) self.assertEqual(boxes, ['ihdr', 'colr', 'cdef'])
self.assertEqual(jp2h.box[2].index, (0, 1, 2)) self.assertEqual(jp2h.box[2].index, (0, 1, 2))
self.assertEqual(jp2h.box[2].channel_type, (0, 0, 0)) self.assertEqual(jp2h.box[2].channel_type, (0, 0, 0))
@ -108,7 +108,7 @@ class TestChannelDefinition(unittest.TestCase):
jp2 = Jp2k(tfile.name) jp2 = Jp2k(tfile.name)
jp2h = jp2.box[2] jp2h = jp2.box[2]
boxes = [box.id for box in jp2h.box] boxes = [box.box_id for box in jp2h.box]
self.assertEqual(boxes, ['ihdr', 'colr', 'cdef']) self.assertEqual(boxes, ['ihdr', 'colr', 'cdef'])
self.assertEqual(jp2h.box[2].index, (0, 1, 2, 3)) self.assertEqual(jp2h.box[2].index, (0, 1, 2, 3))
self.assertEqual(jp2h.box[2].channel_type, (0, 0, 0, 1)) self.assertEqual(jp2h.box[2].channel_type, (0, 0, 0, 1))
@ -141,7 +141,7 @@ class TestChannelDefinition(unittest.TestCase):
jp2 = Jp2k(tfile.name) jp2 = Jp2k(tfile.name)
jp2h = jp2.box[2] jp2h = jp2.box[2]
boxes = [box.id for box in jp2h.box] boxes = [box.box_id for box in jp2h.box]
self.assertEqual(boxes, ['ihdr', 'colr', 'cdef']) self.assertEqual(boxes, ['ihdr', 'colr', 'cdef'])
self.assertEqual(jp2h.box[2].index, (0,)) self.assertEqual(jp2h.box[2].index, (0,))
self.assertEqual(jp2h.box[2].channel_type, (0,)) self.assertEqual(jp2h.box[2].channel_type, (0,))
@ -161,7 +161,7 @@ class TestChannelDefinition(unittest.TestCase):
jp2 = Jp2k(tfile.name) jp2 = Jp2k(tfile.name)
jp2h = jp2.box[2] jp2h = jp2.box[2]
boxes = [box.id for box in jp2h.box] boxes = [box.box_id for box in jp2h.box]
self.assertEqual(boxes, ['ihdr', 'colr', 'cdef']) self.assertEqual(boxes, ['ihdr', 'colr', 'cdef'])
self.assertEqual(jp2h.box[2].index, (0, 1)) self.assertEqual(jp2h.box[2].index, (0, 1))
self.assertEqual(jp2h.box[2].channel_type, (0, 1)) self.assertEqual(jp2h.box[2].channel_type, (0, 1))
@ -268,9 +268,9 @@ class TestXML(unittest.TestCase):
j2k = Jp2k(self.j2kfile) j2k = Jp2k(self.j2kfile)
c = j2k.get_codestream() c = j2k.get_codestream()
height = c.segment[1].Ysiz height = c.segment[1].ysiz
width = c.segment[1].Xsiz width = c.segment[1].xsiz
num_components = len(c.segment[1].XRsiz) num_components = len(c.segment[1].xrsiz)
self.jP = JPEG2000SignatureBox() self.jP = JPEG2000SignatureBox()
self.ftyp = FileTypeBox() self.ftyp = FileTypeBox()
@ -309,7 +309,7 @@ class TestXML(unittest.TestCase):
with tempfile.NamedTemporaryFile(suffix=".jp2") as tfile: with tempfile.NamedTemporaryFile(suffix=".jp2") as tfile:
j2k.wrap(tfile.name, boxes=boxes) j2k.wrap(tfile.name, boxes=boxes)
jp2 = Jp2k(tfile.name) jp2 = Jp2k(tfile.name)
self.assertEqual(jp2.box[3].id, 'xml ') self.assertEqual(jp2.box[3].box_id, 'xml ')
self.assertEqual(ET.tostring(jp2.box[3].xml), self.assertEqual(ET.tostring(jp2.box[3].xml),
b'<data>0</data>') b'<data>0</data>')
@ -326,7 +326,7 @@ class TestXML(unittest.TestCase):
j2k.wrap(tfile.name, boxes=boxes) j2k.wrap(tfile.name, boxes=boxes)
jp2 = Jp2k(tfile.name) jp2 = Jp2k(tfile.name)
output_boxes = [box.id for box in jp2.box] output_boxes = [box.box_id for box in jp2.box]
self.assertEqual(output_boxes, ['jP ', 'ftyp', 'jp2h', 'xml ', self.assertEqual(output_boxes, ['jP ', 'ftyp', 'jp2h', 'xml ',
'jp2c']) 'jp2c'])
@ -345,9 +345,9 @@ class TestColourSpecificationBox(unittest.TestCase):
j2k = Jp2k(self.j2kfile) j2k = Jp2k(self.j2kfile)
c = j2k.get_codestream() c = j2k.get_codestream()
height = c.segment[1].Ysiz height = c.segment[1].ysiz
width = c.segment[1].Xsiz width = c.segment[1].xsiz
num_components = len(c.segment[1].XRsiz) num_components = len(c.segment[1].xrsiz)
self.jP = JPEG2000SignatureBox() self.jP = JPEG2000SignatureBox()
self.ftyp = FileTypeBox() self.ftyp = FileTypeBox()
@ -409,7 +409,7 @@ class TestColourSpecificationBox(unittest.TestCase):
approximation=approx) approximation=approx)
@unittest.skipIf(glymur.lib.openjp2._OPENJP2 is None, @unittest.skipIf(glymur.lib.openjp2.OPENJP2 is None,
"Missing openjp2 library.") "Missing openjp2 library.")
class TestJp2Boxes(unittest.TestCase): class TestJp2Boxes(unittest.TestCase):
@ -449,37 +449,37 @@ class TestJp2Boxes(unittest.TestCase):
def test_default_ContiguousCodestreamBox(self): def test_default_ContiguousCodestreamBox(self):
b = ContiguousCodestreamBox() b = ContiguousCodestreamBox()
self.assertEqual(b.id, 'jp2c') self.assertEqual(b.box_id, 'jp2c')
self.assertEqual(b.main_header, []) self.assertIsNone(b.main_header)
def verify_wrapped_raw(self, jp2file): def verify_wrapped_raw(self, jp2file):
# Shared method by at least two tests. # Shared method by at least two tests.
jp2 = Jp2k(jp2file) jp2 = Jp2k(jp2file)
self.assertEqual(len(jp2.box), 4) self.assertEqual(len(jp2.box), 4)
self.assertEqual(jp2.box[0].id, 'jP ') self.assertEqual(jp2.box[0].box_id, 'jP ')
self.assertEqual(jp2.box[0].offset, 0) self.assertEqual(jp2.box[0].offset, 0)
self.assertEqual(jp2.box[0].length, 12) self.assertEqual(jp2.box[0].length, 12)
self.assertEqual(jp2.box[0].longname, 'JPEG 2000 Signature') self.assertEqual(jp2.box[0].longname, 'JPEG 2000 Signature')
self.assertEqual(jp2.box[1].id, 'ftyp') self.assertEqual(jp2.box[1].box_id, 'ftyp')
self.assertEqual(jp2.box[1].offset, 12) self.assertEqual(jp2.box[1].offset, 12)
self.assertEqual(jp2.box[1].length, 20) self.assertEqual(jp2.box[1].length, 20)
self.assertEqual(jp2.box[1].longname, 'File Type') self.assertEqual(jp2.box[1].longname, 'File Type')
self.assertEqual(jp2.box[2].id, 'jp2h') self.assertEqual(jp2.box[2].box_id, 'jp2h')
self.assertEqual(jp2.box[2].offset, 32) self.assertEqual(jp2.box[2].offset, 32)
self.assertEqual(jp2.box[2].length, 45) self.assertEqual(jp2.box[2].length, 45)
self.assertEqual(jp2.box[2].longname, 'JP2 Header') self.assertEqual(jp2.box[2].longname, 'JP2 Header')
self.assertEqual(jp2.box[3].id, 'jp2c') self.assertEqual(jp2.box[3].box_id, 'jp2c')
self.assertEqual(jp2.box[3].offset, 77) self.assertEqual(jp2.box[3].offset, 77)
self.assertEqual(jp2.box[3].length, 115228) self.assertEqual(jp2.box[3].length, 115228)
# jp2h super box # jp2h super box
self.assertEqual(len(jp2.box[2].box), 2) self.assertEqual(len(jp2.box[2].box), 2)
self.assertEqual(jp2.box[2].box[0].id, 'ihdr') self.assertEqual(jp2.box[2].box[0].box_id, 'ihdr')
self.assertEqual(jp2.box[2].box[0].offset, 40) self.assertEqual(jp2.box[2].box[0].offset, 40)
self.assertEqual(jp2.box[2].box[0].length, 22) self.assertEqual(jp2.box[2].box[0].length, 22)
self.assertEqual(jp2.box[2].box[0].longname, 'Image Header') self.assertEqual(jp2.box[2].box[0].longname, 'Image Header')
@ -492,7 +492,7 @@ class TestJp2Boxes(unittest.TestCase):
self.assertEqual(jp2.box[2].box[0].colorspace_unknown, False) self.assertEqual(jp2.box[2].box[0].colorspace_unknown, False)
self.assertEqual(jp2.box[2].box[0].ip_provided, False) self.assertEqual(jp2.box[2].box[0].ip_provided, False)
self.assertEqual(jp2.box[2].box[1].id, 'colr') self.assertEqual(jp2.box[2].box[1].box_id, 'colr')
self.assertEqual(jp2.box[2].box[1].offset, 62) self.assertEqual(jp2.box[2].box[1].offset, 62)
self.assertEqual(jp2.box[2].box[1].length, 15) self.assertEqual(jp2.box[2].box[1].length, 15)
self.assertEqual(jp2.box[2].box[1].longname, 'Colour Specification') self.assertEqual(jp2.box[2].box[1].longname, 'Colour Specification')
@ -511,7 +511,7 @@ class TestJp2Boxes(unittest.TestCase):
j2k = Jp2k(self.j2kfile) j2k = Jp2k(self.j2kfile)
with tempfile.NamedTemporaryFile(suffix=".jp2") as tfile: with tempfile.NamedTemporaryFile(suffix=".jp2") as tfile:
jp2 = j2k.wrap(tfile.name) jp2 = j2k.wrap(tfile.name)
boxes = [box.id for box in jp2.box] boxes = [box.box_id for box in jp2.box]
self.assertEqual(boxes, ['jP ', 'ftyp', 'jp2h', 'jp2c']) self.assertEqual(boxes, ['jP ', 'ftyp', 'jp2h', 'jp2c'])
def test_default_layout_but_with_specified_boxes(self): def test_default_layout_but_with_specified_boxes(self):
@ -521,9 +521,9 @@ class TestJp2Boxes(unittest.TestCase):
JP2HeaderBox(), JP2HeaderBox(),
ContiguousCodestreamBox()] ContiguousCodestreamBox()]
c = j2k.get_codestream() c = j2k.get_codestream()
height = c.segment[1].Ysiz height = c.segment[1].ysiz
width = c.segment[1].Xsiz width = c.segment[1].xsiz
num_components = len(c.segment[1].XRsiz) num_components = len(c.segment[1].xrsiz)
boxes[2].box = [ImageHeaderBox(height=height, boxes[2].box = [ImageHeaderBox(height=height,
width=width, width=width,
num_components=num_components), num_components=num_components),
@ -540,9 +540,9 @@ class TestJp2Boxes(unittest.TestCase):
JP2HeaderBox(), JP2HeaderBox(),
ContiguousCodestreamBox()] ContiguousCodestreamBox()]
c = j2k.get_codestream() c = j2k.get_codestream()
height = c.segment[1].Ysiz height = c.segment[1].ysiz
width = c.segment[1].Xsiz width = c.segment[1].xsiz
num_components = len(c.segment[1].XRsiz) num_components = len(c.segment[1].xrsiz)
boxes[2].box = [ColourSpecificationBox(colorspace=glymur.core.SRGB), boxes[2].box = [ColourSpecificationBox(colorspace=glymur.core.SRGB),
ImageHeaderBox(height=height, ImageHeaderBox(height=height,
width=width, width=width,
@ -554,9 +554,9 @@ class TestJp2Boxes(unittest.TestCase):
def test_first_2_boxes_not_jP_and_ftyp(self): def test_first_2_boxes_not_jP_and_ftyp(self):
j2k = Jp2k(self.j2kfile) j2k = Jp2k(self.j2kfile)
c = j2k.get_codestream() c = j2k.get_codestream()
height = c.segment[1].Ysiz height = c.segment[1].ysiz
width = c.segment[1].Xsiz width = c.segment[1].xsiz
num_components = len(c.segment[1].XRsiz) num_components = len(c.segment[1].xrsiz)
jP = JPEG2000SignatureBox() jP = JPEG2000SignatureBox()
ftyp = FileTypeBox() ftyp = FileTypeBox()
@ -574,9 +574,9 @@ class TestJp2Boxes(unittest.TestCase):
def test_jp2h_not_preceeding_jp2c(self): def test_jp2h_not_preceeding_jp2c(self):
j2k = Jp2k(self.j2kfile) j2k = Jp2k(self.j2kfile)
c = j2k.get_codestream() c = j2k.get_codestream()
height = c.segment[1].Ysiz height = c.segment[1].ysiz
width = c.segment[1].Xsiz width = c.segment[1].xsiz
num_components = len(c.segment[1].XRsiz) num_components = len(c.segment[1].xrsiz)
jP = JPEG2000SignatureBox() jP = JPEG2000SignatureBox()
ftyp = FileTypeBox() ftyp = FileTypeBox()
@ -594,9 +594,9 @@ class TestJp2Boxes(unittest.TestCase):
def test_missing_codestream(self): def test_missing_codestream(self):
j2k = Jp2k(self.j2kfile) j2k = Jp2k(self.j2kfile)
c = j2k.get_codestream() c = j2k.get_codestream()
height = c.segment[1].Ysiz height = c.segment[1].ysiz
width = c.segment[1].Xsiz width = c.segment[1].xsiz
num_components = len(c.segment[1].XRsiz) num_components = len(c.segment[1].xrsiz)
jP = JPEG2000SignatureBox() jP = JPEG2000SignatureBox()
ftyp = FileTypeBox() ftyp = FileTypeBox()

View file

@ -33,12 +33,12 @@ except:
# 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):
if glymur.lib.openjp2._OPENJP2 is not None: if glymur.lib.openjp2.OPENJP2 is not None:
tests.addTests(doctest.DocTestSuite('glymur.jp2k')) tests.addTests(doctest.DocTestSuite('glymur.jp2k'))
return tests return tests
@unittest.skipIf(glymur.lib.openjp2._OPENJP2 is None, @unittest.skipIf(glymur.lib.openjp2.OPENJP2 is None,
"Missing openjp2 library.") "Missing openjp2 library.")
class TestJp2k(unittest.TestCase): class TestJp2k(unittest.TestCase):
@ -88,11 +88,11 @@ class TestJp2k(unittest.TestCase):
with self.assertWarns(UserWarning) as cw: with self.assertWarns(UserWarning) as cw:
jp2k = Jp2k(self._bad_xml_file) jp2k = Jp2k(self._bad_xml_file)
def test_reduce_max(self): def test_rlevel_max(self):
# Verify that reduce=-1 gets us the lowest resolution image # Verify that rlevel=-1 gets us the lowest resolution image
j = Jp2k(self.j2kfile) j = Jp2k(self.j2kfile)
thumbnail1 = j.read(reduce=-1) thumbnail1 = j.read(rlevel=-1)
thumbnail2 = j.read(reduce=5) thumbnail2 = j.read(rlevel=5)
np.testing.assert_array_equal(thumbnail1, thumbnail2) np.testing.assert_array_equal(thumbnail1, thumbnail2)
self.assertEqual(thumbnail1.shape, (25, 15, 3)) self.assertEqual(thumbnail1.shape, (25, 15, 3))
@ -102,7 +102,7 @@ class TestJp2k(unittest.TestCase):
warnings.simplefilter("ignore") warnings.simplefilter("ignore")
jp2k = Jp2k(self._bad_xml_file) jp2k = Jp2k(self._bad_xml_file)
self.assertEqual(jp2k.box[3].id, 'xml ') self.assertEqual(jp2k.box[3].box_id, 'xml ')
self.assertEqual(jp2k.box[3].offset, 77) self.assertEqual(jp2k.box[3].offset, 77)
self.assertEqual(jp2k.box[3].length, 28) self.assertEqual(jp2k.box[3].length, 28)
self.assertIsNone(jp2k.box[3].xml) self.assertIsNone(jp2k.box[3].xml)
@ -120,11 +120,11 @@ class TestJp2k(unittest.TestCase):
# End corner must be >= start corner # End corner must be >= start corner
d = j.read(area=(10, 10, 8, 8)) d = j.read(area=(10, 10, 8, 8))
def test_reduce_too_high(self): def test_rlevel_too_high(self):
# Verify that we error out appropriately if not given a JPEG 2000 file. # Verify that we error out appropriately if not given a JPEG 2000 file.
j = Jp2k(self.jp2file) j = Jp2k(self.jp2file)
with self.assertRaises(IOError): with self.assertRaises(IOError):
d = j.read(reduce=6) d = j.read(rlevel=6)
def test_not_JPEG2000(self): def test_not_JPEG2000(self):
# Verify that we error out appropriately if not given a JPEG 2000 file. # Verify that we error out appropriately if not given a JPEG 2000 file.
@ -153,7 +153,7 @@ class TestJp2k(unittest.TestCase):
np.testing.assert_array_equal(actdata, expdata) np.testing.assert_array_equal(actdata, expdata)
c = ofile.get_codestream() c = ofile.get_codestream()
self.assertEqual(c.segment[2].SPcod[3], 0) # no mct self.assertEqual(c.segment[2].spcod[3], 0) # no mct
def test_write_grayscale_with_mct(self): def test_write_grayscale_with_mct(self):
# MCT usage makes no sense for grayscale images. # MCT usage makes no sense for grayscale images.
@ -167,7 +167,7 @@ class TestJp2k(unittest.TestCase):
def test_write_cprl(self): def test_write_cprl(self):
# Issue 17 # Issue 17
j = Jp2k(self.jp2file) j = Jp2k(self.jp2file)
expdata = j.read(reduce=1) expdata = j.read(rlevel=1)
with tempfile.NamedTemporaryFile(suffix='.jp2') as tfile: with tempfile.NamedTemporaryFile(suffix='.jp2') as tfile:
ofile = Jp2k(tfile.name, 'wb') ofile = Jp2k(tfile.name, 'wb')
ofile.write(expdata, prog='CPRL') ofile.write(expdata, prog='CPRL')
@ -175,7 +175,7 @@ class TestJp2k(unittest.TestCase):
np.testing.assert_array_equal(actdata, expdata) np.testing.assert_array_equal(actdata, expdata)
c = ofile.get_codestream() c = ofile.get_codestream()
self.assertEqual(c.segment[2].SPcod[0], glymur.core.CPRL) self.assertEqual(c.segment[2].spcod[0], glymur.core.CPRL)
def test_jp2_boxes(self): def test_jp2_boxes(self):
# Verify the boxes of a JP2 file. # Verify the boxes of a JP2 file.
@ -184,37 +184,37 @@ class TestJp2k(unittest.TestCase):
# top-level boxes # top-level boxes
self.assertEqual(len(jp2k.box), 6) self.assertEqual(len(jp2k.box), 6)
self.assertEqual(jp2k.box[0].id, 'jP ') self.assertEqual(jp2k.box[0].box_id, 'jP ')
self.assertEqual(jp2k.box[0].offset, 0) self.assertEqual(jp2k.box[0].offset, 0)
self.assertEqual(jp2k.box[0].length, 12) self.assertEqual(jp2k.box[0].length, 12)
self.assertEqual(jp2k.box[0].longname, 'JPEG 2000 Signature') self.assertEqual(jp2k.box[0].longname, 'JPEG 2000 Signature')
self.assertEqual(jp2k.box[1].id, 'ftyp') self.assertEqual(jp2k.box[1].box_id, 'ftyp')
self.assertEqual(jp2k.box[1].offset, 12) self.assertEqual(jp2k.box[1].offset, 12)
self.assertEqual(jp2k.box[1].length, 20) self.assertEqual(jp2k.box[1].length, 20)
self.assertEqual(jp2k.box[1].longname, 'File Type') self.assertEqual(jp2k.box[1].longname, 'File Type')
self.assertEqual(jp2k.box[2].id, 'jp2h') self.assertEqual(jp2k.box[2].box_id, 'jp2h')
self.assertEqual(jp2k.box[2].offset, 32) self.assertEqual(jp2k.box[2].offset, 32)
self.assertEqual(jp2k.box[2].length, 45) self.assertEqual(jp2k.box[2].length, 45)
self.assertEqual(jp2k.box[2].longname, 'JP2 Header') self.assertEqual(jp2k.box[2].longname, 'JP2 Header')
self.assertEqual(jp2k.box[3].id, 'uuid') self.assertEqual(jp2k.box[3].box_id, 'uuid')
self.assertEqual(jp2k.box[3].offset, 77) self.assertEqual(jp2k.box[3].offset, 77)
self.assertEqual(jp2k.box[3].length, 638) self.assertEqual(jp2k.box[3].length, 638)
self.assertEqual(jp2k.box[4].id, 'uuid') self.assertEqual(jp2k.box[4].box_id, 'uuid')
self.assertEqual(jp2k.box[4].offset, 715) self.assertEqual(jp2k.box[4].offset, 715)
self.assertEqual(jp2k.box[4].length, 2412) self.assertEqual(jp2k.box[4].length, 2412)
self.assertEqual(jp2k.box[5].id, 'jp2c') self.assertEqual(jp2k.box[5].box_id, 'jp2c')
self.assertEqual(jp2k.box[5].offset, 3127) self.assertEqual(jp2k.box[5].offset, 3127)
self.assertEqual(jp2k.box[5].length, 1132296) self.assertEqual(jp2k.box[5].length, 1132296)
# jp2h super box # jp2h super box
self.assertEqual(len(jp2k.box[2].box), 2) self.assertEqual(len(jp2k.box[2].box), 2)
self.assertEqual(jp2k.box[2].box[0].id, 'ihdr') self.assertEqual(jp2k.box[2].box[0].box_id, 'ihdr')
self.assertEqual(jp2k.box[2].box[0].offset, 40) self.assertEqual(jp2k.box[2].box[0].offset, 40)
self.assertEqual(jp2k.box[2].box[0].length, 22) self.assertEqual(jp2k.box[2].box[0].length, 22)
self.assertEqual(jp2k.box[2].box[0].longname, 'Image Header') self.assertEqual(jp2k.box[2].box[0].longname, 'Image Header')
@ -227,7 +227,7 @@ class TestJp2k(unittest.TestCase):
self.assertEqual(jp2k.box[2].box[0].colorspace_unknown, False) self.assertEqual(jp2k.box[2].box[0].colorspace_unknown, False)
self.assertEqual(jp2k.box[2].box[0].ip_provided, False) self.assertEqual(jp2k.box[2].box[0].ip_provided, False)
self.assertEqual(jp2k.box[2].box[1].id, 'colr') self.assertEqual(jp2k.box[2].box[1].box_id, 'colr')
self.assertEqual(jp2k.box[2].box[1].offset, 62) self.assertEqual(jp2k.box[2].box[1].offset, 62)
self.assertEqual(jp2k.box[2].box[1].length, 15) self.assertEqual(jp2k.box[2].box[1].length, 15)
self.assertEqual(jp2k.box[2].box[1].longname, 'Colour Specification') self.assertEqual(jp2k.box[2].box[1].longname, 'Colour Specification')
@ -272,7 +272,7 @@ class TestJp2k(unittest.TestCase):
jp2k = Jp2k(tfile.name) jp2k = Jp2k(tfile.name)
self.assertEqual(jp2k.box[5].id, 'jp2c') self.assertEqual(jp2k.box[5].box_id, 'jp2c')
self.assertEqual(jp2k.box[5].offset, 3127) self.assertEqual(jp2k.box[5].offset, 3127)
self.assertEqual(jp2k.box[5].length, 1133427 + 8) self.assertEqual(jp2k.box[5].length, 1133427 + 8)
@ -303,8 +303,8 @@ class TestJp2k(unittest.TestCase):
# The top level boxes in each file should match. # The top level boxes in each file should match.
for j in range(len(baseline_jp2.box)): for j in range(len(baseline_jp2.box)):
self.assertEqual(new_jp2.box[j].id, self.assertEqual(new_jp2.box[j].box_id,
baseline_jp2.box[j].id) baseline_jp2.box[j].box_id)
self.assertEqual(new_jp2.box[j].offset, self.assertEqual(new_jp2.box[j].offset,
baseline_jp2.box[j].offset) baseline_jp2.box[j].offset)
self.assertEqual(new_jp2.box[j].length, self.assertEqual(new_jp2.box[j].length,
@ -344,7 +344,7 @@ class TestJp2k(unittest.TestCase):
c = j.get_codestream() c = j.get_codestream()
# Code block size is reported as XY in the codestream. # Code block size is reported as XY in the codestream.
self.assertEqual(tuple(c.segment[2].SPcod[5:7]), (3, 2)) self.assertEqual(tuple(c.segment[2].spcod[5:7]), (3, 2))
def test_negative_too_many_dimensions(self): def test_negative_too_many_dimensions(self):
# OpenJP2 only allows 2D or 3D images. # OpenJP2 only allows 2D or 3D images.
@ -479,23 +479,23 @@ class TestJp2k(unittest.TestCase):
jp2k = Jp2k(tfile.name) jp2k = Jp2k(tfile.name)
self.assertEqual(jp2k.box[3].id, 'uinf') self.assertEqual(jp2k.box[3].box_id, 'uinf')
self.assertEqual(jp2k.box[3].offset, 77) self.assertEqual(jp2k.box[3].offset, 77)
self.assertEqual(jp2k.box[3].length, 50) self.assertEqual(jp2k.box[3].length, 50)
self.assertEqual(jp2k.box[3].box[0].id, 'ulst') self.assertEqual(jp2k.box[3].box[0].box_id, 'ulst')
self.assertEqual(jp2k.box[3].box[0].offset, 85) self.assertEqual(jp2k.box[3].box[0].offset, 85)
self.assertEqual(jp2k.box[3].box[0].length, 26) self.assertEqual(jp2k.box[3].box[0].length, 26)
ulst = [] ulst = []
ulst.append(uuid.UUID('00000000-0000-0000-0000-000000000000')) ulst.append(uuid.UUID('00000000-0000-0000-0000-000000000000'))
self.assertEqual(jp2k.box[3].box[0].ulst, ulst) self.assertEqual(jp2k.box[3].box[0].ulst, ulst)
self.assertEqual(jp2k.box[3].box[1].id, 'url ') self.assertEqual(jp2k.box[3].box[1].box_id, 'url ')
self.assertEqual(jp2k.box[3].box[1].offset, 111) self.assertEqual(jp2k.box[3].box[1].offset, 111)
self.assertEqual(jp2k.box[3].box[1].length, 16) self.assertEqual(jp2k.box[3].box[1].length, 16)
self.assertEqual(jp2k.box[3].box[1].version, 0) self.assertEqual(jp2k.box[3].box[1].version, 0)
self.assertEqual(jp2k.box[3].box[1].flag, (0, 0, 0)) self.assertEqual(jp2k.box[3].box[1].flag, (0, 0, 0))
self.assertEqual(jp2k.box[3].box[1].URL, 'abcd') self.assertEqual(jp2k.box[3].box[1].url, 'abcd')
def test_xml_box_with_trailing_nulls(self): def test_xml_box_with_trailing_nulls(self):
# ElementTree does not like trailing null chars after valid XML # ElementTree does not like trailing null chars after valid XML
@ -522,14 +522,14 @@ class TestJp2k(unittest.TestCase):
jp2k = Jp2k(tfile.name) jp2k = Jp2k(tfile.name)
self.assertEqual(jp2k.box[3].id, 'xml ') self.assertEqual(jp2k.box[3].box_id, 'xml ')
self.assertEqual(jp2k.box[3].offset, 77) self.assertEqual(jp2k.box[3].offset, 77)
self.assertEqual(jp2k.box[3].length, 36) self.assertEqual(jp2k.box[3].length, 36)
def test_asoc_label_box(self): def test_asoc_label_box(self):
# Construct a fake file with an asoc and a label box, as # Construct a fake file with an asoc and a label box, as
# OpenJPEG doesn't have such a file. # OpenJPEG doesn't have such a file.
data = Jp2k(self.jp2file).read(reduce=1) data = Jp2k(self.jp2file).read(rlevel=1)
with tempfile.NamedTemporaryFile(suffix='.jp2') as tfile: with tempfile.NamedTemporaryFile(suffix='.jp2') as tfile:
j = Jp2k(tfile.name, 'wb') j = Jp2k(tfile.name, 'wb')
j.write(data) j.write(data)
@ -567,10 +567,10 @@ class TestJp2k(unittest.TestCase):
tfile2.flush() tfile2.flush()
jasoc = Jp2k(tfile2.name) jasoc = Jp2k(tfile2.name)
self.assertEqual(jasoc.box[3].id, 'asoc') self.assertEqual(jasoc.box[3].box_id, 'asoc')
self.assertEqual(jasoc.box[3].box[0].id, 'lbl ') self.assertEqual(jasoc.box[3].box[0].box_id, 'lbl ')
self.assertEqual(jasoc.box[3].box[0].label, 'label') self.assertEqual(jasoc.box[3].box[0].label, 'label')
self.assertEqual(jasoc.box[3].box[1].id, 'xml ') self.assertEqual(jasoc.box[3].box[1].box_id, 'xml ')
def test_openjpeg_library_message(self): def test_openjpeg_library_message(self):
# Verify the error message produced by the openjpeg library. # Verify the error message produced by the openjpeg library.
@ -599,11 +599,11 @@ class TestJp2k(unittest.TestCase):
Invalid\svalues\sfor\scomp\s=\s0\s+ Invalid\svalues\sfor\scomp\s=\s0\s+
:\sdx=1\sdy=0''', re.VERBOSE) :\sdx=1\sdy=0''', re.VERBOSE)
if sys.hexversion < 0x03020000: if sys.hexversion < 0x03020000:
with self.assertRaisesRegexp(IOError, regexp) as ce: with self.assertRaisesRegexp((IOError, OSError), regexp) as ce:
d = j.read(reduce=3) d = j.read(rlevel=1)
else: else:
with self.assertRaisesRegex(IOError, regexp) as ce: with self.assertRaisesRegex((IOError, OSError), regexp) as ce:
d = j.read(reduce=3) d = j.read(rlevel=1)
def test_xmp_attribute(self): def test_xmp_attribute(self):
# Verify that we can read the XMP packet in our shipping example file. # Verify that we can read the XMP packet in our shipping example file.
@ -648,20 +648,20 @@ class TestJp2k(unittest.TestCase):
self.assertFalse('Make' in exif['Image'].keys()) self.assertFalse('Make' in exif['Image'].keys())
@unittest.skipIf(glymur.lib.openjpeg._OPENJPEG is None, @unittest.skipIf(glymur.lib.openjpeg.OPENJPEG is None,
"Missing openjpeg library.") "Missing openjpeg library.")
class TestJp2k15(unittest.TestCase): class TestJp2k15(unittest.TestCase):
@classmethod @classmethod
def setUpClass(cls): def setUpClass(cls):
# Monkey patch the package so as to use OPENJPEG instead of OPENJP2 # Monkey patch the package so as to use OPENJPEG instead of OPENJP2
cls.openjp2 = glymur.lib.openjp2._OPENJP2 cls.openjp2 = glymur.lib.openjp2.OPENJP2
glymur.lib.openjp2._OPENJP2 = None glymur.lib.openjp2.OPENJP2 = None
@classmethod @classmethod
def tearDownClass(cls): def tearDownClass(cls):
# Restore OPENJP2 # Restore OPENJP2
glymur.lib.openjp2._OPENJP2 = cls.openjp2 glymur.lib.openjp2.OPENJP2 = cls.openjp2
def setUp(self): def setUp(self):
self.jp2file = glymur.data.nemo() self.jp2file = glymur.data.nemo()
@ -699,7 +699,7 @@ class TestJp2k15(unittest.TestCase):
# and OPJ_DATA_ROOT is not set. We need at least one # and OPJ_DATA_ROOT is not set. We need at least one
# working JP2 test. # working JP2 test.
j2k = Jp2k(self.jp2file) j2k = Jp2k(self.jp2file)
d = j2k.read(reduce=1) d = j2k.read(rlevel=1)
def test_basic_j2k(self): def test_basic_j2k(self):
# This test is only useful when openjp2 is not available # This test is only useful when openjp2 is not available

File diff suppressed because it is too large Load diff

View file

@ -57,7 +57,7 @@ def read_image(infile):
return data return data
@unittest.skipIf(glymur.lib.openjp2._OPENJP2 is None, @unittest.skipIf(glymur.lib.openjp2.OPENJP2 is None,
"Missing openjp2 library.") "Missing openjp2 library.")
@unittest.skipIf(no_read_backend, no_read_backend_msg) @unittest.skipIf(no_read_backend, no_read_backend_msg)
@unittest.skipIf(data_root is None, @unittest.skipIf(data_root is None,
@ -94,7 +94,7 @@ class TestSuiteNegative(unittest.TestCase):
# Verify that the last segment returned in the codestream is SOD, # Verify that the last segment returned in the codestream is SOD,
# not EOC. Codestream parsing should stop when we try to jump to # not EOC. Codestream parsing should stop when we try to jump to
# the end of SOT. # the end of SOT.
self.assertEqual(c.segment[-1].id, 'SOD') self.assertEqual(c.segment[-1].marker_id, 'SOD')
@unittest.skipIf(sys.hexversion < 0x03020000, @unittest.skipIf(sys.hexversion < 0x03020000,
"Uses features introduced in 3.2.") "Uses features introduced in 3.2.")
@ -109,7 +109,7 @@ class TestSuiteNegative(unittest.TestCase):
# Verify that the last segment returned in the codestream is SOD, # Verify that the last segment returned in the codestream is SOD,
# not EOC. Codestream parsing should stop when we try to jump to # not EOC. Codestream parsing should stop when we try to jump to
# the end of SOT. # the end of SOT.
self.assertEqual(c.segment[-1].id, 'SOD') self.assertEqual(c.segment[-1].marker_id, 'SOD')
@unittest.skipIf(sys.hexversion < 0x03020000, @unittest.skipIf(sys.hexversion < 0x03020000,
"Uses features introduced in 3.2.") "Uses features introduced in 3.2.")
@ -124,7 +124,7 @@ class TestSuiteNegative(unittest.TestCase):
# Verify that the last segment returned in the codestream is SOD, # Verify that the last segment returned in the codestream is SOD,
# not EOC. Codestream parsing should stop when we try to jump to # not EOC. Codestream parsing should stop when we try to jump to
# the end of SOT. # the end of SOT.
self.assertEqual(c.segment[-1].id, 'SOD') self.assertEqual(c.segment[-1].marker_id, 'SOD')
def test_code_block_dimensions(self): def test_code_block_dimensions(self):
# opj_compress doesn't allow the dimensions of a codeblock # opj_compress doesn't allow the dimensions of a codeblock
@ -157,7 +157,7 @@ class TestSuiteNegative(unittest.TestCase):
def test_precinct_size_not_multiple_of_two(self): def test_precinct_size_not_multiple_of_two(self):
# Seems like precinct sizes should be powers of two. # Seems like precinct sizes should be powers of two.
ifile = Jp2k(self.j2kfile) ifile = Jp2k(self.j2kfile)
data = ifile.read(reduce=2) data = ifile.read(rlevel=2)
with tempfile.NamedTemporaryFile(suffix='.jp2') as tfile: with tempfile.NamedTemporaryFile(suffix='.jp2') as tfile:
ofile = Jp2k(tfile.name, 'wb') ofile = Jp2k(tfile.name, 'wb')
with self.assertRaises(IOError) as ce: with self.assertRaises(IOError) as ce:
@ -166,7 +166,7 @@ class TestSuiteNegative(unittest.TestCase):
def test_codeblock_size_not_multiple_of_two(self): def test_codeblock_size_not_multiple_of_two(self):
# Seems like code block sizes should be powers of two. # Seems like code block sizes should be powers of two.
ifile = Jp2k(self.j2kfile) ifile = Jp2k(self.j2kfile)
data = ifile.read(reduce=2) data = ifile.read(rlevel=2)
with tempfile.NamedTemporaryFile(suffix='.jp2') as tfile: with tempfile.NamedTemporaryFile(suffix='.jp2') as tfile:
ofile = Jp2k(tfile.name, 'wb') ofile = Jp2k(tfile.name, 'wb')
with self.assertRaises(IOError) as ce: with self.assertRaises(IOError) as ce:
@ -176,7 +176,7 @@ class TestSuiteNegative(unittest.TestCase):
# Seems like code block sizes should never exceed half that of # Seems like code block sizes should never exceed half that of
# precinct size. # precinct size.
ifile = Jp2k(self.j2kfile) ifile = Jp2k(self.j2kfile)
data = ifile.read(reduce=2) data = ifile.read(rlevel=2)
with tempfile.NamedTemporaryFile(suffix='.jp2') as tfile: with tempfile.NamedTemporaryFile(suffix='.jp2') as tfile:
ofile = Jp2k(tfile.name, 'wb') ofile = Jp2k(tfile.name, 'wb')
with self.assertRaises(IOError) as ce: with self.assertRaises(IOError) as ce:

View file

@ -57,7 +57,7 @@ def read_image(infile):
return data return data
@unittest.skipIf(glymur.lib.openjp2._OPENJP2 is None, @unittest.skipIf(glymur.lib.openjp2.OPENJP2 is None,
"Missing openjp2 library.") "Missing openjp2 library.")
@unittest.skipIf(no_read_backend, no_read_backend_msg) @unittest.skipIf(no_read_backend, no_read_backend_msg)
@unittest.skipIf(data_root is None, @unittest.skipIf(data_root is None,
@ -83,50 +83,50 @@ class TestSuiteWrite(unittest.TestCase):
# SIZ: Image and tile size # SIZ: Image and tile size
# Profile: "0" means profile 2 # Profile: "0" means profile 2
self.assertEqual(c.segment[1].Rsiz, 0) self.assertEqual(c.segment[1].rsiz, 0)
# Reference grid size # Reference grid size
self.assertEqual((c.segment[1].Xsiz, c.segment[1].Ysiz), self.assertEqual((c.segment[1].xsiz, c.segment[1].ysiz),
(640, 480)) (640, 480))
# Reference grid offset # Reference grid offset
self.assertEqual((c.segment[1].XOsiz, c.segment[1].YOsiz), (0, 0)) self.assertEqual((c.segment[1].xosiz, c.segment[1].yosiz), (0, 0))
# Tile size # Tile size
self.assertEqual((c.segment[1].XTsiz, c.segment[1].YTsiz), self.assertEqual((c.segment[1].xtsiz, c.segment[1].ytsiz),
(640, 480)) (640, 480))
# Tile offset # Tile offset
self.assertEqual((c.segment[1].XTOsiz, c.segment[1].YTOsiz), self.assertEqual((c.segment[1].xtosiz, c.segment[1].ytosiz),
(0, 0)) (0, 0))
# bitdepth # bitdepth
self.assertEqual(c.segment[1]._bitdepth, (8, 8, 8)) self.assertEqual(c.segment[1]._bitdepth, (8, 8, 8))
# signed # signed
self.assertEqual(c.segment[1]._signed, (False, False, False)) self.assertEqual(c.segment[1]._signed, (False, False, False))
# subsampling # subsampling
self.assertEqual(list(zip(c.segment[1].XRsiz, c.segment[1].YRsiz)), self.assertEqual(list(zip(c.segment[1].xrsiz, c.segment[1].yrsiz)),
[(1, 1)] * 3) [(1, 1)] * 3)
# COD: Coding style default # COD: Coding style default
self.assertFalse(c.segment[2].Scod & 2) # no sop self.assertFalse(c.segment[2].scod & 2) # no sop
self.assertFalse(c.segment[2].Scod & 4) # no eph self.assertFalse(c.segment[2].scod & 4) # no eph
self.assertEqual(c.segment[2].SPcod[0], glymur.core.LRCP) self.assertEqual(c.segment[2].spcod[0], glymur.core.LRCP)
self.assertEqual(c.segment[2]._layers, 3) # layers = 3 self.assertEqual(c.segment[2]._layers, 3) # layers = 3
self.assertEqual(c.segment[2].SPcod[3], 1) # mct self.assertEqual(c.segment[2].spcod[3], 1) # mct
self.assertEqual(c.segment[2].SPcod[4], 5) # levels self.assertEqual(c.segment[2].spcod[4], 5) # levels
self.assertEqual(tuple(c.segment[2]._code_block_size), self.assertEqual(tuple(c.segment[2]._code_block_size),
(64, 64)) # cblksz (64, 64)) # cblksz
# Selective arithmetic coding bypass # Selective arithmetic coding bypass
self.assertFalse(c.segment[2].SPcod[7] & 0x01) self.assertFalse(c.segment[2].spcod[7] & 0x01)
# Reset context probabilities # Reset context probabilities
self.assertFalse(c.segment[2].SPcod[7] & 0x02) self.assertFalse(c.segment[2].spcod[7] & 0x02)
# Termination on each coding pass # Termination on each coding pass
self.assertFalse(c.segment[2].SPcod[7] & 0x04) self.assertFalse(c.segment[2].spcod[7] & 0x04)
# Vertically causal context # Vertically causal context
self.assertFalse(c.segment[2].SPcod[7] & 0x08) self.assertFalse(c.segment[2].spcod[7] & 0x08)
# Predictable termination # Predictable termination
self.assertFalse(c.segment[2].SPcod[7] & 0x0010) self.assertFalse(c.segment[2].spcod[7] & 0x0010)
# Segmentation symbols # Segmentation symbols
self.assertFalse(c.segment[2].SPcod[7] & 0x0020) self.assertFalse(c.segment[2].spcod[7] & 0x0020)
self.assertEqual(c.segment[2].SPcod[8], self.assertEqual(c.segment[2].spcod[8],
glymur.core.WAVELET_TRANSFORM_5x3_REVERSIBLE) glymur.core.WAVELET_XFORM_5X3_REVERSIBLE)
self.assertEqual(len(c.segment[2].SPcod), 9) self.assertEqual(len(c.segment[2].spcod), 9)
def test_NR_ENC_Bretagne1_ppm_2_encode(self): def test_NR_ENC_Bretagne1_ppm_2_encode(self):
# NR-ENC-Bretagne1.ppm-2-encode # NR-ENC-Bretagne1.ppm-2-encode
@ -141,50 +141,50 @@ class TestSuiteWrite(unittest.TestCase):
# SIZ: Image and tile size # SIZ: Image and tile size
# Profile: "0" means profile 2 # Profile: "0" means profile 2
self.assertEqual(c.segment[1].Rsiz, 0) self.assertEqual(c.segment[1].rsiz, 0)
# Reference grid size # Reference grid size
self.assertEqual((c.segment[1].Xsiz, c.segment[1].Ysiz), self.assertEqual((c.segment[1].xsiz, c.segment[1].ysiz),
(640, 480)) (640, 480))
# Reference grid offset # Reference grid offset
self.assertEqual((c.segment[1].XOsiz, c.segment[1].YOsiz), (0, 0)) self.assertEqual((c.segment[1].xosiz, c.segment[1].yosiz), (0, 0))
# Tile size # Tile size
self.assertEqual((c.segment[1].XTsiz, c.segment[1].YTsiz), self.assertEqual((c.segment[1].xtsiz, c.segment[1].ytsiz),
(640, 480)) (640, 480))
# Tile offset # Tile offset
self.assertEqual((c.segment[1].XTOsiz, c.segment[1].YTOsiz), self.assertEqual((c.segment[1].xtosiz, c.segment[1].ytosiz),
(0, 0)) (0, 0))
# bitdepth # bitdepth
self.assertEqual(c.segment[1]._bitdepth, (8, 8, 8)) self.assertEqual(c.segment[1]._bitdepth, (8, 8, 8))
# signed # signed
self.assertEqual(c.segment[1]._signed, (False, False, False)) self.assertEqual(c.segment[1]._signed, (False, False, False))
# subsampling # subsampling
self.assertEqual(list(zip(c.segment[1].XRsiz, c.segment[1].YRsiz)), self.assertEqual(list(zip(c.segment[1].xrsiz, c.segment[1].yrsiz)),
[(1, 1)] * 3) [(1, 1)] * 3)
# COD: Coding style default # COD: Coding style default
self.assertFalse(c.segment[2].Scod & 2) # no sop self.assertFalse(c.segment[2].scod & 2) # no sop
self.assertFalse(c.segment[2].Scod & 4) # no eph self.assertFalse(c.segment[2].scod & 4) # no eph
self.assertEqual(c.segment[2].SPcod[0], glymur.core.LRCP) self.assertEqual(c.segment[2].spcod[0], glymur.core.LRCP)
self.assertEqual(c.segment[2]._layers, 3) # layers = 3 self.assertEqual(c.segment[2]._layers, 3) # layers = 3
self.assertEqual(c.segment[2].SPcod[3], 1) # mct self.assertEqual(c.segment[2].spcod[3], 1) # mct
self.assertEqual(c.segment[2].SPcod[4], 1) # levels self.assertEqual(c.segment[2].spcod[4], 1) # levels
self.assertEqual(tuple(c.segment[2]._code_block_size), self.assertEqual(tuple(c.segment[2]._code_block_size),
(64, 64)) # cblksz (64, 64)) # cblksz
# Selective arithmetic coding bypass # Selective arithmetic coding bypass
self.assertFalse(c.segment[2].SPcod[7] & 0x01) self.assertFalse(c.segment[2].spcod[7] & 0x01)
# Reset context probabilities # Reset context probabilities
self.assertFalse(c.segment[2].SPcod[7] & 0x02) self.assertFalse(c.segment[2].spcod[7] & 0x02)
# Termination on each coding pass # Termination on each coding pass
self.assertFalse(c.segment[2].SPcod[7] & 0x04) self.assertFalse(c.segment[2].spcod[7] & 0x04)
# Vertically causal context # Vertically causal context
self.assertFalse(c.segment[2].SPcod[7] & 0x08) self.assertFalse(c.segment[2].spcod[7] & 0x08)
# Predictable termination # Predictable termination
self.assertFalse(c.segment[2].SPcod[7] & 0x0010) self.assertFalse(c.segment[2].spcod[7] & 0x0010)
# Segmentation symbols # Segmentation symbols
self.assertFalse(c.segment[2].SPcod[7] & 0x0020) self.assertFalse(c.segment[2].spcod[7] & 0x0020)
self.assertEqual(c.segment[2].SPcod[8], self.assertEqual(c.segment[2].spcod[8],
glymur.core.WAVELET_TRANSFORM_5x3_REVERSIBLE) glymur.core.WAVELET_XFORM_5X3_REVERSIBLE)
self.assertEqual(len(c.segment[2].SPcod), 9) self.assertEqual(len(c.segment[2].spcod), 9)
def test_NR_ENC_Bretagne1_ppm_3_encode(self): def test_NR_ENC_Bretagne1_ppm_3_encode(self):
# NR-ENC-Bretagne1.ppm-3-encode # NR-ENC-Bretagne1.ppm-3-encode
@ -200,49 +200,49 @@ class TestSuiteWrite(unittest.TestCase):
# SIZ: Image and tile size # SIZ: Image and tile size
# Profile: "0" means profile 2 # Profile: "0" means profile 2
self.assertEqual(c.segment[1].Rsiz, 0) self.assertEqual(c.segment[1].rsiz, 0)
# Reference grid size # Reference grid size
self.assertEqual((c.segment[1].Xsiz, c.segment[1].Ysiz), self.assertEqual((c.segment[1].xsiz, c.segment[1].ysiz),
(640, 480)) (640, 480))
# Reference grid offset # Reference grid offset
self.assertEqual((c.segment[1].XOsiz, c.segment[1].YOsiz), (0, 0)) self.assertEqual((c.segment[1].xosiz, c.segment[1].yosiz), (0, 0))
# Tile size # Tile size
self.assertEqual((c.segment[1].XTsiz, c.segment[1].YTsiz), self.assertEqual((c.segment[1].xtsiz, c.segment[1].ytsiz),
(640, 480)) (640, 480))
# Tile offset # Tile offset
self.assertEqual((c.segment[1].XTOsiz, c.segment[1].YTOsiz), self.assertEqual((c.segment[1].xtosiz, c.segment[1].ytosiz),
(0, 0)) (0, 0))
# bitdepth # bitdepth
self.assertEqual(c.segment[1]._bitdepth, (8, 8, 8)) self.assertEqual(c.segment[1]._bitdepth, (8, 8, 8))
# signed # signed
self.assertEqual(c.segment[1]._signed, (False, False, False)) self.assertEqual(c.segment[1]._signed, (False, False, False))
# subsampling # subsampling
self.assertEqual(list(zip(c.segment[1].XRsiz, c.segment[1].YRsiz)), self.assertEqual(list(zip(c.segment[1].xrsiz, c.segment[1].yrsiz)),
[(1, 1)] * 3) [(1, 1)] * 3)
# COD: Coding style default # COD: Coding style default
self.assertFalse(c.segment[2].Scod & 2) # no sop self.assertFalse(c.segment[2].scod & 2) # no sop
self.assertFalse(c.segment[2].Scod & 4) # no eph self.assertFalse(c.segment[2].scod & 4) # no eph
self.assertEqual(c.segment[2].SPcod[0], glymur.core.LRCP) self.assertEqual(c.segment[2].spcod[0], glymur.core.LRCP)
self.assertEqual(c.segment[2]._layers, 3) # layers = 3 self.assertEqual(c.segment[2]._layers, 3) # layers = 3
self.assertEqual(c.segment[2].SPcod[3], 1) # mct self.assertEqual(c.segment[2].spcod[3], 1) # mct
self.assertEqual(c.segment[2].SPcod[4], 5) # levels self.assertEqual(c.segment[2].spcod[4], 5) # levels
self.assertEqual(tuple(c.segment[2]._code_block_size), self.assertEqual(tuple(c.segment[2]._code_block_size),
(16, 16)) # cblksz (16, 16)) # cblksz
# Selective arithmetic coding bypass # Selective arithmetic coding bypass
self.assertFalse(c.segment[2].SPcod[7] & 0x01) self.assertFalse(c.segment[2].spcod[7] & 0x01)
# Reset context probabilities # Reset context probabilities
self.assertFalse(c.segment[2].SPcod[7] & 0x02) self.assertFalse(c.segment[2].spcod[7] & 0x02)
# Termination on each coding pass # Termination on each coding pass
self.assertFalse(c.segment[2].SPcod[7] & 0x04) self.assertFalse(c.segment[2].spcod[7] & 0x04)
# Vertically causal context # Vertically causal context
self.assertFalse(c.segment[2].SPcod[7] & 0x08) self.assertFalse(c.segment[2].spcod[7] & 0x08)
# Predictable termination # Predictable termination
self.assertFalse(c.segment[2].SPcod[7] & 0x0010) self.assertFalse(c.segment[2].spcod[7] & 0x0010)
# Segmentation symbols # Segmentation symbols
self.assertFalse(c.segment[2].SPcod[7] & 0x0020) self.assertFalse(c.segment[2].spcod[7] & 0x0020)
self.assertEqual(c.segment[2].SPcod[8], self.assertEqual(c.segment[2].spcod[8],
glymur.core.WAVELET_TRANSFORM_5x3_REVERSIBLE) glymur.core.WAVELET_XFORM_5X3_REVERSIBLE)
self.assertEqual(c.segment[2]._precinct_size, self.assertEqual(c.segment[2]._precinct_size,
[(2, 2), (4, 4), (8, 8), (16, 16), (32, 32), [(2, 2), (4, 4), (8, 8), (16, 16), (32, 32),
(64, 64)]) (64, 64)])
@ -263,49 +263,49 @@ class TestSuiteWrite(unittest.TestCase):
# SIZ: Image and tile size # SIZ: Image and tile size
# Profile: "0" means profile 2 # Profile: "0" means profile 2
self.assertEqual(c.segment[1].Rsiz, 0) self.assertEqual(c.segment[1].rsiz, 0)
# Reference grid size # Reference grid size
self.assertEqual((c.segment[1].Xsiz, c.segment[1].Ysiz), self.assertEqual((c.segment[1].xsiz, c.segment[1].ysiz),
(data.shape[1], data.shape[0])) (data.shape[1], data.shape[0]))
# Reference grid offset # Reference grid offset
self.assertEqual((c.segment[1].XOsiz, c.segment[1].YOsiz), (0, 0)) self.assertEqual((c.segment[1].xosiz, c.segment[1].yosiz), (0, 0))
# Tile size. Reported as XY, not RC. # Tile size. Reported as XY, not RC.
self.assertEqual((c.segment[1].XTsiz, c.segment[1].YTsiz), self.assertEqual((c.segment[1].xtsiz, c.segment[1].ytsiz),
(640, 480)) (640, 480))
# Tile offset # Tile offset
self.assertEqual((c.segment[1].XTOsiz, c.segment[1].YTOsiz), self.assertEqual((c.segment[1].xtosiz, c.segment[1].ytosiz),
(0, 0)) (0, 0))
# bitdepth # bitdepth
self.assertEqual(c.segment[1]._bitdepth, (8, 8, 8)) self.assertEqual(c.segment[1]._bitdepth, (8, 8, 8))
# signed # signed
self.assertEqual(c.segment[1]._signed, (False, False, False)) self.assertEqual(c.segment[1]._signed, (False, False, False))
# subsampling # subsampling
self.assertEqual(list(zip(c.segment[1].XRsiz, c.segment[1].YRsiz)), self.assertEqual(list(zip(c.segment[1].xrsiz, c.segment[1].yrsiz)),
[(1, 1)] * 3) [(1, 1)] * 3)
# COD: Coding style default # COD: Coding style default
self.assertFalse(c.segment[2].Scod & 2) # no sop self.assertFalse(c.segment[2].scod & 2) # no sop
self.assertFalse(c.segment[2].Scod & 4) # no eph self.assertFalse(c.segment[2].scod & 4) # no eph
self.assertEqual(c.segment[2].SPcod[0], glymur.core.LRCP) self.assertEqual(c.segment[2].spcod[0], glymur.core.LRCP)
self.assertEqual(c.segment[2]._layers, 3) # layers = 3 self.assertEqual(c.segment[2]._layers, 3) # layers = 3
self.assertEqual(c.segment[2].SPcod[3], 1) # mct self.assertEqual(c.segment[2].spcod[3], 1) # mct
self.assertEqual(c.segment[2].SPcod[4], 5) # levels self.assertEqual(c.segment[2].spcod[4], 5) # levels
self.assertEqual(tuple(c.segment[2]._code_block_size), self.assertEqual(tuple(c.segment[2]._code_block_size),
(32, 32)) # cblksz (32, 32)) # cblksz
# Selective arithmetic coding bypass # Selective arithmetic coding bypass
self.assertFalse(c.segment[2].SPcod[7] & 0x01) self.assertFalse(c.segment[2].spcod[7] & 0x01)
# Reset context probabilities # Reset context probabilities
self.assertFalse(c.segment[2].SPcod[7] & 0x02) self.assertFalse(c.segment[2].spcod[7] & 0x02)
# Termination on each coding pass # Termination on each coding pass
self.assertFalse(c.segment[2].SPcod[7] & 0x04) self.assertFalse(c.segment[2].spcod[7] & 0x04)
# Vertically causal context # Vertically causal context
self.assertFalse(c.segment[2].SPcod[7] & 0x08) self.assertFalse(c.segment[2].spcod[7] & 0x08)
# Predictable termination # Predictable termination
self.assertFalse(c.segment[2].SPcod[7] & 0x0010) self.assertFalse(c.segment[2].spcod[7] & 0x0010)
# Segmentation symbols # Segmentation symbols
self.assertFalse(c.segment[2].SPcod[7] & 0x0020) self.assertFalse(c.segment[2].spcod[7] & 0x0020)
self.assertEqual(c.segment[2].SPcod[8], self.assertEqual(c.segment[2].spcod[8],
glymur.core.WAVELET_TRANSFORM_5x3_REVERSIBLE) glymur.core.WAVELET_XFORM_5X3_REVERSIBLE)
self.assertEqual(c.segment[2]._precinct_size, self.assertEqual(c.segment[2]._precinct_size,
[(16, 16), (32, 32), (64, 64)] + [(128, 128)] * 3) [(16, 16), (32, 32), (64, 64)] + [(128, 128)] * 3)
@ -321,50 +321,50 @@ class TestSuiteWrite(unittest.TestCase):
# SIZ: Image and tile size # SIZ: Image and tile size
# Profile: "0" means profile 2 # Profile: "0" means profile 2
self.assertEqual(c.segment[1].Rsiz, 0) self.assertEqual(c.segment[1].rsiz, 0)
# Reference grid size # Reference grid size
self.assertEqual((c.segment[1].Xsiz, c.segment[1].Ysiz), self.assertEqual((c.segment[1].xsiz, c.segment[1].ysiz),
(data.shape[1], data.shape[0])) (data.shape[1], data.shape[0]))
# Reference grid offset # Reference grid offset
self.assertEqual((c.segment[1].XOsiz, c.segment[1].YOsiz), (0, 0)) self.assertEqual((c.segment[1].xosiz, c.segment[1].yosiz), (0, 0))
# Tile size # Tile size
self.assertEqual((c.segment[1].XTsiz, c.segment[1].YTsiz), self.assertEqual((c.segment[1].xtsiz, c.segment[1].ytsiz),
(127, 127)) (127, 127))
# Tile offset # Tile offset
self.assertEqual((c.segment[1].XTOsiz, c.segment[1].YTOsiz), self.assertEqual((c.segment[1].xtosiz, c.segment[1].ytosiz),
(0, 0)) (0, 0))
# bitdepth # bitdepth
self.assertEqual(c.segment[1]._bitdepth, (8, 8, 8)) self.assertEqual(c.segment[1]._bitdepth, (8, 8, 8))
# signed # signed
self.assertEqual(c.segment[1]._signed, (False, False, False)) self.assertEqual(c.segment[1]._signed, (False, False, False))
# subsampling # subsampling
self.assertEqual(list(zip(c.segment[1].XRsiz, c.segment[1].YRsiz)), self.assertEqual(list(zip(c.segment[1].xrsiz, c.segment[1].yrsiz)),
[(1, 1)] * 3) [(1, 1)] * 3)
# COD: Coding style default # COD: Coding style default
self.assertFalse(c.segment[2].Scod & 2) # no sop self.assertFalse(c.segment[2].scod & 2) # no sop
self.assertFalse(c.segment[2].Scod & 4) # no eph self.assertFalse(c.segment[2].scod & 4) # no eph
self.assertEqual(c.segment[2].SPcod[0], glymur.core.PCRL) self.assertEqual(c.segment[2].spcod[0], glymur.core.PCRL)
self.assertEqual(c.segment[2]._layers, 1) # layers = 1 self.assertEqual(c.segment[2]._layers, 1) # layers = 1
self.assertEqual(c.segment[2].SPcod[3], 1) # mct self.assertEqual(c.segment[2].spcod[3], 1) # mct
self.assertEqual(c.segment[2].SPcod[4], 5) # levels self.assertEqual(c.segment[2].spcod[4], 5) # levels
self.assertEqual(tuple(c.segment[2]._code_block_size), self.assertEqual(tuple(c.segment[2]._code_block_size),
(64, 64)) # cblksz (64, 64)) # cblksz
# Selective arithmetic coding bypass # Selective arithmetic coding bypass
self.assertFalse(c.segment[2].SPcod[7] & 0x01) self.assertFalse(c.segment[2].spcod[7] & 0x01)
# Reset context probabilities # Reset context probabilities
self.assertFalse(c.segment[2].SPcod[7] & 0x02) self.assertFalse(c.segment[2].spcod[7] & 0x02)
# Termination on each coding pass # Termination on each coding pass
self.assertFalse(c.segment[2].SPcod[7] & 0x04) self.assertFalse(c.segment[2].spcod[7] & 0x04)
# Vertically causal context # Vertically causal context
self.assertFalse(c.segment[2].SPcod[7] & 0x08) self.assertFalse(c.segment[2].spcod[7] & 0x08)
# Predictable termination # Predictable termination
self.assertFalse(c.segment[2].SPcod[7] & 0x0010) self.assertFalse(c.segment[2].spcod[7] & 0x0010)
# Segmentation symbols # Segmentation symbols
self.assertFalse(c.segment[2].SPcod[7] & 0x0020) self.assertFalse(c.segment[2].spcod[7] & 0x0020)
self.assertEqual(c.segment[2].SPcod[8], self.assertEqual(c.segment[2].spcod[8],
glymur.core.WAVELET_TRANSFORM_5x3_REVERSIBLE) glymur.core.WAVELET_XFORM_5X3_REVERSIBLE)
self.assertEqual(len(c.segment[2].SPcod), 9) self.assertEqual(len(c.segment[2].spcod), 9)
def test_NR_ENC_Bretagne2_ppm_6_encode(self): def test_NR_ENC_Bretagne2_ppm_6_encode(self):
# NR-ENC-Bretagne2.ppm-6-encode # NR-ENC-Bretagne2.ppm-6-encode
@ -378,53 +378,53 @@ class TestSuiteWrite(unittest.TestCase):
# SIZ: Image and tile size # SIZ: Image and tile size
# Profile: "0" means profile 2 # Profile: "0" means profile 2
self.assertEqual(c.segment[1].Rsiz, 0) self.assertEqual(c.segment[1].rsiz, 0)
# Reference grid size # Reference grid size
self.assertEqual((c.segment[1].Xsiz, c.segment[1].Ysiz), self.assertEqual((c.segment[1].xsiz, c.segment[1].ysiz),
(5183, 3887)) (5183, 3887))
# Reference grid offset # Reference grid offset
self.assertEqual((c.segment[1].XOsiz, c.segment[1].YOsiz), (0, 0)) self.assertEqual((c.segment[1].xosiz, c.segment[1].yosiz), (0, 0))
# Tile size # Tile size
self.assertEqual((c.segment[1].XTsiz, c.segment[1].YTsiz), self.assertEqual((c.segment[1].xtsiz, c.segment[1].ytsiz),
(5183, 3887)) (5183, 3887))
# Tile offset # Tile offset
self.assertEqual((c.segment[1].XTOsiz, c.segment[1].YTOsiz), self.assertEqual((c.segment[1].xtosiz, c.segment[1].ytosiz),
(0, 0)) (0, 0))
# bitdepth # bitdepth
self.assertEqual(c.segment[1]._bitdepth, (8, 8, 8)) self.assertEqual(c.segment[1]._bitdepth, (8, 8, 8))
# signed # signed
self.assertEqual(c.segment[1]._signed, (False, False, False)) self.assertEqual(c.segment[1]._signed, (False, False, False))
# subsampling # subsampling
self.assertEqual(list(zip(c.segment[1].XRsiz, c.segment[1].YRsiz)), self.assertEqual(list(zip(c.segment[1].xrsiz, c.segment[1].yrsiz)),
[(2, 2)] * 3) [(2, 2)] * 3)
# COD: Coding style default # COD: Coding style default
self.assertTrue(c.segment[2].Scod & 2) # sop self.assertTrue(c.segment[2].scod & 2) # sop
self.assertFalse(c.segment[2].Scod & 4) # no eph self.assertFalse(c.segment[2].scod & 4) # no eph
self.assertEqual(c.segment[2].SPcod[0], glymur.core.LRCP) self.assertEqual(c.segment[2].spcod[0], glymur.core.LRCP)
self.assertEqual(c.segment[2]._layers, 1) # layers = 1 self.assertEqual(c.segment[2]._layers, 1) # layers = 1
self.assertEqual(c.segment[2].SPcod[3], 1) # mct self.assertEqual(c.segment[2].spcod[3], 1) # mct
self.assertEqual(c.segment[2].SPcod[4], 5) # levels self.assertEqual(c.segment[2].spcod[4], 5) # levels
self.assertEqual(tuple(c.segment[2]._code_block_size), self.assertEqual(tuple(c.segment[2]._code_block_size),
(64, 64)) # cblksz (64, 64)) # cblksz
# Selective arithmetic coding bypass # Selective arithmetic coding bypass
self.assertFalse(c.segment[2].SPcod[7] & 0x01) self.assertFalse(c.segment[2].spcod[7] & 0x01)
# Reset context probabilities # Reset context probabilities
self.assertFalse(c.segment[2].SPcod[7] & 0x02) self.assertFalse(c.segment[2].spcod[7] & 0x02)
# Termination on each coding pass # Termination on each coding pass
self.assertFalse(c.segment[2].SPcod[7] & 0x04) self.assertFalse(c.segment[2].spcod[7] & 0x04)
# Vertically causal context # Vertically causal context
self.assertFalse(c.segment[2].SPcod[7] & 0x08) self.assertFalse(c.segment[2].spcod[7] & 0x08)
# Predictable termination # Predictable termination
self.assertFalse(c.segment[2].SPcod[7] & 0x0010) self.assertFalse(c.segment[2].spcod[7] & 0x0010)
# Segmentation symbols # Segmentation symbols
self.assertFalse(c.segment[2].SPcod[7] & 0x0020) self.assertFalse(c.segment[2].spcod[7] & 0x0020)
self.assertEqual(c.segment[2].SPcod[8], self.assertEqual(c.segment[2].spcod[8],
glymur.core.WAVELET_TRANSFORM_5x3_REVERSIBLE) glymur.core.WAVELET_XFORM_5X3_REVERSIBLE)
self.assertEqual(len(c.segment[2].SPcod), 9) self.assertEqual(len(c.segment[2].spcod), 9)
# 18 SOP segments. # 18 SOP segments.
nsops = [x.Nsop for x in c.segment if x.id == 'SOP'] nsops = [x.nsop for x in c.segment if x.marker_id == 'SOP']
self.assertEqual(nsops, list(range(18))) self.assertEqual(nsops, list(range(18)))
def test_NR_ENC_Bretagne2_ppm_7_encode(self): def test_NR_ENC_Bretagne2_ppm_7_encode(self):
@ -438,53 +438,53 @@ class TestSuiteWrite(unittest.TestCase):
# SIZ: Image and tile size # SIZ: Image and tile size
# Profile: "0" means profile 2 # Profile: "0" means profile 2
self.assertEqual(c.segment[1].Rsiz, 0) self.assertEqual(c.segment[1].rsiz, 0)
# Reference grid size # Reference grid size
self.assertEqual((c.segment[1].Xsiz, c.segment[1].Ysiz), self.assertEqual((c.segment[1].xsiz, c.segment[1].ysiz),
(2592, 1944)) (2592, 1944))
# Reference grid offset # Reference grid offset
self.assertEqual((c.segment[1].XOsiz, c.segment[1].YOsiz), (0, 0)) self.assertEqual((c.segment[1].xosiz, c.segment[1].yosiz), (0, 0))
# Tile size # Tile size
self.assertEqual((c.segment[1].XTsiz, c.segment[1].YTsiz), self.assertEqual((c.segment[1].xtsiz, c.segment[1].ytsiz),
(2592, 1944)) (2592, 1944))
# Tile offset # Tile offset
self.assertEqual((c.segment[1].XTOsiz, c.segment[1].YTOsiz), self.assertEqual((c.segment[1].xtosiz, c.segment[1].ytosiz),
(0, 0)) (0, 0))
# bitdepth # bitdepth
self.assertEqual(c.segment[1]._bitdepth, (8, 8, 8)) self.assertEqual(c.segment[1]._bitdepth, (8, 8, 8))
# signed # signed
self.assertEqual(c.segment[1]._signed, (False, False, False)) self.assertEqual(c.segment[1]._signed, (False, False, False))
# subsampling # subsampling
self.assertEqual(list(zip(c.segment[1].XRsiz, c.segment[1].YRsiz)), self.assertEqual(list(zip(c.segment[1].xrsiz, c.segment[1].yrsiz)),
[(1, 1)] * 3) [(1, 1)] * 3)
# COD: Coding style default # COD: Coding style default
self.assertFalse(c.segment[2].Scod & 2) # no sop self.assertFalse(c.segment[2].scod & 2) # no sop
self.assertTrue(c.segment[2].Scod & 4) # eph self.assertTrue(c.segment[2].scod & 4) # eph
self.assertEqual(c.segment[2].SPcod[0], glymur.core.LRCP) self.assertEqual(c.segment[2].spcod[0], glymur.core.LRCP)
self.assertEqual(c.segment[2]._layers, 1) # layers = 1 self.assertEqual(c.segment[2]._layers, 1) # layers = 1
self.assertEqual(c.segment[2].SPcod[3], 1) # mct self.assertEqual(c.segment[2].spcod[3], 1) # mct
self.assertEqual(c.segment[2].SPcod[4], 5) # levels self.assertEqual(c.segment[2].spcod[4], 5) # levels
self.assertEqual(tuple(c.segment[2]._code_block_size), self.assertEqual(tuple(c.segment[2]._code_block_size),
(64, 64)) # cblksz (64, 64)) # cblksz
# Selective arithmetic coding BYPASS # Selective arithmetic coding BYPASS
self.assertFalse(c.segment[2].SPcod[7] & 0x01) self.assertFalse(c.segment[2].spcod[7] & 0x01)
# RESET context probabilities (RESET) # RESET context probabilities (RESET)
self.assertTrue(c.segment[2].SPcod[7] & 0x02) self.assertTrue(c.segment[2].spcod[7] & 0x02)
# Termination on each coding pass, RESTART(TERMALL) # Termination on each coding pass, RESTART(TERMALL)
self.assertTrue(c.segment[2].SPcod[7] & 0x04) self.assertTrue(c.segment[2].spcod[7] & 0x04)
# Vertically causal context (VSC) # Vertically causal context (VSC)
self.assertFalse(c.segment[2].SPcod[7] & 0x08) self.assertFalse(c.segment[2].spcod[7] & 0x08)
# Predictable termination, ERTERM(SEGTERM) # Predictable termination, ERTERM(SEGTERM)
self.assertFalse(c.segment[2].SPcod[7] & 0x0010) self.assertFalse(c.segment[2].spcod[7] & 0x0010)
# Segmentation symbols, SEGMARK(SEGSYSM) # Segmentation symbols, SEGMARK(SEGSYSM)
self.assertTrue(c.segment[2].SPcod[7] & 0x0020) self.assertTrue(c.segment[2].spcod[7] & 0x0020)
self.assertEqual(c.segment[2].SPcod[8], self.assertEqual(c.segment[2].spcod[8],
glymur.core.WAVELET_TRANSFORM_5x3_REVERSIBLE) glymur.core.WAVELET_XFORM_5X3_REVERSIBLE)
self.assertEqual(len(c.segment[2].SPcod), 9) self.assertEqual(len(c.segment[2].spcod), 9)
# 18 EPH segments. # 18 EPH segments.
ephs = [x for x in c.segment if x.id == 'EPH'] ephs = [x for x in c.segment if x.marker_id == 'EPH']
self.assertEqual(len(ephs), 18) self.assertEqual(len(ephs), 18)
def test_NR_ENC_Bretagne2_ppm_8_encode(self): def test_NR_ENC_Bretagne2_ppm_8_encode(self):
@ -498,51 +498,51 @@ class TestSuiteWrite(unittest.TestCase):
# SIZ: Image and tile size # SIZ: Image and tile size
# Profile: "0" means profile 2 # Profile: "0" means profile 2
self.assertEqual(c.segment[1].Rsiz, 0) self.assertEqual(c.segment[1].rsiz, 0)
# Reference grid size # Reference grid size
self.assertEqual((c.segment[1].Xsiz, c.segment[1].Ysiz), self.assertEqual((c.segment[1].xsiz, c.segment[1].ysiz),
(2742, 2244)) (2742, 2244))
# Reference grid offset # Reference grid offset
self.assertEqual((c.segment[1].XOsiz, c.segment[1].YOsiz), self.assertEqual((c.segment[1].xosiz, c.segment[1].yosiz),
(150, 300)) (150, 300))
# Tile size # Tile size
self.assertEqual((c.segment[1].XTsiz, c.segment[1].YTsiz), self.assertEqual((c.segment[1].xtsiz, c.segment[1].ytsiz),
(2742, 2244)) (2742, 2244))
# Tile offset # Tile offset
self.assertEqual((c.segment[1].XTOsiz, c.segment[1].YTOsiz), self.assertEqual((c.segment[1].xtosiz, c.segment[1].ytosiz),
(0, 0)) (0, 0))
# bitdepth # bitdepth
self.assertEqual(c.segment[1]._bitdepth, (8, 8, 8)) self.assertEqual(c.segment[1]._bitdepth, (8, 8, 8))
# signed # signed
self.assertEqual(c.segment[1]._signed, (False, False, False)) self.assertEqual(c.segment[1]._signed, (False, False, False))
# subsampling # subsampling
self.assertEqual(list(zip(c.segment[1].XRsiz, c.segment[1].YRsiz)), self.assertEqual(list(zip(c.segment[1].xrsiz, c.segment[1].yrsiz)),
[(1, 1)] * 3) [(1, 1)] * 3)
# COD: Coding style default # COD: Coding style default
self.assertFalse(c.segment[2].Scod & 2) # no sop self.assertFalse(c.segment[2].scod & 2) # no sop
self.assertFalse(c.segment[2].Scod & 4) # no eph self.assertFalse(c.segment[2].scod & 4) # no eph
self.assertEqual(c.segment[2].SPcod[0], glymur.core.LRCP) self.assertEqual(c.segment[2].spcod[0], glymur.core.LRCP)
self.assertEqual(c.segment[2]._layers, 1) # layers = 1 self.assertEqual(c.segment[2]._layers, 1) # layers = 1
self.assertEqual(c.segment[2].SPcod[3], 1) # mct self.assertEqual(c.segment[2].spcod[3], 1) # mct
self.assertEqual(c.segment[2].SPcod[4], 5) # levels self.assertEqual(c.segment[2].spcod[4], 5) # levels
self.assertEqual(tuple(c.segment[2]._code_block_size), self.assertEqual(tuple(c.segment[2]._code_block_size),
(64, 64)) # cblksz (64, 64)) # cblksz
# Selective arithmetic coding BYPASS # Selective arithmetic coding BYPASS
self.assertFalse(c.segment[2].SPcod[7] & 0x01) self.assertFalse(c.segment[2].spcod[7] & 0x01)
# RESET context probabilities (RESET) # RESET context probabilities (RESET)
self.assertFalse(c.segment[2].SPcod[7] & 0x02) self.assertFalse(c.segment[2].spcod[7] & 0x02)
# Termination on each coding pass, RESTART(TERMALL) # Termination on each coding pass, RESTART(TERMALL)
self.assertFalse(c.segment[2].SPcod[7] & 0x04) self.assertFalse(c.segment[2].spcod[7] & 0x04)
# Vertically causal context (VSC) # Vertically causal context (VSC)
self.assertFalse(c.segment[2].SPcod[7] & 0x08) self.assertFalse(c.segment[2].spcod[7] & 0x08)
# Predictable termination, ERTERM(SEGTERM) # Predictable termination, ERTERM(SEGTERM)
self.assertFalse(c.segment[2].SPcod[7] & 0x0010) self.assertFalse(c.segment[2].spcod[7] & 0x0010)
# Segmentation symbols, SEGMARK(SEGSYSM) # Segmentation symbols, SEGMARK(SEGSYSM)
self.assertFalse(c.segment[2].SPcod[7] & 0x0020) self.assertFalse(c.segment[2].spcod[7] & 0x0020)
self.assertEqual(c.segment[2].SPcod[8], self.assertEqual(c.segment[2].spcod[8],
glymur.core.WAVELET_TRANSFORM_5x3_REVERSIBLE) glymur.core.WAVELET_XFORM_5X3_REVERSIBLE)
self.assertEqual(len(c.segment[2].SPcod), 9) self.assertEqual(len(c.segment[2].spcod), 9)
def test_NR_ENC_Cevennes1_bmp_9_encode(self): def test_NR_ENC_Cevennes1_bmp_9_encode(self):
infile = os.path.join(data_root, 'input/nonregression/Cevennes1.bmp') infile = os.path.join(data_root, 'input/nonregression/Cevennes1.bmp')
@ -555,50 +555,50 @@ class TestSuiteWrite(unittest.TestCase):
# SIZ: Image and tile size # SIZ: Image and tile size
# Profile: "0" means profile 2 # Profile: "0" means profile 2
self.assertEqual(c.segment[1].Rsiz, 0) self.assertEqual(c.segment[1].rsiz, 0)
# Reference grid size # Reference grid size
self.assertEqual((c.segment[1].Xsiz, c.segment[1].Ysiz), self.assertEqual((c.segment[1].xsiz, c.segment[1].ysiz),
(2592, 1944)) (2592, 1944))
# Reference grid offset # Reference grid offset
self.assertEqual((c.segment[1].XOsiz, c.segment[1].YOsiz), (0, 0)) self.assertEqual((c.segment[1].xosiz, c.segment[1].yosiz), (0, 0))
# Tile size # Tile size
self.assertEqual((c.segment[1].XTsiz, c.segment[1].YTsiz), self.assertEqual((c.segment[1].xtsiz, c.segment[1].ytsiz),
(2592, 1944)) (2592, 1944))
# Tile offset # Tile offset
self.assertEqual((c.segment[1].XTOsiz, c.segment[1].YTOsiz), self.assertEqual((c.segment[1].xtosiz, c.segment[1].ytosiz),
(0, 0)) (0, 0))
# bitdepth # bitdepth
self.assertEqual(c.segment[1]._bitdepth, (8, 8, 8)) self.assertEqual(c.segment[1]._bitdepth, (8, 8, 8))
# signed # signed
self.assertEqual(c.segment[1]._signed, (False, False, False)) self.assertEqual(c.segment[1]._signed, (False, False, False))
# subsampling # subsampling
self.assertEqual(list(zip(c.segment[1].XRsiz, c.segment[1].YRsiz)), self.assertEqual(list(zip(c.segment[1].xrsiz, c.segment[1].yrsiz)),
[(1, 1)] * 3) [(1, 1)] * 3)
# COD: Coding style default # COD: Coding style default
self.assertFalse(c.segment[2].Scod & 2) # no sop self.assertFalse(c.segment[2].scod & 2) # no sop
self.assertFalse(c.segment[2].Scod & 4) # no eph self.assertFalse(c.segment[2].scod & 4) # no eph
self.assertEqual(c.segment[2].SPcod[0], glymur.core.LRCP) self.assertEqual(c.segment[2].spcod[0], glymur.core.LRCP)
self.assertEqual(c.segment[2]._layers, 1) # layers = 1 self.assertEqual(c.segment[2]._layers, 1) # layers = 1
self.assertEqual(c.segment[2].SPcod[3], 1) # mct self.assertEqual(c.segment[2].spcod[3], 1) # mct
self.assertEqual(c.segment[2].SPcod[4], 5) # levels self.assertEqual(c.segment[2].spcod[4], 5) # levels
self.assertEqual(tuple(c.segment[2]._code_block_size), self.assertEqual(tuple(c.segment[2]._code_block_size),
(64, 64)) # cblksz (64, 64)) # cblksz
# Selective arithmetic coding BYPASS # Selective arithmetic coding BYPASS
self.assertFalse(c.segment[2].SPcod[7] & 0x01) self.assertFalse(c.segment[2].spcod[7] & 0x01)
# RESET context probabilities (RESET) # RESET context probabilities (RESET)
self.assertFalse(c.segment[2].SPcod[7] & 0x02) self.assertFalse(c.segment[2].spcod[7] & 0x02)
# Termination on each coding pass, RESTART(TERMALL) # Termination on each coding pass, RESTART(TERMALL)
self.assertFalse(c.segment[2].SPcod[7] & 0x04) self.assertFalse(c.segment[2].spcod[7] & 0x04)
# Vertically causal context (VSC) # Vertically causal context (VSC)
self.assertFalse(c.segment[2].SPcod[7] & 0x08) self.assertFalse(c.segment[2].spcod[7] & 0x08)
# Predictable termination, ERTERM(SEGTERM) # Predictable termination, ERTERM(SEGTERM)
self.assertFalse(c.segment[2].SPcod[7] & 0x0010) self.assertFalse(c.segment[2].spcod[7] & 0x0010)
# Segmentation symbols, SEGMARK(SEGSYSM) # Segmentation symbols, SEGMARK(SEGSYSM)
self.assertFalse(c.segment[2].SPcod[7] & 0x0020) self.assertFalse(c.segment[2].spcod[7] & 0x0020)
self.assertEqual(c.segment[2].SPcod[8], self.assertEqual(c.segment[2].spcod[8],
glymur.core.WAVELET_TRANSFORM_5x3_REVERSIBLE) glymur.core.WAVELET_XFORM_5X3_REVERSIBLE)
self.assertEqual(len(c.segment[2].SPcod), 9) self.assertEqual(len(c.segment[2].spcod), 9)
def test_NR_ENC_Cevennes2_ppm_10_encode(self): def test_NR_ENC_Cevennes2_ppm_10_encode(self):
infile = os.path.join(data_root, 'input/nonregression/Cevennes2.ppm') infile = os.path.join(data_root, 'input/nonregression/Cevennes2.ppm')
@ -611,50 +611,50 @@ class TestSuiteWrite(unittest.TestCase):
# SIZ: Image and tile size # SIZ: Image and tile size
# Profile: "0" means profile 2 # Profile: "0" means profile 2
self.assertEqual(c.segment[1].Rsiz, 0) self.assertEqual(c.segment[1].rsiz, 0)
# Reference grid size # Reference grid size
self.assertEqual((c.segment[1].Xsiz, c.segment[1].Ysiz), self.assertEqual((c.segment[1].xsiz, c.segment[1].ysiz),
(640, 480)) (640, 480))
# Reference grid offset # Reference grid offset
self.assertEqual((c.segment[1].XOsiz, c.segment[1].YOsiz), (0, 0)) self.assertEqual((c.segment[1].xosiz, c.segment[1].yosiz), (0, 0))
# Tile size # Tile size
self.assertEqual((c.segment[1].XTsiz, c.segment[1].YTsiz), self.assertEqual((c.segment[1].xtsiz, c.segment[1].ytsiz),
(640, 480)) (640, 480))
# Tile offset # Tile offset
self.assertEqual((c.segment[1].XTOsiz, c.segment[1].YTOsiz), self.assertEqual((c.segment[1].xtosiz, c.segment[1].ytosiz),
(0, 0)) (0, 0))
# bitdepth # bitdepth
self.assertEqual(c.segment[1]._bitdepth, (8, 8, 8)) self.assertEqual(c.segment[1]._bitdepth, (8, 8, 8))
# signed # signed
self.assertEqual(c.segment[1]._signed, (False, False, False)) self.assertEqual(c.segment[1]._signed, (False, False, False))
# subsampling # subsampling
self.assertEqual(list(zip(c.segment[1].XRsiz, c.segment[1].YRsiz)), self.assertEqual(list(zip(c.segment[1].xrsiz, c.segment[1].yrsiz)),
[(1, 1)] * 3) [(1, 1)] * 3)
# COD: Coding style default # COD: Coding style default
self.assertFalse(c.segment[2].Scod & 2) # no sop self.assertFalse(c.segment[2].scod & 2) # no sop
self.assertFalse(c.segment[2].Scod & 4) # no eph self.assertFalse(c.segment[2].scod & 4) # no eph
self.assertEqual(c.segment[2].SPcod[0], glymur.core.LRCP) self.assertEqual(c.segment[2].spcod[0], glymur.core.LRCP)
self.assertEqual(c.segment[2]._layers, 1) # layers = 1 self.assertEqual(c.segment[2]._layers, 1) # layers = 1
self.assertEqual(c.segment[2].SPcod[3], 1) # mct self.assertEqual(c.segment[2].spcod[3], 1) # mct
self.assertEqual(c.segment[2].SPcod[4], 5) # levels self.assertEqual(c.segment[2].spcod[4], 5) # levels
self.assertEqual(tuple(c.segment[2]._code_block_size), self.assertEqual(tuple(c.segment[2]._code_block_size),
(64, 64)) # cblksz (64, 64)) # cblksz
# Selective arithmetic coding BYPASS # Selective arithmetic coding BYPASS
self.assertFalse(c.segment[2].SPcod[7] & 0x01) self.assertFalse(c.segment[2].spcod[7] & 0x01)
# RESET context probabilities (RESET) # RESET context probabilities (RESET)
self.assertFalse(c.segment[2].SPcod[7] & 0x02) self.assertFalse(c.segment[2].spcod[7] & 0x02)
# Termination on each coding pass, RESTART(TERMALL) # Termination on each coding pass, RESTART(TERMALL)
self.assertFalse(c.segment[2].SPcod[7] & 0x04) self.assertFalse(c.segment[2].spcod[7] & 0x04)
# Vertically causal context (VSC) # Vertically causal context (VSC)
self.assertFalse(c.segment[2].SPcod[7] & 0x08) self.assertFalse(c.segment[2].spcod[7] & 0x08)
# Predictable termination, ERTERM(SEGTERM) # Predictable termination, ERTERM(SEGTERM)
self.assertFalse(c.segment[2].SPcod[7] & 0x0010) self.assertFalse(c.segment[2].spcod[7] & 0x0010)
# Segmentation symbols, SEGMARK(SEGSYSM) # Segmentation symbols, SEGMARK(SEGSYSM)
self.assertFalse(c.segment[2].SPcod[7] & 0x0020) self.assertFalse(c.segment[2].spcod[7] & 0x0020)
self.assertEqual(c.segment[2].SPcod[8], self.assertEqual(c.segment[2].spcod[8],
glymur.core.WAVELET_TRANSFORM_5x3_REVERSIBLE) glymur.core.WAVELET_XFORM_5X3_REVERSIBLE)
self.assertEqual(len(c.segment[2].SPcod), 9) self.assertEqual(len(c.segment[2].spcod), 9)
def test_NR_ENC_Rome_bmp_11_encode(self): def test_NR_ENC_Rome_bmp_11_encode(self):
infile = os.path.join(data_root, 'input/nonregression/Rome.bmp') infile = os.path.join(data_root, 'input/nonregression/Rome.bmp')
@ -663,11 +663,11 @@ class TestSuiteWrite(unittest.TestCase):
jp2 = Jp2k(tfile.name, 'wb') jp2 = Jp2k(tfile.name, 'wb')
jp2.write(data, psnr=[30, 35, 50], prog='LRCP', numres=3) jp2.write(data, psnr=[30, 35, 50], prog='LRCP', numres=3)
ids = [box.id for box in jp2.box] ids = [box.box_id for box in jp2.box]
lst = ['jP ', 'ftyp', 'jp2h', 'jp2c'] lst = ['jP ', 'ftyp', 'jp2h', 'jp2c']
self.assertEqual(ids, lst) self.assertEqual(ids, lst)
ids = [box.id for box in jp2.box[2].box] ids = [box.box_id for box in jp2.box[2].box]
self.assertEqual(ids, ['ihdr', 'colr']) self.assertEqual(ids, ['ihdr', 'colr'])
# Signature box. Check for corruption. # Signature box. Check for corruption.
@ -701,51 +701,51 @@ class TestSuiteWrite(unittest.TestCase):
# SIZ: Image and tile size # SIZ: Image and tile size
# Profile: "0" means profile 2 # Profile: "0" means profile 2
self.assertEqual(c.segment[1].Rsiz, 0) self.assertEqual(c.segment[1].rsiz, 0)
# Reference grid size # Reference grid size
self.assertEqual((c.segment[1].Xsiz, c.segment[1].Ysiz), self.assertEqual((c.segment[1].xsiz, c.segment[1].ysiz),
(640, 480)) (640, 480))
# Reference grid offset # Reference grid offset
self.assertEqual((c.segment[1].XOsiz, c.segment[1].YOsiz), self.assertEqual((c.segment[1].xosiz, c.segment[1].yosiz),
(0, 0)) (0, 0))
# Tile size # Tile size
self.assertEqual((c.segment[1].XTsiz, c.segment[1].YTsiz), self.assertEqual((c.segment[1].xtsiz, c.segment[1].ytsiz),
(640, 480)) (640, 480))
# Tile offset # Tile offset
self.assertEqual((c.segment[1].XTOsiz, c.segment[1].YTOsiz), self.assertEqual((c.segment[1].xtosiz, c.segment[1].ytosiz),
(0, 0)) (0, 0))
# bitdepth # bitdepth
self.assertEqual(c.segment[1]._bitdepth, (8, 8, 8)) self.assertEqual(c.segment[1]._bitdepth, (8, 8, 8))
# signed # signed
self.assertEqual(c.segment[1]._signed, (False, False, False)) self.assertEqual(c.segment[1]._signed, (False, False, False))
# subsampling # subsampling
self.assertEqual(list(zip(c.segment[1].XRsiz, c.segment[1].YRsiz)), self.assertEqual(list(zip(c.segment[1].xrsiz, c.segment[1].yrsiz)),
[(1, 1)] * 3) [(1, 1)] * 3)
# COD: Coding style default # COD: Coding style default
self.assertFalse(c.segment[2].Scod & 2) # no sop self.assertFalse(c.segment[2].scod & 2) # no sop
self.assertFalse(c.segment[2].Scod & 4) # no eph self.assertFalse(c.segment[2].scod & 4) # no eph
self.assertEqual(c.segment[2].SPcod[0], glymur.core.LRCP) self.assertEqual(c.segment[2].spcod[0], glymur.core.LRCP)
self.assertEqual(c.segment[2]._layers, 3) # layers = 3 self.assertEqual(c.segment[2]._layers, 3) # layers = 3
self.assertEqual(c.segment[2].SPcod[3], 1) # mct self.assertEqual(c.segment[2].spcod[3], 1) # mct
self.assertEqual(c.segment[2].SPcod[4], 2) # levels self.assertEqual(c.segment[2].spcod[4], 2) # levels
self.assertEqual(tuple(c.segment[2]._code_block_size), self.assertEqual(tuple(c.segment[2]._code_block_size),
(64, 64)) # cblksz (64, 64)) # cblksz
# Selective arithmetic coding BYPASS # Selective arithmetic coding BYPASS
self.assertFalse(c.segment[2].SPcod[7] & 0x01) self.assertFalse(c.segment[2].spcod[7] & 0x01)
# RESET context probabilities (RESET) # RESET context probabilities (RESET)
self.assertFalse(c.segment[2].SPcod[7] & 0x02) self.assertFalse(c.segment[2].spcod[7] & 0x02)
# Termination on each coding pass, RESTART(TERMALL) # Termination on each coding pass, RESTART(TERMALL)
self.assertFalse(c.segment[2].SPcod[7] & 0x04) self.assertFalse(c.segment[2].spcod[7] & 0x04)
# Vertically causal context (VSC) # Vertically causal context (VSC)
self.assertFalse(c.segment[2].SPcod[7] & 0x08) self.assertFalse(c.segment[2].spcod[7] & 0x08)
# Predictable termination, ERTERM(SEGTERM) # Predictable termination, ERTERM(SEGTERM)
self.assertFalse(c.segment[2].SPcod[7] & 0x0010) self.assertFalse(c.segment[2].spcod[7] & 0x0010)
# Segmentation symbols, SEGMARK(SEGSYSM) # Segmentation symbols, SEGMARK(SEGSYSM)
self.assertFalse(c.segment[2].SPcod[7] & 0x0020) self.assertFalse(c.segment[2].spcod[7] & 0x0020)
self.assertEqual(c.segment[2].SPcod[8], self.assertEqual(c.segment[2].spcod[8],
glymur.core.WAVELET_TRANSFORM_5x3_REVERSIBLE) glymur.core.WAVELET_XFORM_5X3_REVERSIBLE)
self.assertEqual(len(c.segment[2].SPcod), 9) self.assertEqual(len(c.segment[2].spcod), 9)
@unittest.skip("Known failure in openjpeg test suite.") @unittest.skip("Known failure in openjpeg test suite.")
def test_NR_ENC_random_issue_0005_tif_12_encode(self): def test_NR_ENC_random_issue_0005_tif_12_encode(self):
@ -762,50 +762,50 @@ class TestSuiteWrite(unittest.TestCase):
# SIZ: Image and tile size # SIZ: Image and tile size
# Profile: "0" means profile 2 # Profile: "0" means profile 2
self.assertEqual(c.segment[1].Rsiz, 0) self.assertEqual(c.segment[1].rsiz, 0)
# Reference grid size # Reference grid size
self.assertEqual((c.segment[1].Xsiz, c.segment[1].Ysiz), self.assertEqual((c.segment[1].xsiz, c.segment[1].ysiz),
(1024, 1024)) (1024, 1024))
# Reference grid offset # Reference grid offset
self.assertEqual((c.segment[1].XOsiz, c.segment[1].YOsiz), (0, 0)) self.assertEqual((c.segment[1].xosiz, c.segment[1].yosiz), (0, 0))
# Tile size # Tile size
self.assertEqual((c.segment[1].XTsiz, c.segment[1].YTsiz), self.assertEqual((c.segment[1].xtsiz, c.segment[1].ytsiz),
(1024, 1024)) (1024, 1024))
# Tile offset # Tile offset
self.assertEqual((c.segment[1].XTOsiz, c.segment[1].YTOsiz), self.assertEqual((c.segment[1].xtosiz, c.segment[1].ytosiz),
(0, 0)) (0, 0))
# bitdepth # bitdepth
self.assertEqual(c.segment[1]._bitdepth, (16,)) self.assertEqual(c.segment[1]._bitdepth, (16,))
# signed # signed
self.assertEqual(c.segment[1]._signed, (False,)) self.assertEqual(c.segment[1]._signed, (False,))
# subsampling # subsampling
self.assertEqual(list(zip(c.segment[1].XRsiz, c.segment[1].YRsiz)), self.assertEqual(list(zip(c.segment[1].xrsiz, c.segment[1].yrsiz)),
[(1, 1)]) [(1, 1)])
# COD: Coding style default # COD: Coding style default
self.assertFalse(c.segment[2].Scod & 2) # no sop self.assertFalse(c.segment[2].scod & 2) # no sop
self.assertFalse(c.segment[2].Scod & 4) # no eph self.assertFalse(c.segment[2].scod & 4) # no eph
self.assertEqual(c.segment[2].SPcod[0], glymur.core.LRCP) self.assertEqual(c.segment[2].spcod[0], glymur.core.LRCP)
self.assertEqual(c.segment[2]._layers, 1) # layers = 1 self.assertEqual(c.segment[2]._layers, 1) # layers = 1
self.assertEqual(c.segment[2].SPcod[3], 0) # mct self.assertEqual(c.segment[2].spcod[3], 0) # mct
self.assertEqual(c.segment[2].SPcod[4], 5) # levels self.assertEqual(c.segment[2].spcod[4], 5) # levels
self.assertEqual(tuple(c.segment[2]._code_block_size), self.assertEqual(tuple(c.segment[2]._code_block_size),
(64, 64)) # cblksz (64, 64)) # cblksz
# Selective arithmetic coding BYPASS # Selective arithmetic coding BYPASS
self.assertFalse(c.segment[2].SPcod[7] & 0x01) self.assertFalse(c.segment[2].spcod[7] & 0x01)
# RESET context probabilities (RESET) # RESET context probabilities (RESET)
self.assertFalse(c.segment[2].SPcod[7] & 0x02) self.assertFalse(c.segment[2].spcod[7] & 0x02)
# Termination on each coding pass, RESTART(TERMALL) # Termination on each coding pass, RESTART(TERMALL)
self.assertFalse(c.segment[2].SPcod[7] & 0x04) self.assertFalse(c.segment[2].spcod[7] & 0x04)
# Vertically causal context (VSC) # Vertically causal context (VSC)
self.assertFalse(c.segment[2].SPcod[7] & 0x08) self.assertFalse(c.segment[2].spcod[7] & 0x08)
# Predictable termination, ERTERM(SEGTERM) # Predictable termination, ERTERM(SEGTERM)
self.assertFalse(c.segment[2].SPcod[7] & 0x0010) self.assertFalse(c.segment[2].spcod[7] & 0x0010)
# Segmentation symbols, SEGMARK(SEGSYSM) # Segmentation symbols, SEGMARK(SEGSYSM)
self.assertFalse(c.segment[2].SPcod[7] & 0x0020) self.assertFalse(c.segment[2].spcod[7] & 0x0020)
self.assertEqual(c.segment[2].SPcod[8], self.assertEqual(c.segment[2].spcod[8],
glymur.core.WAVELET_TRANSFORM_5x3_REVERSIBLE) glymur.core.WAVELET_XFORM_5X3_REVERSIBLE)
self.assertEqual(len(c.segment[2].SPcod), 9) self.assertEqual(len(c.segment[2].spcod), 9)
if __name__ == "__main__": if __name__ == "__main__":
unittest.main() unittest.main()

View file

@ -21,7 +21,7 @@ except:
raise raise
@unittest.skipIf(glymur.lib.openjp2._OPENJP2 is None, @unittest.skipIf(glymur.lib.openjp2.OPENJP2 is None,
"Missing openjp2 library.") "Missing openjp2 library.")
class TestPrintingNeedsLib(unittest.TestCase): class TestPrintingNeedsLib(unittest.TestCase):
"""These tests require the library, mostly in order to just setup the test. """These tests require the library, mostly in order to just setup the test.
@ -34,7 +34,7 @@ class TestPrintingNeedsLib(unittest.TestCase):
with tempfile.NamedTemporaryFile(suffix='.jp2', delete=False) as tfile: with tempfile.NamedTemporaryFile(suffix='.jp2', delete=False) as tfile:
cls._plain_nemo_file = tfile.name cls._plain_nemo_file = tfile.name
ijfile = Jp2k(jp2file) ijfile = Jp2k(jp2file)
data = ijfile.read(reduce=1) data = ijfile.read(rlevel=1)
ojfile = Jp2k(cls._plain_nemo_file, 'wb') ojfile = Jp2k(cls._plain_nemo_file, 'wb')
ojfile.write(data) ojfile.write(data)
@ -122,7 +122,7 @@ class TestPrintingNeedsLib(unittest.TestCase):
def test_asoc_label_box(self): def test_asoc_label_box(self):
# Construct a fake file with an asoc and a label box, as # Construct a fake file with an asoc and a label box, as
# OpenJPEG doesn't have such a file. # OpenJPEG doesn't have such a file.
data = glymur.Jp2k(self.jp2file).read(reduce=1) data = glymur.Jp2k(self.jp2file).read(rlevel=1)
with tempfile.NamedTemporaryFile(suffix='.jp2') as tfile: with tempfile.NamedTemporaryFile(suffix='.jp2') as tfile:
j = glymur.Jp2k(tfile.name, 'wb') j = glymur.Jp2k(tfile.name, 'wb')
j.write(data) j.write(data)
@ -640,6 +640,7 @@ class TestPrinting(unittest.TestCase):
' CME marker segment @ (3209, 37)', ' CME marker segment @ (3209, 37)',
' "Created by OpenJPEG version 2.0.0"'] ' "Created by OpenJPEG version 2.0.0"']
expected = '\n'.join(lst) expected = '\n'.join(lst)
self.maxDiff = None
self.assertEqual(actual, expected) self.assertEqual(actual, expected)
@unittest.skipIf(data_root is None, @unittest.skipIf(data_root is None,