Pillow/encode.c

958 lines
28 KiB
C
Raw Normal View History

2010-07-31 06:52:47 +04:00
/*
* The Python Imaging Library.
*
* standard encoder interfaces for the Imaging library
*
* History:
* 1996-04-19 fl Based on decoders.c
* 1996-05-12 fl Compile cleanly as C++
* 1996-12-30 fl Plugged potential memory leak for tiled images
* 1997-01-03 fl Added GIF encoder
* 1997-01-05 fl Plugged encoder buffer leaks
* 1997-01-11 fl Added encode_to_file method
* 1998-03-09 fl Added mode/rawmode argument to encoders
* 1998-07-09 fl Added interlace argument to GIF encoder
* 1999-02-07 fl Added PCX encoder
*
* Copyright (c) 1997-2001 by Secret Labs AB
* Copyright (c) 1996-1997 by Fredrik Lundh
2010-07-31 06:52:47 +04:00
*
* See the README file for information on usage and redistribution.
*/
/* FIXME: make these pluggable! */
#include "Python.h"
#include "Imaging.h"
#include "py3.h"
2010-07-31 06:52:47 +04:00
#include "Gif.h"
#ifdef HAVE_UNISTD_H
#include <unistd.h> /* write */
#endif
/* -------------------------------------------------------------------- */
2014-03-04 08:43:47 +04:00
/* Common */
2010-07-31 06:52:47 +04:00
/* -------------------------------------------------------------------- */
typedef struct {
PyObject_HEAD
int (*encode)(Imaging im, ImagingCodecState state,
2014-03-04 08:43:47 +04:00
UINT8* buffer, int bytes);
2014-03-13 22:27:16 +04:00
int (*cleanup)(ImagingCodecState state);
2010-07-31 06:52:47 +04:00
struct ImagingCodecStateInstance state;
Imaging im;
PyObject* lock;
} ImagingEncoderObject;
static PyTypeObject ImagingEncoderType;
2010-07-31 06:52:47 +04:00
static ImagingEncoderObject*
PyImaging_EncoderNew(int contextsize)
{
ImagingEncoderObject *encoder;
void *context;
if(!PyType_Ready(&ImagingEncoderType) < 0)
return NULL;
2010-07-31 06:52:47 +04:00
encoder = PyObject_New(ImagingEncoderObject, &ImagingEncoderType);
if (encoder == NULL)
2014-03-04 08:43:47 +04:00
return NULL;
2010-07-31 06:52:47 +04:00
/* Clear the encoder state */
memset(&encoder->state, 0, sizeof(encoder->state));
/* Allocate encoder context */
if (contextsize > 0) {
2014-03-04 08:43:47 +04:00
context = (void*) calloc(1, contextsize);
if (!context) {
Py_DECREF(encoder);
(void) PyErr_NoMemory();
return NULL;
}
2010-07-31 06:52:47 +04:00
} else
2014-03-04 08:43:47 +04:00
context = 0;
2010-07-31 06:52:47 +04:00
/* Initialize encoder context */
encoder->state.context = context;
2014-03-13 22:27:16 +04:00
/* Most encoders don't need this */
encoder->cleanup = NULL;
2010-07-31 06:52:47 +04:00
/* Target image */
encoder->lock = NULL;
encoder->im = NULL;
return encoder;
}
static void
_dealloc(ImagingEncoderObject* encoder)
{
2014-03-13 22:27:16 +04:00
if (encoder->cleanup)
encoder->cleanup(&encoder->state);
2010-07-31 06:52:47 +04:00
free(encoder->state.buffer);
free(encoder->state.context);
Py_XDECREF(encoder->lock);
PyObject_Del(encoder);
}
static PyObject*
2010-07-31 06:52:47 +04:00
_encode(ImagingEncoderObject* encoder, PyObject* args)
{
PyObject* buf;
PyObject* result;
int status;
/* Encode to a Python string (allocated by this method) */
int bufsize = 16384;
if (!PyArg_ParseTuple(args, "|i", &bufsize))
2014-03-04 08:43:47 +04:00
return NULL;
2010-07-31 06:52:47 +04:00
buf = PyBytes_FromStringAndSize(NULL, bufsize);
2010-07-31 06:52:47 +04:00
if (!buf)
2014-03-04 08:43:47 +04:00
return NULL;
2010-07-31 06:52:47 +04:00
status = encoder->encode(encoder->im, &encoder->state,
2014-03-04 08:43:47 +04:00
(UINT8*) PyBytes_AsString(buf), bufsize);
2010-07-31 06:52:47 +04:00
/* adjust string length to avoid slicing in encoder */
if (_PyBytes_Resize(&buf, (status > 0) ? status : 0) < 0)
2010-07-31 06:52:47 +04:00
return NULL;
result = Py_BuildValue("iiO", status, encoder->state.errcode, buf);
Py_DECREF(buf); /* must release buffer!!! */
return result;
}
static PyObject*
2010-07-31 06:52:47 +04:00
_encode_to_file(ImagingEncoderObject* encoder, PyObject* args)
{
UINT8* buf;
int status;
ImagingSectionCookie cookie;
/* Encode to a file handle */
int fh;
int bufsize = 16384;
if (!PyArg_ParseTuple(args, "i|i", &fh, &bufsize))
2014-03-04 08:43:47 +04:00
return NULL;
2010-07-31 06:52:47 +04:00
/* Allocate an encoder buffer */
buf = (UINT8*) malloc(bufsize);
if (!buf)
2014-03-04 08:43:47 +04:00
return PyErr_NoMemory();
2010-07-31 06:52:47 +04:00
ImagingSectionEnter(&cookie);
do {
2014-03-04 08:43:47 +04:00
/* This replaces the inner loop in the ImageFile _save
function. */
2010-07-31 06:52:47 +04:00
2014-03-04 08:43:47 +04:00
status = encoder->encode(encoder->im, &encoder->state, buf, bufsize);
2010-07-31 06:52:47 +04:00
2014-03-04 08:43:47 +04:00
if (status > 0)
if (write(fh, buf, status) < 0) {
2010-07-31 06:52:47 +04:00
ImagingSectionLeave(&cookie);
2014-03-04 08:43:47 +04:00
free(buf);
return PyErr_SetFromErrno(PyExc_IOError);
}
2010-07-31 06:52:47 +04:00
} while (encoder->state.errcode == 0);
ImagingSectionLeave(&cookie);
free(buf);
return Py_BuildValue("i", encoder->state.errcode);
}
extern Imaging PyImaging_AsImaging(PyObject *op);
static PyObject*
_setimage(ImagingEncoderObject* encoder, PyObject* args)
{
PyObject* op;
Imaging im;
ImagingCodecState state;
int x0, y0, x1, y1;
/* Define where image data should be stored */
x0 = y0 = x1 = y1 = 0;
/* FIXME: should publish the ImagingType descriptor */
if (!PyArg_ParseTuple(args, "O|(iiii)", &op, &x0, &y0, &x1, &y1))
2014-03-04 08:43:47 +04:00
return NULL;
2010-07-31 06:52:47 +04:00
im = PyImaging_AsImaging(op);
if (!im)
2014-03-04 08:43:47 +04:00
return NULL;
2010-07-31 06:52:47 +04:00
encoder->im = im;
state = &encoder->state;
if (x0 == 0 && x1 == 0) {
2014-03-04 08:43:47 +04:00
state->xsize = im->xsize;
state->ysize = im->ysize;
2010-07-31 06:52:47 +04:00
} else {
2014-03-04 08:43:47 +04:00
state->xoff = x0;
state->yoff = y0;
state->xsize = x1 - x0;
state->ysize = y1 - y0;
2010-07-31 06:52:47 +04:00
}
if (state->xsize <= 0 ||
2014-03-04 08:43:47 +04:00
state->xsize + state->xoff > im->xsize ||
state->ysize <= 0 ||
state->ysize + state->yoff > im->ysize) {
PyErr_SetString(PyExc_SystemError, "tile cannot extend outside image");
return NULL;
2010-07-31 06:52:47 +04:00
}
/* Allocate memory buffer (if bits field is set) */
if (state->bits > 0) {
2014-03-04 08:43:47 +04:00
state->bytes = (state->bits * state->xsize+7)/8;
state->buffer = (UINT8*) malloc(state->bytes);
if (!state->buffer)
return PyErr_NoMemory();
2010-07-31 06:52:47 +04:00
}
/* Keep a reference to the image object, to make sure it doesn't
go away before we do */
Py_INCREF(op);
Py_XDECREF(encoder->lock);
encoder->lock = op;
Py_INCREF(Py_None);
return Py_None;
}
static struct PyMethodDef methods[] = {
{"encode", (PyCFunction)_encode, 1},
{"encode_to_file", (PyCFunction)_encode_to_file, 1},
{"setimage", (PyCFunction)_setimage, 1},
{NULL, NULL} /* sentinel */
};
static PyTypeObject ImagingEncoderType = {
2014-03-04 08:43:47 +04:00
PyVarObject_HEAD_INIT(NULL, 0)
"ImagingEncoder", /*tp_name*/
sizeof(ImagingEncoderObject), /*tp_size*/
0, /*tp_itemsize*/
/* methods */
(destructor)_dealloc, /*tp_dealloc*/
0, /*tp_print*/
0, /*tp_getattr*/
0, /*tp_setattr*/
0, /*tp_compare*/
0, /*tp_repr*/
0, /*tp_as_number */
0, /*tp_as_sequence */
0, /*tp_as_mapping */
0, /*tp_hash*/
0, /*tp_call*/
0, /*tp_str*/
0, /*tp_getattro*/
0, /*tp_setattro*/
0, /*tp_as_buffer*/
Py_TPFLAGS_DEFAULT, /*tp_flags*/
0, /*tp_doc*/
0, /*tp_traverse*/
0, /*tp_clear*/
0, /*tp_richcompare*/
0, /*tp_weaklistoffset*/
0, /*tp_iter*/
0, /*tp_iternext*/
methods, /*tp_methods*/
0, /*tp_members*/
0, /*tp_getset*/
2010-07-31 06:52:47 +04:00
};
/* -------------------------------------------------------------------- */
int
get_packer(ImagingEncoderObject* encoder, const char* mode,
const char* rawmode)
{
int bits;
ImagingShuffler pack;
pack = ImagingFindPacker(mode, rawmode, &bits);
if (!pack) {
2014-03-04 08:43:47 +04:00
Py_DECREF(encoder);
PyErr_SetString(PyExc_SystemError, "unknown raw mode");
return -1;
2010-07-31 06:52:47 +04:00
}
encoder->state.shuffle = pack;
encoder->state.bits = bits;
return 0;
}
/* -------------------------------------------------------------------- */
2014-03-04 08:43:47 +04:00
/* EPS */
2010-07-31 06:52:47 +04:00
/* -------------------------------------------------------------------- */
PyObject*
PyImaging_EpsEncoderNew(PyObject* self, PyObject* args)
{
ImagingEncoderObject* encoder;
encoder = PyImaging_EncoderNew(0);
if (encoder == NULL)
2014-03-04 08:43:47 +04:00
return NULL;
2010-07-31 06:52:47 +04:00
encoder->encode = ImagingEpsEncode;
return (PyObject*) encoder;
}
/* -------------------------------------------------------------------- */
2014-03-04 08:43:47 +04:00
/* GIF */
2010-07-31 06:52:47 +04:00
/* -------------------------------------------------------------------- */
PyObject*
PyImaging_GifEncoderNew(PyObject* self, PyObject* args)
{
ImagingEncoderObject* encoder;
char *mode;
char *rawmode;
int bits = 8;
int interlace = 0;
if (!PyArg_ParseTuple(args, "ss|ii", &mode, &rawmode, &bits, &interlace))
2014-03-04 08:43:47 +04:00
return NULL;
2010-07-31 06:52:47 +04:00
encoder = PyImaging_EncoderNew(sizeof(GIFENCODERSTATE));
if (encoder == NULL)
2014-03-04 08:43:47 +04:00
return NULL;
2010-07-31 06:52:47 +04:00
if (get_packer(encoder, mode, rawmode) < 0)
2014-03-04 08:43:47 +04:00
return NULL;
2010-07-31 06:52:47 +04:00
encoder->encode = ImagingGifEncode;
((GIFENCODERSTATE*)encoder->state.context)->bits = bits;
((GIFENCODERSTATE*)encoder->state.context)->interlace = interlace;
return (PyObject*) encoder;
}
/* -------------------------------------------------------------------- */
2014-03-04 08:43:47 +04:00
/* PCX */
2010-07-31 06:52:47 +04:00
/* -------------------------------------------------------------------- */
PyObject*
PyImaging_PcxEncoderNew(PyObject* self, PyObject* args)
{
ImagingEncoderObject* encoder;
char *mode;
char *rawmode;
int bits = 8;
2014-03-04 08:43:47 +04:00
if (!PyArg_ParseTuple(args, "ss|ii", &mode, &rawmode, &bits)) {
return NULL;
}
2010-07-31 06:52:47 +04:00
encoder = PyImaging_EncoderNew(0);
2014-03-04 08:43:47 +04:00
if (encoder == NULL) {
return NULL;
}
2010-07-31 06:52:47 +04:00
2014-03-04 08:43:47 +04:00
if (get_packer(encoder, mode, rawmode) < 0) {
return NULL;
}
2010-07-31 06:52:47 +04:00
encoder->encode = ImagingPcxEncode;
return (PyObject*) encoder;
}
/* -------------------------------------------------------------------- */
2014-03-04 08:43:47 +04:00
/* RAW */
2010-07-31 06:52:47 +04:00
/* -------------------------------------------------------------------- */
PyObject*
PyImaging_RawEncoderNew(PyObject* self, PyObject* args)
{
ImagingEncoderObject* encoder;
char *mode;
char *rawmode;
int stride = 0;
int ystep = 1;
if (!PyArg_ParseTuple(args, "ss|ii", &mode, &rawmode, &stride, &ystep))
2014-03-04 08:43:47 +04:00
return NULL;
2010-07-31 06:52:47 +04:00
encoder = PyImaging_EncoderNew(0);
if (encoder == NULL)
2014-03-04 08:43:47 +04:00
return NULL;
2010-07-31 06:52:47 +04:00
if (get_packer(encoder, mode, rawmode) < 0)
2014-03-04 08:43:47 +04:00
return NULL;
2010-07-31 06:52:47 +04:00
encoder->encode = ImagingRawEncode;
encoder->state.ystep = ystep;
encoder->state.count = stride;
return (PyObject*) encoder;
}
/* -------------------------------------------------------------------- */
2014-03-04 08:43:47 +04:00
/* XBM */
2010-07-31 06:52:47 +04:00
/* -------------------------------------------------------------------- */
PyObject*
PyImaging_XbmEncoderNew(PyObject* self, PyObject* args)
{
ImagingEncoderObject* encoder;
encoder = PyImaging_EncoderNew(0);
if (encoder == NULL)
2014-03-04 08:43:47 +04:00
return NULL;
2010-07-31 06:52:47 +04:00
if (get_packer(encoder, "1", "1;R") < 0)
2014-03-04 08:43:47 +04:00
return NULL;
2010-07-31 06:52:47 +04:00
encoder->encode = ImagingXbmEncode;
return (PyObject*) encoder;
}
/* -------------------------------------------------------------------- */
2014-03-04 08:43:47 +04:00
/* ZIP */
2010-07-31 06:52:47 +04:00
/* -------------------------------------------------------------------- */
#ifdef HAVE_LIBZ
#include "Zip.h"
PyObject*
PyImaging_ZipEncoderNew(PyObject* self, PyObject* args)
{
ImagingEncoderObject* encoder;
char* mode;
char* rawmode;
int optimize = 0;
int compress_level = -1;
int compress_type = -1;
2010-07-31 06:52:47 +04:00
char* dictionary = NULL;
int dictionary_size = 0;
if (!PyArg_ParseTuple(args, "ss|iii"PY_ARG_BYTES_LENGTH, &mode, &rawmode,
&optimize,
&compress_level, &compress_type,
&dictionary, &dictionary_size))
return NULL;
/* Copy to avoid referencing Python's memory, but there's no mechanism to
free this memory later, so this function (and several others here)
leaks. */
if (dictionary && dictionary_size > 0) {
char* p = malloc(dictionary_size);
if (!p)
return PyErr_NoMemory();
memcpy(p, dictionary, dictionary_size);
dictionary = p;
} else
dictionary = NULL;
2010-07-31 06:52:47 +04:00
encoder = PyImaging_EncoderNew(sizeof(ZIPSTATE));
if (encoder == NULL)
2014-03-04 08:43:47 +04:00
return NULL;
2010-07-31 06:52:47 +04:00
if (get_packer(encoder, mode, rawmode) < 0)
2014-03-04 08:43:47 +04:00
return NULL;
2010-07-31 06:52:47 +04:00
encoder->encode = ImagingZipEncode;
if (rawmode[0] == 'P')
2014-03-04 08:43:47 +04:00
/* disable filtering */
((ZIPSTATE*)encoder->state.context)->mode = ZIP_PNG_PALETTE;
2010-07-31 06:52:47 +04:00
((ZIPSTATE*)encoder->state.context)->optimize = optimize;
((ZIPSTATE*)encoder->state.context)->compress_level = compress_level;
((ZIPSTATE*)encoder->state.context)->compress_type = compress_type;
2010-07-31 06:52:47 +04:00
((ZIPSTATE*)encoder->state.context)->dictionary = dictionary;
((ZIPSTATE*)encoder->state.context)->dictionary_size = dictionary_size;
return (PyObject*) encoder;
}
#endif
/* -------------------------------------------------------------------- */
2014-03-04 08:43:47 +04:00
/* JPEG */
2010-07-31 06:52:47 +04:00
/* -------------------------------------------------------------------- */
#ifdef HAVE_LIBJPEG
/* We better define this encoder last in this file, so the following
undef's won't mess things up for the Imaging library proper. */
2014-03-04 08:43:47 +04:00
#undef HAVE_PROTOTYPES
#undef HAVE_STDDEF_H
#undef HAVE_STDLIB_H
#undef UINT8
#undef UINT16
#undef UINT32
#undef INT8
#undef INT16
#undef INT32
2010-07-31 06:52:47 +04:00
#include "Jpeg.h"
static unsigned int** get_qtables_arrays(PyObject* qtables) {
PyObject* tables;
PyObject* table;
PyObject* table_data;
int i, j, num_tables;
unsigned int **qarrays;
2013-05-12 03:56:15 +04:00
if ((qtables == NULL) || (qtables == Py_None)) {
return NULL;
}
if (!PySequence_Check(qtables)) {
PyErr_SetString(PyExc_ValueError, "Invalid quantization tables");
return NULL;
}
tables = PySequence_Fast(qtables, "expected a sequence");
num_tables = PySequence_Size(qtables);
if (num_tables < 1 || num_tables > NUM_QUANT_TBLS) {
PyErr_SetString(PyExc_ValueError, "Not a valid numbers of quantization tables. Should be between 1 and 4.");
return NULL;
}
qarrays = (unsigned int**) PyMem_Malloc(num_tables * sizeof(unsigned int*));
if (!qarrays) {
Py_DECREF(tables);
PyErr_NoMemory();
return NULL;
}
for (i = 0; i < num_tables; i++) {
table = PySequence_Fast_GET_ITEM(tables, i);
if (!PySequence_Check(table)) {
Py_DECREF(tables);
PyErr_SetString(PyExc_ValueError, "Invalid quantization tables");
return NULL;
}
if (PySequence_Size(table) != DCTSIZE2) {
Py_DECREF(tables);
PyErr_SetString(PyExc_ValueError, "Invalid quantization tables");
return NULL;
}
table_data = PySequence_Fast(table, "expected a sequence");
qarrays[i] = (unsigned int*) PyMem_Malloc(DCTSIZE2 * sizeof(unsigned int));
if (!qarrays[i]) {
Py_DECREF(tables);
PyErr_NoMemory();
return NULL;
}
for (j = 0; j < DCTSIZE2; j++) {
qarrays[i][j] = PyInt_AS_LONG(PySequence_Fast_GET_ITEM(table_data, j));
}
}
Py_DECREF(tables);
if (PyErr_Occurred()) {
PyMem_Free(qarrays);
qarrays = NULL;
}
return qarrays;
}
2010-07-31 06:52:47 +04:00
PyObject*
PyImaging_JpegEncoderNew(PyObject* self, PyObject* args)
{
ImagingEncoderObject* encoder;
char *mode;
char *rawmode;
int quality = 0;
int progressive = 0;
int smooth = 0;
int optimize = 0;
int streamtype = 0; /* 0=interchange, 1=tables only, 2=image only */
int xdpi = 0, ydpi = 0;
int subsampling = -1; /* -1=default, 0=none, 1=medium, 2=high */
2013-05-12 03:56:15 +04:00
PyObject* qtables=NULL;
unsigned int **qarrays = NULL;
char* extra = NULL;
int extra_size;
char* rawExif = NULL;
int rawExifLen = 0;
if (!PyArg_ParseTuple(args, "ss|iiiiiiiiO"PY_ARG_BYTES_LENGTH""PY_ARG_BYTES_LENGTH,
&mode, &rawmode, &quality,
&progressive, &smooth, &optimize, &streamtype,
&xdpi, &ydpi, &subsampling, &qtables, &extra, &extra_size,
&rawExif, &rawExifLen))
2014-03-04 08:43:47 +04:00
return NULL;
2010-07-31 06:52:47 +04:00
encoder = PyImaging_EncoderNew(sizeof(JPEGENCODERSTATE));
if (encoder == NULL)
2014-03-04 08:43:47 +04:00
return NULL;
2010-07-31 06:52:47 +04:00
if (get_packer(encoder, mode, rawmode) < 0)
2014-03-04 08:43:47 +04:00
return NULL;
2010-07-31 06:52:47 +04:00
qarrays = get_qtables_arrays(qtables);
2010-07-31 06:52:47 +04:00
if (extra && extra_size > 0) {
char* p = malloc(extra_size);
if (!p)
return PyErr_NoMemory();
memcpy(p, extra, extra_size);
extra = p;
} else
extra = NULL;
if (rawExif && rawExifLen > 0) {
char* pp = malloc(rawExifLen);
if (!pp)
return PyErr_NoMemory();
memcpy(pp, rawExif, rawExifLen);
rawExif = pp;
} else
rawExif = NULL;
2010-07-31 06:52:47 +04:00
encoder->encode = ImagingJpegEncode;
((JPEGENCODERSTATE*)encoder->state.context)->quality = quality;
((JPEGENCODERSTATE*)encoder->state.context)->qtables = qarrays;
2010-07-31 06:52:47 +04:00
((JPEGENCODERSTATE*)encoder->state.context)->subsampling = subsampling;
((JPEGENCODERSTATE*)encoder->state.context)->progressive = progressive;
((JPEGENCODERSTATE*)encoder->state.context)->smooth = smooth;
((JPEGENCODERSTATE*)encoder->state.context)->optimize = optimize;
((JPEGENCODERSTATE*)encoder->state.context)->streamtype = streamtype;
((JPEGENCODERSTATE*)encoder->state.context)->xdpi = xdpi;
((JPEGENCODERSTATE*)encoder->state.context)->ydpi = ydpi;
((JPEGENCODERSTATE*)encoder->state.context)->extra = extra;
((JPEGENCODERSTATE*)encoder->state.context)->extra_size = extra_size;
((JPEGENCODERSTATE*)encoder->state.context)->rawExif = rawExif;
((JPEGENCODERSTATE*)encoder->state.context)->rawExifLen = rawExifLen;
2010-07-31 06:52:47 +04:00
return (PyObject*) encoder;
}
#endif
/* -------------------------------------------------------------------- */
/* LibTiff */
/* -------------------------------------------------------------------- */
#ifdef HAVE_LIBTIFF
#include "TiffDecode.h"
#include <string.h>
PyObject*
PyImaging_LibTiffEncoderNew(PyObject* self, PyObject* args)
{
ImagingEncoderObject* encoder;
char* mode;
char* rawmode;
char* compname;
char* filename;
int fp;
PyObject *dir;
PyObject *key, *value;
Py_ssize_t pos = 0;
int status;
Py_ssize_t d_size;
PyObject *keys, *values;
if (! PyArg_ParseTuple(args, "sssisO", &mode, &rawmode, &compname, &fp, &filename, &dir)) {
return NULL;
}
if (!PyDict_Check(dir)) {
PyErr_SetString(PyExc_ValueError, "Invalid Dictionary");
return NULL;
} else {
d_size = PyDict_Size(dir);
TRACE(("dict size: %d\n", (int)d_size));
keys = PyDict_Keys(dir);
values = PyDict_Values(dir);
for (pos=0;pos<d_size;pos++){
TRACE((" key: %d\n", (int)PyInt_AsLong(PyList_GetItem(keys,pos))));
}
pos = 0;
}
TRACE(("new tiff encoder %s fp: %d, filename: %s \n", compname, fp, filename));
encoder = PyImaging_EncoderNew(sizeof(TIFFSTATE));
if (encoder == NULL)
return NULL;
if (get_packer(encoder, mode, rawmode) < 0)
return NULL;
if (! ImagingLibTiffEncodeInit(&encoder->state, filename, fp)) {
Py_DECREF(encoder);
PyErr_SetString(PyExc_RuntimeError, "tiff codec initialization failed");
return NULL;
}
2014-03-04 08:43:47 +04:00
// While failes on 64 bit machines, complains that pos is an int instead of a Py_ssize_t
// while (PyDict_Next(dir, &pos, &key, &value)) {
for (pos=0;pos<d_size;pos++){
key = PyList_GetItem(keys,pos);
value = PyList_GetItem(values,pos);
status = 0;
2013-03-14 02:10:37 +04:00
TRACE(("Attempting to set key: %d\n", (int)PyInt_AsLong(key)));
if (PyInt_Check(value)) {
TRACE(("Setting from Int: %d %ld \n", (int)PyInt_AsLong(key),PyInt_AsLong(value)));
status = ImagingLibTiffSetField(&encoder->state,
(ttag_t) PyInt_AsLong(key),
PyInt_AsLong(value));
} else if(PyBytes_Check(value)) {
2013-10-22 20:29:56 +04:00
TRACE(("Setting from Bytes: %d, %s \n", (int)PyInt_AsLong(key),PyBytes_AsString(value)));
status = ImagingLibTiffSetField(&encoder->state,
(ttag_t) PyInt_AsLong(key),
PyBytes_AsString(value));
} else if(PyList_Check(value)) {
int len,i;
float *floatav;
int *intav;
TRACE(("Setting from List: %d \n", (int)PyInt_AsLong(key)));
len = (int)PyList_Size(value);
if (len) {
if (PyInt_Check(PyList_GetItem(value,0))) {
TRACE((" %d elements, setting as ints \n", len));
intav = malloc(sizeof(int)*len);
if (intav) {
for (i=0;i<len;i++) {
intav[i] = (int)PyInt_AsLong(PyList_GetItem(value,i));
}
status = ImagingLibTiffSetField(&encoder->state,
(ttag_t) PyInt_AsLong(key),
intav);
free(intav);
}
} else {
TRACE((" %d elements, setting as floats \n", len));
floatav = malloc(sizeof(float)*len);
if (floatav) {
for (i=0;i<len;i++) {
floatav[i] = (float)PyFloat_AsDouble(PyList_GetItem(value,i));
}
status = ImagingLibTiffSetField(&encoder->state,
(ttag_t) PyInt_AsLong(key),
floatav);
free(floatav);
}
}
}
} else if (PyFloat_Check(value)) {
2013-10-22 20:29:56 +04:00
TRACE(("Setting from Float: %d, %f \n", (int)PyInt_AsLong(key),PyFloat_AsDouble(value)));
status = ImagingLibTiffSetField(&encoder->state,
(ttag_t) PyInt_AsLong(key),
(float)PyFloat_AsDouble(value));
} else {
2013-10-22 20:29:56 +04:00
TRACE(("Unhandled type for key %d : %s \n",
(int)PyInt_AsLong(key),
PyBytes_AsString(PyObject_Str(value))));
}
if (!status) {
TRACE(("Error setting Field\n"));
Py_DECREF(encoder);
PyErr_SetString(PyExc_RuntimeError, "Error setting from dictionary");
return NULL;
}
}
encoder->encode = ImagingLibTiffEncode;
return (PyObject*) encoder;
}
#endif
2014-03-13 22:27:16 +04:00
/* -------------------------------------------------------------------- */
/* JPEG 2000 */
/* -------------------------------------------------------------------- */
#ifdef HAVE_OPENJPEG
#include "Jpeg2K.h"
static void
j2k_decode_coord_tuple(PyObject *tuple, int *x, int *y)
{
*x = *y = 0;
if (tuple && PyTuple_Check(tuple) && PyTuple_GET_SIZE(tuple) == 2) {
*x = (int)PyInt_AsLong(PyTuple_GET_ITEM(tuple, 0));
*y = (int)PyInt_AsLong(PyTuple_GET_ITEM(tuple, 1));
if (*x < 0)
*x = 0;
if (*y < 0)
*y = 0;
}
}
PyObject*
PyImaging_Jpeg2KEncoderNew(PyObject *self, PyObject *args)
{
ImagingEncoderObject *encoder;
JPEG2KENCODESTATE *context;
char *mode;
char *format;
OPJ_CODEC_FORMAT codec_format;
PyObject *offset = NULL, *tile_offset = NULL, *tile_size = NULL;
char *quality_mode = "rates";
PyObject *quality_layers = NULL;
int num_resolutions = 0;
PyObject *cblk_size = NULL, *precinct_size = NULL;
PyObject *irreversible = NULL;
2014-03-13 22:27:16 +04:00
char *progression = "LRCP";
OPJ_PROG_ORDER prog_order;
char *cinema_mode = "no";
OPJ_CINEMA_MODE cine_mode;
int fd = -1;
2014-03-13 22:27:16 +04:00
if (!PyArg_ParseTuple(args, "ss|OOOsOIOOOssi", &mode, &format,
2014-03-13 22:27:16 +04:00
&offset, &tile_offset, &tile_size,
&quality_mode, &quality_layers, &num_resolutions,
&cblk_size, &precinct_size,
&irreversible, &progression, &cinema_mode,
&fd))
2014-03-13 22:27:16 +04:00
return NULL;
if (strcmp (format, "j2k") == 0)
codec_format = OPJ_CODEC_J2K;
else if (strcmp (format, "jpt") == 0)
codec_format = OPJ_CODEC_JPT;
else if (strcmp (format, "jp2") == 0)
codec_format = OPJ_CODEC_JP2;
else
return NULL;
if (strcmp(progression, "LRCP") == 0)
prog_order = OPJ_LRCP;
else if (strcmp(progression, "RLCP") == 0)
prog_order = OPJ_RLCP;
else if (strcmp(progression, "RPCL") == 0)
prog_order = OPJ_RPCL;
else if (strcmp(progression, "PCRL") == 0)
prog_order = OPJ_PCRL;
else if (strcmp(progression, "CPRL") == 0)
prog_order = OPJ_CPRL;
else
return NULL;
if (strcmp(cinema_mode, "no") == 0)
cine_mode = OPJ_OFF;
else if (strcmp(cinema_mode, "cinema2k-24") == 0)
cine_mode = OPJ_CINEMA2K_24;
else if (strcmp(cinema_mode, "cinema2k-48") == 0)
cine_mode = OPJ_CINEMA2K_48;
else if (strcmp(cinema_mode, "cinema4k-24") == 0)
cine_mode = OPJ_CINEMA4K_24;
else
return NULL;
encoder = PyImaging_EncoderNew(sizeof(JPEG2KENCODESTATE));
2014-03-13 22:27:16 +04:00
if (!encoder)
return NULL;
encoder->encode = ImagingJpeg2KEncode;
encoder->cleanup = ImagingJpeg2KEncodeCleanup;
context = (JPEG2KENCODESTATE *)encoder->state.context;
context->fd = fd;
2014-03-13 22:27:16 +04:00
context->format = codec_format;
context->offset_x = context->offset_y = 0;
j2k_decode_coord_tuple(offset, &context->offset_x, &context->offset_y);
j2k_decode_coord_tuple(tile_offset,
&context->tile_offset_x,
&context->tile_offset_y);
j2k_decode_coord_tuple(tile_size,
2014-03-13 22:27:16 +04:00
&context->tile_size_x,
&context->tile_size_y);
/* Error on illegal tile offsets */
if (context->tile_size_x && context->tile_size_y) {
if (context->tile_offset_x <= context->offset_x - context->tile_size_x
|| context->tile_offset_y <= context->offset_y - context->tile_size_y) {
PyErr_SetString(PyExc_ValueError,
"JPEG 2000 tile offset too small; top left tile must "
"intersect image area");
}
if (context->tile_offset_x > context->offset_x
|| context->tile_offset_y > context->offset_y) {
PyErr_SetString(PyExc_ValueError,
"JPEG 2000 tile offset too large to cover image area");
Py_DECREF(encoder);
return NULL;
}
}
2014-03-13 22:27:16 +04:00
if (quality_layers && PySequence_Check(quality_layers)) {
context->quality_is_in_db = strcmp (quality_mode, "dB") == 0;
context->quality_layers = quality_layers;
Py_INCREF(quality_layers);
2014-03-13 22:27:16 +04:00
}
context->num_resolutions = num_resolutions;
2014-03-04 08:43:47 +04:00
2014-03-13 22:27:16 +04:00
j2k_decode_coord_tuple(cblk_size,
&context->cblk_width,
&context->cblk_height);
j2k_decode_coord_tuple(precinct_size,
&context->precinct_width,
&context->precinct_height);
2014-03-13 22:27:16 +04:00
context->irreversible = PyObject_IsTrue(irreversible);
2014-03-13 22:27:16 +04:00
context->progression = prog_order;
context->cinema_mode = cine_mode;
return (PyObject *)encoder;
}
#endif
/*
* Local Variables:
* c-basic-offset: 4
* End:
*
*/