Merge branch 'issue84' into devel

This commit is contained in:
John Evans 2013-07-24 12:03:29 -04:00
commit 181b31ff94
5 changed files with 232 additions and 18 deletions

View file

@ -6,7 +6,6 @@ from .jp2k import Jp2k
from .jp2dump import jp2dump
from . import data
#from . import test
def runtests():

View file

@ -520,6 +520,195 @@ class ChannelDefinitionBox(Jp2kBox):
return box
class CodestreamHeaderBox(Jp2kBox):
"""Container for codestream header 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.
box : list
List of boxes contained in this superbox.
"""
def __init__(self, length=0, offset=-1):
Jp2kBox.__init__(self, box_id='jpch', longname='Codestream Header')
self.length = length
self.offset = offset
self.box = []
def __str__(self):
msg = Jp2kBox.__str__(self)
for box in self.box:
boxstr = str(box)
# Add indentation.
strs = [('\n ' + x) for x in boxstr.split('\n')]
msg += ''.join(strs)
return msg
@staticmethod
def parse(fptr, offset, length):
"""Parse codestream header box.
Parameters
----------
fptr : file
Open file object.
offset : int
Start position of box in bytes.
length : int
Length of the box in bytes.
Returns
-------
AssociationBox instance
"""
box = CodestreamHeaderBox(length=length, offset=offset)
# The codestream header box is a superbox, so go ahead and parse its
# child boxes.
box.box = box.parse_superbox(fptr)
return box
class CompositingLayerHeaderBox(Jp2kBox):
"""Container for compositing layer header 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.
box : list
List of boxes contained in this superbox.
"""
def __init__(self, length=0, offset=-1):
Jp2kBox.__init__(self, box_id='jplh',
longname='Compositing Layer Header')
self.length = length
self.offset = offset
self.box = []
def __str__(self):
msg = Jp2kBox.__str__(self)
for box in self.box:
boxstr = str(box)
# Add indentation.
strs = [('\n ' + x) for x in boxstr.split('\n')]
msg += ''.join(strs)
return msg
@staticmethod
def parse(fptr, offset, length):
"""Parse compositing layer header box.
Parameters
----------
fptr : file
Open file object.
offset : int
Start position of box in bytes.
length : int
Length of the box in bytes.
Returns
-------
AssociationBox instance
"""
box = CompositingLayerHeaderBox(length=length, offset=offset)
# This box is a superbox, so go ahead and parse its # child boxes.
box.box = box.parse_superbox(fptr)
return box
class JP2HeaderBox(Jp2kBox):
"""Container for JP2 header 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.
box : list
List of boxes contained in this superbox.
"""
def __init__(self, length=0, offset=-1):
Jp2kBox.__init__(self, box_id='jp2h', longname='JP2 Header')
self.length = length
self.offset = offset
self.box = []
def __str__(self):
msg = Jp2kBox.__str__(self)
for box in self.box:
boxstr = str(box)
# Add indentation.
strs = [('\n ' + x) for x in boxstr.split('\n')]
msg += ''.join(strs)
return msg
def write(self, fptr):
"""Write a JP2 Header box to file.
"""
# Write the contained boxes, then come back and write the length.
orig_pos = fptr.tell()
fptr.write(struct.pack('>I', 0))
fptr.write('jp2h'.encode())
for box in self.box:
box.write(fptr)
end_pos = fptr.tell()
fptr.seek(orig_pos)
fptr.write(struct.pack('>I', end_pos - orig_pos))
fptr.seek(end_pos)
@staticmethod
def parse(fptr, offset, length):
"""Parse JPEG 2000 header box.
Parameters
----------
fptr : file
Open file object.
offset : int
Start position of box in bytes.
length : int
Length of the box in bytes.
Returns
-------
JP2HeaderBox instance
"""
box = JP2HeaderBox(length=length, offset=offset)
# The JP2 header box is a superbox, so go ahead and parse its child
# boxes.
box.box = box.parse_superbox(fptr)
return box
class ComponentMappingBox(Jp2kBox):
"""Container for channel identification information.
@ -2509,11 +2698,13 @@ _BOX_WITH_ID = {
'cdef': ChannelDefinitionBox,
'cmap': ComponentMappingBox,
'colr': ColourSpecificationBox,
'jP ': JPEG2000SignatureBox,
'ftyp': FileTypeBox,
'ihdr': ImageHeaderBox,
'jp2h': JP2HeaderBox,
'jP ': JPEG2000SignatureBox,
'jpch': CodestreamHeaderBox,
'jplh': CompositingLayerHeaderBox,
'jp2c': ContiguousCodestreamBox,
'jp2h': JP2HeaderBox,
'lbl ': LabelBox,
'pclr': PaletteBox,
'res ': ResolutionBox,

View file

@ -1,11 +0,0 @@
from .test_callbacks import TestCallbacks as callbacks
from .test_codestream import TestCodestream as codestream
from .test_config import TestSuite as config
from .test_jp2k import TestJp2k as jp2k
from .test_icc import TestICC as icc
from .test_printing import TestPrinting as printing
from .test_opj_suite import TestSuite as suite
from .test_opj_suite import TestSuiteDump as suitedump
from .test_opj_suite_write import TestSuiteWrite as suitew
from .test_opj_suite_neg import TestSuiteNegative as suiteneg
from .test_jp2box import TestJp2Boxes as box

View file

@ -20,15 +20,11 @@ try:
format_corpus_data_root = os.environ['FORMAT_CORPUS_DATA_ROOT']
except KeyError:
format_corpus_data_root = None
except:
raise
try:
opj_data_root = os.environ['OPJ_DATA_ROOT']
except KeyError:
opj_data_root = None
except:
raise
@unittest.skipIf(format_corpus_data_root is None,

View file

@ -19,6 +19,11 @@ from glymur.jp2box import *
from glymur.core import COLOR, OPACITY
from glymur.core import RED, GREEN, BLUE, GREY, WHOLE_IMAGE
try:
format_corpus_data_root = os.environ['FORMAT_CORPUS_DATA_ROOT']
except KeyError:
format_corpus_data_root = None
# Doc tests should be run as well.
def load_tests(loader, tests, ignore):
@ -673,5 +678,39 @@ class TestJp2Boxes(unittest.TestCase):
with self.assertRaises(IOError):
j2k.wrap(tfile.name, boxes=boxes)
class TestJpxBoxes(unittest.TestCase):
def setUp(self):
pass
def tearDown(self):
pass
@unittest.skipIf(format_corpus_data_root is None,
"FORMAT_CORPUS_DATA_ROOT environment variable not set")
def test_codestream_header(self):
# Should recognize codestream header box.
jfile = os.path.join(format_corpus_data_root,
'jp2k-formats/balloon.jpf')
jpx = Jp2k(jfile)
# This superbox just happens to be empty.
self.assertEqual(jpx.box[4].box_id, 'jpch')
self.assertEqual(len(jpx.box[4].box), 0)
@unittest.skipIf(format_corpus_data_root is None,
"FORMAT_CORPUS_DATA_ROOT environment variable not set")
def test_compositing_layer_header(self):
# Should recognize compositing layer header box.
jfile = os.path.join(format_corpus_data_root,
'jp2k-formats/balloon.jpf')
jpx = Jp2k(jfile)
# This superbox just happens to be empty.
self.assertEqual(jpx.box[5].box_id, 'jplh')
self.assertEqual(len(jpx.box[5].box), 0)
if __name__ == "__main__":
unittest.main()