pylint work, #99

This commit is contained in:
jevans 2013-08-10 16:42:08 -04:00
commit 63168e6b3a
2 changed files with 151 additions and 138 deletions

View file

@ -3,7 +3,9 @@
License: MIT License: MIT
""" """
# pylint: disable=C0302 # W0201: Since we are using ctypes Structures, we often have to access
# attributes that are not defined in __init__ but in _fields_ instead.
# pylint: disable=W0201
import sys import sys
if sys.hexversion >= 0x03030000: if sys.hexversion >= 0x03030000:
@ -32,7 +34,7 @@ from .jp2box import ImageHeaderBox
from .jp2box import ColourSpecificationBox from .jp2box import ColourSpecificationBox
from .lib import openjpeg as opj from .lib import openjpeg as opj
from .lib import openjp2 as opj2 from .lib import openjp2 as opj2
from .lib import c as _libc from .lib import c as libc
# Need to known if openjp2 library is the officially release v2.0.0 or not. # Need to known if openjp2 library is the officially release v2.0.0 or not.
_OPENJP2_IS_OFFICIAL_V2 = False _OPENJP2_IS_OFFICIAL_V2 = False
@ -233,7 +235,6 @@ class Jp2k(Jp2kBox):
cparams : CompressionParametersType(ctypes.Structure) cparams : CompressionParametersType(ctypes.Structure)
Corresponds to cparameters_t type in openjp2 headers. Corresponds to cparameters_t type in openjp2 headers.
""" """
cparams = opj2.set_default_encoder_parameters() cparams = opj2.set_default_encoder_parameters()
outfile = self.filename.encode() outfile = self.filename.encode()
@ -308,70 +309,6 @@ class Jp2k(Jp2kBox):
return cparams return cparams
def _validate_compression_params(self, img_array, cparams):
"""Check that the compression parameters are valid.
Parameters
----------
img_array : ndarray
Image data to be written to file.
cparams : CompressionParametersType(ctypes.Structure)
Corresponds to cparameters_t type in openjp2 headers.
"""
# Code block size
code_block_specified = False
if cparams.cblockw_init != 0 and cparams.cblockh_init != 0:
# These fields ARE zero if uninitialized.
width = cparams.cblockw_init
height = cparams.cblockh_init
code_block_specified = True
if height * width > 4096 or height < 4 or width < 4:
msg = "Code block area cannot exceed 4096. "
msg += "Code block height and width must be larger than 4."
raise IOError(msg)
if ((math.log(height, 2) != math.floor(math.log(height, 2)) or
math.log(width, 2) != math.floor(math.log(width, 2)))):
msg = "Bad code block size ({0}, {1}), "
msg += "must be powers of 2."
raise IOError(msg.format(height, width))
# Precinct size
if cparams.res_spec != 0:
# precinct size was not specified if this field is zero.
for j in range(cparams.res_spec):
prch = cparams.prch_init[j]
prcw = cparams.prcw_init[j]
if j == 0 and code_block_specified:
height, width = cparams.cblockh_init, cparams.cblockw_init
if height * 2 > prch or width * 2 > prcw:
msg = "Highest Resolution precinct size must be at "
msg += "least twice that of the code block dimensions."
raise IOError(msg)
if ((math.log(prch, 2) != math.floor(math.log(prch, 2)) or
math.log(prcw, 2) != math.floor(math.log(prcw, 2)))):
msg = "Bad precinct sizes ({0}, {1}), "
msg += "must be powers of 2."
raise IOError(msg.format(prch, prcw))
# What would the point of 1D images be?
if img_array.ndim == 1 or img_array.ndim > 3:
msg = "{0}D imagery is not allowed.".format(img_array.ndim)
raise IOError(msg)
if _OPENJP2_IS_OFFICIAL_V2:
if (((img_array.ndim != 2) and
(img_array.shape[2] != 1 and img_array.shape[2] != 3))):
msg = "Writing images is restricted to single-channel "
msg += "greyscale images or three-channel RGB images when "
msg += "the OpenJPEG library version is the official 2.0.0 "
msg += "release."
raise IOError(msg)
if img_array.dtype != np.uint8 and img_array.dtype != np.uint16:
msg = "Only uint8 and uint16 images are currently supported."
raise RuntimeError(msg)
def _process_write_inputs(self, img_array, colorspace=None, **kwargs): def _process_write_inputs(self, img_array, colorspace=None, **kwargs):
"""Directs processing of write method arguments. """Directs processing of write method arguments.
@ -403,7 +340,7 @@ class Jp2k(Jp2kBox):
raise IOError(msg) raise IOError(msg)
cparams = self._populate_cparams(**kwargs) cparams = self._populate_cparams(**kwargs)
self._validate_compression_params(img_array, cparams) _validate_compression_params(img_array, cparams)
colorspace = _unpack_colorspace(colorspace, img_array, cparams) colorspace = _unpack_colorspace(colorspace, img_array, cparams)
@ -426,38 +363,6 @@ class Jp2k(Jp2kBox):
return cparams, colorspace return cparams, colorspace
def _populate_image_struct(self, 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):
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 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
various parameters follows that of OpenJPEG's opj_compress utility. various parameters follows that of OpenJPEG's opj_compress utility.
@ -537,24 +442,10 @@ 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)
# Only two precisions are possible. comptparms = _populate_comptparms(img_array, cparams)
comp_prec = 8 if img_array.dtype == np.uint8 else 16
numrows, numcols, num_comps = img_array.shape
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
image = opj2.image_create(comptparms, colorspace) image = opj2.image_create(comptparms, colorspace)
self._populate_image_struct(cparams, image, img_array) _populate_image_struct(cparams, image, img_array)
codec = opj2.create_compress(cparams.codec_fmt) codec = opj2.create_compress(cparams.codec_fmt)
@ -566,7 +457,7 @@ class Jp2k(Jp2kBox):
opj2.setup_encoder(codec, cparams, image) opj2.setup_encoder(codec, cparams, image)
if _OPENJP2_IS_OFFICIAL_V2: if _OPENJP2_IS_OFFICIAL_V2:
fptr = _libc.fopen(self.filename, 'wb') fptr = libc.fopen(self.filename, 'wb')
strm = opj2.stream_create_default_file_stream(fptr, False) strm = opj2.stream_create_default_file_stream(fptr, False)
else: else:
# This routine introduced in 2.0 devel series. # This routine introduced in 2.0 devel series.
@ -580,7 +471,7 @@ class Jp2k(Jp2kBox):
if _OPENJP2_IS_OFFICIAL_V2: if _OPENJP2_IS_OFFICIAL_V2:
opj2.stream_destroy(strm) opj2.stream_destroy(strm)
_libc.fclose(fptr) libc.fclose(fptr)
else: else:
# This routine introduced in 2.0 devel series. # This routine introduced in 2.0 devel series.
opj2.stream_destroy_v3(strm) opj2.stream_destroy_v3(strm)
@ -804,8 +695,7 @@ class Jp2k(Jp2kBox):
return data return data
def _read_openjp2(self, rlevel=0, layer=0, area=None, tile=None, def _read_openjp2(self, **kwargs):
verbose=False):
"""Read a JPEG 2000 image using libopenjp2. """Read a JPEG 2000 image using libopenjp2.
Parameters Parameters
@ -835,12 +725,7 @@ class Jp2k(Jp2kBox):
""" """
self._subsampling_sanity_check() self._subsampling_sanity_check()
img_array = self._read_common(rlevel=rlevel, img_array = self._read_common(as_bands=False, **kwargs)
layer=layer,
area=area,
tile=tile,
verbose=verbose,
as_bands=False)
if img_array.shape[2] == 1: if img_array.shape[2] == 1:
img_array = img_array.view() img_array = img_array.view()
@ -936,8 +821,8 @@ class Jp2k(Jp2kBox):
True) True)
stack.callback(opj2.stream_destroy_v3, stream) stack.callback(opj2.stream_destroy_v3, stream)
else: else:
fptr = _libc.fopen(self.filename, 'rb') fptr = libc.fopen(self.filename, 'rb')
stack.callback(_libc.fclose, fptr) stack.callback(libc.fclose, fptr)
stream = opj2.stream_create_default_file_stream(fptr, True) stream = opj2.stream_create_default_file_stream(fptr, True)
stack.callback(opj2.stream_destroy, stream) stack.callback(opj2.stream_destroy, stream)
codec = opj2.create_decompress(self._codec_format) codec = opj2.create_decompress(self._codec_format)
@ -970,8 +855,7 @@ class Jp2k(Jp2kBox):
return data return data
def read_bands(self, rlevel=0, layer=0, area=None, tile=None, def read_bands(self, **kwargs):
verbose=False):
"""Read a JPEG 2000 image. """Read a JPEG 2000 image.
The only time you should use this method is when the image has The only time you should use this method is when the image has
@ -1018,13 +902,7 @@ class Jp2k(Jp2kBox):
"of OpenJP2 installed before using " "of OpenJP2 installed before using "
"this functionality.") "this functionality.")
lst = self._read_common(rlevel=rlevel, lst = self._read_common(as_bands=True, **kwargs)
layer=layer,
area=area,
tile=tile,
verbose=verbose,
as_bands=True)
return lst return lst
def get_codestream(self, header_only=True): def get_codestream(self, header_only=True):
@ -1298,3 +1176,138 @@ def _unpack_colorspace(colorspace, img_array, cparams):
colorspace = _COLORSPACE_MAP[colorspace.lower()] colorspace = _COLORSPACE_MAP[colorspace.lower()]
return colorspace return colorspace
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
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):
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 _validate_compression_params(img_array, cparams):
"""Check that the compression parameters are valid.
Parameters
----------
img_array : ndarray
Image data to be written to file.
cparams : CompressionParametersType(ctypes.Structure)
Corresponds to cparameters_t type in openjp2 headers.
"""
# Code block size
code_block_specified = False
if cparams.cblockw_init != 0 and cparams.cblockh_init != 0:
# These fields ARE zero if uninitialized.
width = cparams.cblockw_init
height = cparams.cblockh_init
code_block_specified = True
if height * width > 4096 or height < 4 or width < 4:
msg = "Code block area cannot exceed 4096. "
msg += "Code block height and width must be larger than 4."
raise IOError(msg)
if ((math.log(height, 2) != math.floor(math.log(height, 2)) or
math.log(width, 2) != math.floor(math.log(width, 2)))):
msg = "Bad code block size ({0}, {1}), "
msg += "must be powers of 2."
raise IOError(msg.format(height, width))
# Precinct size
if cparams.res_spec != 0:
# precinct size was not specified if this field is zero.
for j in range(cparams.res_spec):
prch = cparams.prch_init[j]
prcw = cparams.prcw_init[j]
if j == 0 and code_block_specified:
height, width = cparams.cblockh_init, cparams.cblockw_init
if height * 2 > prch or width * 2 > prcw:
msg = "Highest Resolution precinct size must be at "
msg += "least twice that of the code block dimensions."
raise IOError(msg)
if ((math.log(prch, 2) != math.floor(math.log(prch, 2)) or
math.log(prcw, 2) != math.floor(math.log(prcw, 2)))):
msg = "Bad precinct sizes ({0}, {1}), "
msg += "must be powers of 2."
raise IOError(msg.format(prch, prcw))
# What would the point of 1D images be?
if img_array.ndim == 1 or img_array.ndim > 3:
msg = "{0}D imagery is not allowed.".format(img_array.ndim)
raise IOError(msg)
if _OPENJP2_IS_OFFICIAL_V2:
if (((img_array.ndim != 2) and
(img_array.shape[2] != 1 and img_array.shape[2] != 3))):
msg = "Writing images is restricted to single-channel "
msg += "greyscale images or three-channel RGB images when "
msg += "the OpenJPEG library version is the official 2.0.0 "
msg += "release."
raise IOError(msg)
if img_array.dtype != np.uint8 and img_array.dtype != np.uint16:
msg = "Only uint8 and uint16 images are currently supported."
raise RuntimeError(msg)

View file

@ -2,7 +2,7 @@
Wraps individual functions in openjp2 library. Wraps individual functions in openjp2 library.
""" """
# pylint: disable=C0302,R0903 # pylint: disable=C0302,R0903,W0201
import ctypes import ctypes
import sys import sys