Merge branch 'issue130' into devel
This commit is contained in:
commit
0c8b11b722
3 changed files with 99 additions and 110 deletions
|
|
@ -380,13 +380,13 @@ class Codestream(object):
|
||||||
COD segment instance.
|
COD segment instance.
|
||||||
"""
|
"""
|
||||||
offset = fptr.tell() - 2
|
offset = fptr.tell() - 2
|
||||||
offset = fptr.tell() - 2
|
|
||||||
|
|
||||||
read_buffer = fptr.read(3)
|
read_buffer = fptr.read(2)
|
||||||
length, scod = struct.unpack('>HB', read_buffer)
|
length, = struct.unpack('>H', read_buffer)
|
||||||
|
|
||||||
numbytes = offset + 2 + length - fptr.tell()
|
read_buffer = fptr.read(length - 2)
|
||||||
spcod = fptr.read(numbytes)
|
scod, = struct.unpack_from('>B', read_buffer, offset=0)
|
||||||
|
spcod = read_buffer[1:]
|
||||||
spcod = np.frombuffer(spcod, dtype=np.uint8)
|
spcod = np.frombuffer(spcod, dtype=np.uint8)
|
||||||
if spcod[0] not in [LRCP, RLCP, RPCL, PCRL, CPRL]:
|
if spcod[0] not in [LRCP, RLCP, RPCL, PCRL, CPRL]:
|
||||||
msg = "Invalid progression order in COD segment: {0}."
|
msg = "Invalid progression order in COD segment: {0}."
|
||||||
|
|
@ -583,22 +583,21 @@ class Codestream(object):
|
||||||
read_buffer = fptr.read(2)
|
read_buffer = fptr.read(2)
|
||||||
length, = struct.unpack('>H', read_buffer)
|
length, = struct.unpack('>H', read_buffer)
|
||||||
|
|
||||||
|
read_buffer = fptr.read(length - 2)
|
||||||
if self._csiz > 256:
|
if self._csiz > 256:
|
||||||
read_buffer = fptr.read(3)
|
|
||||||
fmt = '>HB'
|
fmt = '>HB'
|
||||||
mantissa_exponent_buffer_length = length - 5
|
mantissa_exponent_offset = 3
|
||||||
else:
|
else:
|
||||||
read_buffer = fptr.read(2)
|
|
||||||
fmt = '>BB'
|
fmt = '>BB'
|
||||||
mantissa_exponent_buffer_length = length - 4
|
mantissa_exponent_offset = 2
|
||||||
cqcc, sqcc = struct.unpack(fmt, read_buffer)
|
cqcc, sqcc = struct.unpack_from(fmt, read_buffer)
|
||||||
if cqcc >= self._csiz:
|
if cqcc >= self._csiz:
|
||||||
msg = "Invalid component number ({0}), "
|
msg = "Invalid component number ({0}), "
|
||||||
msg += "number of components is only {1}."
|
msg += "number of components is only {1}."
|
||||||
msg = msg.format(cqcc, self._csiz)
|
msg = msg.format(cqcc, self._csiz)
|
||||||
warnings.warn(msg)
|
warnings.warn(msg)
|
||||||
|
|
||||||
spqcc = fptr.read(mantissa_exponent_buffer_length)
|
spqcc = read_buffer[mantissa_exponent_offset:]
|
||||||
|
|
||||||
return QCCsegment(cqcc, sqcc, spqcc, length, offset)
|
return QCCsegment(cqcc, sqcc, spqcc, length, offset)
|
||||||
|
|
||||||
|
|
@ -670,8 +669,8 @@ class Codestream(object):
|
||||||
read_buffer = fptr.read(2)
|
read_buffer = fptr.read(2)
|
||||||
length, = struct.unpack('>H', read_buffer)
|
length, = struct.unpack('>H', read_buffer)
|
||||||
|
|
||||||
xy_buffer = fptr.read(36)
|
read_buffer = fptr.read(length - 2)
|
||||||
data = struct.unpack('>HIIIIIIIIH', xy_buffer)
|
data = struct.unpack_from('>HIIIIIIIIH', read_buffer)
|
||||||
|
|
||||||
rsiz = data[0]
|
rsiz = data[0]
|
||||||
if rsiz not in _KNOWN_PROFILES:
|
if rsiz not in _KNOWN_PROFILES:
|
||||||
|
|
@ -685,9 +684,8 @@ class Codestream(object):
|
||||||
# Csiz is the number of components
|
# Csiz is the number of components
|
||||||
Csiz = data[9]
|
Csiz = data[9]
|
||||||
|
|
||||||
component_buffer = fptr.read(Csiz * 3)
|
data = struct.unpack_from('>' + 'B' * (length - 36 - 2),
|
||||||
data = struct.unpack('>' + 'B' * len(component_buffer),
|
read_buffer, offset=36)
|
||||||
component_buffer)
|
|
||||||
|
|
||||||
bitdepth = tuple(((x & 0x7f) + 1) for x in data[0::3])
|
bitdepth = tuple(((x & 0x7f) + 1) for x in data[0::3])
|
||||||
signed = tuple(((x & 0x80) > 0) for x in data[0::3])
|
signed = tuple(((x & 0x80) > 0) for x in data[0::3])
|
||||||
|
|
@ -804,8 +802,8 @@ class Codestream(object):
|
||||||
read_buffer = fptr.read(2)
|
read_buffer = fptr.read(2)
|
||||||
length, = struct.unpack('>H', read_buffer)
|
length, = struct.unpack('>H', read_buffer)
|
||||||
|
|
||||||
read_buffer = fptr.read(2)
|
read_buffer = fptr.read(length - 2)
|
||||||
ztlm, stlm = struct.unpack('>BB', read_buffer)
|
ztlm, stlm = struct.unpack_from('>BB', read_buffer)
|
||||||
ttlm_st = (stlm >> 4) & 0x3
|
ttlm_st = (stlm >> 4) & 0x3
|
||||||
ptlm_sp = (stlm >> 6) & 0x1
|
ptlm_sp = (stlm >> 6) & 0x1
|
||||||
|
|
||||||
|
|
@ -815,7 +813,6 @@ class Codestream(object):
|
||||||
else:
|
else:
|
||||||
ntiles = nbytes / (ttlm_st + (ptlm_sp + 1) * 2)
|
ntiles = nbytes / (ttlm_st + (ptlm_sp + 1) * 2)
|
||||||
|
|
||||||
read_buffer = fptr.read(nbytes)
|
|
||||||
if ttlm_st == 0:
|
if ttlm_st == 0:
|
||||||
ttlm = None
|
ttlm = None
|
||||||
fmt = ''
|
fmt = ''
|
||||||
|
|
@ -829,7 +826,8 @@ class Codestream(object):
|
||||||
else:
|
else:
|
||||||
fmt += 'I'
|
fmt += 'I'
|
||||||
|
|
||||||
data = struct.unpack('>' + fmt * int(ntiles), read_buffer)
|
data = struct.unpack_from('>' + fmt * int(ntiles), read_buffer,
|
||||||
|
offset=2)
|
||||||
if ttlm_st == 0:
|
if ttlm_st == 0:
|
||||||
ttlm = None
|
ttlm = None
|
||||||
ptlm = data
|
ptlm = data
|
||||||
|
|
|
||||||
106
glymur/jp2box.py
106
glymur/jp2box.py
|
|
@ -43,7 +43,7 @@ _METHOD_DISPLAY = {
|
||||||
ANY_ICC_PROFILE: 'any ICC profile',
|
ANY_ICC_PROFILE: 'any ICC profile',
|
||||||
VENDOR_COLOR_METHOD: 'vendor color method'}
|
VENDOR_COLOR_METHOD: 'vendor color method'}
|
||||||
|
|
||||||
_factory = lambda x: '{0} (invalid)'.format(x)
|
_factory = lambda x: '{0} (invalid)'.format(x)
|
||||||
_APPROX_DISPLAY = _Keydefaultdict(_factory,
|
_APPROX_DISPLAY = _Keydefaultdict(_factory,
|
||||||
{1: 'accurately represents correct colorspace definition',
|
{1: 'accurately represents correct colorspace definition',
|
||||||
2: 'approximates correct colorspace definition, exceptional quality',
|
2: 'approximates correct colorspace definition, exceptional quality',
|
||||||
|
|
@ -125,7 +125,7 @@ class Jp2kBox(object):
|
||||||
String to be indented.
|
String to be indented.
|
||||||
indent_level : str
|
indent_level : str
|
||||||
Number of spaces of indentation to add.
|
Number of spaces of indentation to add.
|
||||||
|
|
||||||
Returns
|
Returns
|
||||||
-------
|
-------
|
||||||
indented_string : str
|
indented_string : str
|
||||||
|
|
@ -407,15 +407,16 @@ class ColourSpecificationBox(Jp2kBox):
|
||||||
-------
|
-------
|
||||||
ColourSpecificationBox instance
|
ColourSpecificationBox instance
|
||||||
"""
|
"""
|
||||||
|
num_bytes = offset + length - fptr.tell()
|
||||||
|
read_buffer = fptr.read(num_bytes)
|
||||||
# Read the brand, minor version.
|
# Read the brand, minor version.
|
||||||
read_buffer = fptr.read(3)
|
(method, precedence, approximation) = struct.unpack_from('>BBB',
|
||||||
(method, precedence, approximation) = struct.unpack('>BBB',
|
read_buffer,
|
||||||
read_buffer)
|
offset=0)
|
||||||
|
|
||||||
if method == 1:
|
if method == 1:
|
||||||
# enumerated colour space
|
# enumerated colour space
|
||||||
read_buffer = fptr.read(4)
|
colorspace, = struct.unpack_from('>I', read_buffer, offset=3)
|
||||||
colorspace, = struct.unpack('>I', read_buffer)
|
|
||||||
if colorspace not in _COLORSPACE_MAP_DISPLAY.keys():
|
if colorspace not in _COLORSPACE_MAP_DISPLAY.keys():
|
||||||
msg = "Unrecognized colorspace: {0}".format(colorspace)
|
msg = "Unrecognized colorspace: {0}".format(colorspace)
|
||||||
warnings.warn(msg)
|
warnings.warn(msg)
|
||||||
|
|
@ -424,14 +425,13 @@ class ColourSpecificationBox(Jp2kBox):
|
||||||
else:
|
else:
|
||||||
# ICC profile
|
# ICC profile
|
||||||
colorspace = None
|
colorspace = None
|
||||||
numbytes = offset + length - fptr.tell()
|
if (num_bytes - 3) < 128:
|
||||||
if numbytes < 128:
|
|
||||||
msg = "ICC profile header is corrupt, length is "
|
msg = "ICC profile header is corrupt, length is "
|
||||||
msg += "only {0} instead of 128."
|
msg += "only {0} instead of 128."
|
||||||
warnings.warn(msg.format(numbytes), UserWarning)
|
warnings.warn(msg.format(num_bytes - 3), UserWarning)
|
||||||
icc_profile = None
|
icc_profile = None
|
||||||
else:
|
else:
|
||||||
profile = _ICCProfile(fptr.read(numbytes))
|
profile = _ICCProfile(read_buffer[3:])
|
||||||
icc_profile = profile.header
|
icc_profile = profile.header
|
||||||
|
|
||||||
return cls(method=method,
|
return cls(method=method,
|
||||||
|
|
@ -659,12 +659,14 @@ class ChannelDefinitionBox(Jp2kBox):
|
||||||
-------
|
-------
|
||||||
ComponentDefinitionBox instance
|
ComponentDefinitionBox instance
|
||||||
"""
|
"""
|
||||||
# Read the number of components.
|
num_bytes = offset + length - fptr.tell()
|
||||||
read_buffer = fptr.read(2)
|
read_buffer = fptr.read(num_bytes)
|
||||||
num_components, = struct.unpack('>H', read_buffer)
|
|
||||||
|
|
||||||
read_buffer = fptr.read(num_components * 6)
|
# Read the number of components.
|
||||||
data = struct.unpack('>' + 'HHH' * num_components, read_buffer)
|
num_components, = struct.unpack_from('>H', read_buffer)
|
||||||
|
|
||||||
|
data = struct.unpack_from('>' + 'HHH' * num_components, read_buffer,
|
||||||
|
offset=2)
|
||||||
index = data[0:num_components * 6:3]
|
index = data[0:num_components * 6:3]
|
||||||
channel_type = data[1:num_components * 6:3]
|
channel_type = data[1:num_components * 6:3]
|
||||||
association = data[2:num_components * 6:3]
|
association = data[2:num_components * 6:3]
|
||||||
|
|
@ -1103,7 +1105,7 @@ class DataReferenceBox(Jp2kBox):
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def parse(cls, fptr, offset, length):
|
def parse(cls, fptr, offset, length):
|
||||||
"""Parse Label box.
|
"""Parse data reference box.
|
||||||
|
|
||||||
Parameters
|
Parameters
|
||||||
----------
|
----------
|
||||||
|
|
@ -1234,19 +1236,17 @@ class FileTypeBox(Jp2kBox):
|
||||||
-------
|
-------
|
||||||
FileTypeBox instance
|
FileTypeBox instance
|
||||||
"""
|
"""
|
||||||
# Read the brand, minor version.
|
read_buffer = fptr.read(length - 8)
|
||||||
read_buffer = fptr.read(8)
|
# Extract the brand, minor version.
|
||||||
(brand, minor_version) = struct.unpack('>4sI', read_buffer)
|
(brand, minor_version) = struct.unpack_from('>4sI', read_buffer, 0)
|
||||||
if sys.hexversion >= 0x030000:
|
if sys.hexversion >= 0x030000:
|
||||||
brand = brand.decode('utf-8')
|
brand = brand.decode('utf-8')
|
||||||
|
|
||||||
# Read the compatibility list. Each entry has 4 bytes.
|
# Extract the compatibility list. Each entry has 4 bytes.
|
||||||
current_pos = fptr.tell()
|
num_entries = int((length - 16)/ 4)
|
||||||
num_bytes = (offset + length - current_pos) / 4
|
|
||||||
read_buffer = fptr.read(int(num_bytes) * 4)
|
|
||||||
compatibility_list = []
|
compatibility_list = []
|
||||||
for j in range(int(num_bytes)):
|
for j in range(int(num_entries)):
|
||||||
entry, = struct.unpack('>4s', read_buffer[4*j:4*(j+1)])
|
entry, = struct.unpack_from('>4s', read_buffer, 8 + j * 4)
|
||||||
if sys.hexversion >= 0x03000000:
|
if sys.hexversion >= 0x03000000:
|
||||||
entry = entry.decode('utf-8')
|
entry = entry.decode('utf-8')
|
||||||
compatibility_list.append(entry)
|
compatibility_list.append(entry)
|
||||||
|
|
@ -1348,11 +1348,13 @@ class FragmentListBox(Jp2kBox):
|
||||||
-------
|
-------
|
||||||
FragmentListBox instance
|
FragmentListBox instance
|
||||||
"""
|
"""
|
||||||
read_buffer = fptr.read(2)
|
num_bytes = offset + length - fptr.tell()
|
||||||
num_fragments, = struct.unpack('>H', read_buffer)
|
read_buffer = fptr.read(num_bytes)
|
||||||
|
num_fragments, = struct.unpack_from('>H', read_buffer, offset=0)
|
||||||
|
|
||||||
read_buffer = fptr.read(num_fragments * 14)
|
lst = struct.unpack_from('>' + 'QIH' * num_fragments,
|
||||||
lst = struct.unpack('>' + 'QIH' * num_fragments, read_buffer)
|
read_buffer,
|
||||||
|
offset=2)
|
||||||
frag_offset = lst[0::3]
|
frag_offset = lst[0::3]
|
||||||
frag_len = lst[1::3]
|
frag_len = lst[1::3]
|
||||||
data_reference = lst[2::3]
|
data_reference = lst[2::3]
|
||||||
|
|
@ -1885,11 +1887,11 @@ class PaletteBox(Jp2kBox):
|
||||||
if all(b == bps[0] for b in bps):
|
if all(b == bps[0] for b in bps):
|
||||||
# All components are the same. Writing is straightforward.
|
# All components are the same. Writing is straightforward.
|
||||||
if self.bits_per_component[0] <= 8:
|
if self.bits_per_component[0] <= 8:
|
||||||
write_buffer = np.getbuffer(self.palette.astype(np.uint8))
|
write_buffer = memoryview(self.palette.astype(np.uint8))
|
||||||
elif self.bits_per_component[0] <= 16:
|
elif self.bits_per_component[0] <= 16:
|
||||||
write_buffer = np.getbuffer(self.palette.astype(np.uint16))
|
write_buffer = memoryview(self.palette.astype(np.uint16))
|
||||||
elif self.bits_per_component[0] <= 32:
|
elif self.bits_per_component[0] <= 32:
|
||||||
write_buffer = np.getbuffer(self.palette.astype(np.uint32))
|
write_buffer = memoryview(self.palette.astype(np.uint32))
|
||||||
fptr.write(write_buffer)
|
fptr.write(write_buffer)
|
||||||
else:
|
else:
|
||||||
# Not all the components are the same. More general, but much rarer
|
# Not all the components are the same. More general, but much rarer
|
||||||
|
|
@ -1920,13 +1922,11 @@ class PaletteBox(Jp2kBox):
|
||||||
-------
|
-------
|
||||||
PaletteBox instance
|
PaletteBox instance
|
||||||
"""
|
"""
|
||||||
# Get the size of the palette.
|
|
||||||
read_buffer = fptr.read(3)
|
read_buffer = fptr.read(3)
|
||||||
(num_entries, num_columns) = struct.unpack('>HB', read_buffer)
|
(nrows, ncols) = struct.unpack('>HB', read_buffer)
|
||||||
|
|
||||||
# Need to determine bps and signed or not
|
read_buffer = fptr.read(ncols)
|
||||||
read_buffer = fptr.read(num_columns)
|
bps_signed = struct.unpack('>' + 'B' * ncols, read_buffer)
|
||||||
bps_signed = struct.unpack('>' + 'B' * num_columns, read_buffer)
|
|
||||||
bps = [((x & 0x7f) + 1) for x in bps_signed]
|
bps = [((x & 0x7f) + 1) for x in bps_signed]
|
||||||
signed = [((x & 0x80) > 1) for x in bps_signed]
|
signed = [((x & 0x80) > 1) for x in bps_signed]
|
||||||
|
|
||||||
|
|
@ -1934,18 +1934,18 @@ class PaletteBox(Jp2kBox):
|
||||||
# Ok the palette has the same datatype for all columns. We should
|
# Ok the palette has the same datatype for all columns. We should
|
||||||
# be able to efficiently read it.
|
# be able to efficiently read it.
|
||||||
if bps[0] <= 8:
|
if bps[0] <= 8:
|
||||||
nbytes_per_row = num_columns
|
nbytes_per_row = ncols
|
||||||
dtype = np.uint8
|
dtype = np.uint8
|
||||||
elif bps[0] <= 16:
|
elif bps[0] <= 16:
|
||||||
nbytes_per_row = 2 * num_columns
|
nbytes_per_row = 2 * ncols
|
||||||
dtype = np.uint16
|
dtype = np.uint16
|
||||||
elif bps[0] <= 32:
|
elif bps[0] <= 32:
|
||||||
nbytes_per_row = 3 * num_columns
|
nbytes_per_row = 3 * ncols
|
||||||
dtype = np.uint32
|
dtype = np.uint32
|
||||||
|
|
||||||
read_buffer = fptr.read(num_entries * nbytes_per_row)
|
read_buffer = fptr.read(nrows * nbytes_per_row)
|
||||||
palette = np.frombuffer(read_buffer, dtype=dtype)
|
palette = np.frombuffer(read_buffer, dtype=dtype)
|
||||||
palette = np.reshape(palette, (num_entries, num_columns))
|
palette = np.reshape(palette, (nrows, ncols))
|
||||||
|
|
||||||
else:
|
else:
|
||||||
# General case where the columns may not be the same width.
|
# General case where the columns may not be the same width.
|
||||||
|
|
@ -1962,9 +1962,9 @@ class PaletteBox(Jp2kBox):
|
||||||
# That means a list comprehension does this in one shot.
|
# That means a list comprehension does this in one shot.
|
||||||
row_nbytes = sum([int(math.ceil(x/8.0)) for x in bps])
|
row_nbytes = sum([int(math.ceil(x/8.0)) for x in bps])
|
||||||
|
|
||||||
read_buffer = fptr.read(num_entries * row_nbytes)
|
read_buffer = fptr.read(nrows * row_nbytes)
|
||||||
palette = np.zeros((num_entries, num_columns), dtype=np.int32)
|
palette = np.zeros((nrows, ncols), dtype=np.int32)
|
||||||
for j in range(num_entries):
|
for j in range(nrows):
|
||||||
palette[j] = struct.unpack_from(fmt, read_buffer,
|
palette[j] = struct.unpack_from(fmt, read_buffer,
|
||||||
offset=j * row_nbytes)
|
offset=j * row_nbytes)
|
||||||
|
|
||||||
|
|
@ -2828,13 +2828,15 @@ class UUIDListBox(Jp2kBox):
|
||||||
-------
|
-------
|
||||||
UUIDListBox instance
|
UUIDListBox instance
|
||||||
"""
|
"""
|
||||||
read_buffer = fptr.read(2)
|
num_bytes = offset + length - fptr.tell()
|
||||||
num_uuids, = struct.unpack('>H', read_buffer)
|
read_buffer = fptr.read(num_bytes)
|
||||||
|
|
||||||
|
num_uuids, = struct.unpack_from('>H', read_buffer)
|
||||||
|
|
||||||
ulst = []
|
ulst = []
|
||||||
for _ in range(num_uuids):
|
for j in range(num_uuids):
|
||||||
read_buffer = fptr.read(16)
|
uuid_buffer = read_buffer[2 + j * 16 : 2 + (j + 1) * 16]
|
||||||
ulst.append(uuid.UUID(bytes=read_buffer))
|
ulst.append(uuid.UUID(bytes=uuid_buffer))
|
||||||
|
|
||||||
return cls(ulst, length=length, offset=offset)
|
return cls(ulst, length=length, offset=offset)
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -691,7 +691,7 @@ class Jp2k(Jp2kBox):
|
||||||
msg = "Unable to locate the specified codestream."
|
msg = "Unable to locate the specified codestream."
|
||||||
raise IOError(msg)
|
raise IOError(msg)
|
||||||
if L == 0:
|
if L == 0:
|
||||||
# The length of the box is presumed to last until the end of
|
# The length of the box is presumed to last until the end of
|
||||||
# the file. Compute the effective length of the box.
|
# the file. Compute the effective length of the box.
|
||||||
L = os.path.getsize(ifile.name) - ifile.tell() + 8
|
L = os.path.getsize(ifile.name) - ifile.tell() + 8
|
||||||
|
|
||||||
|
|
@ -833,38 +833,12 @@ class Jp2k(Jp2kBox):
|
||||||
"""
|
"""
|
||||||
self._subsampling_sanity_check()
|
self._subsampling_sanity_check()
|
||||||
|
|
||||||
# Must check the specified rlevel against the maximum.
|
dparameters = self._populate_dparam(rlevel, ignore_pclr_cmap_cdef)
|
||||||
if rlevel != 0:
|
|
||||||
# Must check the specified rlevel against the maximum.
|
|
||||||
codestream = self.get_codestream()
|
|
||||||
max_rlevel = codestream.segment[2].spcod[4]
|
|
||||||
if rlevel == -1:
|
|
||||||
# -1 is shorthand for the largest rlevel
|
|
||||||
rlevel = max_rlevel
|
|
||||||
elif rlevel < -1 or rlevel > max_rlevel:
|
|
||||||
msg = "rlevel must be in the range [-1, {0}] for this image."
|
|
||||||
msg = msg.format(max_rlevel)
|
|
||||||
raise IOError(msg)
|
|
||||||
|
|
||||||
with ExitStack() as stack:
|
with ExitStack() as stack:
|
||||||
try:
|
try:
|
||||||
# Set decoding parameters.
|
|
||||||
# TODO: look to refactor, use _populate_dparam
|
|
||||||
dparameters = opj.DecompressionParametersType()
|
|
||||||
opj.set_default_decoder_parameters(ctypes.byref(dparameters))
|
|
||||||
|
|
||||||
if ignore_pclr_cmap_cdef is True:
|
|
||||||
# Return raw codestream components.
|
|
||||||
dparameters.flags |= 1
|
|
||||||
|
|
||||||
dparameters.cp_reduce = rlevel
|
|
||||||
dparameters.decod_format = self._codec_format
|
dparameters.decod_format = self._codec_format
|
||||||
|
|
||||||
infile = self.filename.encode()
|
|
||||||
nelts = opj.PATH_LEN - len(infile)
|
|
||||||
infile += b'0' * nelts
|
|
||||||
dparameters.infile = infile
|
|
||||||
|
|
||||||
dinfo = opj.create_decompress(dparameters.decod_format)
|
dinfo = opj.create_decompress(dparameters.decod_format)
|
||||||
|
|
||||||
event_mgr = opj.EventMgrType()
|
event_mgr = opj.EventMgrType()
|
||||||
|
|
@ -931,8 +905,8 @@ class Jp2k(Jp2kBox):
|
||||||
"""
|
"""
|
||||||
self._subsampling_sanity_check()
|
self._subsampling_sanity_check()
|
||||||
|
|
||||||
dparam = self._populate_dparam(layer, rlevel, area, tile,
|
dparam = self._populate_dparam(rlevel, ignore_pclr_cmap_cdef,
|
||||||
ignore_pclr_cmap_cdef)
|
layer=layer, tile=tile, area=area)
|
||||||
|
|
||||||
with ExitStack() as stack:
|
with ExitStack() as stack:
|
||||||
if hasattr(opj2.OPENJP2,
|
if hasattr(opj2.OPENJP2,
|
||||||
|
|
@ -976,8 +950,8 @@ class Jp2k(Jp2kBox):
|
||||||
|
|
||||||
return img_array
|
return img_array
|
||||||
|
|
||||||
def _populate_dparam(self, layer, rlevel, area, tile,
|
def _populate_dparam(self, rlevel, ignore_pclr_cmap_cdef, tile=None,
|
||||||
ignore_pclr_cmap_cdef):
|
layer=None, area=None):
|
||||||
"""Populate decompression structure with appropriate input parameters.
|
"""Populate decompression structure with appropriate input parameters.
|
||||||
|
|
||||||
Parameters
|
Parameters
|
||||||
|
|
@ -1000,7 +974,11 @@ class Jp2k(Jp2kBox):
|
||||||
dparam : DecompressionParametersType (ctypes)
|
dparam : DecompressionParametersType (ctypes)
|
||||||
Corresponds to openjp2 decompression parameters structure.
|
Corresponds to openjp2 decompression parameters structure.
|
||||||
"""
|
"""
|
||||||
dparam = opj2.set_default_decoder_parameters()
|
if opj2.OPENJP2 is not None:
|
||||||
|
dparam = opj2.set_default_decoder_parameters()
|
||||||
|
else:
|
||||||
|
dparam = opj.DecompressionParametersType()
|
||||||
|
opj.set_default_decoder_parameters(ctypes.byref(dparam))
|
||||||
|
|
||||||
infile = self.filename.encode()
|
infile = self.filename.encode()
|
||||||
nelts = opj2.PATH_LEN - len(infile)
|
nelts = opj2.PATH_LEN - len(infile)
|
||||||
|
|
@ -1009,12 +987,22 @@ class Jp2k(Jp2kBox):
|
||||||
|
|
||||||
dparam.decod_format = self._codec_format
|
dparam.decod_format = self._codec_format
|
||||||
|
|
||||||
dparam.cp_layer = layer
|
if layer is not None:
|
||||||
|
dparam.cp_layer = layer
|
||||||
|
|
||||||
if rlevel == -1:
|
# Must check the specified rlevel against the maximum.
|
||||||
# Get the lowest resolution thumbnail.
|
if rlevel != 0:
|
||||||
|
# Must check the specified rlevel against the maximum.
|
||||||
codestream = self.get_codestream()
|
codestream = self.get_codestream()
|
||||||
rlevel = codestream.segment[2].spcod[4]
|
max_rlevel = codestream.segment[2].spcod[4]
|
||||||
|
if rlevel == -1:
|
||||||
|
# -1 is shorthand for the largest rlevel
|
||||||
|
rlevel = max_rlevel
|
||||||
|
elif rlevel < -1 or rlevel > max_rlevel:
|
||||||
|
msg = "rlevel must be in the range [-1, {0}] for this image."
|
||||||
|
msg = msg.format(max_rlevel)
|
||||||
|
raise IOError(msg)
|
||||||
|
|
||||||
dparam.cp_reduce = rlevel
|
dparam.cp_reduce = rlevel
|
||||||
|
|
||||||
if area is not None:
|
if area is not None:
|
||||||
|
|
@ -1088,7 +1076,8 @@ class Jp2k(Jp2kBox):
|
||||||
"of OpenJP2 installed before using "
|
"of OpenJP2 installed before using "
|
||||||
"this functionality.")
|
"this functionality.")
|
||||||
|
|
||||||
dparam = self._populate_dparam(layer, rlevel, area, tile, ignore_pclr_cmap_cdef)
|
dparam = self._populate_dparam(rlevel, ignore_pclr_cmap_cdef,
|
||||||
|
layer=layer, tile=tile, area=area)
|
||||||
|
|
||||||
with ExitStack() as stack:
|
with ExitStack() as stack:
|
||||||
if hasattr(opj2.OPENJP2,
|
if hasattr(opj2.OPENJP2,
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue