diff --git a/glymur/lib/openjp2.py b/glymur/lib/openjp2.py index d7578d0..b6e655c 100644 --- a/glymur/lib/openjp2.py +++ b/glymur/lib/openjp2.py @@ -1,6 +1,9 @@ """ Wraps individual functions in openjp2 library. """ +import ctypes +import platform +from ctypes.util import find_library def _glymurrc_fname(): @@ -23,19 +26,46 @@ def _glymurrc_fname(): fname = os.path.join(confdir, 'glymurrc') if os.path.exists(fname): return fname - else: - msg = "Configuration file '{0}' does not exist.".format(confdir) - warnings.warn(msg, UserWarning) # didn't find a configuration file. return None -def _config(): - """Read configuration file. +def _get_openjpeg_config(): + libopenjpeg_path = find_library('openjpeg') + + # If we could not find it, then look in some likely locations. + if libopenjpeg_path is None: + if platform.system() == 'Darwin': + path = '/opt/local/lib/libopenjpeg.dylib' + if os.path.exists(path): + libopenjpeg_path = path + elif os.name == 'nt': + path = os.path.join('C:\\', 'Program files', 'OpenJPEG 1.5', + 'bin', 'openjpeg.dll') + if os.path.exists(path): + libopenjpeg_path = path - Based on matplotlib. - """ + try: + if os.name == "nt": + _OPENJPEG = ctypes.windll.LoadLibrary(libopenjpeg_path) + else: + _OPENJPEG = ctypes.CDLL(libopenjpeg_path) + except OSError: + _OPENJPEG = None + + if _OPENJPEG is not None: + # Must be at least 1.5.0 + _OPENJPEG.opj_version.restype = ctypes.c_char_p + v = _OPENJPEG.opj_version() + v = v.decode('utf-8') + major, minor, patch = v.split('.') + if minor != '5': + _OPENJPEG = None + return _OPENJPEG + + +def _get_openjp2_config(): filename = _glymurrc_fname() if filename is not None: # Read the configuration file for the library location. @@ -44,7 +74,6 @@ def _config(): libopenjp2_path = parser.get('library', 'openjp2') else: # No help from the config file, try to find it ourselves. - from ctypes.util import find_library libopenjp2_path = find_library('openjp2') if libopenjp2_path is None: @@ -60,6 +89,13 @@ def _config(): return _OPENJP2 +def _config(): + """Read configuration file. + """ + _OPENJP2 = _get_openjp2_config() + _OPENJPEG = _get_openjpeg_config() + return _OPENJP2, _OPENJPEG + def _get_configdir(): """Return string representing the configuration directory. @@ -73,7 +109,6 @@ def _get_configdir(): if 'HOME' in os.environ: return os.path.join(os.environ['HOME'], '.config', 'glymur') -import ctypes import os import warnings @@ -85,7 +120,12 @@ else: from configparser import ConfigParser from configparser import NoOptionError -_OPENJP2 = _config() +_OPENJP2, _OPENJPEG = _config() +if _OPENJP2 is None and _OPENJPEG is None: + msg = "Neither the glymur configuration file could not be located " + msg += "nor could openjpeg 1.5.1 be located. Glymur can only " + msg += "operate under extremely degraded conditions." + warnings.warn(msg, UserWarning) import numpy as np diff --git a/glymur/test/__init__.py b/glymur/test/__init__.py index 199a1f7..2a62da4 100644 --- a/glymur/test/__init__.py +++ b/glymur/test/__init__.py @@ -1,5 +1,6 @@ from .test_callbacks import TestCallbacks as callbacks from .test_codestream import TestCodestream as codestream +from .test_config import TestSuite as config from .test_jp2k import TestJp2k as jp2k from .test_jp2k_15 import TestSuite as jp2k15 from .test_icc import TestICC as icc diff --git a/glymur/test/test_config.py b/glymur/test/test_config.py index 8f78804..9e5374a 100644 --- a/glymur/test/test_config.py +++ b/glymur/test/test_config.py @@ -1,3 +1,7 @@ +"""These tests are for edge cases where OPENJPEG does not exist, but +OPENJP2 may be present in some form or other. +""" + import imp import os import sys @@ -16,21 +20,33 @@ from glymur import Jp2k from glymur.lib import openjp2 as opj2 +@unittest.skip("Cannot work when both OPENJPEG and OPENJP2 are both present.") +@unittest.skipIf(glymur.lib.openjp2._OPENJP2 is None, + "Needs openjp2 library first before these tests make sense.") @unittest.skipIf(sys.hexversion < 0x03020000, "Uses features introduced in 3.2.") -class TestJp2k(unittest.TestCase): +class TestSuite(unittest.TestCase): + + @classmethod + def setUpClass(cls): + # Monkey patch the package so as to ignore OPENJPEG if it exists. + cls.openjpeg = glymur.lib.openjpeg._OPENJPEG + glymur.lib.openjp2._OPENJPEG = None + + @classmethod + def tearDownClass(cls): + # Restore OPENJPEG + glymur.lib.openjpeg._OPENJPEG = cls.openjpeg + def setUp(self): - self.jp2file = pkg_resources.resource_filename(glymur.__name__, - "data/nemo.jp2") imp.reload(glymur) imp.reload(glymur.lib.openjp2) + self.jp2file = glymur.data.nemo() def tearDown(self): imp.reload(glymur) imp.reload(glymur.lib.openjp2) - @unittest.skipIf(glymur.lib.openjp2._OPENJP2 is None, - "Needs openjp2 library first.") def test_config_file_via_environ(self): """Verify that we can read a configuration file set via environ var.""" with tempfile.TemporaryDirectory() as tdir: