Hooked up openjpeg event handlers. #67
This commit is contained in:
parent
32dcb12823
commit
39e2859a66
4 changed files with 85 additions and 5 deletions
|
|
@ -595,7 +595,7 @@ class Jp2k(Jp2kBox):
|
||||||
img = self._read_openjpeg(**kwargs)
|
img = self._read_openjpeg(**kwargs)
|
||||||
return img
|
return img
|
||||||
|
|
||||||
def _read_openjpeg(self, reduce=0):
|
def _read_openjpeg(self, reduce=0, verbose=False):
|
||||||
"""Read a JPEG 2000 image using libopenjpeg.
|
"""Read a JPEG 2000 image using libopenjpeg.
|
||||||
|
|
||||||
Parameters
|
Parameters
|
||||||
|
|
@ -603,6 +603,8 @@ class Jp2k(Jp2kBox):
|
||||||
reduce : int, optional
|
reduce : int, optional
|
||||||
Factor by which to reduce output resolution. Use -1 to get the
|
Factor by which to reduce output resolution. Use -1 to get the
|
||||||
lowest resolution thumbnail.
|
lowest resolution thumbnail.
|
||||||
|
verbose : bool, optional
|
||||||
|
Print informational messages produced by the OpenJPEG library.
|
||||||
|
|
||||||
Returns
|
Returns
|
||||||
-------
|
-------
|
||||||
|
|
@ -629,6 +631,15 @@ class Jp2k(Jp2kBox):
|
||||||
|
|
||||||
dinfo = opj._create_decompress(dparameters.decod_format)
|
dinfo = opj._create_decompress(dparameters.decod_format)
|
||||||
|
|
||||||
|
event_mgr = opj.event_mgr_t()
|
||||||
|
info_handler = ctypes.cast(_info_callback, ctypes.c_void_p)
|
||||||
|
event_mgr.info_handler = info_handler if verbose else None
|
||||||
|
event_mgr.warning_handler = ctypes.cast(_warning_callback,
|
||||||
|
ctypes.c_void_p)
|
||||||
|
event_mgr.error_handler = ctypes.cast(_error_callback,
|
||||||
|
ctypes.c_void_p)
|
||||||
|
opj._set_event_mgr(dinfo, ctypes.byref(event_mgr))
|
||||||
|
|
||||||
opj._setup_decoder(dinfo, dparameters)
|
opj._setup_decoder(dinfo, dparameters)
|
||||||
|
|
||||||
with open(self.filename, 'rb') as fp:
|
with open(self.filename, 'rb') as fp:
|
||||||
|
|
|
||||||
|
|
@ -166,6 +166,16 @@ def _set_default_decoder_parameters(dparams_p):
|
||||||
_OPENJPEG.opj_set_default_decoder_parameters(dparams_p)
|
_OPENJPEG.opj_set_default_decoder_parameters(dparams_p)
|
||||||
|
|
||||||
|
|
||||||
|
def _set_event_mgr(dinfo, event_mgr, context=None):
|
||||||
|
"""Wrapper for openjpeg library function opj_set_event_mgr.
|
||||||
|
"""
|
||||||
|
argtypes = [ctypes.POINTER(common_struct_t),
|
||||||
|
ctypes.POINTER(event_mgr_t),
|
||||||
|
ctypes.c_void_p]
|
||||||
|
_OPENJPEG.opj_set_event_mgr(ctypes.cast(dinfo,
|
||||||
|
ctypes.POINTER(common_struct_t)),
|
||||||
|
event_mgr, context)
|
||||||
|
|
||||||
def _setup_decoder(dinfo, dparams):
|
def _setup_decoder(dinfo, dparams):
|
||||||
"""Wrapper for openjpeg library function opj_setup_decoder."""
|
"""Wrapper for openjpeg library function opj_setup_decoder."""
|
||||||
argtypes = [ctypes.POINTER(dinfo_t), ctypes.POINTER(dparameters_t)]
|
argtypes = [ctypes.POINTER(dinfo_t), ctypes.POINTER(dparameters_t)]
|
||||||
|
|
|
||||||
|
|
@ -59,5 +59,50 @@ class TestCallbacks(unittest.TestCase):
|
||||||
self.assertEqual(actual, expected)
|
self.assertEqual(actual, expected)
|
||||||
|
|
||||||
|
|
||||||
|
@unittest.skipIf(glymur.lib.openjp2._OPENJPEG is None,
|
||||||
|
"Missing openjpeg library.")
|
||||||
|
class TestCallbacks15(unittest.TestCase):
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def setUpClass(cls):
|
||||||
|
# Monkey patch the package so as to use OPENJPEG instead of OPENJP2
|
||||||
|
cls.openjp2 = glymur.lib.openjp2._OPENJP2
|
||||||
|
glymur.lib.openjp2._OPENJP2 = None
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def tearDownClass(cls):
|
||||||
|
# Restore OPENJP2
|
||||||
|
glymur.lib.openjp2._OPENJP2 = cls.openjp2
|
||||||
|
|
||||||
|
def setUp(self):
|
||||||
|
# Save sys.stdout.
|
||||||
|
self.stdout = sys.stdout
|
||||||
|
sys.stdout = StringIO()
|
||||||
|
self.jp2file = glymur.data.nemo()
|
||||||
|
self.j2kfile = glymur.data.goodstuff()
|
||||||
|
|
||||||
|
def tearDown(self):
|
||||||
|
# Restore stdout.
|
||||||
|
sys.stdout = self.stdout
|
||||||
|
|
||||||
|
def test_info_callbacks_on_read(self):
|
||||||
|
# Verify that we get the expected stdio output when our internal info
|
||||||
|
# callback handler is enabled.
|
||||||
|
j = glymur.Jp2k(self.j2kfile)
|
||||||
|
d = j.read(reduce=1, verbose=True)
|
||||||
|
actual = sys.stdout.getvalue().strip()
|
||||||
|
|
||||||
|
# We can't actually match this because the times will be different.
|
||||||
|
lines = ['[INFO] tile 1 of 1',
|
||||||
|
'[INFO] - tiers-1 took 0.050149 s',
|
||||||
|
'[INFO] - dwt took 0.004188 s',
|
||||||
|
'[INFO] - tile decoded in 0.058203 s']
|
||||||
|
|
||||||
|
expected = '\n'.join(lines)
|
||||||
|
self.assertTrue('[INFO]' in actual)
|
||||||
|
self.assertTrue('dwt took' in actual)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
if __name__ == "__main__":
|
if __name__ == "__main__":
|
||||||
unittest.main()
|
unittest.main()
|
||||||
|
|
|
||||||
|
|
@ -35,6 +35,7 @@ class TestJp2k(unittest.TestCase):
|
||||||
glymur.lib.openjp2._OPENJP2 = cls.openjp2
|
glymur.lib.openjp2._OPENJP2 = cls.openjp2
|
||||||
|
|
||||||
def setUp(self):
|
def setUp(self):
|
||||||
|
self.jp2file = glymur.data.nemo()
|
||||||
self.j2kfile = glymur.data.goodstuff()
|
self.j2kfile = glymur.data.goodstuff()
|
||||||
|
|
||||||
def tearDown(self):
|
def tearDown(self):
|
||||||
|
|
@ -64,10 +65,17 @@ class TestJp2k(unittest.TestCase):
|
||||||
with self.assertRaises(TypeError) as ce:
|
with self.assertRaises(TypeError) as ce:
|
||||||
d = j2k.read(layer=1)
|
d = j2k.read(layer=1)
|
||||||
|
|
||||||
def test_basic(self):
|
def test_basic_jp2(self):
|
||||||
# This test is only useful when openjp2 is not available
|
# This test is only useful when openjp2 is not available
|
||||||
# and OPJ_DATA_ROOT is not set. We need at least one
|
# and OPJ_DATA_ROOT is not set. We need at least one
|
||||||
# working read test.
|
# working JP2 test.
|
||||||
|
j2k = Jp2k(self.jp2file)
|
||||||
|
d = j2k.read(reduce=1)
|
||||||
|
|
||||||
|
def test_basic_j2k(self):
|
||||||
|
# This test is only useful when openjp2 is not available
|
||||||
|
# and OPJ_DATA_ROOT is not set. We need at least one
|
||||||
|
# working J2K test.
|
||||||
j2k = Jp2k(self.j2kfile)
|
j2k = Jp2k(self.j2kfile)
|
||||||
d = j2k.read()
|
d = j2k.read()
|
||||||
|
|
||||||
|
|
@ -309,7 +317,10 @@ class TestSuite(unittest.TestCase):
|
||||||
def test_ETS_C1P0_p0_10_j2k(self):
|
def test_ETS_C1P0_p0_10_j2k(self):
|
||||||
jfile = os.path.join(data_root, 'input/conformance/p0_10.j2k')
|
jfile = os.path.join(data_root, 'input/conformance/p0_10.j2k')
|
||||||
jp2k = Jp2k(jfile)
|
jp2k = Jp2k(jfile)
|
||||||
jpdata = jp2k.read(reduce=0)
|
with warnings.catch_warnings():
|
||||||
|
# This file has an invalid ICC profile
|
||||||
|
warnings.simplefilter("ignore")
|
||||||
|
jpdata = jp2k.read(reduce=0)
|
||||||
|
|
||||||
pgxfile = os.path.join(data_root, 'baseline/conformance/c1p0_10_0.pgx')
|
pgxfile = os.path.join(data_root, 'baseline/conformance/c1p0_10_0.pgx')
|
||||||
pgxdata = read_pgx(pgxfile)
|
pgxdata = read_pgx(pgxfile)
|
||||||
|
|
@ -695,7 +706,10 @@ class TestSuite(unittest.TestCase):
|
||||||
def test_NR_DEC_kakadu_v4_4_openjpegv2_broken_j2k_16_decode(self):
|
def test_NR_DEC_kakadu_v4_4_openjpegv2_broken_j2k_16_decode(self):
|
||||||
relpath = 'input/nonregression/kakadu_v4-4_openjpegv2_broken.j2k'
|
relpath = 'input/nonregression/kakadu_v4-4_openjpegv2_broken.j2k'
|
||||||
jfile = os.path.join(data_root, relpath)
|
jfile = os.path.join(data_root, relpath)
|
||||||
data = Jp2k(jfile).read()
|
with warnings.catch_warnings():
|
||||||
|
# This file has an invalid ICC profile
|
||||||
|
warnings.simplefilter("ignore")
|
||||||
|
data = Jp2k(jfile).read()
|
||||||
self.assertTrue(True)
|
self.assertTrue(True)
|
||||||
|
|
||||||
def test_NR_DEC_MarkerIsNotCompliant_j2k_17_decode(self):
|
def test_NR_DEC_MarkerIsNotCompliant_j2k_17_decode(self):
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue