#include "mplutils.h"
#include "_image.h"
#include "py_converters.h"
/**********************************************************************
* Image
* */
typedef struct
{
PyObject_HEAD;
Image *x;
Py_ssize_t shape[3];
Py_ssize_t strides[3];
Py_ssize_t suboffsets[3];
PyObject *dict;
} PyImage;
static PyTypeObject PyImageType;
static PyObject *PyImage_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
{
PyImage *self;
self = (PyImage *)type->tp_alloc(type, 0);
memset(self, 0, sizeof(PyImage));
self->x = NULL;
self->dict = PyDict_New();
return (PyObject *)self;
}
static PyObject *PyImage_cnew(Image *im)
{
PyImage *self;
self = (PyImage *)PyImageType.tp_alloc(&PyImageType, 0);
self->x = im;
self->dict = PyDict_New();
return (PyObject *)self;
}
static int PyImage_init(PyImage *self, PyObject *args, PyObject *kwds)
{
if (!PyArg_ParseTuple(args, "")) {
return -1;
}
CALL_CPP_INIT("Image", (self->x = new Image()));
return 0;
}
static void PyImage_dealloc(PyImage *self)
{
delete self->x;
Py_DECREF(self->dict);
Py_TYPE(self)->tp_free((PyObject *)self);
}
const char *PyImage_apply_rotation__doc__ =
"apply_rotation(angle)\n"
"\n"
"Apply the rotation (degrees) to image";
static PyObject *PyImage_apply_rotation(PyImage *self, PyObject *args, PyObject *kwds)
{
double r;
if (!PyArg_ParseTuple(args, "d:apply_rotation", &r)) {
return NULL;
}
CALL_CPP("apply_rotation", (self->x->apply_rotation(r)));
Py_RETURN_NONE;
}
const char *PyImage_set_bg__doc__ =
"set_bg(r,g,b,a)\n"
"\n"
"Set the background color";
static PyObject *PyImage_set_bg(PyImage *self, PyObject *args, PyObject *kwds)
{
double r, g, b, a;
if (!PyArg_ParseTuple(args, "dddd:set_bg", &r, &g, &b, &a)) {
return NULL;
}
CALL_CPP("set_bg", (self->x->set_bg(r, g, b, a)));
Py_RETURN_NONE;
}
const char *PyImage_apply_scaling__doc__ =
"apply_scaling(sx, sy)\n"
"\n"
"Apply the scale factors sx, sy to the transform matrix";
static PyObject *PyImage_apply_scaling(PyImage *self, PyObject *args, PyObject *kwds)
{
double sx, sy;
if (!PyArg_ParseTuple(args, "dd:apply_scaling", &sx, &sy)) {
return NULL;
}
CALL_CPP("apply_scaling", (self->x->apply_scaling(sx, sy)));
Py_RETURN_NONE;
}
const char *PyImage_apply_translation__doc__ =
"apply_translation(tx, ty)\n"
"\n"
"Apply the translation tx, ty to the transform matrix";
static PyObject *PyImage_apply_translation(PyImage *self, PyObject *args, PyObject *kwds)
{
double tx, ty;
if (!PyArg_ParseTuple(args, "dd:apply_translation", &tx, &ty)) {
return NULL;
}
CALL_CPP("apply_translation", self->x->apply_translation(tx, ty));
Py_RETURN_NONE;
}
const char *PyImage_as_rgba_str__doc__ =
"numrows, numcols, s = as_rgba_str()"
"\n"
"Call this function after resize to get the data as string\n"
"The string is a numrows by numcols x 4 (RGBA) unsigned char buffer\n";
static PyObject *PyImage_as_rgba_str(PyImage *self, PyObject *args, PyObject *kwds)
{
// TODO: This performs a copy. Use buffer interface when possible
PyObject *result = PyBytes_FromStringAndSize(NULL, self->x->rowsOut * self->x->colsOut * 4);
if (result == NULL) {
return NULL;
}
CALL_CPP_CLEANUP("as_rgba_str",
(self->x->as_rgba_str((agg::int8u *)PyBytes_AsString(result))),
Py_DECREF(result));
return Py_BuildValue("nnN", self->x->rowsOut, self->x->colsOut, result);
}
const char *PyImage_color_conv__doc__ =
"numrows, numcols, buffer = color_conv(format)"
"\n"
"format 0(BGRA) or 1(ARGB)\n"
"Convert image to format and return in a writable buffer\n";
// TODO: This function is a terrible interface. Change/remove? Only
// used by Cairo backend.
static PyObject *PyImage_color_conv(PyImage *self, PyObject *args, PyObject *kwds)
{
int format;
if (!PyArg_ParseTuple(args, "i:color_conv", &format)) {
return NULL;
}
Py_ssize_t size = self->x->rowsOut * self->x->colsOut * 4;
agg::int8u *buff = (agg::int8u *)malloc(size);
if (buff == NULL) {
PyErr_SetString(PyExc_MemoryError, "Out of memory");
return NULL;
}
CALL_CPP_CLEANUP("color_conv",
(self->x->color_conv(format, buff)),
free(buff));
PyObject *result = PyByteArray_FromStringAndSize((const char *)buff, size);
if (result == NULL) {
free(buff);
return NULL;
}
return Py_BuildValue("nnN", self->x->rowsOut, self->x->colsOut, result);
}
const char *PyImage_buffer_rgba__doc__ =
"buffer = buffer_rgba()"
"\n"
"Return the image buffer as rgba32\n";
static PyObject *PyImage_buffer_rgba(PyImage *self, PyObject *args, PyObject *kwds)
{
#if PY3K
return Py_BuildValue("nny#",
self->x->rowsOut,
self->x->colsOut,
self->x->rbufOut,
self->x->rowsOut * self->x->colsOut * 4);
#else
PyObject *buffer =
PyBuffer_FromReadWriteMemory(self->x->rbufOut, self->x->rowsOut * self->x->colsOut * 4);
if (buffer == NULL) {
return NULL;
}
return Py_BuildValue("nnN", self->x->rowsOut, self->x->colsOut, buffer);
#endif
}
const char *PyImage_reset_matrix__doc__ =
"reset_matrix()"
"\n"
"Reset the transformation matrix";
static PyObject *PyImage_reset_matrix(PyImage *self, PyObject *args, PyObject *kwds)
{
CALL_CPP("reset_matrix", self->x->reset_matrix());
Py_RETURN_NONE;
}
const char *PyImage_get_matrix__doc__ =
"(m11,m21,m12,m22,m13,m23) = get_matrix()\n"
"\n"
"Get the affine transformation matrix\n"
" /m11,m12,m13\\\n"
" /m21,m22,m23|\n"
" \\ 0 , 0 , 1 /";
static PyObject *PyImage_get_matrix(PyImage *self, PyObject *args, PyObject *kwds)
{
double m[6];
self->x->srcMatrix.store_to(m);
return Py_BuildValue("dddddd", m[0], m[1], m[2], m[3], m[4], m[5]);
}
const char *PyImage_resize__doc__ =
"resize(width, height, norm=1, radius=4.0)\n"
"\n"
"Resize the image to width, height using interpolation\n"
"norm and radius are optional args for some of the filters\n";
static PyObject *PyImage_resize(PyImage *self, PyObject *args, PyObject *kwds)
{
double width;
double height;
double norm;
double radius;
const char *names[] = { "width", "height", "norm", "radius", NULL };
if (!PyArg_ParseTupleAndKeywords(
args, kwds, "dd|dd:resize", (char **)names, &width, &height, &norm, &radius)) {
return NULL;
}
CALL_CPP("resize", (self->x->resize(width, height, norm, radius)));
Py_RETURN_NONE;
}
const char *PyImage_get_interpolation__doc__ =
"get_interpolation()\n"
"\n"
"Get the interpolation scheme to one of the module constants, "
"one of image.NEAREST, image.BILINEAR, etc...";
static PyObject *PyImage_get_interpolation(PyImage *self, PyObject *args, PyObject *kwds)
{
return PyLong_FromLong(self->x->interpolation);
}
const char *PyImage_set_interpolation__doc__ =
"set_interpolation(scheme)\n"
"\n"
"Set the interpolation scheme to one of the module constants, "
"eg, image.NEAREST, image.BILINEAR, etc...";
static PyObject *PyImage_set_interpolation(PyImage *self, PyObject *args, PyObject *kwds)
{
int method;
if (!PyArg_ParseTuple(args, "i:set_interpolation", &method)) {
return NULL;
}
self->x->interpolation = method;
Py_RETURN_NONE;
}
const char *PyImage_get_aspect__doc__ =
"get_aspect()\n"
"\n"
"Get the aspect constraint constants";
static PyObject *PyImage_get_aspect(PyImage *self, PyObject *args, PyObject *kwds)
{
return PyLong_FromLong(self->x->aspect);
}
const char *PyImage_set_aspect__doc__ =
"set_aspect(scheme)\n"
"\n"
"Set the aspect ratio to one of the image module constant."
"eg, one of image.ASPECT_PRESERVE, image.ASPECT_FREE";
static PyObject *PyImage_set_aspect(PyImage *self, PyObject *args, PyObject *kwds)
{
int scheme;
if (!PyArg_ParseTuple(args, "i:set_aspect", &scheme)) {
return NULL;
}
self->x->aspect = scheme;
Py_RETURN_NONE;
}
const char *PyImage_get_size__doc__ =
"numrows, numcols = get_size()\n"
"\n"
"Get the number or rows and columns of the input image";
static PyObject *PyImage_get_size(PyImage *self, PyObject *args, PyObject *kwds)
{
return Py_BuildValue("ii", self->x->rowsIn, self->x->colsIn);
}
const char *PyImage_get_resample__doc__ =
"get_resample()\n"
"\n"
"Get the resample flag.";
static PyObject *PyImage_get_resample(PyImage *self, PyObject *args, PyObject *kwds)
{
if (self->x->resample) {
Py_RETURN_TRUE;
}
Py_RETURN_FALSE;
}
const char *PyImage_set_resample__doc__ =
"set_resample(boolean)\n"
"\n"
"Set the resample flag.";
static PyObject *PyImage_set_resample(PyImage *self, PyObject *args, PyObject *kwds)
{
int resample;
if (!PyArg_ParseTuple(args, "i:set_resample", &resample)) {
return NULL;
}
self->x->resample = resample;
Py_RETURN_NONE;
}
const char *PyImage_get_size_out__doc__ =
"numrows, numcols = get_size_out()\n"
"\n"
"Get the number or rows and columns of the output image";
static PyObject *PyImage_get_size_out(PyImage *self, PyObject *args, PyObject *kwds)
{
return Py_BuildValue("ii", self->x->rowsOut, self->x->colsOut);
}
static int PyImage_get_buffer(PyImage *self, Py_buffer *buf, int flags)
{
Image *im = self->x;
Py_INCREF(self);
buf->obj = (PyObject *)self;
buf->buf = im->bufferOut;
buf->len = im->colsOut * im->rowsOut * 4;
buf->readonly = 0;
buf->format = (char *)"B";
buf->ndim = 3;
self->shape[0] = im->rowsOut;
self->shape[1] = im->colsOut;
self->shape[2] = 4;
buf->shape = self->shape;
self->strides[0] = im->colsOut * 4;
self->strides[1] = 4;
self->strides[2] = 1;
buf->strides = self->strides;
buf->suboffsets = NULL;
buf->itemsize = 1;
buf->internal = NULL;
return 1;
}
static PyTypeObject *PyImage_init_type(PyObject *m, PyTypeObject *type)
{
static PyMethodDef methods[] = {
{"apply_rotation", (PyCFunction)PyImage_apply_rotation, METH_VARARGS, PyImage_apply_rotation__doc__},
{"set_bg", (PyCFunction)PyImage_set_bg, METH_VARARGS, PyImage_set_bg__doc__},
{"apply_scaling", (PyCFunction)PyImage_apply_scaling, METH_VARARGS, PyImage_apply_scaling__doc__},
{"apply_translation", (PyCFunction)PyImage_apply_translation, METH_VARARGS, PyImage_apply_translation__doc__},
{"as_rgba_str", (PyCFunction)PyImage_as_rgba_str, METH_NOARGS, PyImage_as_rgba_str__doc__},
{"color_conv", (PyCFunction)PyImage_color_conv, METH_VARARGS, PyImage_color_conv__doc__},
{"buffer_rgba", (PyCFunction)PyImage_buffer_rgba, METH_NOARGS, PyImage_buffer_rgba__doc__},
{"reset_matrix", (PyCFunction)PyImage_reset_matrix, METH_NOARGS, PyImage_reset_matrix__doc__},
{"get_matrix", (PyCFunction)PyImage_get_matrix, METH_NOARGS, PyImage_get_matrix__doc__},
{"resize", (PyCFunction)PyImage_resize, METH_VARARGS|METH_KEYWORDS, PyImage_resize__doc__},
{"get_interpolation", (PyCFunction)PyImage_get_interpolation, METH_NOARGS, PyImage_get_interpolation__doc__},
{"set_interpolation", (PyCFunction)PyImage_set_interpolation, METH_VARARGS, PyImage_set_interpolation__doc__},
{"get_aspect", (PyCFunction)PyImage_get_aspect, METH_NOARGS, PyImage_get_aspect__doc__},
{"set_aspect", (PyCFunction)PyImage_set_aspect, METH_VARARGS, PyImage_set_aspect__doc__},
{"get_size", (PyCFunction)PyImage_get_size, METH_NOARGS, PyImage_get_size__doc__},
{"get_resample", (PyCFunction)PyImage_get_resample, METH_VARARGS, PyImage_get_resample__doc__},
{"set_resample", (PyCFunction)PyImage_set_resample, METH_VARARGS, PyImage_set_resample__doc__},
{"get_size_out", (PyCFunction)PyImage_get_size_out, METH_VARARGS, PyImage_get_size_out__doc__},
{NULL}
};
static PyBufferProcs buffer_procs;
memset(&buffer_procs, 0, sizeof(PyBufferProcs));
buffer_procs.bf_getbuffer = (getbufferproc)PyImage_get_buffer;
memset(type, 0, sizeof(PyTypeObject));
type->tp_name = "matplotlib._image.Image";
type->tp_basicsize = sizeof(PyImage);
type->tp_dealloc = (destructor)PyImage_dealloc;
type->tp_flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | Py_TPFLAGS_HAVE_NEWBUFFER;
type->tp_methods = methods;
type->tp_new = PyImage_new;
type->tp_init = (initproc)PyImage_init;
type->tp_as_buffer = &buffer_procs;
type->tp_dictoffset = offsetof(PyImage, dict);
if (PyType_Ready(type) < 0) {
return NULL;
}
if (PyModule_AddObject(m, "Image", (PyObject *)type)) {
return NULL;
}
return type;
}
/**********************************************************************
* Free functions
* */
const char *image_from_images__doc__ =
"from_images(numrows, numcols, seq)\n"
"\n"
"return an image instance with numrows, numcols from a seq of image\n"
"instances using alpha blending. seq is a list of (Image, ox, oy)";
static PyObject *image_from_images(PyObject *self, PyObject *args, PyObject *kwds)
{
unsigned int numrows;
unsigned int numcols;
PyObject *images;
size_t numimages;
if (!PyArg_ParseTuple(args, "IIO:from_images", &numrows, &numcols, &images)) {
return NULL;
}
if (!PySequence_Check(images)) {
return NULL;
}
Image *im = new Image(numrows, numcols, true);
im->clear();
numimages = PySequence_Size(images);
for (size_t i = 0; i < numimages; ++i) {
PyObject *entry = PySequence_GetItem(images, i);
if (entry == NULL) {
delete im;
return NULL;
}
PyObject *subimage;
unsigned int x;
unsigned int y;
PyObject *alphaobj = NULL;
double alpha = 0.0;
if (!PyArg_ParseTuple(entry, "O!II|O", &PyImageType, &subimage, &x, &y, &alphaobj)) {
Py_DECREF(entry);
delete im;
return NULL;
}
bool has_alpha = false;
if (alphaobj != NULL && alphaobj != Py_None) {
has_alpha = true;
alpha = PyFloat_AsDouble(alphaobj);
if (PyErr_Occurred()) {
Py_DECREF(entry);
delete im;
return NULL;
}
}
CALL_CPP("from_images",
(im->blend_image(*((PyImage *)subimage)->x, x, y, has_alpha, alpha)));
Py_DECREF(entry);
}
return PyImage_cnew(im);
}
const char *image_fromarray__doc__ =
"fromarray(A, isoutput)\n"
"\n"
"Load the image from a numpy array\n"
"By default this function fills the input buffer, which can subsequently\n"
"be resampled using resize. If isoutput=1, fill the output buffer.\n"
"This is used to support raw pixel images w/o resampling\n";
static PyObject *image_fromarray(PyObject *self, PyObject *args, PyObject *kwds)
{
PyObject *array;
int isoutput;
const char *names[] = { "array", "isoutput", NULL };
if (!PyArg_ParseTupleAndKeywords(
args, kwds, "O|i:fromarray", (char **)names, &array, &isoutput)) {
return NULL;
}
numpy::array_view color_array;
numpy::array_view grey_array;
Image *result = NULL;
if (color_array.converter(array, &color_array)) {
CALL_CPP("fromarray", result = from_color_array(color_array, isoutput));
} else if (grey_array.converter(array, &grey_array)) {
CALL_CPP("fromarray", result = from_grey_array(grey_array, isoutput));
} else {
PyErr_SetString(PyExc_ValueError, "invalid array");
return NULL;
}
return PyImage_cnew(result);
}
const char *image_frombyte__doc__ =
"frombyte(A, isoutput)\n"
"\n"
"Load the image from a byte array.\n"
"By default this function fills the input buffer, which can subsequently\n"
"be resampled using resize. If isoutput=1, fill the output buffer.\n"
"This is used to support raw pixel images w/o resampling.";
static PyObject *image_frombyte(PyObject *self, PyObject *args, PyObject *kwds)
{
numpy::array_view array;
int isoutput;
const char *names[] = { "array", "isoutput", NULL };
Image *result;
if (!PyArg_ParseTupleAndKeywords(args,
kwds,
"O&|i:frombyte",
(char **)names,
&array.converter,
&array,
&isoutput)) {
return NULL;
}
CALL_CPP("frombyte", (result = frombyte(array, isoutput)));
return PyImage_cnew(result);
}
const char *image_frombuffer__doc__ =
"frombuffer(buffer, width, height, isoutput)\n"
"\n"
"Load the image from a character buffer\n"
"By default this function fills the input buffer, which can subsequently\n"
"be resampled using resize. If isoutput=1, fill the output buffer.\n"
"This is used to support raw pixel images w/o resampling.";
static PyObject *image_frombuffer(PyObject *self, PyObject *args, PyObject *kwds)
{
PyObject *buffer;
unsigned x;
unsigned y;
int isoutput;
const char *names[] = { "buffer", "x", "y", "isoutput", NULL };
if (!PyArg_ParseTupleAndKeywords(
args, kwds, "OII|i:frombuffer", (char **)names, &buffer, &x, &y, &isoutput)) {
return NULL;
}
const void *rawbuf;
Py_ssize_t buflen;
if (PyObject_AsReadBuffer(buffer, &rawbuf, &buflen) != 0) {
return NULL;
}
if (buflen != (Py_ssize_t)(y * x * 4)) {
PyErr_SetString(PyExc_ValueError, "Buffer is incorrect length");
return NULL;
}
Image *im;
CALL_CPP("frombuffer", (im = new Image(y, x, isoutput)));
agg::int8u *inbuf = (agg::int8u *)rawbuf;
agg::int8u *outbuf;
if (isoutput) {
outbuf = im->bufferOut;
} else {
outbuf = im->bufferIn;
}
for (int i = (x * 4) * (y - 1); i >= 0; i -= (x * 4)) {
memmove(outbuf, &inbuf[i], (x * 4));
outbuf += x * 4;
}
return PyImage_cnew(im);
}
const char *image_pcolor__doc__ =
"pcolor(x, y, data, rows, cols, bounds)\n"
"\n"
"Generate a pseudo-color image from data on a non-uniform grid using\n"
"nearest neighbour or linear interpolation.\n"
"bounds = (x_min, x_max, y_min, y_max)\n"
"interpolation = NEAREST or BILINEAR \n";
static PyObject *image_pcolor(PyObject *self, PyObject *args, PyObject *kwds)
{
numpy::array_view x;
numpy::array_view y;
numpy::array_view d;
unsigned int rows;
unsigned int cols;
float bounds[4];
int interpolation;
Image *result;
if (!PyArg_ParseTuple(args,
"O&O&O&II(ffff)i:pcolor",
&x.converter,
&x,
&y.converter,
&y,
&d.converter_contiguous,
&d,
&rows,
&cols,
&bounds[0],
&bounds[1],
&bounds[2],
&bounds[3],
&interpolation)) {
return NULL;
}
CALL_CPP("pcolor", (result = pcolor(x, y, d, rows, cols, bounds, interpolation)));
return PyImage_cnew(result);
}
const char *image_pcolor2__doc__ =
"pcolor2(x, y, data, rows, cols, bounds, bg)\n"
"\n"
"Generate a pseudo-color image from data on a non-uniform grid\n"
"specified by its cell boundaries.\n"
"bounds = (x_left, x_right, y_bot, y_top)\n"
"bg = ndarray of 4 uint8 representing background rgba\n";
static PyObject *image_pcolor2(PyObject *self, PyObject *args, PyObject *kwds)
{
numpy::array_view x;
numpy::array_view y;
numpy::array_view d;
unsigned int rows;
unsigned int cols;
float bounds[4];
numpy::array_view bg;
Image *result;
if (!PyArg_ParseTuple(args,
"O&O&O&II(ffff)O&:pcolor2",
&x.converter,
&x,
&y.converter,
&y,
&d.converter_contiguous,
&d,
&rows,
&cols,
&bounds[0],
&bounds[1],
&bounds[2],
&bounds[3],
&bg.converter,
&bg)) {
return NULL;
}
CALL_CPP("pcolor2", (result = pcolor2(x, y, d, rows, cols, bounds, bg)));
return PyImage_cnew(result);
}
static PyMethodDef module_functions[] = {
{"from_images", (PyCFunction)image_from_images, METH_VARARGS, image_from_images__doc__},
{"fromarray", (PyCFunction)image_fromarray, METH_VARARGS|METH_KEYWORDS, image_fromarray__doc__},
{"frombyte", (PyCFunction)image_frombyte, METH_VARARGS|METH_KEYWORDS, image_frombyte__doc__},
{"frombuffer", (PyCFunction)image_frombuffer, METH_VARARGS|METH_KEYWORDS, image_frombuffer__doc__},
{"pcolor", (PyCFunction)image_pcolor, METH_VARARGS, image_pcolor__doc__},
{"pcolor2", (PyCFunction)image_pcolor2, METH_VARARGS, image_pcolor2__doc__},
{NULL}
};
extern "C" {
struct module_state
{
int _dummy;
};
#if PY3K
static struct PyModuleDef moduledef = {
PyModuleDef_HEAD_INIT,
"_image",
NULL,
sizeof(struct module_state),
module_functions,
NULL,
NULL,
NULL,
NULL
};
#define INITERROR return NULL
PyMODINIT_FUNC PyInit__image(void)
#else
#define INITERROR return
PyMODINIT_FUNC init_image(void)
#endif
{
PyObject *m;
#if PY3K
m = PyModule_Create(&moduledef);
#else
m = Py_InitModule3("_image", module_functions, NULL);
#endif
if (m == NULL) {
INITERROR;
}
if (!PyImage_init_type(m, &PyImageType)) {
INITERROR;
}
PyObject *d = PyModule_GetDict(m);
if (add_dict_int(d, "NEAREST", Image::NEAREST) ||
add_dict_int(d, "BILINEAR", Image::BILINEAR) ||
add_dict_int(d, "BICUBIC", Image::BICUBIC) ||
add_dict_int(d, "SPLINE16", Image::SPLINE16) ||
add_dict_int(d, "SPLINE36", Image::SPLINE36) ||
add_dict_int(d, "HANNING", Image::HANNING) ||
add_dict_int(d, "HAMMING", Image::HAMMING) ||
add_dict_int(d, "HERMITE", Image::HERMITE) ||
add_dict_int(d, "KAISER", Image::KAISER) ||
add_dict_int(d, "QUADRIC", Image::QUADRIC) ||
add_dict_int(d, "CATROM", Image::CATROM) ||
add_dict_int(d, "GAUSSIAN", Image::GAUSSIAN) ||
add_dict_int(d, "BESSEL", Image::BESSEL) ||
add_dict_int(d, "MITCHELL", Image::MITCHELL) ||
add_dict_int(d, "SINC", Image::SINC) ||
add_dict_int(d, "LANCZOS", Image::LANCZOS) ||
add_dict_int(d, "BLACKMAN", Image::BLACKMAN) ||
add_dict_int(d, "ASPECT_FREE", Image::ASPECT_FREE) ||
add_dict_int(d, "ASPECT_PRESERVE", Image::ASPECT_PRESERVE)) {
INITERROR;
}
import_array();
#if PY3K
return m;
#endif
}
} // extern "C"