Merge branch 'issue111' into devel

This commit is contained in:
jevans 2013-09-12 19:36:12 -04:00
commit c051d8d291
5 changed files with 610 additions and 77 deletions

View file

@ -80,60 +80,42 @@ MacPorts supplies both OpenJPEG 1.5.0 and OpenJPEG 2.0.0.
Linux
-----
For the most part, you only need python and numpy to run glymur. In order to
run as many tests as possible, however, the following Python packages may also
need to be installed.
* setuptools
* matplotlib
* pillow
* contextlib2 (python 2.7 only)
* mock (python 2.7 only)
OpenSUSE 12.3
'''''''''''''
Ships with Python 3.3 and 2.7. You should use pip to install Pillow.
Fedora 19
'''''''''
Fedora 18 ships with Python 3.3 and all the necessary RPMs are available to
run the maximum number of tests.
* python3
* python3-numpy
* python3-setuptools
* python3-matplotlib (for running tests)
* python3-matplotlib-tk (or whichever matplotlib backend you prefer)
* python3-pillow (for running tests)
Ships with Python 3.3 and 2.7. All packages available as RPMs.
Fedora 18
'''''''''
Fedora 18 ships with Python 3.3 and the following RPMs are available to
meet the minimal set of requirements for running glymur.
* python3
* python3-numpy
* python3-setuptools
For running the maximal number of tests, you also need
* python3-matplotlib
* python3-matplotlib-tk (or whichever matplotlib backend you prefer)
Pillow is also needed in order to run the maximum number of tests, so
go ahead and install Pillow via pip since Pillow is not available
in Fedora 18 default repositories::
Fedora 18 ships with Python 3.3 and 2.7. Most packages are available as
standard RPMS, but you should use pip to install Pillow as it is not available
in the Fedora 18 default repositories::
$ yum install python3-devel # pip needs this in order to compile Pillow
$ yum install python3-pip
$ pip-python3 install Pillow --user
$ export PYTHONPATH=$HOME/.local/lib/python3.3/site-packages:$PYTHONPATH
Fedora 17
'''''''''
Fedora 17 ships with Python 2.7 and OpenJPEG 1.4. You should have the
following RPMs installed.
* python
* python-mock
* python-pip
* python-setuptools
* numpy
* matplotlib (optional)
In addition, you must install contextlib2 and Pillow via pip. ::
Fedora 17 ships with Python 2.7 and OpenJPEG 1.4. You must install contextlib2
and Pillow via pip. ::
$ yum install python-devel # pip needs this in order to compile Pillow
$ pip-python install Pillow --user
$ pip-python install contextlib2 --user
$ export PYTHONPATH=$HOME/.local/lib/python2.7/site-packages:$PYTHONPATH
Windows
-------

View file

@ -15,14 +15,14 @@ else:
import ctypes
import math
import os
import re
import struct
import warnings
import numpy as np
from .codestream import Codestream
from .core import SRGB
from .core import GREYSCALE
from .core import SRGB, GREYSCALE
from .core import PROGRESSION_ORDER
from .core import ENUMERATED_COLORSPACE, RESTRICTED_ICC_PROFILE
from .jp2box import Jp2kBox
@ -33,6 +33,13 @@ from .lib import openjpeg as opj
from .lib import openjp2 as opj2
from .lib import c as libc
if opj.OPENJPEG is None and opj2.OPENJP2 is None:
OPENJPEG_VERSION = '0.0.0'
elif opj2.OPENJP2 is None:
OPENJPEG_VERSION = opj.version()
else:
OPENJPEG_VERSION = opj2.version()
class Jp2k(Jp2kBox):
"""JPEG 2000 file.
@ -185,7 +192,10 @@ class Jp2k(Jp2kBox):
cparams : CompressionParametersType(ctypes.Structure)
Corresponds to cparameters_t type in openjp2 headers.
"""
cparams = opj2.set_default_encoder_parameters()
if re.match(r"""1\.\d\.\d""", OPENJPEG_VERSION):
cparams = opj.set_default_encoder_parameters()
else:
cparams = opj2.set_default_encoder_parameters()
outfile = self.filename.encode()
num_pad_bytes = opj2.PATH_LEN - len(outfile)
@ -280,9 +290,6 @@ class Jp2k(Jp2kBox):
Corresponds to cparameters_t type in openjp2 headers.
colorspace : int
Either CLRSPC_SRGB or CLRSPC_GRAY
mct : bool, optional
Specifies usage of the multi component transform. If not
specified, defaults to True if the colorspace is RGB.
"""
if 'cratios' in kwargs and 'psnr' in kwargs:
@ -380,11 +387,127 @@ class Jp2k(Jp2kBox):
glymur.LibraryNotFoundError
If glymur is unable to load the openjp2 library.
"""
if opj2.OPENJP2 is None:
raise LibraryNotFoundError("You must have the openjp2 library "
"installed before using this "
if opj2.OPENJP2 is not None:
img = self._write_openjp2(img_array, verbose=verbose, **kwargs)
elif opj.OPENJPEG is not None:
img = self._write_openjpeg(img_array, verbose=verbose, **kwargs)
else:
raise LibraryNotFoundError("You must have version 1.5 of OpenJPEG "
"or more recent before using this "
"functionality.")
def _write_openjpeg(self, img_array, verbose=False, **kwargs):
"""
"""
cparams, colorspace = self._process_write_inputs(img_array, **kwargs)
if img_array.ndim == 2:
# Force the image to be 3D. Just makes things easier later on.
numrows, numcols = img_array.shape
img_array = img_array.reshape(numrows, numcols, 1)
comptparms = _populate_comptparms(img_array, cparams)
image = opj.image_create(comptparms, colorspace)
numrows, numcols, numlayers = img_array.shape
# set image offset and reference grid
image.contents.x0 = cparams.image_offset_x0
image.contents.y0 = cparams.image_offset_y0
image.contents.x1 = image.contents.x0 + (numcols - 1) * cparams.subsampling_dx + 1
image.contents.y1 = image.contents.y0 + (numrows - 1) * cparams.subsampling_dy + 1
# Stage the image data to the openjpeg data structure.
for k in range(0,numlayers):
layer = np.ascontiguousarray(img_array[:,:,k], dtype=np.int32)
dest = image.contents.comps[k].data
src = layer.ctypes.data
ctypes.memmove(dest, src, layer.nbytes)
# set encode format
cinfo = opj.create_compress(cparams.codec_fmt)
event_mgr = opj.EventMgrType(None, None, None)
#opj.set_event_mgr(cparams, ctypes.byref(event_mgr), None)
opj.setup_encoder(cinfo, ctypes.byref(cparams), image)
# open a byte stream for writing
# allocate memory for all tiles
cio = opj.cio_open(cinfo)
opj.encode(cinfo, cio, image)
pos = opj.cio_tell(cio)
ss = ctypes.string_at(cio.contents.buffer, pos)
f = open(self.filename,'wb')
f.write(ss)
f.close()
opj.cio_close(cio);
opj.destroy_compress(cinfo);
opj.image_destroy(image);
self.parse()
def _write_openjp2(self, img_array, verbose=False, **kwargs):
"""Write image data to a JP2/JPX/J2k file. Intended usage of the
various parameters follows that of OpenJPEG's opj_compress utility.
This method can only be used to create JPEG 2000 images that can fit
in memory.
Parameters
----------
img_array : ndarray
Image data to be written to file.
cbsize : tuple, optional
Code block size (DY, DX).
colorspace : str, optional
Either 'rgb' or 'gray'.
cratios : iterable
Compression ratios for successive layers.
eph : bool, optional
If true, write SOP marker after each header packet.
grid_offset : tuple, optional
Offset (DY, DX) of the origin of the image in the reference grid.
mct : bool, optional
Specifies usage of the multi component transform. If not
specified, defaults to True if the colorspace is RGB.
modesw : int, optional
Mode switch.
1 = BYPASS(LAZY)
2 = RESET
4 = RESTART(TERMALL)
8 = VSC
16 = ERTERM(SEGTERM)
32 = SEGMARK(SEGSYM)
numres : int, optional
Number of resolutions.
prog : str, optional
Progression order, one of "LRCP" "RLCP", "RPCL", "PCRL", "CPRL".
psnr : iterable, optional
Different PSNR for successive layers.
psizes : list, optional
List of precinct sizes. Each precinct size tuple is defined in
(height x width).
sop : bool, optional
If true, write SOP marker before each packet.
subsam : tuple, optional
Subsampling factors (dy, dx).
tilesize : tuple, optional
Numeric tuple specifying tile size in terms of (numrows, numcols),
not (X, Y).
verbose : bool, optional
Print informational messages produced by the OpenJPEG library.
Raises
------
glymur.LibraryNotFoundError
If glymur is unable to load the openjp2 library.
"""
cparams, colorspace = self._process_write_inputs(img_array, **kwargs)
if img_array.ndim == 2:
@ -1207,7 +1330,10 @@ def _populate_comptparms(img_array, cparams):
comp_prec = 16
numrows, numcols, num_comps = img_array.shape
comptparms = (opj2.ImageComptParmType * num_comps)()
if re.match(r"""1\.\d\.\d""", OPENJPEG_VERSION):
comptparms = (opj.ImageComptParmType * num_comps)()
else:
comptparms = (opj2.ImageComptParmType * num_comps)()
for j in range(num_comps):
comptparms[j].dx = cparams.subsampling_dx
comptparms[j].dy = cparams.subsampling_dy

View file

@ -6,10 +6,16 @@
import ctypes
import sys
import numpy as np
from .config import glymur_config
_, OPENJPEG = glymur_config()
PATH_LEN = 4096 # maximum allowed size for filenames
# Maximum number of tile parts expected by JPWL: increase at your will
JPWL_MAX_NO_TILESPECS = 16
J2K_MAXRLVLS = 33 # Number of maximum resolution level authorized
PATH_LEN = 4096 # maximum allowed size for filenames
def version():
@ -52,14 +58,8 @@ class CommonStructType(ctypes.Structure):
("mj2_handle", ctypes.c_void_p)]
class DecompressionInfoType(ctypes.Structure):
"""This is for decompression contexts.
Corresponds to dinfo_t type in openjpeg headers.
"""
pass
STREAM_READ = 0x0001 # The stream was opened for reading.
STREAM_WRITE = 0x0002 # The stream was opened for writing.
class CioType(ctypes.Structure):
"""Byte input-output stream (CIO)
@ -80,6 +80,266 @@ class CioType(ctypes.Structure):
("bp", ctypes.c_char_p)]
class CompressionInfoType(CommonStructType):
"""Common fields between JPEG-2000 compression and decompression contexts.
This is for compression contexts. Corresponds to common_struct_t.
"""
pass
class PocType(ctypes.Structure):
"""Progression order changes."""
_fields_ = [("resno", ctypes.c_int),
# Resolution num start, Component num start, given by POC
("compno0", ctypes.c_int),
# Layer num end,Resolution num end, Component num end, given by POC
("layno1", ctypes.c_int),
("resno1", ctypes.c_int),
("compno1", ctypes.c_int),
# Layer num start,Precinct num start, Precinct num end
("layno0", ctypes.c_int),
("precno0", ctypes.c_int),
("precno1", ctypes.c_int),
# Progression order enum
# OPJ_PROG_ORDER prg1,prg;
("prg1", ctypes.c_int),
("prg", ctypes.c_int),
# Progression order string
# char progorder[5];
("progorder", ctypes.c_char * 5),
# Tile number
# int tile;
("tile", ctypes.c_int),
# /** Start and end values for Tile width and height*/
# int tx0,tx1,ty0,ty1;
("tx0", ctypes.c_int),
("tx1", ctypes.c_int),
("ty0", ctypes.c_int),
("ty1", ctypes.c_int),
# /** Start value, initialised in pi_initialise_encode*/
# int layS, resS, compS, prcS;
("layS", ctypes.c_int),
("resS", ctypes.c_int),
("compS", ctypes.c_int),
("prcS", ctypes.c_int),
# /** End value, initialised in pi_initialise_encode */
# int layE, resE, compE, prcE;
("layE", ctypes.c_int),
("resE", ctypes.c_int),
("compE", ctypes.c_int),
("prcE", ctypes.c_int),
# Start and end values of Tile width and height, initialised in
# pi_initialise_encode int txS,txE,tyS,tyE,dx,dy;
("txS", ctypes.c_int),
("txE", ctypes.c_int),
("tyS", ctypes.c_int),
("tyE", ctypes.c_int),
("dx", ctypes.c_int),
("dy", ctypes.c_int),
# Temporary values for Tile parts, initialised in pi_create_encode
# int lay_t, res_t, comp_t, prc_t,tx0_t,ty0_t;
("lay_t", ctypes.c_int),
("res_t", ctypes.c_int),
("comp_t", ctypes.c_int),
("prc_t", ctypes.c_int),
("tx0_t", ctypes.c_int),
("ty0_t", ctypes.c_int)]
class CompressionParametersType(ctypes.Structure):
"""Compression parameters.
Corresponds to cparameters_t type in openjp2 headers.
"""
_fields_ = [
# size of tile:
# tile_size_on = false (not in argument) or
# = true (in argument)
("tile_size_on", ctypes.c_int),
# XTOsiz, YTOsiz
("cp_tx0", ctypes.c_int),
("cp_ty0", ctypes.c_int),
# XTsiz, YTsiz
("cp_tdx", ctypes.c_int),
("cp_tdy", ctypes.c_int),
# allocation by rate/distortion
("cp_disto_alloc", ctypes.c_int),
# allocation by fixed layer
("cp_fixed_alloc", ctypes.c_int),
# add fixed_quality
("cp_fixed_quality", ctypes.c_int),
# fixed layer
("cp_matrice", ctypes.c_void_p),
# comment for coding
("cp_comment", ctypes.c_char_p),
# csty : coding style
("csty", ctypes.c_int),
# progression order (default OPJ_LRCP)
("prog_order", ctypes.c_int),
# progression order changes
("poc", PocType * 32),
# number of progression order changes (POC), default to 0
("numpocs", ctypes.c_uint),
# number of layers
("tcp_numlayers", ctypes.c_int),
# rates of layers
("tcp_rates", ctypes.c_float * 100),
# different psnr for successive layers
("tcp_distoratio", ctypes.c_float * 100),
# number of resolutions
("numresolution", ctypes.c_int),
# initial code block width, default to 64
("cblockw_init", ctypes.c_int),
# initial code block height, default to 64
("cblockh_init", ctypes.c_int),
# mode switch (cblk_style)
("mode", ctypes.c_int),
# 1 : use the irreversible DWT 9-7
# 0 : use lossless compression (default)
("irreversible", ctypes.c_int),
# region of interest: affected component in [0..3], -1 means no ROI
("roi_compno", ctypes.c_int),
# region of interest: upshift value
("roi_shift", ctypes.c_int),
# number of precinct size specifications
("res_spec", ctypes.c_int),
# initial precinct width
("prcw_init", ctypes.c_int * J2K_MAXRLVLS),
# initial precinct height
("prch_init", ctypes.c_int * J2K_MAXRLVLS),
# input file name
("infile", ctypes.c_char * PATH_LEN),
# output file name
("outfile", ctypes.c_char * PATH_LEN),
# DEPRECATED.
("index_on", ctypes.c_int),
# DEPRECATED.
("index", ctypes.c_char * PATH_LEN),
# subimage encoding: origin image offset in x direction
# subimage encoding: origin image offset in y direction
("image_offset_x0", ctypes.c_int),
("image_offset_y0", ctypes.c_int),
# subsampling value for dx
# subsampling value for dy
("subsampling_dx", ctypes.c_int),
("subsampling_dy", ctypes.c_int),
# input file format 0: PGX, 1: PxM, 2: BMP 3:TIF
# output file format 0: J2K, 1: JP2, 2: JPT
("decod_format", ctypes.c_int),
("cod_format", ctypes.c_int),
# JPWL encoding parameters
# enables writing of EPC in MH, thus activating JPWL
("jpwl_epc_on", ctypes.c_int),
# error protection method for MH (0,1,16,32,37-128)
("jpwl_hprot_mh", ctypes.c_int),
# tile number of header protection specification (>=0)
("jpwl_hprot_tph_tileno", ctypes.c_int * JPWL_MAX_NO_TILESPECS),
# error protection methods for TPHs (0,1,16,32,37-128)
("jpwl_hprot_tph", ctypes.c_int * JPWL_MAX_NO_TILESPECS),
# tile number of packet protection specification (>=0)
("jpwl_pprot_tileno", ctypes.c_int * JPWL_MAX_NO_TILESPECS),
# packet number of packet protection specification (>=0)
("jpwl_pprot_packno", ctypes.c_int * JPWL_MAX_NO_TILESPECS),
# error protection methods for packets (0,1,16,32,37-128)
("jpwl_pprot", ctypes.c_int * JPWL_MAX_NO_TILESPECS),
# enables writing of ESD, (0=no/1/2 bytes)
("jpwl_sens_size", ctypes.c_int),
# sensitivity addressing size (0=auto/2/4 bytes)
("jpwl_sens_addr", ctypes.c_int),
# sensitivity range (0-3)
("jpwl_sens_range", ctypes.c_int),
# sensitivity method for MH (-1=no,0-7)
("jpwl_sens_mh", ctypes.c_int),
# tile number of sensitivity specification (>=0)
("jpwl_sens_tph_tileno", ctypes.c_int * JPWL_MAX_NO_TILESPECS),
# sensitivity methods for TPHs (-1=no,0-7)
("jpwl_sens_tph", ctypes.c_int * JPWL_MAX_NO_TILESPECS),
# Digital Cinema compliance 0-not compliant, 1-compliant
("cp_cinema", ctypes.c_int),
# Maximum rate for each component.
# If == 0, component size limitation is not considered
("max_comp_size", ctypes.c_int),
# Profile name
("cp_rsiz", ctypes.c_int),
# Tile part generation
("tp_on", ctypes.c_uint8),
# Flag for Tile part generation
("tp_flag", ctypes.c_uint8),
# MCT (multiple component transform)
("tcp_mct", ctypes.c_uint8),
# Enable JPIP indexing
("jpip_on", ctypes.c_int)]
class DecompressionInfoType(ctypes.Structure):
"""This is for decompression contexts.
Corresponds to dinfo_t type in openjpeg headers.
"""
pass
class DecompressionParametersType(ctypes.Structure):
"""Decompression parameters.
@ -111,23 +371,51 @@ class DecompressionParametersType(ctypes.Structure):
_fields_.append(("flags", ctypes.c_uint))
class ImageCompType(ctypes.Structure):
"""Defines a single image component.
Corresponds to image_comp_t type in openjpeg.
class ImageComptParmType(ctypes.Structure):
"""Component parameters structure used by the opj_image_create function.
"""
_fields_ = [("dx", ctypes.c_int),
("dy", ctypes.c_int),
("w", ctypes.c_int),
("h", ctypes.c_int),
("x0", ctypes.c_int),
("y0", ctypes.c_int),
("prec", ctypes.c_int),
("bpp", ctypes.c_int),
("sgnd", ctypes.c_int),
("resno_decoded", ctypes.c_int),
("factor", ctypes.c_int),
("data", ctypes.POINTER(ctypes.c_int))]
_fields_ = [
# XRsiz: horizontal separation of a sample of ith component with
# respect to the reference grid
("dx", ctypes.c_int),
# YRsiz: vertical separation of a sample of ith component with
# respect to the reference grid */
("dy", ctypes.c_int),
# data width, height
("w", ctypes.c_int),
("h", ctypes.c_int),
# x component offset compared to the whole image
# y component offset compared to the whole image
("x0", ctypes.c_int),
("y0", ctypes.c_int),
# precision
('prec', ctypes.c_int),
# image depth in bits
('bpp', ctypes.c_int),
# signed (1) / unsigned (0)
('sgnd', ctypes.c_int)]
class ImageCompType(ctypes.Structure):
"""Defines a single image component. """
_fields_ = [("dx", ctypes.c_int),
("dy", ctypes.c_int),
("w", ctypes.c_int),
("h", ctypes.c_int),
("x0", ctypes.c_int),
("y0", ctypes.c_int),
("prec", ctypes.c_int),
("bpp", ctypes.c_int),
("sgnd", ctypes.c_int),
("resno_decoded", ctypes.c_int),
("factor", ctypes.c_int),
("data", ctypes.POINTER(ctypes.c_int))]
class ImageType(ctypes.Structure):
@ -146,16 +434,22 @@ class ImageType(ctypes.Structure):
("icc_profile_len", ctypes.c_int)]
def cio_open(cinfo, src):
def cio_open(cinfo, src=None):
"""Wrapper for openjpeg library function opj_cio_open."""
argtypes = [ctypes.POINTER(CommonStructType), ctypes.c_char_p,
ctypes.c_int]
OPENJPEG.opj_cio_open.argtypes = argtypes
OPENJPEG.opj_cio_open.restype = ctypes.POINTER(CioType)
if src is None:
length = 0
else:
length = len(src)
cio = OPENJPEG.opj_cio_open(ctypes.cast(cinfo,
ctypes.POINTER(CommonStructType)),
src, len(src))
src,
length)
return cio
@ -166,6 +460,24 @@ def cio_close(cio):
OPENJPEG.opj_cio_close(cio)
def cio_tell(cio):
"""Get position in byte stream."""
OPENJPEG.cio_tell.argtypes = [ctypes.POINTER(CioType)]
OPENJPEG.cio_tell.restype = ctypes.c_int
pos = OPENJPEG.cio_tell(cio)
return pos
def create_compress(fmt):
"""Wrapper for openjpeg library function opj_create_compress.
Creates a J2K/JPT/JP2 compression structure.
"""
OPENJPEG.opj_create_compress.argtypes = [ctypes.c_int]
OPENJPEG.opj_create_compress.restype = ctypes.POINTER(CompressionInfoType)
cinfo = OPENJPEG.opj_create_compress(fmt)
return cinfo
def create_decompress(fmt):
"""Wraps openjpeg library function opj_create_decompress.
"""
@ -186,6 +498,39 @@ def decode(dinfo, cio):
return image
def destroy_compress(cinfo):
"""Wrapper for openjpeg library function opj_destroy_compress.
Release resources for a compressor handle.
"""
argtypes = [ctypes.POINTER(CompressionInfoType)]
OPENJPEG.opj_destroy_compress.argtypes = argtypes
OPENJPEG.opj_destroy_compress(cinfo)
def encode(cinfo, cio, image):
"""Wrapper for openjpeg library function opj_encode.
Encodes an image into a JPEG-2000 codestream.
Parameters
----------
cinfo : compression handle
cio : output buffer stream
image : image to encode
"""
argtypes = [ctypes.POINTER(CompressionInfoType),
ctypes.POINTER(CioType),
ctypes.POINTER(ImageType)]
OPENJPEG.opj_encode.argtypes = argtypes
OPENJPEG.opj_encode.restype = ctypes.c_int
status = OPENJPEG.opj_encode(cinfo, cio, image)
if not status:
raise RuntimeError("opj_encode failed")
def destroy_decompress(dinfo):
"""Wraps openjpeg library function opj_destroy_decompress."""
argtypes = [ctypes.POINTER(DecompressionInfoType)]
@ -193,12 +538,78 @@ def destroy_decompress(dinfo):
OPENJPEG.opj_destroy_decompress(dinfo)
def image_cmptparm_t_from_np(np_image):
"""Return appropriate image_cmptparm_t based on given numpy array.
"""
try:
num_comps = np_image.shape[2]
except IndexError:
num_comps = 1
cmpt_parm_array_t = ImageCmptparmType * num_comps
tarr = cmpt_parm_array_t()
if np_image.dtype == np.uint8:
prec = 8
bpp = 8
sgnd = 0
elif np_image.dtype == np.int8:
prec = 8
bpp = 8
sgnd = 1
elif np_image.dtype == np.uint16:
prec = 16
bpp = 16
sgnd = 0
elif np_image.dtype == np.int16:
prec = 16
bpp = 16
sgnd = 1
else:
raise(TypeError("unhandled"))
for j in range(0, num_comps):
tarr[j].dx = 1
tarr[j].dy = 1
tarr[j].w = np_image.shape[1]
tarr[j].h = np_image.shape[0]
tarr[j].x0 = 0
tarr[j].y0 = 0
tarr[j].prec = prec
tarr[j].bpp = bpp
tarr[j].sgnd = sgnd
return(tarr)
def image_create(cmptparms, cspace):
"""Wrapper for openjpeg library function opj_image_create.
"""
OPENJPEG.opj_image_create.argtypes = [ctypes.c_int,
ctypes.POINTER(ImageComptParmType),
ctypes.c_int]
OPENJPEG.opj_image_create.restype = ctypes.POINTER(ImageType)
image = OPENJPEG.opj_image_create(len(cmptparms), cmptparms, cspace)
return(image)
def image_destroy(image):
"""Wraps openjpeg library function opj_image_destroy."""
OPENJPEG.opj_image_destroy.argtypes = [ctypes.POINTER(ImageType)]
OPENJPEG.opj_image_destroy(image)
def set_default_encoder_parameters():
"""Wrapper for openjpeg library function opj_set_default_encoder_parameters.
"""
cparams = CompressionParametersType()
argtypes = [ctypes.POINTER(CompressionParametersType)]
OPENJPEG.opj_set_default_encoder_parameters.argtypes = argtypes
OPENJPEG.opj_set_default_encoder_parameters(ctypes.byref(cparams))
return cparams
def set_default_decoder_parameters(dparams_p):
"""Wrapper for opj_set_default_decoder_parameters.
"""
@ -219,6 +630,15 @@ def set_event_mgr(dinfo, event_mgr, context=None):
event_mgr, context)
def setup_encoder(cinfo, cparameters, image):
"""Wrapper for openjpeg library function opj_setup_decoder."""
argtypes = [ctypes.POINTER(CompressionInfoType),
ctypes.POINTER(CompressionParametersType),
ctypes.POINTER(ImageType)]
OPENJPEG.opj_setup_encoder.argtypes = argtypes
OPENJPEG.opj_setup_encoder(cinfo, cparameters, image)
def setup_decoder(dinfo, dparams):
"""Wrapper for openjpeg library function opj_setup_decoder."""
argtypes = [ctypes.POINTER(DecompressionInfoType),

View file

@ -679,6 +679,9 @@ class TestJp2k15(unittest.TestCase):
j2k.read(layer=1)
@unittest.skipIf(os.name == "nt", "NamedTemporaryFile issue on windows")
@unittest.skipIf(re.match(r"""1\.[01234]\.\d""",
OPENJPEG_VERSION) is not None,
"Writing only supported with openjpeg version 1.5+.")
def test_2d_rgb(self):
"""RGB must have at least 3 components."""
with tempfile.NamedTemporaryFile(suffix='.jp2') as tfile:

View file

@ -10,6 +10,7 @@ suite.
# pylint: disable=F0401
import os
import re
import sys
import tempfile
@ -19,15 +20,16 @@ else:
import unittest
from .fixtures import read_image, NO_READ_BACKEND, NO_READ_BACKEND_MSG
from .fixtures import OPJ_DATA_ROOT, opj_data_file
from .fixtures import OPJ_DATA_ROOT, OPENJPEG_VERSION, opj_data_file
from glymur import Jp2k
import glymur
@unittest.skipIf(os.name == "nt", "no write support on windows, period")
@unittest.skipIf(glymur.lib.openjp2.OPENJP2 is None,
"Missing openjp2 library.")
@unittest.skipIf(re.match(r"""1\.[01234]\.\d""",
OPENJPEG_VERSION) is not None,
"Writing only supported with openjpeg version 1.5+.")
@unittest.skipIf(NO_READ_BACKEND, NO_READ_BACKEND_MSG)
@unittest.skipIf(OPJ_DATA_ROOT is None,
"OPJ_DATA_ROOT environment variable not set")