All parsing routines have the same signature now. #94
This commit is contained in:
parent
40e91dae7f
commit
2b5b1d081d
1 changed files with 81 additions and 69 deletions
|
|
@ -103,7 +103,7 @@ class Codestream(object):
|
||||||
|
|
||||||
read_buffer = fptr.read(2)
|
read_buffer = fptr.read(2)
|
||||||
try:
|
try:
|
||||||
marker_id, = struct.unpack('>H', read_buffer)
|
self._marker_id, = struct.unpack('>H', read_buffer)
|
||||||
except struct.error:
|
except struct.error:
|
||||||
# Treat this as a warning.
|
# Treat this as a warning.
|
||||||
msg = "Marker had length {0} instead of expected length of 2 "
|
msg = "Marker had length {0} instead of expected length of 2 "
|
||||||
|
|
@ -111,13 +111,15 @@ class Codestream(object):
|
||||||
warnings.warn(msg.format(len(read_buffer)))
|
warnings.warn(msg.format(len(read_buffer)))
|
||||||
break
|
break
|
||||||
|
|
||||||
if marker_id == 0xff90 and header_only:
|
self._offset = fptr.tell() - 2
|
||||||
|
|
||||||
|
if self._marker_id == 0xff90 and header_only:
|
||||||
# Start-of-tile (SOT) means that we are out of the main header
|
# Start-of-tile (SOT) means that we are out of the main header
|
||||||
# and there is no need to go further.
|
# and there is no need to go further.
|
||||||
break
|
break
|
||||||
|
|
||||||
try:
|
try:
|
||||||
segment = self._process_marker_segment(fptr, marker_id)
|
segment = self._process_marker_segment(fptr)
|
||||||
except Exception as error:
|
except Exception as error:
|
||||||
# Treat this as a warning.
|
# Treat this as a warning.
|
||||||
msg = str(error)
|
msg = str(error)
|
||||||
|
|
@ -126,11 +128,11 @@ class Codestream(object):
|
||||||
|
|
||||||
self.segment.append(segment)
|
self.segment.append(segment)
|
||||||
|
|
||||||
if marker_id == 0xffd9:
|
if self._marker_id == 0xffd9:
|
||||||
# end of codestream, should break.
|
# end of codestream, should break.
|
||||||
break
|
break
|
||||||
|
|
||||||
if marker_id == 0xff93:
|
if self._marker_id == 0xff93:
|
||||||
# If SOD, then we need to seek past the tile part bit stream.
|
# If SOD, then we need to seek past the tile part bit stream.
|
||||||
if self._parse_tpart_flag and not header_only:
|
if self._parse_tpart_flag and not header_only:
|
||||||
# But first parse the tile part bit stream for SOP and
|
# But first parse the tile part bit stream for SOP and
|
||||||
|
|
@ -140,93 +142,126 @@ class Codestream(object):
|
||||||
|
|
||||||
fptr.seek(self._tile_offset[-1] + self._tile_length[-1])
|
fptr.seek(self._tile_offset[-1] + self._tile_length[-1])
|
||||||
|
|
||||||
def _process_marker_segment(self, fptr, marker_id):
|
def _process_marker_segment(self, fptr):
|
||||||
"""Process and return a segment from the codestream.
|
"""Process and return a segment from the codestream.
|
||||||
"""
|
"""
|
||||||
offset = fptr.tell() - 2
|
if self._marker_id >= 0xff30 and self._marker_id <= 0xff3f:
|
||||||
|
segment = self._parse_reserved_marker(fptr)
|
||||||
|
|
||||||
if marker_id >= 0xff30 and marker_id <= 0xff3f:
|
elif self._marker_id == 0xff51:
|
||||||
the_id = '0x{0:x}'.format(marker_id)
|
|
||||||
segment = Segment(marker_id=the_id, offset=offset, length=0)
|
|
||||||
|
|
||||||
elif marker_id == 0xff51:
|
|
||||||
segment = self._parse_siz_segment(fptr)
|
segment = self._parse_siz_segment(fptr)
|
||||||
|
|
||||||
elif marker_id == 0xff52:
|
elif self._marker_id == 0xff52:
|
||||||
segment = self._parse_cod_segment(fptr)
|
segment = self._parse_cod_segment(fptr)
|
||||||
|
|
||||||
elif marker_id == 0xff53:
|
elif self._marker_id == 0xff53:
|
||||||
segment = self._parse_coc_segment(fptr)
|
segment = self._parse_coc_segment(fptr)
|
||||||
|
|
||||||
elif marker_id == 0xff55:
|
elif self._marker_id == 0xff55:
|
||||||
segment = self._parse_tlm_segment(fptr)
|
segment = self._parse_tlm_segment(fptr)
|
||||||
|
|
||||||
elif marker_id == 0xff58:
|
elif self._marker_id == 0xff58:
|
||||||
segment = self._parse_plt_segment(fptr)
|
segment = self._parse_plt_segment(fptr)
|
||||||
|
|
||||||
elif marker_id == 0xff5c:
|
elif self._marker_id == 0xff5c:
|
||||||
segment = self._parse_qcd_segment(fptr)
|
segment = self._parse_qcd_segment(fptr)
|
||||||
|
|
||||||
elif marker_id == 0xff5d:
|
elif self._marker_id == 0xff5d:
|
||||||
segment = self._parse_qcc_segment(fptr)
|
segment = self._parse_qcc_segment(fptr)
|
||||||
|
|
||||||
elif marker_id == 0xff5e:
|
elif self._marker_id == 0xff5e:
|
||||||
segment = self._parse_rgn_segment(fptr)
|
segment = self._parse_rgn_segment(fptr)
|
||||||
|
|
||||||
elif marker_id == 0xff5f:
|
elif self._marker_id == 0xff5f:
|
||||||
segment = self._parse_pod_segment(fptr)
|
segment = self._parse_pod_segment(fptr)
|
||||||
|
|
||||||
elif marker_id == 0xff60:
|
elif self._marker_id == 0xff60:
|
||||||
segment = self._parse_ppm_segment(fptr)
|
segment = self._parse_ppm_segment(fptr)
|
||||||
|
|
||||||
elif marker_id == 0xff61:
|
elif self._marker_id == 0xff61:
|
||||||
segment = self._parse_ppt_segment(fptr)
|
segment = self._parse_ppt_segment(fptr)
|
||||||
|
|
||||||
elif marker_id == 0xff63:
|
elif self._marker_id == 0xff63:
|
||||||
segment = self._parse_crg_segment(fptr)
|
segment = self._parse_crg_segment(fptr)
|
||||||
|
|
||||||
elif marker_id == 0xff64:
|
elif self._marker_id == 0xff64:
|
||||||
segment = self._parse_cme_segment(fptr)
|
segment = self._parse_cme_segment(fptr)
|
||||||
|
|
||||||
elif marker_id == 0xff90:
|
elif self._marker_id == 0xff90:
|
||||||
segment = self._parse_sot_segment(fptr)
|
segment = self._parse_sot_segment(fptr)
|
||||||
|
|
||||||
elif marker_id == 0xff93:
|
elif self._marker_id == 0xff93:
|
||||||
segment = self._parse_sod_segment(fptr)
|
segment = self._parse_sod_segment(fptr)
|
||||||
|
|
||||||
elif marker_id == 0xffd9:
|
elif self._marker_id == 0xffd9:
|
||||||
segment = self._parse_eoc_segment(fptr)
|
segment = self._parse_eoc_segment(fptr)
|
||||||
|
|
||||||
elif marker_id in _VALID_MARKERS:
|
elif self._marker_id in _VALID_MARKERS:
|
||||||
# It's a reserved marker that I don't know anything about.
|
# It's a reserved marker that I don't know anything about.
|
||||||
# See table A-1 in ISO/IEC FCD15444-1.
|
# See table A-1 in ISO/IEC FCD15444-1.
|
||||||
segment = _parse_generic_segment(fptr, marker_id)
|
segment = self._parse_reserved_segment(fptr)
|
||||||
|
|
||||||
elif ((marker_id & 0xff00) >> 8) == 255:
|
elif self._marker_id == 0xff79:
|
||||||
# Peek ahead to see if the next two bytes are a marker or not.
|
segment = self._parse_unrecognized_segment(fptr)
|
||||||
# Then seek back.
|
|
||||||
msg = "Unrecognized marker id: 0x{0:x}".format(marker_id)
|
|
||||||
warnings.warn(msg)
|
|
||||||
cpos = fptr.tell()
|
|
||||||
read_buffer = fptr.read(2)
|
|
||||||
next_item, = struct.unpack('>H', read_buffer)
|
|
||||||
fptr.seek(cpos)
|
|
||||||
if ((next_item & 0xff00) >> 8) == 255:
|
|
||||||
# No segment associated with this marker, so reset
|
|
||||||
# to two bytes after it.
|
|
||||||
segment = Segment(id='0x{0:x}'.format(marker_id),
|
|
||||||
offset=offset, length=0)
|
|
||||||
else:
|
|
||||||
segment = _parse_generic_segment(fptr, marker_id)
|
|
||||||
|
|
||||||
else:
|
else:
|
||||||
msg = 'Invalid marker id encountered at byte {0:d} '
|
msg = 'Invalid marker id encountered at byte {0:d} '
|
||||||
msg += 'in codestream: "0x{1:x}"'
|
msg += 'in codestream: "0x{1:x}"'
|
||||||
msg = msg.format(offset, marker_id)
|
msg = msg.format(self._offset, self._marker_id)
|
||||||
raise IOError(msg)
|
raise IOError(msg)
|
||||||
|
|
||||||
return segment
|
return segment
|
||||||
|
|
||||||
|
def _parse_unrecognized_segment(self, fptr):
|
||||||
|
"""Looks like a marker, but not sure what it is.
|
||||||
|
"""
|
||||||
|
msg = "Unrecognized marker id: 0x{0:x}".format(self._marker_id)
|
||||||
|
warnings.warn(msg)
|
||||||
|
cpos = fptr.tell()
|
||||||
|
read_buffer = fptr.read(2)
|
||||||
|
next_item, = struct.unpack('>H', read_buffer)
|
||||||
|
fptr.seek(cpos)
|
||||||
|
if ((next_item & 0xff00) >> 8) == 255:
|
||||||
|
# No segment associated with this marker, so reset
|
||||||
|
# to two bytes after it.
|
||||||
|
segment = Segment(id='0x{0:x}'.format(self._marker_id),
|
||||||
|
offset=self._offset, length=0)
|
||||||
|
else:
|
||||||
|
segment = self._parse_reserved_segment(fptr)
|
||||||
|
return segment
|
||||||
|
|
||||||
|
|
||||||
|
def _parse_reserved_marker(self, fptr):
|
||||||
|
"""Marker range between 0xff30 and 0xff39.
|
||||||
|
"""
|
||||||
|
the_id = '0x{0:x}'.format(self._marker_id)
|
||||||
|
segment = Segment(marker_id=the_id, offset=self._offset, length=0)
|
||||||
|
return segment
|
||||||
|
|
||||||
|
|
||||||
|
def _parse_reserved_segment(self, fptr):
|
||||||
|
"""Parse a marker segment for which we know nothing of the segment itself.
|
||||||
|
|
||||||
|
Parameters
|
||||||
|
----------
|
||||||
|
fptr : file
|
||||||
|
Open file object.
|
||||||
|
|
||||||
|
Returns
|
||||||
|
-------
|
||||||
|
Segment instance.
|
||||||
|
"""
|
||||||
|
offset = fptr.tell() - 2
|
||||||
|
|
||||||
|
read_buffer = fptr.read(2)
|
||||||
|
length, = struct.unpack('>H', read_buffer)
|
||||||
|
data = fptr.read(length-2)
|
||||||
|
|
||||||
|
segment = Segment(marker_id='0x{0:x}'.format(self._marker_id),
|
||||||
|
offset=offset, length=length, data=data)
|
||||||
|
return segment
|
||||||
|
|
||||||
|
|
||||||
def _parse_tile_part_bit_stream(self, fptr, sod_marker, tile_length):
|
def _parse_tile_part_bit_stream(self, fptr, sod_marker, tile_length):
|
||||||
"""Parse the tile part bit stream for SOP, EPH marker segments."""
|
"""Parse the tile part bit stream for SOP, EPH marker segments."""
|
||||||
read_buffer = fptr.read(tile_length)
|
read_buffer = fptr.read(tile_length)
|
||||||
|
|
@ -1763,26 +1798,3 @@ def _print_quantization_style(sqcc):
|
||||||
elif sqcc & 0x1f == 2:
|
elif sqcc & 0x1f == 2:
|
||||||
msg += 'scalar explicit, '
|
msg += 'scalar explicit, '
|
||||||
return msg
|
return msg
|
||||||
|
|
||||||
|
|
||||||
def _parse_generic_segment(fptr, marker_id):
|
|
||||||
"""Parse a generic marker segment.
|
|
||||||
|
|
||||||
Parameters
|
|
||||||
----------
|
|
||||||
fptr : file
|
|
||||||
Open file object.
|
|
||||||
|
|
||||||
Returns
|
|
||||||
-------
|
|
||||||
Segment instance.
|
|
||||||
"""
|
|
||||||
offset = fptr.tell() - 2
|
|
||||||
|
|
||||||
read_buffer = fptr.read(2)
|
|
||||||
length, = struct.unpack('>H', read_buffer)
|
|
||||||
data = fptr.read(length-2)
|
|
||||||
|
|
||||||
segment = Segment(marker_id='0x{0:x}'.format(marker_id), offset=offset,
|
|
||||||
length=length, data=data)
|
|
||||||
return segment
|
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue