Added cdef write support.

This commit is contained in:
jevans 2013-06-26 19:37:43 -04:00
commit 028b297285
3 changed files with 125 additions and 2 deletions

View file

@ -444,6 +444,19 @@ class ChannelDefinitionBox(Jp2kBox):
msg = msg.format(self.index[j], color_type_string, assn)
return msg
def _write(self, f):
"""Write a channel definition box to file.
"""
N = len(self.association)
f.write(struct.pack('>I', 8 + 2 + N * 6))
f.write('cdef'.encode('utf-8'))
f.write(struct.pack('>H', N))
for j in range(N):
f.write(struct.pack('>' + 'H' * 3,
self.index[j],
self.channel_type[j],
self.association[j]))
@staticmethod
def _parse(f, id, offset, length):
"""Parse component definition box.

View file

@ -19,6 +19,36 @@ def load_tests(loader, tests, ignore):
class TestChannelDefinition(unittest.TestCase):
@classmethod
def setUpClass(cls):
"""Need a one_plane plane image for greyscale testing."""
j2k = Jp2k(glymur.data.goodstuff())
data = j2k.read()
# Write the first component back out to file.
with tempfile.NamedTemporaryFile(suffix=".j2k", delete=False) as tfile:
grey_j2k = Jp2k(tfile.name, 'wb')
grey_j2k.write(data[:,:,0])
cls.one_plane = tfile.name
# Write the first two components back out to file.
with tempfile.NamedTemporaryFile(suffix=".j2k", delete=False) as tfile:
grey_j2k = Jp2k(tfile.name, 'wb')
grey_j2k.write(data[:,:,0:1])
cls.two_planes = tfile.name
# Write four components back out to file.
with tempfile.NamedTemporaryFile(suffix=".j2k", delete=False) as tfile:
rgba_jp2 = Jp2k(tfile.name, 'wb')
shape = (data.shape[0], data.shape[1], 1)
alpha = np.zeros((shape), dtype=data.dtype)
data4 = np.concatenate((data, alpha), axis=2)
rgba_jp2.write(data4)
cls.four_planes = tfile.name
@classmethod
def tearDownClass(cls):
os.unlink(cls.one_plane)
os.unlink(cls.two_planes)
os.unlink(cls.four_planes)
def setUp(self):
self.jp2file = glymur.data.nemo()
self.j2kfile = glymur.data.goodstuff()
@ -36,10 +66,91 @@ class TestChannelDefinition(unittest.TestCase):
self.ihdr = ImageHeaderBox(height=height, width=width,
num_components=num_components)
self.colr_rgb = ColourSpecificationBox(colorspace=glymur.core.SRGB)
self.colr_gr = ColourSpecificationBox(colorspace=glymur.core.GREYSCALE)
def tearDown(self):
pass
def test_rgb(self):
"""Just regular RGB."""
j2k = Jp2k(self.j2kfile)
cdef = glymur.jp2box.ChannelDefinitionBox(index=[0, 1, 2],
channel_type=[0, 0, 0],
association=[1, 2, 3])
boxes = [self.ihdr, self.colr_rgb, cdef]
self.jp2h.box = boxes
boxes = [self.jP, self.ftyp, self.jp2h, self.jp2c]
with tempfile.NamedTemporaryFile(suffix=".jp2") as tfile:
j2k.wrap(tfile.name, boxes=boxes)
jp2 = Jp2k(tfile.name)
jp2h = jp2.box[2]
boxes = [box.id for box in jp2h.box]
self.assertEqual(boxes, ['ihdr', 'colr', 'cdef'])
self.assertEqual(jp2h.box[2].index, (0, 1, 2))
self.assertEqual(jp2h.box[2].channel_type, (0, 0, 0))
self.assertEqual(jp2h.box[2].association, (1, 2, 3))
def test_rgba(self):
"""Just regular RGBA."""
j2k = Jp2k(self.four_planes)
cdef = glymur.jp2box.ChannelDefinitionBox(index=[0, 1, 2, 3],
channel_type=[0, 0, 0, 1],
association=[1, 2, 3, 0])
boxes = [self.ihdr, self.colr_rgb, cdef]
self.jp2h.box = boxes
boxes = [self.jP, self.ftyp, self.jp2h, self.jp2c]
with tempfile.NamedTemporaryFile(suffix=".jp2") as tfile:
j2k.wrap(tfile.name, boxes=boxes)
jp2 = Jp2k(tfile.name)
jp2h = jp2.box[2]
boxes = [box.id for box in jp2h.box]
self.assertEqual(boxes, ['ihdr', 'colr', 'cdef'])
self.assertEqual(jp2h.box[2].index, (0, 1, 2, 3))
self.assertEqual(jp2h.box[2].channel_type, (0, 0, 0, 1))
self.assertEqual(jp2h.box[2].association, (1, 2, 3, 0))
def test_grey(self):
"""Just regular greyscale."""
j2k = Jp2k(self.one_plane)
cdef = glymur.jp2box.ChannelDefinitionBox(index=[0],
channel_type=[0],
association=[1])
boxes = [self.ihdr, self.colr_gr, cdef]
self.jp2h.box = boxes
boxes = [self.jP, self.ftyp, self.jp2h, self.jp2c]
with tempfile.NamedTemporaryFile(suffix=".jp2") as tfile:
j2k.wrap(tfile.name, boxes=boxes)
jp2 = Jp2k(tfile.name)
jp2h = jp2.box[2]
boxes = [box.id for box in jp2h.box]
self.assertEqual(boxes, ['ihdr', 'colr', 'cdef'])
self.assertEqual(jp2h.box[2].index, (0,))
self.assertEqual(jp2h.box[2].channel_type, (0,))
self.assertEqual(jp2h.box[2].association, (1,))
def test_grey_alpha(self):
"""Just regular greyscale plus alpha."""
j2k = Jp2k(self.two_planes)
cdef = glymur.jp2box.ChannelDefinitionBox(index=[0, 1],
channel_type=[0, 1],
association=[1, 0])
boxes = [self.ihdr, self.colr_gr, cdef]
self.jp2h.box = boxes
boxes = [self.jP, self.ftyp, self.jp2h, self.jp2c]
with tempfile.NamedTemporaryFile(suffix=".jp2") as tfile:
j2k.wrap(tfile.name, boxes=boxes)
jp2 = Jp2k(tfile.name)
jp2h = jp2.box[2]
boxes = [box.id for box in jp2h.box]
self.assertEqual(boxes, ['ihdr', 'colr', 'cdef'])
self.assertEqual(jp2h.box[2].index, (0, 1))
self.assertEqual(jp2h.box[2].channel_type, (0, 1))
self.assertEqual(jp2h.box[2].association, (1, 0))
def test_only_one_cdef_in_jp2_header(self):
"""There can only be one channel definition box in the jp2 header."""
j2k = Jp2k(self.j2kfile)

View file

@ -30,8 +30,7 @@ class TestPrintingNeedsLib(unittest.TestCase):
@classmethod
def setUpClass(cls):
# Setup a plain JP2 file without the two UUID boxes.
jp2file = pkg_resources.resource_filename(glymur.__name__,
"data/nemo.jp2")
jp2file = glymur.data.nemo()
with tempfile.NamedTemporaryFile(suffix='.jp2', delete=False) as tfile:
cls._plain_nemo_file = tfile.name
ijfile = Jp2k(jp2file)