Added Colour group box support. #188

This commit is contained in:
jevans 2014-03-19 20:14:46 -04:00
commit cf4317df57
2 changed files with 113 additions and 0 deletions

View file

@ -754,6 +754,75 @@ class CodestreamHeaderBox(Jp2kBox):
return box
class ColourGroupBox(Jp2kBox):
"""Container for colour group 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, box=None, length=0, offset=-1):
Jp2kBox.__init__(self, box_id='cgrp', longname='Colour Group')
self.length = length
self.offset = offset
self.box = box if box is not None else []
def __repr__(self):
msg = "glymur.jp2box.ColourGroupBox(box={0})".format(self.box)
return msg
def __str__(self):
msg = self._str_superbox()
return msg
def _validate(self, writing=True):
"""Verify that the box obeys the specifications."""
if any([box.box_id != 'colr' for box in self.box]):
msg = "Colour group boxes can only contain colour specification "
msg += "boxes."
self._dispatch_validation_error(msg, writing=writing)
def write(self, fptr):
"""Write an association box to file.
"""
self._validate(writing=True)
self._write_superbox(fptr)
@staticmethod
def parse(fptr, offset, length):
"""Parse colour group box.
Parameters
----------
fptr : file
Open file object.
offset : int
Start position of box in bytes.
length : int
Length of the box in bytes.
Returns
-------
ColourGroupBox instance
"""
box = ColourGroupBox(length=length, offset=offset)
# The colour group 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.
@ -3101,6 +3170,7 @@ class UUIDBox(Jp2kBox):
_BOX_WITH_ID = {
b'asoc': AssociationBox,
b'cdef': ChannelDefinitionBox,
b'cgrp': ColourGroupBox,
b'cmap': ComponentMappingBox,
b'colr': ColourSpecificationBox,
b'dtbl': DataReferenceBox,

View file

@ -16,6 +16,7 @@ import glymur
from glymur import Jp2k
from glymur.jp2box import DataEntryURLBox, FileTypeBox, JPEG2000SignatureBox
from glymur.jp2box import DataReferenceBox, FragmentListBox, FragmentTableBox
from glymur.jp2box import ColourSpecificationBox
@unittest.skipIf(os.name == "nt", "Temporary file issue on window.")
class TestJPXWrap(unittest.TestCase):
@ -109,6 +110,48 @@ class TestJPXWrap(unittest.TestCase):
with self.assertRaises(IOError):
jp2.wrap(tfile.name, boxes=boxes)
def test_cgrp(self):
"""Write a color group box."""
jp2 = Jp2k(self.jp2file)
boxes = [jp2.box[idx] for idx in [0, 1, 2, 4]]
# The ftyp box must be modified to jpx.
boxes[1].brand = 'jpx '
boxes[1].compatibility_list = ['jp2 ', 'jpxb']
colr_rgb = ColourSpecificationBox(colorspace=glymur.core.SRGB)
colr_gr = ColourSpecificationBox(colorspace=glymur.core.GREYSCALE)
box = [colr_rgb, colr_gr]
cgrp = glymur.jp2box.ColourGroupBox(box=box)
boxes.append(cgrp)
with tempfile.NamedTemporaryFile(suffix=".jpx") as tfile:
jpx = jp2.wrap(tfile.name, boxes=boxes)
self.assertEqual(jpx.box[-1].box_id, 'cgrp')
self.assertEqual(jpx.box[-1].box[0].box_id, 'colr')
self.assertEqual(jpx.box[-1].box[1].box_id, 'colr')
def test_cgrp_neg(self):
"""Can't write a cgrp with anything but colr sub boxes"""
jp2 = Jp2k(self.jp2file)
boxes = [jp2.box[idx] for idx in [0, 1, 2, 4]]
# The ftyp box must be modified to jpx.
boxes[1].brand = 'jpx '
boxes[1].compatibility_list = ['jp2 ', 'jpxb']
lblb = glymur.jp2box.LabelBox("Just a test")
box = [lblb]
cgrp = glymur.jp2box.ColourGroupBox(box=box)
boxes.append(cgrp)
with tempfile.NamedTemporaryFile(suffix=".jpx") as tfile:
with self.assertRaises(IOError):
jpx = jp2.wrap(tfile.name, boxes=boxes)
def test_ftbl(self):
"""Write a fragment table box."""
# Add a negative test where offset < 0