box_id and longname are class attributes now instead of instance attributes

Some simplification of the individual box constructors, and a palette box
error message became a bit more clear because of this.
This commit is contained in:
jevans 2014-09-23 20:00:47 -04:00
commit 9bebd6438c
3 changed files with 119 additions and 50 deletions

View file

@ -62,17 +62,13 @@ class Jp2kBox(object):
length of the box in bytes.
offset : int
offset of the box from the start of the file.
longname : str
more verbose description of the box.
box : list
List of JPEG 2000 boxes.
"""
def __init__(self, box_id='', offset=0, length=0, longname=''):
self.box_id = box_id
def __init__(self, offset=0, length=0):
self.length = length
self.offset = offset
self.longname = longname
self.box = []
def __repr__(self):
@ -197,7 +193,7 @@ class Jp2kBox(object):
msg = "Encountered an unrecoverable ValueError while parsing a {0} "
msg += "box at byte offset {1}. The original error message was "
msg += "\"{2}\""
msg = msg.format(box_id.decode('utf-8'), start, str(err))
msg = msg.format(_BOX_WITH_ID[box_id].longname, start, str(err))
warnings.warn(msg, UserWarning)
box = UnknownBox(box_id.decode('utf-8'),
length=num_bytes, offset=start, longname='Unknown')
@ -300,11 +296,12 @@ class ColourSpecificationBox(Jp2kBox):
ICC profile header according to ICC profile specification. If
colorspace is not None, then icc_profile must be empty.
"""
longname = 'Colour Specification'
box_id = 'colr'
def __init__(self, method=ENUMERATED_COLORSPACE, precedence=0,
approximation=0, colorspace=None, icc_profile=None,
length=0, offset=-1):
Jp2kBox.__init__(self, box_id='colr', longname='Colour Specification')
Jp2kBox.__init__(self)
self.method = method
self.precedence = precedence
@ -588,8 +585,11 @@ class ChannelDefinitionBox(Jp2kBox):
association : list
index of the associated color
"""
box_id = 'cdef'
longname = 'Channel Definition'
def __init__(self, channel_type, association, index=None, **kwargs):
Jp2kBox.__init__(self, box_id='cdef', longname='Channel Definition')
Jp2kBox.__init__(self)
if index is None:
self.index = tuple(range(len(channel_type)))
@ -704,8 +704,11 @@ class CodestreamHeaderBox(Jp2kBox):
box : list
List of boxes contained in this superbox.
"""
box_id = 'jpch'
longname = 'Codestream Header'
def __init__(self, box=None, length=0, offset=-1):
Jp2kBox.__init__(self, box_id='jpch', longname='Codestream Header')
Jp2kBox.__init__(self)
self.length = length
self.offset = offset
self.box = box if box is not None else []
@ -765,8 +768,11 @@ class ColourGroupBox(Jp2kBox):
box : list
List of boxes contained in this superbox.
"""
box_id = 'cgrp'
longname = 'Colour Group'
def __init__(self, box=None, length=0, offset=-1):
Jp2kBox.__init__(self, box_id='cgrp', longname='Colour Group')
Jp2kBox.__init__(self)
self.length = length
self.offset = offset
self.box = box if box is not None else []
@ -834,9 +840,11 @@ class CompositingLayerHeaderBox(Jp2kBox):
box : list
List of boxes contained in this superbox.
"""
box_id = 'jplh'
longname='Compositing Layer Header'
def __init__(self, box=None, length=0, offset=-1):
Jp2kBox.__init__(self, box_id='jplh',
longname='Compositing Layer Header')
Jp2kBox.__init__(self)
self.length = length
self.offset = offset
self.box = box if box is not None else []
@ -900,9 +908,12 @@ class ComponentMappingBox(Jp2kBox):
palette_index : tuple
Index component from palette
"""
box_id = 'cmap'
longname = 'Component Mapping'
def __init__(self, component_index, mapping_type, palette_index,
length=0, offset=-1):
Jp2kBox.__init__(self, box_id='cmap', longname='Component Mapping')
Jp2kBox.__init__(self)
self.component_index = component_index
self.mapping_type = mapping_type
self.palette_index = palette_index
@ -995,9 +1006,12 @@ class ContiguousCodestreamBox(Jp2kBox):
main_header_offset : int
offset of main header from start of file
"""
box_id = 'jp2c'
longname = 'Contiguous Codestream'
def __init__(self, main_header=None, main_header_offset=None, length=0,
offset=-1):
Jp2kBox.__init__(self, box_id='jp2c', longname='Contiguous Codestream')
Jp2kBox.__init__(self)
self._main_header = main_header
self.length = length
self.offset = offset
@ -1078,8 +1092,11 @@ class DataReferenceBox(Jp2kBox):
DR : list
Data Entry URL boxes.
"""
box_id = 'dtbl'
longname = 'Data Reference'
def __init__(self, data_entry_url_boxes=None, length=0, offset=-1):
Jp2kBox.__init__(self, box_id='dtbl', longname='Data Reference')
Jp2kBox.__init__(self)
if data_entry_url_boxes is None:
self.DR = []
else:
@ -1205,9 +1222,12 @@ class FileTypeBox(Jp2kBox):
compatibility_list: list
List of file conformance profiles.
"""
box_id = 'ftyp'
longname = 'File Type'
def __init__(self, brand='jp2 ', minor_version=0,
compatibility_list=None, length=0, offset=-1):
Jp2kBox.__init__(self, box_id='ftyp', longname='File Type')
Jp2kBox.__init__(self)
self.brand = brand
self.minor_version = minor_version
if compatibility_list is None:
@ -1317,9 +1337,12 @@ class FragmentListBox(Jp2kBox):
longname : str
more verbose description of the box.
"""
box_id = 'flst'
longname = 'Fragment List'
def __init__(self, fragment_offset, fragment_length, data_reference,
length=0, offset=-1):
Jp2kBox.__init__(self, box_id='flst', longname='Fragment List')
Jp2kBox.__init__(self)
self.fragment_offset = fragment_offset
self.fragment_length = fragment_length
self.data_reference = data_reference
@ -1423,8 +1446,11 @@ class FragmentTableBox(Jp2kBox):
longname : str
more verbose description of the box.
"""
box_id = 'ftbl'
longname = 'Fragment Table'
def __init__(self, box=None, length=0, offset=-1):
Jp2kBox.__init__(self, box_id='ftbl', longname='Fragment Table')
Jp2kBox.__init__(self)
self.length = length
self.offset = offset
self.box = box if box is not None else []
@ -1493,8 +1519,11 @@ class FreeBox(Jp2kBox):
longname : str
more verbose description of the box.
"""
box_id = 'free'
longname = 'Free'
def __init__(self, length=0, offset=-1):
Jp2kBox.__init__(self, box_id='free', longname='Free')
Jp2kBox.__init__(self)
self.length = length
self.offset = offset
@ -1558,6 +1587,9 @@ class ImageHeaderBox(Jp2kBox):
False if the file does not contain intellectual propery rights
information.
"""
box_id = 'ihdr'
longname = 'Image Header'
def __init__(self, height, width, num_components=1, signed=False,
bits_per_component=8, compression=7, colorspace_unknown=False,
ip_provided=False, length=0, offset=-1):
@ -1567,7 +1599,7 @@ class ImageHeaderBox(Jp2kBox):
>>> import glymur
>>> box = glymur.jp2box.ImageHeaderBox(height=512, width=256)
"""
Jp2kBox.__init__(self, box_id='ihdr', longname='Image Header')
Jp2kBox.__init__(self)
self.height = height
self.width = width
self.num_components = num_components
@ -1686,8 +1718,11 @@ class AssociationBox(Jp2kBox):
box : list
List of boxes contained in this superbox.
"""
box_id = 'asoc'
longname = 'Association'
def __init__(self, box=None, length=0, offset=-1):
Jp2kBox.__init__(self, box_id='asoc', longname='Association')
Jp2kBox.__init__(self)
self.length = length
self.offset = offset
self.box = box if box is not None else []
@ -1747,8 +1782,11 @@ class JP2HeaderBox(Jp2kBox):
box : list
List of boxes contained in this superbox.
"""
box_id = 'jp2h'
longname = 'JP2 Header'
def __init__(self, box=None, length=0, offset=-1):
Jp2kBox.__init__(self, box_id='jp2h', longname='JP2 Header')
Jp2kBox.__init__(self)
self.length = length
self.offset = offset
self.box = box if box is not None else []
@ -1808,8 +1846,11 @@ class JPEG2000SignatureBox(Jp2kBox):
signature : tuple
Four-byte tuple identifying the file as JPEG 2000.
"""
box_id = 'jP '
longname = 'JPEG 2000 Signature'
def __init__(self, signature=(13, 10, 135, 10), length=0, offset=-1):
Jp2kBox.__init__(self, box_id='jP ', longname='JPEG 2000 Signature')
Jp2kBox.__init__(self)
self.signature = signature
self.length = length
self.offset = offset
@ -1872,9 +1913,12 @@ class PaletteBox(Jp2kBox):
palette : ndarray
Colormap array.
"""
longname = 'Palette'
box_id = 'pclr'
def __init__(self, palette, bits_per_component, signed, length=0,
offset=-1):
Jp2kBox.__init__(self, box_id='pclr', longname='Palette')
Jp2kBox.__init__(self)
self.palette = palette
self.bits_per_component = bits_per_component
self.signed = signed
@ -2129,9 +2173,12 @@ class ReaderRequirementsBox(Jp2kBox):
Specifies the compatibility mask for each corresponding vendor
feature.
"""
box_id = 'rreq'
longname = 'Reader Requirements'
def __init__(self, fuam, dcm, standard_flag, standard_mask, vendor_feature,
vendor_mask, length=0, offset=-1):
Jp2kBox.__init__(self, box_id='rreq', longname='Reader Requirements')
Jp2kBox.__init__(self)
self.fuam = fuam
self.dcm = dcm
self.standard_flag = tuple(standard_flag)
@ -2368,8 +2415,11 @@ class ResolutionBox(Jp2kBox):
box : list
List of boxes contained in this superbox.
"""
box_id = 'res '
longname = 'Resolution'
def __init__(self, box=None, length=0, offset=-1):
Jp2kBox.__init__(self, box_id='res ', longname='Resolution')
Jp2kBox.__init__(self)
self.length = length
self.offset = offset
self.box = box if box is not None else []
@ -2425,9 +2475,12 @@ class CaptureResolutionBox(Jp2kBox):
vertical_resolution, horizontal_resolution : float
Vertical, horizontal resolution.
"""
box_id = 'resc'
longname = 'Capture Resolution'
def __init__(self, vertical_resolution, horizontal_resolution, length=0,
offset=-1):
Jp2kBox.__init__(self, box_id='resc', longname='Capture Resolution')
Jp2kBox.__init__(self)
self.vertical_resolution = vertical_resolution
self.horizontal_resolution = horizontal_resolution
self.length = length
@ -2488,9 +2541,12 @@ class DisplayResolutionBox(Jp2kBox):
vertical_resolution, horizontal_resolution : float
Vertical, horizontal resolution.
"""
box_id = 'resd'
longname = 'Display Resolution'
def __init__(self, vertical_resolution, horizontal_resolution,
length=0, offset=-1):
Jp2kBox.__init__(self, box_id='resd', longname='Display Resolution')
Jp2kBox.__init__(self)
self.vertical_resolution = vertical_resolution
self.horizontal_resolution = horizontal_resolution
self.length = length
@ -2552,8 +2608,11 @@ class LabelBox(Jp2kBox):
label : str
Textual label.
"""
box_id = 'lbl '
longname = 'Label'
def __init__(self, label, length=0, offset=-1):
Jp2kBox.__init__(self, box_id='lbl ', longname='Label')
Jp2kBox.__init__(self)
self.label = label
self.length = length
self.offset = offset
@ -2617,8 +2676,11 @@ class NumberListBox(Jp2kBox):
Descriptors of an entity with which the data contained within the same
Association box is associated.
"""
box_id = 'nlst'
longname = 'Number List'
def __init__(self, associations, length=0, offset=-1):
Jp2kBox.__init__(self, box_id='nlst', longname='Number List')
Jp2kBox.__init__(self)
self.associations = associations
self.length = length
self.offset = offset
@ -2698,6 +2760,9 @@ class XMLBox(Jp2kBox):
xml : ElementTree object
XML section.
"""
box_id = 'xml '
longname = 'XML'
def __init__(self, xml=None, filename=None, length=0, offset=-1):
"""
Parameters
@ -2708,7 +2773,7 @@ class XMLBox(Jp2kBox):
File from which to read XML. If filename is not None, then the xml
keyword argument must be None.
"""
Jp2kBox.__init__(self, box_id='xml ', longname='XML')
Jp2kBox.__init__(self)
if filename is not None and xml is not None:
msg = "Only one of either filename or xml should be provided."
raise IOError(msg)
@ -2830,8 +2895,11 @@ class UUIDListBox(Jp2kBox):
ulst : list
List of UUIDs.
"""
box_id = 'ulst'
longname = 'UUID List'
def __init__(self, ulst, length=0, offset=-1):
Jp2kBox.__init__(self, box_id='ulst', longname='UUID List')
Jp2kBox.__init__(self)
self.ulst = ulst
self.length = length
self.offset = offset
@ -2895,8 +2963,11 @@ class UUIDInfoBox(Jp2kBox):
box : list
List of boxes contained in this superbox.
"""
box_id = 'uinf'
longname = 'UUIDInfo'
def __init__(self, box=None, length=0, offset=-1):
Jp2kBox.__init__(self, box_id='uinf', longname='UUIDInfo')
Jp2kBox.__init__(self)
self.length = length
self.offset = offset
self.box = box if box is not None else []
@ -2956,8 +3027,11 @@ class DataEntryURLBox(Jp2kBox):
URL : str
Associated URL.
"""
box_id = 'url '
longname = 'Data Entry URL'
def __init__(self, version, flag, url, length=0, offset=-1):
Jp2kBox.__init__(self, box_id='url ', longname='Data Entry URL')
Jp2kBox.__init__(self)
self.version = version
self.flag = flag
self.url = url
@ -3045,7 +3119,9 @@ class UnknownBox(Jp2kBox):
more verbose description of the box.
"""
def __init__(self, box_id, length=0, offset=-1, longname=''):
Jp2kBox.__init__(self, box_id=box_id, longname=longname)
Jp2kBox.__init__(self)
self.longname = longname
self.box_id = box_id
self.length = length
self.offset = offset
@ -3089,6 +3165,9 @@ class UUIDBox(Jp2kBox):
16684-1:2012 - Graphic technology -- Extensible metadata platform (XMP)
specification -- Part 1: Data model, serialization and core properties
"""
box_id = 'uuid'
longname = 'UUID'
def __init__(self, the_uuid, raw_data, length=0, offset=-1):
"""
Parameters
@ -3102,7 +3181,7 @@ class UUIDBox(Jp2kBox):
offset : int
offset of the box from the start of the file.
"""
Jp2kBox.__init__(self, box_id='uuid', longname='UUID')
Jp2kBox.__init__(self)
self.uuid = the_uuid
self.raw_data = raw_data
self.length = length

View file

@ -40,9 +40,9 @@ class TestWarnings(unittest.TestCase):
infile = os.path.join(OPJ_DATA_ROOT,
'input/nonregression/mem-b2ace68c-1381.jp2')
regex = re.compile(r'''Encountered\san\sunrecoverable\sValueError\s
while\sparsing\sa\spclr\sbox\sat\sbyte\soffset\s
\d+\.\s+The\soriginal\serror\smessage\swas\s
"total\ssize\sof\snew\sarray\smust\sbe\s
while\sparsing\sa\sPalette\sbox\sat\sbyte\s
offset\s\d+\.\s+The\soriginal\serror\smessage\s
was\s"total\ssize\sof\snew\sarray\smust\sbe\s
unchanged"''',
re.VERBOSE)
with self.assertWarnsRegex(UserWarning, regex):

View file

@ -1246,16 +1246,6 @@ class TestRepr(MetadataBase):
self.assertEqual(newbox.ulst[0], uuid1)
self.assertEqual(newbox.ulst[1], uuid2)
def test_jp2k_box(self):
"""Verify Superclass repr."""
box = glymur.jp2box.Jp2kBox(box_id='one', offset=2, length=3,
longname='four')
newbox = eval(repr(box))
self.assertEqual(newbox.box_id, 'one')
self.assertEqual(newbox.offset, 2)
self.assertEqual(newbox.length, 3)
self.assertEqual(newbox.longname, 'four')
def test_palette_box(self):
"""Verify Palette box repr."""
palette = np.array([[255, 0, 1000], [0, 255, 0]], dtype=np.int32)