From e42129241681dde7adae7d20697e7b421682fbb4 Mon Sep 17 00:00:00 2001 From: Daniel Baumann Date: Sat, 27 Apr 2024 18:23:22 +0200 Subject: Adding upstream version 2.10.22. Signed-off-by: Daniel Baumann --- plug-ins/pygimp/pygimp-image.c | 1564 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 1564 insertions(+) create mode 100644 plug-ins/pygimp/pygimp-image.c (limited to 'plug-ins/pygimp/pygimp-image.c') diff --git a/plug-ins/pygimp/pygimp-image.c b/plug-ins/pygimp/pygimp-image.c new file mode 100644 index 0000000..d8c0cbf --- /dev/null +++ b/plug-ins/pygimp/pygimp-image.c @@ -0,0 +1,1564 @@ +/* -*- Mode: C; c-basic-offset: 4 -*- + * Gimp-Python - allows the writing of Gimp plugins in Python. + * Copyright (C) 1997-2002 James Henstridge + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#ifdef HAVE_CONFIG_H +# include +#endif + +#include "pygimp.h" + +static PyObject * +img_add_channel(PyGimpImage *self, PyObject *args) +{ + PyGimpChannel *chn; + int pos = -1; + + if (!PyArg_ParseTuple(args, "O!|i:add_channel", + &PyGimpChannel_Type, &chn, &pos)) + return NULL; + + if (!gimp_image_insert_channel(self->ID, chn->ID, -1, pos)) { + PyErr_Format(pygimp_error, + "could not add channel (ID %d) to image (ID %d)", + chn->ID, self->ID); + return NULL; + } + + Py_INCREF(Py_None); + return Py_None; +} + +static PyObject * +img_insert_channel(PyGimpImage *self, PyObject *args, PyObject *kwargs) +{ + PyGimpChannel *chn; + PyGimpChannel *parent = NULL; + int pos = -1; + + static char *kwlist[] = { "channel", "parent", "position", NULL }; + + if (!PyArg_ParseTupleAndKeywords(args, kwargs, + "O!|O!i:insert_channel", kwlist, + &PyGimpChannel_Type, &chn, + &PyGimpChannel_Type, &parent, + &pos)) + return NULL; + + if (!gimp_image_insert_channel(self->ID, + chn->ID, parent ? parent->ID : -1, pos)) { + PyErr_Format(pygimp_error, + "could not insert channel (ID %d) to image (ID %d)", + chn->ID, self->ID); + return NULL; + } + + Py_INCREF(Py_None); + return Py_None; +} + +static PyObject * +img_add_layer(PyGimpImage *self, PyObject *args) +{ + PyGimpLayer *lay; + int pos = -1; + + if (!PyArg_ParseTuple(args, "O!|i:add_layer", &PyGimpLayer_Type, &lay, + &pos)) + return NULL; + + if (!gimp_image_insert_layer(self->ID, lay->ID, -1, pos)) { + PyErr_Format(pygimp_error, + "could not add layer (ID %d) to image (ID %d)", + lay->ID, self->ID); + return NULL; + } + + Py_INCREF(Py_None); + return Py_None; +} + +static PyObject * +img_insert_layer(PyGimpImage *self, PyObject *args, PyObject *kwargs) +{ + PyGimpLayer *lay; + PyGimpLayer *parent = NULL; + int pos = -1; + + static char *kwlist[] = { "layer", "parent", "position", NULL }; + + if (!PyArg_ParseTupleAndKeywords(args, kwargs, + "O!|O!i:insert_layer", kwlist, + &PyGimpLayer_Type, &lay, + &PyGimpLayer_Type, &parent, + &pos)) + return NULL; + + if (!gimp_image_insert_layer(self->ID, + lay->ID, parent ? parent->ID : -1, pos)) { + PyErr_Format(pygimp_error, + "could not insert layer (ID %d) to image (ID %d)", + lay->ID, self->ID); + return NULL; + } + + Py_INCREF(Py_None); + return Py_None; +} + +static PyObject * +img_new_layer(PyGimpImage *self, PyObject *args, PyObject *kwargs) +{ + char *layer_name; + int layer_id; + int width, height; + int layer_type; + int offs_x = 0, offs_y = 0; + gboolean alpha = TRUE; + int pos = -1; + double opacity = 100.0; + GimpLayerMode mode = GIMP_LAYER_MODE_NORMAL; + GimpFillType fill_mode = -1; + + static char *kwlist[] = { "name", "width", "height", "offset_x", "offset_y", + "alpha", "pos", "opacity", "mode", "fill_mode", + NULL }; + + layer_name = "New Layer"; + + width = gimp_image_width(self->ID); + height = gimp_image_height(self->ID); + + if (!PyArg_ParseTupleAndKeywords(args, kwargs, + "|siiiiiidii:new_layer", kwlist, + &layer_name, &width, &height, + &offs_x, &offs_y, &alpha, &pos, + &opacity, &mode, &fill_mode)) + return NULL; + + + switch (gimp_image_base_type(self->ID)) { + case GIMP_RGB: + layer_type = alpha ? GIMP_RGBA_IMAGE: GIMP_RGB_IMAGE; + break; + case GIMP_GRAY: + layer_type = alpha ? GIMP_GRAYA_IMAGE: GIMP_GRAY_IMAGE; + break; + case GIMP_INDEXED: + layer_type = alpha ? GIMP_INDEXEDA_IMAGE: GIMP_INDEXED_IMAGE; + break; + default: + PyErr_SetString(pygimp_error, "Unknown image base type"); + return NULL; + } + + if (fill_mode == -1) + fill_mode = alpha ? GIMP_FILL_TRANSPARENT: GIMP_FILL_BACKGROUND; + + + layer_id = gimp_layer_new(self->ID, layer_name, width, height, + layer_type, opacity, mode); + + if (!layer_id) { + PyErr_Format(pygimp_error, + "could not create new layer in image (ID %d)", + self->ID); + return NULL; + } + + if (!gimp_drawable_fill(layer_id, fill_mode)) { + gimp_item_delete(layer_id); + PyErr_Format(pygimp_error, + "could not fill new layer with fill mode %d", + fill_mode); + return NULL; + } + + if (!gimp_image_insert_layer(self->ID, layer_id, -1, pos)) { + gimp_item_delete(layer_id); + PyErr_Format(pygimp_error, + "could not add layer (ID %d) to image (ID %d)", + layer_id, self->ID); + return NULL; + } + + if (!gimp_layer_set_offsets(layer_id, offs_x, offs_y)) { + gimp_image_remove_layer(self->ID, layer_id); + PyErr_Format(pygimp_error, + "could not set offset %d, %d on layer (ID %d)", + offs_x, offs_y, layer_id); + return NULL; + } + + return pygimp_group_layer_new(layer_id); +} + + +static PyObject * +img_clean_all(PyGimpImage *self) +{ + if (!gimp_image_clean_all(self->ID)) { + PyErr_Format(pygimp_error, "could not clean all on image (ID %d)", + self->ID); + return NULL; + } + + Py_INCREF(Py_None); + return Py_None; +} + +static PyObject * +img_disable_undo(PyGimpImage *self) +{ + return PyBool_FromLong(gimp_image_undo_disable(self->ID)); +} + +static PyObject * +img_enable_undo(PyGimpImage *self) +{ + return PyBool_FromLong(gimp_image_undo_enable(self->ID)); +} + +static PyObject * +img_flatten(PyGimpImage *self) +{ + return pygimp_group_layer_new(gimp_image_flatten(self->ID)); +} + +static PyObject * +img_lower_channel(PyGimpImage *self, PyObject *args) +{ + PyGimpChannel *chn; + + if (!PyArg_ParseTuple(args, "O!:lower_channel", &PyGimpChannel_Type, &chn)) + return NULL; + + if (!gimp_image_lower_item(self->ID, chn->ID)) { + PyErr_Format(pygimp_error, + "could not lower channel (ID %d) on image (ID %d)", + chn->ID, self->ID); + return NULL; + } + + Py_INCREF(Py_None); + return Py_None; +} + +static PyObject * +img_lower_layer(PyGimpImage *self, PyObject *args) +{ + PyGimpLayer *lay; + + if (!PyArg_ParseTuple(args, "O!:lower_layer", &PyGimpLayer_Type, &lay)) + return NULL; + + if (!gimp_image_lower_item(self->ID, lay->ID)) { + PyErr_Format(pygimp_error, + "could not lower layer (ID %d) on image (ID %d)", + lay->ID, self->ID); + return NULL; + } + + Py_INCREF(Py_None); + return Py_None; +} + +static PyObject * +img_lower_layer_to_bottom(PyGimpImage *self, PyObject *args) +{ + PyGimpLayer *lay; + + if (!PyArg_ParseTuple(args, "O!:lower_layer_to_bottom", + &PyGimpLayer_Type, &lay)) + return NULL; + + if (!gimp_image_lower_item_to_bottom(self->ID, lay->ID)) { + PyErr_Format(pygimp_error, + "could not lower layer (ID %d) to bottom on image (ID %d)", + lay->ID, self->ID); + return NULL; + } + + Py_INCREF(Py_None); + return Py_None; +} + +static PyObject * +img_merge_visible_layers(PyGimpImage *self, PyObject *args) +{ + gint32 id; + int merge; + + if (!PyArg_ParseTuple(args, "i:merge_visible_layers", &merge)) + return NULL; + + id = gimp_image_merge_visible_layers(self->ID, merge); + + if (id == -1) { + PyErr_Format(pygimp_error, + "could not merge visible layers on image (ID %d) " + "with merge type %d", + self->ID, merge); + return NULL; + } + + return pygimp_group_layer_new(id); +} + +static PyObject * +img_merge_down(PyGimpImage *self, PyObject *args) +{ + gint32 id; + PyGimpLayer *layer; + int merge; + + if (!PyArg_ParseTuple(args, "O!i:merge_down", + &PyGimpLayer_Type, &layer, &merge)) + return NULL; + + id = gimp_image_merge_down(self->ID, layer->ID, merge); + + if (id == -1) { + PyErr_Format(pygimp_error, + "could not merge down layer (ID %d) on image (ID %d) " + "with merge type %d", + layer->ID, self->ID, merge); + return NULL; + } + + return pygimp_group_layer_new(id); +} + +static PyObject * +img_pick_correlate_layer(PyGimpImage *self, PyObject *args) +{ + int x,y; + gint32 id; + + if (!PyArg_ParseTuple(args, "ii:pick_correlate_layer", &x, &y)) + return NULL; + + id = gimp_image_pick_correlate_layer(self->ID, x, y); + + if (id == -1) { + Py_INCREF(Py_None); + return Py_None; + } + + return pygimp_group_layer_new(id); +} + +static PyObject * +img_raise_channel(PyGimpImage *self, PyObject *args) +{ + PyGimpChannel *chn; + + if (!PyArg_ParseTuple(args, "O!:raise_channel", &PyGimpChannel_Type, &chn)) + return NULL; + + if (!gimp_image_raise_item(self->ID, chn->ID)) { + PyErr_Format(pygimp_error, + "could not raise channel (ID %d) on image (ID %d)", + chn->ID, self->ID); + return NULL; + } + + Py_INCREF(Py_None); + return Py_None; +} + +static PyObject * +img_raise_layer(PyGimpImage *self, PyObject *args) +{ + PyGimpLayer *lay; + + if (!PyArg_ParseTuple(args, "O!:raise_layer", &PyGimpLayer_Type, &lay)) + return NULL; + + if (!gimp_image_raise_item(self->ID, lay->ID)) { + PyErr_Format(pygimp_error, + "could not raise layer (ID %d) on image (ID %d)", + lay->ID, self->ID); + return NULL; + } + + Py_INCREF(Py_None); + return Py_None; +} + +static PyObject * +img_raise_layer_to_top(PyGimpImage *self, PyObject *args) +{ + PyGimpLayer *lay; + + if (!PyArg_ParseTuple(args, "O!:raise_layer_to_top", + &PyGimpLayer_Type, &lay)) + return NULL; + + if (!gimp_image_raise_item_to_top(self->ID, lay->ID)) { + PyErr_Format(pygimp_error, + "could not raise layer (ID %d) to top on image (ID %d)", + lay->ID, self->ID); + return NULL; + } + + Py_INCREF(Py_None); + return Py_None; +} + +static PyObject * +img_remove_channel(PyGimpImage *self, PyObject *args) +{ + PyGimpChannel *chn; + + if (!PyArg_ParseTuple(args, "O!:remove_channel", &PyGimpChannel_Type, &chn)) + return NULL; + + if (!gimp_image_remove_channel(self->ID, chn->ID)) { + PyErr_Format(pygimp_error, + "could not remove channel (ID %d) from image (ID %d)", + chn->ID, self->ID); + return NULL; + } + + Py_INCREF(Py_None); + return Py_None; +} + +static PyObject * +img_remove_layer(PyGimpImage *self, PyObject *args) +{ + PyGimpLayer *lay; + + if (!PyArg_ParseTuple(args, "O!:remove_layer", &PyGimpLayer_Type, &lay)) + return NULL; + + if (!gimp_image_remove_layer(self->ID, lay->ID)) { + PyErr_Format(pygimp_error, + "could not remove layer (ID %d) from image (ID %d)", + lay->ID, self->ID); + return NULL; + } + + Py_INCREF(Py_None); + return Py_None; +} + +static PyObject * +img_resize(PyGimpImage *self, PyObject *args, PyObject *kwargs) +{ + int new_w, new_h; + int offs_x = 0, offs_y = 0; + + static char *kwlist[] = { "width", "height", "offset_x", "offset_y", + NULL }; + + if (!PyArg_ParseTupleAndKeywords(args, kwargs, "ii|ii:resize", kwlist, + &new_w, &new_h, &offs_x, &offs_y)) + return NULL; + + if (!gimp_image_resize(self->ID, new_w, new_h, offs_x, offs_y)) { + PyErr_Format(pygimp_error, + "could not resize image (ID %d) to %dx%d, offset %d, %d", + self->ID, new_w, new_h, offs_x, offs_y); + return NULL; + } + + Py_INCREF(Py_None); + return Py_None; +} + +static PyObject * +img_resize_to_layers(PyGimpImage *self) +{ + if (!gimp_image_resize_to_layers(self->ID)) { + PyErr_Format(pygimp_error, "could not resize to layers on image " + "(ID %d)", + self->ID); + return NULL; + } + + Py_INCREF(Py_None); + return Py_None; +} + +static PyObject * +img_scale(PyGimpImage *self, PyObject *args, PyObject *kwargs) +{ + int new_width, new_height; + int interpolation = -1; + + static char *kwlist[] = { "width", "height", "interpolation", NULL }; + + if (!PyArg_ParseTupleAndKeywords(args, kwargs, "ii|i:scale", kwlist, + &new_width, &new_height, &interpolation)) + return NULL; + + if (interpolation != -1) { + gimp_context_push(); + gimp_context_set_interpolation(interpolation); + } + + if (!gimp_image_scale(self->ID, new_width, new_height)) { + PyErr_Format(pygimp_error, "could not scale image (ID %d) to %dx%d", + self->ID, new_width, new_height); + if (interpolation != -1) { + gimp_context_pop(); + } + return NULL; + } + + if (interpolation != -1) { + gimp_context_pop(); + } + + Py_INCREF(Py_None); + return Py_None; +} + +static PyObject * +img_crop(PyGimpImage *self, PyObject *args, PyObject *kwargs) +{ + int new_w, new_h; + int offs_x = 0, offs_y = 0; + + static char *kwlist[] = { "width", "height", "offset_x", "offset_y", + NULL }; + + if (!PyArg_ParseTupleAndKeywords(args, kwargs, "ii|ii:crop", kwlist, + &new_w, &new_h, &offs_x, &offs_y)) + return NULL; + + if (!gimp_image_crop(self->ID, new_w, new_h, offs_x, offs_y)) { + PyErr_Format(pygimp_error, + "could not crop image (ID %d) to %dx%d, offset %d, %d", + self->ID, new_w, new_h, offs_x, offs_y); + return NULL; + } + + Py_INCREF(Py_None); + return Py_None; +} + +static PyObject * +img_free_shadow(PyGimpImage *self) +{ + /* this procedure is deprecated and does absolutely nothing */ + + Py_INCREF(Py_None); + return Py_None; +} + +static PyObject * +img_unset_active_channel(PyGimpImage *self) +{ + if (!gimp_image_unset_active_channel(self->ID)) { + PyErr_Format(pygimp_error, + "could not unset active channel on image (ID %d)", + self->ID); + return NULL; + } + + Py_INCREF(Py_None); + return Py_None; +} + +static PyObject * +img_get_component_active(PyGimpImage *self, PyObject *args) +{ + int comp; + + if (!PyArg_ParseTuple(args, "i:get_component_active", &comp)) + return NULL; + + return PyBool_FromLong(gimp_image_get_component_active(self->ID, comp)); +} + + +static PyObject * +img_get_component_visible(PyGimpImage *self, PyObject *args) +{ + int comp; + + if (!PyArg_ParseTuple(args, "i:get_component_visible", &comp)) + return NULL; + + return PyBool_FromLong(gimp_image_get_component_visible(self->ID, comp)); +} + + +static PyObject * +img_set_component_active(PyGimpImage *self, PyObject *args) +{ + int comp, a; + + if (!PyArg_ParseTuple(args, "ii:set_component_active", &comp, &a)) + return NULL; + + if (!gimp_image_set_component_active(self->ID, comp, a)) { + PyErr_Format(pygimp_error, + "could not set component (%d) %sactive on image (ID %d)", + comp, a ? "" : "in", self->ID); + return NULL; + } + + Py_INCREF(Py_None); + return Py_None; +} + +static PyObject * +img_set_component_visible(PyGimpImage *self, PyObject *args) +{ + int comp, v; + + if (!PyArg_ParseTuple(args, "ii:set_component_visible", &comp, &v)) + return NULL; + + if (!gimp_image_set_component_visible(self->ID, comp, v)) { + PyErr_Format(pygimp_error, + "could not set component (%d) %svisible on image (ID %d)", + comp, v ? "" : "in", self->ID); + return NULL; + } + + Py_INCREF(Py_None); + return Py_None; +} + +static PyObject * +img_parasite_find(PyGimpImage *self, PyObject *args) +{ + char *name; + + if (!PyArg_ParseTuple(args, "s:parasite_find", &name)) + return NULL; + + return pygimp_parasite_new (gimp_image_get_parasite (self->ID, name)); +} + +static PyObject * +img_parasite_attach(PyGimpImage *self, PyObject *args) +{ + PyGimpParasite *parasite; + + if (!PyArg_ParseTuple(args, "O!:parasite_attach", &PyGimpParasite_Type, + ¶site)) + return NULL; + + if (! gimp_image_attach_parasite (self->ID, parasite->para)) { + PyErr_Format(pygimp_error, + "could not attach parasite '%s' to image (ID %d)", + parasite->para->name, self->ID); + return NULL; + } + + Py_INCREF(Py_None); + return Py_None; +} + +static PyObject * +img_attach_new_parasite(PyGimpImage *self, PyObject *args, PyObject *kwargs) +{ + char *name; + int flags, size; + guint8 *data; + GimpParasite *parasite; + gboolean success; + + static char *kwlist[] = { "name", "flags", "data", NULL }; + + if (!PyArg_ParseTupleAndKeywords(args, kwargs, + "sis#:attach_new_parasite", kwlist, + &name, &flags, &data, &size)) + return NULL; + + parasite = gimp_parasite_new (name, flags, size, data); + success = gimp_image_attach_parasite (self->ID, parasite); + gimp_parasite_free (parasite); + + if (!success) { + PyErr_Format(pygimp_error, + "could not attach new parasite '%s' to image (ID %d)", + name, self->ID); + return NULL; + } + + Py_INCREF(Py_None); + return Py_None; +} + +static PyObject * +img_parasite_detach(PyGimpImage *self, PyObject *args) +{ + char *name; + + if (!PyArg_ParseTuple(args, "s:parasite_detach", &name)) + return NULL; + + if (!gimp_image_detach_parasite (self->ID, name)) { + PyErr_Format(pygimp_error, + "could not detach parasite '%s' from image (ID %d)", + name, self->ID); + return NULL; + } + + Py_INCREF(Py_None); + return Py_None; +} + +static PyObject * +img_parasite_list(PyGimpImage *self) +{ + gint num_parasites; + gchar **parasites; + PyObject *ret; + gint i; + + parasites = gimp_image_get_parasite_list (self->ID, &num_parasites); + + ret = PyTuple_New(num_parasites); + + for (i = 0; i < num_parasites; i++) + PyTuple_SetItem(ret, i, PyString_FromString(parasites[i])); + + g_strfreev(parasites); + return ret; +} + +static PyObject * +img_get_layer_by_tattoo(PyGimpImage *self, PyObject *args) +{ + int tattoo; + + if (!PyArg_ParseTuple(args, "i:get_layer_by_tattoo", &tattoo)) + return NULL; + + return pygimp_group_layer_new(gimp_image_get_layer_by_tattoo(self->ID, tattoo)); +} + +static PyObject * +img_get_channel_by_tattoo(PyGimpImage *self, PyObject *args) +{ + int tattoo; + + if (!PyArg_ParseTuple(args, "i:get_channel_by_tattoo", &tattoo)) + return NULL; + + return pygimp_channel_new(gimp_image_get_channel_by_tattoo(self->ID, + tattoo)); +} + +static PyObject * +img_add_hguide(PyGimpImage *self, PyObject *args) +{ + int ypos; + + if (!PyArg_ParseTuple(args, "i:add_hguide", &ypos)) + return NULL; + + return PyInt_FromLong(gimp_image_add_hguide(self->ID, ypos)); +} + +static PyObject * +img_add_vguide(PyGimpImage *self, PyObject *args) +{ + int xpos; + + if (!PyArg_ParseTuple(args, "i:add_vguide", &xpos)) + return NULL; + + return PyInt_FromLong(gimp_image_add_vguide(self->ID, xpos)); +} + +static PyObject * +img_delete_guide(PyGimpImage *self, PyObject *args) +{ + int guide; + + if (!PyArg_ParseTuple(args, "i:delete_guide", &guide)) + return NULL; + + if (!gimp_image_delete_guide(self->ID, guide)) { + PyErr_Format(pygimp_error, + "could not delete guide (ID %d) from image (ID %d)", + guide, self->ID); + return NULL; + } + + Py_INCREF(Py_None); + return Py_None; +} + +static PyObject * +img_find_next_guide(PyGimpImage *self, PyObject *args) +{ + int guide; + + if (!PyArg_ParseTuple(args, "i:find_next_guide", &guide)) + return NULL; + + return PyInt_FromLong(gimp_image_find_next_guide(self->ID, guide)); +} + +static PyObject * +img_get_guide_orientation(PyGimpImage *self, PyObject *args) +{ + int guide; + + if (!PyArg_ParseTuple(args, "i:get_guide_orientation", &guide)) + return NULL; + + return PyInt_FromLong(gimp_image_get_guide_orientation(self->ID, guide)); +} + +static PyObject * +img_get_guide_position(PyGimpImage *self, PyObject *args) +{ + int guide; + + if (!PyArg_ParseTuple(args, "i:get_guide_position", &guide)) + return NULL; + + return PyInt_FromLong(gimp_image_get_guide_position(self->ID, guide)); +} + +static PyObject * +img_undo_is_enabled(PyGimpImage *self) +{ + return PyBool_FromLong(gimp_image_undo_is_enabled(self->ID)); +} + +static PyObject * +img_undo_freeze(PyGimpImage *self) +{ + return PyBool_FromLong(gimp_image_undo_freeze(self->ID)); +} + +static PyObject * +img_undo_thaw(PyGimpImage *self) +{ + return PyBool_FromLong(gimp_image_undo_thaw(self->ID)); +} + +static PyObject * +img_duplicate(PyGimpImage *self) +{ + return pygimp_image_new(gimp_image_duplicate(self->ID)); +} + +static PyObject * +img_undo_group_start(PyGimpImage *self) +{ + if (!gimp_image_undo_group_start(self->ID)) { + PyErr_Format(pygimp_error, + "could not start undo group on image (ID %d)", + self->ID); + return NULL; + } + + Py_INCREF(Py_None); + return Py_None; +} + +static PyObject * +img_undo_group_end(PyGimpImage *self) +{ + if (!gimp_image_undo_group_end(self->ID)) { + PyErr_Format(pygimp_error, + "could not end undo group on image (ID %d)", + self->ID); + return NULL; + } + + Py_INCREF(Py_None); + return Py_None; +} + +static PyMethodDef img_methods[] = { + {"add_channel", (PyCFunction)img_add_channel, METH_VARARGS}, + {"insert_channel", (PyCFunction)img_insert_channel, METH_VARARGS | METH_KEYWORDS}, + {"add_layer", (PyCFunction)img_add_layer, METH_VARARGS}, + {"insert_layer", (PyCFunction)img_insert_layer, METH_VARARGS | METH_KEYWORDS}, + {"new_layer", (PyCFunction)img_new_layer, METH_VARARGS | METH_KEYWORDS}, + {"clean_all", (PyCFunction)img_clean_all, METH_NOARGS}, + {"disable_undo", (PyCFunction)img_disable_undo, METH_NOARGS}, + {"enable_undo", (PyCFunction)img_enable_undo, METH_NOARGS}, + {"flatten", (PyCFunction)img_flatten, METH_NOARGS}, + {"lower_channel", (PyCFunction)img_lower_channel, METH_VARARGS}, + {"lower_layer", (PyCFunction)img_lower_layer, METH_VARARGS}, + {"lower_layer_to_bottom", (PyCFunction)img_lower_layer_to_bottom, METH_VARARGS}, + {"merge_visible_layers", (PyCFunction)img_merge_visible_layers, METH_VARARGS}, + {"merge_down", (PyCFunction)img_merge_down, METH_VARARGS}, + {"pick_correlate_layer", (PyCFunction)img_pick_correlate_layer, METH_VARARGS}, + {"raise_channel", (PyCFunction)img_raise_channel, METH_VARARGS}, + {"raise_layer", (PyCFunction)img_raise_layer, METH_VARARGS}, + {"raise_layer_to_top", (PyCFunction)img_raise_layer_to_top, METH_VARARGS}, + {"remove_channel", (PyCFunction)img_remove_channel, METH_VARARGS}, + {"remove_layer", (PyCFunction)img_remove_layer, METH_VARARGS}, + {"resize", (PyCFunction)img_resize, METH_VARARGS | METH_KEYWORDS}, + {"resize_to_layers", (PyCFunction)img_resize_to_layers, METH_NOARGS}, + {"get_component_active", (PyCFunction)img_get_component_active, METH_VARARGS}, + {"get_component_visible", (PyCFunction)img_get_component_visible, METH_VARARGS}, + {"set_component_active", (PyCFunction)img_set_component_active, METH_VARARGS}, + {"set_component_visible", (PyCFunction)img_set_component_visible, METH_VARARGS}, + {"parasite_find", (PyCFunction)img_parasite_find, METH_VARARGS}, + {"parasite_attach", (PyCFunction)img_parasite_attach, METH_VARARGS}, + {"attach_new_parasite", (PyCFunction)img_attach_new_parasite, METH_VARARGS | METH_KEYWORDS}, + {"parasite_detach", (PyCFunction)img_parasite_detach, METH_VARARGS}, + {"parasite_list", (PyCFunction)img_parasite_list, METH_NOARGS}, + {"get_layer_by_tattoo",(PyCFunction)img_get_layer_by_tattoo,METH_VARARGS}, + {"get_channel_by_tattoo",(PyCFunction)img_get_channel_by_tattoo,METH_VARARGS}, + {"add_hguide", (PyCFunction)img_add_hguide, METH_VARARGS}, + {"add_vguide", (PyCFunction)img_add_vguide, METH_VARARGS}, + {"delete_guide", (PyCFunction)img_delete_guide, METH_VARARGS}, + {"find_next_guide", (PyCFunction)img_find_next_guide, METH_VARARGS}, + {"get_guide_orientation",(PyCFunction)img_get_guide_orientation,METH_VARARGS}, + {"get_guide_position", (PyCFunction)img_get_guide_position, METH_VARARGS}, + {"scale", (PyCFunction)img_scale, METH_VARARGS | METH_KEYWORDS}, + {"crop", (PyCFunction)img_crop, METH_VARARGS | METH_KEYWORDS}, + {"free_shadow", (PyCFunction)img_free_shadow, METH_NOARGS}, + {"unset_active_channel", (PyCFunction)img_unset_active_channel, METH_NOARGS}, + {"undo_is_enabled", (PyCFunction)img_undo_is_enabled, METH_NOARGS}, + {"undo_freeze", (PyCFunction)img_undo_freeze, METH_NOARGS}, + {"undo_thaw", (PyCFunction)img_undo_thaw, METH_NOARGS}, + {"duplicate", (PyCFunction)img_duplicate, METH_NOARGS}, + {"undo_group_start", (PyCFunction)img_undo_group_start, METH_NOARGS}, + {"undo_group_end", (PyCFunction)img_undo_group_end, METH_NOARGS}, + {NULL, NULL} /* sentinel */ +}; + +static PyObject * +img_get_ID(PyGimpImage *self, void *closure) +{ + return PyInt_FromLong(self->ID); +} + +static PyObject * +img_get_active_channel(PyGimpImage *self, void *closure) +{ + gint32 id = gimp_image_get_active_channel(self->ID); + + if (id == -1) { + Py_INCREF(Py_None); + return Py_None; + } + + return pygimp_channel_new(id); +} + +static int +img_set_active_channel(PyGimpImage *self, PyObject *value, void *closure) +{ + PyGimpChannel *chn; + + if (value == NULL) { + PyErr_SetString(PyExc_TypeError, "cannot delete active_channel"); + return -1; + } + + if (!pygimp_channel_check(value)) { + PyErr_SetString(PyExc_TypeError, "type mismatch"); + return -1; + } + + chn = (PyGimpChannel *)value; + + if (!gimp_image_set_active_channel(self->ID, chn->ID)) { + PyErr_Format(pygimp_error, + "could not set active channel (ID %d) on image (ID %d)", + chn->ID, self->ID); + return -1; + } + + return 0; +} + +static PyObject * +img_get_active_drawable(PyGimpImage *self, void *closure) +{ + gint32 id = gimp_image_get_active_drawable(self->ID); + + if (id == -1) { + Py_INCREF(Py_None); + return Py_None; + } + + return pygimp_drawable_new(NULL, id); +} + +static PyObject * +img_get_active_layer(PyGimpImage *self, void *closure) +{ + gint32 id = gimp_image_get_active_layer(self->ID); + + if (id == -1) { + Py_INCREF(Py_None); + return Py_None; + } + + return pygimp_group_layer_new(id); +} + +static int +img_set_active_layer(PyGimpImage *self, PyObject *value, void *closure) +{ + PyGimpLayer *lay; + + if (value == NULL) { + PyErr_SetString(PyExc_TypeError, "cannot delete active_layer"); + return -1; + } + + if (!pygimp_layer_check(value)) { + PyErr_SetString(PyExc_TypeError, "type mismatch"); + return -1; + } + + lay = (PyGimpLayer *)value; + + if (!gimp_image_set_active_layer(self->ID, lay->ID)) { + PyErr_Format(pygimp_error, + "could not set active layer (ID %d) on image (ID %d)", + lay->ID, self->ID); + return -1; + } + + return 0; +} + +static PyObject * +img_get_base_type(PyGimpImage *self, void *closure) +{ + return PyInt_FromLong(gimp_image_base_type(self->ID)); +} + +static PyObject * +img_get_channels(PyGimpImage *self, void *closure) +{ + gint32 *channels; + gint n_channels, i; + PyObject *ret; + + channels = gimp_image_get_channels(self->ID, &n_channels); + + ret = PyList_New(n_channels); + + for (i = 0; i < n_channels; i++) + PyList_SetItem(ret, i, pygimp_channel_new(channels[i])); + + g_free(channels); + + return ret; +} + +static PyObject * +img_get_colormap(PyGimpImage *self, void *closure) +{ + guchar *cmap; + gint n_colours; + PyObject *ret; + + cmap = gimp_image_get_colormap(self->ID, &n_colours); + + if (cmap == NULL) { + PyErr_Format(pygimp_error, "could not get colormap for image (ID %d)", + self->ID); + return NULL; + } + + ret = PyString_FromStringAndSize((char *)cmap, n_colours * 3); + g_free(cmap); + + return ret; +} + +static int +img_set_colormap(PyGimpImage *self, PyObject *value, void *closure) +{ + if (value == NULL) { + PyErr_SetString(PyExc_TypeError, "cannot delete colormap"); + return -1; + } + + if (!PyString_Check(value)) { + PyErr_SetString(PyExc_TypeError, "type mismatch"); + return -1; + } + + if (!gimp_image_set_colormap(self->ID, (guchar *)PyString_AsString(value), + PyString_Size(value) / 3)) { + PyErr_Format(pygimp_error, "could not set colormap on image (ID %d)", + self->ID); + return -1; + } + + return 0; +} + +static PyObject * +img_get_is_dirty(PyGimpImage *self, void *closure) +{ + return PyBool_FromLong(gimp_image_is_dirty(self->ID)); +} + +static PyObject * +img_get_filename(PyGimpImage *self, void *closure) +{ + gchar *filename; + + filename = gimp_image_get_filename(self->ID); + + if (filename) { + PyObject *ret = PyString_FromString(filename); + g_free(filename); + return ret; + } + + Py_INCREF(Py_None); + return Py_None; +} + +static int +img_set_filename(PyGimpImage *self, PyObject *value, void *closure) +{ + if (value == NULL) { + PyErr_SetString(PyExc_TypeError, "cannot delete filename"); + return -1; + } + + if (!PyString_Check(value)) { + PyErr_SetString(PyExc_TypeError, "type mismatch"); + return -1; + } + + if (!gimp_image_set_filename(self->ID, PyString_AsString(value))) { + PyErr_SetString(PyExc_TypeError, "could not set filename " + "(possibly bad encoding)"); + return -1; + } + + return 0; +} + +static PyObject * +img_get_uri(PyGimpImage *self, void *closure) +{ + gchar *uri; + + uri = gimp_image_get_uri(self->ID); + + if (uri) { + PyObject *ret = PyString_FromString(uri); + g_free(uri); + return ret; + } + + Py_INCREF(Py_None); + return Py_None; +} + +static PyObject * +img_get_floating_selection(PyGimpImage *self, void *closure) +{ + gint32 id; + + id = gimp_image_get_floating_sel(self->ID); + + if (id == -1) { + Py_INCREF(Py_None); + return Py_None; + } + + return pygimp_layer_new(id); +} + +static PyObject * +img_get_floating_sel_attached_to(PyGimpImage *self, void *closure) +{ + gint32 id; + + id = gimp_image_floating_sel_attached_to(self->ID); + + if (id == -1) { + Py_INCREF(Py_None); + return Py_None; + } + + return pygimp_layer_new(id); +} + +static PyObject * +img_get_layers(PyGimpImage *self, void *closure) +{ + gint32 *layers; + gint n_layers, i; + PyObject *ret; + + layers = gimp_image_get_layers(self->ID, &n_layers); + + ret = PyList_New(n_layers); + + for (i = 0; i < n_layers; i++) + PyList_SetItem(ret, i, pygimp_group_layer_new(layers[i])); + + g_free(layers); + + return ret; +} + +static PyObject * +img_get_name(PyGimpImage *self, void *closure) +{ + gchar *name; + + name = gimp_image_get_name(self->ID); + + if (name) { + PyObject *ret = PyString_FromString(name); + g_free(name); + return ret; + } + + Py_INCREF(Py_None); + return Py_None; +} + +static PyObject * +img_get_selection(PyGimpImage *self, void *closure) +{ + return pygimp_channel_new(gimp_image_get_selection(self->ID)); +} + +static PyObject * +img_get_tattoo_state(PyGimpImage *self, void *closure) +{ + return PyInt_FromLong(gimp_image_get_tattoo_state(self->ID)); +} + +static int +img_set_tattoo_state(PyGimpImage *self, PyObject *value, void *closure) +{ + if (value == NULL) { + PyErr_SetString(PyExc_TypeError, "cannot delete tattoo_state"); + return -1; + } + + if (!PyInt_Check(value)) { + PyErr_SetString(PyExc_TypeError, "type mismatch"); + return -1; + } + + gimp_image_set_tattoo_state(self->ID, PyInt_AsLong(value)); + + return 0; +} + +static PyObject * +img_get_height(PyGimpImage *self, void *closure) +{ + return PyInt_FromLong(gimp_image_height(self->ID)); +} + +static PyObject * +img_get_width(PyGimpImage *self, void *closure) +{ + return PyInt_FromLong(gimp_image_width(self->ID)); +} + + +static PyObject * +img_get_precision(PyGimpImage *self, void *closure) +{ + return PyInt_FromLong(gimp_image_get_precision(self->ID)); +} + +static PyObject * +img_get_resolution(PyGimpImage *self, void *closure) +{ + double xres, yres; + + gimp_image_get_resolution(self->ID, &xres, &yres); + + return Py_BuildValue("(dd)", xres, yres); +} + +static int +img_set_resolution(PyGimpImage *self, PyObject *value, void *closure) +{ + gdouble xres, yres; + + if (value == NULL) { + PyErr_SetString(PyExc_TypeError, "cannot delete resolution"); + return -1; + } + + if (!PySequence_Check(value) || + !PyArg_ParseTuple(value, "dd", &xres, &yres)) { + PyErr_Clear(); + PyErr_SetString(PyExc_TypeError, "type mismatch"); + return -1; + } + + if (!gimp_image_set_resolution(self->ID, xres, yres)) { + PyErr_SetString(PyExc_TypeError, "could not set resolution"); + return -1; + } + + return 0; +} + +static PyObject * +img_get_unit(PyGimpImage *self, void *closure) +{ + return PyInt_FromLong(gimp_image_get_unit(self->ID)); +} + +static int +img_set_unit(PyGimpImage *self, PyObject *value, void *closure) +{ + if (value == NULL) { + PyErr_SetString(PyExc_TypeError, "cannot delete unit"); + return -1; + } + + if (!PyInt_Check(value)) { + PyErr_SetString(PyExc_TypeError, "type mismatch"); + return -1; + } + + if (!gimp_image_set_unit(self->ID, PyInt_AsLong(value))) { + PyErr_SetString(PyExc_TypeError, "could not set unit"); + return -1; + } + + return 0; +} + +static PyObject * +img_get_vectors(PyGimpImage *self, void *closure) +{ + int *vectors; + int i, num_vectors; + PyObject *ret; + + vectors = gimp_image_get_vectors(self->ID, &num_vectors); + + ret = PyList_New(num_vectors); + + for (i = 0; i < num_vectors; i++) + PyList_SetItem(ret, i, pygimp_vectors_new(vectors[i])); + + g_free(vectors); + + return ret; +} + +static PyObject * +img_get_active_vectors(PyGimpImage *self, void *closure) +{ + gint32 id = gimp_image_get_active_vectors(self->ID); + + if (id == -1) { + Py_INCREF(Py_None); + return Py_None; + } + + return pygimp_vectors_new(id); +} + +static int +img_set_active_vectors(PyGimpImage *self, PyObject *value, void *closure) +{ + PyGimpVectors *vtr; + + if (value == NULL) { + PyErr_SetString(PyExc_TypeError, "cannot delete active_vectors"); + return -1; + } + + if (!pygimp_vectors_check(value)) { + PyErr_SetString(PyExc_TypeError, "type mismatch"); + return -1; + } + + vtr = (PyGimpVectors *)value; + + if (!gimp_image_set_active_vectors(self->ID, vtr->ID)) { + PyErr_Format(pygimp_error, + "could not set active vectors (ID %d) on image (ID %d)", + vtr->ID, self->ID); + return -1; + } + + return 0; +} + +static PyGetSetDef img_getsets[] = { + { "ID", (getter)img_get_ID, (setter)0 }, + { "active_channel", (getter)img_get_active_channel, + (setter)img_set_active_channel }, + { "active_drawable", (getter)img_get_active_drawable, (setter)0 }, + { "active_layer", (getter)img_get_active_layer, + (setter)img_set_active_layer }, + { "active_vectors", (getter)img_get_active_vectors, + (setter)img_set_active_vectors}, + { "base_type", (getter)img_get_base_type, (setter)0 }, + { "channels", (getter)img_get_channels, (setter)0 }, + { "colormap", (getter)img_get_colormap, (setter)img_set_colormap }, + { "dirty", (getter)img_get_is_dirty, (setter)0 }, + { "filename", (getter)img_get_filename, (setter)img_set_filename }, + { "floating_selection", (getter)img_get_floating_selection, (setter)0 }, + { "floating_sel_attached_to", (getter)img_get_floating_sel_attached_to, + (setter)0 }, + { "height", (getter)img_get_height, (setter)0 }, + { "layers", (getter)img_get_layers, (setter)0 }, + { "name", (getter)img_get_name, (setter)0 }, + { "precision", (getter)img_get_precision, (setter)0 }, + { "resolution", (getter)img_get_resolution, (setter)img_set_resolution }, + { "selection", (getter)img_get_selection, (setter)0 }, + { "tattoo_state", (getter)img_get_tattoo_state, + (setter)img_set_tattoo_state }, + { "unit", (getter)img_get_unit, (setter)img_set_unit }, + { "uri", (getter)img_get_uri, (setter)0 }, + { "vectors", (getter)img_get_vectors, (setter)0 }, + { "width", (getter)img_get_width, (setter)0 }, + { NULL, (getter)0, (setter)0 } +}; + +/* ---------- */ + + +PyObject * +pygimp_image_new(gint32 ID) +{ + PyGimpImage *self; + + if (!gimp_image_is_valid(ID)) { + Py_INCREF(Py_None); + return Py_None; + } + + self = PyObject_NEW(PyGimpImage, &PyGimpImage_Type); + + if (self == NULL) + return NULL; + + self->ID = ID; + + return (PyObject *)self; +} + + +static void +img_dealloc(PyGimpImage *self) +{ + /* XXXX Add your own cleanup code here */ + PyObject_DEL(self); +} + +static PyObject * +img_repr(PyGimpImage *self) +{ + PyObject *s; + gchar *name; + + name = gimp_image_get_name(self->ID); + s = PyString_FromFormat("", name ? name : "(null)"); + g_free(name); + + return s; +} + +static int +img_cmp(PyGimpImage *self, PyGimpImage *other) +{ + if (self->ID == other->ID) + return 0; + + if (self->ID > other->ID) + return -1; + + return 1; +} + +static int +img_init(PyGimpImage *self, PyObject *args, PyObject *kwargs) +{ + guint width, height; + GimpImageBaseType type = GIMP_RGB; + + static char *kwlist[] = { "width", "height", "type", NULL }; + + if (!PyArg_ParseTupleAndKeywords(args, kwargs, + "ii|i:gimp.Image.__init__", kwlist, + &width, &height, &type)) + return -1; + + self->ID = gimp_image_new(width, height, type); + + if (self->ID < 0) { + PyErr_Format(pygimp_error, + "could not create image (width: %d, height: %d, type: %d)", + width, height, type); + return -1; + } + + return 0; +} + +PyTypeObject PyGimpImage_Type = { + PyObject_HEAD_INIT(NULL) + 0, /* ob_size */ + "gimp.Image", /* tp_name */ + sizeof(PyGimpImage), /* tp_basicsize */ + 0, /* tp_itemsize */ + /* methods */ + (destructor)img_dealloc, /* tp_dealloc */ + (printfunc)0, /* tp_print */ + (getattrfunc)0, /* tp_getattr */ + (setattrfunc)0, /* tp_setattr */ + (cmpfunc)img_cmp, /* tp_compare */ + (reprfunc)img_repr, /* tp_repr */ + 0, /* tp_as_number */ + 0, /* tp_as_sequence */ + 0, /* tp_as_mapping */ + (hashfunc)0, /* tp_hash */ + (ternaryfunc)0, /* tp_call */ + (reprfunc)0, /* tp_str */ + (getattrofunc)0, /* tp_getattro */ + (setattrofunc)0, /* tp_setattro */ + 0, /* tp_as_buffer */ + Py_TPFLAGS_DEFAULT, /* tp_flags */ + NULL, /* Documentation string */ + (traverseproc)0, /* tp_traverse */ + (inquiry)0, /* tp_clear */ + (richcmpfunc)0, /* tp_richcompare */ + 0, /* tp_weaklistoffset */ + (getiterfunc)0, /* tp_iter */ + (iternextfunc)0, /* tp_iternext */ + img_methods, /* tp_methods */ + 0, /* tp_members */ + img_getsets, /* tp_getset */ + (PyTypeObject *)0, /* tp_base */ + (PyObject *)0, /* tp_dict */ + 0, /* tp_descr_get */ + 0, /* tp_descr_set */ + 0, /* tp_dictoffset */ + (initproc)img_init, /* tp_init */ + (allocfunc)0, /* tp_alloc */ + (newfunc)0, /* tp_new */ +}; -- cgit v1.2.3