Merge branch 'devel' into issue104
This commit is contained in:
commit
1b09fd8eaa
2 changed files with 29 additions and 82 deletions
|
|
@ -1193,8 +1193,8 @@ class PaletteBox(Jp2kBox):
|
||||||
offset of the box from the start of the file.
|
offset of the box from the start of the file.
|
||||||
longname : str
|
longname : str
|
||||||
more verbose description of the box.
|
more verbose description of the box.
|
||||||
palette : list
|
palette : ndarray
|
||||||
Colormap represented as list of 1D arrays, one per color component.
|
Colormap array.
|
||||||
"""
|
"""
|
||||||
def __init__(self, palette, bits_per_component, signed, length=0,
|
def __init__(self, palette, bits_per_component, signed, length=0,
|
||||||
offset=-1):
|
offset=-1):
|
||||||
|
|
@ -1207,8 +1207,7 @@ class PaletteBox(Jp2kBox):
|
||||||
|
|
||||||
def __str__(self):
|
def __str__(self):
|
||||||
msg = Jp2kBox.__str__(self)
|
msg = Jp2kBox.__str__(self)
|
||||||
msg += '\n Size: ({0} x {1})'.format(len(self.palette[0]),
|
msg += '\n Size: ({0} x {1})'.format(*self.palette.shape)
|
||||||
len(self.palette))
|
|
||||||
return msg
|
return msg
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
|
|
@ -1238,68 +1237,29 @@ class PaletteBox(Jp2kBox):
|
||||||
bps = [((x & 0x07f) + 1) for x in data]
|
bps = [((x & 0x07f) + 1) for x in data]
|
||||||
signed = [((x & 0x80) > 1) for x in data]
|
signed = [((x & 0x80) > 1) for x in data]
|
||||||
|
|
||||||
|
fmt = '>'
|
||||||
|
for bits in bps:
|
||||||
|
if bits <= 8:
|
||||||
|
fmt += 'B'
|
||||||
|
elif bits <= 16:
|
||||||
|
fmt += 'H'
|
||||||
|
elif bits <= 32:
|
||||||
|
fmt += 'I'
|
||||||
|
|
||||||
# Each palette component is padded out to the next largest byte.
|
# Each palette component is padded out to the next largest byte.
|
||||||
# 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])
|
||||||
|
|
||||||
# Form the format string so that we can intelligently unpack the
|
|
||||||
# colormap. We have to do this because it is possible that the
|
|
||||||
# colormap columns could have different datatypes.
|
|
||||||
#
|
|
||||||
# This means that we store the palette as a list of 1D arrays,
|
|
||||||
# which reverses the usual indexing scheme.
|
|
||||||
read_buffer = fptr.read(num_entries * row_nbytes)
|
read_buffer = fptr.read(num_entries * row_nbytes)
|
||||||
palette = _buffer2palette(read_buffer, num_entries, num_columns, bps)
|
palette = np.zeros((num_entries, num_columns), dtype=np.int32)
|
||||||
|
for j in range(num_entries):
|
||||||
|
palette[j] = struct.unpack_from(fmt, read_buffer,
|
||||||
|
offset=j * row_nbytes)
|
||||||
|
|
||||||
box = PaletteBox(palette, bps, signed, length=length, offset=offset)
|
box = PaletteBox(palette, bps, signed, length=length, offset=offset)
|
||||||
return box
|
return box
|
||||||
|
|
||||||
|
|
||||||
def _buffer2palette(read_buffer, num_rows, num_cols, bps):
|
|
||||||
"""Construct the palette from the buffer read from file.
|
|
||||||
|
|
||||||
Parameters
|
|
||||||
----------
|
|
||||||
read_buffer : iterable
|
|
||||||
Byte array of palette information read from file.
|
|
||||||
num_rows, num_cols : int
|
|
||||||
Size of palette.
|
|
||||||
bps : iterable
|
|
||||||
Bits per sample for each channel.
|
|
||||||
|
|
||||||
Returns
|
|
||||||
-------
|
|
||||||
palette : list of 1D arrays
|
|
||||||
Each 1D array corresponds to a channel.
|
|
||||||
"""
|
|
||||||
row_nbytes = 0
|
|
||||||
palette = []
|
|
||||||
fmt = '>'
|
|
||||||
for j in range(num_cols):
|
|
||||||
if bps[j] <= 8:
|
|
||||||
row_nbytes += 1
|
|
||||||
fmt += 'B'
|
|
||||||
palette.append(np.zeros(num_rows, dtype=np.uint8))
|
|
||||||
elif bps[j] <= 16:
|
|
||||||
row_nbytes += 2
|
|
||||||
fmt += 'H'
|
|
||||||
palette.append(np.zeros(num_rows, dtype=np.uint16))
|
|
||||||
elif bps[j] <= 32:
|
|
||||||
row_nbytes += 4
|
|
||||||
fmt += 'I'
|
|
||||||
palette.append(np.zeros(num_rows, dtype=np.uint32))
|
|
||||||
else:
|
|
||||||
msg = 'Unsupported palette bitdepth (%d).'.format(bps[j])
|
|
||||||
raise IOError(msg)
|
|
||||||
|
|
||||||
for j in range(num_rows):
|
|
||||||
row_buffer = read_buffer[(row_nbytes * j):(row_nbytes * (j + 1))]
|
|
||||||
row = struct.unpack(fmt, row_buffer)
|
|
||||||
for k in range(num_cols):
|
|
||||||
palette[k][j] = row[k]
|
|
||||||
|
|
||||||
return palette
|
|
||||||
|
|
||||||
# Map rreq codes to display text.
|
# Map rreq codes to display text.
|
||||||
_READER_REQUIREMENTS_DISPLAY = {
|
_READER_REQUIREMENTS_DISPLAY = {
|
||||||
0: 'File not completely understood',
|
0: 'File not completely understood',
|
||||||
|
|
|
||||||
|
|
@ -3797,19 +3797,16 @@ class TestSuiteDump(unittest.TestCase):
|
||||||
self.assertEqual(jp2.box[2].box[0].ip_provided, False)
|
self.assertEqual(jp2.box[2].box[0].ip_provided, False)
|
||||||
|
|
||||||
# Palette box.
|
# Palette box.
|
||||||
self.assertEqual(len(jp2.box[2].box[1].palette), 3)
|
self.assertEqual(jp2.box[2].box[1].palette.shape, (256, 3))
|
||||||
self.assertEqual(len(jp2.box[2].box[1].palette[0]), 256)
|
np.testing.assert_array_equal(jp2.box[2].box[1].palette[0, 0], 0)
|
||||||
self.assertEqual(len(jp2.box[2].box[1].palette[1]), 256)
|
np.testing.assert_array_equal(jp2.box[2].box[1].palette[0, 1], 0)
|
||||||
self.assertEqual(len(jp2.box[2].box[1].palette[2]), 256)
|
np.testing.assert_array_equal(jp2.box[2].box[1].palette[0, 2], 0)
|
||||||
np.testing.assert_array_equal(jp2.box[2].box[1].palette[0][0], 0)
|
np.testing.assert_array_equal(jp2.box[2].box[1].palette[128, 0], 73)
|
||||||
np.testing.assert_array_equal(jp2.box[2].box[1].palette[1][0], 0)
|
np.testing.assert_array_equal(jp2.box[2].box[1].palette[128, 1], 92)
|
||||||
np.testing.assert_array_equal(jp2.box[2].box[1].palette[2][0], 0)
|
np.testing.assert_array_equal(jp2.box[2].box[1].palette[128, 2], 53)
|
||||||
np.testing.assert_array_equal(jp2.box[2].box[1].palette[0][128], 73)
|
np.testing.assert_array_equal(jp2.box[2].box[1].palette[255, 0], 245)
|
||||||
np.testing.assert_array_equal(jp2.box[2].box[1].palette[1][128], 92)
|
np.testing.assert_array_equal(jp2.box[2].box[1].palette[255, 1], 245)
|
||||||
np.testing.assert_array_equal(jp2.box[2].box[1].palette[2][128], 53)
|
np.testing.assert_array_equal(jp2.box[2].box[1].palette[255, 2], 245)
|
||||||
np.testing.assert_array_equal(jp2.box[2].box[1].palette[0][-1], 245)
|
|
||||||
np.testing.assert_array_equal(jp2.box[2].box[1].palette[1][-1], 245)
|
|
||||||
np.testing.assert_array_equal(jp2.box[2].box[1].palette[2][-1], 245)
|
|
||||||
|
|
||||||
# Component mapping box
|
# Component mapping box
|
||||||
self.assertEqual(jp2.box[2].box[2].component_index, (0, 0, 0))
|
self.assertEqual(jp2.box[2].box[2].component_index, (0, 0, 0))
|
||||||
|
|
@ -5699,10 +5696,7 @@ class TestSuiteDump(unittest.TestCase):
|
||||||
|
|
||||||
# Jp2 Header
|
# Jp2 Header
|
||||||
# Palette box.
|
# Palette box.
|
||||||
self.assertEqual(len(jp2.box[3].box[2].palette), 3)
|
self.assertEqual(jp2.box[3].box[2].palette.shape, (256, 3))
|
||||||
self.assertEqual(len(jp2.box[3].box[2].palette[0]), 256)
|
|
||||||
self.assertEqual(len(jp2.box[3].box[2].palette[1]), 256)
|
|
||||||
self.assertEqual(len(jp2.box[3].box[2].palette[2]), 256)
|
|
||||||
|
|
||||||
# Jp2 Header
|
# Jp2 Header
|
||||||
# Component mapping box
|
# Component mapping box
|
||||||
|
|
@ -6127,11 +6121,7 @@ class TestSuiteDump(unittest.TestCase):
|
||||||
|
|
||||||
# Jp2 Header
|
# Jp2 Header
|
||||||
# Palette box.
|
# Palette box.
|
||||||
self.assertEqual(len(jp2.box[3].box[2].palette), 4)
|
self.assertEqual(jp2.box[3].box[2].palette.shape, (1, 4))
|
||||||
self.assertEqual(len(jp2.box[3].box[2].palette[0]), 1)
|
|
||||||
self.assertEqual(len(jp2.box[3].box[2].palette[1]), 1)
|
|
||||||
self.assertEqual(len(jp2.box[3].box[2].palette[2]), 1)
|
|
||||||
self.assertEqual(len(jp2.box[3].box[2].palette[3]), 1)
|
|
||||||
|
|
||||||
# Jp2 Header
|
# Jp2 Header
|
||||||
# Component mapping box
|
# Component mapping box
|
||||||
|
|
@ -6242,10 +6232,7 @@ class TestSuiteDump(unittest.TestCase):
|
||||||
# Jp2 Header
|
# Jp2 Header
|
||||||
# Palette box.
|
# Palette box.
|
||||||
# 3 columns with 16 entries.
|
# 3 columns with 16 entries.
|
||||||
self.assertEqual(len(jp2.box[3].box[2].palette), 3)
|
self.assertEqual(jp2.box[3].box[2].palette.shape, (16, 3))
|
||||||
self.assertEqual(len(jp2.box[3].box[2].palette[0]), 16)
|
|
||||||
self.assertEqual(len(jp2.box[3].box[2].palette[1]), 16)
|
|
||||||
self.assertEqual(len(jp2.box[3].box[2].palette[2]), 16)
|
|
||||||
|
|
||||||
# Jp2 Header
|
# Jp2 Header
|
||||||
# Component mapping box
|
# Component mapping box
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue