From 3bad8a4b2e5444484e959d74b966845d7221a39c Mon Sep 17 00:00:00 2001 From: John Evans Date: Thu, 6 Mar 2014 09:20:21 -0500 Subject: [PATCH] Added negative test for cinema2k frame rate not 24 or 48. #139 Some refactoring of cinema2k code. --- glymur/jp2k.py | 133 +++++++++++++++------------- glymur/test/fixtures.py | 2 +- glymur/test/test_opj_suite_write.py | 16 +++- glymur/test/test_printing.py | 5 +- 4 files changed, 88 insertions(+), 68 deletions(-) diff --git a/glymur/jp2k.py b/glymur/jp2k.py index 890c2fd..255e2be 100644 --- a/glymur/jp2k.py +++ b/glymur/jp2k.py @@ -155,6 +155,73 @@ class Jp2k(Jp2kBox): msg += "profile if the file type box brand is 'jp2 '." warnings.warn(msg) + def _set_cinema_params(self, cparams, fps): + """Populate compression parameters structure for cinema2K. + + Parameters + ---------- + fps : int + Frames per second, should be either 24 or 48. + """ + if fps not in [24, 48]: + raise IOError('Cinema2K frame rate must be either 24 or 48.') + cparams.cp_cinema = fps + + cparams.cp_rsiz = RSIZ['CINEMA2K'] + # No tiling + cparams.tile_size_on = opj2.FALSE + cparams.cp_tdx = 1 + cparams.cp_tdy = 1 + + # One tile part for each component. + cparams.tp_flag = ord('C') + cparams.tp_on = 1 + + # tile and image shall be as (0,0) + cparams.cp_tx0 = 0 + cparams.cp_ty0 = 0 + cparams.image_offset_x0 = 0 + cparams.image_offset_y0 = 0 + + # Codeblock size = 32 * 32 + cparams.cblockw_init = 32 + cparams.cblockh_init = 32 + + # code block style, no mode switch enabled. + cparams.mode = 0 + + # no ROI + cparams.roi_compno = -1 + + # no subsampling + cparams.subsampling_dx = 1 + cparams.subsampling_dy = 1 + + # 9-7 transform + cparams.irreversible = 1 + + # number of layers + if cparams.tcp_numlayers > 1: + # TODO: warning or error + cparams.tcp_numlayers = 1 + + if cparams.numresolution > 6: + # TODO: warning or error + cparams.numresolution = 6 + + # precincts + cparams.csty |= 0x01 + cparams.res_spec = cparams.numresolution - 1 + for j in range(cparams.res_spec): + cparams.prcw_init[j] = 256 + cparams.prch_init[j] = 256 + + # Progression order shall be CPRL + cparams.prog_order = PROGRESSION_ORDER['CPRL'] + + # progression order changes not allowed for 2K + cparams.numpocs = 0 + def _populate_cparams(self, **kwargs): """Populate compression parameters structure from input arguments. @@ -221,64 +288,8 @@ class Jp2k(Jp2kBox): cparams.tcp_numlayers = 1 cparams.cp_disto_alloc = 1 - if 'cinema2K' in kwargs: - # TODO: error if either 24 or 48 - cparams.cp_cinema = kwargs['cinema2K'] - - cparams.cp_rsiz = RSIZ['CINEMA2K'] - # No tiling - cparams.tile_size_on = opj2.FALSE - cparams.cp_tdx = 1 - cparams.cp_tdy = 1 - - # One tile part for each component. - cparams.tp_flag = ord('C') - cparams.tp_on = 1 - - # tile and image shall be as (0,0) - cparams.cp_tx0 = 0 - cparams.cp_ty0 = 0 - cparams.image_offset_x0 = 0 - cparams.image_offset_y0 = 0 - - # Codeblock size = 32 * 32 - cparams.cblockw_init = 32 - cparams.cblockh_init = 32 - - # code block style, no mode switch enabled. - cparams.mode = 0 - - # no ROI - cparams.roi_compno = -1 - - # no subsampling - cparams.subsampling_dx = 1 - cparams.subsampling_dy = 1 - - # 9-7 transform - cparams.irreversible = 1 - - # number of layers - if cparams.tcp_numlayers > 1: - # TODO: warning or error - cparams.tcp_numlayers = 1 - - if cparams.numresolution > 6: - # TODO: warning or error - cparams.numresolution = 6 - - # precincts - cparams.csty |= 0x01 - cparams.res_spec = cparams.numresolution - 1 - for j in range(cparams.res_spec): - cparams.prcw_init[j] = 256 - cparams.prch_init[j] = 256 - - # Progression order shall be CPRL - cparams.prog_order = PROGRESSION_ORDER['CPRL'] - - # progression order changes not allowed for 2K - cparams.numpocs = 0 + if 'cinema2k' in kwargs: + self._set_cinema_params(cparams, kwargs['cinema2k']) return cparams if 'cbsize' in kwargs: @@ -402,8 +413,8 @@ class Jp2k(Jp2kBox): Image data to be written to file. cbsize : tuple, optional Code block size (DY, DX). - cinema2K : int, optional - either 24 or 48 + cinema2k : int, optional + frames per second, either 24 or 48 colorspace : str, optional Either 'rgb' or 'gray'. cratios : iterable @@ -577,7 +588,7 @@ class Jp2k(Jp2kBox): _populate_image_struct(cparams, image, img_array) - if 'cinema2K' in kwargs: + if 'cinema2k' in kwargs: self._set_cinema_rate(cparams, image) codec = opj2.create_compress(cparams.codec_fmt) diff --git a/glymur/test/fixtures.py b/glymur/test/fixtures.py index 666fb6b..7e4d9e8 100644 --- a/glymur/test/fixtures.py +++ b/glymur/test/fixtures.py @@ -22,7 +22,7 @@ try: HAS_PYTHON_XMP_TOOLKIT = True else: HAS_PYTHON_XMP_TOOLKIT = False -except ImportError: +except: HAS_PYTHON_XMP_TOOLKIT = False # Need to know of the libopenjp2 version is the official 2.0.0 release and NOT diff --git a/glymur/test/test_opj_suite_write.py b/glymur/test/test_opj_suite_write.py index 335202d..21c2578 100644 --- a/glymur/test/test_opj_suite_write.py +++ b/glymur/test/test_opj_suite_write.py @@ -16,7 +16,7 @@ try: import skimage.io skimage.io.use_plugin('freeimage', 'imread') _HAS_SKIMAGE_FREEIMAGE_SUPPORT = True -except ImportError: +except ((ImportError, RuntimeError)): _HAS_SKIMAGE_FREEIMAGE_SUPPORT = False from .fixtures import read_image, NO_READ_BACKEND, NO_READ_BACKEND_MSG @@ -25,7 +25,6 @@ from .fixtures import OPJ_DATA_ROOT, opj_data_file from glymur import Jp2k import glymur - @unittest.skipIf(os.name == "nt", "no write support on windows, period") @unittest.skipIf(re.match(r"""1\.[01234]\.\d""", glymur.version.openjpeg_version) is not None, @@ -53,7 +52,7 @@ class TestSuiteWrite(unittest.TestCase): data = skimage.io.imread(infile) with tempfile.NamedTemporaryFile(suffix='.j2k') as tfile: j = Jp2k(tfile.name, 'wb') - j.write(data, cinema2K=24) + j.write(data, cinema2k=24) codestream = j.get_codestream() @@ -111,7 +110,16 @@ class TestSuiteWrite(unittest.TestCase): self.assertEqual(len(codestream.segment[2].spcod), 9) - + @unittest.skipIf(not _HAS_SKIMAGE_FREEIMAGE_SUPPORT, + "Cannot read input image without scikit-image/freeimage") + def test_cinema2k_bad_frame_rate(self): + relfile = 'input/nonregression/X_4_2K_24_185_CBR_WB_000.tif' + infile = opj_data_file(relfile) + data = skimage.io.imread(infile) + with tempfile.NamedTemporaryFile(suffix='.j2k') as tfile: + j = Jp2k(tfile.name, 'wb') + with self.assertRaises(IOError): + j.write(data, cinema2k=36) def test_NR_ENC_Bretagne1_ppm_1_encode(self): diff --git a/glymur/test/test_printing.py b/glymur/test/test_printing.py index f90ade3..c59d73f 100644 --- a/glymur/test/test_printing.py +++ b/glymur/test/test_printing.py @@ -133,7 +133,6 @@ class TestPrinting(unittest.TestCase): lst = lst[1:] actual = '\n'.join(lst) expected = fixtures.nemo_dump_no_xml - self.maxDiff = None self.assertEqual(actual, expected) def test_printoptions_short(self): @@ -745,7 +744,9 @@ class TestPrinting(unittest.TestCase): with patch('sys.stdout', new=StringIO()) as fake_out: print(j.box[2]) actual = fake_out.getvalue().strip() - self.assertEqual(actual, fixtures.file7_rreq) + self.maxDiff = None + expected = fixtures.file7_rreq + self.assertEqual(actual, expected) @unittest.skipIf(OPJ_DATA_ROOT is None, "OPJ_DATA_ROOT environment variable not set")