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)
|
||||
return img
|
||||
|
||||
def _read_openjpeg(self, reduce=0):
|
||||
def _read_openjpeg(self, reduce=0, verbose=False):
|
||||
"""Read a JPEG 2000 image using libopenjpeg.
|
||||
|
||||
Parameters
|
||||
|
|
@ -603,6 +603,8 @@ class Jp2k(Jp2kBox):
|
|||
reduce : int, optional
|
||||
Factor by which to reduce output resolution. Use -1 to get the
|
||||
lowest resolution thumbnail.
|
||||
verbose : bool, optional
|
||||
Print informational messages produced by the OpenJPEG library.
|
||||
|
||||
Returns
|
||||
-------
|
||||
|
|
@ -629,6 +631,15 @@ class Jp2k(Jp2kBox):
|
|||
|
||||
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)
|
||||
|
||||
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)
|
||||
|
||||
|
||||
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):
|
||||
"""Wrapper for openjpeg library function opj_setup_decoder."""
|
||||
argtypes = [ctypes.POINTER(dinfo_t), ctypes.POINTER(dparameters_t)]
|
||||
|
|
|
|||
|
|
@ -59,5 +59,50 @@ class TestCallbacks(unittest.TestCase):
|
|||
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__":
|
||||
unittest.main()
|
||||
|
|
|
|||
|
|
@ -35,6 +35,7 @@ class TestJp2k(unittest.TestCase):
|
|||
glymur.lib.openjp2._OPENJP2 = cls.openjp2
|
||||
|
||||
def setUp(self):
|
||||
self.jp2file = glymur.data.nemo()
|
||||
self.j2kfile = glymur.data.goodstuff()
|
||||
|
||||
def tearDown(self):
|
||||
|
|
@ -64,10 +65,17 @@ class TestJp2k(unittest.TestCase):
|
|||
with self.assertRaises(TypeError) as ce:
|
||||
d = j2k.read(layer=1)
|
||||
|
||||
def test_basic(self):
|
||||
def test_basic_jp2(self):
|
||||
# This test is only useful when openjp2 is not available
|
||||
# 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)
|
||||
d = j2k.read()
|
||||
|
||||
|
|
@ -309,7 +317,10 @@ class TestSuite(unittest.TestCase):
|
|||
def test_ETS_C1P0_p0_10_j2k(self):
|
||||
jfile = os.path.join(data_root, 'input/conformance/p0_10.j2k')
|
||||
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')
|
||||
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):
|
||||
relpath = 'input/nonregression/kakadu_v4-4_openjpegv2_broken.j2k'
|
||||
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)
|
||||
|
||||
def test_NR_DEC_MarkerIsNotCompliant_j2k_17_decode(self):
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue