Added support for Data Reference box.

This commit is contained in:
jevans 2014-02-01 15:42:13 -05:00
commit 1e43cb32cb
4 changed files with 108 additions and 7 deletions

View file

@ -1,6 +1,6 @@
Jan 29, 2014 - Added read support for JPX FreeBox, NumberListBox. Palette box
now a 2D numpy array instead of a list of 1D arrays. JP2 super box
constructors now take optional box list argument.
Feb 01, 2014 - Added read support for JPX FreeBox, NumberListBox, Data Reference
Box. Palette box now a 2D numpy array instead of a list of 1D arrays.
JP2 super box constructors now take optional box list argument.
Jan 28, 2014 - v0.5.10 Fixed bad warning when reader requirements box mask
length is unsupported.

Binary file not shown.

View file

@ -811,6 +811,75 @@ class ContiguousCodestreamBox(Jp2kBox):
return box
class DataReferenceBox(Jp2kBox):
"""Container for Data Reference box information.
Attributes
----------
box_id : str
4-character identifier for the box.
length : int
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.
DR : list
Data Entry URL boxes.
"""
def __init__(self, data_entry_url_boxes, length=0, offset=-1):
Jp2kBox.__init__(self, box_id='dtbl', longname='Data Reference')
self.DR = data_entry_url_boxes
self.length = length
self.offset = offset
def __str__(self):
msg = Jp2kBox.__str__(self)
for box in enumerate(self.DR):
msg += '\n ' + str(box)
return msg
def __repr__(self):
msg = 'glymur.jp2box.DataReferenceBox()'
return msg
@staticmethod
def parse(fptr, offset, length):
"""Parse Label box.
Parameters
----------
fptr : file
Open file object.
offset : int
Start position of box in bytes.
length : int
Length of the box in bytes.
Returns
-------
DataReferenceBox instance
"""
# Read the number of data references
read_buffer = fptr.read(2)
ndr, = struct.unpack('>H', read_buffer)
# Read each data entry url box.
data_entry_url_box_list = []
for _ in range(ndr):
start = fptr.tell()
read_buffer = fptr.read(8)
(box_length, box_id) = struct.unpack('>I4s', read_buffer)
if sys.hexversion >= 0x03000000:
box_id = box_id.decode('utf-8')
box = DataEntryURLBox.parse(fptr, start, box_length)
data_entry_url_box_list.append(box)
return DataReferenceBox(data_entry_url_box_list,
length=length, offset=offset)
class FileTypeBox(Jp2kBox):
"""Container for JPEG 2000 file type box information.
@ -2922,6 +2991,7 @@ _BOX_WITH_ID = {
'cdef': ChannelDefinitionBox,
'cmap': ComponentMappingBox,
'colr': ColourSpecificationBox,
'dtbl': DataReferenceBox,
'ftyp': FileTypeBox,
'ihdr': ImageHeaderBox,
'jP ': JPEG2000SignatureBox,

View file

@ -8,7 +8,6 @@ import struct
import sys
import tempfile
import warnings
import xml.etree.cElementTree as ET
if sys.hexversion < 0x02070000:
import unittest2 as unittest
@ -17,7 +16,6 @@ else:
import glymur
from glymur import Jp2k
from glymur.jp2box import ReaderRequirementsBox
@unittest.skipIf(sys.hexversion < 0x03000000, "Warning assert on 2.x.")
@ -27,7 +25,6 @@ class TestJPXOther(unittest.TestCase):
def setUp(self):
self.jpxfile = glymur.data.jpxfile()
pass
def tearDown(self):
pass
@ -51,6 +48,40 @@ class TestJPXOther(unittest.TestCase):
self.assertEqual(j.box[16].box[0].box_id, 'free')
self.assertEqual(type(j.box[16].box[0]), glymur.jp2box.FreeBox)
def test_dtbl(self):
"""Verify that we can interpret Data Reference boxes."""
# Copy the existing JPX file, add a data reference box onto the end.
with tempfile.NamedTemporaryFile(suffix='.jpx') as tfile:
with open(self.jpxfile, 'rb') as ifile:
tfile.write(ifile.read())
write_buffer = struct.pack('>I4s', 50, b'dtbl')
tfile.write(write_buffer)
# Just two boxes.
write_buffer = struct.pack('>H', 2)
tfile.write(write_buffer)
# First data entry url box.
write_buffer = struct.pack('>I4s', 20, b'url ')
tfile.write(write_buffer)
write_buffer = struct.pack('>BBBB8s', 0, 0, 0, 0, b'file:///')
tfile.write(write_buffer)
# Second data entry url box.
write_buffer = struct.pack('>I4s', 20, b'url ')
tfile.write(write_buffer)
write_buffer = struct.pack('>BBBB8s', 0, 0, 0, 0, b'file:///')
tfile.write(write_buffer)
tfile.flush()
with self.assertWarns(UserWarning):
jpx = Jp2k(tfile.name)
self.assertEqual(jpx.box[-1].box_id, 'dtbl')
self.assertEqual(len(jpx.box[-1].DR), 2)
def test_nlst(self):
"""Verify that we can handle a free box."""
with warnings.catch_warnings():
@ -60,7 +91,7 @@ class TestJPXOther(unittest.TestCase):
self.assertEqual(j.box[16].box[1].box[0].box_id, 'nlst')
self.assertEqual(type(j.box[16].box[1].box[0]),
glymur.jp2box.NumberListBox)
# Two associations.
self.assertEqual(len(j.box[16].box[1].box[0].associations), 2)