Commit message: add several TIFF decoders and encoders
CVE: CVE-2016-0740
CWE: CWE-119
Vulnerability description: Buffer overflow in the ImagingLibTiffDecode function in libImaging/TiffDecode.c in Pillow before 3.1.1 allows remote attackers to overwrite memory via a crafted TIFF file.

Project: Pillow
File: encode.c

PyImaging_EpsEncoderNew(PyObject* self, PyObject* args)
{
    ImagingEncoderObject* encoder;

    encoder = PyImaging_EncoderNew(0);
    if (encoder == NULL)
	return NULL;

    encoder->encode = ImagingEpsEncode;

    return (PyObject*) encoder;
}

Project: Pillow
File: decode.c

PyImaging_PcxDecoderNew(PyObject* self, PyObject* args)
{
    ImagingDecoderObject* decoder;

    char* mode;
    char* rawmode;
    int stride;
    if (!PyArg_ParseTuple(args, "ssi", &mode, &rawmode, &stride))
        return NULL;

    decoder = PyImaging_DecoderNew(0);
    if (decoder == NULL)
        return NULL;

    if (get_unpacker(decoder, mode, rawmode) < 0)
        return NULL;

    decoder->state.bytes = stride;

    decoder->decode = ImagingPcxDecode;

    return (PyObject*) decoder;
}

Project: Pillow
File: decode.c

PyImaging_XbmDecoderNew(PyObject* self, PyObject* args)
{
    ImagingDecoderObject* decoder;

    decoder = PyImaging_DecoderNew(0);
    if (decoder == NULL)
        return NULL;

    if (get_unpacker(decoder, "1", "1;R") < 0)
        return NULL;

    decoder->decode = ImagingXbmDecode;

    return (PyObject*) decoder;
}

Project: Pillow
File: decode.c

PyImaging_HexDecoderNew(PyObject* self, PyObject* args)
{
    ImagingDecoderObject* decoder;

    char* mode;
    char* rawmode;
    if (!PyArg_ParseTuple(args, "ss", &mode, &rawmode))
        return NULL;

    decoder = PyImaging_DecoderNew(0);
    if (decoder == NULL)
        return NULL;

    if (get_unpacker(decoder, mode, rawmode) < 0)
        return NULL;

    decoder->decode = ImagingHexDecode;

    return (PyObject*) decoder;
}

Project: Pillow
File: encode.c

PyImaging_ZipEncoderNew(PyObject* self, PyObject* args)
{
    ImagingEncoderObject* encoder;

    char* mode;
    char* rawmode;
    int optimize = 0;
    int compress_level = -1;
    int compress_type = -1;
    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;

    encoder = PyImaging_EncoderNew(sizeof(ZIPSTATE));
    if (encoder == NULL)
	return NULL;

    if (get_packer(encoder, mode, rawmode) < 0)
	return NULL;

    encoder->encode = ImagingZipEncode;

    if (rawmode[0] == 'P')
	/* disable filtering */
	((ZIPSTATE*)encoder->state.context)->mode = ZIP_PNG_PALETTE;

    ((ZIPSTATE*)encoder->state.context)->optimize = optimize;
    ((ZIPSTATE*)encoder->state.context)->compress_level = compress_level;
    ((ZIPSTATE*)encoder->state.context)->compress_type = compress_type;
    ((ZIPSTATE*)encoder->state.context)->dictionary = dictionary;
    ((ZIPSTATE*)encoder->state.context)->dictionary_size = dictionary_size;

    return (PyObject*) encoder;
}

Project: Pillow
File: encode.c

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 */
    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))
	return NULL;

    encoder = PyImaging_EncoderNew(sizeof(JPEGENCODERSTATE));
    if (encoder == NULL)
	return NULL;

    if (get_packer(encoder, mode, rawmode) < 0)
	return NULL;

    qarrays = get_qtables_arrays(qtables);

    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;

    encoder->encode = ImagingJpegEncode;

    ((JPEGENCODERSTATE*)encoder->state.context)->quality = quality;
    ((JPEGENCODERSTATE*)encoder->state.context)->qtables = qarrays;
    ((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;

    return (PyObject*) encoder;
}

Project: Pillow
File: decode.c

_dealloc(ImagingDecoderObject* decoder)
{
    free(decoder->state.buffer);
    free(decoder->state.context);
    Py_XDECREF(decoder->lock);
    PyObject_Del(decoder);
}

Project: Pillow
File: decode.c

_decode(ImagingDecoderObject* decoder, PyObject* args)
{
    UINT8* buffer;
    int bufsize, status;

    if (!PyArg_ParseTuple(args, PY_ARG_BYTES_LENGTH, &buffer, &bufsize))
        return NULL;

    status = decoder->decode(decoder->im, &decoder->state, buffer, bufsize);

    return Py_BuildValue("ii", status, decoder->state.errcode);
}

Project: Pillow
File: decode.c

PyImaging_RawDecoderNew(PyObject* self, PyObject* args)
{
    ImagingDecoderObject* decoder;

    char* mode;
    char* rawmode;
    int stride = 0;
    int ystep  = 1;
    if (!PyArg_ParseTuple(args, "ss|ii", &mode, &rawmode, &stride, &ystep))
        return NULL;

    decoder = PyImaging_DecoderNew(sizeof(RAWSTATE));
    if (decoder == NULL)
        return NULL;

    if (get_unpacker(decoder, mode, rawmode) < 0)
        return NULL;

    decoder->decode = ImagingRawDecode;

    decoder->state.ystep = ystep;

    ((RAWSTATE*)decoder->state.context)->stride = stride;

    return (PyObject*) decoder;
}

Project: Pillow
File: decode.c

PyImaging_DecoderNew(int contextsize)
{
    ImagingDecoderObject *decoder;
    void *context;

    if(PyType_Ready(&ImagingDecoderType) < 0)
        return NULL;

    decoder = PyObject_New(ImagingDecoderObject, &ImagingDecoderType);
    if (decoder == NULL)
        return NULL;

    /* Clear the decoder state */
    memset(&decoder->state, 0, sizeof(decoder->state));

    /* Allocate decoder context */
    if (contextsize > 0) {
        context = (void*) calloc(1, contextsize);
        if (!context) {
            Py_DECREF(decoder);
            (void) PyErr_NoMemory();
            return NULL;
        }
    } else
        context = 0;

    /* Initialize decoder context */
    decoder->state.context = context;

    /* Target image */
    decoder->lock = NULL;
    decoder->im = NULL;

    /* Initialize the cleanup function pointer */
    decoder->cleanup = NULL;

    return decoder;
}

Project: Pillow
File: decode.c

PyImaging_ZipDecoderNew(PyObject* self, PyObject* args)
{
    ImagingDecoderObject* decoder;

    char* mode;
    char* rawmode;
    int interlaced = 0;
    if (!PyArg_ParseTuple(args, "ss|i", &mode, &rawmode, &interlaced))
        return NULL;

    decoder = PyImaging_DecoderNew(sizeof(ZIPSTATE));
    if (decoder == NULL)
        return NULL;

    if (get_unpacker(decoder, mode, rawmode) < 0)
        return NULL;

    decoder->decode = ImagingZipDecode;

    ((ZIPSTATE*)decoder->state.context)->interlaced = interlaced;

    return (PyObject*) decoder;
}

Project: Pillow
File: decode.c

PyImaging_LibTiffDecoderNew(PyObject* self, PyObject* args)
{
    ImagingDecoderObject* decoder;
    char* mode;
    char* rawmode;
    char* compname;
    int compression;
    int fp;

    if (! PyArg_ParseTuple(args, "sssi", &mode, &rawmode, &compname, &fp))
        return NULL;

    TRACE(("new tiff decoder %s\n", compname));

    /* UNDONE -- we can probably do almost any arbitrary compression here,
     * since we're effective passing in the whole file in one shot and
     * getting back the data row by row. V2 maybe
     */

    if (strcasecmp(compname, "tiff_ccitt") == 0) {
        compression = COMPRESSION_CCITTRLE;

    } else if (strcasecmp(compname, "group3") == 0) {
        compression = COMPRESSION_CCITTFAX3;

    } else if (strcasecmp(compname, "group4") == 0) {
        compression = COMPRESSION_CCITTFAX4;

    } else if (strcasecmp(compname, "tiff_jpeg") == 0) {
        compression = COMPRESSION_OJPEG;

    } else if (strcasecmp(compname, "tiff_adobe_deflate") == 0) {
        compression = COMPRESSION_ADOBE_DEFLATE;

    } else if (strcasecmp(compname, "tiff_thunderscan") == 0) {
        compression = COMPRESSION_THUNDERSCAN;

    } else if (strcasecmp(compname, "tiff_deflate") == 0) {
        compression = COMPRESSION_DEFLATE;

    } else if (strcasecmp(compname, "tiff_sgilog") == 0) {
        compression = COMPRESSION_SGILOG;

    } else if (strcasecmp(compname, "tiff_sgilog24") == 0) {
        compression = COMPRESSION_SGILOG24;

    } else if (strcasecmp(compname, "tiff_raw_16") == 0) {
        compression = COMPRESSION_CCITTRLEW;

    } else {
        PyErr_SetString(PyExc_ValueError, "unknown compession");
        return NULL;
    }

    decoder = PyImaging_DecoderNew(sizeof(TIFFSTATE));
    if (decoder == NULL)
        return NULL;

    if (get_unpacker(decoder, mode, rawmode) < 0)
        return NULL;

    if (! ImagingLibTiffInit(&decoder->state, compression, fp)) {
        Py_DECREF(decoder);
        PyErr_SetString(PyExc_RuntimeError, "tiff codec initialization failed");
        return NULL;
    }

    decoder->decode  = ImagingLibTiffDecode;

    return (PyObject*) decoder;
}

Project: Pillow
File: encode.c

_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))
	return NULL;

    /* Allocate an encoder buffer */
    buf = (UINT8*) malloc(bufsize);
    if (!buf)
	return PyErr_NoMemory();

    ImagingSectionEnter(&cookie);

    do {

	/* This replaces the inner loop in the ImageFile _save
	   function. */

	status = encoder->encode(encoder->im, &encoder->state, buf, bufsize);

	if (status > 0)
	    if (write(fh, buf, status) < 0) {
                ImagingSectionLeave(&cookie);
		free(buf);
		return PyErr_SetFromErrno(PyExc_IOError);
	    }

    } while (encoder->state.errcode == 0);

    ImagingSectionLeave(&cookie);

    free(buf);

    return Py_BuildValue("i", encoder->state.errcode);
}

Project: Pillow
File: decode.c

PyImaging_TiffLzwDecoderNew(PyObject* self, PyObject* args)
{
    ImagingDecoderObject* decoder;

    char* mode;
    char* rawmode;
    int filter = 0;
    if (!PyArg_ParseTuple(args, "ss|i", &mode, &rawmode, &filter))
        return NULL;

    decoder = PyImaging_DecoderNew(sizeof(LZWSTATE));
    if (decoder == NULL)
        return NULL;

    if (get_unpacker(decoder, mode, rawmode) < 0)
        return NULL;

    decoder->decode = ImagingLzwDecode;

    ((LZWSTATE*)decoder->state.context)->filter = filter;

    return (PyObject*) decoder;
}

Project: Pillow
File: encode.c

static unsigned int** get_qtables_arrays(PyObject* qtables) {
    PyObject* tables;
    PyObject* table;
    PyObject* table_data;
    int i, j, num_tables;
    unsigned int **qarrays;

    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 < 2 || num_tables > NUM_QUANT_TBLS) {
        PyErr_SetString(PyExc_ValueError, "Not a valid numbers of quantization tables. Should be between 2 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;
}

Project: Pillow
File: decode.c

_setimage(ImagingDecoderObject* decoder, PyObject* args)
{
    PyObject* op;
    Imaging im;
    ImagingCodecState state;
    int x0, y0, x1, y1;

    x0 = y0 = x1 = y1 = 0;

    /* FIXME: should publish the ImagingType descriptor */
    if (!PyArg_ParseTuple(args, "O|(iiii)", &op, &x0, &y0, &x1, &y1))
        return NULL;
    im = PyImaging_AsImaging(op);
    if (!im)
        return NULL;

    decoder->im = im;

    state = &decoder->state;

    /* Setup decoding tile extent */
    if (x0 == 0 && x1 == 0) {
        state->xsize = im->xsize;
        state->ysize = im->ysize;
    } else {
        state->xoff = x0;
        state->yoff = y0;
        state->xsize = x1 - x0;
        state->ysize = y1 - y0;
    }

    if (state->xsize <= 0 ||
        state->xsize + state->xoff > (int) im->xsize ||
        state->ysize <= 0 ||
        state->ysize + state->yoff > (int) im->ysize) {
        PyErr_SetString(PyExc_ValueError, "tile cannot extend outside image");
        return NULL;
    }

    /* Allocate memory buffer (if bits field is set) */
    if (state->bits > 0) {
        if (!state->bytes)
            state->bytes = (state->bits * state->xsize+7)/8;
        state->buffer = (UINT8*) malloc(state->bytes);
        if (!state->buffer)
            return PyErr_NoMemory();
    }

    /* Keep a reference to the image object, to make sure it doesn't
       go away before we do */
    Py_INCREF(op);
    Py_XDECREF(decoder->lock);
    decoder->lock = op;

    Py_INCREF(Py_None);
    return Py_None;
}

Project: Pillow
File: decode.c

PyImaging_PcdDecoderNew(PyObject* self, PyObject* args)
{
    ImagingDecoderObject* decoder;

    decoder = PyImaging_DecoderNew(0);
    if (decoder == NULL)
        return NULL;

    /* Unpack from PhotoYCC to RGB */
    if (get_unpacker(decoder, "RGB", "YCC;P") < 0)
        return NULL;

    decoder->decode = ImagingPcdDecode;

    return (PyObject*) decoder;
}

Project: Pillow
File: decode.c

get_unpacker(ImagingDecoderObject* decoder, const char* mode,
             const char* rawmode)
{
    int bits;
    ImagingShuffler unpack;

    unpack = ImagingFindUnpacker(mode, rawmode, &bits);
    if (!unpack) {
        Py_DECREF(decoder);
        PyErr_SetString(PyExc_ValueError, "unknown raw mode");
        return -1;
    }

    decoder->state.shuffle = unpack;
    decoder->state.bits = bits;

    return 0;
}

Project: Pillow
File: decode.c

PyImaging_BitDecoderNew(PyObject* self, PyObject* args)
{
    ImagingDecoderObject* decoder;

    char* mode;
    int bits  = 8;
    int pad   = 8;
    int fill  = 0;
    int sign  = 0;
    int ystep = 1;
    if (!PyArg_ParseTuple(args, "s|iiiii", &mode, &bits, &pad, &fill,
                          &sign, &ystep))
        return NULL;

    if (strcmp(mode, "F") != 0) {
        PyErr_SetString(PyExc_ValueError, "bad image mode");
        return NULL;
    }

    decoder = PyImaging_DecoderNew(sizeof(BITSTATE));
    if (decoder == NULL)
        return NULL;

    decoder->decode = ImagingBitDecode;

    decoder->state.ystep = ystep;

    ((BITSTATE*)decoder->state.context)->bits = bits;
    ((BITSTATE*)decoder->state.context)->pad  = pad;
    ((BITSTATE*)decoder->state.context)->fill = fill;
    ((BITSTATE*)decoder->state.context)->sign = sign;

    return (PyObject*) decoder;
}

Project: Pillow
File: decode.c

PyImaging_FliDecoderNew(PyObject* self, PyObject* args)
{
    ImagingDecoderObject* decoder;

    decoder = PyImaging_DecoderNew(0);
    if (decoder == NULL)
        return NULL;

    decoder->decode = ImagingFliDecode;

    return (PyObject*) decoder;
}

Project: Pillow
File: encode.c

_dealloc(ImagingEncoderObject* encoder)
{
    free(encoder->state.buffer);
    free(encoder->state.context);
    Py_XDECREF(encoder->lock);
    PyObject_Del(encoder);
}

Project: Pillow
File: encode.c

PyImaging_XbmEncoderNew(PyObject* self, PyObject* args)
{
    ImagingEncoderObject* encoder;

    encoder = PyImaging_EncoderNew(0);
    if (encoder == NULL)
	return NULL;

    if (get_packer(encoder, "1", "1;R") < 0)
	return NULL;

    encoder->encode = ImagingXbmEncode;

    return (PyObject*) encoder;
}

Project: Pillow
File: decode.c

PyImaging_SunRleDecoderNew(PyObject* self, PyObject* args)
{
    ImagingDecoderObject* decoder;

    char* mode;
    char* rawmode;
    if (!PyArg_ParseTuple(args, "ss", &mode, &rawmode))
        return NULL;

    decoder = PyImaging_DecoderNew(0);
    if (decoder == NULL)
        return NULL;

    if (get_unpacker(decoder, mode, rawmode) < 0)
        return NULL;

    decoder->decode = ImagingSunRleDecode;

    return (PyObject*) decoder;
}

Project: Pillow
File: decode.c

PyImaging_PackbitsDecoderNew(PyObject* self, PyObject* args)
{
    ImagingDecoderObject* decoder;

    char* mode;
    char* rawmode;
    if (!PyArg_ParseTuple(args, "ss", &mode, &rawmode))
        return NULL;

    decoder = PyImaging_DecoderNew(0);
    if (decoder == NULL)
        return NULL;

    if (get_unpacker(decoder, mode, rawmode) < 0)
        return NULL;

    decoder->decode = ImagingPackbitsDecode;

    return (PyObject*) decoder;
}

Project: Pillow
File: decode.c

PyImaging_MspDecoderNew(PyObject* self, PyObject* args)
{
    ImagingDecoderObject* decoder;

    decoder = PyImaging_DecoderNew(0);
    if (decoder == NULL)
        return NULL;

    if (get_unpacker(decoder, "1", "1") < 0)
        return NULL;

    decoder->decode = ImagingMspDecode;

    return (PyObject*) decoder;
}

Project: Pillow
File: encode.c

PyImaging_PcxEncoderNew(PyObject* self, PyObject* args)
{
    ImagingEncoderObject* encoder;

    char *mode;
    char *rawmode;
    int bits = 8;
    if (!PyArg_ParseTuple(args, "ss|ii", &mode, &rawmode, &bits))
	return NULL;

    encoder = PyImaging_EncoderNew(0);
    if (encoder == NULL)
	return NULL;

    if (get_packer(encoder, mode, rawmode) < 0)
	return NULL;

    encoder->encode = ImagingPcxEncode;

    return (PyObject*) encoder;
}

Project: Pillow
File: encode.c

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))
	return NULL;

    encoder = PyImaging_EncoderNew(0);
    if (encoder == NULL)
	return NULL;

    if (get_packer(encoder, mode, rawmode) < 0)
	return NULL;

    encoder->encode = ImagingRawEncode;

    encoder->state.ystep = ystep;
    encoder->state.count = stride;

    return (PyObject*) encoder;
}

Project: Pillow
File: encode.c

get_packer(ImagingEncoderObject* encoder, const char* mode,
           const char* rawmode)
{
    int bits;
    ImagingShuffler pack;

    pack = ImagingFindPacker(mode, rawmode, &bits);
    if (!pack) {
	Py_DECREF(encoder);
	PyErr_SetString(PyExc_SystemError, "unknown raw mode");
	return -1;
    }

    encoder->state.shuffle = pack;
    encoder->state.bits = bits;

    return 0;
}

Project: Pillow
File: encode.c

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))
	return NULL;

    encoder = PyImaging_EncoderNew(sizeof(GIFENCODERSTATE));
    if (encoder == NULL)
	return NULL;

    if (get_packer(encoder, mode, rawmode) < 0)
	return NULL;

    encoder->encode = ImagingGifEncode;

    ((GIFENCODERSTATE*)encoder->state.context)->bits = bits;
    ((GIFENCODERSTATE*)encoder->state.context)->interlace = interlace;

    return (PyObject*) encoder;
}

Project: Pillow
File: decode.c

_decode_cleanup(ImagingDecoderObject* decoder, PyObject* args)
{
    int status = 0;

    if (decoder->cleanup){
        status = decoder->cleanup(&decoder->state);
    }

    return Py_BuildValue("i", status);
}

Project: Pillow
File: decode.c

PyImaging_GifDecoderNew(PyObject* self, PyObject* args)
{
    ImagingDecoderObject* decoder;

    char* mode;
    int bits = 8;
    int interlace = 0;
    if (!PyArg_ParseTuple(args, "s|ii", &mode, &bits, &interlace))
        return NULL;

    if (strcmp(mode, "L") != 0 && strcmp(mode, "P") != 0) {
        PyErr_SetString(PyExc_ValueError, "bad image mode");
        return NULL;
    }

    decoder = PyImaging_DecoderNew(sizeof(GIFDECODERSTATE));
    if (decoder == NULL)
        return NULL;

    decoder->decode = ImagingGifDecode;

    ((GIFDECODERSTATE*)decoder->state.context)->bits = bits;
    ((GIFDECODERSTATE*)decoder->state.context)->interlace = interlace;

    return (PyObject*) decoder;
}

Project: Pillow
File: decode.c

PyImaging_JpegDecoderNew(PyObject* self, PyObject* args)
{
    ImagingDecoderObject* decoder;

    char* mode;
    char* rawmode; /* what we wan't from the decoder */
    char* jpegmode; /* what's in the file */
    int scale = 1;
    int draft = 0;
    if (!PyArg_ParseTuple(args, "ssz|ii", &mode, &rawmode, &jpegmode,
                          &scale, &draft))
        return NULL;

    if (!jpegmode)
        jpegmode = "";

    decoder = PyImaging_DecoderNew(sizeof(JPEGSTATE));
    if (decoder == NULL)
        return NULL;

    if (get_unpacker(decoder, mode, rawmode) < 0)
        return NULL;

    decoder->decode = ImagingJpegDecode;
    decoder->cleanup = ImagingJpegDecodeCleanup;

    strncpy(((JPEGSTATE*)decoder->state.context)->rawmode, rawmode, 8);
    strncpy(((JPEGSTATE*)decoder->state.context)->jpegmode, jpegmode, 8);

    ((JPEGSTATE*)decoder->state.context)->scale = scale;
    ((JPEGSTATE*)decoder->state.context)->draft = draft;

    return (PyObject*) decoder;
}

Project: Pillow
File: encode.c

PyImaging_EncoderNew(int contextsize)
{
    ImagingEncoderObject *encoder;
    void *context;

    if(!PyType_Ready(&ImagingEncoderType) < 0)
        return NULL;

    encoder = PyObject_New(ImagingEncoderObject, &ImagingEncoderType);
    if (encoder == NULL)
	return NULL;

    /* Clear the encoder state */
    memset(&encoder->state, 0, sizeof(encoder->state));

    /* Allocate encoder context */
    if (contextsize > 0) {
	context = (void*) calloc(1, contextsize);
	if (!context) {
	    Py_DECREF(encoder);
	    (void) PyErr_NoMemory();
	    return NULL;
	}
    } else
	context = 0;

    /* Initialize encoder context */
    encoder->state.context = context;

    /* Target image */
    encoder->lock = NULL;
    encoder->im = NULL;

    return encoder;
}

Project: Pillow
File: encode.c

PyImaging_LibTiffEncoderNew(PyObject* self, PyObject* args)
{
    ImagingEncoderObject* encoder;

    char* mode;
    char* rawmode;
    char* compname;
    char* filename;
    int compression;
    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));

    /* UNDONE -- we can probably do almost any arbitrary compression here,
     *  so long as we're doing row/stripe based actions and not tiles.
     */

    if (strcasecmp(compname, "tiff_ccitt") == 0) {
        compression = COMPRESSION_CCITTRLE;

    } else if (strcasecmp(compname, "group3") == 0) {
        compression = COMPRESSION_CCITTFAX3;

    } else if (strcasecmp(compname, "group4") == 0) {
        compression = COMPRESSION_CCITTFAX4;

    } else if (strcasecmp(compname, "tiff_jpeg") == 0) {
        compression = COMPRESSION_OJPEG;

    } else if (strcasecmp(compname, "tiff_adobe_deflate") == 0) {
        compression = COMPRESSION_ADOBE_DEFLATE;

    } else if (strcasecmp(compname, "tiff_thunderscan") == 0) {
        compression = COMPRESSION_THUNDERSCAN;

    } else if (strcasecmp(compname, "tiff_deflate") == 0) {
        compression = COMPRESSION_DEFLATE;

    } else if (strcasecmp(compname, "tiff_sgilog") == 0) {
        compression = COMPRESSION_SGILOG;

    } else if (strcasecmp(compname, "tiff_sgilog24") == 0) {
        compression = COMPRESSION_SGILOG24;

    } else if (strcasecmp(compname, "tiff_raw_16") == 0) {
        compression = COMPRESSION_CCITTRLEW;

    } else {
        PyErr_SetString(PyExc_ValueError, "unknown compession");
        return NULL;
    }

    TRACE(("Found compression: %d\n", compression));

    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;
    }

	// 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;
        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)) {
            TRACE(("Setting from String: %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;
            TRACE(("Setting from List: %d \n", (int)PyInt_AsLong(key)));
            len = (int)PyList_Size(value);
            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)) {
            TRACE(("Setting from String: %d, %f \n", (int)PyInt_AsLong(key),PyFloat_AsDouble(value)));
            status = ImagingLibTiffSetField(&encoder->state,
                                            (ttag_t) PyInt_AsLong(key),
                                            (float)PyFloat_AsDouble(value));
        } else {
            TRACE(("Unhandled type for key %d : %s ",
                   (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;
}

Project: Pillow
File: decode.c

PyImaging_TgaRleDecoderNew(PyObject* self, PyObject* args)
{
    ImagingDecoderObject* decoder;

    char* mode;
    char* rawmode;
    int ystep = 1;
    int depth = 8;
    if (!PyArg_ParseTuple(args, "ss|ii", &mode, &rawmode, &ystep, &depth))
        return NULL;

    decoder = PyImaging_DecoderNew(0);
    if (decoder == NULL)
        return NULL;

    if (get_unpacker(decoder, mode, rawmode) < 0)
        return NULL;

    decoder->decode = ImagingTgaRleDecode;

    decoder->state.ystep = ystep;
    decoder->state.count = depth / 8;

    return (PyObject*) decoder;
}

Project: Pillow
File: encode.c

_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))
	return NULL;

    buf = PyBytes_FromStringAndSize(NULL, bufsize);
    if (!buf)
	return NULL;

    status = encoder->encode(encoder->im, &encoder->state,
			     (UINT8*) PyBytes_AsString(buf), bufsize);

    /* adjust string length to avoid slicing in encoder */
    if (_PyBytes_Resize(&buf, (status > 0) ? status : 0) < 0)
        return NULL;

    result = Py_BuildValue("iiO", status, encoder->state.errcode, buf);

    Py_DECREF(buf); /* must release buffer!!! */

    return result;
}

Project: Pillow
File: encode.c

_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))
	return NULL;
    im = PyImaging_AsImaging(op);
    if (!im)
	return NULL;

    encoder->im = im;

    state = &encoder->state;

    if (x0 == 0 && x1 == 0) {
	state->xsize = im->xsize;
	state->ysize = im->ysize;
    } else {
	state->xoff = x0;
	state->yoff = y0;
	state->xsize = x1 - x0;
	state->ysize = y1 - y0;
    }

    if (state->xsize <= 0 ||
	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;
    }

    /* Allocate memory buffer (if bits field is set) */
    if (state->bits > 0) {
	state->bytes = (state->bits * state->xsize+7)/8;
	state->buffer = (UINT8*) malloc(state->bytes);
	if (!state->buffer)
	    return PyErr_NoMemory();
    }

    /* 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;
}