From 2ca9c14724c8a51982df29200def07b908ded435 Mon Sep 17 00:00:00 2001 From: jevans Date: Mon, 24 Jun 2013 18:58:17 -0400 Subject: [PATCH] Closes #63 --- glymur/jp2k.py | 34 +++++++++++++++++++--------------- glymur/test/test_jp2box.py | 31 +++++++++++++++++++++++-------- 2 files changed, 42 insertions(+), 23 deletions(-) diff --git a/glymur/jp2k.py b/glymur/jp2k.py index 4d679b9..1a1e3f2 100644 --- a/glymur/jp2k.py +++ b/glymur/jp2k.py @@ -409,17 +409,12 @@ class Jp2k(Jp2kBox): boxes : list JP2 box definitions to define the JP2 file format. """ - if len(self.box) > 0: - msg = "This method can only be used on files consisting only of " - msg += "a raw codestream. It cannot be used on a file that " - msg += "already has the JP2 format." - raise IOError(msg) - if boxes is None: # Try to create a reasonable default. boxes = [JPEG2000SignatureBox(), FileTypeBox(), - JP2HeaderBox()] + JP2HeaderBox(), + ContiguousCodestreamBox()] c = self.get_codestream() height = c.segment[1].Ysiz width = c.segment[1].Xsiz @@ -428,16 +423,25 @@ class Jp2k(Jp2kBox): width=width, num_components=num_components), ColourSpecificationBox(colorspace=SRGB)] + + # Check for a bad sequence of boxes. + # 1st two boxes must be 'jP ' and 'ftyp' + if boxes[0].id != 'jP ' or boxes[1].id != 'ftyp': + msg = "The first box must be the signature box and the second " + msg += "must be the file type box." + raise IOError(msg) + with open(filename, 'wb') as ofile: for box in boxes: - box._write(ofile) - - # The codestream gets written last. - ofile.write(struct.pack('>I', self.length + 8)) - ofile.write('jp2c'.encode()) - - with open(self.filename, 'rb') as ifile: - ofile.write(ifile.read()) + if box.id != 'jp2c': + box._write(ofile) + else: + # The codestream gets written last. + ofile.write(struct.pack('>I', self.length + 8)) + ofile.write('jp2c'.encode()) + + with open(self.filename, 'rb') as ifile: + ofile.write(ifile.read()) ofile.flush() diff --git a/glymur/test/test_jp2box.py b/glymur/test/test_jp2box.py index 17cb70e..291b1ba 100644 --- a/glymur/test/test_jp2box.py +++ b/glymur/test/test_jp2box.py @@ -163,7 +163,8 @@ class TestJp2Boxes(unittest.TestCase): j2k = Jp2k(self.raw_codestream) boxes = [JPEG2000SignatureBox(), FileTypeBox(), - JP2HeaderBox()] + JP2HeaderBox(), + ContiguousCodestreamBox()] c = j2k.get_codestream() height = c.segment[1].Ysiz width = c.segment[1].Xsiz @@ -259,13 +260,6 @@ class TestJp2Boxes(unittest.TestCase): with self.assertRaises(NotImplementedError): j2k.wrap(tfile.name, boxes=boxes) - def test_wrap_on_jp2(self): - # Should not use "tojp2" method on file that is already jp2. - j = glymur.Jp2k(self.jp2file) - with tempfile.NamedTemporaryFile(suffix=".jp2") as tfile: - with self.assertRaises(IOError): - j.wrap(tfile.name) - def test_default_xml(self): # Should be able to write an xml box. self.assertTrue(False) @@ -275,5 +269,26 @@ class TestJp2Boxes(unittest.TestCase): # say, create an image with an alpha layer. self.assertTrue(False) + def test_first_2_boxes_not_jP_and_ftyp(self): + j2k = Jp2k(self.raw_codestream) + c = j2k.get_codestream() + height = c.segment[1].Ysiz + width = c.segment[1].Xsiz + num_components = len(c.segment[1].XRsiz) + + jP = JPEG2000SignatureBox() + ftyp = FileTypeBox() + jp2h = JP2HeaderBox() + jp2c = ContiguousCodestreamBox() + colr = ColourSpecificationBox(colorspace=glymur.core.SRGB) + ihdr = ImageHeaderBox(height=height, width=width, + num_components=num_components) + jp2h.box = [ihdr, colr] + boxes = [ftyp, jP, jp2h, jp2c] + with tempfile.NamedTemporaryFile(suffix=".jp2") as tfile: + with self.assertRaises(IOError): + j2k.wrap(tfile.name, boxes=boxes) + + if __name__ == "__main__": unittest.main()