Added support for Data Reference box.
This commit is contained in:
parent
dfa1fce072
commit
1e43cb32cb
4 changed files with 108 additions and 7 deletions
|
|
@ -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.
|
|
@ -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,
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue