pylint work, #99
This commit is contained in:
parent
658b61672c
commit
77a601b4de
1 changed files with 135 additions and 130 deletions
265
glymur/jp2k.py
265
glymur/jp2k.py
|
|
@ -582,72 +582,7 @@ class Jp2k(Jp2kBox):
|
||||||
num_components=num_components),
|
num_components=num_components),
|
||||||
ColourSpecificationBox(colorspace=SRGB)]
|
ColourSpecificationBox(colorspace=SRGB)]
|
||||||
|
|
||||||
# Check for a bad sequence of boxes.
|
_validate_jp2_box_sequence(boxes)
|
||||||
# 1st two boxes must be 'jP ' and '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 += "must be the file type box."
|
|
||||||
raise IOError(msg)
|
|
||||||
|
|
||||||
# jp2c must be preceeded by jp2h
|
|
||||||
jp2h_lst = [idx for (idx, box) in enumerate(boxes)
|
|
||||||
if box.box_id == 'jp2h']
|
|
||||||
jp2h_idx = jp2h_lst[0]
|
|
||||||
jp2c_lst = [idx for (idx, box) in enumerate(boxes)
|
|
||||||
if box.box_id == 'jp2c']
|
|
||||||
if len(jp2c_lst) == 0:
|
|
||||||
msg = "A codestream box must be defined in the outermost "
|
|
||||||
msg += "list of boxes."
|
|
||||||
raise IOError(msg)
|
|
||||||
|
|
||||||
jp2c_idx = jp2c_lst[0]
|
|
||||||
if jp2h_idx >= jp2c_idx:
|
|
||||||
msg = "The codestream box must be preceeded by a jp2 header box."
|
|
||||||
raise IOError(msg)
|
|
||||||
|
|
||||||
# 1st jp2 header box must be ihdr
|
|
||||||
jp2h = boxes[jp2h_idx]
|
|
||||||
if jp2h.box[0].box_id != 'ihdr':
|
|
||||||
msg = "The first box in the jp2 header box must be the image "
|
|
||||||
msg += "header box."
|
|
||||||
raise IOError(msg)
|
|
||||||
|
|
||||||
# colr must be present in jp2 header box.
|
|
||||||
colr_lst = [j for (j, box) in enumerate(jp2h.box)
|
|
||||||
if box.box_id == 'colr']
|
|
||||||
if len(colr_lst) == 0:
|
|
||||||
msg = "The jp2 header box must contain a color definition box."
|
|
||||||
raise IOError(msg)
|
|
||||||
colr = jp2h.box[colr_lst[0]]
|
|
||||||
|
|
||||||
# Any cdef box must be in the jp2 header following the image header.
|
|
||||||
cdef_lst = [j for (j, box) in enumerate(boxes) if box.box_id == 'cdef']
|
|
||||||
if len(cdef_lst) != 0:
|
|
||||||
msg = "Any channel defintion box must be in the JP2 header "
|
|
||||||
msg += "following the image header."
|
|
||||||
raise IOError(msg)
|
|
||||||
|
|
||||||
cdef_lst = [j for (j, box) in enumerate(jp2h.box)
|
|
||||||
if box.box_id == 'cdef']
|
|
||||||
if len(cdef_lst) > 1:
|
|
||||||
msg = "Only one channel definition box is allowed in the "
|
|
||||||
msg += "JP2 header."
|
|
||||||
raise IOError(msg)
|
|
||||||
elif len(cdef_lst) == 1:
|
|
||||||
cdef = jp2h.box[cdef_lst[0]]
|
|
||||||
assn = cdef.association
|
|
||||||
typ = cdef.channel_type
|
|
||||||
if colr.colorspace == SRGB:
|
|
||||||
if any([chan + 1 not in assn or typ[chan] != 0
|
|
||||||
for chan in [0, 1, 2]]):
|
|
||||||
msg = "All color channels must be defined in the "
|
|
||||||
msg += "channel definition box."
|
|
||||||
raise IOError(msg)
|
|
||||||
elif colr.colorspace == GREYSCALE:
|
|
||||||
if 0 not in typ:
|
|
||||||
msg = "All color channels must be defined in the "
|
|
||||||
msg += "channel definition box."
|
|
||||||
raise IOError(msg)
|
|
||||||
|
|
||||||
with open(filename, 'wb') as ofile:
|
with open(filename, 'wb') as ofile:
|
||||||
for box in boxes:
|
for box in boxes:
|
||||||
|
|
@ -740,6 +675,18 @@ class Jp2k(Jp2kBox):
|
||||||
"using this functionality.")
|
"using this functionality.")
|
||||||
return img
|
return img
|
||||||
|
|
||||||
|
def _subsampling_sanity_check(self):
|
||||||
|
"""Check for differing subsample factors.
|
||||||
|
"""
|
||||||
|
codestream = self.get_codestream(header_only=True)
|
||||||
|
dxs = np.array(codestream.segment[1].xrsiz)
|
||||||
|
dys = np.array(codestream.segment[1].yrsiz)
|
||||||
|
if np.any(dxs - dxs[0]) or np.any(dys - dys[0]):
|
||||||
|
msg = "Components must all have the same subsampling factors "
|
||||||
|
msg += "to use this method. Please consider using OPENJP2 and "
|
||||||
|
msg += "the read_bands method instead."
|
||||||
|
raise RuntimeError(msg)
|
||||||
|
|
||||||
def _read_openjpeg(self, rlevel=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.
|
||||||
|
|
||||||
|
|
@ -761,15 +708,7 @@ class Jp2k(Jp2kBox):
|
||||||
RuntimeError
|
RuntimeError
|
||||||
If the image has differing subsample factors.
|
If the image has differing subsample factors.
|
||||||
"""
|
"""
|
||||||
# Check for differing subsample factors.
|
self._subsampling_sanity_check()
|
||||||
codestream = self.get_codestream(header_only=True)
|
|
||||||
dxs = np.array(codestream.segment[1].xrsiz)
|
|
||||||
dys = np.array(codestream.segment[1].yrsiz)
|
|
||||||
if np.any(dxs - dxs[0]) or np.any(dys - dys[0]):
|
|
||||||
msg = "Components must all have the same subsampling factors "
|
|
||||||
msg += "to use this method with OpenJPEG 1.5.1. Please consider "
|
|
||||||
msg += "using OPENJP2 instead."
|
|
||||||
raise RuntimeError(msg)
|
|
||||||
|
|
||||||
with ExitStack() as stack:
|
with ExitStack() as stack:
|
||||||
# Set decoding parameters.
|
# Set decoding parameters.
|
||||||
|
|
@ -808,20 +747,7 @@ class Jp2k(Jp2kBox):
|
||||||
|
|
||||||
ncomps = image.contents.numcomps
|
ncomps = image.contents.numcomps
|
||||||
component = image.contents.comps[0]
|
component = image.contents.comps[0]
|
||||||
if component.sgnd:
|
dtype = component2dtype(component)
|
||||||
if component.prec <= 8:
|
|
||||||
dtype = np.int8
|
|
||||||
elif component.prec <= 16:
|
|
||||||
dtype = np.int16
|
|
||||||
else:
|
|
||||||
raise RuntimeError("Unhandled precision, datatype")
|
|
||||||
else:
|
|
||||||
if component.prec <= 8:
|
|
||||||
dtype = np.uint8
|
|
||||||
elif component.prec <= 16:
|
|
||||||
dtype = np.uint16
|
|
||||||
else:
|
|
||||||
raise RuntimeError("Unhandled precision, datatype")
|
|
||||||
|
|
||||||
nrows = image.contents.comps[0].h
|
nrows = image.contents.comps[0].h
|
||||||
ncols = image.contents.comps[0].w
|
ncols = image.contents.comps[0].w
|
||||||
|
|
@ -833,12 +759,7 @@ class Jp2k(Jp2kBox):
|
||||||
nrows = component.h
|
nrows = component.h
|
||||||
ncols = component.w
|
ncols = component.w
|
||||||
|
|
||||||
if nrows == 0 or ncols == 0:
|
_validate_nonzero_image_size(nrows, ncols, k)
|
||||||
# Letting this situation continue would segfault
|
|
||||||
# Python.
|
|
||||||
msg = "Component {0} has dimensions {1} x {2}"
|
|
||||||
msg = msg.format(k, nrows, ncols)
|
|
||||||
raise IOError(msg)
|
|
||||||
|
|
||||||
addr = ctypes.addressof(component.data.contents)
|
addr = ctypes.addressof(component.data.contents)
|
||||||
with warnings.catch_warnings():
|
with warnings.catch_warnings():
|
||||||
|
|
@ -884,13 +805,7 @@ class Jp2k(Jp2kBox):
|
||||||
RuntimeError
|
RuntimeError
|
||||||
If the image has differing subsample factors.
|
If the image has differing subsample factors.
|
||||||
"""
|
"""
|
||||||
# Check for differing subsample factors.
|
self._subsampling_sanity_check()
|
||||||
codestream = self.get_codestream(header_only=True)
|
|
||||||
dxs = np.array(codestream.segment[1].xrsiz)
|
|
||||||
dys = np.array(codestream.segment[1].yrsiz)
|
|
||||||
if np.any(dxs - dxs[0]) or np.any(dys - dys[0]):
|
|
||||||
msg = "Components must all have the same subsampling factors."
|
|
||||||
raise RuntimeError(msg)
|
|
||||||
|
|
||||||
img_array = self._read_common(rlevel=rlevel,
|
img_array = self._read_common(rlevel=rlevel,
|
||||||
layer=layer,
|
layer=layer,
|
||||||
|
|
@ -948,14 +863,10 @@ class Jp2k(Jp2kBox):
|
||||||
|
|
||||||
dparam.cp_reduce = rlevel
|
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 or area[2] <= 0 or area[3] <= 0:
|
||||||
msg = "Upper left corner coordinates must be nonnegative: {0}"
|
msg = "Upper left corner coordinates must be nonnegative and "
|
||||||
msg = msg.format(area)
|
msg += "lower right corner coordinates must be positive: {0}"
|
||||||
raise IOError(msg)
|
raise IOError(msg.format(area))
|
||||||
if area[2] <= 0 or area[3] <= 0:
|
|
||||||
msg = "Lower right corner coordinates must be positive: {0}"
|
|
||||||
msg = msg.format(area)
|
|
||||||
raise IOError(msg)
|
|
||||||
dparam.DA_y0 = area[0]
|
dparam.DA_y0 = area[0]
|
||||||
dparam.DA_x0 = area[1]
|
dparam.DA_x0 = area[1]
|
||||||
dparam.DA_y1 = area[2]
|
dparam.DA_y1 = area[2]
|
||||||
|
|
@ -1001,20 +912,7 @@ class Jp2k(Jp2kBox):
|
||||||
_opj2.end_decompress(codec, stream)
|
_opj2.end_decompress(codec, stream)
|
||||||
|
|
||||||
component = image.contents.comps[0]
|
component = image.contents.comps[0]
|
||||||
if component.sgnd:
|
dtype = component2dtype(component)
|
||||||
if component.prec <= 8:
|
|
||||||
dtype = np.int8
|
|
||||||
elif component.prec <= 16:
|
|
||||||
dtype = np.int16
|
|
||||||
else:
|
|
||||||
raise RuntimeError("Unhandled precision, datatype")
|
|
||||||
else:
|
|
||||||
if component.prec <= 8:
|
|
||||||
dtype = np.uint8
|
|
||||||
elif component.prec <= 16:
|
|
||||||
dtype = np.uint16
|
|
||||||
else:
|
|
||||||
raise RuntimeError("Unhandled precision, datatype")
|
|
||||||
|
|
||||||
if as_bands:
|
if as_bands:
|
||||||
data = []
|
data = []
|
||||||
|
|
@ -1029,12 +927,7 @@ class Jp2k(Jp2kBox):
|
||||||
nrows = component.h
|
nrows = component.h
|
||||||
ncols = component.w
|
ncols = component.w
|
||||||
|
|
||||||
if nrows == 0 or ncols == 0:
|
_validate_nonzero_image_size(nrows, ncols, k)
|
||||||
# Letting this situation continue would segfault
|
|
||||||
# Python.
|
|
||||||
msg = "Component {0} has dimensions {1} x {2}"
|
|
||||||
msg = msg.format(k, nrows, ncols)
|
|
||||||
raise IOError(msg)
|
|
||||||
|
|
||||||
addr = ctypes.addressof(component.data.contents)
|
addr = ctypes.addressof(component.data.contents)
|
||||||
with warnings.catch_warnings():
|
with warnings.catch_warnings():
|
||||||
|
|
@ -1165,3 +1058,115 @@ class Jp2k(Jp2kBox):
|
||||||
header_only=header_only)
|
header_only=header_only)
|
||||||
|
|
||||||
return codestream
|
return codestream
|
||||||
|
|
||||||
|
def component2dtype(component):
|
||||||
|
"""Take an OpenJPEG component structure and determine the numpy datatype.
|
||||||
|
|
||||||
|
Parameters
|
||||||
|
----------
|
||||||
|
component : ctypes pointer to ImageCompType (image_comp_t)
|
||||||
|
single image component structure.
|
||||||
|
|
||||||
|
Returns
|
||||||
|
-------
|
||||||
|
dtype : builtins.type
|
||||||
|
numpy datatype to be used to construct an image array.
|
||||||
|
"""
|
||||||
|
if component.sgnd:
|
||||||
|
if component.prec <= 8:
|
||||||
|
dtype = np.int8
|
||||||
|
elif component.prec <= 16:
|
||||||
|
dtype = np.int16
|
||||||
|
else:
|
||||||
|
raise RuntimeError("Unhandled precision, datatype")
|
||||||
|
else:
|
||||||
|
if component.prec <= 8:
|
||||||
|
dtype = np.uint8
|
||||||
|
elif component.prec <= 16:
|
||||||
|
dtype = np.uint16
|
||||||
|
else:
|
||||||
|
raise RuntimeError("Unhandled precision, datatype")
|
||||||
|
|
||||||
|
return dtype
|
||||||
|
|
||||||
|
|
||||||
|
def _validate_nonzero_image_size(nrows, ncols, component_index):
|
||||||
|
"""The image cannot have area of zero.
|
||||||
|
"""
|
||||||
|
if nrows == 0 or ncols == 0:
|
||||||
|
# Letting this situation continue would segfault Python.
|
||||||
|
msg = "Component {0} has dimensions {1} x {2}"
|
||||||
|
msg = msg.format(component_index, nrows, ncols)
|
||||||
|
raise IOError(msg)
|
||||||
|
|
||||||
|
def _validate_jp2_box_sequence(boxes):
|
||||||
|
"""Run through series of tests for JP2 box legality.
|
||||||
|
|
||||||
|
This is non-exhaustive.
|
||||||
|
"""
|
||||||
|
# Check for a bad sequence of boxes.
|
||||||
|
# 1st two boxes must be 'jP ' and '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 += "must be the file type box."
|
||||||
|
raise IOError(msg)
|
||||||
|
|
||||||
|
# jp2c must be preceeded by jp2h
|
||||||
|
jp2h_lst = [idx for (idx, box) in enumerate(boxes)
|
||||||
|
if box.box_id == 'jp2h']
|
||||||
|
jp2h_idx = jp2h_lst[0]
|
||||||
|
jp2c_lst = [idx for (idx, box) in enumerate(boxes)
|
||||||
|
if box.box_id == 'jp2c']
|
||||||
|
if len(jp2c_lst) == 0:
|
||||||
|
msg = "A codestream box must be defined in the outermost "
|
||||||
|
msg += "list of boxes."
|
||||||
|
raise IOError(msg)
|
||||||
|
|
||||||
|
jp2c_idx = jp2c_lst[0]
|
||||||
|
if jp2h_idx >= jp2c_idx:
|
||||||
|
msg = "The codestream box must be preceeded by a jp2 header box."
|
||||||
|
raise IOError(msg)
|
||||||
|
|
||||||
|
# 1st jp2 header box must be ihdr
|
||||||
|
jp2h = boxes[jp2h_idx]
|
||||||
|
if jp2h.box[0].box_id != 'ihdr':
|
||||||
|
msg = "The first box in the jp2 header box must be the image "
|
||||||
|
msg += "header box."
|
||||||
|
raise IOError(msg)
|
||||||
|
|
||||||
|
# colr must be present in jp2 header box.
|
||||||
|
colr_lst = [j for (j, box) in enumerate(jp2h.box)
|
||||||
|
if box.box_id == 'colr']
|
||||||
|
if len(colr_lst) == 0:
|
||||||
|
msg = "The jp2 header box must contain a color definition box."
|
||||||
|
raise IOError(msg)
|
||||||
|
colr = jp2h.box[colr_lst[0]]
|
||||||
|
|
||||||
|
# Any cdef box must be in the jp2 header following the image header.
|
||||||
|
cdef_lst = [j for (j, box) in enumerate(boxes) if box.box_id == 'cdef']
|
||||||
|
if len(cdef_lst) != 0:
|
||||||
|
msg = "Any channel defintion box must be in the JP2 header "
|
||||||
|
msg += "following the image header."
|
||||||
|
raise IOError(msg)
|
||||||
|
|
||||||
|
cdef_lst = [j for (j, box) in enumerate(jp2h.box)
|
||||||
|
if box.box_id == 'cdef']
|
||||||
|
if len(cdef_lst) > 1:
|
||||||
|
msg = "Only one channel definition box is allowed in the "
|
||||||
|
msg += "JP2 header."
|
||||||
|
raise IOError(msg)
|
||||||
|
elif len(cdef_lst) == 1:
|
||||||
|
cdef = jp2h.box[cdef_lst[0]]
|
||||||
|
if colr.colorspace == SRGB:
|
||||||
|
if any([chan + 1 not in cdef.association
|
||||||
|
or cdef.channel_type[chan] != 0
|
||||||
|
for chan in [0, 1, 2]]):
|
||||||
|
msg = "All color channels must be defined in the "
|
||||||
|
msg += "channel definition box."
|
||||||
|
raise IOError(msg)
|
||||||
|
elif colr.colorspace == GREYSCALE:
|
||||||
|
if 0 not in cdef.channel_type:
|
||||||
|
msg = "All color channels must be defined in the "
|
||||||
|
msg += "channel definition box."
|
||||||
|
raise IOError(msg)
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue