diff --git a/glymur/__init__.py b/glymur/__init__.py index a69d28f..fb37ef0 100644 --- a/glymur/__init__.py +++ b/glymur/__init__.py @@ -6,7 +6,7 @@ from .jp2k import Jp2k from .jp2dump import jp2dump from . import data -from . import test +#from . import test def runtests(): diff --git a/glymur/jp2k.py b/glymur/jp2k.py index 5baebac..4efcb77 100644 --- a/glymur/jp2k.py +++ b/glymur/jp2k.py @@ -22,6 +22,7 @@ from .codestream import Codestream from .core import SRGB from .core import GREYSCALE from .core import PROGRESSION_ORDER +from .core import ENUMERATED_COLORSPACE, RESTRICTED_ICC_PROFILE from .jp2box import Jp2kBox from .jp2box import JPEG2000SignatureBox from .jp2box import FileTypeBox @@ -159,6 +160,23 @@ class Jp2k(Jp2kBox): # boxes) here. fptr.seek(0) self.box = self.parse_superbox(fptr) + self._validate() + + def _validate(self): + """Validate the JPEG 2000 outermost superbox. + """ + # A jp2-branded file cannot contain an "any ICC profile + ftyp = self.box[1] + jp2h = [box for box in self.box if box.box_id == 'jp2h'][0] + colr = [box for box in jp2h.box if box.box_id == 'colr'][0] + if (((ftyp.brand == 'jp2 ') and + (colr.method not in (ENUMERATED_COLORSPACE, + RESTRICTED_ICC_PROFILE)))): + msg = "Color Specification box method must specify either an " + msg += "enumerated colorspace or a restricted ICC profile if the " + msg += "file type box brand is 'jp2 '." + warnings.warn(msg) + # pylint: disable-msg=W0221 def write(self, img_array, cratios=None, eph=False, psnr=None, numres=None, diff --git a/glymur/test/test_format_corpus.py b/glymur/test/test_format_corpus.py index 28e1d4d..93af29d 100644 --- a/glymur/test/test_format_corpus.py +++ b/glymur/test/test_format_corpus.py @@ -81,5 +81,16 @@ class TestSuite(unittest.TestCase): #with self.assertRaises(OSError): # j2k.read(rlevel=-1) + def test_jp2_brand_vs_any_icc_profile(self): + # If 'jp2 ', then the method cannot be any icc profile. + jfile = os.path.join(data_root, + 'jp2k-test/icc/balloon_eciRGBv2_ps_adobeplugin.jpf') + with self.assertWarns(UserWarning): + j2k = Jp2k(jfile) + + # Should error out, it does not. + #with self.assertRaises(OSError): + # j2k.read(rlevel=-1) + if __name__ == "__main__": unittest.main() diff --git a/glymur/test/test_opj_suite.py b/glymur/test/test_opj_suite.py index 4aab788..4699b06 100644 --- a/glymur/test/test_opj_suite.py +++ b/glymur/test/test_opj_suite.py @@ -990,7 +990,11 @@ class TestSuite(unittest.TestCase): def test_NR_DEC_text_GBR_jp2_29_decode(self): jfile = os.path.join(data_root, 'input/nonregression/text_GBR.jp2') - data = Jp2k(jfile).read() + with warnings.catch_warnings(): + # brand is 'jp2 ', but has any icc profile. + warnings.simplefilter("ignore") + jp2 = Jp2k(jfile) + data = jp2.read() self.assertTrue(True) def test_NR_DEC_pacs_ge_j2k_30_decode(self): @@ -7260,7 +7264,10 @@ class TestSuiteDump(unittest.TestCase): def test_NR_text_GBR_dump(self): jfile = os.path.join(data_root, 'input/nonregression/text_GBR.jp2') - jp2 = Jp2k(jfile) + with warnings.catch_warnings(): + # brand is 'jp2 ', but has any icc profile. + warnings.simplefilter("ignore") + jp2 = Jp2k(jfile) ids = [box.box_id for box in jp2.box] lst = ['jP ', 'ftyp', 'rreq', 'jp2h', diff --git a/glymur/test/test_printing.py b/glymur/test/test_printing.py index 09f828c..79a12e1 100644 --- a/glymur/test/test_printing.py +++ b/glymur/test/test_printing.py @@ -4,6 +4,7 @@ import pkg_resources import struct import sys import tempfile +import warnings if sys.hexversion < 0x02070000: import unittest2 as unittest @@ -277,9 +278,12 @@ class TestPrinting(unittest.TestCase): "OPJ_DATA_ROOT environment variable not set") def test_icc_profile(self): filename = os.path.join(data_root, 'input/nonregression/text_GBR.jp2') - j = glymur.Jp2k(filename) + with warnings.catch_warnings(): + # brand is 'jp2 ', but has any icc profile. + warnings.simplefilter("ignore") + jp2 = Jp2k(filename) with patch('sys.stdout', new=StringIO()) as fake_out: - print(j.box[3].box[1]) + print(jp2.box[3].box[1]) actual = fake_out.getvalue().strip() lin27 = ["Colour Specification Box (colr) @ (179, 1339)", " Method: any ICC profile", @@ -902,10 +906,13 @@ class TestPrinting(unittest.TestCase): # ICC profiles may be used in JP2, but the approximation field should # be zero unless we have jpx. This file does both. filename = os.path.join(data_root, 'input/nonregression/text_GBR.jp2') - j = glymur.Jp2k(filename) + with warnings.catch_warnings(): + # brand is 'jp2 ', but has any icc profile. + warnings.simplefilter("ignore") + jp2 = Jp2k(filename) with patch('sys.stdout', new=StringIO()) as fake_out: - print(j.box[3].box[1]) + print(jp2.box[3].box[1]) actual = fake_out.getvalue().strip() lines = ["Colour Specification Box (colr) @ (179, 1339)", " Method: any ICC profile", @@ -942,10 +949,13 @@ class TestPrinting(unittest.TestCase): def test_uuid(self): # UUID box filename = os.path.join(data_root, 'input/nonregression/text_GBR.jp2') - j = glymur.Jp2k(filename) + with warnings.catch_warnings(): + # brand is 'jp2 ', but has any icc profile. + warnings.simplefilter("ignore") + jp2 = Jp2k(filename) with patch('sys.stdout', new=StringIO()) as fake_out: - print(j.box[4]) + print(jp2.box[4]) actual = fake_out.getvalue().strip() lines = ['UUID Box (uuid) @ (1544, 25)', ' UUID: 3a0d0218-0ae9-4115-b376-4bca41ce0e71',