Support for opj_version, opj_set_default_decoder_parameters.

This commit is contained in:
jevans 2013-07-02 20:42:05 -04:00
commit 5a7c410288
6 changed files with 207 additions and 6 deletions

View file

@ -186,4 +186,3 @@ _reader_requirements_display = {
+ 'requirements in M.9.2.3',
73: 'YPbPr(1125/60) enumerated colourspace',
74: 'YPbPr(1250/50) enumerated colourspace'}

View file

@ -18,6 +18,7 @@ import numpy as np
from .codestream import Codestream
from .core import *
from .jp2box import *
from .lib import openjpeg as opj
from .lib import openjp2 as opj2
_cspace_map = {'rgb': opj2._CLRSPC_SRGB,
@ -544,16 +545,17 @@ class Jp2k(Jp2kBox):
jp2 = Jp2k(filename)
return jp2
def read(self, reduce=0, layer=0, area=None, tile=None, verbose=False):
def read(self, **kwargs):
"""Read a JPEG 2000 image.
Parameters
----------
layer : int, optional
Number of quality layer to decode.
reduce : int, optional
Factor by which to reduce output resolution. Use -1 to get the
lowest resolution thumbnail.
lowest resolution thumbnail. This is the only keyword option
available to use when only OpenJPEG version 1.5.1 is present.
layer : int, optional
Number of quality layer to decode.
area : tuple, optional
Specifies decoding image area,
(first_row, first_col, last_row, last_col)
@ -587,6 +589,62 @@ class Jp2k(Jp2kBox):
>>> thumbnail.shape
(46, 81, 3)
"""
if opj2._OPENJP2 is not None:
img_array = self._read_openjp2(**kwargs)
else:
img_array = self._read_openjpeg(**kwargs)
return img_array
def _read_openjpeg(self, reduce=0):
"""Read a JPEG 2000 image using libopenjpeg.
Parameters
----------
reduce : int, optional
Factor by which to reduce output resolution. Use -1 to get the
lowest resolution thumbnail.
Returns
-------
img_array : ndarray
The image data.
Raises
------
IOError
If the image has differing subsample factors.
"""
raise NotImplementedError("not there yet")
def _read_openjp2(self, reduce=0, layer=0, area=None, tile=None,
verbose=False):
"""Read a JPEG 2000 image using libopenjp2.
Parameters
----------
layer : int, optional
Number of quality layer to decode.
reduce : int, optional
Factor by which to reduce output resolution. Use -1 to get the
lowest resolution thumbnail.
area : tuple, optional
Specifies decoding image area,
(first_row, first_col, last_row, last_col)
tile : int, optional
Number of tile to decode.
verbose : bool, optional
Print informational messages produced by the OpenJPEG library.
Returns
-------
img_array : ndarray
The image data.
Raises
------
IOError
If the image has differing subsample factors.
"""
# Check for differing subsample factors.
codestream = self.get_codestream(header_only=True)
dxs = np.array(codestream.segment[1].XRsiz)

View file

@ -1,3 +1,4 @@
"""This package organizes individual libraries employed by glymur."""
from . import openjp2
from . import test
from . import openjpeg
#from . import test

58
glymur/lib/openjpeg.py Normal file
View file

@ -0,0 +1,58 @@
"""Wraps library calls to openjpeg.
"""
import ctypes
from ctypes.util import find_library
import platform
import os
if os.name == "nt":
_OPENJPEG = ctypes.windll.LoadLibrary('openjpeg')
else:
if platform.system() == 'Darwin':
_OPENJPEG = ctypes.CDLL('/opt/local/lib/libopenjpeg.dylib')
if _OPENJPEG is None:
# Make one last attempt. Does the system know where it is?
_OPENJPEG = find_library('openjpeg')
OPJ_PATH_LEN = 4096 # maximum allowed size for filenames
class dparameters_t(ctypes.Structure):
# cp_reduce: the number of highest resolution levels to be discarded
_fields_ = [("cp_reduce", ctypes.c_int),
# cp_layer: the maximum number of quality layers to decode
("cp_layer", ctypes.c_int),
# infile: input file name
("infile", ctypes.c_char * OPJ_PATH_LEN),
# outfile: output file name
("outfile", ctypes.c_char * OPJ_PATH_LEN),
# decod_format: input file format 0: J2K, 1: JP2, 2: JPT
("decod_format", ctypes.c_int),
# cod_format: output file format 0: PGX, 1: PxM, 2: BMP
("cod_format", ctypes.c_int),
# jpwl_correct: activates the JPWL correction capabilities
("jpwl_correct", ctypes.c_bool),
# jpwl_exp_comps: expected number of components
("jpwl_exp_comps", ctypes.c_int),
# jpwl_max_tiles: maximum number of tiles
("jpwl_max_tiles", ctypes.c_int),
# cp_limit_decoding: whether decoding should be done on the
# entire codestream or be limited to the main header
("cp_limit_decoding", ctypes.c_int),
("flags", ctypes.c_uint)]
def _set_default_decoder_parameters(dparams_p):
"""Wrapper for opj_set_default_decoder_parameters.
"""
argtypes = [ctypes.POINTER(dparameters_t)]
_OPENJPEG.opj_set_default_decoder_parameters.argtypes = argtypes
_OPENJPEG.opj_set_default_decoder_parameters(dparams_p)
def _version():
"""Wrapper for opj_version library routine."""
_OPENJPEG.opj_version.restype = ctypes.c_char_p
v = _OPENJPEG.opj_version()
return v.decode('utf-8')

View file

@ -0,0 +1,38 @@
import ctypes
import unittest
import glymur
@unittest.skipIf(glymur.lib.openjpeg._OPENJPEG is None,
"Missing openjpeg library.")
class TestOpenJPEG(unittest.TestCase):
def setUp(self):
pass
def tearDown(self):
pass
def test_version(self):
v = glymur.lib.openjpeg._version()
parts = v.split('.')
self.assertEqual(parts[0], '1')
self.assertEqual(parts[1], '5')
def test_set_default_decoder_parameters(self):
# Verify that we properly set the default decode parameters.
dp = glymur.lib.openjpeg.dparameters_t()
glymur.lib.openjpeg._set_default_decoder_parameters(ctypes.byref(dp))
self.assertEqual(dp.cp_reduce, 0)
self.assertEqual(dp.cp_layer, 0)
self.assertEqual(dp.infile, b'')
self.assertEqual(dp.outfile, b'')
self.assertEqual(dp.decod_format, -1)
self.assertEqual(dp.cod_format, -1)
self.assertEqual(dp.jpwl_correct, 0)
self.assertEqual(dp.jpwl_exp_comps, 0)
self.assertEqual(dp.jpwl_max_tiles, 0)
self.assertEqual(dp.cp_limit_decoding, 0)
self.assertEqual(dp.flags, 0)

View file

@ -0,0 +1,47 @@
import os
import unittest
import numpy as np
import glymur
from glymur import Jp2k
from glymur.lib import openjpeg as opj
try:
data_root = os.environ['OPJ_DATA_ROOT']
except KeyError:
data_root = None
except:
raise
@unittest.skipIf(glymur.lib.openjpeg._OPENJPEG is None,
"Missing openjpeg library.")
class TestJp2k15(unittest.TestCase):
def setUp(self):
self.jp2file = glymur.data.nemo()
self.j2kfile = glymur.data.goodstuff()
def tearDown(self):
pass
def test_layers(self):
# Layers not allowed for 1.5.1.
self.assertTrue(False)
def test_area(self):
# Area option not allowed for 1.5.1.
self.assertTrue(False)
def test_tile(self):
# Tile option not allowed for 1.5.1.
self.assertTrue(False)
def test_verbose(self):
# Verbose option not allowed for 1.5.1.
self.assertTrue(False)
if __name__ == "__main__":
unittest.main()