diff --git a/CHANGES.txt b/CHANGES.txt index 410f243..8461f8e 100644 --- a/CHANGES.txt +++ b/CHANGES.txt @@ -1,3 +1,10 @@ +Jul 25, 2013 - v0.2.7 Warns but no longer errors out when neither library is + found (issue89). + +Jul 24, 2013 - v0.2.6 No longer warning when configuration file not found. + Added read support for jpch, jplh boxes. Added testing of files in + format-corpus repository. + Jul 23, 2013 - v0.2.5 Fixed inconsistency in XML handling, now all instances are always ElementTree objects (issue82). diff --git a/docs/source/conf.py b/docs/source/conf.py index d9f833e..b501034 100644 --- a/docs/source/conf.py +++ b/docs/source/conf.py @@ -76,9 +76,9 @@ copyright = u'2013, John Evans' # built documents. # # The short X.Y version. -version = '0.1' +version = '0.2' # The full version, including alpha/beta/rc tags. -release = '0.2.5' +release = '0.2.7' # The language for content autogenerated by Sphinx. Refer to documentation # for a list of supported languages. diff --git a/glymur/codestream.py b/glymur/codestream.py index c4d8b4b..637f40e 100644 --- a/glymur/codestream.py +++ b/glymur/codestream.py @@ -140,7 +140,6 @@ class Codestream(object): fptr.seek(self._tile_offset[-1] + self._tile_length[-1]) - def _process_marker_segment(self, fptr, marker_id): """Process and return a segment from the codestream. """ @@ -207,7 +206,8 @@ class Codestream(object): segment = _parse_sot_segment(fptr) self._tile_offset.append(segment.offset) if segment.psot == 0: - tile_part_length = self.offset + self.length - segment.offset - 2 + tile_part_length = (self.offset + self.length - + segment.offset - 2) else: tile_part_length = segment.psot self._tile_length.append(tile_part_length) diff --git a/glymur/jp2box.py b/glymur/jp2box.py index b5637f6..4949752 100644 --- a/glymur/jp2box.py +++ b/glymur/jp2box.py @@ -571,7 +571,7 @@ class CodestreamHeaderBox(Jp2kBox): """ box = CodestreamHeaderBox(length=length, offset=offset) - # The codestream header box is a superbox, so go ahead and parse its + # The codestream header box is a superbox, so go ahead and parse its # child boxes. box.box = box.parse_superbox(fptr) diff --git a/glymur/jp2k.py b/glymur/jp2k.py index 319bf46..2d9b220 100644 --- a/glymur/jp2k.py +++ b/glymur/jp2k.py @@ -170,7 +170,7 @@ class Jp2k(Jp2kBox): if ftyp.brand == 'jp2 ': jp2h = [box for box in self.box if box.box_id == 'jp2h'][0] colrs = [box for box in jp2h.box if box.box_id == 'colr'] - for colr in colrs: + for colr in colrs: if colr.method not in (ENUMERATED_COLORSPACE, RESTRICTED_ICC_PROFILE): msg = "Color Specification box method must specify either " @@ -178,7 +178,6 @@ class Jp2k(Jp2kBox): msg += "profile if the file type box brand is 'jp2 '." warnings.warn(msg) - # pylint: disable-msg=W0221 def write(self, img_array, cratios=None, eph=False, psnr=None, numres=None, cbsize=None, psizes=None, grid_offset=None, sop=False, diff --git a/glymur/lib/__init__.py b/glymur/lib/__init__.py index ebd4fa7..ba5915d 100644 --- a/glymur/lib/__init__.py +++ b/glymur/lib/__init__.py @@ -1,4 +1,3 @@ """This package organizes individual libraries employed by glymur.""" from . import openjp2 as _openjp2 from . import openjpeg as _openjpeg -#from . import test diff --git a/glymur/lib/config.py b/glymur/lib/config.py index 7e9e2a9..7fcaeb6 100644 --- a/glymur/lib/config.py +++ b/glymur/lib/config.py @@ -35,9 +35,6 @@ def glymurrc_fname(): fname = os.path.join(confdir, 'glymurrc') if os.path.exists(fname): return fname - else: - msg = "Configuration directory '{0}' does not exist.".format(fname) - warnings.warn(msg) # didn't find a configuration file. return None @@ -61,6 +58,9 @@ def load_openjpeg(libopenjpeg_path): 'bin', 'openjpeg.dll') if os.path.exists(path): libopenjpeg_path = path + else: + # No sense trying further on Linux + return None try: if os.name == "nt": @@ -127,6 +127,10 @@ def glymur_config(): libs = read_config_file() libopenjp2_handle = load_openjp2(libs['openjp2']) libopenjpeg_handle = load_openjpeg(libs['openjpeg']) + if libopenjp2_handle is None and libopenjpeg_handle is None: + msg = "Neither the openjp2 nor the openjpeg library could be loaded. " + msg += "Operating in severely degraded mode." + warnings.warn(msg, UserWarning) return libopenjp2_handle, libopenjpeg_handle diff --git a/glymur/lib/openjpeg.py b/glymur/lib/openjpeg.py index 3dd0592..56bdfd3 100644 --- a/glymur/lib/openjpeg.py +++ b/glymur/lib/openjpeg.py @@ -22,8 +22,15 @@ def version(): return library_version # Need to get the minor version, make sure we are at least at 1.4.x -#import pdb; pdb.set_trace() -_MINOR = version().split('.')[1] +if OPENJPEG is not None: + _MINOR = version().split('.')[1] +else: + # Does not really matter. But version should not be called if there is no + # OpenJPEG library found. + _MINOR = 0 + # Redefine version so that we can use it. + def version(): + return '0.0.0' class EventMgrType(ctypes.Structure): diff --git a/glymur/test/test_config.py b/glymur/test/test_config.py index 09370e0..7833865 100644 --- a/glymur/test/test_config.py +++ b/glymur/test/test_config.py @@ -81,40 +81,5 @@ class TestSuite(unittest.TestCase): with self.assertWarns(UserWarning) as cw: imp.reload(glymur.lib.openjp2) - def test_missing_config_file_via_environ(self): - # Verify that we error out properly if the configuration file - # specified via environment variable is not found. - with tempfile.TemporaryDirectory() as tdir: - with patch.dict('os.environ', {'XDG_CONFIG_HOME': tdir}): - # Misconfigured new configuration file should - # be rejected. - with self.assertWarns(UserWarning) as cw: - imp.reload(glymur.lib.openjp2) - - def test_home_dir_missing_config_dir(self): - # Verify no exception is raised if $HOME is missing .config directory. - with tempfile.TemporaryDirectory() as tdir: - with patch.dict('os.environ', {'HOME': tdir}): - # Misconfigured new configuration file should - # be rejected. - with self.assertWarns(UserWarning) as cw: - imp.reload(glymur.lib.openjp2) - - def test_home_dir_missing_glymur_rc_dir(self): - # Should warn but not error if $HOME/.config but no glymurrc dir. - with tempfile.TemporaryDirectory() as tdir: - # We need the subdirectory to be specifically named as ".config" - # in order for this test to work. A specifically-named temporary - # directory does not seem to be possible, so try to symlink it. - # Supposedly the symlink gets cleaned up with tdir gets cleaned up. - with tempfile.TemporaryDirectory(suffix=".config", dir=tdir) \ - as tdir_config: - os.symlink(tdir_config, os.path.join(tdir, '.config')) - with patch.dict('os.environ', {'HOME': tdir}): - # Misconfigured new configuration file should - # be rejected. - with self.assertWarns(UserWarning) as cw: - imp.reload(glymur.lib.openjp2) - if __name__ == "__main__": unittest.main() diff --git a/glymur/test/test_conformance.py b/glymur/test/test_conformance.py index 9f40b3e..9e1ad1a 100644 --- a/glymur/test/test_conformance.py +++ b/glymur/test/test_conformance.py @@ -46,7 +46,7 @@ class TestSuiteFormatCorpus(unittest.TestCase): j2k = Jp2k(jfile) with self.assertWarns(UserWarning): c = j2k.get_codestream(header_only=False) - + # The last segment is truncated, so there should not be an EOC marker. self.assertNotEqual(c.segment[-1].marker_id, 'EOC') @@ -61,7 +61,7 @@ class TestSuiteFormatCorpus(unittest.TestCase): j2k = Jp2k(jfile) with self.assertWarns(UserWarning): c = j2k.get_codestream(header_only=False) - + # The last segment is truncated, so there should not be an EOC marker. self.assertNotEqual(c.segment[-1].marker_id, 'EOC') @@ -76,7 +76,7 @@ class TestSuiteFormatCorpus(unittest.TestCase): j2k = Jp2k(jfile) with self.assertWarns(UserWarning): c = j2k.get_codestream(header_only=False) - + # The last segment is truncated, so there should not be an EOC marker. self.assertNotEqual(c.segment[-1].marker_id, 'EOC') @@ -91,7 +91,7 @@ class TestSuiteFormatCorpus(unittest.TestCase): 'balloon_eciRGBv2_ps_adobeplugin.jpf') with self.assertWarns(UserWarning): j2k = Jp2k(jfile) - + def test_jp2_brand_vs_any_icc_profile_multiple_colr(self): # Has colr box, one that conforms, one that does not. @@ -104,7 +104,7 @@ class TestSuiteFormatCorpus(unittest.TestCase): jfile = os.path.join(*lst) with self.assertWarns(UserWarning): j2k = Jp2k(jfile) - + @unittest.skipIf(opj_data_root is None, "OPJ_DATA_ROOT environment variable not set") @@ -124,6 +124,6 @@ class TestSuiteOpj(unittest.TestCase): 'input/nonregression/text_GBR.jp2') with self.assertWarns(UserWarning): j2k = Jp2k(filename) - + if __name__ == "__main__": unittest.main() diff --git a/glymur/test/test_jp2box.py b/glymur/test/test_jp2box.py index 8fdd3c3..a2aa9d6 100644 --- a/glymur/test/test_jp2box.py +++ b/glymur/test/test_jp2box.py @@ -472,7 +472,7 @@ class TestColourSpecificationBox(unittest.TestCase): @unittest.skipIf(glymur.lib.openjp2.OPENJP2 is None, "Missing openjp2 library.") -class TestJp2Boxes(unittest.TestCase): +class TestWrap(unittest.TestCase): def setUp(self): self.j2kfile = glymur.data.goodstuff() @@ -481,39 +481,6 @@ class TestJp2Boxes(unittest.TestCase): def tearDown(self): pass - def test_default_JPEG2000SignatureBox(self): - # Should be able to instantiate a JPEG2000SignatureBox - b = glymur.jp2box.JPEG2000SignatureBox() - self.assertEqual(b.signature, (13, 10, 135, 10)) - - def test_default_FileTypeBox(self): - # Should be able to instantiate a FileTypeBox - b = glymur.jp2box.FileTypeBox() - self.assertEqual(b.brand, 'jp2 ') - self.assertEqual(b.minor_version, 0) - self.assertEqual(b.compatibility_list, ['jp2 ']) - - def test_default_ImageHeaderBox(self): - # Should be able to instantiate an image header box. - b = glymur.jp2box.ImageHeaderBox(height=512, width=256, - num_components=3) - self.assertEqual(b.height, 512) - self.assertEqual(b.width, 256) - self.assertEqual(b.num_components, 3) - self.assertEqual(b.bits_per_component, 8) - self.assertFalse(b.signed) - self.assertFalse(b.colorspace_unknown) - - def test_default_JP2HeaderBox(self): - b1 = JP2HeaderBox() - b1.box = [ImageHeaderBox(height=512, width=256), - ColourSpecificationBox(colorspace=glymur.core.GREYSCALE)] - - def test_default_ContiguousCodestreamBox(self): - b = ContiguousCodestreamBox() - self.assertEqual(b.box_id, 'jp2c') - self.assertIsNone(b.main_header) - def verify_wrapped_raw(self, jp2file): # Shared method by at least two tests. jp2 = Jp2k(jp2file) @@ -679,6 +646,42 @@ class TestJp2Boxes(unittest.TestCase): j2k.wrap(tfile.name, boxes=boxes) +class TestJp2Boxes(unittest.TestCase): + + def test_default_JPEG2000SignatureBox(self): + # Should be able to instantiate a JPEG2000SignatureBox + b = glymur.jp2box.JPEG2000SignatureBox() + self.assertEqual(b.signature, (13, 10, 135, 10)) + + def test_default_FileTypeBox(self): + # Should be able to instantiate a FileTypeBox + b = glymur.jp2box.FileTypeBox() + self.assertEqual(b.brand, 'jp2 ') + self.assertEqual(b.minor_version, 0) + self.assertEqual(b.compatibility_list, ['jp2 ']) + + def test_default_ImageHeaderBox(self): + # Should be able to instantiate an image header box. + b = glymur.jp2box.ImageHeaderBox(height=512, width=256, + num_components=3) + self.assertEqual(b.height, 512) + self.assertEqual(b.width, 256) + self.assertEqual(b.num_components, 3) + self.assertEqual(b.bits_per_component, 8) + self.assertFalse(b.signed) + self.assertFalse(b.colorspace_unknown) + + def test_default_JP2HeaderBox(self): + b1 = JP2HeaderBox() + b1.box = [ImageHeaderBox(height=512, width=256), + ColourSpecificationBox(colorspace=glymur.core.GREYSCALE)] + + def test_default_ContiguousCodestreamBox(self): + b = ContiguousCodestreamBox() + self.assertEqual(b.box_id, 'jp2c') + self.assertIsNone(b.main_header) + + class TestJpxBoxes(unittest.TestCase): def setUp(self): diff --git a/glymur/test/test_jp2k.py b/glymur/test/test_jp2k.py index 43eaade..34d49a5 100644 --- a/glymur/test/test_jp2k.py +++ b/glymur/test/test_jp2k.py @@ -47,6 +47,9 @@ def load_tests(loader, tests, ignore): return tests +@unittest.skipIf(glymur.lib.openjp2.OPENJP2 is None and + glymur.lib.openjpeg.OPENJPEG is None, + "Missing openjp2 library.") class TestConfig(unittest.TestCase): def setUp(self): diff --git a/glymur/test/test_opj_suite.py b/glymur/test/test_opj_suite.py index 4699b06..47d50f8 100644 --- a/glymur/test/test_opj_suite.py +++ b/glymur/test/test_opj_suite.py @@ -832,7 +832,6 @@ class TestSuite(unittest.TestCase): data = Jp2k(jfile).read() self.assertTrue(True) - @unittest.skipIf(sys.hexversion < 0x03020000, "Uses features introduced in 3.2.") def test_NR_DEC_broken3_jp2_6_decode(self): diff --git a/release.txt b/release.txt index f41ecb4..7504f7f 100644 --- a/release.txt +++ b/release.txt @@ -6,15 +6,15 @@ | | | | | pass. | +-----------+--------+--------+--------+--------------------------------------+ | Mac | X | | | MacPorts with both OpenJPEG 1.5.1 | -| 10.6.8 | | | | and OpenJPEG svn. 352 of 450 tests | +| 10.6.8 | | | | and OpenJPEG svn. 354 of 455 tests | | | | | | should pass. | +-----------+--------+--------+--------+--------------------------------------+ | Mac | | X | | MacPorts with both OpenJPEG 1.5.1 | -| 10.6.8 | | | | and OpenJPEG svn. 377 of 455 tests | +| 10.6.8 | | | | and OpenJPEG svn. 379 of 460 tests | | | | | | should pass. | +-----------+--------+--------+--------+--------------------------------------+ | Mac | | | X | MacPorts with both OpenJPEG 1.5.1 | -| 10.6.8 | | | | and OpenJPEG svn. 402 of 455 | +| 10.6.8 | | | | and OpenJPEG svn. 407 of 460 | | | | | | tests should pass. | +-----------+--------+--------+-----------------------------------------------+ | Fedora 19 | | | X | Ships with 1.5.1, openjp2 built too. | @@ -26,10 +26,10 @@ | Fedora 17 | | X | | Ships with 1.4.0. 166 of 450 tests | | | | | | should pass. | +-----------+--------+--------+--------+--------------------------------------+ -| CentOS | X | | | Ships with 1.3.0. 164 of 450 tests | +| CentOS | X | | | Ships with 1.3.0. 169 of 455 tests | | 6.3 | | | | should pass. | +-----------+--------+--------+--------+--------------------------------------+ -| Raspberry | | X | | Ships with 1.3.0. 166 of 450 tests | +| Raspberry | | X | | Ships with 1.3.0. 171 of 455 tests | | Pi | | | | should pass. | | Debian 7 | | | | | +-----------+--------+--------+--------+--------------------------------------+ diff --git a/setup.py b/setup.py index 8d88a3a..52df311 100644 --- a/setup.py +++ b/setup.py @@ -2,7 +2,7 @@ from setuptools import setup, find_packages import sys kwargs = {'name': 'Glymur', - 'version': '0.2.5', + 'version': '0.2.7', 'description': 'Tools for accessing JPEG2000 files', 'long_description': open('README.md').read(), 'author': 'John Evans',