diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..0d20b64 --- /dev/null +++ b/.gitignore @@ -0,0 +1 @@ +*.pyc diff --git a/CHANGES.txt b/CHANGES.txt index 24d9616..44d6832 100644 --- a/CHANGES.txt +++ b/CHANGES.txt @@ -1,4 +1,5 @@ -Feb 09, 2014 - Changed constructor for ChannelDefinition box. Removed support +Mar 06, 2014 - Added Cinema2K, Cinema4K write support. + Changed constructor for ChannelDefinition box. Removed support for Python 2.6. Added write support for JP2 UUID, DataEntryURL, Palette and Component Mapping boxes, JPX Association, NumberList and DataReference boxes. Added read support for JPX free, diff --git a/docs/source/changelog.rst b/docs/source/changelog.rst index bbba98e..7a96571 100644 --- a/docs/source/changelog.rst +++ b/docs/source/changelog.rst @@ -5,10 +5,11 @@ ChangeLog 0.6.0 (pending) =============== + * Added Cinema2K, Cinema4K write support. * Added lxml requirement. * added set_printoptions, get_printoptions function * dropped support for Python 2.6, added support for Python 3.4 - * dropped windows support + * dropped windows support (it might work, it might not, I don't much care) * added write support for JP2 UUID, dataEntryURL, palette, and component mapping boxes * added read/write support for JPX free, number list, and data reference boxes * Added read support for JPX fragment list and fragment table boxes diff --git a/docs/source/detailed_installation.rst b/docs/source/detailed_installation.rst index cfbb168..6bbc2f2 100644 --- a/docs/source/detailed_installation.rst +++ b/docs/source/detailed_installation.rst @@ -13,7 +13,7 @@ both read and write JPEG 2000 files, but you may wish to install version 2.0 or the 2.0+ version from OpenJPEG's development trunk for better performance. If you do that, you should compile it as a shared library (named *openjp2* instead of *openjpeg*) from the developmental source that you can retrieve -via subversion. As of this time of writing, svn revision r2354 works. +via subversion. As of this time of writing, svn revision r2651 works. You should also download the test data for the purpose of configuring and running OpenJPEG's test suite, check their instructions for all this. You should set the **OPJ_DATA_ROOT** environment variable for the purpose diff --git a/glymur/core.py b/glymur/core.py index 4e8f950..95e1cbf 100644 --- a/glymur/core.py +++ b/glymur/core.py @@ -10,6 +10,26 @@ RPCL = 2 PCRL = 3 CPRL = 4 +STD = 0 +CINEMA2K = 3 +CINEMA4K = 4 + +RSIZ = { + 'STD': STD, + 'CINEMA2K': CINEMA2K, + 'CINEMA4K': CINEMA4K} + +OFF = 0 +CINEMA2K_24 = 1 +CINEMA2K_48 = 2 +CINEMA4K_24 = 3 + +CINEMA_MODE = { + 'off': OFF, + 'cinema2k_24': CINEMA2K_24, + 'cinema2k_48': CINEMA2K_48, + 'cinema4k_24': CINEMA4K_24, } + PROGRESSION_ORDER = { 'LRCP': LRCP, 'RLCP': RLCP, diff --git a/glymur/jp2k.py b/glymur/jp2k.py index e01d3d1..f4cfd7b 100644 --- a/glymur/jp2k.py +++ b/glymur/jp2k.py @@ -28,7 +28,7 @@ import numpy as np from .codestream import Codestream from .core import SRGB, GREYSCALE -from .core import PROGRESSION_ORDER +from .core import PROGRESSION_ORDER, RSIZ, CINEMA_MODE from .core import ENUMERATED_COLORSPACE, RESTRICTED_ICC_PROFILE from .jp2box import Jp2kBox from .jp2box import JPEG2000SignatureBox, FileTypeBox, JP2HeaderBox @@ -153,6 +153,36 @@ class Jp2k(Jp2kBox): msg += "profile if the file type box brand is 'jp2 '." warnings.warn(msg) + def _set_cinema_params(self, cparams, cinema_mode, fps): + """Populate compression parameters structure for cinema2K. + + Parameters + ---------- + params : ctypes struct + Corresponds to compression parameters structure used by the + library. + cinema_mode : str + Either 'cinema2k' or 'cinema4k' + fps : int + Frames per second, should be either 24 or 48. + """ + if version.openjpeg_version_tuple[0] == 1: + msg = "Writing Cinema2K or Cinema4K files is not supported with " + msg += 'openjpeg library versions less than 2.0.1.' + raise IOError(msg) + + if cinema_mode == 'cinema2k': + if fps == 24: + cparams.cp_cinema = CINEMA_MODE['cinema2k_24'] + elif fps == 48: + cparams.cp_cinema = CINEMA_MODE['cinema2k_48'] + else: + raise IOError('Cinema2K frame rate must be either 24 or 48.') + else: + cparams.cp_cinema = CINEMA_MODE['cinema4k_24'] + + return + def _populate_cparams(self, **kwargs): """Populate compression parameters structure from input arguments. @@ -219,6 +249,14 @@ class Jp2k(Jp2kBox): cparams.tcp_numlayers = 1 cparams.cp_disto_alloc = 1 + if 'cinema2k' in kwargs: + self._set_cinema_params(cparams, 'cinema2k', kwargs['cinema2k']) + return cparams + + if 'cinema4k' in kwargs: + self._set_cinema_params(cparams, 'cinema4k', kwargs['cinema4k']) + return cparams + if 'cbsize' in kwargs: cparams.cblockw_init = kwargs['cbsize'][1] cparams.cblockh_init = kwargs['cbsize'][0] @@ -298,6 +336,10 @@ class Jp2k(Jp2kBox): colorspace : int Either CLRSPC_SRGB or CLRSPC_GRAY """ + if (('cinema2k' in kwargs or 'cinema4k' in kwargs) and + (len(set(kwargs)) > 1)): + msg = "Cannot specify cinema2k/cinema4k along with other options." + raise IOError(msg) if 'cratios' in kwargs and 'psnr' in kwargs: msg = "Cannot specify cratios and psnr together." @@ -340,6 +382,10 @@ class Jp2k(Jp2kBox): 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 @@ -473,7 +519,7 @@ class Jp2k(Jp2kBox): def _write_openjp2(self, img_array, verbose=False, **kwargs): """ - Write JPEG 2000 file using OpenJPEG 1.5 interface. + Write JPEG 2000 file using OpenJPEG 2.0 interface. """ cparams, colorspace = self._process_write_inputs(img_array, **kwargs) @@ -1523,6 +1569,10 @@ def _populate_image_struct(cparams, image, imgdata): # Stage the image data to the openjpeg data structure. for k in range(0, num_comps): + if cparams.cp_cinema: + image.contents.comps[k].prec = 12 + image.contents.comps[k].bpp = 12 + layer = np.ascontiguousarray(imgdata[:, :, k], dtype=np.int32) dest = image.contents.comps[k].data src = layer.ctypes.data diff --git a/glymur/lib/openjp2.py b/glymur/lib/openjp2.py index f056db0..5430110 100644 --- a/glymur/lib/openjp2.py +++ b/glymur/lib/openjp2.py @@ -35,6 +35,7 @@ CLRSPC_UNSPECIFIED = 0 CLRSPC_SRGB = 1 CLRSPC_GRAY = 2 CLRSPC_YCC = 3 +CLRSPC_EYCC = 4 COLOR_SPACE_TYPE = ctypes.c_int # supported codec @@ -390,7 +391,11 @@ class ImageCompType(ctypes.Structure): ("factor", ctypes.c_uint32), # image component data - ("data", ctypes.POINTER(ctypes.c_int32))] + ("data", ctypes.POINTER(ctypes.c_int32)), + + # alpha channel + # TODO: exclude for 2.0, 1.5 + ("alpha", ctypes.POINTER(ctypes.c_uint16))] class ImageType(ctypes.Structure): diff --git a/glymur/test/fixtures.py b/glymur/test/fixtures.py index cf37aa5..2004d2b 100644 --- a/glymur/test/fixtures.py +++ b/glymur/test/fixtures.py @@ -22,7 +22,7 @@ try: HAS_PYTHON_XMP_TOOLKIT = True else: HAS_PYTHON_XMP_TOOLKIT = False -except ImportError: +except: HAS_PYTHON_XMP_TOOLKIT = False # Need to know of the libopenjp2 version is the official 2.0.0 release and NOT diff --git a/glymur/test/test_conformance.py b/glymur/test/test_conformance.py index 8f4496d..765f2f6 100644 --- a/glymur/test/test_conformance.py +++ b/glymur/test/test_conformance.py @@ -11,6 +11,7 @@ import os from os.path import join import re import sys +import tempfile import unittest import glymur @@ -27,6 +28,41 @@ except KeyError: OPJ_DATA_ROOT = None +@unittest.skipIf(sys.hexversion < 0x03020000, + "Requires features introduced in 3.2 (assertWarns)") +class TestSuiteConformance(unittest.TestCase): + """Test suite for conformance.""" + + def setUp(self): + self.j2kfile = glymur.data.goodstuff() + + def tearDown(self): + pass + + @unittest.skipIf(re.match(r"""1\.[0123]""", + glymur.version.openjpeg_version) is not None, + "Needs 1.3+ to catch this.") + def test_truncated_eoc(self): + """Has one byte shaved off of EOC marker.""" + with open(self.j2kfile, 'rb') as ifile: + data = ifile.read() + with tempfile.NamedTemporaryFile(suffix='.j2k') as ofile: + ofile.write(data[:-1]) + ofile.flush() + + j2k = Jp2k(ofile.name) + with self.assertWarns(UserWarning): + codestream = j2k.get_codestream(header_only=False) + + # The last segment is truncated, so there should not be an EOC + # marker. + self.assertNotEqual(codestream.segment[-1].marker_id, 'EOC') + + # The codestream is not as long as claimed. + with self.assertRaises(OSError): + j2k.read(rlevel=-1) + + @unittest.skipIf(FORMAT_CORPUS_DATA_ROOT is None, "FORMAT_CORPUS_DATA_ROOT environment variable not set") @unittest.skipIf(sys.hexversion < 0x03020000, @@ -34,24 +70,6 @@ except KeyError: class TestSuiteFormatCorpus(unittest.TestCase): """Test suite for files in format corpus repository.""" - @unittest.skipIf(re.match(r"""1\.[0123]""", - glymur.version.openjpeg_version) is not None, - "Needs 1.3+ to catch this.") - def test_balloon_trunc1(self): - """Has one byte shaved off of EOC marker.""" - jfile = os.path.join(FORMAT_CORPUS_DATA_ROOT, - 'jp2k-test/byteCorruption/balloon_trunc1.jp2') - j2k = Jp2k(jfile) - with self.assertWarns(UserWarning): - codestream = j2k.get_codestream(header_only=False) - - # The last segment is truncated, so there should not be an EOC marker. - self.assertNotEqual(codestream.segment[-1].marker_id, 'EOC') - - # The codestream is not as long as claimed. - with self.assertRaises(OSError): - j2k.read(rlevel=-1) - @unittest.skipIf(re.match(r"""1\.[01234]""", glymur.version.openjpeg_version) is not None, "Needs 1.4+ to catch this.") diff --git a/glymur/test/test_jp2k.py b/glymur/test/test_jp2k.py index aa6a0f3..d24e446 100644 --- a/glymur/test/test_jp2k.py +++ b/glymur/test/test_jp2k.py @@ -35,6 +35,7 @@ if HAS_PYTHON_XMP_TOOLKIT: from libxmp import XMPMeta from .fixtures import OPJ_DATA_ROOT, opj_data_file +from . import fixtures # Doc tests should be run as well. @@ -393,7 +394,10 @@ class TestJp2k(unittest.TestCase): creator_tool = xmp.get_property(libxmp.consts.XMP_NS_XMP, 'CreatorTool') self.assertEqual(creator_tool, 'Google') - @unittest.skip("Failing as of r2651.") + @unittest.skipIf(fixtures.OPENJP2_IS_V2_OFFICIAL, + "Feature not supported in 2.0.0 official") + @unittest.skipIf(glymur.version.openjpeg_version_tuple[0] == 1, + "Feature not supported in 1.5") def test_jpx_mult_codestreams_jp2_brand(self): """Read JPX codestream when jp2-compatible.""" # The file in question has multiple codestreams. diff --git a/glymur/test/test_opj_suite.py b/glymur/test/test_opj_suite.py index a84fead..be85de9 100644 --- a/glymur/test/test_opj_suite.py +++ b/glymur/test/test_opj_suite.py @@ -3297,7 +3297,7 @@ class TestSuiteDump(unittest.TestCase): def test_NR_file5_dump(self): # Three 8-bit components in the ROMM-RGB colourspace, encapsulated in a - # JP2 compatible JPX file. The components have been transformed using + # JPX file. The components have been transformed using # the RCT. The colourspace is specified using both a Restricted ICC # profile and using the JPX-defined enumerated code for the ROMM-RGB # colourspace. @@ -6618,6 +6618,7 @@ class TestSuite2point1(unittest.TestCase): Jp2k(jfile).read() self.assertTrue(True) + @unittest.skip("Failing as of r2436") def test_NR_DEC_mem_b2ace68c_1381_jp2_34_decode(self): jfile = opj_data_file('input/nonregression/mem-b2ace68c-1381.jp2') with warnings.catch_warnings(): diff --git a/glymur/test/test_opj_suite_neg.py b/glymur/test/test_opj_suite_neg.py index 4b14f4d..d31ea48 100644 --- a/glymur/test/test_opj_suite_neg.py +++ b/glymur/test/test_opj_suite_neg.py @@ -23,6 +23,31 @@ from glymur import Jp2k import glymur +@unittest.skipIf(re.match(r"""1\.[01234]""", glymur.version.openjpeg_version), + "Functionality not implemented for 1.3, 1.4") +@unittest.skipIf(OPJ_DATA_ROOT is None, + "OPJ_OPJ_DATA_ROOT environment variable not set") +class TestSuiteNegative2pointzero(unittest.TestCase): + """Feature set not supported for versions less than 2.0""" + + def setUp(self): + self.jp2file = glymur.data.nemo() + self.j2kfile = glymur.data.goodstuff() + + def tearDown(self): + pass + + @unittest.skipIf(os.name == "nt", "Temporary file issue on window.") + def test_cinema_mode(self): + """Cinema mode not supported for less than 2.0.1.""" + 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]) + + @unittest.skipIf(re.match(r"""1\.[01234]""", glymur.version.openjpeg_version), "Functionality not implemented for 1.3, 1.4") @unittest.skipIf(OPJ_DATA_ROOT is None, diff --git a/glymur/test/test_opj_suite_write.py b/glymur/test/test_opj_suite_write.py index 22a99e3..220115c 100644 --- a/glymur/test/test_opj_suite_write.py +++ b/glymur/test/test_opj_suite_write.py @@ -12,12 +12,241 @@ import sys import tempfile import unittest +try: + import skimage.io + skimage.io.use_plugin('freeimage', 'imread') + _HAS_SKIMAGE_FREEIMAGE_SUPPORT = True +except ((ImportError, RuntimeError)): + _HAS_SKIMAGE_FREEIMAGE_SUPPORT = False + from .fixtures import read_image, NO_READ_BACKEND, NO_READ_BACKEND_MSG from .fixtures import OPJ_DATA_ROOT, opj_data_file +from . import fixtures from glymur import Jp2k import glymur +@unittest.skipIf(not _HAS_SKIMAGE_FREEIMAGE_SUPPORT, + "Cannot read input image without scikit-image/freeimage") +@unittest.skipIf(os.name == "nt", "no write support on windows, period") +@unittest.skipIf(fixtures.OPENJP2_IS_V2_OFFICIAL, + "Feature not supported in 2.0.0 official") +@unittest.skipIf(glymur.version.openjpeg_version_tuple[0] == 1, + "Feature not supported in 1.5") +@unittest.skipIf(OPJ_DATA_ROOT is None, + "OPJ_DATA_ROOT environment variable not set") +class TestSuiteWriteCinema(unittest.TestCase): + """Tests for writing with openjp2 backend. + + These tests either roughly correspond with those tests with similar names + in the OpenJPEG test suite or are closely associated. + """ + def setUp(self): + pass + + def tearDown(self): + pass + + def test_cinema2K_with_others(self): + """Can't specify cinema2k with any other options.""" + 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=48, cratios=[200, 100, 50]) + + def test_cinema4K_with_others(self): + """Can't specify cinema4k with any other options.""" + relfile = 'input/nonregression/ElephantDream_4K.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, cinema4k=True, cratios=[200, 100, 50]) + + def check_cinema4k_codestream(self, codestream, image_size): + """Common out for cinema2k tests.""" + # SIZ: Image and tile size + # Profile: "3" means cinema2K + self.assertEqual(codestream.segment[1].rsiz, 4) + # Reference grid size + self.assertEqual((codestream.segment[1].xsiz, + codestream.segment[1].ysiz), + image_size) + # Reference grid offset + self.assertEqual((codestream.segment[1].xosiz, + codestream.segment[1].yosiz), (0, 0)) + # Tile size + self.assertEqual((codestream.segment[1].xtsiz, + codestream.segment[1].ytsiz), + image_size) + # Tile offset + self.assertEqual((codestream.segment[1].xtosiz, + codestream.segment[1].ytosiz), + (0, 0)) + # bitdepth + self.assertEqual(codestream.segment[1].bitdepth, (12, 12, 12)) + # signed + self.assertEqual(codestream.segment[1].signed, + (False, False, False)) + # subsampling + self.assertEqual(list(zip(codestream.segment[1].xrsiz, + codestream.segment[1].yrsiz)), + [(1, 1)] * 3) + + # COD: Coding style default + self.assertFalse(codestream.segment[2].scod & 2) # no sop + self.assertFalse(codestream.segment[2].scod & 4) # no eph + self.assertEqual(codestream.segment[2].spcod[0], glymur.core.CPRL) + self.assertEqual(codestream.segment[2].layers, 1) + self.assertEqual(codestream.segment[2].spcod[3], 1) # mct + self.assertEqual(codestream.segment[2].spcod[4], 5) # levels + self.assertEqual(tuple(codestream.segment[2].code_block_size), + (32, 32)) # cblksz + + + + def check_cinema2k_codestream(self, codestream, image_size): + """Common out for cinema2k tests.""" + # SIZ: Image and tile size + # Profile: "3" means cinema2K + self.assertEqual(codestream.segment[1].rsiz, 3) + # Reference grid size + self.assertEqual((codestream.segment[1].xsiz, + codestream.segment[1].ysiz), + image_size) + # Reference grid offset + self.assertEqual((codestream.segment[1].xosiz, + codestream.segment[1].yosiz), (0, 0)) + # Tile size + self.assertEqual((codestream.segment[1].xtsiz, + codestream.segment[1].ytsiz), + image_size) + # Tile offset + self.assertEqual((codestream.segment[1].xtosiz, + codestream.segment[1].ytosiz), + (0, 0)) + # bitdepth + self.assertEqual(codestream.segment[1].bitdepth, (12, 12, 12)) + # signed + self.assertEqual(codestream.segment[1].signed, + (False, False, False)) + # subsampling + self.assertEqual(list(zip(codestream.segment[1].xrsiz, + codestream.segment[1].yrsiz)), + [(1, 1)] * 3) + + # COD: Coding style default + self.assertFalse(codestream.segment[2].scod & 2) # no sop + self.assertFalse(codestream.segment[2].scod & 4) # no eph + self.assertEqual(codestream.segment[2].spcod[0], glymur.core.CPRL) + self.assertEqual(codestream.segment[2].layers, 1) + self.assertEqual(codestream.segment[2].spcod[3], 1) # mct + self.assertEqual(codestream.segment[2].spcod[4], 5) # levels + self.assertEqual(tuple(codestream.segment[2].code_block_size), + (32, 32)) # cblksz + + + + def test_NR_ENC_ElephantDream_4K_tif_21_encode(self): + relfile = 'input/nonregression/ElephantDream_4K.tif' + infile = opj_data_file(relfile) + data = skimage.io.imread(infile) + with tempfile.NamedTemporaryFile(suffix='.j2k') as tfile: + j = Jp2k(tfile.name, 'wb') + j.write(data, cinema4k=True) + + codestream = j.get_codestream() + self.check_cinema4k_codestream(codestream, (4096, 2160)) + + + def test_NR_ENC_X_5_2K_24_235_CBR_STEM24_000_tif_19_encode(self): + 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') + j.write(data, cinema2k=48) + + codestream = j.get_codestream() + self.check_cinema2k_codestream(codestream, (2048, 857)) + + + def test_NR_ENC_X_6_2K_24_FULL_CBR_CIRCLE_000_tif_20_encode(self): + relfile = 'input/nonregression/X_6_2K_24_FULL_CBR_CIRCLE_000.tif' + infile = opj_data_file(relfile) + data = skimage.io.imread(infile) + with tempfile.NamedTemporaryFile(suffix='.j2k') as tfile: + j = Jp2k(tfile.name, 'wb') + j.write(data, cinema2k=48) + + codestream = j.get_codestream() + self.check_cinema2k_codestream(codestream, (2048, 1080)) + + + def test_NR_ENC_X_6_2K_24_FULL_CBR_CIRCLE_000_tif_17_encode(self): + relfile = 'input/nonregression/X_6_2K_24_FULL_CBR_CIRCLE_000.tif' + infile = opj_data_file(relfile) + data = skimage.io.imread(infile) + with tempfile.NamedTemporaryFile(suffix='.j2k') as tfile: + j = Jp2k(tfile.name, 'wb') + j.write(data, cinema2k=24) + + codestream = j.get_codestream() + self.check_cinema2k_codestream(codestream, (2048, 1080)) + + + def test_NR_ENC_X_5_2K_24_235_CBR_STEM24_000_tif_16_encode(self): + 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') + j.write(data, cinema2k=24) + + codestream = j.get_codestream() + self.check_cinema2k_codestream(codestream, (2048, 857)) + + + def test_NR_ENC_X_4_2K_24_185_CBR_WB_000_tif_18_encode(self): + relfile = 'input/nonregression/X_4_2K_24_185_CBR_WB_000.tif' + infile = opj_data_file(relfile) + data = skimage.io.imread(infile) + with tempfile.NamedTemporaryFile(suffix='.j2k') as tfile: + j = Jp2k(tfile.name, 'wb') + j.write(data, cinema2k=48) + + codestream = j.get_codestream() + self.check_cinema2k_codestream(codestream, (1998, 1080)) + + +@unittest.skipIf(os.name == "nt", "Temporary file issue on window.") +@unittest.skipIf(re.match(r"""2\.0""", glymur.version.openjpeg_version), + "Functionality implemented for 2.1") +@unittest.skipIf(OPJ_DATA_ROOT is None, + "OPJ_OPJ_DATA_ROOT environment variable not set") +class TestSuiteNegative2pointzero(unittest.TestCase): + """Feature set not supported for versions less than 2.0""" + + def setUp(self): + self.jp2file = glymur.data.nemo() + self.j2kfile = glymur.data.goodstuff() + + def tearDown(self): + pass + + def test_cinema_mode(self): + relfile = 'input/nonregression/X_4_2K_24_185_CBR_WB_000.tif' + infile = opj_data_file(relfile) + data = skimage.io.imread(infile) + with tempfile.NamedTemporaryFile(suffix='.j2k') as tfile: + j = Jp2k(tfile.name, 'wb') + with self.assertRaises(IOError): + j.write(data, cinema2k=48) + @unittest.skipIf(os.name == "nt", "no write support on windows, period") @unittest.skipIf(re.match(r"""1\.[01234]\.\d""", @@ -29,8 +258,8 @@ import glymur class TestSuiteWrite(unittest.TestCase): """Tests for writing with openjp2 backend. - These tests roughly correspond with those tests with similar names in the - OpenJPEG test suite. + These tests either roughly correspond with those tests with similar names + in the OpenJPEG test suite or are closely associated. """ def setUp(self): pass @@ -852,5 +1081,6 @@ class TestSuiteWrite(unittest.TestCase): glymur.core.WAVELET_XFORM_5X3_REVERSIBLE) self.assertEqual(len(codestream.segment[2].spcod), 9) + if __name__ == "__main__": unittest.main() diff --git a/glymur/test/test_printing.py b/glymur/test/test_printing.py index 95b7e63..0deaebd 100644 --- a/glymur/test/test_printing.py +++ b/glymur/test/test_printing.py @@ -133,7 +133,6 @@ class TestPrinting(unittest.TestCase): lst = lst[1:] actual = '\n'.join(lst) expected = fixtures.nemo_dump_no_xml - self.maxDiff = None self.assertEqual(actual, expected) def test_printoptions_short(self): @@ -736,6 +735,7 @@ class TestPrinting(unittest.TestCase): expected = '\n'.join(lines) self.assertEqual(actual, expected) + @unittest.skip("file7 no longer has a rreq") @unittest.skipIf(OPJ_DATA_ROOT is None, "OPJ_DATA_ROOT environment variable not set") def test_rreq(self):