From 89a1b0bb1c6b812f82805a3bb3488051ec40045f Mon Sep 17 00:00:00 2001 From: John Evans Date: Tue, 11 Nov 2014 10:46:59 -0500 Subject: [PATCH 01/23] progress, working on rlevel --- glymur/jp2k.py | 52 ++++++++++++++++++++++++++++------------ glymur/test/test_jp2k.py | 46 ++++++++++++++++++++--------------- 2 files changed, 64 insertions(+), 34 deletions(-) diff --git a/glymur/jp2k.py b/glymur/jp2k.py index f36b75e..25efacd 100644 --- a/glymur/jp2k.py +++ b/glymur/jp2k.py @@ -60,6 +60,23 @@ class Jp2k(Jp2kBox): List of top-level boxes in the file. Each box may in turn contain its own list of boxes. Will be empty if the file consists only of a raw codestream. + + Examples + -------- + >>> import glymur + >>> jfile = glymur.data.nemo() + >>> jp2 = glymur.Jp2k(jfile) + >>> jp2.shape + (1456, 2592, 3) + >>> image = jp2[:] + >>> image.shape + (1456, 2592, 3) + + Read a lower resolution thumbnail. + + >>> thumbnail = jp2[::2, ::2] + >>> thumbnail.shape + (728, 1296, 3) """ def __init__(self, filename, mode='rb'): @@ -957,6 +974,25 @@ class Jp2k(Jp2kBox): return data[:, :, bands] + def _read(self): + """Read a JPEG 2000 image. + + Returns + ------- + img_array : ndarray + The image data. + + Raises + ------ + IOError + If the image has differing subsample factors. + """ + if version.openjpeg_version_tuple[0] < 2: + img = self._read_openjpeg(**kwargs) + else: + img = self._read_openjp2(**kwargs) + return img + def read(self, **kwargs): """Read a JPEG 2000 image. @@ -988,22 +1024,8 @@ class Jp2k(Jp2kBox): ------ IOError If the image has differing subsample factors. - - Examples - -------- - >>> import glymur - >>> jfile = glymur.data.nemo() - >>> jp = glymur.Jp2k(jfile) - >>> image = jp.read() - >>> image.shape - (1456, 2592, 3) - - Read the lowest resolution thumbnail. - - >>> thumbnail = jp.read(rlevel=-1) - >>> thumbnail.shape - (728, 1296, 3) """ + warnings.warn("Use array-style slicing instead.", DeprecationWarning) if version.openjpeg_version_tuple[0] < 2: img = self._read_openjpeg(**kwargs) else: diff --git a/glymur/test/test_jp2k.py b/glymur/test/test_jp2k.py index 9a9fb72..4933777 100644 --- a/glymur/test/test_jp2k.py +++ b/glymur/test/test_jp2k.py @@ -67,11 +67,13 @@ class SliceProtocolBase(unittest.TestCase): def setUpClass(self): self.jp2 = Jp2k(glymur.data.nemo()) - self.jp2_data = self.jp2.read() + self.jp2_data = self.jp2[:] + self.jp2_data_r1 = self.jp2[::2, ::2] self.j2k = Jp2k(glymur.data.goodstuff()) - self.j2k_data = self.j2k.read() + self.j2k_data = self.j2k[:] + self.j2k_data_r1 = self.j2k[::2, ::2] @unittest.skipIf(os.name == "nt", fixtures.WINDOWS_TMP_FILE_MSG) class TestSliceProtocolBaseWrite(SliceProtocolBase): @@ -82,7 +84,7 @@ class TestSliceProtocolBaseWrite(SliceProtocolBase): with tempfile.NamedTemporaryFile(suffix='.j2k') as tfile: j = Jp2k(tfile.name, 'wb') j[...] = self.j2k_data - actual = j.read() + actual = j[:] np.testing.assert_array_equal(actual, expected) @@ -92,7 +94,7 @@ class TestSliceProtocolBaseWrite(SliceProtocolBase): with tempfile.NamedTemporaryFile(suffix='.j2k') as tfile: j = Jp2k(tfile.name, 'wb') j[:] = self.j2k_data - actual = j.read() + actual = j[:] np.testing.assert_array_equal(actual, expected) @@ -167,9 +169,9 @@ class TestSliceProtocolRead(SliceProtocolBase): np.testing.assert_array_equal(actual, expected) def test_reduce_resolution_and_slice_in_third_dimension(self): - d = self.j2k[::2, ::2, 1:3] - all = self.j2k.read(rlevel=1) - np.testing.assert_array_equal(all[:,:,1:3], d) + actual = self.j2k[::2, ::2, 1:3] + expected = self.j2k_data_r1[:, :, 1:3] + np.testing.assert_array_equal(actual, expected) def test_retrieve_single_row(self): actual = self.jp2[0] @@ -231,24 +233,24 @@ class TestSliceProtocolRead(SliceProtocolBase): expected = self.jp2_data[728:, :] np.testing.assert_array_equal(actual, expected) - def test_region_rlevel1(self): + def test_region_rlevel1_odd(self): actual = self.jp2[0:201:2, 0:201:2] - expected = self.jp2.read(area=(0, 0, 201, 201), rlevel=1) + expected = self.jp2_data_r1[:101, :101, :] + np.testing.assert_array_equal(actual, expected) + + def test_region_rlevel1_even(self): + actual = self.jp2[0:202:2, 0:202:2] + expected = self.jp2_data_r1[:101, :101, :] np.testing.assert_array_equal(actual, expected) def test_region_rlevel1_slice_start_is_none(self): actual = self.jp2[:201:2, :201:2] - expected = self.jp2.read(area=(0, 0, 201, 201), rlevel=1) + expected = self.jp2_data_r1[:101, :101, :] np.testing.assert_array_equal(actual, expected) def test_region_rlevel1_slice_stop_is_none(self): actual = self.jp2[201::2, 201::2] - expected = self.jp2.read(area=(201, 201, 1456, 2592), rlevel=1) - np.testing.assert_array_equal(actual, expected) - - def test_region_rlevel1(self): - actual = self.jp2[0:202:2, 0:202:2] - expected = self.jp2.read(area=(0, 0, 202, 202), rlevel=1) + expected = self.jp2_data_r1[101:, 101:, :] np.testing.assert_array_equal(actual, expected) def test_ellipsis_full_read(self): @@ -476,6 +478,12 @@ class TestJp2k(unittest.TestCase): def tearDown(self): pass + @unittest.skipIf(WARNING_INFRASTRUCTURE_ISSUE, WARNING_INFRASTRUCTURE_MSG) + def test_warn_if_using_read_method(self): + """Should warn if read method is called""" + with self.assertWarns(DeprecationWarning): + Jp2k(self.jp2file).read() + def test_shape_jp2(self): """verify shape attribute for JP2 file """ @@ -519,7 +527,7 @@ class TestJp2k(unittest.TestCase): def test_irreversible(self): """Irreversible""" j = Jp2k(self.jp2file) - expdata = j.read() + expdata = j[:] with tempfile.NamedTemporaryFile(suffix='.j2k') as tfile: j2 = Jp2k(tfile.name, 'wb') j2.write(expdata, irreversible=True) @@ -528,7 +536,7 @@ class TestJp2k(unittest.TestCase): self.assertEqual(codestream.segment[2].spcod[8], glymur.core.WAVELET_XFORM_9X7_IRREVERSIBLE) - actdata = j2.read() + actdata = j2[:] self.assertTrue(fixtures.mse(actdata[0], expdata[0]) < 0.38) @unittest.skipIf(re.match('1.[0-4]', openjpeg_version) is not None, @@ -538,7 +546,7 @@ class TestJp2k(unittest.TestCase): def test_no_cxform_pclr_jpx(self): """Indices for pclr jpxfile if no color transform""" j = Jp2k(self.jpxfile) - rgb = j.read() + rgb = j[:] idx = j.read(ignore_pclr_cmap_cdef=True) nr, nc = 1024, 1024 self.assertEqual(rgb.shape, (nr, nc, 3)) From a1413b0f15c7e40d1fd86312a0a7b563c5219989 Mon Sep 17 00:00:00 2001 From: John Evans Date: Wed, 12 Nov 2014 17:30:43 -0500 Subject: [PATCH 02/23] progress --- glymur/test/test_jp2k.py | 49 ++++++++++--------- glymur/test/test_opj_suite.py | 90 +++++++++++++++++------------------ 2 files changed, 69 insertions(+), 70 deletions(-) diff --git a/glymur/test/test_jp2k.py b/glymur/test/test_jp2k.py index 4933777..5e28db0 100644 --- a/glymur/test/test_jp2k.py +++ b/glymur/test/test_jp2k.py @@ -74,6 +74,7 @@ class SliceProtocolBase(unittest.TestCase): self.j2k_data = self.j2k[:] self.j2k_data_r1 = self.j2k[::2, ::2] + self.j2k_data_r5 = self.j2k[::32, ::32] @unittest.skipIf(os.name == "nt", fixtures.WINDOWS_TMP_FILE_MSG) class TestSliceProtocolBaseWrite(SliceProtocolBase): @@ -313,7 +314,7 @@ class TestSliceProtocolRead(SliceProtocolBase): def test_region_rlevel5(self): actual = self.j2k[5:533:32, 27:423:32] - expected = self.j2k.read(area=(5, 27, 533, 423), rlevel=5) + expected = self.j2k_data_r5[1:17, 1:14] np.testing.assert_array_equal(actual, expected) @unittest.skipIf(OPJ_DATA_ROOT is None, @@ -480,7 +481,7 @@ class TestJp2k(unittest.TestCase): @unittest.skipIf(WARNING_INFRASTRUCTURE_ISSUE, WARNING_INFRASTRUCTURE_MSG) def test_warn_if_using_read_method(self): - """Should warn if read method is called""" + """Should warn if deprecated read method is called""" with self.assertWarns(DeprecationWarning): Jp2k(self.jp2file).read() @@ -575,7 +576,7 @@ class TestJp2k(unittest.TestCase): """Verify that rlevel=-1 gets us the lowest resolution image""" j = Jp2k(self.j2kfile) thumbnail1 = j.read(rlevel=-1) - thumbnail2 = j.read(rlevel=5) + thumbnail2 = j[::32, ::32] np.testing.assert_array_equal(thumbnail1, thumbnail2) self.assertEqual(thumbnail1.shape, (25, 15, 3)) @@ -734,7 +735,7 @@ class TestJp2k(unittest.TestCase): """Just a very basic test that reading a JP2 file does not error out. """ j2k = Jp2k(self.jp2file) - j2k.read(rlevel=1) + j2k[::2, ::2] def test_basic_j2k(self): """This test is only useful when openjp2 is not available @@ -742,7 +743,7 @@ class TestJp2k(unittest.TestCase): working J2K test. """ j2k = Jp2k(self.j2kfile) - j2k.read() + j2k[:] def test_empty_box_with_j2k(self): """Verify that the list of boxes in a J2C/J2K file is present, but @@ -867,7 +868,7 @@ class TestJp2k(unittest.TestCase): """Read JPX codestream when jp2-compatible.""" # The file in question has multiple codestreams. jpx = Jp2k(self.jpxfile) - data = jpx.read() + data = jpx[:] self.assertEqual(data.shape, (1024, 1024, 3)) def test_read_bands_without_openjp2(self): @@ -1021,21 +1022,21 @@ class TestJp2k_write(unittest.TestCase): def test_write_with_jp2_in_caps(self): """should be able to write with JP2 suffix.""" j2k = Jp2k(self.j2kfile) - expdata = j2k.read() + expdata = j2k[:] with tempfile.NamedTemporaryFile(suffix='.JP2') as tfile: ofile = Jp2k(tfile.name, 'wb') - ofile.write(expdata) - actdata = ofile.read() + ofile[:] = expdata + actdata = ofile[:] np.testing.assert_array_equal(actdata, expdata) def test_write_srgb_without_mct(self): """should be able to write RGB without specifying mct""" j2k = Jp2k(self.j2kfile) - expdata = j2k.read() + expdata = j2k[:] with tempfile.NamedTemporaryFile(suffix='.jp2') as tfile: ofile = Jp2k(tfile.name, 'wb') ofile.write(expdata, mct=False) - actdata = ofile.read() + actdata = ofile[:] np.testing.assert_array_equal(actdata, expdata) codestream = ofile.get_codestream() @@ -1044,7 +1045,7 @@ class TestJp2k_write(unittest.TestCase): def test_write_grayscale_with_mct(self): """MCT usage makes no sense for grayscale images.""" j2k = Jp2k(self.j2kfile) - expdata = j2k.read() + expdata = j2k[:] with tempfile.NamedTemporaryFile(suffix='.jp2') as tfile: ofile = Jp2k(tfile.name, 'wb') with self.assertRaises(IOError): @@ -1054,11 +1055,11 @@ class TestJp2k_write(unittest.TestCase): """Must be able to write a CPRL progression order file""" # Issue 17 j = Jp2k(self.jp2file) - expdata = j.read(rlevel=1) + expdata = j[::2, ::2] with tempfile.NamedTemporaryFile(suffix='.jp2') as tfile: ofile = Jp2k(tfile.name, 'wb') ofile.write(expdata, prog='CPRL') - actdata = ofile.read() + actdata = ofile[:] np.testing.assert_array_equal(actdata, expdata) codestream = ofile.get_codestream() @@ -1145,7 +1146,7 @@ class TestJp2k_2_0(unittest.TestCase): """Test asoc and label box""" # Construct a fake file with an asoc and a label box, as # OpenJPEG doesn't have such a file. - data = Jp2k(self.jp2file).read(rlevel=1) + data = Jp2k(self.jp2file)[::2, ::2] with tempfile.NamedTemporaryFile(suffix='.jp2') as tfile: j = Jp2k(tfile.name, 'wb') j.write(data) @@ -1246,11 +1247,9 @@ class TestJp2k_2_1(unittest.TestCase): tfile.write(data[offset+53:offset+55]) tfile.write(b'\x00') tfile.write(data[offset+57:offset+59]) - #tfile.write(data[3184:3186]) tfile.write(b'\x00') tfile.write(data[offset+59:]) - #tfile.write(data[3186:]) tfile.flush() with warnings.catch_warnings(): warnings.simplefilter('ignore') @@ -1260,10 +1259,10 @@ class TestJp2k_2_1(unittest.TestCase): :\sdx=1\sdy=0''', re.VERBOSE) if sys.hexversion < 0x03020000: with self.assertRaisesRegexp((IOError, OSError), regexp): - j.read(rlevel=1) + j[::2, ::2] else: with self.assertRaisesRegex((IOError, OSError), regexp): - j.read(rlevel=1) + j[::2, ::2] @unittest.skipIf(OPJ_DATA_ROOT is None, "OPJ_DATA_ROOT environment variable not set") @@ -1364,7 +1363,7 @@ class TestJp2kOpjDataRoot(unittest.TestCase): self.assertEqual(codestream.segment[2].spcod[8], glymur.core.WAVELET_XFORM_9X7_IRREVERSIBLE) - actdata = j.read() + actdata = j[:] self.assertTrue(fixtures.mse(actdata, expdata) < 250) @unittest.skipIf(WARNING_INFRASTRUCTURE_ISSUE, WARNING_INFRASTRUCTURE_MSG) @@ -1372,9 +1371,9 @@ class TestJp2kOpjDataRoot(unittest.TestCase): """Indices for pclr jpxfile if no color transform""" filename = opj_data_file('input/conformance/file9.jp2') with self.assertWarns(UserWarning): - j = Jp2k(filename) - rgb = j.read() - idx = j.read(ignore_pclr_cmap_cdef=True) + jp2 = Jp2k(filename) + rgb = jp2[:] + idx = jp2.read(ignore_pclr_cmap_cdef=True) self.assertEqual(rgb.shape, (512, 768, 3)) self.assertEqual(idx.shape, (512, 768)) @@ -1396,7 +1395,7 @@ class TestJp2kOpjDataRoot(unittest.TestCase): filename = opj_data_file('input/conformance/p0_05.j2k') j = Jp2k(filename) with self.assertRaises(RuntimeError): - j.read() + j[:] @unittest.skipIf(WARNING_INFRASTRUCTURE_ISSUE, WARNING_INFRASTRUCTURE_MSG) def test_no_cxform_cmap(self): @@ -1407,7 +1406,7 @@ class TestJp2kOpjDataRoot(unittest.TestCase): with self.assertWarns(UserWarning): # The file has a bad compatibility list entry. Not important here. j = Jp2k(filename) - ycbcr = j.read() + ycbcr = j[:] crcby = j.read(ignore_pclr_cmap_cdef=True) expected = np.zeros(ycbcr.shape, ycbcr.dtype) diff --git a/glymur/test/test_opj_suite.py b/glymur/test/test_opj_suite.py index a033aae..a10185b 100644 --- a/glymur/test/test_opj_suite.py +++ b/glymur/test/test_opj_suite.py @@ -57,7 +57,7 @@ class TestSuite(unittest.TestCase): def test_ETS_C1P0_p0_01_j2k(self): jfile = opj_data_file('input/conformance/p0_01.j2k') jp2k = Jp2k(jfile) - jpdata = jp2k.read(rlevel=0) + jpdata = jp2k[:] pgxfile = opj_data_file('baseline/conformance/c1p0_01_0.pgx') pgxdata = read_pgx(pgxfile) @@ -67,7 +67,7 @@ class TestSuite(unittest.TestCase): def test_ETS_C1P0_p0_03_j2k(self): jfile = opj_data_file('input/conformance/p0_03.j2k') jp2k = Jp2k(jfile) - jpdata = jp2k.read(rlevel=0) + jpdata = jp2k[:] pgxfile = opj_data_file('baseline/conformance/c1p0_03_0.pgx') pgxdata = read_pgx(pgxfile) @@ -77,7 +77,7 @@ class TestSuite(unittest.TestCase): def test_ETS_C1P0_p0_04_j2k(self): jfile = opj_data_file('input/conformance/p0_04.j2k') jp2k = Jp2k(jfile) - jpdata = jp2k.read(rlevel=0) + jpdata = jp2k[:] pgxfile = opj_data_file('baseline/conformance/c1p0_04_0.pgx') pgxdata = read_pgx(pgxfile) @@ -97,7 +97,7 @@ class TestSuite(unittest.TestCase): def test_ETS_C1P0_p0_08_j2k(self): jfile = opj_data_file('input/conformance/p0_08.j2k') jp2k = Jp2k(jfile) - jpdata = jp2k.read(rlevel=1) + jpdata = jp2k[::2, ::2] pgxfile = opj_data_file('baseline/conformance/c1p0_08_0.pgx') pgxdata = read_pgx(pgxfile) @@ -114,7 +114,7 @@ class TestSuite(unittest.TestCase): def test_ETS_C1P0_p0_09_j2k(self): jfile = opj_data_file('input/conformance/p0_09.j2k') jp2k = Jp2k(jfile) - jpdata = jp2k.read(rlevel=0) + jpdata = jp2k[:] pgxfile = opj_data_file('baseline/conformance/c1p0_09_0.pgx') pgxdata = read_pgx(pgxfile) @@ -123,7 +123,7 @@ class TestSuite(unittest.TestCase): def test_ETS_C1P0_p0_11_j2k(self): jfile = opj_data_file('input/conformance/p0_11.j2k') jp2k = Jp2k(jfile) - jpdata = jp2k.read(rlevel=0) + jpdata = jp2k[:] pgxfile = opj_data_file('baseline/conformance/c1p0_11_0.pgx') pgxdata = read_pgx(pgxfile) @@ -132,7 +132,7 @@ class TestSuite(unittest.TestCase): def test_ETS_C1P0_p0_14_j2k(self): jfile = opj_data_file('input/conformance/p0_14.j2k') jp2k = Jp2k(jfile) - jpdata = jp2k.read(rlevel=0) + jpdata = jp2k[:] pgxfile = opj_data_file('baseline/conformance/c1p0_14_0.pgx') pgxdata = read_pgx(pgxfile) @@ -149,7 +149,7 @@ class TestSuite(unittest.TestCase): def test_ETS_C1P0_p0_15_j2k(self): jfile = opj_data_file('input/conformance/p0_15.j2k') jp2k = Jp2k(jfile) - jpdata = jp2k.read(rlevel=0) + jpdata = jp2k[:] pgxfile = opj_data_file('baseline/conformance/c1p0_15_0.pgx') pgxdata = read_pgx(pgxfile) @@ -158,7 +158,7 @@ class TestSuite(unittest.TestCase): def test_ETS_C1P0_p0_16_j2k(self): jfile = opj_data_file('input/conformance/p0_16.j2k') jp2k = Jp2k(jfile) - jpdata = jp2k.read(rlevel=0) + jpdata = jp2k[:] pgxfile = opj_data_file('baseline/conformance/c1p0_16_0.pgx') pgxdata = read_pgx(pgxfile) @@ -167,7 +167,7 @@ class TestSuite(unittest.TestCase): def test_ETS_C1P1_p1_01_j2k(self): jfile = opj_data_file('input/conformance/p1_01.j2k') jp2k = Jp2k(jfile) - jpdata = jp2k.read(rlevel=0) + jpdata = jp2k[:] pgxfile = opj_data_file('baseline/conformance/c1p1_01_0.pgx') pgxdata = read_pgx(pgxfile) @@ -176,7 +176,7 @@ class TestSuite(unittest.TestCase): def test_ETS_C1P1_p1_02_j2k(self): jfile = opj_data_file('input/conformance/p1_02.j2k') jp2k = Jp2k(jfile) - jpdata = jp2k.read(rlevel=0) + jpdata = jp2k[:] pgxfile = opj_data_file('baseline/conformance/c1p1_02_0.pgx') pgxdata = read_pgx(pgxfile) @@ -196,7 +196,7 @@ class TestSuite(unittest.TestCase): def test_ETS_C1P1_p1_04_j2k(self): jfile = opj_data_file('input/conformance/p1_04.j2k') jp2k = Jp2k(jfile) - jpdata = jp2k.read() + jpdata = jp2k[:] pgxfile = opj_data_file('baseline/conformance/c1p1_04_0.pgx') pgxdata = read_pgx(pgxfile) @@ -206,95 +206,95 @@ class TestSuite(unittest.TestCase): def test_NR_DEC_Bretagne2_j2k_1_decode(self): jfile = opj_data_file('input/nonregression/Bretagne2.j2k') jp2 = Jp2k(jfile) - jp2.read() + jp2[:] self.assertTrue(True) def test_NR_DEC__00042_j2k_2_decode(self): jfile = opj_data_file('input/nonregression/_00042.j2k') jp2 = Jp2k(jfile) - jp2.read() + jp2[:] self.assertTrue(True) def test_NR_DEC_buxI_j2k_9_decode(self): jfile = opj_data_file('input/nonregression/buxI.j2k') - Jp2k(jfile).read() + Jp2k(jfile)[:] self.assertTrue(True) def test_NR_DEC_buxR_j2k_10_decode(self): jfile = opj_data_file('input/nonregression/buxR.j2k') - Jp2k(jfile).read() + Jp2k(jfile)[:] self.assertTrue(True) def test_NR_DEC_Cannotreaddatawithnosizeknown_j2k_11_decode(self): relpath = 'input/nonregression/Cannotreaddatawithnosizeknown.j2k' jfile = opj_data_file(relpath) - Jp2k(jfile).read() + Jp2k(jfile)[:] self.assertTrue(True) def test_NR_DEC_cthead1_j2k_12_decode(self): jfile = opj_data_file('input/nonregression/cthead1.j2k') - Jp2k(jfile).read() + Jp2k(jfile)[:] self.assertTrue(True) def test_NR_DEC_CT_Phillips_JPEG2K_Decompr_Problem_j2k_13_decode(self): relpath = 'input/nonregression/CT_Phillips_JPEG2K_Decompr_Problem.j2k' jfile = opj_data_file(relpath) - Jp2k(jfile).read() + Jp2k(jfile)[:] self.assertTrue(True) def test_NR_DEC_j2k32_j2k_15_decode(self): jfile = opj_data_file('input/nonregression/j2k32.j2k') - Jp2k(jfile).read() + Jp2k(jfile)[:] self.assertTrue(True) def test_NR_DEC_MarkerIsNotCompliant_j2k_17_decode(self): jfile = opj_data_file('input/nonregression/MarkerIsNotCompliant.j2k') - Jp2k(jfile).read() + Jp2k(jfile)[:] self.assertTrue(True) def test_NR_DEC_Marrin_jp2_18_decode(self): jfile = opj_data_file('input/nonregression/Marrin.jp2') - Jp2k(jfile).read() + Jp2k(jfile)[:] self.assertTrue(True) def test_NR_DEC_movie_00000_j2k_20_decode(self): jfile = opj_data_file('input/nonregression/movie_00000.j2k') - Jp2k(jfile).read() + Jp2k(jfile)[:] self.assertTrue(True) def test_NR_DEC_movie_00001_j2k_21_decode(self): jfile = opj_data_file('input/nonregression/movie_00001.j2k') - Jp2k(jfile).read() + Jp2k(jfile)[:] self.assertTrue(True) def test_NR_DEC_movie_00002_j2k_22_decode(self): jfile = opj_data_file('input/nonregression/movie_00002.j2k') - Jp2k(jfile).read() + Jp2k(jfile)[:] self.assertTrue(True) def test_NR_DEC_orb_blue_lin_j2k_j2k_23_decode(self): jfile = opj_data_file('input/nonregression/orb-blue10-lin-j2k.j2k') - Jp2k(jfile).read() + Jp2k(jfile)[:] self.assertTrue(True) def test_NR_DEC_orb_blue_win_j2k_j2k_24_decode(self): jfile = opj_data_file('input/nonregression/orb-blue10-win-j2k.j2k') - Jp2k(jfile).read() + Jp2k(jfile)[:] self.assertTrue(True) def test_NR_DEC_relax_jp2_27_decode(self): jfile = opj_data_file('input/nonregression/relax.jp2') - Jp2k(jfile).read() + Jp2k(jfile)[:] self.assertTrue(True) def test_NR_DEC_test_lossless_j2k_28_decode(self): jfile = opj_data_file('input/nonregression/test_lossless.j2k') - Jp2k(jfile).read() + Jp2k(jfile)[:] self.assertTrue(True) def test_NR_DEC_pacs_ge_j2k_30_decode(self): jfile = opj_data_file('input/nonregression/pacs.ge.j2k') - Jp2k(jfile).read() + Jp2k(jfile)[:] self.assertTrue(True) @@ -317,14 +317,14 @@ class TestSuiteWarns(MetadataBase): with self.assertWarns(UserWarning): # Bad compatibility list item. jp2k = Jp2k(jfile) - jpdata = jp2k.read() + jpdata = jp2k[:] self.assertEqual(jpdata.shape, (512, 768, 3)) def test_ETS_JP2_file2(self): jfile = opj_data_file('input/conformance/file2.jp2') with self.assertWarns(UserWarning): jp2k = Jp2k(jfile) - jpdata = jp2k.read() + jpdata = jp2k[:] self.assertEqual(jpdata.shape, (640, 480, 3)) @unittest.skipIf(glymur.version.openjpeg_version_tuple[0] < 2, @@ -342,7 +342,7 @@ class TestSuiteWarns(MetadataBase): jfile = opj_data_file('input/conformance/file4.jp2') with self.assertWarns(UserWarning): jp2k = Jp2k(jfile) - jpdata = jp2k.read() + jpdata = jp2k[:] self.assertEqual(jpdata.shape, (512, 768)) def test_ETS_JP2_file5(self): @@ -351,35 +351,35 @@ class TestSuiteWarns(MetadataBase): # There's a warning for an unknown compatibility entry. # Ignore it here. jp2k = Jp2k(jfile) - jpdata = jp2k.read() + jpdata = jp2k[:] self.assertEqual(jpdata.shape, (512, 768, 3)) def test_ETS_JP2_file6(self): jfile = opj_data_file('input/conformance/file6.jp2') with self.assertWarns(UserWarning): jp2k = Jp2k(jfile) - jpdata = jp2k.read() + jpdata = jp2k[:] self.assertEqual(jpdata.shape, (512, 768)) def test_ETS_JP2_file7(self): jfile = opj_data_file('input/conformance/file7.jp2') with self.assertWarns(UserWarning): jp2k = Jp2k(jfile) - jpdata = jp2k.read() + jpdata = jp2k[:] self.assertEqual(jpdata.shape, (640, 480, 3)) def test_ETS_JP2_file8(self): jfile = opj_data_file('input/conformance/file8.jp2') with self.assertWarns(UserWarning): jp2k = Jp2k(jfile) - jpdata = jp2k.read() + jpdata = jp2k[:] self.assertEqual(jpdata.shape, (400, 700)) def test_ETS_JP2_file9(self): jfile = opj_data_file('input/conformance/file9.jp2') with self.assertWarns(UserWarning): jp2k = Jp2k(jfile) - jpdata = jp2k.read() + jpdata = jp2k[:] self.assertEqual(jpdata.shape, (512, 768, 3)) def test_NR_broken_jp2_dump(self): @@ -469,13 +469,13 @@ class TestSuiteWarns(MetadataBase): jfile = opj_data_file('input/nonregression/orb-blue10-lin-jp2.jp2') with self.assertWarns(UserWarning): # This file has an invalid ICC profile - Jp2k(jfile).read() + Jp2k(jfile)[:] self.assertTrue(True) def test_NR_DEC_orb_blue_win_jp2_26_decode(self): jfile = opj_data_file('input/nonregression/orb-blue10-win-jp2.jp2') with self.assertWarns(UserWarning): - Jp2k(jfile).read() + Jp2k(jfile)[:] self.assertTrue(True) @@ -590,7 +590,7 @@ class TestSuite2point0(unittest.TestCase): def test_ETS_C1P0_p0_10_j2k(self): jfile = opj_data_file('input/conformance/p0_10.j2k') jp2k = Jp2k(jfile) - jpdata = jp2k.read(rlevel=0) + jpdata = jp2k[:] pgxfile = opj_data_file('baseline/conformance/c1p0_10_0.pgx') pgxdata = read_pgx(pgxfile) @@ -611,7 +611,7 @@ class TestSuite2point0(unittest.TestCase): with self.assertRaises(IOError): with self.assertWarns(UserWarning): # Invalid marker ID. - Jp2k(jfile).read() + Jp2k(jfile)[:] self.assertTrue(True) @unittest.skipIf(WARNING_INFRASTRUCTURE_ISSUE, WARNING_INFRASTRUCTURE_MSG) @@ -620,7 +620,7 @@ class TestSuite2point0(unittest.TestCase): with self.assertRaises(IOError): with self.assertWarns(UserWarning): # invalid number of subbands, bad marker ID - Jp2k(jfile).read() + Jp2k(jfile)[:] self.assertTrue(True) @unittest.skipIf(WARNING_INFRASTRUCTURE_ISSUE, WARNING_INFRASTRUCTURE_MSG) @@ -632,9 +632,9 @@ class TestSuite2point0(unittest.TestCase): if glymur.version.openjpeg_version_tuple[0] < 2: with self.assertWarns(UserWarning): # Incorrect warning issued about tile parts. - Jp2k(jfile).read() + Jp2k(jfile)[:] else: - Jp2k(jfile).read() + Jp2k(jfile)[:] self.assertTrue(True) From c15fe52f82e11d83264068edd55ab93daf2bf0ad Mon Sep 17 00:00:00 2001 From: jevans Date: Wed, 12 Nov 2014 20:53:13 -0500 Subject: [PATCH 03/23] progress --- glymur/test/test_opj_suite_neg.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/glymur/test/test_opj_suite_neg.py b/glymur/test/test_opj_suite_neg.py index 058be42..440ebaa 100644 --- a/glymur/test/test_opj_suite_neg.py +++ b/glymur/test/test_opj_suite_neg.py @@ -121,7 +121,7 @@ class TestSuiteNegative(unittest.TestCase): def test_precinct_size_not_p2(self): """precinct sizes should be powers of two.""" ifile = Jp2k(self.j2kfile) - data = ifile.read(rlevel=2) + data = ifile[::4, ::4] with tempfile.NamedTemporaryFile(suffix='.jp2') as tfile: ofile = Jp2k(tfile.name, 'wb') with self.assertRaises(IOError): @@ -131,7 +131,7 @@ class TestSuiteNegative(unittest.TestCase): def test_cblk_size_not_power_of_two(self): """code block sizes should be powers of two.""" ifile = Jp2k(self.j2kfile) - data = ifile.read(rlevel=2) + data = ifile[::4, ::4] with tempfile.NamedTemporaryFile(suffix='.jp2') as tfile: ofile = Jp2k(tfile.name, 'wb') with self.assertRaises(IOError): @@ -141,7 +141,7 @@ class TestSuiteNegative(unittest.TestCase): def test_cblk_size_precinct_size(self): """code block sizes should never exceed half that of precinct size.""" ifile = Jp2k(self.j2kfile) - data = ifile.read(rlevel=2) + data = ifile[::4, ::4] with tempfile.NamedTemporaryFile(suffix='.jp2') as tfile: ofile = Jp2k(tfile.name, 'wb') with self.assertRaises(IOError): From 82a9edae6246c2703b12887f85af01e606039de6 Mon Sep 17 00:00:00 2001 From: jevans Date: Wed, 12 Nov 2014 21:09:09 -0500 Subject: [PATCH 04/23] progress --- glymur/jp2k.py | 4 ++-- glymur/test/test_jp2k.py | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/glymur/jp2k.py b/glymur/jp2k.py index 25efacd..a33d466 100644 --- a/glymur/jp2k.py +++ b/glymur/jp2k.py @@ -966,7 +966,7 @@ class Jp2k(Jp2kBox): numrows if rows.stop is None else rows.stop, numcols if cols.stop is None else cols.stop ) - data = self.read(area=area, rlevel=rlevel) + data = self._read(area=area, rlevel=rlevel) if len(pargs) == 2: return data @@ -974,7 +974,7 @@ class Jp2k(Jp2kBox): return data[:, :, bands] - def _read(self): + def _read(self, **kwargs): """Read a JPEG 2000 image. Returns diff --git a/glymur/test/test_jp2k.py b/glymur/test/test_jp2k.py index 5e28db0..dda8161 100644 --- a/glymur/test/test_jp2k.py +++ b/glymur/test/test_jp2k.py @@ -1379,7 +1379,7 @@ class TestJp2kOpjDataRoot(unittest.TestCase): # Should be able to manually reconstruct the RGB image from the palette # and indices. - palette = j.box[2].box[1].palette + palette = jp2.box[2].box[1].palette rgb_from_idx = np.zeros(rgb.shape, dtype=np.uint8) for r in np.arange(rgb.shape[0]): for c in np.arange(rgb.shape[1]): From 4f2a896eff2a0707b494fb8db95fa09b1be9dd19 Mon Sep 17 00:00:00 2001 From: jevans Date: Thu, 13 Nov 2014 13:39:36 -0500 Subject: [PATCH 05/23] ignore_pclr_cmap_cdef is now a property --- glymur/jp2k.py | 49 ++++++++++++++++++------------- glymur/test/test_jp2k.py | 9 ++++-- glymur/test/test_opj_suite_2p1.py | 4 +-- glymur/test/test_printing.py | 2 +- 4 files changed, 37 insertions(+), 27 deletions(-) diff --git a/glymur/jp2k.py b/glymur/jp2k.py index a33d466..f7271dd 100644 --- a/glymur/jp2k.py +++ b/glymur/jp2k.py @@ -60,6 +60,11 @@ class Jp2k(Jp2kBox): List of top-level boxes in the file. Each box may in turn contain its own list of boxes. Will be empty if the file consists only of a raw codestream. + shape : tuple + Size of the image. + ignore_pclr_cmap_cdef : bool + Whether or not to ignore the pclr, cmap, or cdef boxes during any + color transformation. Defaults to False. Examples -------- @@ -95,11 +100,20 @@ class Jp2k(Jp2kBox): self._codec_format = None self._colorspace = None self._shape = None + self._ignore_pclr_cmap_cdef = False # Parse the file for JP2/JPX contents only if we are reading it. if mode == 'rb': self.parse() + @property + def ignore_pclr_cmap_cdef(self): + return self._ignore_pclr_cmap_cdef + + @ignore_pclr_cmap_cdef.setter + def ignore_pclr_cmap_cdef(self, ignore_pclr_cmap_cdef): + self._ignore_pclr_cmap_cdef = ignore_pclr_cmap_cdef + @property def shape(self): if self._shape is not None: @@ -1009,9 +1023,6 @@ class Jp2k(Jp2kBox): (first_row, first_col, last_row, last_col) tile : int, optional Number of tile to decode. - ignore_pclr_cmap_cdef : bool - Whether or not to ignore the pclr, cmap, or cdef boxes during any - color transformation. Defaults to False. verbose : bool, optional Print informational messages produced by the OpenJPEG library. @@ -1025,6 +1036,8 @@ class Jp2k(Jp2kBox): IOError If the image has differing subsample factors. """ + if 'ignore_pclr_cmap_cdef' in kwargs: + self.ignore_pclr_cmap_cdef = kwargs['ignore_pclr_cmap_cdef'] warnings.warn("Use array-style slicing instead.", DeprecationWarning) if version.openjpeg_version_tuple[0] < 2: img = self._read_openjpeg(**kwargs) @@ -1044,8 +1057,7 @@ class Jp2k(Jp2kBox): msg += "the read_bands method instead." raise RuntimeError(msg) - def _read_openjpeg(self, rlevel=0, ignore_pclr_cmap_cdef=False, - verbose=False, area=None): + def _read_openjpeg(self, rlevel=0, verbose=False, area=None): """Read a JPEG 2000 image using libopenjpeg. Parameters @@ -1053,9 +1065,6 @@ class Jp2k(Jp2kBox): rlevel : int, optional Factor by which to rlevel output resolution. Use -1 to get the lowest resolution thumbnail. - ignore_pclr_cmap_cdef : bool - Whether or not to ignore the pclr, cmap, or cdef boxes during any - color transformation. Defaults to False. verbose : bool, optional Print informational messages produced by the OpenJPEG library. area : tuple, optional @@ -1074,7 +1083,7 @@ class Jp2k(Jp2kBox): """ self._subsampling_sanity_check() - self._populate_dparams(rlevel, ignore_pclr_cmap_cdef) + self._populate_dparams(rlevel) with ExitStack() as stack: try: @@ -1127,8 +1136,7 @@ class Jp2k(Jp2kBox): return data - def _read_openjp2(self, rlevel=0, layer=0, area=None, tile=None, - verbose=False, ignore_pclr_cmap_cdef=False): + def _read_openjp2(self, rlevel=0, layer=0, area=None, tile=None, verbose=False): """Read a JPEG 2000 image using libopenjp2. Parameters @@ -1158,8 +1166,7 @@ class Jp2k(Jp2kBox): """ self._subsampling_sanity_check() - self._populate_dparams(rlevel, ignore_pclr_cmap_cdef, - layer=layer, tile=tile, area=area) + self._populate_dparams(rlevel, layer=layer, tile=tile, area=area) with ExitStack() as stack: if re.match("2.1", version.openjpeg_version): @@ -1203,8 +1210,7 @@ class Jp2k(Jp2kBox): return img_array - def _populate_dparams(self, rlevel, ignore_pclr_cmap_cdef, tile=None, - layer=None, area=None): + def _populate_dparams(self, rlevel, tile=None, layer=None, area=None): """Populate decompression structure with appropriate input parameters. Parameters @@ -1218,9 +1224,6 @@ class Jp2k(Jp2kBox): (first_row, first_col, last_row, last_col) tile : int Number of tile to decode. - ignore_pclr_cmap_cdef : bool - Whether or not to ignore the pclr, cmap, or cdef boxes during any - color transformation. Defaults to False. """ if opj2.OPENJP2 is not None: dparam = opj2.set_default_decoder_parameters() @@ -1233,6 +1236,10 @@ class Jp2k(Jp2kBox): infile += b'0' * nelts dparam.infile = infile + if self.ignore_pclr_cmap_cdef: + # Return raw codestream components. + dparam.flags |= 1 + dparam.decod_format = self._codec_format if layer is not None: @@ -1267,7 +1274,7 @@ class Jp2k(Jp2kBox): dparam.tile_index = tile dparam.nb_tile_to_decode = 1 - if ignore_pclr_cmap_cdef is True: + if self.ignore_pclr_cmap_cdef: # Return raw codestream components. dparam.flags |= 1 @@ -1319,8 +1326,8 @@ class Jp2k(Jp2kBox): "OpenJPEG installed before using this " "functionality.") - self._populate_dparams(rlevel, ignore_pclr_cmap_cdef, - layer=layer, tile=tile, area=area) + self.ignore_pclr_cmap_cdef = ignore_pclr_cmap_cdef + self._populate_dparams(rlevel, layer=layer, tile=tile, area=area) with ExitStack() as stack: if re.match("2.1", version.openjpeg_version): diff --git a/glymur/test/test_jp2k.py b/glymur/test/test_jp2k.py index dda8161..f615cc4 100644 --- a/glymur/test/test_jp2k.py +++ b/glymur/test/test_jp2k.py @@ -548,7 +548,8 @@ class TestJp2k(unittest.TestCase): """Indices for pclr jpxfile if no color transform""" j = Jp2k(self.jpxfile) rgb = j[:] - idx = j.read(ignore_pclr_cmap_cdef=True) + j.ignore_pclr_cmap_cdef = True + idx = j[:] nr, nc = 1024, 1024 self.assertEqual(rgb.shape, (nr, nc, 3)) self.assertEqual(idx.shape, (nr, nc)) @@ -1373,7 +1374,8 @@ class TestJp2kOpjDataRoot(unittest.TestCase): with self.assertWarns(UserWarning): jp2 = Jp2k(filename) rgb = jp2[:] - idx = jp2.read(ignore_pclr_cmap_cdef=True) + jp2.ignore_pclr_cmap_cdef = True + idx = jp2[:] self.assertEqual(rgb.shape, (512, 768, 3)) self.assertEqual(idx.shape, (512, 768)) @@ -1407,7 +1409,8 @@ class TestJp2kOpjDataRoot(unittest.TestCase): # The file has a bad compatibility list entry. Not important here. j = Jp2k(filename) ycbcr = j[:] - crcby = j.read(ignore_pclr_cmap_cdef=True) + j.ignore_pclr_cmap_cdef = True + crcby = j[:] expected = np.zeros(ycbcr.shape, ycbcr.dtype) for k in range(crcby.shape[2]): diff --git a/glymur/test/test_opj_suite_2p1.py b/glymur/test/test_opj_suite_2p1.py index addc48b..b151842 100644 --- a/glymur/test/test_opj_suite_2p1.py +++ b/glymur/test/test_opj_suite_2p1.py @@ -134,7 +134,7 @@ class TestSuite2point1(unittest.TestCase): jfile = opj_data_file('input/conformance/p1_04.j2k') jp2k = Jp2k(jfile) tdata = jp2k.read(tile=63, rlevel=2) # last tile - odata = jp2k.read(rlevel=2) + odata = jp2k[::4, ::4] np.testing.assert_array_equal(tdata, odata[224:256, 224:256]) def test_NR_DEC_p1_04_j2k_59_decode(self): @@ -148,7 +148,7 @@ class TestSuite2point1(unittest.TestCase): jfile = opj_data_file('input/conformance/p1_04.j2k') jp2k = Jp2k(jfile) tdata = jp2k.read(tile=12, rlevel=1) # 2nd row, 5th column - odata = jp2k.read(rlevel=1) + odata = jp2k[::2, ::2] np.testing.assert_array_equal(tdata, odata[64:128, 256:320]) @unittest.skipIf(WARNING_INFRASTRUCTURE_ISSUE, WARNING_INFRASTRUCTURE_MSG) diff --git a/glymur/test/test_printing.py b/glymur/test/test_printing.py index 7a5f9b9..5c09c81 100644 --- a/glymur/test/test_printing.py +++ b/glymur/test/test_printing.py @@ -111,7 +111,7 @@ class TestPrinting(unittest.TestCase): """verify printing of asoc, label boxes""" # Construct a fake file with an asoc and a label box, as # OpenJPEG doesn't have such a file. - data = glymur.Jp2k(self.jp2file).read(rlevel=1) + data = glymur.Jp2k(self.jp2file)[::2, ::2] with tempfile.NamedTemporaryFile(suffix='.jp2') as tfile: j = glymur.Jp2k(tfile.name, 'wb') j.write(data) From 4f1c34991fc4de349495280d8af51f5cdfa2c15c Mon Sep 17 00:00:00 2001 From: jevans Date: Mon, 17 Nov 2014 07:33:43 -0500 Subject: [PATCH 06/23] replacing more uses of read function with array-style slicing --- glymur/jp2k.py | 4 +- glymur/test/test_opj_suite_2p1.py | 96 +++++++++++++++---------------- 2 files changed, 50 insertions(+), 50 deletions(-) diff --git a/glymur/jp2k.py b/glymur/jp2k.py index f7271dd..a45f9e2 100644 --- a/glymur/jp2k.py +++ b/glymur/jp2k.py @@ -894,7 +894,7 @@ class Jp2k(Jp2kBox): # This retrieves a single row. row = pargs area = (row, 0, row + 1, numcols) - return self.read(area=area).squeeze() + return self._read(area=area).squeeze() if pargs is Ellipsis: # Case of jp2[...] @@ -903,7 +903,7 @@ class Jp2k(Jp2kBox): if isinstance(pargs, slice): if pargs.start is None and pargs.stop is None and pargs.step is None: # Case of jp2[:] - return self.read() + return self._read() # Corner case of jp2[x] where x is a slice object with non-null # members. Just augment it with an ellipsis and let the code diff --git a/glymur/test/test_opj_suite_2p1.py b/glymur/test/test_opj_suite_2p1.py index b151842..0fec986 100644 --- a/glymur/test/test_opj_suite_2p1.py +++ b/glymur/test/test_opj_suite_2p1.py @@ -61,27 +61,27 @@ class TestSuite2point1(unittest.TestCase): with self.assertWarns(UserWarning): # brand is 'jp2 ', but has any icc profile. jp2 = Jp2k(jfile) - jp2.read() + jp2[:] self.assertTrue(True) def test_NR_DEC_kodak_2layers_lrcp_j2c_31_decode(self): jfile = opj_data_file('input/nonregression/kodak_2layers_lrcp.j2c') - Jp2k(jfile).read() + Jp2k(jfile)[:] self.assertTrue(True) def test_NR_DEC_kodak_2layers_lrcp_j2c_32_decode(self): jfile = opj_data_file('input/nonregression/kodak_2layers_lrcp.j2c') - Jp2k(jfile).read(layer=2) + Jp2k(jfile)[::4, ::4] self.assertTrue(True) def test_NR_DEC_issue104_jpxstream_jp2_33_decode(self): jfile = opj_data_file('input/nonregression/issue104_jpxstream.jp2') - Jp2k(jfile).read() + Jp2k(jfile)[:] self.assertTrue(True) def test_NR_DEC_mem_b2b86b74_2753_jp2_35_decode(self): jfile = opj_data_file('input/nonregression/mem-b2b86b74-2753.jp2') - Jp2k(jfile).read() + Jp2k(jfile)[:] self.assertTrue(True) @unittest.skipIf(WARNING_INFRASTRUCTURE_ISSUE, WARNING_INFRASTRUCTURE_MSG) @@ -92,7 +92,7 @@ class TestSuite2point1(unittest.TestCase): # Invalid number of resolutions. j = Jp2k(jfile) with self.assertRaises(IOError): - j.read() + j[:] @unittest.skipIf(WARNING_INFRASTRUCTURE_ISSUE, WARNING_INFRASTRUCTURE_MSG) def test_NR_DEC_gdal_fuzzer_check_number_of_tiles_jp2_38_decode(self): @@ -102,7 +102,7 @@ class TestSuite2point1(unittest.TestCase): # Invalid number of tiles. j = Jp2k(jfile) with self.assertRaises(IOError): - j.read() + j[:] @unittest.skipIf(WARNING_INFRASTRUCTURE_ISSUE, WARNING_INFRASTRUCTURE_MSG) def test_NR_DEC_gdal_fuzzer_check_comp_dx_dy_jp2_39_decode(self): @@ -111,23 +111,23 @@ class TestSuite2point1(unittest.TestCase): with self.assertWarns(UserWarning): # Invalid subsampling value with self.assertRaises(IOError): - Jp2k(jfile).read() + Jp2k(jfile)[:] def test_NR_DEC_file_409752_jp2_40_decode(self): jfile = opj_data_file('input/nonregression/file409752.jp2') with self.assertRaises(RuntimeError): - Jp2k(jfile).read() + Jp2k(jfile)[:] def test_NR_DEC_issue206_image_000_jp2_42_decode(self): jfile = opj_data_file('input/nonregression/issue206_image-000.jp2') - Jp2k(jfile).read() + Jp2k(jfile)[:] self.assertTrue(True) def test_NR_DEC_p1_04_j2k_57_decode(self): jfile = opj_data_file('input/conformance/p1_04.j2k') jp2k = Jp2k(jfile) tdata = jp2k.read(tile=63) # last tile - odata = jp2k.read() + odata = jp2k[:] np.testing.assert_array_equal(tdata, odata[896:1024, 896:1024]) def test_NR_DEC_p1_04_j2k_58_decode(self): @@ -141,7 +141,7 @@ class TestSuite2point1(unittest.TestCase): jfile = opj_data_file('input/conformance/p1_04.j2k') jp2k = Jp2k(jfile) tdata = jp2k.read(tile=12) # 2nd row, 5th column - odata = jp2k.read() + odata = jp2k[:] np.testing.assert_array_equal(tdata, odata[128:256, 512:640]) def test_NR_DEC_p1_04_j2k_60_decode(self): @@ -161,7 +161,7 @@ class TestSuite2point1(unittest.TestCase): # Invalid component number. j = Jp2k(jfile) with self.assertRaises(IOError): - j.read() + j[:] @unittest.skipIf(OPJ_DATA_ROOT is None, "OPJ_DATA_ROOT environment variable not set") @@ -179,164 +179,164 @@ class TestReadArea(unittest.TestCase): jfile = opj_data_file('input/conformance/p1_04.j2k') self.j2k = Jp2k(jfile) - self.j2k_data = self.j2k.read() - self.j2k_half_data = self.j2k.read(rlevel=1) - self.j2k_quarter_data = self.j2k.read(rlevel=2) + self.j2k_data = self.j2k[:] + self.j2k_half_data = self.j2k[::2, ::2] + self.j2k_quarter_data = self.j2k[::4, ::4] jfile = opj_data_file('input/conformance/p1_06.j2k') self.j2k_p1_06 = Jp2k(jfile) def test_NR_DEC_p1_04_j2k_43_decode(self): - actual = self.j2k.read(area=(0, 0, 1024, 1024)) + actual = self.j2k[:1024, :1024] expected = self.j2k_data np.testing.assert_array_equal(actual, expected) def test_NR_DEC_p1_04_j2k_44_decode(self): - actual = self.j2k.read(area=(640, 512, 768, 640)) + actual = self.j2k[640:768, 512:640] expected = self.j2k_data[640:768, 512:640] np.testing.assert_array_equal(actual, expected) def test_NR_DEC_p1_04_j2k_45_decode(self): - actual = self.j2k.read(area=(896, 896, 1024, 1024)) + actual = self.j2k[896:1024, 896:1024] expected = self.j2k_data[896:1024, 896:1024] np.testing.assert_array_equal(actual, expected) def test_NR_DEC_p1_04_j2k_46_decode(self): - actual = self.j2k.read(area=(500, 100, 800, 300)) + actual = self.j2k[500:800, 100:300] expected = self.j2k_data[500:800, 100:300] np.testing.assert_array_equal(actual, expected) def test_NR_DEC_p1_04_j2k_47_decode(self): - actual = self.j2k.read(area=(520, 260, 600, 360)) + actual = self.j2k[520:600, 260:360] expected = self.j2k_data[520:600, 260:360] np.testing.assert_array_equal(actual, expected) def test_NR_DEC_p1_04_j2k_48_decode(self): - actual = self.j2k.read(area=(520, 260, 660, 360)) + actual = self.j2k[520:660, 260:360] expected = self.j2k_data[520:660, 260:360] np.testing.assert_array_equal(actual, expected) def test_NR_DEC_p1_04_j2k_49_decode(self): - actual = self.j2k.read(area=(520, 360, 600, 400)) + actual = self.j2k[520:600, 360:400] expected = self.j2k_data[520:600, 360:400] np.testing.assert_array_equal(actual, expected) def test_NR_DEC_p1_04_j2k_50_decode(self): - actual = self.j2k.read(area=(0, 0, 1024, 1024), rlevel=2) + actual = self.j2k[:1024:4, :1024:4] expected = self.j2k_quarter_data np.testing.assert_array_equal(actual, expected) def test_NR_DEC_p1_04_j2k_51_decode(self): - actual = self.j2k.read(area=(640, 512, 768, 640), rlevel=2) + actual = self.j2k[640:768:4, 512:640:4] expected = self.j2k_quarter_data[160:192, 128:160] np.testing.assert_array_equal(actual, expected) def test_NR_DEC_p1_04_j2k_52_decode(self): - actual = self.j2k.read(area=(896, 896, 1024, 1024), rlevel=2) + actual = self.j2k[896:1024:4, 896:1024:4] expected = self.j2k_quarter_data[224:352, 224:352] np.testing.assert_array_equal(actual, expected) def test_NR_DEC_p1_04_j2k_53_decode(self): - actual = self.j2k.read(area=(500, 100, 800, 300), rlevel=2) + actual = self.j2k[500:800:4, 100:300:4] expected = self.j2k_quarter_data[125:200, 25:75] np.testing.assert_array_equal(actual, expected) def test_NR_DEC_p1_04_j2k_54_decode(self): - actual = self.j2k.read(area=(520, 260, 600, 360), rlevel=2) + actual = self.j2k[520:600:4, 260:360:4] expected = self.j2k_quarter_data[130:150, 65:90] np.testing.assert_array_equal(actual, expected) def test_NR_DEC_p1_04_j2k_55_decode(self): - actual = self.j2k.read(area=(520, 260, 660, 360), rlevel=2) + actual = self.j2k[520:660:4, 260:360:4] expected = self.j2k_quarter_data[130:165, 65:90] np.testing.assert_array_equal(actual, expected) def test_NR_DEC_p1_04_j2k_56_decode(self): - actual = self.j2k.read(area=(520, 360, 600, 400), rlevel=2) + actual = self.j2k[520:600:4, 360:400:4] expected = self.j2k_quarter_data[130:150, 90:100] np.testing.assert_array_equal(actual, expected) def test_NR_DEC_p1_06_j2k_70_decode(self): - actual = self.j2k_p1_06.read(area=(9, 9, 12, 12), rlevel=1) + actual = self.j2k_p1_06[9:12:2, 9:12:2] self.assertEqual(actual.shape, (1, 1, 3)) def test_NR_DEC_p1_06_j2k_71_decode(self): - actual = self.j2k_p1_06.read(area=(10, 4, 12, 10), rlevel=1) + actual = self.j2k_p1_06[10:12:2, 4:10:2] self.assertEqual(actual.shape, (1, 3, 3)) def test_NR_DEC_p1_06_j2k_72_decode(self): - ssdata = self.j2k_p1_06.read(area=(3, 3, 9, 9), rlevel=1) + ssdata = self.j2k_p1_06[3:9:2, 3:9:2] self.assertEqual(ssdata.shape, (3, 3, 3)) def test_NR_DEC_p1_06_j2k_73_decode(self): - ssdata = self.j2k_p1_06.read(area=(4, 4, 7, 7), rlevel=1) + ssdata = self.j2k_p1_06[4:7:2, 4:7:2] self.assertEqual(ssdata.shape, (2, 2, 3)) def test_NR_DEC_p1_06_j2k_74_decode(self): - ssdata = self.j2k_p1_06.read(area=(4, 4, 5, 5), rlevel=1) + ssdata = self.j2k_p1_06[4:5:2, 4:5:2] self.assertEqual(ssdata.shape, (1, 1, 3)) def test_NR_DEC_p1_06_j2k_75_decode(self): # Image size would be 0 x 0. with self.assertRaises((IOError, OSError)): - self.j2k_p1_06.read(area=(9, 9, 12, 12), rlevel=2) + self.j2k_p1_06[9:12:4, 9:12:4] def test_NR_DEC_p0_04_j2k_85_decode(self): - actual = self.j2k.read(area=(0, 0, 256, 256)) + actual = self.j2k[:256, :256] expected = self.j2k_data[:256, :256] np.testing.assert_array_equal(actual, expected) def test_NR_DEC_p0_04_j2k_86_decode(self): - actual = self.j2k.read(area=(0, 128, 128, 256)) + actual = self.j2k[:128, 128:256] expected = self.j2k_data[:128, 128:256] np.testing.assert_array_equal(actual, expected) def test_NR_DEC_p0_04_j2k_87_decode(self): - actual = self.j2k.read(area=(10, 50, 200, 120)) + actual = self.j2k[10:200, 50:120] expected = self.j2k_data[10:200, 50:120] np.testing.assert_array_equal(actual, expected) def test_NR_DEC_p0_04_j2k_88_decode(self): - actual = self.j2k.read(area=(150, 10, 210, 190)) + actual = self.j2k[150:210, 10:190] expected = self.j2k_data[150:210, 10:190] np.testing.assert_array_equal(actual, expected) def test_NR_DEC_p0_04_j2k_89_decode(self): - actual = self.j2k.read(area=(80, 100, 150, 200)) + actual = self.j2k[80:150, 100:200] expected = self.j2k_data[80:150, 100:200] np.testing.assert_array_equal(actual, expected) def test_NR_DEC_p0_04_j2k_90_decode(self): - actual = self.j2k.read(area=(20, 150, 50, 200)) + actual = self.j2k[20:50, 150:200] expected = self.j2k_data[20:50, 150:200] np.testing.assert_array_equal(actual, expected) def test_NR_DEC_p0_04_j2k_91_decode(self): - actual = self.j2k.read(area=(0, 0, 256, 256), rlevel=2) + actual = self.j2k[:256:4, :256:4] expected = self.j2k_quarter_data[0:64, 0:64] np.testing.assert_array_equal(actual, expected) def test_NR_DEC_p0_04_j2k_92_decode(self): - actual = self.j2k.read(area=(0, 128, 128, 256), rlevel=2) + actual = self.j2k[:128:4, 128:256:4] expected = self.j2k_quarter_data[:32, 32:64] np.testing.assert_array_equal(actual, expected) def test_NR_DEC_p0_04_j2k_93_decode(self): - actual = self.j2k.read(area=(10, 50, 200, 120), rlevel=2) + actual = self.j2k[10:200:4, 50:120:4] expected = self.j2k_quarter_data[3:50, 13:30] np.testing.assert_array_equal(actual, expected) def test_NR_DEC_p0_04_j2k_94_decode(self): - actual = self.j2k.read(area=(150, 10, 210, 190), rlevel=2) + actual = self.j2k[150:210:4, 10:190:4] expected = self.j2k_quarter_data[38:53, 3:48] np.testing.assert_array_equal(actual, expected) def test_NR_DEC_p0_04_j2k_95_decode(self): - actual = self.j2k.read(area=(80, 100, 150, 200), rlevel=2) + actual = self.j2k[80:150:4, 100:200:4] expected = self.j2k_quarter_data[20:38, 25:50] np.testing.assert_array_equal(actual, expected) def test_NR_DEC_p0_04_j2k_96_decode(self): - actual = self.j2k.read(area=(20, 150, 50, 200), rlevel=2) + actual = self.j2k[20:50:4, 150:200:4] expected = self.j2k_quarter_data[5:13, 38:50] np.testing.assert_array_equal(actual, expected) From 63d6a2f1e18e7d3adfbda0a14776e62c3c6a2753 Mon Sep 17 00:00:00 2001 From: jevans Date: Mon, 17 Nov 2014 18:17:47 -0500 Subject: [PATCH 07/23] progress --- glymur/test/test_opj_suite_2p1.py | 60 ++++++++++++++++++++++++++++--- 1 file changed, 56 insertions(+), 4 deletions(-) diff --git a/glymur/test/test_opj_suite_2p1.py b/glymur/test/test_opj_suite_2p1.py index 0fec986..12bffcf 100644 --- a/glymur/test/test_opj_suite_2p1.py +++ b/glymur/test/test_opj_suite_2p1.py @@ -30,6 +30,7 @@ suite. import re import sys import unittest +import warnings import numpy as np @@ -41,6 +42,24 @@ from .fixtures import WARNING_INFRASTRUCTURE_ISSUE, WARNING_INFRASTRUCTURE_MSG from .fixtures import mse, peak_tolerance, read_pgx, opj_data_file +@unittest.skipIf(OPJ_DATA_ROOT is None, + "OPJ_DATA_ROOT environment variable not set") +@unittest.skipIf(re.match(r'''(1|2.0.0)''', + glymur.version.openjpeg_version) is not None, + "Only supported in 2.0.1 or higher") +#class TestVersion0p7BackwardsCompatibility(unittest.TestSuite): +class TestBlah(unittest.TestSuite): + """ + Tests for backwards compatibility with version 0.7. + """ + + def test_blah_NR_DEC_p1_04_j2k_57_decode(self): + jfile = opj_data_file('input/conformance/p1_04.j2k') + jp2k = Jp2k(jfile) + tdata = jp2k.read(tile=63) # last tile + odata = jp2k[:] + np.testing.assert_array_equal(tdata, odata[896:1024, 896:1024]) + @unittest.skipIf(OPJ_DATA_ROOT is None, "OPJ_DATA_ROOT environment variable not set") @unittest.skipIf(re.match(r'''(1|2.0.0)''', @@ -126,28 +145,61 @@ class TestSuite2point1(unittest.TestCase): def test_NR_DEC_p1_04_j2k_57_decode(self): jfile = opj_data_file('input/conformance/p1_04.j2k') jp2k = Jp2k(jfile) - tdata = jp2k.read(tile=63) # last tile + tdata = jp2k[896:1024, 896:1024] # last tile odata = jp2k[:] np.testing.assert_array_equal(tdata, odata[896:1024, 896:1024]) + def test_NR_DEC_p1_04_j2k_57_decode_0p7_backwards_compatibility(self): + """ + 0.7.x usage deprecated + """ + jfile = opj_data_file('input/conformance/p1_04.j2k') + jp2k = Jp2k(jfile) + if sys.hexversion < 0x03000000: + with warnings.catch_warnings(): + # Suppress a warning due to deprecated syntax + warnings.simplefilter("ignore") + tdata = jp2k.read(tile=63) # last tile + else: + with self.assertWarns(DeprecationWarning): + tdata = jp2k.read(tile=63) # last tile + odata = jp2k[:] + np.testing.assert_array_equal(tdata, odata[896:1024, 896:1024]) + + def test_NR_DEC_p1_04_j2k_58_decode_0p7_backwards_compatibility(self): + """ + 0.7.x usage deprecated + """ + jfile = opj_data_file('input/conformance/p1_04.j2k') + jp2k = Jp2k(jfile) + if sys.hexversion < 0x03000000: + with warnings.catch_warnings(): + # Suppress a warning due to deprecated syntax + tdata = jp2k.read(tile=63, rlevel=2) # last tile + else: + with self.assertWarns(DeprecationWarning): + tdata = jp2k.read(tile=63, rlevel=2) # last tile + odata = jp2k[::4, ::4] + np.testing.assert_array_equal(tdata, odata[224:256, 224:256]) + def test_NR_DEC_p1_04_j2k_58_decode(self): jfile = opj_data_file('input/conformance/p1_04.j2k') jp2k = Jp2k(jfile) - tdata = jp2k.read(tile=63, rlevel=2) # last tile + tdata = jp2k[896:1024:4, 896:1024:4] # last tile odata = jp2k[::4, ::4] np.testing.assert_array_equal(tdata, odata[224:256, 224:256]) def test_NR_DEC_p1_04_j2k_59_decode(self): jfile = opj_data_file('input/conformance/p1_04.j2k') jp2k = Jp2k(jfile) - tdata = jp2k.read(tile=12) # 2nd row, 5th column + tdata = jp2k[128:256, 512:640] # 2nd row, 5th column odata = jp2k[:] np.testing.assert_array_equal(tdata, odata[128:256, 512:640]) def test_NR_DEC_p1_04_j2k_60_decode(self): jfile = opj_data_file('input/conformance/p1_04.j2k') jp2k = Jp2k(jfile) - tdata = jp2k.read(tile=12, rlevel=1) # 2nd row, 5th column + tdata = jp2k[128:256:2, 512:640:2] # 2nd row, 5th column odata = jp2k[::2, ::2] np.testing.assert_array_equal(tdata, odata[64:128, 256:320]) From 2a3128e983c23422bc4f5c857f1c4c05b63061d6 Mon Sep 17 00:00:00 2001 From: jevans Date: Mon, 17 Nov 2014 22:27:52 -0500 Subject: [PATCH 08/23] subsumed test_opj_suite_2p1 ito test_opj_suite --- glymur/test/test_opj_suite.py | 334 ++++++++++++++++++++++++- glymur/test/test_opj_suite_2p1.py | 394 ------------------------------ 2 files changed, 332 insertions(+), 396 deletions(-) delete mode 100644 glymur/test/test_opj_suite_2p1.py diff --git a/glymur/test/test_opj_suite.py b/glymur/test/test_opj_suite.py index a10185b..1dd4026 100644 --- a/glymur/test/test_opj_suite.py +++ b/glymur/test/test_opj_suite.py @@ -638,5 +638,335 @@ class TestSuite2point0(unittest.TestCase): self.assertTrue(True) -if __name__ == "__main__": - unittest.main() +@unittest.skipIf(OPJ_DATA_ROOT is None, + "OPJ_DATA_ROOT environment variable not set") +@unittest.skipIf(re.match(r'''(1|2.0.0)''', + glymur.version.openjpeg_version) is not None, + "Only supported in 2.0.1 or higher") +class TestSuite2point1(unittest.TestCase): + """Runs tests introduced in version 2.0+ or that pass only in 2.0+""" + + def setUp(self): + pass + + def tearDown(self): + pass + + @unittest.skipIf(WARNING_INFRASTRUCTURE_ISSUE, WARNING_INFRASTRUCTURE_MSG) + def test_NR_DEC_text_GBR_jp2_29_decode(self): + jfile = opj_data_file('input/nonregression/text_GBR.jp2') + with self.assertWarns(UserWarning): + # brand is 'jp2 ', but has any icc profile. + jp2 = Jp2k(jfile) + jp2[:] + self.assertTrue(True) + + def test_NR_DEC_kodak_2layers_lrcp_j2c_31_decode(self): + jfile = opj_data_file('input/nonregression/kodak_2layers_lrcp.j2c') + Jp2k(jfile)[:] + self.assertTrue(True) + + def test_NR_DEC_kodak_2layers_lrcp_j2c_32_decode(self): + jfile = opj_data_file('input/nonregression/kodak_2layers_lrcp.j2c') + Jp2k(jfile)[::4, ::4] + self.assertTrue(True) + + def test_NR_DEC_issue104_jpxstream_jp2_33_decode(self): + jfile = opj_data_file('input/nonregression/issue104_jpxstream.jp2') + Jp2k(jfile)[:] + self.assertTrue(True) + + def test_NR_DEC_mem_b2b86b74_2753_jp2_35_decode(self): + jfile = opj_data_file('input/nonregression/mem-b2b86b74-2753.jp2') + Jp2k(jfile)[:] + self.assertTrue(True) + + @unittest.skipIf(WARNING_INFRASTRUCTURE_ISSUE, WARNING_INFRASTRUCTURE_MSG) + def test_NR_DEC_gdal_fuzzer_unchecked_num_resolutions_jp2_36_decode(self): + f = 'input/nonregression/gdal_fuzzer_unchecked_numresolutions.jp2' + jfile = opj_data_file(f) + with self.assertWarns(UserWarning): + # Invalid number of resolutions. + j = Jp2k(jfile) + with self.assertRaises(IOError): + j[:] + + @unittest.skipIf(WARNING_INFRASTRUCTURE_ISSUE, WARNING_INFRASTRUCTURE_MSG) + def test_NR_DEC_gdal_fuzzer_check_number_of_tiles_jp2_38_decode(self): + relpath = 'input/nonregression/gdal_fuzzer_check_number_of_tiles.jp2' + jfile = opj_data_file(relpath) + with self.assertWarns(UserWarning): + # Invalid number of tiles. + j = Jp2k(jfile) + with self.assertRaises(IOError): + j[:] + + @unittest.skipIf(WARNING_INFRASTRUCTURE_ISSUE, WARNING_INFRASTRUCTURE_MSG) + def test_NR_DEC_gdal_fuzzer_check_comp_dx_dy_jp2_39_decode(self): + relpath = 'input/nonregression/gdal_fuzzer_check_comp_dx_dy.jp2' + jfile = opj_data_file(relpath) + with self.assertWarns(UserWarning): + # Invalid subsampling value + with self.assertRaises(IOError): + Jp2k(jfile)[:] + + def test_NR_DEC_file_409752_jp2_40_decode(self): + jfile = opj_data_file('input/nonregression/file409752.jp2') + with self.assertRaises(RuntimeError): + Jp2k(jfile)[:] + + def test_NR_DEC_issue206_image_000_jp2_42_decode(self): + jfile = opj_data_file('input/nonregression/issue206_image-000.jp2') + Jp2k(jfile)[:] + self.assertTrue(True) + + def test_NR_DEC_p1_04_j2k_57_decode(self): + jfile = opj_data_file('input/conformance/p1_04.j2k') + jp2k = Jp2k(jfile) + tdata = jp2k[896:1024, 896:1024] # last tile + odata = jp2k[:] + np.testing.assert_array_equal(tdata, odata[896:1024, 896:1024]) + + def test_NR_DEC_p1_04_j2k_57_decode_0p7_backwards_compatibility(self): + """ + 0.7.x usage deprecated + """ + jfile = opj_data_file('input/conformance/p1_04.j2k') + jp2k = Jp2k(jfile) + if sys.hexversion < 0x03000000: + with warnings.catch_warnings(): + # Suppress a warning due to deprecated syntax + warnings.simplefilter("ignore") + tdata = jp2k.read(tile=63) # last tile + else: + with self.assertWarns(DeprecationWarning): + tdata = jp2k.read(tile=63) # last tile + odata = jp2k[:] + np.testing.assert_array_equal(tdata, odata[896:1024, 896:1024]) + + def test_NR_DEC_p1_04_j2k_58_decode_0p7_backwards_compatibility(self): + """ + 0.7.x usage deprecated + """ + jfile = opj_data_file('input/conformance/p1_04.j2k') + jp2k = Jp2k(jfile) + if sys.hexversion < 0x03000000: + with warnings.catch_warnings(): + # Suppress a warning due to deprecated syntax + tdata = jp2k.read(tile=63, rlevel=2) # last tile + else: + with self.assertWarns(DeprecationWarning): + tdata = jp2k.read(tile=63, rlevel=2) # last tile + odata = jp2k[::4, ::4] + np.testing.assert_array_equal(tdata, odata[224:256, 224:256]) + + def test_NR_DEC_p1_04_j2k_58_decode(self): + jfile = opj_data_file('input/conformance/p1_04.j2k') + jp2k = Jp2k(jfile) + tdata = jp2k[896:1024:4, 896:1024:4] # last tile + odata = jp2k[::4, ::4] + np.testing.assert_array_equal(tdata, odata[224:256, 224:256]) + + def test_NR_DEC_p1_04_j2k_59_decode(self): + jfile = opj_data_file('input/conformance/p1_04.j2k') + jp2k = Jp2k(jfile) + tdata = jp2k[128:256, 512:640] # 2nd row, 5th column + odata = jp2k[:] + np.testing.assert_array_equal(tdata, odata[128:256, 512:640]) + + def test_NR_DEC_p1_04_j2k_60_decode(self): + jfile = opj_data_file('input/conformance/p1_04.j2k') + jp2k = Jp2k(jfile) + tdata = jp2k[128:256:2, 512:640:2] # 2nd row, 5th column + odata = jp2k[::2, ::2] + np.testing.assert_array_equal(tdata, odata[64:128, 256:320]) + + @unittest.skipIf(WARNING_INFRASTRUCTURE_ISSUE, WARNING_INFRASTRUCTURE_MSG) + def test_NR_DEC_jp2_36_decode(self): + lst = ('input', + 'nonregression', + 'gdal_fuzzer_assert_in_opj_j2k_read_SQcd_SQcc.patch.jp2') + jfile = opj_data_file('/'.join(lst)) + with self.assertWarns(UserWarning): + # Invalid component number. + j = Jp2k(jfile) + with self.assertRaises(IOError): + j[:] + +@unittest.skipIf(OPJ_DATA_ROOT is None, + "OPJ_DATA_ROOT environment variable not set") +@unittest.skipIf(re.match(r'''(1|2.0.0)''', + glymur.version.openjpeg_version) is not None, + "Only supported in 2.0.1 or higher") +class TestReadArea(unittest.TestCase): + """ + Runs tests introduced in version 2.0+ or that pass only in 2.0+ + + Specifically for read method with area parameter. + """ + @classmethod + def setUpClass(self): + + jfile = opj_data_file('input/conformance/p1_04.j2k') + self.j2k = Jp2k(jfile) + self.j2k_data = self.j2k[:] + self.j2k_half_data = self.j2k[::2, ::2] + self.j2k_quarter_data = self.j2k[::4, ::4] + + jfile = opj_data_file('input/conformance/p1_06.j2k') + self.j2k_p1_06 = Jp2k(jfile) + + def test_NR_DEC_p1_04_j2k_43_decode(self): + actual = self.j2k[:1024, :1024] + expected = self.j2k_data + np.testing.assert_array_equal(actual, expected) + + def test_NR_DEC_p1_04_j2k_44_decode(self): + actual = self.j2k[640:768, 512:640] + expected = self.j2k_data[640:768, 512:640] + np.testing.assert_array_equal(actual, expected) + + def test_NR_DEC_p1_04_j2k_45_decode(self): + actual = self.j2k[896:1024, 896:1024] + expected = self.j2k_data[896:1024, 896:1024] + np.testing.assert_array_equal(actual, expected) + + def test_NR_DEC_p1_04_j2k_46_decode(self): + actual = self.j2k[500:800, 100:300] + expected = self.j2k_data[500:800, 100:300] + np.testing.assert_array_equal(actual, expected) + + def test_NR_DEC_p1_04_j2k_47_decode(self): + actual = self.j2k[520:600, 260:360] + expected = self.j2k_data[520:600, 260:360] + np.testing.assert_array_equal(actual, expected) + + def test_NR_DEC_p1_04_j2k_48_decode(self): + actual = self.j2k[520:660, 260:360] + expected = self.j2k_data[520:660, 260:360] + np.testing.assert_array_equal(actual, expected) + + def test_NR_DEC_p1_04_j2k_49_decode(self): + actual = self.j2k[520:600, 360:400] + expected = self.j2k_data[520:600, 360:400] + np.testing.assert_array_equal(actual, expected) + + def test_NR_DEC_p1_04_j2k_50_decode(self): + actual = self.j2k[:1024:4, :1024:4] + expected = self.j2k_quarter_data + np.testing.assert_array_equal(actual, expected) + + def test_NR_DEC_p1_04_j2k_51_decode(self): + actual = self.j2k[640:768:4, 512:640:4] + expected = self.j2k_quarter_data[160:192, 128:160] + np.testing.assert_array_equal(actual, expected) + + def test_NR_DEC_p1_04_j2k_52_decode(self): + actual = self.j2k[896:1024:4, 896:1024:4] + expected = self.j2k_quarter_data[224:352, 224:352] + np.testing.assert_array_equal(actual, expected) + + def test_NR_DEC_p1_04_j2k_53_decode(self): + actual = self.j2k[500:800:4, 100:300:4] + expected = self.j2k_quarter_data[125:200, 25:75] + np.testing.assert_array_equal(actual, expected) + + def test_NR_DEC_p1_04_j2k_54_decode(self): + actual = self.j2k[520:600:4, 260:360:4] + expected = self.j2k_quarter_data[130:150, 65:90] + np.testing.assert_array_equal(actual, expected) + + def test_NR_DEC_p1_04_j2k_55_decode(self): + actual = self.j2k[520:660:4, 260:360:4] + expected = self.j2k_quarter_data[130:165, 65:90] + np.testing.assert_array_equal(actual, expected) + + def test_NR_DEC_p1_04_j2k_56_decode(self): + actual = self.j2k[520:600:4, 360:400:4] + expected = self.j2k_quarter_data[130:150, 90:100] + np.testing.assert_array_equal(actual, expected) + + def test_NR_DEC_p1_06_j2k_70_decode(self): + actual = self.j2k_p1_06[9:12:2, 9:12:2] + self.assertEqual(actual.shape, (1, 1, 3)) + + def test_NR_DEC_p1_06_j2k_71_decode(self): + actual = self.j2k_p1_06[10:12:2, 4:10:2] + self.assertEqual(actual.shape, (1, 3, 3)) + + def test_NR_DEC_p1_06_j2k_72_decode(self): + ssdata = self.j2k_p1_06[3:9:2, 3:9:2] + self.assertEqual(ssdata.shape, (3, 3, 3)) + + def test_NR_DEC_p1_06_j2k_73_decode(self): + ssdata = self.j2k_p1_06[4:7:2, 4:7:2] + self.assertEqual(ssdata.shape, (2, 2, 3)) + + def test_NR_DEC_p1_06_j2k_74_decode(self): + ssdata = self.j2k_p1_06[4:5:2, 4:5:2] + self.assertEqual(ssdata.shape, (1, 1, 3)) + + def test_NR_DEC_p1_06_j2k_75_decode(self): + # Image size would be 0 x 0. + with self.assertRaises((IOError, OSError)): + self.j2k_p1_06[9:12:4, 9:12:4] + + def test_NR_DEC_p0_04_j2k_85_decode(self): + actual = self.j2k[:256, :256] + expected = self.j2k_data[:256, :256] + np.testing.assert_array_equal(actual, expected) + + def test_NR_DEC_p0_04_j2k_86_decode(self): + actual = self.j2k[:128, 128:256] + expected = self.j2k_data[:128, 128:256] + np.testing.assert_array_equal(actual, expected) + + def test_NR_DEC_p0_04_j2k_87_decode(self): + actual = self.j2k[10:200, 50:120] + expected = self.j2k_data[10:200, 50:120] + np.testing.assert_array_equal(actual, expected) + + def test_NR_DEC_p0_04_j2k_88_decode(self): + actual = self.j2k[150:210, 10:190] + expected = self.j2k_data[150:210, 10:190] + np.testing.assert_array_equal(actual, expected) + + def test_NR_DEC_p0_04_j2k_89_decode(self): + actual = self.j2k[80:150, 100:200] + expected = self.j2k_data[80:150, 100:200] + np.testing.assert_array_equal(actual, expected) + + def test_NR_DEC_p0_04_j2k_90_decode(self): + actual = self.j2k[20:50, 150:200] + expected = self.j2k_data[20:50, 150:200] + np.testing.assert_array_equal(actual, expected) + + def test_NR_DEC_p0_04_j2k_91_decode(self): + actual = self.j2k[:256:4, :256:4] + expected = self.j2k_quarter_data[0:64, 0:64] + np.testing.assert_array_equal(actual, expected) + + def test_NR_DEC_p0_04_j2k_92_decode(self): + actual = self.j2k[:128:4, 128:256:4] + expected = self.j2k_quarter_data[:32, 32:64] + np.testing.assert_array_equal(actual, expected) + + def test_NR_DEC_p0_04_j2k_93_decode(self): + actual = self.j2k[10:200:4, 50:120:4] + expected = self.j2k_quarter_data[3:50, 13:30] + np.testing.assert_array_equal(actual, expected) + + def test_NR_DEC_p0_04_j2k_94_decode(self): + actual = self.j2k[150:210:4, 10:190:4] + expected = self.j2k_quarter_data[38:53, 3:48] + np.testing.assert_array_equal(actual, expected) + + def test_NR_DEC_p0_04_j2k_95_decode(self): + actual = self.j2k[80:150:4, 100:200:4] + expected = self.j2k_quarter_data[20:38, 25:50] + np.testing.assert_array_equal(actual, expected) + + def test_NR_DEC_p0_04_j2k_96_decode(self): + actual = self.j2k[20:50:4, 150:200:4] + expected = self.j2k_quarter_data[5:13, 38:50] + np.testing.assert_array_equal(actual, expected) diff --git a/glymur/test/test_opj_suite_2p1.py b/glymur/test/test_opj_suite_2p1.py deleted file mode 100644 index 12bffcf..0000000 --- a/glymur/test/test_opj_suite_2p1.py +++ /dev/null @@ -1,394 +0,0 @@ -""" -The tests defined here roughly correspond to what is in the OpenJPEG test -suite. -""" - -# Some test names correspond with openjpeg tests. Long names are ok in this -# case. -# pylint: disable=C0103 - -# All of these tests correspond to tests in openjpeg, so no docstring is really -# needed. -# pylint: disable=C0111 - -# This module is very long, cannot be helped. -# pylint: disable=C0302 - -# unittest fools pylint with "too many public methods" -# pylint: disable=R0904 - -# Some tests use numpy test infrastructure, which means the tests never -# reference "self", so pylint claims it should be a function. No, no, no. -# pylint: disable=R0201 - -# Many tests are pretty long and that can't be helped. -# pylint: disable=R0915 - -# asserWarns introduced in python 3.2 (python2.7/pylint issue) -# pylint: disable=E1101 - -import re -import sys -import unittest -import warnings - -import numpy as np - -from glymur import Jp2k -import glymur - -from .fixtures import OPJ_DATA_ROOT -from .fixtures import WARNING_INFRASTRUCTURE_ISSUE, WARNING_INFRASTRUCTURE_MSG -from .fixtures import mse, peak_tolerance, read_pgx, opj_data_file - - -@unittest.skipIf(OPJ_DATA_ROOT is None, - "OPJ_DATA_ROOT environment variable not set") -@unittest.skipIf(re.match(r'''(1|2.0.0)''', - glymur.version.openjpeg_version) is not None, - "Only supported in 2.0.1 or higher") -#class TestVersion0p7BackwardsCompatibility(unittest.TestSuite): -class TestBlah(unittest.TestSuite): - """ - Tests for backwards compatibility with version 0.7. - """ - - def test_blah_NR_DEC_p1_04_j2k_57_decode(self): - jfile = opj_data_file('input/conformance/p1_04.j2k') - jp2k = Jp2k(jfile) - tdata = jp2k.read(tile=63) # last tile - odata = jp2k[:] - np.testing.assert_array_equal(tdata, odata[896:1024, 896:1024]) - -@unittest.skipIf(OPJ_DATA_ROOT is None, - "OPJ_DATA_ROOT environment variable not set") -@unittest.skipIf(re.match(r'''(1|2.0.0)''', - glymur.version.openjpeg_version) is not None, - "Only supported in 2.0.1 or higher") -class TestSuite2point1(unittest.TestCase): - """Runs tests introduced in version 2.0+ or that pass only in 2.0+""" - - def setUp(self): - pass - - def tearDown(self): - pass - - @unittest.skipIf(WARNING_INFRASTRUCTURE_ISSUE, WARNING_INFRASTRUCTURE_MSG) - def test_NR_DEC_text_GBR_jp2_29_decode(self): - jfile = opj_data_file('input/nonregression/text_GBR.jp2') - with self.assertWarns(UserWarning): - # brand is 'jp2 ', but has any icc profile. - jp2 = Jp2k(jfile) - jp2[:] - self.assertTrue(True) - - def test_NR_DEC_kodak_2layers_lrcp_j2c_31_decode(self): - jfile = opj_data_file('input/nonregression/kodak_2layers_lrcp.j2c') - Jp2k(jfile)[:] - self.assertTrue(True) - - def test_NR_DEC_kodak_2layers_lrcp_j2c_32_decode(self): - jfile = opj_data_file('input/nonregression/kodak_2layers_lrcp.j2c') - Jp2k(jfile)[::4, ::4] - self.assertTrue(True) - - def test_NR_DEC_issue104_jpxstream_jp2_33_decode(self): - jfile = opj_data_file('input/nonregression/issue104_jpxstream.jp2') - Jp2k(jfile)[:] - self.assertTrue(True) - - def test_NR_DEC_mem_b2b86b74_2753_jp2_35_decode(self): - jfile = opj_data_file('input/nonregression/mem-b2b86b74-2753.jp2') - Jp2k(jfile)[:] - self.assertTrue(True) - - @unittest.skipIf(WARNING_INFRASTRUCTURE_ISSUE, WARNING_INFRASTRUCTURE_MSG) - def test_NR_DEC_gdal_fuzzer_unchecked_num_resolutions_jp2_36_decode(self): - f = 'input/nonregression/gdal_fuzzer_unchecked_numresolutions.jp2' - jfile = opj_data_file(f) - with self.assertWarns(UserWarning): - # Invalid number of resolutions. - j = Jp2k(jfile) - with self.assertRaises(IOError): - j[:] - - @unittest.skipIf(WARNING_INFRASTRUCTURE_ISSUE, WARNING_INFRASTRUCTURE_MSG) - def test_NR_DEC_gdal_fuzzer_check_number_of_tiles_jp2_38_decode(self): - relpath = 'input/nonregression/gdal_fuzzer_check_number_of_tiles.jp2' - jfile = opj_data_file(relpath) - with self.assertWarns(UserWarning): - # Invalid number of tiles. - j = Jp2k(jfile) - with self.assertRaises(IOError): - j[:] - - @unittest.skipIf(WARNING_INFRASTRUCTURE_ISSUE, WARNING_INFRASTRUCTURE_MSG) - def test_NR_DEC_gdal_fuzzer_check_comp_dx_dy_jp2_39_decode(self): - relpath = 'input/nonregression/gdal_fuzzer_check_comp_dx_dy.jp2' - jfile = opj_data_file(relpath) - with self.assertWarns(UserWarning): - # Invalid subsampling value - with self.assertRaises(IOError): - Jp2k(jfile)[:] - - def test_NR_DEC_file_409752_jp2_40_decode(self): - jfile = opj_data_file('input/nonregression/file409752.jp2') - with self.assertRaises(RuntimeError): - Jp2k(jfile)[:] - - def test_NR_DEC_issue206_image_000_jp2_42_decode(self): - jfile = opj_data_file('input/nonregression/issue206_image-000.jp2') - Jp2k(jfile)[:] - self.assertTrue(True) - - def test_NR_DEC_p1_04_j2k_57_decode(self): - jfile = opj_data_file('input/conformance/p1_04.j2k') - jp2k = Jp2k(jfile) - tdata = jp2k[896:1024, 896:1024] # last tile - odata = jp2k[:] - np.testing.assert_array_equal(tdata, odata[896:1024, 896:1024]) - - def test_NR_DEC_p1_04_j2k_57_decode_0p7_backwards_compatibility(self): - """ - 0.7.x usage deprecated - """ - jfile = opj_data_file('input/conformance/p1_04.j2k') - jp2k = Jp2k(jfile) - if sys.hexversion < 0x03000000: - with warnings.catch_warnings(): - # Suppress a warning due to deprecated syntax - warnings.simplefilter("ignore") - tdata = jp2k.read(tile=63) # last tile - else: - with self.assertWarns(DeprecationWarning): - tdata = jp2k.read(tile=63) # last tile - odata = jp2k[:] - np.testing.assert_array_equal(tdata, odata[896:1024, 896:1024]) - - def test_NR_DEC_p1_04_j2k_58_decode_0p7_backwards_compatibility(self): - """ - 0.7.x usage deprecated - """ - jfile = opj_data_file('input/conformance/p1_04.j2k') - jp2k = Jp2k(jfile) - if sys.hexversion < 0x03000000: - with warnings.catch_warnings(): - # Suppress a warning due to deprecated syntax - tdata = jp2k.read(tile=63, rlevel=2) # last tile - else: - with self.assertWarns(DeprecationWarning): - tdata = jp2k.read(tile=63, rlevel=2) # last tile - odata = jp2k[::4, ::4] - np.testing.assert_array_equal(tdata, odata[224:256, 224:256]) - - def test_NR_DEC_p1_04_j2k_58_decode(self): - jfile = opj_data_file('input/conformance/p1_04.j2k') - jp2k = Jp2k(jfile) - tdata = jp2k[896:1024:4, 896:1024:4] # last tile - odata = jp2k[::4, ::4] - np.testing.assert_array_equal(tdata, odata[224:256, 224:256]) - - def test_NR_DEC_p1_04_j2k_59_decode(self): - jfile = opj_data_file('input/conformance/p1_04.j2k') - jp2k = Jp2k(jfile) - tdata = jp2k[128:256, 512:640] # 2nd row, 5th column - odata = jp2k[:] - np.testing.assert_array_equal(tdata, odata[128:256, 512:640]) - - def test_NR_DEC_p1_04_j2k_60_decode(self): - jfile = opj_data_file('input/conformance/p1_04.j2k') - jp2k = Jp2k(jfile) - tdata = jp2k[128:256:2, 512:640:2] # 2nd row, 5th column - odata = jp2k[::2, ::2] - np.testing.assert_array_equal(tdata, odata[64:128, 256:320]) - - @unittest.skipIf(WARNING_INFRASTRUCTURE_ISSUE, WARNING_INFRASTRUCTURE_MSG) - def test_NR_DEC_jp2_36_decode(self): - lst = ('input', - 'nonregression', - 'gdal_fuzzer_assert_in_opj_j2k_read_SQcd_SQcc.patch.jp2') - jfile = opj_data_file('/'.join(lst)) - with self.assertWarns(UserWarning): - # Invalid component number. - j = Jp2k(jfile) - with self.assertRaises(IOError): - j[:] - -@unittest.skipIf(OPJ_DATA_ROOT is None, - "OPJ_DATA_ROOT environment variable not set") -@unittest.skipIf(re.match(r'''(1|2.0.0)''', - glymur.version.openjpeg_version) is not None, - "Only supported in 2.0.1 or higher") -class TestReadArea(unittest.TestCase): - """ - Runs tests introduced in version 2.0+ or that pass only in 2.0+ - - Specifically for read method with area parameter. - """ - @classmethod - def setUpClass(self): - - jfile = opj_data_file('input/conformance/p1_04.j2k') - self.j2k = Jp2k(jfile) - self.j2k_data = self.j2k[:] - self.j2k_half_data = self.j2k[::2, ::2] - self.j2k_quarter_data = self.j2k[::4, ::4] - - jfile = opj_data_file('input/conformance/p1_06.j2k') - self.j2k_p1_06 = Jp2k(jfile) - - def test_NR_DEC_p1_04_j2k_43_decode(self): - actual = self.j2k[:1024, :1024] - expected = self.j2k_data - np.testing.assert_array_equal(actual, expected) - - def test_NR_DEC_p1_04_j2k_44_decode(self): - actual = self.j2k[640:768, 512:640] - expected = self.j2k_data[640:768, 512:640] - np.testing.assert_array_equal(actual, expected) - - def test_NR_DEC_p1_04_j2k_45_decode(self): - actual = self.j2k[896:1024, 896:1024] - expected = self.j2k_data[896:1024, 896:1024] - np.testing.assert_array_equal(actual, expected) - - def test_NR_DEC_p1_04_j2k_46_decode(self): - actual = self.j2k[500:800, 100:300] - expected = self.j2k_data[500:800, 100:300] - np.testing.assert_array_equal(actual, expected) - - def test_NR_DEC_p1_04_j2k_47_decode(self): - actual = self.j2k[520:600, 260:360] - expected = self.j2k_data[520:600, 260:360] - np.testing.assert_array_equal(actual, expected) - - def test_NR_DEC_p1_04_j2k_48_decode(self): - actual = self.j2k[520:660, 260:360] - expected = self.j2k_data[520:660, 260:360] - np.testing.assert_array_equal(actual, expected) - - def test_NR_DEC_p1_04_j2k_49_decode(self): - actual = self.j2k[520:600, 360:400] - expected = self.j2k_data[520:600, 360:400] - np.testing.assert_array_equal(actual, expected) - - def test_NR_DEC_p1_04_j2k_50_decode(self): - actual = self.j2k[:1024:4, :1024:4] - expected = self.j2k_quarter_data - np.testing.assert_array_equal(actual, expected) - - def test_NR_DEC_p1_04_j2k_51_decode(self): - actual = self.j2k[640:768:4, 512:640:4] - expected = self.j2k_quarter_data[160:192, 128:160] - np.testing.assert_array_equal(actual, expected) - - def test_NR_DEC_p1_04_j2k_52_decode(self): - actual = self.j2k[896:1024:4, 896:1024:4] - expected = self.j2k_quarter_data[224:352, 224:352] - np.testing.assert_array_equal(actual, expected) - - def test_NR_DEC_p1_04_j2k_53_decode(self): - actual = self.j2k[500:800:4, 100:300:4] - expected = self.j2k_quarter_data[125:200, 25:75] - np.testing.assert_array_equal(actual, expected) - - def test_NR_DEC_p1_04_j2k_54_decode(self): - actual = self.j2k[520:600:4, 260:360:4] - expected = self.j2k_quarter_data[130:150, 65:90] - np.testing.assert_array_equal(actual, expected) - - def test_NR_DEC_p1_04_j2k_55_decode(self): - actual = self.j2k[520:660:4, 260:360:4] - expected = self.j2k_quarter_data[130:165, 65:90] - np.testing.assert_array_equal(actual, expected) - - def test_NR_DEC_p1_04_j2k_56_decode(self): - actual = self.j2k[520:600:4, 360:400:4] - expected = self.j2k_quarter_data[130:150, 90:100] - np.testing.assert_array_equal(actual, expected) - - def test_NR_DEC_p1_06_j2k_70_decode(self): - actual = self.j2k_p1_06[9:12:2, 9:12:2] - self.assertEqual(actual.shape, (1, 1, 3)) - - def test_NR_DEC_p1_06_j2k_71_decode(self): - actual = self.j2k_p1_06[10:12:2, 4:10:2] - self.assertEqual(actual.shape, (1, 3, 3)) - - def test_NR_DEC_p1_06_j2k_72_decode(self): - ssdata = self.j2k_p1_06[3:9:2, 3:9:2] - self.assertEqual(ssdata.shape, (3, 3, 3)) - - def test_NR_DEC_p1_06_j2k_73_decode(self): - ssdata = self.j2k_p1_06[4:7:2, 4:7:2] - self.assertEqual(ssdata.shape, (2, 2, 3)) - - def test_NR_DEC_p1_06_j2k_74_decode(self): - ssdata = self.j2k_p1_06[4:5:2, 4:5:2] - self.assertEqual(ssdata.shape, (1, 1, 3)) - - def test_NR_DEC_p1_06_j2k_75_decode(self): - # Image size would be 0 x 0. - with self.assertRaises((IOError, OSError)): - self.j2k_p1_06[9:12:4, 9:12:4] - - def test_NR_DEC_p0_04_j2k_85_decode(self): - actual = self.j2k[:256, :256] - expected = self.j2k_data[:256, :256] - np.testing.assert_array_equal(actual, expected) - - def test_NR_DEC_p0_04_j2k_86_decode(self): - actual = self.j2k[:128, 128:256] - expected = self.j2k_data[:128, 128:256] - np.testing.assert_array_equal(actual, expected) - - def test_NR_DEC_p0_04_j2k_87_decode(self): - actual = self.j2k[10:200, 50:120] - expected = self.j2k_data[10:200, 50:120] - np.testing.assert_array_equal(actual, expected) - - def test_NR_DEC_p0_04_j2k_88_decode(self): - actual = self.j2k[150:210, 10:190] - expected = self.j2k_data[150:210, 10:190] - np.testing.assert_array_equal(actual, expected) - - def test_NR_DEC_p0_04_j2k_89_decode(self): - actual = self.j2k[80:150, 100:200] - expected = self.j2k_data[80:150, 100:200] - np.testing.assert_array_equal(actual, expected) - - def test_NR_DEC_p0_04_j2k_90_decode(self): - actual = self.j2k[20:50, 150:200] - expected = self.j2k_data[20:50, 150:200] - np.testing.assert_array_equal(actual, expected) - - def test_NR_DEC_p0_04_j2k_91_decode(self): - actual = self.j2k[:256:4, :256:4] - expected = self.j2k_quarter_data[0:64, 0:64] - np.testing.assert_array_equal(actual, expected) - - def test_NR_DEC_p0_04_j2k_92_decode(self): - actual = self.j2k[:128:4, 128:256:4] - expected = self.j2k_quarter_data[:32, 32:64] - np.testing.assert_array_equal(actual, expected) - - def test_NR_DEC_p0_04_j2k_93_decode(self): - actual = self.j2k[10:200:4, 50:120:4] - expected = self.j2k_quarter_data[3:50, 13:30] - np.testing.assert_array_equal(actual, expected) - - def test_NR_DEC_p0_04_j2k_94_decode(self): - actual = self.j2k[150:210:4, 10:190:4] - expected = self.j2k_quarter_data[38:53, 3:48] - np.testing.assert_array_equal(actual, expected) - - def test_NR_DEC_p0_04_j2k_95_decode(self): - actual = self.j2k[80:150:4, 100:200:4] - expected = self.j2k_quarter_data[20:38, 25:50] - np.testing.assert_array_equal(actual, expected) - - def test_NR_DEC_p0_04_j2k_96_decode(self): - actual = self.j2k[20:50:4, 150:200:4] - expected = self.j2k_quarter_data[5:13, 38:50] - np.testing.assert_array_equal(actual, expected) From a35ebe18369e3892d6ca1713a76ecfdacbccd428 Mon Sep 17 00:00:00 2001 From: John Evans Date: Tue, 18 Nov 2014 08:03:34 -0500 Subject: [PATCH 09/23] backwards compatibility tests need to be filtered out on some platforms The need to verify the warning means that the python-six issue applies. --- glymur/test/test_opj_suite.py | 3 +++ 1 file changed, 3 insertions(+) diff --git a/glymur/test/test_opj_suite.py b/glymur/test/test_opj_suite.py index 1dd4026..cf44eaa 100644 --- a/glymur/test/test_opj_suite.py +++ b/glymur/test/test_opj_suite.py @@ -30,6 +30,7 @@ suite. import re import sys import unittest +import warnings import numpy as np @@ -727,6 +728,7 @@ class TestSuite2point1(unittest.TestCase): odata = jp2k[:] np.testing.assert_array_equal(tdata, odata[896:1024, 896:1024]) + @unittest.skipIf(WARNING_INFRASTRUCTURE_ISSUE, WARNING_INFRASTRUCTURE_MSG) def test_NR_DEC_p1_04_j2k_57_decode_0p7_backwards_compatibility(self): """ 0.7.x usage deprecated @@ -744,6 +746,7 @@ class TestSuite2point1(unittest.TestCase): odata = jp2k[:] np.testing.assert_array_equal(tdata, odata[896:1024, 896:1024]) + @unittest.skipIf(WARNING_INFRASTRUCTURE_ISSUE, WARNING_INFRASTRUCTURE_MSG) def test_NR_DEC_p1_04_j2k_58_decode_0p7_backwards_compatibility(self): """ 0.7.x usage deprecated From 036b14cc2b671ce375c32bf99677e8acc546556e Mon Sep 17 00:00:00 2001 From: John Evans Date: Tue, 18 Nov 2014 09:48:19 -0500 Subject: [PATCH 10/23] filter out write tests that should not run on openjpeg 1.3 --- glymur/test/test_jp2box.py | 2 ++ glymur/test/test_jp2k.py | 4 ++++ glymur/test/test_printing.py | 2 ++ 3 files changed, 8 insertions(+) diff --git a/glymur/test/test_jp2box.py b/glymur/test/test_jp2box.py index 72daf17..b8ad2ec 100644 --- a/glymur/test/test_jp2box.py +++ b/glymur/test/test_jp2box.py @@ -54,6 +54,8 @@ class TestDataEntryURL(unittest.TestCase): def setUp(self): self.jp2file = glymur.data.nemo() + @unittest.skipIf(re.match("1.5|2", glymur.version.openjpeg_version) is None, + "Must have openjpeg 1.5 or higher to run") def test_wrap_greyscale(self): """A single component should be wrapped as GREYSCALE.""" j = Jp2k(self.jp2file) diff --git a/glymur/test/test_jp2k.py b/glymur/test/test_jp2k.py index f615cc4..73315bc 100644 --- a/glymur/test/test_jp2k.py +++ b/glymur/test/test_jp2k.py @@ -76,6 +76,8 @@ class SliceProtocolBase(unittest.TestCase): self.j2k_data_r1 = self.j2k[::2, ::2] self.j2k_data_r5 = self.j2k[::32, ::32] +@unittest.skipIf(re.match("1.5|2", glymur.version.openjpeg_version) is None, + "Must have openjpeg 1.5 or higher to run") @unittest.skipIf(os.name == "nt", fixtures.WINDOWS_TMP_FILE_MSG) class TestSliceProtocolBaseWrite(SliceProtocolBase): @@ -524,6 +526,8 @@ class TestJp2k(unittest.TestCase): jpx = Jp2k(self.jpxfile) self.assertEqual(jpx.shape, (1024, 1024, 3)) + @unittest.skipIf(re.match("1.5|2", glymur.version.openjpeg_version) is None, + "Must have openjpeg 1.5 or higher to run") @unittest.skipIf(os.name == "nt", "Unexplained failure on windows") def test_irreversible(self): """Irreversible""" diff --git a/glymur/test/test_printing.py b/glymur/test/test_printing.py index 5c09c81..5dae016 100644 --- a/glymur/test/test_printing.py +++ b/glymur/test/test_printing.py @@ -107,6 +107,8 @@ class TestPrinting(unittest.TestCase): with self.assertRaises(TypeError): glymur.set_printoptions(hi='low') + @unittest.skipIf(re.match("1.5|2", glymur.version.openjpeg_version) is None, + "Must have openjpeg 1.5 or higher to run") def test_asoc_label_box(self): """verify printing of asoc, label boxes""" # Construct a fake file with an asoc and a label box, as From 117b7d1bbe71ac9b3bd26d866e6fce94dcf6116e Mon Sep 17 00:00:00 2001 From: John Evans Date: Tue, 18 Nov 2014 10:06:52 -0500 Subject: [PATCH 11/23] refactored, skipping tests not to be run on openjpeg 1.3 --- glymur/test/test_opj_suite_neg.py | 77 +++++++++++++++++-------------- 1 file changed, 43 insertions(+), 34 deletions(-) diff --git a/glymur/test/test_opj_suite_neg.py b/glymur/test/test_opj_suite_neg.py index 440ebaa..350b7a5 100644 --- a/glymur/test/test_opj_suite_neg.py +++ b/glymur/test/test_opj_suite_neg.py @@ -24,6 +24,7 @@ from .fixtures import OPJ_DATA_ROOT, opj_data_file, read_image from .fixtures import NO_READ_BACKEND, NO_READ_BACKEND_MSG from .fixtures import NO_SKIMAGE_FREEIMAGE_SUPPORT from .fixtures import WARNING_INFRASTRUCTURE_ISSUE, WARNING_INFRASTRUCTURE_MSG +from . import fixtures from glymur import Jp2k import glymur @@ -31,7 +32,7 @@ import glymur @unittest.skipIf(OPJ_DATA_ROOT is None, "OPJ_OPJ_DATA_ROOT environment variable not set") -class TestSuiteNegative(unittest.TestCase): +class TestSuiteNegativeRead(unittest.TestCase): """Test suite for certain negative tests from openjpeg suite.""" def setUp(self): @@ -41,33 +42,6 @@ class TestSuiteNegative(unittest.TestCase): def tearDown(self): pass - - @unittest.skipIf(NO_SKIMAGE_FREEIMAGE_SUPPORT, - "Cannot read input image without scikit-image/freeimage") - @unittest.skipIf(os.name == "nt", "Temporary file issue on window.") - def test_cinema2K_bad_frame_rate(self): - """Cinema2k frame rate must be either 24 or 48.""" - relfile = 'input/nonregression/X_5_2K_24_235_CBR_STEM24_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) - - - @unittest.skipIf(NO_READ_BACKEND, NO_READ_BACKEND_MSG) - @unittest.skipIf(os.name == "nt", "Temporary file issue on window.") - def test_psnr_with_cratios(self): - """Using psnr with cratios options is not allowed.""" - # Not an OpenJPEG test, but close. - infile = opj_data_file('input/nonregression/Bretagne1.ppm') - data = read_image(infile) - with tempfile.NamedTemporaryFile(suffix='.j2k') as tfile: - j = Jp2k(tfile.name, 'wb') - with self.assertRaises(IOError): - j.write(data, psnr=[30, 35, 40], cratios=[2, 3, 4]) - def test_nr_marker_not_compliant(self): """non-compliant marker, should still be able to read""" relpath = 'input/nonregression/MarkerIsNotCompliant.j2k' @@ -98,7 +72,47 @@ class TestSuiteNegative(unittest.TestCase): jp2k.get_codestream(header_only=False) self.assertTrue(True) - @unittest.skipIf(os.name == "nt", "Temporary file issue on window.") + +@unittest.skipIf(re.match("1.5|2", glymur.version.openjpeg_version) is None, + "Must have openjpeg 1.5 or higher to run") +@unittest.skipIf(os.name == "nt", fixtures.WINDOWS_TMP_FILE_MSG) +@unittest.skipIf(OPJ_DATA_ROOT is None, + "OPJ_OPJ_DATA_ROOT environment variable not set") +class TestSuiteNegativeWrite(unittest.TestCase): + """Test suite for certain negative tests from openjpeg suite.""" + + def setUp(self): + self.jp2file = glymur.data.nemo() + self.j2kfile = glymur.data.goodstuff() + + def tearDown(self): + pass + + + @unittest.skipIf(NO_SKIMAGE_FREEIMAGE_SUPPORT, + "Cannot read input image without scikit-image/freeimage") + def test_cinema2K_bad_frame_rate(self): + """Cinema2k frame rate must be either 24 or 48.""" + relfile = 'input/nonregression/X_5_2K_24_235_CBR_STEM24_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) + + + @unittest.skipIf(NO_READ_BACKEND, NO_READ_BACKEND_MSG) + def test_psnr_with_cratios(self): + """Using psnr with cratios options is not allowed.""" + # Not an OpenJPEG test, but close. + infile = opj_data_file('input/nonregression/Bretagne1.ppm') + data = read_image(infile) + with tempfile.NamedTemporaryFile(suffix='.j2k') as tfile: + j = Jp2k(tfile.name, 'wb') + with self.assertRaises(IOError): + j.write(data, psnr=[30, 35, 40], cratios=[2, 3, 4]) + def test_code_block_dimensions(self): """don't allow extreme codeblock sizes""" # opj_compress doesn't allow the dimensions of a codeblock @@ -117,7 +131,6 @@ class TestSuiteNegative(unittest.TestCase): with self.assertRaises(IOError): j.write(data, cbsize=(2, 2048)) - @unittest.skipIf(os.name == "nt", "Temporary file issue on window.") def test_precinct_size_not_p2(self): """precinct sizes should be powers of two.""" ifile = Jp2k(self.j2kfile) @@ -127,7 +140,6 @@ class TestSuiteNegative(unittest.TestCase): with self.assertRaises(IOError): ofile.write(data, psizes=[(13, 13)]) - @unittest.skipIf(os.name == "nt", "Temporary file issue on window.") def test_cblk_size_not_power_of_two(self): """code block sizes should be powers of two.""" ifile = Jp2k(self.j2kfile) @@ -137,7 +149,6 @@ class TestSuiteNegative(unittest.TestCase): with self.assertRaises(IOError): ofile.write(data, cbsize=(13, 12)) - @unittest.skipIf(os.name == "nt", "Temporary file issue on window.") def test_cblk_size_precinct_size(self): """code block sizes should never exceed half that of precinct size.""" ifile = Jp2k(self.j2kfile) @@ -149,5 +160,3 @@ class TestSuiteNegative(unittest.TestCase): cbsize=(64, 64), psizes=[(64, 64)]) -if __name__ == "__main__": - unittest.main() From 373afb692e3f90a2f5896f3edfd372e0c659eb41 Mon Sep 17 00:00:00 2001 From: jevans Date: Tue, 18 Nov 2014 20:45:25 -0500 Subject: [PATCH 12/23] progress --- glymur/jp2k.py | 29 +++++++++++++++++++++++++---- glymur/test/test_callbacks.py | 25 +++++++++++++++++++++---- 2 files changed, 46 insertions(+), 8 deletions(-) diff --git a/glymur/jp2k.py b/glymur/jp2k.py index a45f9e2..8d8ffd4 100644 --- a/glymur/jp2k.py +++ b/glymur/jp2k.py @@ -62,9 +62,15 @@ class Jp2k(Jp2kBox): raw codestream. shape : tuple Size of the image. + + Properties + ---------- ignore_pclr_cmap_cdef : bool - Whether or not to ignore the pclr, cmap, or cdef boxes during any - color transformation. Defaults to False. + whether or not to ignore the pclr, cmap, or cdef boxes during any + color transformation, defaults to False. + verbose : bool + whether or not to print informational messages produced by the + OpenJPEG library, defaults to false Examples -------- @@ -100,7 +106,9 @@ class Jp2k(Jp2kBox): self._codec_format = None self._colorspace = None self._shape = None + self._ignore_pclr_cmap_cdef = False + self._verbose = False # Parse the file for JP2/JPX contents only if we are reading it. if mode == 'rb': @@ -114,6 +122,14 @@ class Jp2k(Jp2kBox): def ignore_pclr_cmap_cdef(self, ignore_pclr_cmap_cdef): self._ignore_pclr_cmap_cdef = ignore_pclr_cmap_cdef + @property + def verbose(self): + return self._verbose + + @verbose.setter + def verbose(self, verbose): + self._verbose = verbose + @property def shape(self): if self._shape is not None: @@ -671,7 +687,11 @@ class Jp2k(Jp2kBox): codec = opj2.create_compress(self._cparams.codec_fmt) stack.callback(opj2.destroy_codec, codec) - info_handler = _INFO_CALLBACK if verbose else None + if self._verbose or verbose: + info_handler = _INFO_CALLBACK + else: + info_handler = None + opj2.set_info_handler(codec, info_handler) opj2.set_warning_handler(codec, _WARNING_CALLBACK) opj2.set_error_handler(codec, _ERROR_CALLBACK) @@ -1183,7 +1203,8 @@ class Jp2k(Jp2kBox): opj2.set_error_handler(codec, _ERROR_CALLBACK) opj2.set_warning_handler(codec, _WARNING_CALLBACK) - if verbose: + + if self._verbose or verbose: opj2.set_info_handler(codec, _INFO_CALLBACK) else: opj2.set_info_handler(codec, None) diff --git a/glymur/test/test_callbacks.py b/glymur/test/test_callbacks.py index ce3bb8c..a58cfeb 100644 --- a/glymur/test/test_callbacks.py +++ b/glymur/test/test_callbacks.py @@ -39,7 +39,7 @@ class TestCallbacks(unittest.TestCase): "Missing openjp2 library.") @unittest.skipIf(WARNING_INFRASTRUCTURE_ISSUE, WARNING_INFRASTRUCTURE_MSG) @unittest.skipIf(os.name == "nt", "Temporary file issue on window.") - def test_info_callback_on_write(self): + def test_info_callback_on_write_backwards_compatibility(self): """Verify messages printed when writing an image in verbose mode.""" j = glymur.Jp2k(self.jp2file) with self.assertWarns(UserWarning): @@ -52,20 +52,37 @@ class TestCallbacks(unittest.TestCase): expected = '[INFO] tile number 1 / 1' self.assertEqual(actual, expected) + @unittest.skipIf(glymur.version.openjpeg_version[0] != '2', + "Missing openjp2 library.") + @unittest.skipIf(os.name == "nt", "Temporary file issue on window.") + def test_info_callback_on_write(self): + """Verify messages printed when writing an image in verbose mode.""" + j = glymur.Jp2k(self.jp2file) + tiledata = j[:] + with tempfile.NamedTemporaryFile(suffix='.jp2') as tfile: + jp2 = glymur.Jp2k(tfile.name, 'wb') + with patch('sys.stdout', new=StringIO()) as fake_out: + jp2.verbose = True + jp2[:] = tiledata + actual = fake_out.getvalue().strip() + expected = '[INFO] tile number 1 / 1' + self.assertEqual(actual, expected) + def test_info_callbacks_on_read(self): """stdio output when info callback handler is enabled""" # Verify that we get the expected stdio output when our internal info # callback handler is enabled. - j = glymur.Jp2k(self.j2kfile) + jp2 = glymur.Jp2k(self.j2kfile) with patch('sys.stdout', new=StringIO()) as fake_out: - j.read(rlevel=1, verbose=True) + jp2.verbose = True + jp2[::2, ::2] actual = fake_out.getvalue().strip() if glymur.version.openjpeg_version[0] == '2': lines = ['[INFO] Start to read j2k main header (0).', '[INFO] Main header has been correctly decoded.', - '[INFO] No decoded area parameters, set the decoded area to the whole image', + '[INFO] Setting decoding area to 0,0,480,800', '[INFO] Header of tile 0 / 0 has been read.', '[INFO] Tile 1/1 has been decoded.', '[INFO] Image data has been updated with tile 1.'] From 9025bb3ec3ee3ae6cb2b8efb01d39cbe08216b4c Mon Sep 17 00:00:00 2001 From: jevans Date: Tue, 18 Nov 2014 23:15:09 -0500 Subject: [PATCH 13/23] layer is now a property --- glymur/jp2k.py | 35 ++++++++++++++++++++++++++--------- glymur/test/test_jp2k.py | 4 ++-- 2 files changed, 28 insertions(+), 11 deletions(-) diff --git a/glymur/jp2k.py b/glymur/jp2k.py index 8d8ffd4..2ea9588 100644 --- a/glymur/jp2k.py +++ b/glymur/jp2k.py @@ -68,6 +68,8 @@ class Jp2k(Jp2kBox): ignore_pclr_cmap_cdef : bool whether or not to ignore the pclr, cmap, or cdef boxes during any color transformation, defaults to False. + layer : int + zero-based number of quality layer to decode verbose : bool whether or not to print informational messages produced by the OpenJPEG library, defaults to false @@ -106,6 +108,7 @@ class Jp2k(Jp2kBox): self._codec_format = None self._colorspace = None self._shape = None + self._layer = 0 self._ignore_pclr_cmap_cdef = False self._verbose = False @@ -122,6 +125,18 @@ class Jp2k(Jp2kBox): def ignore_pclr_cmap_cdef(self, ignore_pclr_cmap_cdef): self._ignore_pclr_cmap_cdef = ignore_pclr_cmap_cdef + @property + def layer(self): + return self._layer + + @layer.setter + def layer(self, layer): + if version.openjpeg_version_tuple[0] < 2: + msg = "Layer property not supported unless the version of OpenJPEG " + msg += "is 2.0 or higher." + raise RuntimeError(msg) + self._layer = layer + @property def verbose(self): return self._verbose @@ -1156,7 +1171,7 @@ class Jp2k(Jp2kBox): return data - def _read_openjp2(self, rlevel=0, layer=0, area=None, tile=None, verbose=False): + def _read_openjp2(self, rlevel=0, layer=None, area=None, tile=None, verbose=False): """Read a JPEG 2000 image using libopenjp2. Parameters @@ -1184,9 +1199,12 @@ class Jp2k(Jp2kBox): RuntimeError If the image has differing subsample factors. """ + if layer is not None: + self._layer = layer + self._subsampling_sanity_check() - self._populate_dparams(rlevel, layer=layer, tile=tile, area=area) + self._populate_dparams(rlevel, tile=tile, area=area) with ExitStack() as stack: if re.match("2.1", version.openjpeg_version): @@ -1231,13 +1249,11 @@ class Jp2k(Jp2kBox): return img_array - def _populate_dparams(self, rlevel, tile=None, layer=None, area=None): + def _populate_dparams(self, rlevel, tile=None, area=None): """Populate decompression structure with appropriate input parameters. Parameters ---------- - layer : int - Number of quality layer to decode. rlevel : int Factor by which to rlevel output resolution. area : tuple @@ -1263,8 +1279,7 @@ class Jp2k(Jp2kBox): dparam.decod_format = self._codec_format - if layer is not None: - dparam.cp_layer = layer + dparam.cp_layer = self._layer # Must check the specified rlevel against the maximum. if rlevel != 0: @@ -1301,7 +1316,7 @@ class Jp2k(Jp2kBox): self._dparams = dparam - def read_bands(self, rlevel=0, layer=0, area=None, tile=None, + def read_bands(self, rlevel=0, layer=None, area=None, tile=None, verbose=False, ignore_pclr_cmap_cdef=False): """Read a JPEG 2000 image. @@ -1348,7 +1363,9 @@ class Jp2k(Jp2kBox): "functionality.") self.ignore_pclr_cmap_cdef = ignore_pclr_cmap_cdef - self._populate_dparams(rlevel, layer=layer, tile=tile, area=area) + if layer is not None: + self._layer = layer + self._populate_dparams(rlevel, tile=tile, area=area) with ExitStack() as stack: if re.match("2.1", version.openjpeg_version): diff --git a/glymur/test/test_jp2k.py b/glymur/test/test_jp2k.py index 73315bc..55cea0e 100644 --- a/glymur/test/test_jp2k.py +++ b/glymur/test/test_jp2k.py @@ -1094,8 +1094,8 @@ class TestJp2k_1_x(unittest.TestCase): """ with patch('glymur.version.openjpeg_version_tuple', new=(1, 5, 0)): j2k = Jp2k(self.j2kfile) - with self.assertRaises(TypeError): - j2k.read(layer=1) + with self.assertRaises(RuntimeError): + j2k.layer = 1 @unittest.skipIf(os.name == "nt", fixtures.WINDOWS_TMP_FILE_MSG) From e2059d59e8a15196fd142870172cead1ef85e54b Mon Sep 17 00:00:00 2001 From: jevans Date: Wed, 19 Nov 2014 07:24:47 -0500 Subject: [PATCH 14/23] removed repeated array-style slicing tests --- glymur/test/test_codestream.py | 149 ---------- glymur/test/test_jp2k.py | 495 +++++++++++++++++---------------- 2 files changed, 255 insertions(+), 389 deletions(-) delete mode 100644 glymur/test/test_codestream.py diff --git a/glymur/test/test_codestream.py b/glymur/test/test_codestream.py deleted file mode 100644 index e520713..0000000 --- a/glymur/test/test_codestream.py +++ /dev/null @@ -1,149 +0,0 @@ -""" -Test suite for codestream parsing. -""" - -# unittest doesn't work well with R0904. -# pylint: disable=R0904 - -import os -import struct -import sys -import tempfile -import unittest - -from glymur import Jp2k -import glymur - -from .fixtures import opj_data_file, OPJ_DATA_ROOT - -class TestCodestream(unittest.TestCase): - """Test suite for unusual codestream cases.""" - - def setUp(self): - self.jp2file = glymur.data.nemo() - - def tearDown(self): - pass - - def test_siz_segment_ssiz_unsigned(self): - """ssiz attribute to be removed in future release""" - j = Jp2k(self.jp2file) - codestream = j.get_codestream() - - # The ssiz attribute was simply a tuple of raw bytes. - # The first 7 bits are interpreted as the bitdepth, the MSB determines - # whether or not it is signed. - self.assertEqual(codestream.segment[1].ssiz, (7, 7, 7)) - - -@unittest.skipIf(OPJ_DATA_ROOT is None, - "OPJ_DATA_ROOT environment variable not set") -class TestCodestreamOpjData(unittest.TestCase): - """Test suite for unusual codestream cases. Uses OPJ_DATA_ROOT""" - - def setUp(self): - self.jp2file = glymur.data.nemo() - - def tearDown(self): - pass - - @unittest.skipIf(os.name == "nt", "Temporary file issue on window.") - def test_reserved_marker_segment(self): - """Reserved marker segments are ok.""" - - # Some marker segments were reserved in FCD15444-1. Since that - # standard is old, some of them may have come into use. - # - # Let's inject a reserved marker segment into a file that - # we know something about to make sure we can still parse it. - filename = os.path.join(OPJ_DATA_ROOT, 'input/conformance/p0_01.j2k') - with tempfile.NamedTemporaryFile(suffix='.j2k') as tfile: - with open(filename, 'rb') as ifile: - # Everything up until the first QCD marker. - read_buffer = ifile.read(45) - tfile.write(read_buffer) - - # Write the new marker segment, 0xff6f = 65391 - read_buffer = struct.pack('>HHB', int(65391), int(3), int(0)) - tfile.write(read_buffer) - - # Get the rest of the input file. - read_buffer = ifile.read() - tfile.write(read_buffer) - tfile.flush() - - codestream = Jp2k(tfile.name).get_codestream() - - self.assertEqual(codestream.segment[2].marker_id, '0xff6f') - self.assertEqual(codestream.segment[2].length, 3) - self.assertEqual(codestream.segment[2].data, b'\x00') - - def test_psot_is_zero(self): - """Psot=0 in SOT is perfectly legal. Issue #78.""" - filename = os.path.join(OPJ_DATA_ROOT, - 'input/nonregression/123.j2c') - j = Jp2k(filename) - codestream = j.get_codestream(header_only=False) - - # The codestream is valid, so we should be able to get the entire - # codestream, so the last one is EOC. - self.assertEqual(codestream.segment[-1].marker_id, 'EOC') - - - def test_siz_segment_ssiz_signed(self): - """ssiz attribute to be removed in future release""" - filename = os.path.join(OPJ_DATA_ROOT, 'input/conformance/p0_03.j2k') - j = Jp2k(filename) - codestream = j.get_codestream() - - # The ssiz attribute was simply a tuple of raw bytes. - # The first 7 bits are interpreted as the bitdepth, the MSB determines - # whether or not it is signed. - self.assertEqual(codestream.segment[1].ssiz, (131,)) - - -class TestCodestreamRepr(unittest.TestCase): - - def setUp(self): - self.jp2file = glymur.data.nemo() - - def tearDown(self): - pass - - def test_soc(self): - """Test SOC segment repr""" - segment = glymur.codestream.SOCsegment() - newseg = eval(repr(segment)) - self.assertEqual(newseg.marker_id, 'SOC') - - def test_siz(self): - """Test SIZ segment repr""" - kwargs = {'rsiz': 0, - 'xysiz': (2592, 1456), - 'xyosiz': (0, 0), - 'xytsiz': (2592, 1456), - 'xytosiz': (0, 0), - 'Csiz': 3, - 'bitdepth': (8, 8, 8), - 'signed': (False, False, False), - 'xyrsiz': ((1, 1, 1), (1, 1, 1))} - segment = glymur.codestream.SIZsegment(**kwargs) - newseg = eval(repr(segment)) - self.assertEqual(newseg.marker_id, 'SIZ') - self.assertEqual(newseg.xsiz, 2592) - self.assertEqual(newseg.ysiz, 1456) - self.assertEqual(newseg.xosiz, 0) - self.assertEqual(newseg.yosiz, 0) - self.assertEqual(newseg.xtsiz, 2592) - self.assertEqual(newseg.ytsiz, 1456) - self.assertEqual(newseg.xtosiz, 0) - self.assertEqual(newseg.ytosiz, 0) - - self.assertEqual(newseg.xrsiz, (1, 1, 1)) - self.assertEqual(newseg.yrsiz, (1, 1, 1)) - self.assertEqual(newseg.bitdepth, (8, 8, 8)) - self.assertEqual(newseg.signed, (False, False, False)) - - -if __name__ == "__main__": - unittest.main() diff --git a/glymur/test/test_jp2k.py b/glymur/test/test_jp2k.py index 55cea0e..7e8c067 100644 --- a/glymur/test/test_jp2k.py +++ b/glymur/test/test_jp2k.py @@ -191,71 +191,6 @@ class TestSliceProtocolRead(SliceProtocolBase): expected = self.jp2_data[20, 20, 2] np.testing.assert_array_equal(actual, expected) - def test_full_resolution_slicing_by_quarters_upper_left(self): - actual = self.jp2[:728, :1296] - expected = self.jp2_data[:728, :1296] - np.testing.assert_array_equal(actual, expected) - - def test_full_resolution_slicing_by_quarters_lower_left(self): - actual = self.jp2[728:, :1296] - expected = self.jp2_data[728:, :1296] - np.testing.assert_array_equal(actual, expected) - - def test_full_resolution_slicing_by_quarters_upper_right(self): - actual = self.jp2[:728, 1296:] - expected = self.jp2_data[:728, 1296:] - np.testing.assert_array_equal(actual, expected) - - def test_full_resolution_slicing_by_quarters_lower_right(self): - actual = self.jp2[728:, 1296:] - expected = self.jp2_data[728:, 1296:] - np.testing.assert_array_equal(actual, expected) - - def test_full_resolution_slicing_by_quarters_center(self): - actual = self.jp2[364:1092, 648:1942] - expected = self.jp2_data[364:1092, 648:1942] - np.testing.assert_array_equal(actual, expected) - - def test_full_resolution_slicing_by_halves_left(self): - actual = self.jp2[:, :1296] - expected = self.jp2_data[:, :1296] - np.testing.assert_array_equal(actual, expected) - - def test_full_resolution_slicing_by_right_half(self): - actual = self.jp2[:, 1296:] - expected = self.jp2_data[:, 1296:] - np.testing.assert_array_equal(actual, expected) - - def test_full_resolution_slicing_by_top_half(self): - actual = self.jp2[:728, :] - expected = self.jp2_data[:728, :] - np.testing.assert_array_equal(actual, expected) - - def test_full_resolution_slicing_by_bottom_half(self): - actual = self.jp2[728:, :] - expected = self.jp2_data[728:, :] - np.testing.assert_array_equal(actual, expected) - - def test_region_rlevel1_odd(self): - actual = self.jp2[0:201:2, 0:201:2] - expected = self.jp2_data_r1[:101, :101, :] - np.testing.assert_array_equal(actual, expected) - - def test_region_rlevel1_even(self): - actual = self.jp2[0:202:2, 0:202:2] - expected = self.jp2_data_r1[:101, :101, :] - np.testing.assert_array_equal(actual, expected) - - def test_region_rlevel1_slice_start_is_none(self): - actual = self.jp2[:201:2, :201:2] - expected = self.jp2_data_r1[:101, :101, :] - np.testing.assert_array_equal(actual, expected) - - def test_region_rlevel1_slice_stop_is_none(self): - actual = self.jp2[201::2, 201::2] - expected = self.jp2_data_r1[101:, 101:, :] - np.testing.assert_array_equal(actual, expected) - def test_ellipsis_full_read(self): actual = self.j2k[...] expected = self.j2k_data @@ -292,184 +227,11 @@ class TestSliceProtocolRead(SliceProtocolBase): expected = self.j2k_data[3:8, :,:] np.testing.assert_array_equal(actual, expected) - def test_slice_protocol_2d_reduce_resolution(self): - d = self.j2k[:] - self.assertEqual(d.shape, (800, 480, 3)) - - d = self.j2k[::1, ::1] - self.assertEqual(d.shape, (800, 480, 3)) - - d = self.j2k[::2, ::2] - self.assertEqual(d.shape, (400, 240, 3)) - - d = self.j2k[::4, ::4] - self.assertEqual(d.shape, (200, 120, 3)) - - d = self.j2k[::8, ::8] - self.assertEqual(d.shape, (100, 60, 3)) - - d = self.j2k[::16, ::16] - self.assertEqual(d.shape, (50, 30, 3)) - - d = self.j2k[::32, ::32] - self.assertEqual(d.shape, (25, 15, 3)) - def test_region_rlevel5(self): actual = self.j2k[5:533:32, 27:423:32] expected = self.j2k_data_r5[1:17, 1:14] np.testing.assert_array_equal(actual, expected) -@unittest.skipIf(OPJ_DATA_ROOT is None, - "OPJ_DATA_ROOT environment variable not set") -class TestSliceProtocolOpjData(unittest.TestCase): - """ - Test slice protocol, i.e. when using [ ] to read image data. - These correspond to tests for the read method with the area parameter. - """ - @classmethod - def setUpClass(self): - - jfile = opj_data_file('input/conformance/p1_04.j2k') - self.j2k = Jp2k(jfile) - self.j2k_data = self.j2k.read() - self.j2k_half_data = self.j2k.read(rlevel=1) - self.j2k_quarter_data = self.j2k.read(rlevel=2) - - def test_NR_DEC_p1_04_j2k_43_decode(self): - actual = self.j2k[:1024, :1024] - expected = self.j2k_data - np.testing.assert_array_equal(actual, expected) - - def test_NR_DEC_p1_04_j2k_44_decode(self): - actual = self.j2k[640:768, 512:640] - expected = self.j2k_data[640:768, 512:640] - np.testing.assert_array_equal(actual, expected) - - def test_NR_DEC_p1_04_j2k_45_decode(self): - actual = self.j2k[896:1024, 896:1024] - expected = self.j2k_data[896:1024, 896:1024] - np.testing.assert_array_equal(actual, expected) - - def test_NR_DEC_p1_04_j2k_46_decode(self): - actual = self.j2k[500:800, 100:300] - expected = self.j2k_data[500:800, 100:300] - np.testing.assert_array_equal(actual, expected) - - def test_NR_DEC_p1_04_j2k_47_decode(self): - actual = self.j2k[520:600, 260:360] - expected = self.j2k_data[520:600, 260:360] - np.testing.assert_array_equal(actual, expected) - - def test_NR_DEC_p1_04_j2k_48_decode(self): - actual = self.j2k[520:660, 260:360] - expected = self.j2k_data[520:660, 260:360] - np.testing.assert_array_equal(actual, expected) - - def test_NR_DEC_p1_04_j2k_49_decode(self): - actual = self.j2k[520:600, 360:400] - expected = self.j2k_data[520:600, 360:400] - np.testing.assert_array_equal(actual, expected) - - def test_NR_DEC_p1_04_j2k_50_decode(self): - actual = self.j2k[:1024:4, :1024:4] - expected = self.j2k_quarter_data[:256, :256] - np.testing.assert_array_equal(actual, expected) - - def test_NR_DEC_p1_04_j2k_51_decode(self): - actual = self.j2k[640:768:4, 512:640:4] - expected = self.j2k_quarter_data[160:192, 128:160] - np.testing.assert_array_equal(actual, expected) - - def test_NR_DEC_p1_04_j2k_52_decode(self): - actual = self.j2k[896:1024:4, 896:1024:4] - expected = self.j2k_quarter_data[224:352, 224:352] - np.testing.assert_array_equal(actual, expected) - - def test_NR_DEC_p1_04_j2k_53_decode(self): - actual = self.j2k[500:800:4, 100:300:4] - expected = self.j2k_quarter_data[125:200, 25:75] - np.testing.assert_array_equal(actual, expected) - - def test_NR_DEC_p1_04_j2k_54_decode(self): - actual = self.j2k[520:600:4, 260:360:4] - expected = self.j2k_quarter_data[130:150, 65:90] - np.testing.assert_array_equal(actual, expected) - - def test_NR_DEC_p1_04_j2k_55_decode(self): - actual = self.j2k[520:660:4, 260:360:4] - expected = self.j2k_quarter_data[130:165, 65:90] - np.testing.assert_array_equal(actual, expected) - - def test_NR_DEC_p1_04_j2k_56_decode(self): - actual = self.j2k[520:600:4, 360:400:4] - expected = self.j2k_quarter_data[130:150, 90:100] - np.testing.assert_array_equal(actual, expected) - - def test_NR_DEC_p1_06_j2k_75_decode(self): - # Image size would be 0 x 0. - with self.assertRaises((IOError, OSError)): - self.j2k[9:12:4, 9:12:4] - - def test_NR_DEC_p0_04_j2k_85_decode(self): - actual = self.j2k[:256, :256] - expected = self.j2k_data[:256, :256] - np.testing.assert_array_equal(actual, expected) - - def test_NR_DEC_p0_04_j2k_86_decode(self): - actual = self.j2k[:128, 128:256] - expected = self.j2k_data[:128, 128:256] - np.testing.assert_array_equal(actual, expected) - - def test_NR_DEC_p0_04_j2k_87_decode(self): - actual = self.j2k[10:200, 50:120] - expected = self.j2k_data[10:200, 50:120] - np.testing.assert_array_equal(actual, expected) - - def test_NR_DEC_p0_04_j2k_88_decode(self): - actual = self.j2k[150:210, 10:190] - expected = self.j2k_data[150:210, 10:190] - np.testing.assert_array_equal(actual, expected) - - def test_NR_DEC_p0_04_j2k_89_decode(self): - actual = self.j2k[80:150, 100:200] - expected = self.j2k_data[80:150, 100:200] - np.testing.assert_array_equal(actual, expected) - - def test_NR_DEC_p0_04_j2k_90_decode(self): - actual = self.j2k[20:50, 150:200] - expected = self.j2k_data[20:50, 150:200] - np.testing.assert_array_equal(actual, expected) - - def test_NR_DEC_p0_04_j2k_91_decode(self): - actual = self.j2k[:256:4, :256:4] - expected = self.j2k_quarter_data[0:64, 0:64] - np.testing.assert_array_equal(actual, expected) - - def test_NR_DEC_p0_04_j2k_92_decode(self): - actual = self.j2k[:128:4, 128:256:4] - expected = self.j2k_quarter_data[:32, 32:64] - np.testing.assert_array_equal(actual, expected) - - def test_NR_DEC_p0_04_j2k_93_decode(self): - actual = self.j2k[10:200:4, 50:120:4] - expected = self.j2k_quarter_data[3:50, 13:30] - np.testing.assert_array_equal(actual, expected) - - def test_NR_DEC_p0_04_j2k_94_decode(self): - actual = self.j2k[150:210:4, 10:190:4] - expected = self.j2k_quarter_data[38:53, 3:48] - np.testing.assert_array_equal(actual, expected) - - def test_NR_DEC_p0_04_j2k_95_decode(self): - actual = self.j2k[80:150:4, 100:200:4] - expected = self.j2k_quarter_data[20:38, 25:50] - np.testing.assert_array_equal(actual, expected) - - def test_NR_DEC_p0_04_j2k_96_decode(self): - actual = self.j2k[20:50:4, 150:200:4] - expected = self.j2k_quarter_data[5:13, 38:50] - np.testing.assert_array_equal(actual, expected) - class TestJp2k(unittest.TestCase): """These tests should be run by just about all configuration.""" @@ -1423,6 +1185,259 @@ class TestJp2kOpjDataRoot(unittest.TestCase): np.testing.assert_array_equal(ycbcr, expected) +class TestCodestream(unittest.TestCase): + """Test suite for unusual codestream cases.""" -if __name__ == "__main__": - unittest.main() + def setUp(self): + self.jp2file = glymur.data.nemo() + + def tearDown(self): + pass + + def test_siz_segment_ssiz_unsigned(self): + """ssiz attribute to be removed in future release""" + j = Jp2k(self.jp2file) + codestream = j.get_codestream() + + # The ssiz attribute was simply a tuple of raw bytes. + # The first 7 bits are interpreted as the bitdepth, the MSB determines + # whether or not it is signed. + self.assertEqual(codestream.segment[1].ssiz, (7, 7, 7)) + + +@unittest.skipIf(OPJ_DATA_ROOT is None, + "OPJ_DATA_ROOT environment variable not set") +class TestCodestreamOpjData(unittest.TestCase): + """Test suite for unusual codestream cases. Uses OPJ_DATA_ROOT""" + + def setUp(self): + self.jp2file = glymur.data.nemo() + + def tearDown(self): + pass + + @unittest.skipIf(os.name == "nt", "Temporary file issue on window.") + def test_reserved_marker_segment(self): + """Reserved marker segments are ok.""" + + # Some marker segments were reserved in FCD15444-1. Since that + # standard is old, some of them may have come into use. + # + # Let's inject a reserved marker segment into a file that + # we know something about to make sure we can still parse it. + filename = os.path.join(OPJ_DATA_ROOT, 'input/conformance/p0_01.j2k') + with tempfile.NamedTemporaryFile(suffix='.j2k') as tfile: + with open(filename, 'rb') as ifile: + # Everything up until the first QCD marker. + read_buffer = ifile.read(45) + tfile.write(read_buffer) + + # Write the new marker segment, 0xff6f = 65391 + read_buffer = struct.pack('>HHB', int(65391), int(3), int(0)) + tfile.write(read_buffer) + + # Get the rest of the input file. + read_buffer = ifile.read() + tfile.write(read_buffer) + tfile.flush() + + codestream = Jp2k(tfile.name).get_codestream() + + self.assertEqual(codestream.segment[2].marker_id, '0xff6f') + self.assertEqual(codestream.segment[2].length, 3) + self.assertEqual(codestream.segment[2].data, b'\x00') + + def test_psot_is_zero(self): + """Psot=0 in SOT is perfectly legal. Issue #78.""" + filename = os.path.join(OPJ_DATA_ROOT, + 'input/nonregression/123.j2c') + j = Jp2k(filename) + codestream = j.get_codestream(header_only=False) + + # The codestream is valid, so we should be able to get the entire + # codestream, so the last one is EOC. + self.assertEqual(codestream.segment[-1].marker_id, 'EOC') + + + def test_siz_segment_ssiz_signed(self): + """ssiz attribute to be removed in future release""" + filename = os.path.join(OPJ_DATA_ROOT, 'input/conformance/p0_03.j2k') + j = Jp2k(filename) + codestream = j.get_codestream() + + # The ssiz attribute was simply a tuple of raw bytes. + # The first 7 bits are interpreted as the bitdepth, the MSB determines + # whether or not it is signed. + self.assertEqual(codestream.segment[1].ssiz, (131,)) + + +class TestCodestreamRepr(unittest.TestCase): + + def setUp(self): + self.jp2file = glymur.data.nemo() + + def tearDown(self): + pass + + def test_soc(self): + """Test SOC segment repr""" + segment = glymur.codestream.SOCsegment() + newseg = eval(repr(segment)) + self.assertEqual(newseg.marker_id, 'SOC') + + def test_siz(self): + """Test SIZ segment repr""" + kwargs = {'rsiz': 0, + 'xysiz': (2592, 1456), + 'xyosiz': (0, 0), + 'xytsiz': (2592, 1456), + 'xytosiz': (0, 0), + 'Csiz': 3, + 'bitdepth': (8, 8, 8), + 'signed': (False, False, False), + 'xyrsiz': ((1, 1, 1), (1, 1, 1))} + segment = glymur.codestream.SIZsegment(**kwargs) + newseg = eval(repr(segment)) + self.assertEqual(newseg.marker_id, 'SIZ') + self.assertEqual(newseg.xsiz, 2592) + self.assertEqual(newseg.ysiz, 1456) + self.assertEqual(newseg.xosiz, 0) + self.assertEqual(newseg.yosiz, 0) + self.assertEqual(newseg.xtsiz, 2592) + self.assertEqual(newseg.ytsiz, 1456) + self.assertEqual(newseg.xtosiz, 0) + self.assertEqual(newseg.ytosiz, 0) + + self.assertEqual(newseg.xrsiz, (1, 1, 1)) + self.assertEqual(newseg.yrsiz, (1, 1, 1)) + self.assertEqual(newseg.bitdepth, (8, 8, 8)) + self.assertEqual(newseg.signed, (False, False, False)) + + +class TestCodestream(unittest.TestCase): + """Test suite for unusual codestream cases.""" + + def setUp(self): + self.jp2file = glymur.data.nemo() + + def tearDown(self): + pass + + def test_siz_segment_ssiz_unsigned(self): + """ssiz attribute to be removed in future release""" + j = Jp2k(self.jp2file) + codestream = j.get_codestream() + + # The ssiz attribute was simply a tuple of raw bytes. + # The first 7 bits are interpreted as the bitdepth, the MSB determines + # whether or not it is signed. + self.assertEqual(codestream.segment[1].ssiz, (7, 7, 7)) + + +@unittest.skipIf(OPJ_DATA_ROOT is None, + "OPJ_DATA_ROOT environment variable not set") +class TestCodestreamOpjData(unittest.TestCase): + """Test suite for unusual codestream cases. Uses OPJ_DATA_ROOT""" + + def setUp(self): + self.jp2file = glymur.data.nemo() + + def tearDown(self): + pass + + @unittest.skipIf(os.name == "nt", "Temporary file issue on window.") + def test_reserved_marker_segment(self): + """Reserved marker segments are ok.""" + + # Some marker segments were reserved in FCD15444-1. Since that + # standard is old, some of them may have come into use. + # + # Let's inject a reserved marker segment into a file that + # we know something about to make sure we can still parse it. + filename = os.path.join(OPJ_DATA_ROOT, 'input/conformance/p0_01.j2k') + with tempfile.NamedTemporaryFile(suffix='.j2k') as tfile: + with open(filename, 'rb') as ifile: + # Everything up until the first QCD marker. + read_buffer = ifile.read(45) + tfile.write(read_buffer) + + # Write the new marker segment, 0xff6f = 65391 + read_buffer = struct.pack('>HHB', int(65391), int(3), int(0)) + tfile.write(read_buffer) + + # Get the rest of the input file. + read_buffer = ifile.read() + tfile.write(read_buffer) + tfile.flush() + + codestream = Jp2k(tfile.name).get_codestream() + + self.assertEqual(codestream.segment[2].marker_id, '0xff6f') + self.assertEqual(codestream.segment[2].length, 3) + self.assertEqual(codestream.segment[2].data, b'\x00') + + def test_psot_is_zero(self): + """Psot=0 in SOT is perfectly legal. Issue #78.""" + filename = os.path.join(OPJ_DATA_ROOT, + 'input/nonregression/123.j2c') + j = Jp2k(filename) + codestream = j.get_codestream(header_only=False) + + # The codestream is valid, so we should be able to get the entire + # codestream, so the last one is EOC. + self.assertEqual(codestream.segment[-1].marker_id, 'EOC') + + + def test_siz_segment_ssiz_signed(self): + """ssiz attribute to be removed in future release""" + filename = os.path.join(OPJ_DATA_ROOT, 'input/conformance/p0_03.j2k') + j = Jp2k(filename) + codestream = j.get_codestream() + + # The ssiz attribute was simply a tuple of raw bytes. + # The first 7 bits are interpreted as the bitdepth, the MSB determines + # whether or not it is signed. + self.assertEqual(codestream.segment[1].ssiz, (131,)) + + +class TestCodestreamRepr(unittest.TestCase): + + def setUp(self): + self.jp2file = glymur.data.nemo() + + def tearDown(self): + pass + + def test_soc(self): + """Test SOC segment repr""" + segment = glymur.codestream.SOCsegment() + newseg = eval(repr(segment)) + self.assertEqual(newseg.marker_id, 'SOC') + + def test_siz(self): + """Test SIZ segment repr""" + kwargs = {'rsiz': 0, + 'xysiz': (2592, 1456), + 'xyosiz': (0, 0), + 'xytsiz': (2592, 1456), + 'xytosiz': (0, 0), + 'Csiz': 3, + 'bitdepth': (8, 8, 8), + 'signed': (False, False, False), + 'xyrsiz': ((1, 1, 1), (1, 1, 1))} + segment = glymur.codestream.SIZsegment(**kwargs) + newseg = eval(repr(segment)) + self.assertEqual(newseg.marker_id, 'SIZ') + self.assertEqual(newseg.xsiz, 2592) + self.assertEqual(newseg.ysiz, 1456) + self.assertEqual(newseg.xosiz, 0) + self.assertEqual(newseg.yosiz, 0) + self.assertEqual(newseg.xtsiz, 2592) + self.assertEqual(newseg.ytsiz, 1456) + self.assertEqual(newseg.xtosiz, 0) + self.assertEqual(newseg.ytosiz, 0) + + self.assertEqual(newseg.xrsiz, (1, 1, 1)) + self.assertEqual(newseg.yrsiz, (1, 1, 1)) + self.assertEqual(newseg.bitdepth, (8, 8, 8)) + self.assertEqual(newseg.signed, (False, False, False)) From 3ebb708e115842f581c2fdcf5952d68341e74822 Mon Sep 17 00:00:00 2001 From: John Evans Date: Wed, 19 Nov 2014 07:59:05 -0500 Subject: [PATCH 15/23] progress --- glymur/jp2k.py | 5 ++++- glymur/test/test_jp2k.py | 5 ++++- 2 files changed, 8 insertions(+), 2 deletions(-) diff --git a/glymur/jp2k.py b/glymur/jp2k.py index 2ea9588..9e2e120 100644 --- a/glymur/jp2k.py +++ b/glymur/jp2k.py @@ -1128,7 +1128,10 @@ class Jp2k(Jp2kBox): event_mgr = opj.EventMgrType() info_handler = ctypes.cast(_INFO_CALLBACK, ctypes.c_void_p) - event_mgr.info_handler = info_handler if verbose else None + if verbose or self._verbose: + event_mgr.info_handler = info_handler + else: + event_mgr.info_handler = None event_mgr.warning_handler = ctypes.cast(_WARNING_CALLBACK, ctypes.c_void_p) event_mgr.error_handler = ctypes.cast(_ERROR_CALLBACK, diff --git a/glymur/test/test_jp2k.py b/glymur/test/test_jp2k.py index 7e8c067..553a07e 100644 --- a/glymur/test/test_jp2k.py +++ b/glymur/test/test_jp2k.py @@ -227,6 +227,7 @@ class TestSliceProtocolRead(SliceProtocolBase): expected = self.j2k_data[3:8, :,:] np.testing.assert_array_equal(actual, expected) + @unittest.skip('see issue 301') def test_region_rlevel5(self): actual = self.j2k[5:533:32, 27:423:32] expected = self.j2k_data_r5[1:17, 1:14] @@ -288,7 +289,7 @@ class TestJp2k(unittest.TestCase): jpx = Jp2k(self.jpxfile) self.assertEqual(jpx.shape, (1024, 1024, 3)) - @unittest.skipIf(re.match("1.5|2", glymur.version.openjpeg_version) is None, + @unittest.skipIf(re.match("0|1.[0-4]", glymur.version.openjpeg_version), "Must have openjpeg 1.5 or higher to run") @unittest.skipIf(os.name == "nt", "Unexplained failure on windows") def test_irreversible(self): @@ -1116,6 +1117,8 @@ class TestJp2kOpjDataRootWarnings(unittest.TestCase): class TestJp2kOpjDataRoot(unittest.TestCase): """These tests should be run by just about all configuration.""" + @unittest.skipIf(re.match("0|1.[0-4]", glymur.version.openjpeg_version), + "Must have openjpeg 1.5 or higher to run") @unittest.skipIf(os.name == "nt", fixtures.WINDOWS_TMP_FILE_MSG) def test_irreversible(self): """Irreversible""" From 3c7341509059e083231bd15198b2a28243958bbd Mon Sep 17 00:00:00 2001 From: John Evans Date: Wed, 19 Nov 2014 09:22:40 -0500 Subject: [PATCH 16/23] progress, no more deprecation warnings? --- glymur/test/test_jp2k.py | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/glymur/test/test_jp2k.py b/glymur/test/test_jp2k.py index 553a07e..5158520 100644 --- a/glymur/test/test_jp2k.py +++ b/glymur/test/test_jp2k.py @@ -340,6 +340,7 @@ class TestJp2k(unittest.TestCase): self.assertEqual(newjp2.mode, 'rb') self.assertEqual(len(newjp2.box), 0) + @unittest.skip("see issue 302") def test_rlevel_max(self): """Verify that rlevel=-1 gets us the lowest resolution image""" j = Jp2k(self.j2kfile) @@ -352,7 +353,7 @@ class TestJp2k(unittest.TestCase): """Should error out appropriately if reduce level too high""" j = Jp2k(self.jp2file) with self.assertRaises(IOError): - j.read(rlevel=6) + j[::64, ::64] def test_not_jpeg2000(self): """Should error out appropriately if not given a JPEG 2000 file.""" @@ -849,8 +850,11 @@ class TestJp2k_1_x(unittest.TestCase): """ with patch('glymur.version.openjpeg_version_tuple', new=(1, 5, 0)): j2k = Jp2k(self.j2kfile) - with self.assertRaises(TypeError): - j2k.read(tile=0) + with warnings.catch_warnings(): + # The tile keyword is deprecated, so suppress the warning. + warnings.simplefilter('ignore') + with self.assertRaises(TypeError): + j2k.read(tile=0) def test_layer(self): """layer option not allowed for 1.x. From 6e1637e470b245a2bbf3b74d2dc95c49359e4838 Mon Sep 17 00:00:00 2001 From: John Evans Date: Wed, 19 Nov 2014 14:25:44 -0500 Subject: [PATCH 17/23] starting on incompatible changes to writing --- glymur/jp2k.py | 112 +++++++++++++++++++++------- glymur/test/test_jp2k.py | 103 +++++++++++-------------- glymur/test/test_opj_suite_write.py | 3 +- 3 files changed, 128 insertions(+), 90 deletions(-) diff --git a/glymur/jp2k.py b/glymur/jp2k.py index 9e2e120..2126d89 100644 --- a/glymur/jp2k.py +++ b/glymur/jp2k.py @@ -37,16 +37,6 @@ from .jp2box import ( ) from .lib import openjpeg as opj, openjp2 as opj2, c as libc -JP2_IDS = ['colr', 'cdef', 'cmap', 'jp2c', 'ftyp', 'ihdr', 'jp2h', 'jP ', - 'pclr', 'res ', 'resc', 'resd', 'xml ', 'ulst', 'uinf', 'url ', - 'uuid'] -JPX_IDS = ['asoc', 'nlst'] - -_COLORSPACE_MAP = {'rgb': opj2.CLRSPC_SRGB, - 'gray': opj2.CLRSPC_GRAY, - 'grey': opj2.CLRSPC_GRAY, - 'ycc': opj2.CLRSPC_YCC} - class Jp2k(Jp2kBox): """JPEG 2000 file. @@ -54,8 +44,6 @@ class Jp2k(Jp2kBox): ---------- filename : str The path to the JPEG 2000 file. - mode : str - The mode used to open the file. box : sequence List of top-level boxes in the file. Each box may in turn contain its own list of boxes. Will be empty if the file consists only of a @@ -92,18 +80,16 @@ class Jp2k(Jp2kBox): (728, 1296, 3) """ - def __init__(self, filename, mode='rb'): + def __init__(self, filename, data=None, shape=None, **kwargs): """ Parameters ---------- filename : str or file The path to JPEG 2000 file. - mode : str, optional - The mode used to open the file. """ Jp2kBox.__init__(self) self.filename = filename - self.mode = mode + self.box = [] self._codec_format = None self._colorspace = None @@ -114,8 +100,10 @@ class Jp2k(Jp2kBox): self._verbose = False # Parse the file for JP2/JPX contents only if we are reading it. - if mode == 'rb': + if data is None and shape is None: self.parse() + else: + self._write(data, **kwargs) @property def ignore_pclr_cmap_cdef(self): @@ -433,6 +421,77 @@ class Jp2k(Jp2kBox): self._cparams = cparams + def _write(self, img_array, verbose=False, **kwargs): + """Write image data to a JP2/JPX/J2k file. Intended usage of the + various parameters follows that of OpenJPEG's opj_compress utility. + + This method can only be used to create JPEG 2000 images that can fit + in memory. + + Parameters + ---------- + img_array : ndarray + Image data to be written to file. + cbsize : tuple, optional + Code block size (DY, DX). + cinema2k : int, optional + frames per second, either 24 or 48 + cinema4k : bool, optional + Set to True to specify Cinema4K mode, defaults to false. + colorspace : str, optional + Either 'rgb' or 'gray'. + cratios : iterable + Compression ratios for successive layers. + eph : bool, optional + If true, write SOP marker after each header packet. + grid_offset : tuple, optional + Offset (DY, DX) of the origin of the image in the reference grid. + irreversible : bool, optional + If true, use the irreversible DWT 9-7 transform. + mct : bool, optional + Specifies usage of the multi component transform. If not + specified, defaults to True if the colorspace is RGB. + modesw : int, optional + Mode switch. + 1 = BYPASS(LAZY) + 2 = RESET + 4 = RESTART(TERMALL) + 8 = VSC + 16 = ERTERM(SEGTERM) + 32 = SEGMARK(SEGSYM) + numres : int, optional + Number of resolutions. + prog : str, optional + Progression order, one of "LRCP" "RLCP", "RPCL", "PCRL", "CPRL". + psnr : iterable, optional + Different PSNR for successive layers. + psizes : list, optional + List of precinct sizes. Each precinct size tuple is defined in + (height x width). + sop : bool, optional + If true, write SOP marker before each packet. + subsam : tuple, optional + Subsampling factors (dy, dx). + tilesize : tuple, optional + Numeric tuple specifying tile size in terms of (numrows, numcols), + not (X, Y). + verbose : bool, optional + Print informational messages produced by the OpenJPEG library. + + """ + if re.match("1.[0-4]", version.openjpeg_version) is not None: + raise RuntimeError("You must have at least version 1.5 of OpenJPEG " + "in order to write images.") + + self._shape = img_array.shape + self._determine_colorspace(**kwargs) + self._populate_cparams(img_array, **kwargs) + + if opj2.OPENJP2 is not None: + self._write_openjp2(img_array, verbose=verbose) + else: + self._write_openjpeg(img_array, verbose=verbose) + def write(self, img_array, verbose=False, **kwargs): """Write image data to a JP2/JPX/J2k file. Intended usage of the various parameters follows that of OpenJPEG's opj_compress utility. @@ -490,16 +549,6 @@ class Jp2k(Jp2kBox): verbose : bool, optional Print informational messages produced by the OpenJPEG library. - Examples - -------- - >>> import glymur - >>> jfile = glymur.data.nemo() - >>> jp2 = glymur.Jp2k(jfile) - >>> data = jp2.read(rlevel=1) - >>> from tempfile import NamedTemporaryFile - >>> tfile = NamedTemporaryFile(suffix='.jp2', delete=False) - >>> j = Jp2k(tfile.name, mode='wb') - >>> j.write(data.astype(np.uint8)) """ if re.match("1.[0-4]", version.openjpeg_version) is not None: raise RuntimeError("You must have at least version 1.5 of OpenJPEG " @@ -679,7 +728,12 @@ class Jp2k(Jp2kBox): # Turn the colorspace from a string to the enumerated value that # the library expects. - self._colorspace = _COLORSPACE_MAP[colorspace.lower()] + COLORSPACE_MAP = {'rgb': opj2.CLRSPC_SRGB, + 'gray': opj2.CLRSPC_GRAY, + 'grey': opj2.CLRSPC_GRAY, + 'ycc': opj2.CLRSPC_YCC} + + self._colorspace = COLORSPACE_MAP[colorspace.lower()] def _write_openjp2(self, img_array, verbose=False): @@ -1780,6 +1834,8 @@ def _validate_singletons(boxes): if 'dtbl' in multiples: raise IOError('There can only be one dtbl box in a file.') +JPX_IDS = ['asoc', 'nlst'] + def _validate_jpx_brand(boxes, brand): """ If there is a JPX box then the brand must be 'jpx '. diff --git a/glymur/test/test_jp2k.py b/glymur/test/test_jp2k.py index 5158520..257688f 100644 --- a/glymur/test/test_jp2k.py +++ b/glymur/test/test_jp2k.py @@ -81,6 +81,7 @@ class SliceProtocolBase(unittest.TestCase): @unittest.skipIf(os.name == "nt", fixtures.WINDOWS_TMP_FILE_MSG) class TestSliceProtocolBaseWrite(SliceProtocolBase): + @unittest.skip('requires shape implementation') def test_write_ellipsis(self): expected = self.j2k_data @@ -95,12 +96,12 @@ class TestSliceProtocolBaseWrite(SliceProtocolBase): expected = self.j2k_data with tempfile.NamedTemporaryFile(suffix='.j2k') as tfile: - j = Jp2k(tfile.name, 'wb') - j[:] = self.j2k_data + j = Jp2k(tfile.name, data=self.j2k_data) actual = j[:] np.testing.assert_array_equal(actual, expected) + @unittest.skip('requires shape implementation') def test_cannot_write_with_non_default_single_slice(self): with tempfile.NamedTemporaryFile(suffix='.j2k') as tfile: j = Jp2k(tfile.name, 'wb') @@ -113,30 +114,35 @@ class TestSliceProtocolBaseWrite(SliceProtocolBase): with self.assertRaises(TypeError): j[slice(0, 640)] = self.j2k_data + @unittest.skip('requires shape implementation') def test_cannot_write_a_row(self): with tempfile.NamedTemporaryFile(suffix='.j2k') as tfile: j = Jp2k(tfile.name, 'wb') with self.assertRaises(TypeError): j[5] = self.j2k_data + @unittest.skip('requires shape implementation') def test_cannot_write_a_pixel(self): with tempfile.NamedTemporaryFile(suffix='.j2k') as tfile: j = Jp2k(tfile.name, 'wb') with self.assertRaises(TypeError): j[25, 35] = self.j2k_data[25, 35] + @unittest.skip('requires shape implementation') def test_cannot_write_a_column(self): with tempfile.NamedTemporaryFile(suffix='.j2k') as tfile: j = Jp2k(tfile.name, 'wb') with self.assertRaises(TypeError): j[:, 25, :] = self.j2k_data[:, :25, :] + @unittest.skip('requires shape implementation') def test_cannot_write_a_band(self): with tempfile.NamedTemporaryFile(suffix='.j2k') as tfile: j = Jp2k(tfile.name, 'wb') with self.assertRaises(TypeError): j[:, :, 0] = self.j2k_data[:, :, 0] + @unittest.skip('requires shape implementation') def test_cannot_write_a_subarray(self): with tempfile.NamedTemporaryFile(suffix='.j2k') as tfile: j = Jp2k(tfile.name, 'wb') @@ -297,8 +303,7 @@ class TestJp2k(unittest.TestCase): j = Jp2k(self.jp2file) expdata = j[:] with tempfile.NamedTemporaryFile(suffix='.j2k') as tfile: - j2 = Jp2k(tfile.name, 'wb') - j2.write(expdata, irreversible=True) + j2 = Jp2k(tfile.name, data=expdata, irreversible=True) codestream = j2.get_codestream() self.assertEqual(codestream.segment[2].spcod[8], @@ -337,7 +342,6 @@ class TestJp2k(unittest.TestCase): newjp2 = eval(repr(j)) self.assertEqual(newjp2.filename, self.j2kfile) - self.assertEqual(newjp2.mode, 'rb') self.assertEqual(len(newjp2.box), 0) @unittest.skip("see issue 302") @@ -664,32 +668,30 @@ class TestJp2k_write(unittest.TestCase): data = np.zeros((640, 480), dtype=np.uint8) with tempfile.NamedTemporaryFile(suffix='.j2k') as tfile: with self.assertRaises(IOError): - j = Jp2k(tfile.name, 'wb') - j.write(data, cbsize=(16, 16), psizes=[(16, 16)]) + j = Jp2k(tfile.name, data=data, + cbsize=(16, 16), psizes=[(16, 16)]) def test_precinct_size_not_power_of_two(self): """must be power of two""" data = np.zeros((640, 480), dtype=np.uint8) with tempfile.NamedTemporaryFile(suffix='.j2k') as tfile: with self.assertRaises(IOError): - j = Jp2k(tfile.name, 'wb') - j.write(data, cbsize=(16, 16), psizes=[(48, 48)]) + j = Jp2k(tfile.name, data=data, + cbsize=(16, 16), psizes=[(48, 48)]) def test_unsupported_int32(self): """Should raise a runtime error if trying to write int32""" data = np.zeros((128, 128), dtype=np.int32) with tempfile.NamedTemporaryFile(suffix='.j2k') as tfile: with self.assertRaises(RuntimeError): - j = Jp2k(tfile.name, 'wb') - j.write(data) + j = Jp2k(tfile.name, data=data) def test_unsupported_uint32(self): """Should raise a runtime error if trying to write uint32""" data = np.zeros((128, 128), dtype=np.uint32) with tempfile.NamedTemporaryFile(suffix='.j2k') as tfile: with self.assertRaises(RuntimeError): - j = Jp2k(tfile.name, 'wb') - j.write(data) + j = Jp2k(tfile.name, data=data) def test_write_with_version_too_early(self): """Should raise a runtime error if trying to write with version 1.3""" @@ -699,8 +701,7 @@ class TestJp2k_write(unittest.TestCase): with patch('glymur.version.openjpeg_version', new=version): with tempfile.NamedTemporaryFile(suffix='.j2k') as tfile: with self.assertRaises(RuntimeError): - j = Jp2k(tfile.name, 'wb') - j.write(data) + j = Jp2k(tfile.name, data=data) def test_cblkh_different_than_width(self): """Verify that we can set a code block size where height does not equal @@ -708,11 +709,8 @@ class TestJp2k_write(unittest.TestCase): """ data = np.zeros((128, 128), dtype=np.uint8) with tempfile.NamedTemporaryFile(suffix='.j2k') as tfile: - j = Jp2k(tfile.name, 'wb') - # The code block dimensions are given as rows x columns. - j.write(data, cbsize=(16, 32)) - + j = Jp2k(tfile.name, data=data, cbsize=(16, 32)) codestream = j.get_codestream() # Code block size is reported as XY in the codestream. @@ -721,59 +719,55 @@ class TestJp2k_write(unittest.TestCase): def test_too_many_dimensions(self): """OpenJP2 only allows 2D or 3D images.""" with tempfile.NamedTemporaryFile(suffix='.j2k') as tfile: - j = Jp2k(tfile.name, 'wb') with self.assertRaises(IOError): - data = np.zeros((128, 128, 2, 2), dtype=np.uint8) - j.write(data) + j = Jp2k(tfile.name, + data=np.zeros((128, 128, 2, 2), dtype=np.uint8)) def test_2d_rgb(self): """RGB must have at least 3 components.""" with tempfile.NamedTemporaryFile(suffix='.jp2') as tfile: - j = Jp2k(tfile.name, 'wb') with self.assertRaises(IOError): - data = np.zeros((128, 128, 2), dtype=np.uint8) - j.write(data, colorspace='rgb') + j = Jp2k(tfile.name, + data=np.zeros((128, 128, 2), dtype=np.uint8), + colorspace='rgb') def test_colorspace_with_j2k(self): """Specifying a colorspace with J2K does not make sense""" with tempfile.NamedTemporaryFile(suffix='.j2k') as tfile: - j = Jp2k(tfile.name, 'wb') with self.assertRaises(IOError): - data = np.zeros((128, 128, 3), dtype=np.uint8) - j.write(data, colorspace='rgb') + j = Jp2k(tfile.name, + data=np.zeros((128, 128, 3), dtype=np.uint8), + colorspace='rgb') def test_specify_rgb(self): """specify RGB explicitly""" with tempfile.NamedTemporaryFile(suffix='.jp2') as tfile: - j = Jp2k(tfile.name, 'wb') - data = np.zeros((128, 128, 3), dtype=np.uint8) - j.write(data, colorspace='rgb') + j = Jp2k(tfile.name, + data=np.zeros((128, 128, 3), dtype=np.uint8), + colorspace='rgb') self.assertEqual(j.box[2].box[1].colorspace, glymur.core.SRGB) def test_specify_gray(self): """test gray explicitly specified (that's GRAY, not GREY)""" with tempfile.NamedTemporaryFile(suffix='.jp2') as tfile: - j = Jp2k(tfile.name, 'wb') data = np.zeros((128, 128), dtype=np.uint8) - j.write(data, colorspace='gray') + j = Jp2k(tfile.name, data=data, colorspace='gray') self.assertEqual(j.box[2].box[1].colorspace, glymur.core.GREYSCALE) def test_specify_grey(self): """test grey explicitly specified""" with tempfile.NamedTemporaryFile(suffix='.jp2') as tfile: - j = Jp2k(tfile.name, 'wb') data = np.zeros((128, 128), dtype=np.uint8) - j.write(data, colorspace='grey') + j = Jp2k(tfile.name, data=data, colorspace='grey') self.assertEqual(j.box[2].box[1].colorspace, glymur.core.GREYSCALE) def test_grey_with_two_extra_comps(self): """should be able to write gray + two extra components""" with tempfile.NamedTemporaryFile(suffix='.jp2') as tfile: - j = Jp2k(tfile.name, 'wb') data = np.zeros((128, 128, 3), dtype=np.uint8) - j.write(data, colorspace='gray') + j = Jp2k(tfile.name, data=data, colorspace='gray') self.assertEqual(j.box[2].box[0].height, 128) self.assertEqual(j.box[2].box[0].width, 128) self.assertEqual(j.box[2].box[0].num_components, 3) @@ -783,18 +777,16 @@ class TestJp2k_write(unittest.TestCase): def test_specify_ycc(self): """Should reject YCC""" with tempfile.NamedTemporaryFile(suffix='.jp2') as tfile: - j = Jp2k(tfile.name, 'wb') with self.assertRaises(IOError): data = np.zeros((128, 128, 3), dtype=np.uint8) - j.write(data, colorspace='ycc') + j = Jp2k(tfile.name, data=data, colorspace='ycc') def test_write_with_jp2_in_caps(self): """should be able to write with JP2 suffix.""" j2k = Jp2k(self.j2kfile) expdata = j2k[:] with tempfile.NamedTemporaryFile(suffix='.JP2') as tfile: - ofile = Jp2k(tfile.name, 'wb') - ofile[:] = expdata + ofile = Jp2k(tfile.name, data=expdata) actdata = ofile[:] np.testing.assert_array_equal(actdata, expdata) @@ -803,8 +795,7 @@ class TestJp2k_write(unittest.TestCase): j2k = Jp2k(self.j2kfile) expdata = j2k[:] with tempfile.NamedTemporaryFile(suffix='.jp2') as tfile: - ofile = Jp2k(tfile.name, 'wb') - ofile.write(expdata, mct=False) + ofile = Jp2k(tfile.name, data=expdata, mct=False) actdata = ofile[:] np.testing.assert_array_equal(actdata, expdata) @@ -816,9 +807,8 @@ class TestJp2k_write(unittest.TestCase): j2k = Jp2k(self.j2kfile) expdata = j2k[:] with tempfile.NamedTemporaryFile(suffix='.jp2') as tfile: - ofile = Jp2k(tfile.name, 'wb') with self.assertRaises(IOError): - ofile.write(expdata[:, :, 0], mct=True) + ofile = Jp2k(tfile.name, data=expdata[:, :, 0], mct=True) def test_write_cprl(self): """Must be able to write a CPRL progression order file""" @@ -826,8 +816,7 @@ class TestJp2k_write(unittest.TestCase): j = Jp2k(self.jp2file) expdata = j[::2, ::2] with tempfile.NamedTemporaryFile(suffix='.jp2') as tfile: - ofile = Jp2k(tfile.name, 'wb') - ofile.write(expdata, prog='CPRL') + ofile = Jp2k(tfile.name, data=expdata, prog='CPRL') actdata = ofile[:] np.testing.assert_array_equal(actdata, expdata) @@ -873,10 +862,9 @@ class Test_2p0_official(unittest.TestCase): """Can only write 4 components on 2.0+, should error out otherwise.""" with patch('glymur.version.openjpeg_version', new="2.0.0"): with tempfile.NamedTemporaryFile(suffix='.jp2') as tfile: - j = Jp2k(tfile.name, 'wb') data = np.zeros((128, 128, 4), dtype=np.uint8) with self.assertRaises(IOError): - j.write(data) + Jp2k(tfile.name, data=data) @unittest.skipIf(glymur.version.openjpeg_version_tuple[0] < 2, @@ -908,10 +896,9 @@ class TestJp2k_2_0(unittest.TestCase): def test_unrecognized_jp2_clrspace(self): """We only allow RGB and GRAYSCALE. Should error out with others""" with tempfile.NamedTemporaryFile(suffix='.jp2') as tfile: - j = Jp2k(tfile.name, 'wb') + data = np.zeros((128, 128, 3), dtype=np.uint8) with self.assertRaises(IOError): - data = np.zeros((128, 128, 3), dtype=np.uint8) - j.write(data, colorspace='cmyk') + j = Jp2k(tfile.name, data=data, colorspace='cmyk') @unittest.skipIf(os.name == "nt", fixtures.WINDOWS_TMP_FILE_MSG) def test_asoc_label_box(self): @@ -920,8 +907,7 @@ class TestJp2k_2_0(unittest.TestCase): # OpenJPEG doesn't have such a file. data = Jp2k(self.jp2file)[::2, ::2] with tempfile.NamedTemporaryFile(suffix='.jp2') as tfile: - j = Jp2k(tfile.name, 'wb') - j.write(data) + j = Jp2k(tfile.name, data=data) with tempfile.NamedTemporaryFile(suffix='.jp2') as tfile2: @@ -979,9 +965,8 @@ class TestJp2k_2_1(unittest.TestCase): def test_grey_with_extra_component(self): """version 2.0 cannot write gray + extra""" with tempfile.NamedTemporaryFile(suffix='.jp2') as tfile: - j = Jp2k(tfile.name, 'wb') data = np.zeros((128, 128, 2), dtype=np.uint8) - j.write(data) + j = Jp2k(tfile.name, data=data) self.assertEqual(j.box[2].box[0].height, 128) self.assertEqual(j.box[2].box[0].width, 128) self.assertEqual(j.box[2].box[0].num_components, 2) @@ -992,9 +977,8 @@ class TestJp2k_2_1(unittest.TestCase): def test_rgb_with_extra_component(self): """v2.0+ should be able to write extra components""" with tempfile.NamedTemporaryFile(suffix='.jp2') as tfile: - j = Jp2k(tfile.name, 'wb') data = np.zeros((128, 128, 4), dtype=np.uint8) - j.write(data) + j = Jp2k(tfile.name, data=data) self.assertEqual(j.box[2].box[0].height, 128) self.assertEqual(j.box[2].box[0].width, 128) self.assertEqual(j.box[2].box[0].num_components, 4) @@ -1130,8 +1114,7 @@ class TestJp2kOpjDataRoot(unittest.TestCase): expdata = np.fromfile(filename, dtype=np.uint16) expdata.resize((2816, 2048)) with tempfile.NamedTemporaryFile(suffix='.j2k') as tfile: - j = Jp2k(tfile.name, 'wb') - j.write(expdata, irreversible=True) + j = Jp2k(tfile.name, data=expdata, irreversible=True) codestream = j.get_codestream() self.assertEqual(codestream.segment[2].spcod[8], diff --git a/glymur/test/test_opj_suite_write.py b/glymur/test/test_opj_suite_write.py index 8be1cef..b394d72 100644 --- a/glymur/test/test_opj_suite_write.py +++ b/glymur/test/test_opj_suite_write.py @@ -221,9 +221,8 @@ class TestNegative2pointzero(unittest.TestCase): for version in versions: with patch('glymur.version.openjpeg_version', new=version): with tempfile.NamedTemporaryFile(suffix='.j2k') as tfile: - j = Jp2k(tfile.name, 'wb') with self.assertRaises(IOError): - j.write(data, cinema2k=48) + j = Jp2k(tfile.name, data=data, cinema2k=48) @unittest.skipIf(re.match(r'''1.[0-4]''', openjpeg_version) is not None, From 8f8e9eff852d7f064c713983c9f64fb590212ba7 Mon Sep 17 00:00:00 2001 From: John Evans Date: Wed, 19 Nov 2014 14:49:15 -0500 Subject: [PATCH 18/23] get write tests passing on travis --- glymur/test/test_jp2box.py | 16 ++++++---------- glymur/test/test_printing.py | 3 +-- 2 files changed, 7 insertions(+), 12 deletions(-) diff --git a/glymur/test/test_jp2box.py b/glymur/test/test_jp2box.py index b8ad2ec..9d1f9cf 100644 --- a/glymur/test/test_jp2box.py +++ b/glymur/test/test_jp2box.py @@ -59,13 +59,12 @@ class TestDataEntryURL(unittest.TestCase): def test_wrap_greyscale(self): """A single component should be wrapped as GREYSCALE.""" j = Jp2k(self.jp2file) - data = j.read() + data = j[:] red = data[:, :, 0] # Write it back out as a raw codestream. with tempfile.NamedTemporaryFile(suffix=".j2k") as tfile1: - j2k = glymur.Jp2k(tfile1.name, 'wb') - j2k.write(data[:, :, 0]) + j2k = glymur.Jp2k(tfile1.name, data=red) # Ok, now rewrap it as JP2. The colorspace should be GREYSCALE. with tempfile.NamedTemporaryFile(suffix=".jp2") as tfile2: @@ -126,24 +125,21 @@ class TestChannelDefinition(unittest.TestCase): def setUpClass(cls): """Need a one_plane plane image for greyscale testing.""" j2k = Jp2k(glymur.data.goodstuff()) - data = j2k.read() + data = j2k[:] # 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]) + grey_j2k = Jp2k(tfile.name, data=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]) + grey_j2k = Jp2k(tfile.name, data=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) + rgba_jp2 = Jp2k(tfile.name, data=data4) cls.four_planes = tfile.name @classmethod diff --git a/glymur/test/test_printing.py b/glymur/test/test_printing.py index 5dae016..5eedfe5 100644 --- a/glymur/test/test_printing.py +++ b/glymur/test/test_printing.py @@ -115,8 +115,7 @@ class TestPrinting(unittest.TestCase): # OpenJPEG doesn't have such a file. data = glymur.Jp2k(self.jp2file)[::2, ::2] with tempfile.NamedTemporaryFile(suffix='.jp2') as tfile: - j = glymur.Jp2k(tfile.name, 'wb') - j.write(data) + j = glymur.Jp2k(tfile.name, data=data) with tempfile.NamedTemporaryFile(suffix='.jp2') as tfile2: From e1846c31e0cb2bfab24456eb26c4b6f3ed539fa6 Mon Sep 17 00:00:00 2001 From: John Evans Date: Wed, 19 Nov 2014 15:34:03 -0500 Subject: [PATCH 19/23] progress on write --- glymur/test/test_callbacks.py | 4 +-- glymur/test/test_opj_suite_neg.py | 27 ++++++--------- glymur/test/test_opj_suite_write.py | 53 ++++++++++++----------------- 3 files changed, 33 insertions(+), 51 deletions(-) diff --git a/glymur/test/test_callbacks.py b/glymur/test/test_callbacks.py index a58cfeb..d8fc28e 100644 --- a/glymur/test/test_callbacks.py +++ b/glymur/test/test_callbacks.py @@ -60,10 +60,8 @@ class TestCallbacks(unittest.TestCase): j = glymur.Jp2k(self.jp2file) tiledata = j[:] with tempfile.NamedTemporaryFile(suffix='.jp2') as tfile: - jp2 = glymur.Jp2k(tfile.name, 'wb') with patch('sys.stdout', new=StringIO()) as fake_out: - jp2.verbose = True - jp2[:] = tiledata + jp2 = glymur.Jp2k(tfile.name, data=tiledata, verbose=True) actual = fake_out.getvalue().strip() expected = '[INFO] tile number 1 / 1' self.assertEqual(actual, expected) diff --git a/glymur/test/test_opj_suite_neg.py b/glymur/test/test_opj_suite_neg.py index 350b7a5..c7e31e5 100644 --- a/glymur/test/test_opj_suite_neg.py +++ b/glymur/test/test_opj_suite_neg.py @@ -97,9 +97,8 @@ class TestSuiteNegativeWrite(unittest.TestCase): 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) + j = Jp2k(tfile.name, data=data, cinema2k=36) @unittest.skipIf(NO_READ_BACKEND, NO_READ_BACKEND_MSG) @@ -109,9 +108,9 @@ class TestSuiteNegativeWrite(unittest.TestCase): infile = opj_data_file('input/nonregression/Bretagne1.ppm') data = read_image(infile) with tempfile.NamedTemporaryFile(suffix='.j2k') as tfile: - j = Jp2k(tfile.name, 'wb') with self.assertRaises(IOError): - j.write(data, psnr=[30, 35, 40], cratios=[2, 3, 4]) + j = Jp2k(tfile.name, + data=data, psnr=[30, 35, 40], cratios=[2, 3, 4]) def test_code_block_dimensions(self): """don't allow extreme codeblock sizes""" @@ -119,44 +118,38 @@ class TestSuiteNegativeWrite(unittest.TestCase): # to be too small or too big, so neither will we. data = np.zeros((256, 256), dtype=np.uint8) with tempfile.NamedTemporaryFile(suffix='.j2k') as tfile: - j = Jp2k(tfile.name, 'wb') - # opj_compress doesn't allow code block area to exceed 4096. with self.assertRaises(IOError): - j.write(data, cbsize=(256, 256)) + j = Jp2k(tfile.name, data=data, cbsize=(256, 256)) # opj_compress doesn't allow either dimension to be less than 4. with self.assertRaises(IOError): - j.write(data, cbsize=(2048, 2)) + j = Jp2k(tfile.name, data=data, cbsize=(2048, 2)) with self.assertRaises(IOError): - j.write(data, cbsize=(2, 2048)) + j = Jp2k(tfile.name, data=data, cbsize=(2, 2048)) def test_precinct_size_not_p2(self): """precinct sizes should be powers of two.""" ifile = Jp2k(self.j2kfile) data = ifile[::4, ::4] with tempfile.NamedTemporaryFile(suffix='.jp2') as tfile: - ofile = Jp2k(tfile.name, 'wb') with self.assertRaises(IOError): - ofile.write(data, psizes=[(13, 13)]) + ofile = Jp2k(tfile.name, data=data, psizes=[(13, 13)]) def test_cblk_size_not_power_of_two(self): """code block sizes should be powers of two.""" ifile = Jp2k(self.j2kfile) data = ifile[::4, ::4] with tempfile.NamedTemporaryFile(suffix='.jp2') as tfile: - ofile = Jp2k(tfile.name, 'wb') with self.assertRaises(IOError): - ofile.write(data, cbsize=(13, 12)) + ofile = Jp2k(tfile.name, data=data, cbsize=(13, 12)) def test_cblk_size_precinct_size(self): """code block sizes should never exceed half that of precinct size.""" ifile = Jp2k(self.j2kfile) data = ifile[::4, ::4] with tempfile.NamedTemporaryFile(suffix='.jp2') as tfile: - ofile = Jp2k(tfile.name, 'wb') with self.assertRaises(IOError): - ofile.write(data, - cbsize=(64, 64), - psizes=[(64, 64)]) + ofile = Jp2k(tfile.name, + data=data, cbsize=(64, 64), psizes=[(64, 64)]) diff --git a/glymur/test/test_opj_suite_write.py b/glymur/test/test_opj_suite_write.py index b394d72..9d8f5b7 100644 --- a/glymur/test/test_opj_suite_write.py +++ b/glymur/test/test_opj_suite_write.py @@ -87,9 +87,9 @@ class WriteCinema(CinemaBase): 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=48, cratios=[200, 100, 50]) + j = Jp2k(tfile.name, data=data, + cinema2k=48, cratios=[200, 100, 50]) def test_cinema4K_with_others(self): """Can't specify cinema4k with any other options.""" @@ -97,9 +97,9 @@ class WriteCinema(CinemaBase): 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, cinema4k=True, cratios=[200, 100, 50]) + j = Jp2k(tfile.name, data=data, + cinema4k=True, cratios=[200, 100, 50]) @unittest.skipIf(WARNING_INFRASTRUCTURE_ISSUE, WARNING_INFRASTRUCTURE_MSG) @@ -248,8 +248,7 @@ class TestSuiteWrite(fixtures.MetadataBase): expdata = np.fromfile(filename, dtype=np.uint16) expdata.resize((2816, 2048)) with tempfile.NamedTemporaryFile(suffix='.j2k') as tfile: - j = Jp2k(tfile.name, 'wb') - j.write(expdata, irreversible=True) + j = Jp2k(tfile.name, data=expdata, irreversible=True) codestream = j.get_codestream() self.assertEqual(codestream.segment[2].spcod[8], @@ -261,8 +260,7 @@ class TestSuiteWrite(fixtures.MetadataBase): infile = opj_data_file('input/nonregression/Bretagne1.ppm') data = read_image(infile) with tempfile.NamedTemporaryFile(suffix='.j2k') as tfile: - j = Jp2k(tfile.name, 'wb') - j.write(data, cratios=[200, 100, 50]) + j = Jp2k(tfile.name, data=data, cratios=[200, 100, 50]) # Should be three layers. c = j.get_codestream() @@ -293,8 +291,7 @@ class TestSuiteWrite(fixtures.MetadataBase): infile = opj_data_file('input/nonregression/Bretagne1.ppm') data = read_image(infile) with tempfile.NamedTemporaryFile(suffix='.j2k') as tfile: - j = Jp2k(tfile.name, 'wb') - j.write(data, psnr=[30, 35, 40], numres=2) + j = Jp2k(tfile.name, data=data, psnr=[30, 35, 40], numres=2) # Should be three layers. codestream = j.get_codestream() @@ -325,9 +322,9 @@ class TestSuiteWrite(fixtures.MetadataBase): infile = opj_data_file('input/nonregression/Bretagne1.ppm') data = read_image(infile) with tempfile.NamedTemporaryFile(suffix='.j2k') as tfile: - j = Jp2k(tfile.name, 'wb') - j.write(data, psnr=[30, 35, 40], cbsize=(16, 16), - psizes=[(64, 64)]) + j = Jp2k(tfile.name, + data=data, + psnr=[30, 35, 40], cbsize=(16, 16), psizes=[(64, 64)]) # Should be three layers. codestream = j.get_codestream() @@ -360,8 +357,8 @@ class TestSuiteWrite(fixtures.MetadataBase): infile = opj_data_file('input/nonregression/Bretagne2.ppm') data = read_image(infile) with tempfile.NamedTemporaryFile(suffix='.j2k') as tfile: - j = Jp2k(tfile.name, 'wb') - j.write(data, + j = Jp2k(tfile.name, + data=data, psizes=[(128, 128)] * 3, cratios=[100, 20, 2], tilesize=(480, 640), @@ -397,8 +394,7 @@ class TestSuiteWrite(fixtures.MetadataBase): infile = opj_data_file('input/nonregression/Bretagne2.ppm') data = read_image(infile) with tempfile.NamedTemporaryFile(suffix='.j2k') as tfile: - j = Jp2k(tfile.name, 'wb') - j.write(data, tilesize=(127, 127), prog="PCRL") + j = Jp2k(tfile.name, data=data, tilesize=(127, 127), prog="PCRL") codestream = j.get_codestream() @@ -428,8 +424,7 @@ class TestSuiteWrite(fixtures.MetadataBase): infile = opj_data_file('input/nonregression/Bretagne2.ppm') data = read_image(infile) with tempfile.NamedTemporaryFile(suffix='.j2k') as tfile: - j = Jp2k(tfile.name, 'wb') - j.write(data, subsam=(2, 2), sop=True) + j = Jp2k(tfile.name, data=data, subsam=(2, 2), sop=True) codestream = j.get_codestream(header_only=False) @@ -464,8 +459,7 @@ class TestSuiteWrite(fixtures.MetadataBase): infile = opj_data_file('input/nonregression/Bretagne2.ppm') data = read_image(infile) with tempfile.NamedTemporaryFile(suffix='.j2k') as tfile: - j = Jp2k(tfile.name, 'wb') - j.write(data, modesw=38, eph=True) + j = Jp2k(tfile.name, data=data, modesw=38, eph=True) codestream = j.get_codestream(header_only=False) @@ -499,8 +493,8 @@ class TestSuiteWrite(fixtures.MetadataBase): infile = opj_data_file('input/nonregression/Bretagne2.ppm') data = read_image(infile) with tempfile.NamedTemporaryFile(suffix='.j2k') as tfile: - j = Jp2k(tfile.name, 'wb') - j.write(data, grid_offset=[300, 150], cratios=[800]) + j = Jp2k(tfile.name, + data=data, grid_offset=[300, 150], cratios=[800]) codestream = j.get_codestream(header_only=False) @@ -530,8 +524,7 @@ class TestSuiteWrite(fixtures.MetadataBase): infile = opj_data_file('input/nonregression/Cevennes1.bmp') data = read_image(infile) with tempfile.NamedTemporaryFile(suffix='.j2k') as tfile: - j = Jp2k(tfile.name, 'wb') - j.write(data, cratios=[800]) + j = Jp2k(tfile.name, data=data, cratios=[800]) codestream = j.get_codestream(header_only=False) @@ -561,8 +554,7 @@ class TestSuiteWrite(fixtures.MetadataBase): infile = opj_data_file('input/nonregression/Cevennes2.ppm') data = read_image(infile) with tempfile.NamedTemporaryFile(suffix='.j2k') as tfile: - j = Jp2k(tfile.name, 'wb') - j.write(data, cratios=[50]) + j = Jp2k(tfile.name, data=data, cratios=[50]) codestream = j.get_codestream(header_only=False) @@ -591,8 +583,8 @@ class TestSuiteWrite(fixtures.MetadataBase): """NR-ENC-Rome.bmp-11-encode""" data = read_image(opj_data_file('input/nonregression/Rome.bmp')) with tempfile.NamedTemporaryFile(suffix='.jp2') as tfile: - jp2 = Jp2k(tfile.name, 'wb') - jp2.write(data, psnr=[30, 35, 50], prog='LRCP', numres=3) + jp2 = Jp2k(tfile.name, + data=data, psnr=[30, 35, 50], prog='LRCP', numres=3) ids = [box.box_id for box in jp2.box] self.assertEqual(ids, ['jP ', 'ftyp', 'jp2h', 'jp2c']) @@ -657,8 +649,7 @@ class TestSuiteWrite(fixtures.MetadataBase): infile = opj_data_file('input/nonregression/random-issue-0005.tif') data = read_image(infile) with tempfile.NamedTemporaryFile(suffix='.j2k') as tfile: - j = Jp2k(tfile.name, 'wb') - j.write(data) + j = Jp2k(tfile.name, data=data) codestream = j.get_codestream(header_only=False) From 5e8a66c38e80c1476cd5518e00a42a223f54644e Mon Sep 17 00:00:00 2001 From: John Evans Date: Wed, 19 Nov 2014 17:08:29 -0500 Subject: [PATCH 20/23] fix tab error --- glymur/test/test_callbacks.py | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/glymur/test/test_callbacks.py b/glymur/test/test_callbacks.py index d8fc28e..c29f816 100644 --- a/glymur/test/test_callbacks.py +++ b/glymur/test/test_callbacks.py @@ -45,10 +45,9 @@ class TestCallbacks(unittest.TestCase): with self.assertWarns(UserWarning): tiledata = j.read(tile=0) with tempfile.NamedTemporaryFile(suffix='.jp2') as tfile: - j = glymur.Jp2k(tfile.name, 'wb') with patch('sys.stdout', new=StringIO()) as fake_out: - j.write(tiledata, verbose=True) - actual = fake_out.getvalue().strip() + j = glymur.Jp2k(tfile.name, data=tiledata, verbose=True) + actual = fake_out.getvalue().strip() expected = '[INFO] tile number 1 / 1' self.assertEqual(actual, expected) From 3f7c08739c7c28a381e8fa4a217a0f3b60eb9c0d Mon Sep 17 00:00:00 2001 From: jevans Date: Wed, 19 Nov 2014 23:09:12 -0500 Subject: [PATCH 21/23] progress --- docs/source/how_do_i.rst | 20 ++- docs/source/roadmap.rst | 9 -- docs/source/whatsnew/0.7.rst | 18 ++- docs/source/whatsnew/0.8.rst | 10 ++ docs/source/whatsnew/index.rst | 5 +- glymur/jp2k.py | 189 +++++++++------------------- glymur/test/test_jp2k.py | 30 ++--- glymur/test/test_opj_suite_dump.py | 3 +- glymur/test/test_opj_suite_write.py | 18 +-- 9 files changed, 117 insertions(+), 185 deletions(-) create mode 100644 docs/source/whatsnew/0.8.rst diff --git a/docs/source/how_do_i.rst b/docs/source/how_do_i.rst index 5d11d67..65647fa 100644 --- a/docs/source/how_do_i.rst +++ b/docs/source/how_do_i.rst @@ -25,16 +25,14 @@ features such as quality layers. ... write images? ================= -So long as the image data can fit entirely into memory, array-style slicing may -also be used to write JPEG 2000 files. +It's pretty simple, just supply the image data as the 2nd argument to the Jp2k +constructor. >>> import glymur, numpy as np - >>> jp2 = glymur.Jp2k('zeros.jp2', mode='wb') - >>> jp2[:] = np.zeros((640, 480), dtype=np.uint8) + >>> data = np.zeros((640, 480), dtype=np.uint8) + >>> jp2 = glymur.Jp2k('zeros.jp2', data=data) -The :py:meth:`write` method exposes many more options for other JPEG 2000 -features. You should have OpenJPEG version 1.5 or more recent before writing -JPEG 2000 images. +You should have OpenJPEG version 1.5 or more recent before writing JPEG 2000 images. ... display metadata? ===================== @@ -354,15 +352,14 @@ image isn't square. :: >>> import numpy as np >>> import glymur >>> from glymur import Jp2k - >>> rgb = Jp2k(glymur.data.goodstuff()).read() + >>> rgb = Jp2k(glymur.data.goodstuff())[:] >>> lx, ly = rgb.shape[0:2] >>> X, Y = np.ogrid[0:lx, 0:ly] >>> mask = ly**2*(X - lx / 2) ** 2 + lx**2*(Y - ly / 2) ** 2 > (lx * ly / 2)**2 >>> alpha = 255 * np.ones((lx, ly, 1), dtype=np.uint8) >>> alpha[mask] = 0 >>> rgba = np.concatenate((rgb, alpha), axis=2) - >>> jp2 = Jp2k('tmp.jp2', 'wb') - >>> jp2[:] = rgba + >>> jp2 = Jp2k('tmp.jp2', data=rgba) Next we need to specify what types of channels we have. The first three channels are color channels, but we identify the fourth as @@ -465,8 +462,7 @@ http://photojournal.jpl.nasa.gov/tiff/PIA17145.tif info JPEG 2000:: >>> import skimage.io >>> image = skimage.io.imread('PIA17145.tif') >>> from glymur import Jp2k - >>> jp2 = Jp2k('PIA17145.jp2', 'wb') - >>> jp2[:] = image + >>> jp2 = Jp2k('PIA17145.jp2', data=image) Next you can extract the XMP metadata. diff --git a/docs/source/roadmap.rst b/docs/source/roadmap.rst index 503fbc4..f0d7017 100644 --- a/docs/source/roadmap.rst +++ b/docs/source/roadmap.rst @@ -1,12 +1,3 @@ -------------------------------------- -Platforms Tested (0.7.0 release only) -------------------------------------- - * Linux Mint 17 / Python 3.4.0 and 2.7.6 / OpenJPEG 2.1.0 and 1.3.0 - * MacOS 10.6.8 / MacPorts Python 3.4.1, 3.3.5,and 2.7.8 / OpenJPEG 2.1.0 - * CentOS 6.5 / Anaconda Python 3.4.1 / OpenJPEG 1.3.0 - * Fedora 20 i386 / Python 2.7.5 and 3.3.2 / OpenJPEG 1.5.1 - * Windows 7 32bit / Anaconda Python 2.7.6 and 3.4.1 / OpenJPEG 2.1.0 - ------------ Known Issues ------------ diff --git a/docs/source/whatsnew/0.7.rst b/docs/source/whatsnew/0.7.rst index 0a21d9b..3ed7715 100644 --- a/docs/source/whatsnew/0.7.rst +++ b/docs/source/whatsnew/0.7.rst @@ -2,10 +2,26 @@ Changes in glymur 0.7 ===================== +Changes in 0.7.3 +================= + + * added read support back for metadata only when the OpenJPEG library is + not installed + +Changes in 0.7.2 +================= + + * added ellipsis support in array-style slicing + +Changes in 0.7.1 +================= + + * fixed release notes regarding Python 3.4 + Changes in 0.7.0 ================= * implemented :py:meth:`__getitem__`, :py:meth:`__setitem__` support * added back windows support * box_id and longname are class attributes now instead of instance - attributes (see issue 248) + attributes diff --git a/docs/source/whatsnew/0.8.rst b/docs/source/whatsnew/0.8.rst new file mode 100644 index 0000000..f36b593 --- /dev/null +++ b/docs/source/whatsnew/0.8.rst @@ -0,0 +1,10 @@ +===================== +Changes in glymur 0.8 +===================== + +Changes in 0.8.0 +================= + + * Simplified writing images by moving data and options into the + constructor. This is backwards-incompatible with 0.7.x. + * Deprecated :py:meth:`read` method in favor of array-style slicing. diff --git a/docs/source/whatsnew/index.rst b/docs/source/whatsnew/index.rst index 2d69949..4569abd 100644 --- a/docs/source/whatsnew/index.rst +++ b/docs/source/whatsnew/index.rst @@ -8,6 +8,7 @@ These document the changes between minor (or major) versions of glymur. .. toctree:: - 0.5 - 0.6 + 0.8 0.7 + 0.6 + 0.5 diff --git a/glymur/jp2k.py b/glymur/jp2k.py index 2126d89..d7e04bb 100644 --- a/glymur/jp2k.py +++ b/glymur/jp2k.py @@ -82,10 +82,63 @@ class Jp2k(Jp2kBox): def __init__(self, filename, data=None, shape=None, **kwargs): """ + Only the filename parameter is required in order to read a JPEG 2000 + file. + Parameters ---------- filename : str or file - The path to JPEG 2000 file. + the path to JPEG 2000 file + image_data : ndarray, optional + image data to be written + shape : tuple + size of image data, only required when image_data is not provided + cbsize : tuple, optional + code block size (DY, DX) + cinema2k : int, optional + frames per second, either 24 or 48 + cinema4k : bool, optional + set to True to specify Cinema4K mode, defaults to false + colorspace : str, optional + either 'rgb' or 'gray' + cratios : iterable + compression ratios for successive layers + eph : bool, optional + if true, write SOP marker after each header packet + grid_offset : tuple, optional + offset (DY, DX) of the origin of the image in the reference grid + irreversible : bool, optional + if true, use the irreversible DWT 9-7 transform + mct : bool, optional + specifies usage of the multi component transform, if not + specified, defaults to True if the colorspace is RGB + modesw : int, optional + mode switch + 1 = BYPASS(LAZY) + 2 = RESET + 4 = RESTART(TERMALL) + 8 = VSC + 16 = ERTERM(SEGTERM) + 32 = SEGMARK(SEGSYM) + numres : int, optional + number of resolutions + prog : str, optional + progression order, one of "LRCP" "RLCP", "RPCL", "PCRL", "CPRL" + psnr : iterable, optional + different PSNR for successive layers + psizes : list, optional + list of precinct sizes, each precinct size tuple is defined in + (height x width) + sop : bool, optional + if true, write SOP marker before each packet + subsam : tuple, optional + subsampling factors (dy, dx) + tilesize : tuple, optional + numeric tuple specifying tile size in terms of (numrows, numcols), + not (X, Y) + verbose : bool, optional + print informational messages produced by the OpenJPEG library + """ Jp2kBox.__init__(self) self.filename = filename @@ -93,8 +146,11 @@ class Jp2k(Jp2kBox): self.box = [] self._codec_format = None self._colorspace = None - self._shape = None self._layer = 0 + if data is not None: + self._shape = data.shape + else: + self._shape = shape self._ignore_pclr_cmap_cdef = False self._verbose = False @@ -102,7 +158,7 @@ class Jp2k(Jp2kBox): # Parse the file for JP2/JPX contents only if we are reading it. if data is None and shape is None: self.parse() - else: + elif data is not None: self._write(data, **kwargs) @property @@ -427,134 +483,11 @@ class Jp2k(Jp2kBox): This method can only be used to create JPEG 2000 images that can fit in memory. - - Parameters - ---------- - img_array : ndarray - Image data to be written to file. - cbsize : tuple, optional - Code block size (DY, DX). - cinema2k : int, optional - frames per second, either 24 or 48 - cinema4k : bool, optional - Set to True to specify Cinema4K mode, defaults to false. - colorspace : str, optional - Either 'rgb' or 'gray'. - cratios : iterable - Compression ratios for successive layers. - eph : bool, optional - If true, write SOP marker after each header packet. - grid_offset : tuple, optional - Offset (DY, DX) of the origin of the image in the reference grid. - irreversible : bool, optional - If true, use the irreversible DWT 9-7 transform. - mct : bool, optional - Specifies usage of the multi component transform. If not - specified, defaults to True if the colorspace is RGB. - modesw : int, optional - Mode switch. - 1 = BYPASS(LAZY) - 2 = RESET - 4 = RESTART(TERMALL) - 8 = VSC - 16 = ERTERM(SEGTERM) - 32 = SEGMARK(SEGSYM) - numres : int, optional - Number of resolutions. - prog : str, optional - Progression order, one of "LRCP" "RLCP", "RPCL", "PCRL", "CPRL". - psnr : iterable, optional - Different PSNR for successive layers. - psizes : list, optional - List of precinct sizes. Each precinct size tuple is defined in - (height x width). - sop : bool, optional - If true, write SOP marker before each packet. - subsam : tuple, optional - Subsampling factors (dy, dx). - tilesize : tuple, optional - Numeric tuple specifying tile size in terms of (numrows, numcols), - not (X, Y). - verbose : bool, optional - Print informational messages produced by the OpenJPEG library. - """ if re.match("1.[0-4]", version.openjpeg_version) is not None: raise RuntimeError("You must have at least version 1.5 of OpenJPEG " "in order to write images.") - self._shape = img_array.shape - self._determine_colorspace(**kwargs) - self._populate_cparams(img_array, **kwargs) - - if opj2.OPENJP2 is not None: - self._write_openjp2(img_array, verbose=verbose) - else: - self._write_openjpeg(img_array, verbose=verbose) - - def write(self, img_array, verbose=False, **kwargs): - """Write image data to a JP2/JPX/J2k file. Intended usage of the - various parameters follows that of OpenJPEG's opj_compress utility. - - This method can only be used to create JPEG 2000 images that can fit - in memory. - - Parameters - ---------- - img_array : ndarray - Image data to be written to file. - cbsize : tuple, optional - Code block size (DY, DX). - cinema2k : int, optional - frames per second, either 24 or 48 - cinema4k : bool, optional - Set to True to specify Cinema4K mode, defaults to false. - colorspace : str, optional - Either 'rgb' or 'gray'. - cratios : iterable - Compression ratios for successive layers. - eph : bool, optional - If true, write SOP marker after each header packet. - grid_offset : tuple, optional - Offset (DY, DX) of the origin of the image in the reference grid. - irreversible : bool, optional - If true, use the irreversible DWT 9-7 transform. - mct : bool, optional - Specifies usage of the multi component transform. If not - specified, defaults to True if the colorspace is RGB. - modesw : int, optional - Mode switch. - 1 = BYPASS(LAZY) - 2 = RESET - 4 = RESTART(TERMALL) - 8 = VSC - 16 = ERTERM(SEGTERM) - 32 = SEGMARK(SEGSYM) - numres : int, optional - Number of resolutions. - prog : str, optional - Progression order, one of "LRCP" "RLCP", "RPCL", "PCRL", "CPRL". - psnr : iterable, optional - Different PSNR for successive layers. - psizes : list, optional - List of precinct sizes. Each precinct size tuple is defined in - (height x width). - sop : bool, optional - If true, write SOP marker before each packet. - subsam : tuple, optional - Subsampling factors (dy, dx). - tilesize : tuple, optional - Numeric tuple specifying tile size in terms of (numrows, numcols), - not (X, Y). - verbose : bool, optional - Print informational messages produced by the OpenJPEG library. - - """ - if re.match("1.[0-4]", version.openjpeg_version) is not None: - raise RuntimeError("You must have at least version 1.5 of OpenJPEG " - "in order to write images.") - - self._shape = img_array.shape self._determine_colorspace(**kwargs) self._populate_cparams(img_array, **kwargs) @@ -964,7 +897,7 @@ class Jp2k(Jp2kBox): # Case of jp2[:] = data, i.e. write the entire image. # # Should have a slice object where start = stop = step = None - self.write(data) + self._write(data) else: msg = "Partial write operations are currently not allowed." raise TypeError(msg) @@ -987,7 +920,7 @@ class Jp2k(Jp2kBox): if pargs is Ellipsis: # Case of jp2[...] - return self.read() + return self._read() if isinstance(pargs, slice): if pargs.start is None and pargs.stop is None and pargs.step is None: diff --git a/glymur/test/test_jp2k.py b/glymur/test/test_jp2k.py index 257688f..8eaf82a 100644 --- a/glymur/test/test_jp2k.py +++ b/glymur/test/test_jp2k.py @@ -81,13 +81,12 @@ class SliceProtocolBase(unittest.TestCase): @unittest.skipIf(os.name == "nt", fixtures.WINDOWS_TMP_FILE_MSG) class TestSliceProtocolBaseWrite(SliceProtocolBase): - @unittest.skip('requires shape implementation') def test_write_ellipsis(self): expected = self.j2k_data with tempfile.NamedTemporaryFile(suffix='.j2k') as tfile: - j = Jp2k(tfile.name, 'wb') - j[...] = self.j2k_data + j = Jp2k(tfile.name, shape=expected.shape) + j[...] = expected actual = j[:] np.testing.assert_array_equal(actual, expected) @@ -101,10 +100,9 @@ class TestSliceProtocolBaseWrite(SliceProtocolBase): np.testing.assert_array_equal(actual, expected) - @unittest.skip('requires shape implementation') def test_cannot_write_with_non_default_single_slice(self): with tempfile.NamedTemporaryFile(suffix='.j2k') as tfile: - j = Jp2k(tfile.name, 'wb') + j = Jp2k(tfile.name, shape=self.j2k_data.shape) with self.assertRaises(TypeError): j[slice(None, 0)] = self.j2k_data with self.assertRaises(TypeError): @@ -114,38 +112,33 @@ class TestSliceProtocolBaseWrite(SliceProtocolBase): with self.assertRaises(TypeError): j[slice(0, 640)] = self.j2k_data - @unittest.skip('requires shape implementation') def test_cannot_write_a_row(self): with tempfile.NamedTemporaryFile(suffix='.j2k') as tfile: - j = Jp2k(tfile.name, 'wb') + j = Jp2k(tfile.name, shape=self.j2k_data.shape) with self.assertRaises(TypeError): j[5] = self.j2k_data - @unittest.skip('requires shape implementation') def test_cannot_write_a_pixel(self): with tempfile.NamedTemporaryFile(suffix='.j2k') as tfile: - j = Jp2k(tfile.name, 'wb') + j = Jp2k(tfile.name, shape=self.j2k_data.shape) with self.assertRaises(TypeError): j[25, 35] = self.j2k_data[25, 35] - @unittest.skip('requires shape implementation') def test_cannot_write_a_column(self): with tempfile.NamedTemporaryFile(suffix='.j2k') as tfile: - j = Jp2k(tfile.name, 'wb') + j = Jp2k(tfile.name, shape=self.j2k_data.shape) with self.assertRaises(TypeError): j[:, 25, :] = self.j2k_data[:, :25, :] - @unittest.skip('requires shape implementation') def test_cannot_write_a_band(self): with tempfile.NamedTemporaryFile(suffix='.j2k') as tfile: - j = Jp2k(tfile.name, 'wb') + j = Jp2k(tfile.name, shape=self.j2k_data.shape) with self.assertRaises(TypeError): j[:, :, 0] = self.j2k_data[:, :, 0] - @unittest.skip('requires shape implementation') def test_cannot_write_a_subarray(self): with tempfile.NamedTemporaryFile(suffix='.j2k') as tfile: - j = Jp2k(tfile.name, 'wb') + j = Jp2k(tfile.name, shape=self.j2k_data.shape) with self.assertRaises(TypeError): j[:25, :45, :] = self.j2k_data[:25, :25, :] @@ -884,13 +877,13 @@ class TestJp2k_2_0(unittest.TestCase): j = Jp2k(self.jp2file) with self.assertRaises(IOError): # Start corner must be >= 0 - j.read(area=(-1, -1, 1, 1)) + j[-1:1, -1:1] with self.assertRaises(IOError): # End corner must be > 0 - j.read(area=(10, 10, 0, 0)) + j[10:0, 10:0] with self.assertRaises(IOError): # End corner must be >= start corner - j.read(area=(10, 10, 8, 8)) + j[10:8, 10:8] @unittest.skipIf(os.name == "nt", fixtures.WINDOWS_TMP_FILE_MSG) def test_unrecognized_jp2_clrspace(self): @@ -1043,7 +1036,6 @@ class TestParsing(unittest.TestCase): with self.assertWarnsRegex(UserWarning, 'Invalid profile'): jp2 = Jp2k(filename) - #@unittest.skip('trouble is a brewing...') def test_main_header(self): """Verify that the main header is not loaded when parsing turned off.""" # The hidden _main_header attribute should show up after accessing it. diff --git a/glymur/test/test_opj_suite_dump.py b/glymur/test/test_opj_suite_dump.py index 8201c9f..ee1838b 100644 --- a/glymur/test/test_opj_suite_dump.py +++ b/glymur/test/test_opj_suite_dump.py @@ -2847,8 +2847,7 @@ class TestSuiteWarns(MetadataBase): relpath = 'input/nonregression/issue188_beach_64bitsbox.jp2' jfile = opj_data_file(relpath) with self.assertWarns(UserWarning): - j = Jp2k(jfile) - d = j.read() + d = Jp2k(jfile)[:] self.assertTrue(True) def test_NR_broken4_jp2_dump(self): diff --git a/glymur/test/test_opj_suite_write.py b/glymur/test/test_opj_suite_write.py index 9d8f5b7..ecb7a7d 100644 --- a/glymur/test/test_opj_suite_write.py +++ b/glymur/test/test_opj_suite_write.py @@ -123,10 +123,9 @@ class WriteCinemaWarns(CinemaBase): infile = opj_data_file(relfile) data = skimage.io.imread(infile) with tempfile.NamedTemporaryFile(suffix='.j2k') as tfile: - j = Jp2k(tfile.name, 'wb') regex = 'OpenJPEG library warning:.*' with self.assertWarnsRegex(UserWarning, re.compile(regex)): - j.write(data, cinema4k=True) + j = Jp2k(tfile.name, data=data, cinema4k=True) codestream = j.get_codestream() self.check_cinema4k_codestream(codestream, (4096, 2160)) @@ -136,9 +135,8 @@ class WriteCinemaWarns(CinemaBase): infile = opj_data_file(relfile) data = skimage.io.imread(infile) with tempfile.NamedTemporaryFile(suffix='.j2k') as tfile: - j = Jp2k(tfile.name, 'wb') with self.assertWarnsRegex(UserWarning, 'OpenJPEG library warning'): - j.write(data, cinema2k=48) + j = Jp2k(tfile.name, data=data, cinema2k=48) codestream = j.get_codestream() self.check_cinema2k_codestream(codestream, (2048, 857)) @@ -148,9 +146,8 @@ class WriteCinemaWarns(CinemaBase): infile = opj_data_file(relfile) data = skimage.io.imread(infile) with tempfile.NamedTemporaryFile(suffix='.j2k') as tfile: - j = Jp2k(tfile.name, 'wb') with self.assertWarnsRegex(UserWarning, 'OpenJPEG library warning'): - j.write(data, cinema2k=48) + j = Jp2k(tfile.name, data=data, cinema2k=48) codestream = j.get_codestream() self.check_cinema2k_codestream(codestream, (2048, 1080)) @@ -160,9 +157,8 @@ class WriteCinemaWarns(CinemaBase): infile = opj_data_file(relfile) data = skimage.io.imread(infile) with tempfile.NamedTemporaryFile(suffix='.j2k') as tfile: - j = Jp2k(tfile.name, 'wb') with self.assertWarnsRegex(UserWarning, 'OpenJPEG library warning'): - j.write(data, cinema2k=24) + j = Jp2k(tfile.name, data=data, cinema2k=24) codestream = j.get_codestream() self.check_cinema2k_codestream(codestream, (2048, 1080)) @@ -172,11 +168,10 @@ class WriteCinemaWarns(CinemaBase): infile = opj_data_file(relfile) data = skimage.io.imread(infile) with tempfile.NamedTemporaryFile(suffix='.j2k') as tfile: - j = Jp2k(tfile.name, 'wb') with self.assertWarnsRegex(UserWarning, 'OpenJPEG library warning'): # OpenJPEG library warning: The desired maximum codestream # size has limited at least one of the desired quality layers - j.write(data, cinema2k=24) + j = Jp2k(tfile.name, data=data, cinema2k=24) codestream = j.get_codestream() self.check_cinema2k_codestream(codestream, (2048, 857)) @@ -186,12 +181,11 @@ class WriteCinemaWarns(CinemaBase): infile = opj_data_file(relfile) data = skimage.io.imread(infile) with tempfile.NamedTemporaryFile(suffix='.j2k') as tfile: - j = Jp2k(tfile.name, 'wb') regex = 'OpenJPEG library warning' with self.assertWarnsRegex(UserWarning, regex): # OpenJPEG library warning: The desired maximum codestream # size has limited at least one of the desired quality layers - j.write(data, cinema2k=48) + j = Jp2k(tfile.name, data=data, cinema2k=48) codestream = j.get_codestream() self.check_cinema2k_codestream(codestream, (1998, 1080)) From e446cb15771202899c30918ad50aff5e6cd5f88f Mon Sep 17 00:00:00 2001 From: John Evans Date: Thu, 20 Nov 2014 10:32:43 -0500 Subject: [PATCH 22/23] filter out max rlevel test on version 1.x of openjpeg, closes #301 there's nothing that can be done about it, it's behavior in the library --- glymur/test/test_jp2k.py | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/glymur/test/test_jp2k.py b/glymur/test/test_jp2k.py index 8eaf82a..99e655f 100644 --- a/glymur/test/test_jp2k.py +++ b/glymur/test/test_jp2k.py @@ -226,8 +226,16 @@ class TestSliceProtocolRead(SliceProtocolBase): expected = self.j2k_data[3:8, :,:] np.testing.assert_array_equal(actual, expected) - @unittest.skip('see issue 301') + @unittest.skipIf(re.match("0|1", glymur.version.openjpeg_version), + "Must have openjpeg 2 or higher to run") def test_region_rlevel5(self): + """ + maximim rlevel + + There seems to be a difference between version of openjpeg, as + openjp2 produces an image of size (16, 13, 3) and openjpeg produced + (17, 12, 3). + """ actual = self.j2k[5:533:32, 27:423:32] expected = self.j2k_data_r5[1:17, 1:14] np.testing.assert_array_equal(actual, expected) From e165edbe53be3fb2024d33a739fb641bfe56b01e Mon Sep 17 00:00:00 2001 From: John Evans Date: Fri, 21 Nov 2014 10:21:55 -0500 Subject: [PATCH 23/23] progress --- docs/source/how_do_i.rst | 7 ++----- glymur/test/test_jp2k.py | 21 +++++++++++++++++---- 2 files changed, 19 insertions(+), 9 deletions(-) diff --git a/docs/source/how_do_i.rst b/docs/source/how_do_i.rst index 65647fa..8a62b32 100644 --- a/docs/source/how_do_i.rst +++ b/docs/source/how_do_i.rst @@ -14,15 +14,12 @@ retrieve a full resolution and first lower-resolution image :: >>> jp2file = glymur.data.nemo() # just a path to a JPEG2000 file >>> jp2 = glymur.Jp2k(jp2file) >>> fullres = jp2[:] - >>> print(fullres.shape) + >>> fullres.shape (1456, 2592, 3) >>> thumbnail = jp2[::2, ::2] - >>> print(thumbnail.shape) + >>> thumbnail.shape (728, 1296, 3) -The :py:meth:`read` method exposes many more options for other JPEG 2000 -features such as quality layers. - ... write images? ================= It's pretty simple, just supply the image data as the 2nd argument to the Jp2k diff --git a/glymur/test/test_jp2k.py b/glymur/test/test_jp2k.py index 99e655f..b903dda 100644 --- a/glymur/test/test_jp2k.py +++ b/glymur/test/test_jp2k.py @@ -345,11 +345,24 @@ class TestJp2k(unittest.TestCase): self.assertEqual(newjp2.filename, self.j2kfile) self.assertEqual(len(newjp2.box), 0) - @unittest.skip("see issue 302") - def test_rlevel_max(self): - """Verify that rlevel=-1 gets us the lowest resolution image""" + @unittest.skipIf(WARNING_INFRASTRUCTURE_ISSUE, WARNING_INFRASTRUCTURE_MSG) + def test_rlevel_max_backwards_compatibility(self): + """ + Verify that rlevel=-1 gets us the lowest resolution image + + This is an old option only available via the read method, not via + array-style slicing. + """ j = Jp2k(self.j2kfile) - thumbnail1 = j.read(rlevel=-1) + if sys.hexversion < 0x03000000: + with warnings.catch_warnings(): + # Suppress a warning due to deprecated syntax + # Not as easy to verify the warning under python2. + warnings.simplefilter("ignore") + thumbnail1 = j.read(rlevel=-1) + else: + with self.assertWarns(DeprecationWarning): + thumbnail1 = j.read(rlevel=-1) thumbnail2 = j[::32, ::32] np.testing.assert_array_equal(thumbnail1, thumbnail2) self.assertEqual(thumbnail1.shape, (25, 15, 3))