Proper repr support for SIZ segment. SIZ segment constructor change.

The SIZ segment was taking raw buffer arguments, which are difficult
for eval(repr()) to deal with, so the constructor was changed to make
the arguments more explicit. #133
This commit is contained in:
John Evans 2013-10-24 08:21:14 -04:00
commit d3dd654c17
3 changed files with 119 additions and 42 deletions

View file

@ -1,5 +1,5 @@
Oct 22, 2013 - v0.5.7 Super boxes constructors now take optional box list Oct 22, 2013 - v0.5.7 Super box constructors now take optional box list
argument. argument. Removed ssiz attribute from SIZsegment class.
Oct 13, 2013 - v0.5.6 Fixed handling of non-ascii chars in XML boxes. Fixed Oct 13, 2013 - v0.5.6 Fixed handling of non-ascii chars in XML boxes. Fixed
some docstring errors in jp2box module. some docstring errors in jp2box module.

View file

@ -646,16 +646,50 @@ class Codestream(object):
length, = struct.unpack('>H', read_buffer) length, = struct.unpack('>H', read_buffer)
xy_buffer = fptr.read(36) xy_buffer = fptr.read(36)
data = struct.unpack('>HIIIIIIIIH', xy_buffer)
num_components, = struct.unpack('>H', xy_buffer[-2:]) rsiz = data[0]
xysiz = (data[1], data[2])
xyosiz = (data[3], data[4])
xytsiz = (data[5], data[6])
xytosiz = (data[7], data[8])
component_buffer = fptr.read(num_components * 3) # Csiz is the number of components
Csiz = data[9]
segment = SIZsegment(xy_buffer, component_buffer, length, offset) component_buffer = fptr.read(Csiz * 3)
data = struct.unpack('>' + 'B' * len(component_buffer),
component_buffer)
bitdepth = tuple(((x & 0x7f) + 1) for x in data[0::3])
signed = tuple(((x & 0xb0) > 0) for x in data[0::3])
xrsiz = data[1::3]
yrsiz = data[2::3]
for j, subsampling in enumerate(zip(xrsiz, yrsiz)):
if 0 in subsampling:
msg = "Invalid subsampling value for component {0}: "
msg += "dx={1}, dy={2}."
msg = msg.format(j, subsampling[0], subsampling[1])
warnings.warn(msg)
kwargs = {'rsiz': rsiz,
'xysiz': xysiz,
'xyosiz': xyosiz,
'xytsiz': xytsiz,
'xytosiz': xytosiz,
'Csiz': Csiz,
'bitdepth': bitdepth,
'signed': signed,
'xyrsiz': (xrsiz, yrsiz),
'length': length,
'offset': offset}
segment = SIZsegment(**kwargs)
# Need to keep track of the number of components from SIZ for # Need to keep track of the number of components from SIZ for
# other markers # other markers.
self._csiz = len(segment.ssiz) self._csiz = Csiz
return segment return segment
@ -1441,8 +1475,8 @@ class SIZsegment(Segment):
Width and height of reference tile with respect to the reference grid. Width and height of reference tile with respect to the reference grid.
xtosiz, ytosiz : int xtosiz, ytosiz : int
Horizontal and vertical offsets of tile from origin of reference grid. Horizontal and vertical offsets of tile from origin of reference grid.
ssiz : iterable bytes Csiz : int
Encoded precision (depth) in bits and sign of each component. Number of components in image.
bitdepth : iterable bytes bitdepth : iterable bytes
Precision (depth) in bits of each component. Precision (depth) in bits of each component.
signed : iterable bool signed : iterable bool
@ -1457,21 +1491,20 @@ class SIZsegment(Segment):
15444-1:2004 - Information technology -- JPEG 2000 image coding system: 15444-1:2004 - Information technology -- JPEG 2000 image coding system:
Core coding system Core coding system
""" """
def __init__(self, xy_buffer, component_buffer, length, offset): def __init__(self, rsiz=-1, xysiz=None, xyosiz=-1, xytsiz=-1, xytosiz=-1,
Segment.__init__(self, marker_id='SIZ') Csiz=-1, bitdepth=None, signed=None, xyrsiz=-1, length=-1,
offset=-1):
Segment.__init__(self, marker_id='SIZ', length=length, offset=offset)
data = struct.unpack('>HIIIIIIIIH', xy_buffer) self.rsiz = rsiz
self.xsiz, self.ysiz = xysiz
self.rsiz = data[0] self.xosiz, self.yosiz = xyosiz
self.xsiz = data[1] self.xtsiz, self.ytsiz = xytsiz
self.ysiz = data[2] self.xtosiz, self.ytosiz = xytosiz
self.xosiz = data[3] self.Csiz = Csiz
self.yosiz = data[4] self.bitdepth = bitdepth
self.xtsiz = data[5] self.signed = signed
self.ytsiz = data[6] self.xrsiz, self.yrsiz = xyrsiz
self.xtosiz = data[7]
self.ytosiz = data[8]
# disregarding the last element in data
num_tiles_x = (self.xsiz - self.xosiz) / (self.xtsiz - self.xtosiz) num_tiles_x = (self.xsiz - self.xosiz) / (self.xtsiz - self.xtosiz)
num_tiles_y = (self.ysiz - self.yosiz) / (self.ytsiz - self.ytosiz) num_tiles_y = (self.ysiz - self.yosiz) / (self.ytsiz - self.ytosiz)
@ -1480,25 +1513,22 @@ class SIZsegment(Segment):
msg = "Invalid number of tiles ({0}).".format(numtiles) msg = "Invalid number of tiles ({0}).".format(numtiles)
warnings.warn(msg) warnings.warn(msg)
data = struct.unpack('>' + 'B' * len(component_buffer),
component_buffer)
self.ssiz = data[0::3] def __repr__(self):
msg = "glymur.codestream.SIZsegment(rsiz={rsiz}, xysiz={xysiz}, "
for j, subsampling in enumerate(list(zip(data[1::3], data[2::3]))): msg += "xyosiz={xyosiz}, xytsiz={xytsiz}, xytosiz={xytosiz}, "
if 0 in subsampling: msg += "Csiz={Csiz}, bitdepth={bitdepth}, signed={signed}, "
msg = "Invalid subsampling value for component {0}: " msg += "xyrsiz={xyrsiz})"
msg += "dx={1}, dy={2}." msg = msg.format(rsiz=self.rsiz,
msg = msg.format(j, subsampling[0], subsampling[1]) xysiz=(self.xsiz, self.ysiz),
warnings.warn(msg) xyosiz=(self.xosiz, self.yosiz),
self.xrsiz = data[1::3] xytsiz=(self.xtsiz, self.ytsiz),
self.yrsiz = data[2::3] xytosiz=(self.xtosiz, self.ytosiz),
Csiz=self.Csiz,
self.bitdepth = tuple(((x & 0x7f) + 1) for x in self.ssiz) bitdepth=self.bitdepth,
self.signed = tuple(((x & 0xb0) > 0) for x in self.ssiz) signed=self.signed,
xyrsiz=(self.xrsiz, self.yrsiz))
self.length = length return msg
self.offset = offset
def __str__(self): def __str__(self):
msg = Segment.__str__(self) msg = Segment.__str__(self)
@ -1549,6 +1579,9 @@ class SOCsegment(Segment):
Segment.__init__(self, marker_id='SOC') Segment.__init__(self, marker_id='SOC')
self.__dict__.update(**kwargs) self.__dict__.update(**kwargs)
def __repr__(self):
msg = "glymur.codestream.SOCsegment()"
return msg
class SODsegment(Segment): class SODsegment(Segment):
"""Container for Start of Data (SOD) segment information. """Container for Start of Data (SOD) segment information.

View file

@ -116,5 +116,49 @@ class TestCodestream(unittest.TestCase):
# codestream, so the last one is EOC. # codestream, so the last one is EOC.
self.assertEqual(codestream.segment[-1].marker_id, 'EOC') self.assertEqual(codestream.segment[-1].marker_id, 'EOC')
class TestCodestreamRepr(unittest.TestCase):
def setUp(self):
self.jp2file = glymur.data.nemo()
def tearDown(self):
pass
def test_soc(self):
"""Test SOC segment repr"""
segment = glymur.codestream.SOCsegment()
newseg = eval(repr(segment))
self.assertEqual(newseg.marker_id, 'SOC')
def test_siz(self):
"""Test SIZ segment repr"""
kwargs = {'rsiz': 0,
'xysiz': (2592, 1456),
'xyosiz': (0, 0),
'xytsiz': (2592, 1456),
'xytosiz': (0, 0),
'Csiz': 3,
'bitdepth': (8, 8, 8),
'signed': (False, False, False),
'xyrsiz': ((1, 1, 1), (1, 1, 1))}
segment = glymur.codestream.SIZsegment(**kwargs)
newseg = eval(repr(segment))
self.assertEqual(newseg.marker_id, 'SIZ')
self.assertEqual(newseg.xsiz, 2592)
self.assertEqual(newseg.ysiz, 1456)
self.assertEqual(newseg.xosiz, 0)
self.assertEqual(newseg.yosiz, 0)
self.assertEqual(newseg.xtsiz, 2592)
self.assertEqual(newseg.ytsiz, 1456)
self.assertEqual(newseg.xtosiz, 0)
self.assertEqual(newseg.ytosiz, 0)
self.assertEqual(newseg.xrsiz, (1, 1, 1))
self.assertEqual(newseg.yrsiz, (1, 1, 1))
self.assertEqual(newseg.bitdepth, (8, 8, 8))
self.assertEqual(newseg.signed, (False, False, False))
if __name__ == "__main__": if __name__ == "__main__":
unittest.main() unittest.main()