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
|
Feb 01, 2014 - Added read support for JPX FreeBox, NumberListBox, Data Reference
|
||||||
now a 2D numpy array instead of a list of 1D arrays. JP2 super box
|
Box. Palette box now a 2D numpy array instead of a list of 1D arrays.
|
||||||
constructors now take optional box list argument.
|
JP2 super box constructors now take optional box list argument.
|
||||||
|
|
||||||
Jan 28, 2014 - v0.5.10 Fixed bad warning when reader requirements box mask
|
Jan 28, 2014 - v0.5.10 Fixed bad warning when reader requirements box mask
|
||||||
length is unsupported.
|
length is unsupported.
|
||||||
|
|
|
||||||
Binary file not shown.
|
|
@ -811,6 +811,75 @@ class ContiguousCodestreamBox(Jp2kBox):
|
||||||
return box
|
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):
|
class FileTypeBox(Jp2kBox):
|
||||||
"""Container for JPEG 2000 file type box information.
|
"""Container for JPEG 2000 file type box information.
|
||||||
|
|
||||||
|
|
@ -2922,6 +2991,7 @@ _BOX_WITH_ID = {
|
||||||
'cdef': ChannelDefinitionBox,
|
'cdef': ChannelDefinitionBox,
|
||||||
'cmap': ComponentMappingBox,
|
'cmap': ComponentMappingBox,
|
||||||
'colr': ColourSpecificationBox,
|
'colr': ColourSpecificationBox,
|
||||||
|
'dtbl': DataReferenceBox,
|
||||||
'ftyp': FileTypeBox,
|
'ftyp': FileTypeBox,
|
||||||
'ihdr': ImageHeaderBox,
|
'ihdr': ImageHeaderBox,
|
||||||
'jP ': JPEG2000SignatureBox,
|
'jP ': JPEG2000SignatureBox,
|
||||||
|
|
|
||||||
|
|
@ -8,7 +8,6 @@ import struct
|
||||||
import sys
|
import sys
|
||||||
import tempfile
|
import tempfile
|
||||||
import warnings
|
import warnings
|
||||||
import xml.etree.cElementTree as ET
|
|
||||||
|
|
||||||
if sys.hexversion < 0x02070000:
|
if sys.hexversion < 0x02070000:
|
||||||
import unittest2 as unittest
|
import unittest2 as unittest
|
||||||
|
|
@ -17,7 +16,6 @@ else:
|
||||||
|
|
||||||
import glymur
|
import glymur
|
||||||
from glymur import Jp2k
|
from glymur import Jp2k
|
||||||
from glymur.jp2box import ReaderRequirementsBox
|
|
||||||
|
|
||||||
|
|
||||||
@unittest.skipIf(sys.hexversion < 0x03000000, "Warning assert on 2.x.")
|
@unittest.skipIf(sys.hexversion < 0x03000000, "Warning assert on 2.x.")
|
||||||
|
|
@ -27,7 +25,6 @@ class TestJPXOther(unittest.TestCase):
|
||||||
|
|
||||||
def setUp(self):
|
def setUp(self):
|
||||||
self.jpxfile = glymur.data.jpxfile()
|
self.jpxfile = glymur.data.jpxfile()
|
||||||
pass
|
|
||||||
|
|
||||||
def tearDown(self):
|
def tearDown(self):
|
||||||
pass
|
pass
|
||||||
|
|
@ -51,6 +48,40 @@ class TestJPXOther(unittest.TestCase):
|
||||||
self.assertEqual(j.box[16].box[0].box_id, 'free')
|
self.assertEqual(j.box[16].box[0].box_id, 'free')
|
||||||
self.assertEqual(type(j.box[16].box[0]), glymur.jp2box.FreeBox)
|
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):
|
def test_nlst(self):
|
||||||
"""Verify that we can handle a free box."""
|
"""Verify that we can handle a free box."""
|
||||||
with warnings.catch_warnings():
|
with warnings.catch_warnings():
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue