More refactoring, think it's in good shape now. #170

This commit is contained in:
John Evans 2014-02-11 13:57:30 -05:00
commit 0205a3cbba

View file

@ -1115,6 +1115,18 @@ def _validate_jp2_box_sequence(boxes):
This is non-exhaustive. This is non-exhaustive.
""" """
_validate_signature_compatibility(boxes)
_validate_jp2h(boxes)
_validate_jp2c(boxes)
_validate_association(boxes)
_validate_jpx_brand(boxes, boxes[1].brand)
_validate_jpx_compatibility(boxes, boxes[1].compatibility_list)
_validate_singletons(boxes)
_validate_top_level(boxes)
def _validate_signature_compatibility(boxes):
"""Validate the file signature and compatibility status."""
# Check for a bad sequence of boxes. # Check for a bad sequence of boxes.
# 1st two boxes must be 'jP ' and 'ftyp' # 1st two boxes must be 'jP ' and 'ftyp'
if boxes[0].box_id != 'jP ' or boxes[1].box_id != 'ftyp': if boxes[0].box_id != 'jP ' or boxes[1].box_id != 'ftyp':
@ -1127,6 +1139,9 @@ def _validate_jp2_box_sequence(boxes):
msg = "The ftyp box must contain 'jp2 ' in the compatibility list." msg = "The ftyp box must contain 'jp2 ' in the compatibility list."
raise IOError(msg) raise IOError(msg)
def _validate_jp2c(boxes):
"""Validate the codestream box in relation to other boxes."""
# jp2c must be preceeded by jp2h # jp2c must be preceeded by jp2h
jp2h_lst = [idx for (idx, box) in enumerate(boxes) jp2h_lst = [idx for (idx, box) in enumerate(boxes)
if box.box_id == 'jp2h'] if box.box_id == 'jp2h']
@ -1143,16 +1158,14 @@ def _validate_jp2_box_sequence(boxes):
msg = "The codestream box must be preceeded by a jp2 header box." msg = "The codestream box must be preceeded by a jp2 header box."
raise IOError(msg) raise IOError(msg)
_validate_jp2h(boxes[jp2h_idx])
_check_jp2h_child_boxes(boxes, 'top-level')
_asoc_check(boxes)
_jpx_brand(boxes, boxes[1].brand)
_jpx_compatibility(boxes, boxes[1].compatibility_list)
_check_for_singletons(boxes)
_check_top_level(boxes)
def _validate_jp2h(jp2h): def _validate_jp2h(boxes):
"""Validate the JP2 Header box.""" """Validate the JP2 Header box."""
_check_jp2h_child_boxes(boxes, 'top-level')
jp2h_lst = [box for box in boxes if box.box_id == 'jp2h']
jp2h = jp2h_lst[0]
# 1st jp2 header box cannot be empty. # 1st jp2 header box cannot be empty.
if len(jp2h.box) == 0: if len(jp2h.box) == 0:
msg = "The JP2 header superbox cannot be empty." msg = "The JP2 header superbox cannot be empty."
@ -1196,7 +1209,7 @@ def _validate_channel_definition(jp2h, colr):
msg = "All color channels must be defined in the " msg = "All color channels must be defined in the "
msg += "channel definition box." msg += "channel definition box."
raise IOError(msg) raise IOError(msg)
JP2H_CHILDREN = set(['bpcc', 'cmap', 'ihdr', 'pclr']) JP2H_CHILDREN = set(['bpcc', 'cmap', 'ihdr', 'pclr'])
def _check_jp2h_child_boxes(boxes, parent_box_name): def _check_jp2h_child_boxes(boxes, parent_box_name):
@ -1241,7 +1254,7 @@ def _check_superbox_for_top_levels(boxes):
if hasattr(box, 'box'): if hasattr(box, 'box'):
_check_superbox_for_top_levels(box.box) _check_superbox_for_top_levels(box.box)
def _check_top_level(boxes): def _validate_top_level(boxes):
"""Several boxes can only occur at the top level.""" """Several boxes can only occur at the top level."""
# Add the counts in the superboxes. # Add the counts in the superboxes.
for box in boxes: for box in boxes:
@ -1254,7 +1267,7 @@ def _check_top_level(boxes):
if 'dtbl' in multiples: if 'dtbl' in multiples:
raise IOError('There can only be one dtbl box in a file.') raise IOError('There can only be one dtbl box in a file.')
def _check_for_singletons(boxes): def _validate_singletons(boxes):
"""Several boxes can only occur once.""" """Several boxes can only occur once."""
count = _collect_box_count(boxes) count = _collect_box_count(boxes)
# Which boxes occur more than once? # Which boxes occur more than once?
@ -1262,7 +1275,7 @@ def _check_for_singletons(boxes):
if 'dtbl' in multiples: if 'dtbl' in multiples:
raise IOError('There can only be one dtbl box in a file.') raise IOError('There can only be one dtbl box in a file.')
def _jpx_brand(boxes, brand): def _validate_jpx_brand(boxes, brand):
""" """
If there is a JPX box then the brand must be 'jpx '. If there is a JPX box then the brand must be 'jpx '.
""" """
@ -1274,9 +1287,9 @@ def _jpx_brand(boxes, brand):
raise RuntimeError(msg) raise RuntimeError(msg)
if hasattr(box, 'box') != 0: if hasattr(box, 'box') != 0:
# Same set of checks on any child boxes. # Same set of checks on any child boxes.
_jpx_brand(box.box, brand) _validate_jpx_brand(box.box, brand)
def _jpx_compatibility(boxes, compatibility_list): def _validate_jpx_compatibility(boxes, compatibility_list):
""" """
If there is a JPX box then the compatibility list must also contain 'jpx '. If there is a JPX box then the compatibility list must also contain 'jpx '.
""" """
@ -1288,10 +1301,10 @@ def _jpx_compatibility(boxes, compatibility_list):
raise RuntimeError(msg) raise RuntimeError(msg)
if hasattr(box, 'box') != 0: if hasattr(box, 'box') != 0:
# Same set of checks on any child boxes. # Same set of checks on any child boxes.
_jpx_compatibility(box.box, compatibility_list) _validate_jpx_compatibility(box.box, compatibility_list)
def _asoc_check(boxes): def _validate_association(boxes):
""" """
Association boxes can only contain number list boxes and xml boxes, as far Association boxes can only contain number list boxes and xml boxes, as far
as we know. as we know.
@ -1304,7 +1317,7 @@ def _asoc_check(boxes):
raise RuntimeError(msg) raise RuntimeError(msg)
if hasattr(box, 'box') != 0: if hasattr(box, 'box') != 0:
# Same set of checks on any child boxes. # Same set of checks on any child boxes.
_asoc_check(box.box) _validate_association(box.box)