Merge branch 'issue135' into devel

This commit is contained in:
John Evans 2013-10-24 16:55:49 -04:00
commit 638c2451b8
2 changed files with 29 additions and 82 deletions

View file

@ -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',

View file

@ -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