internalized some private functions into Jp2k class methods
This commit is contained in:
parent
6abf184ad7
commit
a783f6f139
1 changed files with 136 additions and 154 deletions
290
glymur/jp2k.py
290
glymur/jp2k.py
|
|
@ -157,7 +157,7 @@ class Jp2k(Jp2kBox):
|
||||||
msg += "profile if the file type box brand is 'jp2 '."
|
msg += "profile if the file type box brand is 'jp2 '."
|
||||||
warnings.warn(msg)
|
warnings.warn(msg)
|
||||||
|
|
||||||
def _set_cinema_params(self, cparams, cinema_mode, fps):
|
def _set_cinema_params(self, cinema_mode, fps):
|
||||||
"""Populate compression parameters structure for cinema2K.
|
"""Populate compression parameters structure for cinema2K.
|
||||||
|
|
||||||
Parameters
|
Parameters
|
||||||
|
|
@ -176,7 +176,7 @@ class Jp2k(Jp2kBox):
|
||||||
raise IOError(msg)
|
raise IOError(msg)
|
||||||
|
|
||||||
# Cinema modes imply MCT.
|
# Cinema modes imply MCT.
|
||||||
cparams.tcp_mct = 1
|
self._cparams.tcp_mct = 1
|
||||||
|
|
||||||
if cinema_mode == 'cinema2k':
|
if cinema_mode == 'cinema2k':
|
||||||
if fps not in [24, 48]:
|
if fps not in [24, 48]:
|
||||||
|
|
@ -185,30 +185,28 @@ class Jp2k(Jp2kBox):
|
||||||
if re.match("2.0", version.openjpeg_version) is not None:
|
if re.match("2.0", version.openjpeg_version) is not None:
|
||||||
# 2.0 API
|
# 2.0 API
|
||||||
if fps == 24:
|
if fps == 24:
|
||||||
cparams.cp_cinema = core.OPJ_CINEMA2K_24
|
self._cparams.cp_cinema = core.OPJ_CINEMA2K_24
|
||||||
else:
|
else:
|
||||||
cparams.cp_cinema = core.OPJ_CINEMA2K_48
|
self._cparams.cp_cinema = core.OPJ_CINEMA2K_48
|
||||||
else:
|
else:
|
||||||
# 2.1 API
|
# 2.1 API
|
||||||
if fps == 24:
|
if fps == 24:
|
||||||
cparams.rsiz = core.OPJ_PROFILE_CINEMA_2K
|
self._cparams.rsiz = core.OPJ_PROFILE_CINEMA_2K
|
||||||
cparams.max_comp_size = core.OPJ_CINEMA_24_COMP
|
self._cparams.max_comp_size = core.OPJ_CINEMA_24_COMP
|
||||||
cparams.max_cs_size = core.OPJ_CINEMA_24_CS
|
self._cparams.max_cs_size = core.OPJ_CINEMA_24_CS
|
||||||
else:
|
else:
|
||||||
cparams.rsiz = core.OPJ_PROFILE_CINEMA_2K
|
self._cparams.rsiz = core.OPJ_PROFILE_CINEMA_2K
|
||||||
cparams.max_comp_size = core.OPJ_CINEMA_48_COMP
|
self._cparams.max_comp_size = core.OPJ_CINEMA_48_COMP
|
||||||
cparams.max_cs_size = core.OPJ_CINEMA_48_CS
|
self._cparams.max_cs_size = core.OPJ_CINEMA_48_CS
|
||||||
|
|
||||||
else:
|
else:
|
||||||
# cinema4k
|
# cinema4k
|
||||||
if re.match("2.0", version.openjpeg_version) is not None:
|
if re.match("2.0", version.openjpeg_version) is not None:
|
||||||
# 2.0 API
|
# 2.0 API
|
||||||
cparams.cp_cinema = core.OPJ_CINEMA4K_24
|
self._cparams.cp_cinema = core.OPJ_CINEMA4K_24
|
||||||
else:
|
else:
|
||||||
# 2.1 API
|
# 2.1 API
|
||||||
cparams.rsiz = core.OPJ_PROFILE_CINEMA_4K
|
self._cparams.rsiz = core.OPJ_PROFILE_CINEMA_4K
|
||||||
|
|
||||||
return
|
|
||||||
|
|
||||||
def _populate_cparams(self, img_array, **kwargs):
|
def _populate_cparams(self, img_array, **kwargs):
|
||||||
"""Directs processing of write method arguments.
|
"""Directs processing of write method arguments.
|
||||||
|
|
@ -219,11 +217,6 @@ class Jp2k(Jp2kBox):
|
||||||
image data to be written to file
|
image data to be written to file
|
||||||
kwargs : dictionary
|
kwargs : dictionary
|
||||||
non-image keyword inputs provided to write method
|
non-image keyword inputs provided to write method
|
||||||
|
|
||||||
Returns
|
|
||||||
-------
|
|
||||||
cparams : CompressionParametersType(ctypes.Structure)
|
|
||||||
corresponds to cparameters_t openjpeg datatype
|
|
||||||
"""
|
"""
|
||||||
if (('cinema2k' in kwargs or 'cinema4k' in kwargs) and
|
if (('cinema2k' in kwargs or 'cinema4k' in kwargs) and
|
||||||
(len(set(kwargs)) > 1)):
|
(len(set(kwargs)) > 1)):
|
||||||
|
|
@ -258,12 +251,14 @@ class Jp2k(Jp2kBox):
|
||||||
cparams.irreversible = 1
|
cparams.irreversible = 1
|
||||||
|
|
||||||
if 'cinema2k' in kwargs:
|
if 'cinema2k' in kwargs:
|
||||||
self._set_cinema_params(cparams, 'cinema2k', kwargs['cinema2k'])
|
self._cparams = cparams
|
||||||
return cparams
|
self._set_cinema_params('cinema2k', kwargs['cinema2k'])
|
||||||
|
return
|
||||||
|
|
||||||
if 'cinema4k' in kwargs:
|
if 'cinema4k' in kwargs:
|
||||||
self._set_cinema_params(cparams, 'cinema4k', kwargs['cinema4k'])
|
self._cparams = cparams
|
||||||
return cparams
|
self._set_cinema_params('cinema4k', kwargs['cinema4k'])
|
||||||
|
return
|
||||||
|
|
||||||
if 'cbsize' in kwargs:
|
if 'cbsize' in kwargs:
|
||||||
cparams.cblockw_init = kwargs['cbsize'][1]
|
cparams.cblockw_init = kwargs['cbsize'][1]
|
||||||
|
|
@ -337,7 +332,7 @@ class Jp2k(Jp2kBox):
|
||||||
|
|
||||||
self._validate_compression_params(img_array, cparams, **kwargs)
|
self._validate_compression_params(img_array, cparams, **kwargs)
|
||||||
|
|
||||||
return cparams
|
self._cparams = cparams
|
||||||
|
|
||||||
def write(self, img_array, verbose=False, **kwargs):
|
def write(self, img_array, verbose=False, **kwargs):
|
||||||
"""Write image data to a JP2/JPX/J2k file. Intended usage of the
|
"""Write image data to a JP2/JPX/J2k file. Intended usage of the
|
||||||
|
|
@ -412,14 +407,14 @@ class Jp2k(Jp2kBox):
|
||||||
"in order to write images.")
|
"in order to write images.")
|
||||||
|
|
||||||
self._determine_colorspace(img_array, **kwargs)
|
self._determine_colorspace(img_array, **kwargs)
|
||||||
cparams = self._populate_cparams(img_array, **kwargs)
|
self._populate_cparams(img_array, **kwargs)
|
||||||
|
|
||||||
if opj2.OPENJP2 is not None:
|
if opj2.OPENJP2 is not None:
|
||||||
self._write_openjp2(img_array, cparams, verbose=verbose)
|
self._write_openjp2(img_array, verbose=verbose)
|
||||||
else:
|
else:
|
||||||
self._write_openjpeg(img_array, cparams, verbose=verbose)
|
self._write_openjpeg(img_array, verbose=verbose)
|
||||||
|
|
||||||
def _write_openjpeg(self, img_array, cparams, verbose=False):
|
def _write_openjpeg(self, img_array, verbose=False):
|
||||||
"""
|
"""
|
||||||
Write JPEG 2000 file using OpenJPEG 1.5 interface.
|
Write JPEG 2000 file using OpenJPEG 1.5 interface.
|
||||||
"""
|
"""
|
||||||
|
|
@ -429,21 +424,21 @@ class Jp2k(Jp2kBox):
|
||||||
img_array.shape[1],
|
img_array.shape[1],
|
||||||
1)
|
1)
|
||||||
|
|
||||||
comptparms = _populate_comptparms(img_array, cparams)
|
self._populate_comptparms(img_array)
|
||||||
|
|
||||||
with ExitStack() as stack:
|
with ExitStack() as stack:
|
||||||
image = opj.image_create(comptparms, self._colorspace)
|
image = opj.image_create(self._comptparms, self._colorspace)
|
||||||
stack.callback(opj.image_destroy, image)
|
stack.callback(opj.image_destroy, image)
|
||||||
|
|
||||||
numrows, numcols, numlayers = img_array.shape
|
numrows, numcols, numlayers = img_array.shape
|
||||||
|
|
||||||
# set image offset and reference grid
|
# set image offset and reference grid
|
||||||
image.contents.x0 = cparams.image_offset_x0
|
image.contents.x0 = self._cparams.image_offset_x0
|
||||||
image.contents.y0 = cparams.image_offset_y0
|
image.contents.y0 = self._cparams.image_offset_y0
|
||||||
image.contents.x1 = image.contents.x0 \
|
image.contents.x1 = image.contents.x0 \
|
||||||
+ (numcols - 1) * cparams.subsampling_dx + 1
|
+ (numcols - 1) * self._cparams.subsampling_dx + 1
|
||||||
image.contents.y1 = image.contents.y0 \
|
image.contents.y1 = image.contents.y0 \
|
||||||
+ (numrows - 1) * cparams.subsampling_dy + 1
|
+ (numrows - 1) * self._cparams.subsampling_dy + 1
|
||||||
|
|
||||||
# Stage the image data to the openjpeg data structure.
|
# Stage the image data to the openjpeg data structure.
|
||||||
for k in range(0, numlayers):
|
for k in range(0, numlayers):
|
||||||
|
|
@ -453,7 +448,7 @@ class Jp2k(Jp2kBox):
|
||||||
src = layer.ctypes.data
|
src = layer.ctypes.data
|
||||||
ctypes.memmove(dest, src, layer.nbytes)
|
ctypes.memmove(dest, src, layer.nbytes)
|
||||||
|
|
||||||
cinfo = opj.create_compress(cparams.codec_fmt)
|
cinfo = opj.create_compress(self._cparams.codec_fmt)
|
||||||
stack.callback(opj.destroy_compress, cinfo)
|
stack.callback(opj.destroy_compress, cinfo)
|
||||||
|
|
||||||
# Setup the info, warning, and error handlers.
|
# Setup the info, warning, and error handlers.
|
||||||
|
|
@ -467,7 +462,7 @@ class Jp2k(Jp2kBox):
|
||||||
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.setup_encoder(cinfo, ctypes.byref(cparams), image)
|
opj.setup_encoder(cinfo, ctypes.byref(self._cparams), image)
|
||||||
|
|
||||||
cio = opj.cio_open(cinfo)
|
cio = opj.cio_open(cinfo)
|
||||||
stack.callback(opj.cio_close, cio)
|
stack.callback(opj.cio_close, cio)
|
||||||
|
|
@ -588,7 +583,7 @@ class Jp2k(Jp2kBox):
|
||||||
self._colorspace = _COLORSPACE_MAP[colorspace.lower()]
|
self._colorspace = _COLORSPACE_MAP[colorspace.lower()]
|
||||||
|
|
||||||
|
|
||||||
def _write_openjp2(self, img_array, cparams, verbose=False):
|
def _write_openjp2(self, img_array, verbose=False):
|
||||||
"""
|
"""
|
||||||
Write JPEG 2000 file using OpenJPEG 2.x interface.
|
Write JPEG 2000 file using OpenJPEG 2.x interface.
|
||||||
"""
|
"""
|
||||||
|
|
@ -597,15 +592,15 @@ class Jp2k(Jp2kBox):
|
||||||
numrows, numcols = img_array.shape
|
numrows, numcols = img_array.shape
|
||||||
img_array = img_array.reshape(numrows, numcols, 1)
|
img_array = img_array.reshape(numrows, numcols, 1)
|
||||||
|
|
||||||
comptparms = _populate_comptparms(img_array, cparams)
|
self._populate_comptparms(img_array)
|
||||||
|
|
||||||
with ExitStack() as stack:
|
with ExitStack() as stack:
|
||||||
image = opj2.image_create(comptparms, self._colorspace)
|
image = opj2.image_create(self._comptparms, self._colorspace)
|
||||||
stack.callback(opj2.image_destroy, image)
|
stack.callback(opj2.image_destroy, image)
|
||||||
|
|
||||||
_populate_image_struct(cparams, image, img_array)
|
self._populate_image_struct(image, img_array)
|
||||||
|
|
||||||
codec = opj2.create_compress(cparams.codec_fmt)
|
codec = opj2.create_compress(self._cparams.codec_fmt)
|
||||||
stack.callback(opj2.destroy_codec, codec)
|
stack.callback(opj2.destroy_codec, codec)
|
||||||
|
|
||||||
info_handler = _INFO_CALLBACK if verbose else None
|
info_handler = _INFO_CALLBACK if verbose else None
|
||||||
|
|
@ -613,7 +608,7 @@ class Jp2k(Jp2kBox):
|
||||||
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, self._cparams, image)
|
||||||
|
|
||||||
if re.match("2.0", version.openjpeg_version) is not None:
|
if re.match("2.0", version.openjpeg_version) is not None:
|
||||||
fptr = libc.fopen(self.filename, 'wb')
|
fptr = libc.fopen(self.filename, 'wb')
|
||||||
|
|
@ -1020,13 +1015,13 @@ class Jp2k(Jp2kBox):
|
||||||
"""
|
"""
|
||||||
self._subsampling_sanity_check()
|
self._subsampling_sanity_check()
|
||||||
|
|
||||||
dparameters = self._populate_dparam(rlevel, ignore_pclr_cmap_cdef)
|
self._populate_dparams(rlevel, ignore_pclr_cmap_cdef)
|
||||||
|
|
||||||
with ExitStack() as stack:
|
with ExitStack() as stack:
|
||||||
try:
|
try:
|
||||||
dparameters.decod_format = self._codec_format
|
self._dparams.decod_format = self._codec_format
|
||||||
|
|
||||||
dinfo = opj.create_decompress(dparameters.decod_format)
|
dinfo = opj.create_decompress(self._dparams.decod_format)
|
||||||
|
|
||||||
event_mgr = opj.EventMgrType()
|
event_mgr = opj.EventMgrType()
|
||||||
info_handler = ctypes.cast(_INFO_CALLBACK, ctypes.c_void_p)
|
info_handler = ctypes.cast(_INFO_CALLBACK, ctypes.c_void_p)
|
||||||
|
|
@ -1037,7 +1032,7 @@ class Jp2k(Jp2kBox):
|
||||||
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, self._dparams)
|
||||||
|
|
||||||
with open(self.filename, 'rb') as fptr:
|
with open(self.filename, 'rb') as fptr:
|
||||||
src = fptr.read()
|
src = fptr.read()
|
||||||
|
|
@ -1104,8 +1099,8 @@ class Jp2k(Jp2kBox):
|
||||||
"""
|
"""
|
||||||
self._subsampling_sanity_check()
|
self._subsampling_sanity_check()
|
||||||
|
|
||||||
dparam = self._populate_dparam(rlevel, ignore_pclr_cmap_cdef,
|
self._populate_dparams(rlevel, ignore_pclr_cmap_cdef,
|
||||||
layer=layer, tile=tile, area=area)
|
layer=layer, tile=tile, area=area)
|
||||||
|
|
||||||
with ExitStack() as stack:
|
with ExitStack() as stack:
|
||||||
if re.match("2.1", version.openjpeg_version):
|
if re.match("2.1", version.openjpeg_version):
|
||||||
|
|
@ -1127,16 +1122,17 @@ class Jp2k(Jp2kBox):
|
||||||
else:
|
else:
|
||||||
opj2.set_info_handler(codec, None)
|
opj2.set_info_handler(codec, None)
|
||||||
|
|
||||||
opj2.setup_decoder(codec, dparam)
|
opj2.setup_decoder(codec, self._dparams)
|
||||||
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 self._dparams.nb_tile_to_decode:
|
||||||
opj2.get_decoded_tile(codec, stream, image, dparam.tile_index)
|
opj2.get_decoded_tile(codec, stream, image,
|
||||||
|
self._dparams.tile_index)
|
||||||
else:
|
else:
|
||||||
opj2.set_decode_area(codec, image,
|
opj2.set_decode_area(codec, image,
|
||||||
dparam.DA_x0, dparam.DA_y0,
|
self._dparams.DA_x0, self._dparams.DA_y0,
|
||||||
dparam.DA_x1, dparam.DA_y1)
|
self._dparams.DA_x1, self._dparams.DA_y1)
|
||||||
opj2.decode(codec, stream, image)
|
opj2.decode(codec, stream, image)
|
||||||
opj2.end_decompress(codec, stream)
|
opj2.end_decompress(codec, stream)
|
||||||
|
|
||||||
|
|
@ -1147,8 +1143,8 @@ class Jp2k(Jp2kBox):
|
||||||
|
|
||||||
return img_array
|
return img_array
|
||||||
|
|
||||||
def _populate_dparam(self, rlevel, ignore_pclr_cmap_cdef, tile=None,
|
def _populate_dparams(self, rlevel, ignore_pclr_cmap_cdef, tile=None,
|
||||||
layer=None, area=None):
|
layer=None, area=None):
|
||||||
"""Populate decompression structure with appropriate input parameters.
|
"""Populate decompression structure with appropriate input parameters.
|
||||||
|
|
||||||
Parameters
|
Parameters
|
||||||
|
|
@ -1165,11 +1161,6 @@ class Jp2k(Jp2kBox):
|
||||||
ignore_pclr_cmap_cdef : bool
|
ignore_pclr_cmap_cdef : bool
|
||||||
Whether or not to ignore the pclr, cmap, or cdef boxes during any
|
Whether or not to ignore the pclr, cmap, or cdef boxes during any
|
||||||
color transformation. Defaults to False.
|
color transformation. Defaults to False.
|
||||||
|
|
||||||
Returns
|
|
||||||
-------
|
|
||||||
dparam : DecompressionParametersType (ctypes)
|
|
||||||
Corresponds to openjp2 decompression parameters structure.
|
|
||||||
"""
|
"""
|
||||||
if opj2.OPENJP2 is not None:
|
if opj2.OPENJP2 is not None:
|
||||||
dparam = opj2.set_default_decoder_parameters()
|
dparam = opj2.set_default_decoder_parameters()
|
||||||
|
|
@ -1220,7 +1211,7 @@ class Jp2k(Jp2kBox):
|
||||||
# Return raw codestream components.
|
# Return raw codestream components.
|
||||||
dparam.flags |= 1
|
dparam.flags |= 1
|
||||||
|
|
||||||
return dparam
|
self._dparams = dparam
|
||||||
|
|
||||||
def read_bands(self, rlevel=0, layer=0, area=None, tile=None,
|
def read_bands(self, rlevel=0, layer=0, area=None, tile=None,
|
||||||
verbose=False, ignore_pclr_cmap_cdef=False):
|
verbose=False, ignore_pclr_cmap_cdef=False):
|
||||||
|
|
@ -1268,8 +1259,8 @@ class Jp2k(Jp2kBox):
|
||||||
"OpenJPEG installed before using this "
|
"OpenJPEG installed before using this "
|
||||||
"functionality.")
|
"functionality.")
|
||||||
|
|
||||||
dparam = self._populate_dparam(rlevel, ignore_pclr_cmap_cdef,
|
self._populate_dparams(rlevel, ignore_pclr_cmap_cdef,
|
||||||
layer=layer, tile=tile, area=area)
|
layer=layer, tile=tile, area=area)
|
||||||
|
|
||||||
with ExitStack() as stack:
|
with ExitStack() as stack:
|
||||||
if re.match("2.1", version.openjpeg_version):
|
if re.match("2.1", version.openjpeg_version):
|
||||||
|
|
@ -1292,16 +1283,17 @@ class Jp2k(Jp2kBox):
|
||||||
else:
|
else:
|
||||||
opj2.set_info_handler(codec, None)
|
opj2.set_info_handler(codec, None)
|
||||||
|
|
||||||
opj2.setup_decoder(codec, dparam)
|
opj2.setup_decoder(codec, self._dparams)
|
||||||
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 self._dparams.nb_tile_to_decode:
|
||||||
opj2.get_decoded_tile(codec, stream, image, dparam.tile_index)
|
opj2.get_decoded_tile(codec, stream, image,
|
||||||
|
self._dparams.tile_index)
|
||||||
else:
|
else:
|
||||||
opj2.set_decode_area(codec, image,
|
opj2.set_decode_area(codec, image,
|
||||||
dparam.DA_x0, dparam.DA_y0,
|
self._dparams.DA_x0, self._dparams.DA_y0,
|
||||||
dparam.DA_x1, dparam.DA_y1)
|
self._dparams.DA_x1, self._dparams.DA_y1)
|
||||||
opj2.decode(codec, stream, image)
|
opj2.decode(codec, stream, image)
|
||||||
opj2.end_decompress(codec, stream)
|
opj2.end_decompress(codec, stream)
|
||||||
|
|
||||||
|
|
@ -1362,7 +1354,83 @@ class Jp2k(Jp2kBox):
|
||||||
|
|
||||||
return codestream
|
return codestream
|
||||||
|
|
||||||
|
def _populate_image_struct(self, image, imgdata):
|
||||||
|
"""Populates image struct needed for compression.
|
||||||
|
|
||||||
|
Parameters
|
||||||
|
----------
|
||||||
|
image : ImageType(ctypes.Structure)
|
||||||
|
Corresponds to image_t type in openjp2 headers.
|
||||||
|
img_array : ndarray
|
||||||
|
Image data to be written to file.
|
||||||
|
"""
|
||||||
|
|
||||||
|
numrows, numcols, num_comps = imgdata.shape
|
||||||
|
|
||||||
|
# set image offset and reference grid
|
||||||
|
image.contents.x0 = self._cparams.image_offset_x0
|
||||||
|
image.contents.y0 = self._cparams.image_offset_y0
|
||||||
|
image.contents.x1 = (image.contents.x0 +
|
||||||
|
(numcols - 1) * self._cparams.subsampling_dx + 1)
|
||||||
|
image.contents.y1 = (image.contents.y0 +
|
||||||
|
(numrows - 1) * self._cparams.subsampling_dy + 1)
|
||||||
|
|
||||||
|
# Stage the image data to the openjpeg data structure.
|
||||||
|
for k in range(0, num_comps):
|
||||||
|
if re.match("2.0", version.openjpeg_version) is not None:
|
||||||
|
# 2.0 API
|
||||||
|
if self._cparams.cp_cinema:
|
||||||
|
image.contents.comps[k].prec = 12
|
||||||
|
image.contents.comps[k].bpp = 12
|
||||||
|
else:
|
||||||
|
# 2.1 API
|
||||||
|
if self._cparams.rsiz in (core.OPJ_PROFILE_CINEMA_2K,
|
||||||
|
core.OPJ_PROFILE_CINEMA_4K):
|
||||||
|
image.contents.comps[k].prec = 12
|
||||||
|
image.contents.comps[k].bpp = 12
|
||||||
|
|
||||||
|
layer = np.ascontiguousarray(imgdata[:, :, k], dtype=np.int32)
|
||||||
|
dest = image.contents.comps[k].data
|
||||||
|
src = layer.ctypes.data
|
||||||
|
ctypes.memmove(dest, src, layer.nbytes)
|
||||||
|
|
||||||
|
return image
|
||||||
|
|
||||||
|
def _populate_comptparms(self, img_array):
|
||||||
|
"""Instantiate and populate comptparms structure.
|
||||||
|
|
||||||
|
This structure defines the image components.
|
||||||
|
|
||||||
|
Parameters
|
||||||
|
----------
|
||||||
|
img_array : ndarray
|
||||||
|
Image data to be written to file.
|
||||||
|
"""
|
||||||
|
# Only two precisions are possible.
|
||||||
|
if img_array.dtype == np.uint8:
|
||||||
|
comp_prec = 8
|
||||||
|
else:
|
||||||
|
comp_prec = 16
|
||||||
|
|
||||||
|
numrows, numcols, num_comps = img_array.shape
|
||||||
|
if version.openjpeg_version_tuple[0] == 1:
|
||||||
|
comptparms = (opj.ImageComptParmType * num_comps)()
|
||||||
|
else:
|
||||||
|
comptparms = (opj2.ImageComptParmType * num_comps)()
|
||||||
|
for j in range(num_comps):
|
||||||
|
comptparms[j].dx = self._cparams.subsampling_dx
|
||||||
|
comptparms[j].dy = self._cparams.subsampling_dy
|
||||||
|
comptparms[j].w = numcols
|
||||||
|
comptparms[j].h = numrows
|
||||||
|
comptparms[j].x0 = self._cparams.image_offset_x0
|
||||||
|
comptparms[j].y0 = self._cparams.image_offset_y0
|
||||||
|
comptparms[j].prec = comp_prec
|
||||||
|
comptparms[j].bpp = comp_prec
|
||||||
|
comptparms[j].sgnd = 0
|
||||||
|
|
||||||
|
self._comptparms = comptparms
|
||||||
|
|
||||||
|
|
||||||
def _component2dtype(component):
|
def _component2dtype(component):
|
||||||
"""Take an OpenJPEG component structure and determine the numpy datatype.
|
"""Take an OpenJPEG component structure and determine the numpy datatype.
|
||||||
|
|
||||||
|
|
@ -1704,92 +1772,6 @@ def extract_image_bands(image):
|
||||||
return data
|
return data
|
||||||
|
|
||||||
|
|
||||||
def _populate_comptparms(img_array, cparams):
|
|
||||||
"""Instantiate and populate comptparms structure.
|
|
||||||
|
|
||||||
This structure defines the image components.
|
|
||||||
|
|
||||||
Parameters
|
|
||||||
----------
|
|
||||||
img_array : ndarray
|
|
||||||
Image data to be written to file.
|
|
||||||
cparams : CompressionParametersType(ctypes.Structure)
|
|
||||||
Corresponds to cparameters_t type in openjp2 headers.
|
|
||||||
|
|
||||||
Returns
|
|
||||||
-------
|
|
||||||
comptparms : ImageCompType(ctypes.Structure)
|
|
||||||
Corresponds to image_comp_t type in openjp2 headers.
|
|
||||||
"""
|
|
||||||
# Only two precisions are possible.
|
|
||||||
if img_array.dtype == np.uint8:
|
|
||||||
comp_prec = 8
|
|
||||||
else:
|
|
||||||
comp_prec = 16
|
|
||||||
|
|
||||||
numrows, numcols, num_comps = img_array.shape
|
|
||||||
if version.openjpeg_version_tuple[0] == 1:
|
|
||||||
comptparms = (opj.ImageComptParmType * num_comps)()
|
|
||||||
else:
|
|
||||||
comptparms = (opj2.ImageComptParmType * num_comps)()
|
|
||||||
for j in range(num_comps):
|
|
||||||
comptparms[j].dx = cparams.subsampling_dx
|
|
||||||
comptparms[j].dy = cparams.subsampling_dy
|
|
||||||
comptparms[j].w = numcols
|
|
||||||
comptparms[j].h = numrows
|
|
||||||
comptparms[j].x0 = cparams.image_offset_x0
|
|
||||||
comptparms[j].y0 = cparams.image_offset_y0
|
|
||||||
comptparms[j].prec = comp_prec
|
|
||||||
comptparms[j].bpp = comp_prec
|
|
||||||
comptparms[j].sgnd = 0
|
|
||||||
|
|
||||||
return comptparms
|
|
||||||
|
|
||||||
|
|
||||||
def _populate_image_struct(cparams, image, imgdata):
|
|
||||||
"""Populates image struct needed for compression.
|
|
||||||
|
|
||||||
Parameters
|
|
||||||
----------
|
|
||||||
cparams : CompressionParametersType(ctypes.Structure)
|
|
||||||
Corresponds to cparameters_t type in openjp2 headers.
|
|
||||||
image : ImageType(ctypes.Structure)
|
|
||||||
Corresponds to image_t type in openjp2 headers.
|
|
||||||
imgarray : ndarray
|
|
||||||
Image data to be written to file.
|
|
||||||
"""
|
|
||||||
|
|
||||||
numrows, numcols, num_comps = imgdata.shape
|
|
||||||
|
|
||||||
# set image offset and reference grid
|
|
||||||
image.contents.x0 = cparams.image_offset_x0
|
|
||||||
image.contents.y0 = cparams.image_offset_y0
|
|
||||||
image.contents.x1 = (image.contents.x0 +
|
|
||||||
(numcols - 1) * cparams.subsampling_dx + 1)
|
|
||||||
image.contents.y1 = (image.contents.y0 +
|
|
||||||
(numrows - 1) * cparams.subsampling_dy + 1)
|
|
||||||
|
|
||||||
# Stage the image data to the openjpeg data structure.
|
|
||||||
for k in range(0, num_comps):
|
|
||||||
if re.match("2.0", version.openjpeg_version) is not None:
|
|
||||||
# 2.0 API
|
|
||||||
if cparams.cp_cinema:
|
|
||||||
image.contents.comps[k].prec = 12
|
|
||||||
image.contents.comps[k].bpp = 12
|
|
||||||
else:
|
|
||||||
# 2.1 API
|
|
||||||
if cparams.rsiz in (core.OPJ_PROFILE_CINEMA_2K,
|
|
||||||
core.OPJ_PROFILE_CINEMA_4K):
|
|
||||||
image.contents.comps[k].prec = 12
|
|
||||||
image.contents.comps[k].bpp = 12
|
|
||||||
|
|
||||||
layer = np.ascontiguousarray(imgdata[:, :, k], dtype=np.int32)
|
|
||||||
dest = image.contents.comps[k].data
|
|
||||||
src = layer.ctypes.data
|
|
||||||
ctypes.memmove(dest, src, layer.nbytes)
|
|
||||||
|
|
||||||
return image
|
|
||||||
|
|
||||||
|
|
||||||
# Setup the default callback handlers. See the callback functions subsection
|
# 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
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue