mirror of
https://github.com/python-pillow/Pillow.git
synced 2024-12-24 17:06:16 +03:00
Merge pull request #423 from wiredfool/trns-png
Support for PNG tRNS header when converting from RGB->RGBA
This commit is contained in:
commit
d48f301d57
14
PIL/Image.py
14
PIL/Image.py
|
@ -724,16 +724,10 @@ class Image:
|
|||
if dither is None:
|
||||
dither = FLOYDSTEINBERG
|
||||
|
||||
# fake a P-mode image, otherwise the transparency will get lost as there is
|
||||
# currently no other way to convert transparency into an RGBA image
|
||||
if self.mode == "L" and mode == "RGBA" and "transparency" in self.info:
|
||||
from PIL import ImagePalette
|
||||
self.mode = "P"
|
||||
bytePalette = bytes(bytearray([i//3 for i in range(768)]))
|
||||
self.palette = ImagePalette.raw("RGB", bytePalette)
|
||||
self.palette.dirty = 1
|
||||
self.load()
|
||||
|
||||
# Use transparent conversion to promote from transparent color to an alpha channel.
|
||||
if self.mode in ("L", "RGB") and mode == "RGBA" and "transparency" in self.info:
|
||||
return self._new(self.im.convert_transparent(mode, self.info['transparency']))
|
||||
|
||||
try:
|
||||
im = self.im.convert(mode, dither)
|
||||
except ValueError:
|
||||
|
|
BIN
Tests/images/rgb_trns.png
Normal file
BIN
Tests/images/rgb_trns.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 1.6 KiB |
|
@ -150,6 +150,17 @@ def test_load_transparent_p():
|
|||
# image has 124 uniqe qlpha values
|
||||
assert_equal(len(im.split()[3].getcolors()), 124)
|
||||
|
||||
def test_load_transparent_rgb():
|
||||
file = "Tests/images/rgb_trns.png"
|
||||
im = Image.open(file)
|
||||
|
||||
assert_image(im, "RGB", (64, 64))
|
||||
im = im.convert("RGBA")
|
||||
assert_image(im, "RGBA", (64, 64))
|
||||
|
||||
# image has 876 transparent pixels
|
||||
assert_equal(im.split()[3].getcolors()[0][0], 876)
|
||||
|
||||
def test_save_p_transparent_palette():
|
||||
in_file = "Tests/images/pil123p.png"
|
||||
im = Image.open(in_file)
|
||||
|
@ -171,6 +182,10 @@ def test_save_l_transparency():
|
|||
file = tempfile("temp.png")
|
||||
assert_no_exception(lambda: im.save(file))
|
||||
|
||||
# There are 559 transparent pixels.
|
||||
im = im.convert('RGBA')
|
||||
assert_equal(im.split()[3].getcolors()[0][0], 559)
|
||||
|
||||
def test_save_rgb_single_transparency():
|
||||
in_file = "Tests/images/caption_6_33_22.png"
|
||||
im = Image.open(in_file)
|
||||
|
|
408
_imaging.c
408
_imaging.c
|
@ -168,12 +168,12 @@ PyImagingNew(Imaging imOut)
|
|||
ImagingObject* imagep;
|
||||
|
||||
if (!imOut)
|
||||
return NULL;
|
||||
return NULL;
|
||||
|
||||
imagep = PyObject_New(ImagingObject, &Imaging_Type);
|
||||
if (imagep == NULL) {
|
||||
ImagingDelete(imOut);
|
||||
return NULL;
|
||||
ImagingDelete(imOut);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
#ifdef VERBOSE
|
||||
|
@ -195,7 +195,7 @@ _dealloc(ImagingObject* imagep)
|
|||
#endif
|
||||
|
||||
if (imagep->access)
|
||||
ImagingAccessDelete(imagep->image, imagep->access);
|
||||
ImagingAccessDelete(imagep->image, imagep->access);
|
||||
ImagingDelete(imagep->image);
|
||||
PyObject_Del(imagep);
|
||||
}
|
||||
|
@ -205,8 +205,8 @@ _dealloc(ImagingObject* imagep)
|
|||
Imaging PyImaging_AsImaging(PyObject *op)
|
||||
{
|
||||
if (!PyImaging_Check(op)) {
|
||||
PyErr_BadInternalCall();
|
||||
return NULL;
|
||||
PyErr_BadInternalCall();
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return ((ImagingObject *)op)->image;
|
||||
|
@ -369,14 +369,14 @@ getlist(PyObject* arg, int* length, const char* wrong_length, int type)
|
|||
void* list;
|
||||
|
||||
if (!PySequence_Check(arg)) {
|
||||
PyErr_SetString(PyExc_TypeError, must_be_sequence);
|
||||
return NULL;
|
||||
PyErr_SetString(PyExc_TypeError, must_be_sequence);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
n = PyObject_Length(arg);
|
||||
if (length && wrong_length && n != *length) {
|
||||
PyErr_SetString(PyExc_ValueError, wrong_length);
|
||||
return NULL;
|
||||
PyErr_SetString(PyExc_ValueError, wrong_length);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
list = malloc(n * (type & 0xff));
|
||||
|
@ -469,33 +469,33 @@ getpixel(Imaging im, ImagingAccess access, int x, int y)
|
|||
} pixel;
|
||||
|
||||
if (x < 0 || x >= im->xsize || y < 0 || y >= im->ysize) {
|
||||
PyErr_SetString(PyExc_IndexError, outside_image);
|
||||
return NULL;
|
||||
PyErr_SetString(PyExc_IndexError, outside_image);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
access->get_pixel(im, x, y, &pixel);
|
||||
|
||||
switch (im->type) {
|
||||
case IMAGING_TYPE_UINT8:
|
||||
switch (im->bands) {
|
||||
case 1:
|
||||
return PyInt_FromLong(pixel.b[0]);
|
||||
case 2:
|
||||
return Py_BuildValue("BB", pixel.b[0], pixel.b[1]);
|
||||
case 3:
|
||||
return Py_BuildValue("BBB", pixel.b[0], pixel.b[1], pixel.b[2]);
|
||||
case 4:
|
||||
return Py_BuildValue("BBBB", pixel.b[0], pixel.b[1], pixel.b[2], pixel.b[3]);
|
||||
}
|
||||
break;
|
||||
switch (im->bands) {
|
||||
case 1:
|
||||
return PyInt_FromLong(pixel.b[0]);
|
||||
case 2:
|
||||
return Py_BuildValue("BB", pixel.b[0], pixel.b[1]);
|
||||
case 3:
|
||||
return Py_BuildValue("BBB", pixel.b[0], pixel.b[1], pixel.b[2]);
|
||||
case 4:
|
||||
return Py_BuildValue("BBBB", pixel.b[0], pixel.b[1], pixel.b[2], pixel.b[3]);
|
||||
}
|
||||
break;
|
||||
case IMAGING_TYPE_INT32:
|
||||
return PyInt_FromLong(pixel.i);
|
||||
return PyInt_FromLong(pixel.i);
|
||||
case IMAGING_TYPE_FLOAT32:
|
||||
return PyFloat_FromDouble(pixel.f);
|
||||
return PyFloat_FromDouble(pixel.f);
|
||||
case IMAGING_TYPE_SPECIAL:
|
||||
if (strncmp(im->mode, "I;16", 4) == 0)
|
||||
return PyInt_FromLong(pixel.h);
|
||||
break;
|
||||
if (strncmp(im->mode, "I;16", 4) == 0)
|
||||
return PyInt_FromLong(pixel.h);
|
||||
break;
|
||||
}
|
||||
|
||||
/* unknown type */
|
||||
|
@ -603,7 +603,7 @@ _fill(PyObject* self, PyObject* args)
|
|||
color = NULL;
|
||||
|
||||
if (!PyArg_ParseTuple(args, "s|(ii)O", &mode, &xsize, &ysize, &color))
|
||||
return NULL;
|
||||
return NULL;
|
||||
|
||||
im = ImagingNew(mode, xsize, ysize);
|
||||
if (!im)
|
||||
|
@ -629,7 +629,7 @@ _new(PyObject* self, PyObject* args)
|
|||
int xsize, ysize;
|
||||
|
||||
if (!PyArg_ParseTuple(args, "s(ii)", &mode, &xsize, &ysize))
|
||||
return NULL;
|
||||
return NULL;
|
||||
|
||||
return PyImagingNew(ImagingNew(mode, xsize, ysize));
|
||||
}
|
||||
|
@ -641,7 +641,7 @@ _new_array(PyObject* self, PyObject* args)
|
|||
int xsize, ysize;
|
||||
|
||||
if (!PyArg_ParseTuple(args, "s(ii)", &mode, &xsize, &ysize))
|
||||
return NULL;
|
||||
return NULL;
|
||||
|
||||
return PyImagingNew(ImagingNewArray(mode, xsize, ysize));
|
||||
}
|
||||
|
@ -653,7 +653,7 @@ _new_block(PyObject* self, PyObject* args)
|
|||
int xsize, ysize;
|
||||
|
||||
if (!PyArg_ParseTuple(args, "s(ii)", &mode, &xsize, &ysize))
|
||||
return NULL;
|
||||
return NULL;
|
||||
|
||||
return PyImagingNew(ImagingNewBlock(mode, xsize, ysize));
|
||||
}
|
||||
|
@ -662,7 +662,7 @@ static PyObject*
|
|||
_getcount(PyObject* self, PyObject* args)
|
||||
{
|
||||
if (!PyArg_ParseTuple(args, ":getcount"))
|
||||
return NULL;
|
||||
return NULL;
|
||||
|
||||
return PyInt_FromLong(ImagingNewCount);
|
||||
}
|
||||
|
@ -673,7 +673,7 @@ _linear_gradient(PyObject* self, PyObject* args)
|
|||
char* mode;
|
||||
|
||||
if (!PyArg_ParseTuple(args, "s", &mode))
|
||||
return NULL;
|
||||
return NULL;
|
||||
|
||||
return PyImagingNew(ImagingFillLinearGradient(mode));
|
||||
}
|
||||
|
@ -684,7 +684,7 @@ _radial_gradient(PyObject* self, PyObject* args)
|
|||
char* mode;
|
||||
|
||||
if (!PyArg_ParseTuple(args, "s", &mode))
|
||||
return NULL;
|
||||
return NULL;
|
||||
|
||||
return PyImagingNew(ImagingFillRadialGradient(mode));
|
||||
}
|
||||
|
@ -695,7 +695,7 @@ _open_ppm(PyObject* self, PyObject* args)
|
|||
char* filename;
|
||||
|
||||
if (!PyArg_ParseTuple(args, "s", &filename))
|
||||
return NULL;
|
||||
return NULL;
|
||||
|
||||
return PyImagingNew(ImagingOpenPPM(filename));
|
||||
}
|
||||
|
@ -709,7 +709,7 @@ _alpha_composite(ImagingObject* self, PyObject* args)
|
|||
if (!PyArg_ParseTuple(args, "O!O!",
|
||||
&Imaging_Type, &imagep1,
|
||||
&Imaging_Type, &imagep2))
|
||||
return NULL;
|
||||
return NULL;
|
||||
|
||||
return PyImagingNew(ImagingAlphaComposite(imagep1->image, imagep2->image));
|
||||
}
|
||||
|
@ -723,10 +723,10 @@ _blend(ImagingObject* self, PyObject* args)
|
|||
|
||||
alpha = 0.5;
|
||||
if (!PyArg_ParseTuple(args, "O!O!|d",
|
||||
&Imaging_Type, &imagep1,
|
||||
&Imaging_Type, &imagep2,
|
||||
&alpha))
|
||||
return NULL;
|
||||
&Imaging_Type, &imagep1,
|
||||
&Imaging_Type, &imagep2,
|
||||
&alpha))
|
||||
return NULL;
|
||||
|
||||
return PyImagingNew(ImagingBlend(imagep1->image, imagep2->image,
|
||||
(float) alpha));
|
||||
|
@ -744,17 +744,17 @@ _convert(ImagingObject* self, PyObject* args)
|
|||
ImagingObject *paletteimage = NULL;
|
||||
|
||||
if (!PyArg_ParseTuple(args, "s|iO", &mode, &dither, &paletteimage))
|
||||
return NULL;
|
||||
return NULL;
|
||||
if (paletteimage != NULL) {
|
||||
if (!PyImaging_Check(paletteimage)) {
|
||||
PyObject_Print((PyObject *)paletteimage, stderr, 0);
|
||||
PyErr_SetString(PyExc_ValueError, "palette argument must be image with mode 'P'");
|
||||
return NULL;
|
||||
}
|
||||
if (paletteimage->image->palette == NULL) {
|
||||
PyErr_SetString(PyExc_ValueError, "null palette");
|
||||
return NULL;
|
||||
}
|
||||
if (!PyImaging_Check(paletteimage)) {
|
||||
PyObject_Print((PyObject *)paletteimage, stderr, 0);
|
||||
PyErr_SetString(PyExc_ValueError, "palette argument must be image with mode 'P'");
|
||||
return NULL;
|
||||
}
|
||||
if (paletteimage->image->palette == NULL) {
|
||||
PyErr_SetString(PyExc_ValueError, "null palette");
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
return PyImagingNew(ImagingConvert(self->image, mode, paletteimage ? paletteimage->image->palette : NULL, dither));
|
||||
|
@ -766,9 +766,9 @@ _convert2(ImagingObject* self, PyObject* args)
|
|||
ImagingObject* imagep1;
|
||||
ImagingObject* imagep2;
|
||||
if (!PyArg_ParseTuple(args, "O!O!",
|
||||
&Imaging_Type, &imagep1,
|
||||
&Imaging_Type, &imagep2))
|
||||
return NULL;
|
||||
&Imaging_Type, &imagep1,
|
||||
&Imaging_Type, &imagep2))
|
||||
return NULL;
|
||||
|
||||
if (!ImagingConvert2(imagep1->image, imagep2->image))
|
||||
return NULL;
|
||||
|
@ -783,7 +783,7 @@ _convert_matrix(ImagingObject* self, PyObject* args)
|
|||
char* mode;
|
||||
float m[12];
|
||||
if (!PyArg_ParseTuple(args, "s(ffff)", &mode, m+0, m+1, m+2, m+3)) {
|
||||
PyErr_Clear();
|
||||
PyErr_Clear();
|
||||
if (!PyArg_ParseTuple(args, "s(ffffffffffff)", &mode,
|
||||
m+0, m+1, m+2, m+3,
|
||||
m+4, m+5, m+6, m+7,
|
||||
|
@ -794,11 +794,26 @@ _convert_matrix(ImagingObject* self, PyObject* args)
|
|||
return PyImagingNew(ImagingConvertMatrix(self->image, mode, m));
|
||||
}
|
||||
|
||||
static PyObject*
|
||||
_convert_transparent(ImagingObject* self, PyObject* args)
|
||||
{
|
||||
char* mode;
|
||||
int r,g,b;
|
||||
if (PyArg_ParseTuple(args, "s(iii)", &mode, &r, &g, &b)) {
|
||||
return PyImagingNew(ImagingConvertTransparent(self->image, mode, r, g, b));
|
||||
}
|
||||
PyErr_Clear();
|
||||
if (PyArg_ParseTuple(args, "si", &mode, &r)) {
|
||||
return PyImagingNew(ImagingConvertTransparent(self->image, mode, r, 0, 0));
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static PyObject*
|
||||
_copy(ImagingObject* self, PyObject* args)
|
||||
{
|
||||
if (!PyArg_ParseTuple(args, ""))
|
||||
return NULL;
|
||||
return NULL;
|
||||
|
||||
return PyImagingNew(ImagingCopy(self->image));
|
||||
}
|
||||
|
@ -809,9 +824,9 @@ _copy2(ImagingObject* self, PyObject* args)
|
|||
ImagingObject* imagep1;
|
||||
ImagingObject* imagep2;
|
||||
if (!PyArg_ParseTuple(args, "O!O!",
|
||||
&Imaging_Type, &imagep1,
|
||||
&Imaging_Type, &imagep2))
|
||||
return NULL;
|
||||
&Imaging_Type, &imagep1,
|
||||
&Imaging_Type, &imagep2))
|
||||
return NULL;
|
||||
|
||||
if (!ImagingCopy2(imagep1->image, imagep2->image))
|
||||
return NULL;
|
||||
|
@ -825,7 +840,7 @@ _crop(ImagingObject* self, PyObject* args)
|
|||
{
|
||||
int x0, y0, x1, y1;
|
||||
if (!PyArg_ParseTuple(args, "(iiii)", &x0, &y0, &x1, &y1))
|
||||
return NULL;
|
||||
return NULL;
|
||||
|
||||
return PyImagingNew(ImagingCrop(self->image, x0, y0, x1, y1));
|
||||
}
|
||||
|
@ -836,7 +851,7 @@ _expand(ImagingObject* self, PyObject* args)
|
|||
int x, y;
|
||||
int mode = 0;
|
||||
if (!PyArg_ParseTuple(args, "ii|i", &x, &y, &mode))
|
||||
return NULL;
|
||||
return NULL;
|
||||
|
||||
return PyImagingNew(ImagingExpand(self->image, x, y, mode));
|
||||
}
|
||||
|
@ -852,7 +867,7 @@ _filter(ImagingObject* self, PyObject* args)
|
|||
float divisor, offset;
|
||||
PyObject* kernel = NULL;
|
||||
if (!PyArg_ParseTuple(args, "(ii)ffO", &xsize, &ysize,
|
||||
&divisor, &offset, &kernel))
|
||||
&divisor, &offset, &kernel))
|
||||
return NULL;
|
||||
|
||||
/* get user-defined kernel */
|
||||
|
@ -907,25 +922,25 @@ _getpalette(ImagingObject* self, PyObject* args)
|
|||
char* mode = "RGB";
|
||||
char* rawmode = "RGB";
|
||||
if (!PyArg_ParseTuple(args, "|ss", &mode, &rawmode))
|
||||
return NULL;
|
||||
return NULL;
|
||||
|
||||
if (!self->image->palette) {
|
||||
PyErr_SetString(PyExc_ValueError, no_palette);
|
||||
return NULL;
|
||||
PyErr_SetString(PyExc_ValueError, no_palette);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
pack = ImagingFindPacker(mode, rawmode, &bits);
|
||||
if (!pack) {
|
||||
PyErr_SetString(PyExc_ValueError, wrong_raw_mode);
|
||||
return NULL;
|
||||
PyErr_SetString(PyExc_ValueError, wrong_raw_mode);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
palette = PyBytes_FromStringAndSize(NULL, palettesize * bits / 8);
|
||||
if (!palette)
|
||||
return NULL;
|
||||
return NULL;
|
||||
|
||||
pack((UINT8*) PyBytes_AsString(palette),
|
||||
self->image->palette->palette, palettesize);
|
||||
self->image->palette->palette, palettesize);
|
||||
|
||||
return palette;
|
||||
}
|
||||
|
@ -1066,14 +1081,14 @@ _histogram(ImagingObject* self, PyObject* args)
|
|||
/* Build an integer list containing the histogram */
|
||||
list = PyList_New(h->bands * 256);
|
||||
for (i = 0; i < h->bands * 256; i++) {
|
||||
PyObject* item;
|
||||
item = PyInt_FromLong(h->histogram[i]);
|
||||
if (item == NULL) {
|
||||
Py_DECREF(list);
|
||||
list = NULL;
|
||||
break;
|
||||
}
|
||||
PyList_SetItem(list, i, item);
|
||||
PyObject* item;
|
||||
item = PyInt_FromLong(h->histogram[i]);
|
||||
if (item == NULL) {
|
||||
Py_DECREF(list);
|
||||
list = NULL;
|
||||
break;
|
||||
}
|
||||
PyList_SetItem(list, i, item);
|
||||
}
|
||||
|
||||
ImagingHistogramDelete(h);
|
||||
|
@ -1087,7 +1102,7 @@ _modefilter(ImagingObject* self, PyObject* args)
|
|||
{
|
||||
int size;
|
||||
if (!PyArg_ParseTuple(args, "i", &size))
|
||||
return NULL;
|
||||
return NULL;
|
||||
|
||||
return PyImagingNew(ImagingModeFilter(self->image, size));
|
||||
}
|
||||
|
@ -1098,7 +1113,7 @@ _offset(ImagingObject* self, PyObject* args)
|
|||
{
|
||||
int xoffset, yoffset;
|
||||
if (!PyArg_ParseTuple(args, "ii", &xoffset, &yoffset))
|
||||
return NULL;
|
||||
return NULL;
|
||||
|
||||
return PyImagingNew(ImagingOffset(self->image, xoffset, yoffset));
|
||||
}
|
||||
|
@ -1379,7 +1394,7 @@ _quantize(ImagingObject* self, PyObject* args)
|
|||
int method = 0;
|
||||
int kmeans = 0;
|
||||
if (!PyArg_ParseTuple(args, "|iii", &colours, &method, &kmeans))
|
||||
return NULL;
|
||||
return NULL;
|
||||
|
||||
if (!self->image->xsize || !self->image->ysize) {
|
||||
/* no content; return an empty image */
|
||||
|
@ -1402,22 +1417,22 @@ _putpalette(ImagingObject* self, PyObject* args)
|
|||
UINT8* palette;
|
||||
int palettesize;
|
||||
if (!PyArg_ParseTuple(args, "s"PY_ARG_BYTES_LENGTH, &rawmode, &palette, &palettesize))
|
||||
return NULL;
|
||||
return NULL;
|
||||
|
||||
if (strcmp(self->image->mode, "L") != 0 && strcmp(self->image->mode, "P")) {
|
||||
PyErr_SetString(PyExc_ValueError, wrong_mode);
|
||||
return NULL;
|
||||
PyErr_SetString(PyExc_ValueError, wrong_mode);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
unpack = ImagingFindUnpacker("RGB", rawmode, &bits);
|
||||
if (!unpack) {
|
||||
PyErr_SetString(PyExc_ValueError, wrong_raw_mode);
|
||||
return NULL;
|
||||
PyErr_SetString(PyExc_ValueError, wrong_raw_mode);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if ( palettesize * 8 / bits > 256) {
|
||||
PyErr_SetString(PyExc_ValueError, wrong_palette_size);
|
||||
return NULL;
|
||||
PyErr_SetString(PyExc_ValueError, wrong_palette_size);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
ImagingPaletteDelete(self->image->palette);
|
||||
|
@ -1464,21 +1479,21 @@ _putpalettealphas(ImagingObject* self, PyObject* args)
|
|||
UINT8 *values;
|
||||
int length;
|
||||
if (!PyArg_ParseTuple(args, "s#", &values, &length))
|
||||
return NULL;
|
||||
return NULL;
|
||||
|
||||
if (!self->image->palette) {
|
||||
PyErr_SetString(PyExc_ValueError, no_palette);
|
||||
return NULL;
|
||||
PyErr_SetString(PyExc_ValueError, no_palette);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (length > 256) {
|
||||
PyErr_SetString(PyExc_ValueError, outside_palette);
|
||||
return NULL;
|
||||
PyErr_SetString(PyExc_ValueError, outside_palette);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
strcpy(self->image->palette->mode, "RGBA");
|
||||
for (i=0; i<length; i++) {
|
||||
self->image->palette->palette[i*4+3] = (UINT8) values[i];
|
||||
self->image->palette->palette[i*4+3] = (UINT8) values[i];
|
||||
}
|
||||
|
||||
Py_INCREF(Py_None);
|
||||
|
@ -1494,13 +1509,13 @@ _putpixel(ImagingObject* self, PyObject* args)
|
|||
int x, y;
|
||||
PyObject* color;
|
||||
if (!PyArg_ParseTuple(args, "(ii)O", &x, &y, &color))
|
||||
return NULL;
|
||||
return NULL;
|
||||
|
||||
im = self->image;
|
||||
|
||||
if (x < 0 || x >= im->xsize || y < 0 || y >= im->ysize) {
|
||||
PyErr_SetString(PyExc_IndexError, outside_image);
|
||||
return NULL;
|
||||
PyErr_SetString(PyExc_IndexError, outside_image);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (!getink(color, im, ink))
|
||||
|
@ -1519,7 +1534,7 @@ _rankfilter(ImagingObject* self, PyObject* args)
|
|||
{
|
||||
int size, rank;
|
||||
if (!PyArg_ParseTuple(args, "ii", &size, &rank))
|
||||
return NULL;
|
||||
return NULL;
|
||||
|
||||
return PyImagingNew(ImagingRankFilter(self->image, size, rank));
|
||||
}
|
||||
|
@ -1534,13 +1549,13 @@ _resize(ImagingObject* self, PyObject* args)
|
|||
int xsize, ysize;
|
||||
int filter = IMAGING_TRANSFORM_NEAREST;
|
||||
if (!PyArg_ParseTuple(args, "(ii)|i", &xsize, &ysize, &filter))
|
||||
return NULL;
|
||||
return NULL;
|
||||
|
||||
imIn = self->image;
|
||||
|
||||
imOut = ImagingNew(imIn->mode, xsize, ysize);
|
||||
if (imOut)
|
||||
(void) ImagingResize(imOut, imIn, filter);
|
||||
(void) ImagingResize(imOut, imIn, filter);
|
||||
|
||||
return PyImagingNew(imOut);
|
||||
}
|
||||
|
@ -1554,7 +1569,7 @@ _rotate(ImagingObject* self, PyObject* args)
|
|||
double theta;
|
||||
int filter = IMAGING_TRANSFORM_NEAREST;
|
||||
if (!PyArg_ParseTuple(args, "d|i", &theta, &filter))
|
||||
return NULL;
|
||||
return NULL;
|
||||
|
||||
imIn = self->image;
|
||||
|
||||
|
@ -1842,8 +1857,8 @@ _getbbox(ImagingObject* self, PyObject* args)
|
|||
{
|
||||
int bbox[4];
|
||||
if (!ImagingGetBBox(self->image, bbox)) {
|
||||
Py_INCREF(Py_None);
|
||||
return Py_None;
|
||||
Py_INCREF(Py_None);
|
||||
return Py_None;
|
||||
}
|
||||
|
||||
return Py_BuildValue("iiii", bbox[0], bbox[1], bbox[2], bbox[3]);
|
||||
|
@ -1858,7 +1873,7 @@ _getcolors(ImagingObject* self, PyObject* args)
|
|||
|
||||
int maxcolors = 256;
|
||||
if (!PyArg_ParseTuple(args, "i:getcolors", &maxcolors))
|
||||
return NULL;
|
||||
return NULL;
|
||||
|
||||
items = ImagingGetColors(self->image, maxcolors, &colors);
|
||||
if (!items)
|
||||
|
@ -1922,9 +1937,9 @@ _getprojection(ImagingObject* self, PyObject* args)
|
|||
yprofile = malloc(self->image->ysize);
|
||||
|
||||
if (xprofile == NULL || yprofile == NULL) {
|
||||
free(xprofile);
|
||||
free(yprofile);
|
||||
return PyErr_NoMemory();
|
||||
free(xprofile);
|
||||
free(yprofile);
|
||||
return PyErr_NoMemory();
|
||||
}
|
||||
|
||||
ImagingGetProjection(self->image, (unsigned char *)xprofile, (unsigned char *)yprofile);
|
||||
|
@ -1947,7 +1962,7 @@ _getband(ImagingObject* self, PyObject* args)
|
|||
int band;
|
||||
|
||||
if (!PyArg_ParseTuple(args, "i", &band))
|
||||
return NULL;
|
||||
return NULL;
|
||||
|
||||
return PyImagingNew(ImagingGetBand(self->image, band));
|
||||
}
|
||||
|
@ -1959,7 +1974,7 @@ _fillband(ImagingObject* self, PyObject* args)
|
|||
int color;
|
||||
|
||||
if (!PyArg_ParseTuple(args, "ii", &band, &color))
|
||||
return NULL;
|
||||
return NULL;
|
||||
|
||||
if (!ImagingFillBand(self->image, band, color))
|
||||
return NULL;
|
||||
|
@ -1974,12 +1989,12 @@ _putband(ImagingObject* self, PyObject* args)
|
|||
ImagingObject* imagep;
|
||||
int band;
|
||||
if (!PyArg_ParseTuple(args, "O!i",
|
||||
&Imaging_Type, &imagep,
|
||||
&band))
|
||||
return NULL;
|
||||
&Imaging_Type, &imagep,
|
||||
&band))
|
||||
return NULL;
|
||||
|
||||
if (!ImagingPutBand(self->image, imagep->image, band))
|
||||
return NULL;
|
||||
return NULL;
|
||||
|
||||
Py_INCREF(Py_None);
|
||||
return Py_None;
|
||||
|
@ -2001,7 +2016,7 @@ _chop_lighter(ImagingObject* self, PyObject* args)
|
|||
ImagingObject* imagep;
|
||||
|
||||
if (!PyArg_ParseTuple(args, "O!", &Imaging_Type, &imagep))
|
||||
return NULL;
|
||||
return NULL;
|
||||
|
||||
return PyImagingNew(ImagingChopLighter(self->image, imagep->image));
|
||||
}
|
||||
|
@ -2012,7 +2027,7 @@ _chop_darker(ImagingObject* self, PyObject* args)
|
|||
ImagingObject* imagep;
|
||||
|
||||
if (!PyArg_ParseTuple(args, "O!", &Imaging_Type, &imagep))
|
||||
return NULL;
|
||||
return NULL;
|
||||
|
||||
return PyImagingNew(ImagingChopDarker(self->image, imagep->image));
|
||||
}
|
||||
|
@ -2023,7 +2038,7 @@ _chop_difference(ImagingObject* self, PyObject* args)
|
|||
ImagingObject* imagep;
|
||||
|
||||
if (!PyArg_ParseTuple(args, "O!", &Imaging_Type, &imagep))
|
||||
return NULL;
|
||||
return NULL;
|
||||
|
||||
return PyImagingNew(ImagingChopDifference(self->image, imagep->image));
|
||||
}
|
||||
|
@ -2034,7 +2049,7 @@ _chop_multiply(ImagingObject* self, PyObject* args)
|
|||
ImagingObject* imagep;
|
||||
|
||||
if (!PyArg_ParseTuple(args, "O!", &Imaging_Type, &imagep))
|
||||
return NULL;
|
||||
return NULL;
|
||||
|
||||
return PyImagingNew(ImagingChopMultiply(self->image, imagep->image));
|
||||
}
|
||||
|
@ -2045,7 +2060,7 @@ _chop_screen(ImagingObject* self, PyObject* args)
|
|||
ImagingObject* imagep;
|
||||
|
||||
if (!PyArg_ParseTuple(args, "O!", &Imaging_Type, &imagep))
|
||||
return NULL;
|
||||
return NULL;
|
||||
|
||||
return PyImagingNew(ImagingChopScreen(self->image, imagep->image));
|
||||
}
|
||||
|
@ -2061,8 +2076,8 @@ _chop_add(ImagingObject* self, PyObject* args)
|
|||
offset = 0;
|
||||
|
||||
if (!PyArg_ParseTuple(args, "O!|fi", &Imaging_Type, &imagep,
|
||||
&scale, &offset))
|
||||
return NULL;
|
||||
&scale, &offset))
|
||||
return NULL;
|
||||
|
||||
return PyImagingNew(ImagingChopAdd(self->image, imagep->image,
|
||||
scale, offset));
|
||||
|
@ -2079,8 +2094,8 @@ _chop_subtract(ImagingObject* self, PyObject* args)
|
|||
offset = 0;
|
||||
|
||||
if (!PyArg_ParseTuple(args, "O!|fi", &Imaging_Type, &imagep,
|
||||
&scale, &offset))
|
||||
return NULL;
|
||||
&scale, &offset))
|
||||
return NULL;
|
||||
|
||||
return PyImagingNew(ImagingChopSubtract(self->image, imagep->image,
|
||||
scale, offset));
|
||||
|
@ -2092,7 +2107,7 @@ _chop_and(ImagingObject* self, PyObject* args)
|
|||
ImagingObject* imagep;
|
||||
|
||||
if (!PyArg_ParseTuple(args, "O!", &Imaging_Type, &imagep))
|
||||
return NULL;
|
||||
return NULL;
|
||||
|
||||
return PyImagingNew(ImagingChopAnd(self->image, imagep->image));
|
||||
}
|
||||
|
@ -2103,7 +2118,7 @@ _chop_or(ImagingObject* self, PyObject* args)
|
|||
ImagingObject* imagep;
|
||||
|
||||
if (!PyArg_ParseTuple(args, "O!", &Imaging_Type, &imagep))
|
||||
return NULL;
|
||||
return NULL;
|
||||
|
||||
return PyImagingNew(ImagingChopOr(self->image, imagep->image));
|
||||
}
|
||||
|
@ -2114,7 +2129,7 @@ _chop_xor(ImagingObject* self, PyObject* args)
|
|||
ImagingObject* imagep;
|
||||
|
||||
if (!PyArg_ParseTuple(args, "O!", &Imaging_Type, &imagep))
|
||||
return NULL;
|
||||
return NULL;
|
||||
|
||||
return PyImagingNew(ImagingChopXor(self->image, imagep->image));
|
||||
}
|
||||
|
@ -2125,7 +2140,7 @@ _chop_add_modulo(ImagingObject* self, PyObject* args)
|
|||
ImagingObject* imagep;
|
||||
|
||||
if (!PyArg_ParseTuple(args, "O!", &Imaging_Type, &imagep))
|
||||
return NULL;
|
||||
return NULL;
|
||||
|
||||
return PyImagingNew(ImagingChopAddModulo(self->image, imagep->image));
|
||||
}
|
||||
|
@ -2136,7 +2151,7 @@ _chop_subtract_modulo(ImagingObject* self, PyObject* args)
|
|||
ImagingObject* imagep;
|
||||
|
||||
if (!PyArg_ParseTuple(args, "O!", &Imaging_Type, &imagep))
|
||||
return NULL;
|
||||
return NULL;
|
||||
|
||||
return PyImagingNew(ImagingChopSubtractModulo(self->image, imagep->image));
|
||||
}
|
||||
|
@ -2159,18 +2174,18 @@ _font_new(PyObject* self_, PyObject* args)
|
|||
unsigned char* glyphdata;
|
||||
int glyphdata_length;
|
||||
if (!PyArg_ParseTuple(args, "O!"PY_ARG_BYTES_LENGTH,
|
||||
&Imaging_Type, &imagep,
|
||||
&glyphdata, &glyphdata_length))
|
||||
&Imaging_Type, &imagep,
|
||||
&glyphdata, &glyphdata_length))
|
||||
return NULL;
|
||||
|
||||
if (glyphdata_length != 256 * 20) {
|
||||
PyErr_SetString(PyExc_ValueError, wrong_length);
|
||||
return NULL;
|
||||
PyErr_SetString(PyExc_ValueError, wrong_length);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
self = PyObject_New(ImagingFontObject, &ImagingFont_Type);
|
||||
if (self == NULL)
|
||||
return NULL;
|
||||
return NULL;
|
||||
|
||||
/* glyph bitmap */
|
||||
self->bitmap = imagep->image;
|
||||
|
@ -2302,7 +2317,7 @@ _draw_new(PyObject* self_, PyObject* args)
|
|||
|
||||
self = PyObject_New(ImagingDrawObject, &ImagingDraw_Type);
|
||||
if (self == NULL)
|
||||
return NULL;
|
||||
return NULL;
|
||||
|
||||
/* keep a reference to the image object */
|
||||
Py_INCREF(imagep);
|
||||
|
@ -2349,7 +2364,7 @@ _draw_arc(ImagingDrawObject* self, PyObject* args)
|
|||
if (!PyArg_ParseTuple(args, "(iiii)iii|i",
|
||||
&x0, &y0, &x1, &y1,
|
||||
&start, &end, &ink))
|
||||
return NULL;
|
||||
return NULL;
|
||||
|
||||
if (ImagingDrawArc(self->image->image, x0, y0, x1, y1, start, end,
|
||||
&ink, op) < 0)
|
||||
|
@ -2369,17 +2384,16 @@ _draw_bitmap(ImagingDrawObject* self, PyObject* args)
|
|||
ImagingObject* bitmap;
|
||||
int ink;
|
||||
if (!PyArg_ParseTuple(args, "OO!i", &data, &Imaging_Type, &bitmap, &ink))
|
||||
return NULL;
|
||||
return NULL;
|
||||
|
||||
n = PyPath_Flatten(data, &xy);
|
||||
if (n < 0)
|
||||
return NULL;
|
||||
return NULL;
|
||||
if (n != 1) {
|
||||
PyErr_SetString(
|
||||
PyExc_TypeError,
|
||||
"coordinate list must contain exactly 1 coordinate"
|
||||
);
|
||||
return NULL;
|
||||
PyErr_SetString(PyExc_TypeError,
|
||||
"coordinate list must contain exactly 1 coordinate"
|
||||
);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
n = ImagingDrawBitmap(
|
||||
|
@ -2404,7 +2418,7 @@ _draw_chord(ImagingDrawObject* self, PyObject* args)
|
|||
int start, end;
|
||||
if (!PyArg_ParseTuple(args, "(iiii)iiii",
|
||||
&x0, &y0, &x1, &y1, &start, &end, &ink, &fill))
|
||||
return NULL;
|
||||
return NULL;
|
||||
|
||||
if (ImagingDrawChord(self->image->image, x0, y0, x1, y1,
|
||||
start, end, &ink, fill, self->blend) < 0)
|
||||
|
@ -2424,23 +2438,23 @@ _draw_ellipse(ImagingDrawObject* self, PyObject* args)
|
|||
int ink;
|
||||
int fill = 0;
|
||||
if (!PyArg_ParseTuple(args, "Oi|i", &data, &ink, &fill))
|
||||
return NULL;
|
||||
return NULL;
|
||||
|
||||
n = PyPath_Flatten(data, &xy);
|
||||
if (n < 0)
|
||||
return NULL;
|
||||
return NULL;
|
||||
if (n != 2) {
|
||||
PyErr_SetString(
|
||||
PyExc_TypeError,
|
||||
"coordinate list must contain exactly 2 coordinates"
|
||||
);
|
||||
return NULL;
|
||||
PyErr_SetString(PyExc_TypeError,
|
||||
"coordinate list must contain exactly 2 coordinates"
|
||||
);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
n = ImagingDrawEllipse(
|
||||
self->image->image, (int) xy[0], (int) xy[1], (int) xy[2], (int) xy[3],
|
||||
&ink, fill, self->blend
|
||||
);
|
||||
n = ImagingDrawEllipse(self->image->image,
|
||||
(int) xy[0], (int) xy[1],
|
||||
(int) xy[2], (int) xy[3],
|
||||
&ink, fill, self->blend
|
||||
);
|
||||
|
||||
free(xy);
|
||||
|
||||
|
@ -2457,11 +2471,11 @@ _draw_line(ImagingDrawObject* self, PyObject* args)
|
|||
int x0, y0, x1, y1;
|
||||
int ink;
|
||||
if (!PyArg_ParseTuple(args, "(ii)(ii)i", &x0, &y0, &x1, &y1, &ink))
|
||||
return NULL;
|
||||
return NULL;
|
||||
|
||||
if (ImagingDrawLine(self->image->image, x0, y0, x1, y1,
|
||||
&ink, self->blend) < 0)
|
||||
return NULL;
|
||||
return NULL;
|
||||
|
||||
Py_INCREF(Py_None);
|
||||
return Py_None;
|
||||
|
@ -2477,11 +2491,11 @@ _draw_lines(ImagingDrawObject* self, PyObject* args)
|
|||
int ink;
|
||||
int width = 0;
|
||||
if (!PyArg_ParseTuple(args, "Oi|i", &data, &ink, &width))
|
||||
return NULL;
|
||||
return NULL;
|
||||
|
||||
n = PyPath_Flatten(data, &xy);
|
||||
if (n < 0)
|
||||
return NULL;
|
||||
return NULL;
|
||||
|
||||
if (width <= 1) {
|
||||
double *p = NULL;
|
||||
|
@ -2526,10 +2540,10 @@ _draw_point(ImagingDrawObject* self, PyObject* args)
|
|||
int x, y;
|
||||
int ink;
|
||||
if (!PyArg_ParseTuple(args, "(ii)i", &x, &y, &ink))
|
||||
return NULL;
|
||||
return NULL;
|
||||
|
||||
if (ImagingDrawPoint(self->image->image, x, y, &ink, self->blend) < 0)
|
||||
return NULL;
|
||||
return NULL;
|
||||
|
||||
Py_INCREF(Py_None);
|
||||
return Py_None;
|
||||
|
@ -2544,11 +2558,11 @@ _draw_points(ImagingDrawObject* self, PyObject* args)
|
|||
PyObject *data;
|
||||
int ink;
|
||||
if (!PyArg_ParseTuple(args, "Oi", &data, &ink))
|
||||
return NULL;
|
||||
return NULL;
|
||||
|
||||
n = PyPath_Flatten(data, &xy);
|
||||
if (n < 0)
|
||||
return NULL;
|
||||
return NULL;
|
||||
|
||||
for (i = 0; i < n; i++) {
|
||||
double *p = &xy[i+i];
|
||||
|
@ -2579,7 +2593,7 @@ _draw_outline(ImagingDrawObject* self, PyObject* args)
|
|||
int ink;
|
||||
int fill = 0;
|
||||
if (!PyArg_ParseTuple(args, "Oi|i", &outline_, &ink, &fill))
|
||||
return NULL;
|
||||
return NULL;
|
||||
|
||||
outline = PyOutline_AsOutline(outline_);
|
||||
if (!outline) {
|
||||
|
@ -2605,7 +2619,7 @@ _draw_pieslice(ImagingDrawObject* self, PyObject* args)
|
|||
int start, end;
|
||||
if (!PyArg_ParseTuple(args, "(iiii)iiii",
|
||||
&x0, &y0, &x1, &y1, &start, &end, &ink, &fill))
|
||||
return NULL;
|
||||
return NULL;
|
||||
|
||||
if (ImagingDrawPieslice(self->image->image, x0, y0, x1, y1,
|
||||
start, end, &ink, fill, self->blend) < 0)
|
||||
|
@ -2626,33 +2640,32 @@ _draw_polygon(ImagingDrawObject* self, PyObject* args)
|
|||
int ink;
|
||||
int fill = 0;
|
||||
if (!PyArg_ParseTuple(args, "Oi|i", &data, &ink, &fill))
|
||||
return NULL;
|
||||
return NULL;
|
||||
|
||||
n = PyPath_Flatten(data, &xy);
|
||||
if (n < 0)
|
||||
return NULL;
|
||||
return NULL;
|
||||
if (n < 2) {
|
||||
PyErr_SetString(
|
||||
PyExc_TypeError,
|
||||
"coordinate list must contain at least 2 coordinates"
|
||||
);
|
||||
return NULL;
|
||||
PyErr_SetString(PyExc_TypeError,
|
||||
"coordinate list must contain at least 2 coordinates"
|
||||
);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* Copy list of vertices to array */
|
||||
ixy = (int*) malloc(n * 2 * sizeof(int));
|
||||
|
||||
for (i = 0; i < n; i++) {
|
||||
ixy[i+i] = (int) xy[i+i];
|
||||
ixy[i+i+1] = (int) xy[i+i+1];
|
||||
ixy[i+i] = (int) xy[i+i];
|
||||
ixy[i+i+1] = (int) xy[i+i+1];
|
||||
}
|
||||
|
||||
free(xy);
|
||||
|
||||
if (ImagingDrawPolygon(self->image->image, n, ixy,
|
||||
&ink, fill, self->blend) < 0) {
|
||||
free(ixy);
|
||||
return NULL;
|
||||
free(ixy);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
free(ixy);
|
||||
|
@ -2671,23 +2684,23 @@ _draw_rectangle(ImagingDrawObject* self, PyObject* args)
|
|||
int ink;
|
||||
int fill = 0;
|
||||
if (!PyArg_ParseTuple(args, "Oi|i", &data, &ink, &fill))
|
||||
return NULL;
|
||||
return NULL;
|
||||
|
||||
n = PyPath_Flatten(data, &xy);
|
||||
if (n < 0)
|
||||
return NULL;
|
||||
return NULL;
|
||||
if (n != 2) {
|
||||
PyErr_SetString(
|
||||
PyExc_TypeError,
|
||||
"coordinate list must contain exactly 2 coordinates"
|
||||
);
|
||||
return NULL;
|
||||
PyErr_SetString(PyExc_TypeError,
|
||||
"coordinate list must contain exactly 2 coordinates"
|
||||
);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
n = ImagingDrawRectangle(
|
||||
self->image->image, (int) xy[0], (int) xy[1],
|
||||
(int) xy[2], (int) xy[3], &ink, fill, self->blend
|
||||
);
|
||||
n = ImagingDrawRectangle(self->image->image,
|
||||
(int) xy[0], (int) xy[1],
|
||||
(int) xy[2], (int) xy[3],
|
||||
&ink, fill, self->blend
|
||||
);
|
||||
|
||||
free(xy);
|
||||
|
||||
|
@ -2734,7 +2747,7 @@ pixel_access_new(ImagingObject* imagep, PyObject* args)
|
|||
|
||||
self = PyObject_New(PixelAccessObject, &PixelAccess_Type);
|
||||
if (self == NULL)
|
||||
return NULL;
|
||||
return NULL;
|
||||
|
||||
/* keep a reference to the image object */
|
||||
Py_INCREF(imagep);
|
||||
|
@ -2778,8 +2791,8 @@ pixel_access_setitem(PixelAccessObject *self, PyObject *xy, PyObject *color)
|
|||
return -1;
|
||||
|
||||
if (x < 0 || x >= im->xsize || y < 0 || y >= im->ysize) {
|
||||
PyErr_SetString(PyExc_IndexError, outside_image);
|
||||
return -1;
|
||||
PyErr_SetString(PyExc_IndexError, outside_image);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (!color) /* FIXME: raise exception? */
|
||||
|
@ -2824,7 +2837,7 @@ _effect_noise(ImagingObject* self, PyObject* args)
|
|||
int xsize, ysize;
|
||||
float sigma = 128;
|
||||
if (!PyArg_ParseTuple(args, "(ii)|f", &xsize, &ysize, &sigma))
|
||||
return NULL;
|
||||
return NULL;
|
||||
|
||||
return PyImagingNew(ImagingEffectNoise(xsize, ysize, sigma));
|
||||
}
|
||||
|
@ -2835,7 +2848,7 @@ _effect_spread(ImagingObject* self, PyObject* args)
|
|||
int dist;
|
||||
|
||||
if (!PyArg_ParseTuple(args, "i", &dist))
|
||||
return NULL;
|
||||
return NULL;
|
||||
|
||||
return PyImagingNew(ImagingEffectSpread(self->image, dist));
|
||||
}
|
||||
|
@ -2858,7 +2871,7 @@ _crc32(PyObject* self, PyObject* args)
|
|||
|
||||
if (!PyArg_ParseTuple(args, PY_ARG_BYTES_LENGTH"|(ii)",
|
||||
&buffer, &bytes, &hi, &lo))
|
||||
return NULL;
|
||||
return NULL;
|
||||
|
||||
crc = ((UINT32) (hi & 0xFFFF) << 16) + (lo & 0xFFFF);
|
||||
|
||||
|
@ -2874,19 +2887,19 @@ _getcodecstatus(PyObject* self, PyObject* args)
|
|||
char* msg;
|
||||
|
||||
if (!PyArg_ParseTuple(args, "i", &status))
|
||||
return NULL;
|
||||
return NULL;
|
||||
|
||||
switch (status) {
|
||||
case IMAGING_CODEC_OVERRUN:
|
||||
msg = "buffer overrun"; break;
|
||||
msg = "buffer overrun"; break;
|
||||
case IMAGING_CODEC_BROKEN:
|
||||
msg = "broken data stream"; break;
|
||||
msg = "broken data stream"; break;
|
||||
case IMAGING_CODEC_UNKNOWN:
|
||||
msg = "unrecognized data stream contents"; break;
|
||||
msg = "unrecognized data stream contents"; break;
|
||||
case IMAGING_CODEC_CONFIG:
|
||||
msg = "codec configuration error"; break;
|
||||
msg = "codec configuration error"; break;
|
||||
case IMAGING_CODEC_MEMORY:
|
||||
msg = "out of memory"; break;
|
||||
msg = "out of memory"; break;
|
||||
default:
|
||||
Py_RETURN_NONE;
|
||||
}
|
||||
|
@ -2907,7 +2920,7 @@ _save_ppm(ImagingObject* self, PyObject* args)
|
|||
char* filename;
|
||||
|
||||
if (!PyArg_ParseTuple(args, "s", &filename))
|
||||
return NULL;
|
||||
return NULL;
|
||||
|
||||
if (!ImagingSavePPM(self->image, filename))
|
||||
return NULL;
|
||||
|
@ -2934,6 +2947,7 @@ static struct PyMethodDef methods[] = {
|
|||
{"convert", (PyCFunction)_convert, 1},
|
||||
{"convert2", (PyCFunction)_convert2, 1},
|
||||
{"convert_matrix", (PyCFunction)_convert_matrix, 1},
|
||||
{"convert_transparent", (PyCFunction)_convert_transparent, 1},
|
||||
{"copy", (PyCFunction)_copy, 1},
|
||||
{"copy2", (PyCFunction)_copy2, 1},
|
||||
#ifdef WITH_CRACKCODE
|
||||
|
|
|
@ -187,9 +187,9 @@ The :py:meth:`~PIL.Image.Image.save` method supports the following options:
|
|||
possible. This includes extra processing in order to find optimal encoder
|
||||
settings.
|
||||
|
||||
**transparency**
|
||||
For ``P`` and ``L`` images, this option controls what color image to mark as
|
||||
transparent.
|
||||
**transparency**
|
||||
For ``P``, ``L``, and ``RGB`` images, this option controls what
|
||||
color image to mark as transparent.
|
||||
|
||||
**bits (experimental)**
|
||||
For ``P`` images, this option controls how many bits to store. If omitted,
|
||||
|
|
|
@ -312,7 +312,33 @@ rgba2rgbA(UINT8* out, const UINT8* in, int xsize)
|
|||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Conversion of RGB + single transparent color to RGBA,
|
||||
* where any pixel that matches the color will have the
|
||||
* alpha channel set to 0
|
||||
*/
|
||||
|
||||
static void
|
||||
rgbT2rgba(UINT8* out, int xsize, int r, int g, int b)
|
||||
{
|
||||
#ifdef WORDS_BIGENDIAN
|
||||
UINT32 trns = ((r & 0xff)<<24) | ((g & 0xff)<<16) | ((b & 0xff)<<8) | 0xff;
|
||||
UINT32 repl = trns & 0xffffff00;
|
||||
#else
|
||||
UINT32 trns = (0xff <<24) | ((b & 0xff)<<16) | ((g & 0xff)<<8) | (r & 0xff);
|
||||
UINT32 repl = trns & 0x00ffffff;
|
||||
#endif
|
||||
|
||||
UINT32* tmp = (UINT32 *)out;
|
||||
int i;
|
||||
|
||||
for (i=0; i < xsize; i++ ,tmp++) {
|
||||
if (tmp[0]==trns) {
|
||||
tmp[0]=repl;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* ---------------- */
|
||||
/* CMYK conversions */
|
||||
|
@ -1162,6 +1188,60 @@ ImagingConvert2(Imaging imOut, Imaging imIn)
|
|||
return convert(imOut, imIn, imOut->mode, NULL, 0);
|
||||
}
|
||||
|
||||
|
||||
Imaging
|
||||
ImagingConvertTransparent(Imaging imIn, const char *mode,
|
||||
int r, int g, int b)
|
||||
{
|
||||
ImagingSectionCookie cookie;
|
||||
ImagingShuffler convert;
|
||||
Imaging imOut = NULL;
|
||||
int y;
|
||||
|
||||
if (!imIn){
|
||||
return (Imaging) ImagingError_ModeError();
|
||||
}
|
||||
|
||||
if (!((strcmp(imIn->mode, "RGB") == 0 ||
|
||||
strcmp(imIn->mode, "L") == 0)
|
||||
&& strcmp(mode, "RGBA") == 0))
|
||||
#ifdef notdef
|
||||
{
|
||||
return (Imaging) ImagingError_ValueError("conversion not supported");
|
||||
}
|
||||
#else
|
||||
{
|
||||
static char buf[256];
|
||||
/* FIXME: may overflow if mode is too large */
|
||||
sprintf(buf, "conversion from %s to %s not supported in convert_transparent", imIn->mode, mode);
|
||||
return (Imaging) ImagingError_ValueError(buf);
|
||||
}
|
||||
#endif
|
||||
|
||||
if (strcmp(imIn->mode, "RGB") == 0) {
|
||||
convert = rgb2rgba;
|
||||
} else {
|
||||
convert = l2rgb;
|
||||
g = b = r;
|
||||
}
|
||||
|
||||
imOut = ImagingNew2(mode, imOut, imIn);
|
||||
if (!imOut){
|
||||
return NULL;
|
||||
}
|
||||
|
||||
ImagingSectionEnter(&cookie);
|
||||
for (y = 0; y < imIn->ysize; y++) {
|
||||
(*convert)((UINT8*) imOut->image[y], (UINT8*) imIn->image[y],
|
||||
imIn->xsize);
|
||||
rgbT2rgba((UINT8*) imOut->image[y], imIn->xsize, r, g, b);
|
||||
}
|
||||
ImagingSectionLeave(&cookie);
|
||||
|
||||
return imOut;
|
||||
|
||||
}
|
||||
|
||||
Imaging
|
||||
ImagingConvertInPlace(Imaging imIn, const char* mode)
|
||||
{
|
||||
|
|
|
@ -248,6 +248,7 @@ extern Imaging ImagingCopy(Imaging im);
|
|||
extern Imaging ImagingConvert(Imaging im, const char* mode, ImagingPalette palette, int dither);
|
||||
extern Imaging ImagingConvertInPlace(Imaging im, const char* mode);
|
||||
extern Imaging ImagingConvertMatrix(Imaging im, const char *mode, float m[]);
|
||||
extern Imaging ImagingConvertTransparent(Imaging im, const char *mode, int r, int g, int b);
|
||||
extern Imaging ImagingCrop(Imaging im, int x0, int y0, int x1, int y1);
|
||||
extern Imaging ImagingExpand(Imaging im, int x, int y, int mode);
|
||||
extern Imaging ImagingFill(Imaging im, const void* ink);
|
||||
|
|
Loading…
Reference in New Issue
Block a user