Added validation step for jp2 brand / any icc profile mismatch. #77

text_GBR.jp2 also shows this issue.
This commit is contained in:
John Evans 2013-07-23 17:22:21 -04:00
commit de7e6e1f0f
5 changed files with 55 additions and 9 deletions

View file

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

View file

@ -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,

View file

@ -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()

View file

@ -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',

View file

@ -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',