added pygimp to tree, as organised with Marc Lehmann. I have not hooked it

1999-09-05  James Henstridge  <james@daa.com.au>

	* plug-ins/pygimp/*: added pygimp to tree, as organised with Marc
	Lehmann.  I have not hooked it into the main makefile yet.  That
	should not be difficult though.
This commit is contained in:
James Henstridge
1999-09-05 15:46:57 +00:00
committed by James Henstridge
parent 34b6cabd7a
commit 910e7cb689
38 changed files with 16203 additions and 0 deletions

View File

@ -1,3 +1,9 @@
1999-09-05 James Henstridge <james@daa.com.au>
* plug-ins/pygimp/*: added pygimp to tree, as organised with Marc
Lehmann. I have not hooked it into the main makefile yet. That
should not be difficult though.
Sun Sep 5 14:48:30 MEST 1999 Sven Neumann <sven@gimp.org>
* app/gimpcontextpreview.c: small cosmetic change

View File

@ -0,0 +1,17 @@
Makefile
#Makefile.in
*.pyc
*.pyo
*.so
configure
config.log
config.h
config.cache
stamp-h
config.h.in
stamp-h.in
aclocal.m4
INSTALL
mkinstalldirs
install-sh

0
plug-ins/pygimp/AUTHORS Normal file
View File

107
plug-ins/pygimp/ChangeLog Normal file
View File

@ -0,0 +1,107 @@
1999-07-08 James Henstridge <james@daa.com.au>
* plug-ins/shadow_bevel.py: added {disable,enable}_undo() calls. Also
made it possible to turn off the creation of a shadow.
* plug-ins/foggify.py: added disable_undo() and enable_undo() calls
round the plugin code.
* plug-ins/Makefile.am: forgot to add foggify and shadow_bevel to
the EXTRA_DIST list.
* gimpui.py: fixed some small bugs that caused an exception when
loading on some versions of python. Weird thing is, it did not
cause problems on my computer (using 1.5.1)
1999-07-05 James Henstridge <james@daa.com.au>
* plug-ins/foggify.py, plug-ins/shadow_bevel.py: two new example
scripts.
1999-07-04 James Henstridge <james@daa.com.au>
* gimpmodule.c: added support for parasites. This new code is
conditionally compiled if GIMP_HAVE_PARASITES is defined.
Added other gimp 1.1 features to gimpmodule.
1999-07-03 James Henstridge <james@daa.com.au>
* gimpmodule.c (initgimp): added {major,minor,micro}_version constants
to gimpmodule.
(*) removed all the empty __doc__ strings -- they were just wasting
space, and I have other docs in there now.
* plug-ins/clothify.py (python_clothify): same here.
* plug-ins/sphere.py (python_sphere): some small hacks to get the
plugin to work with both gimp 1.0 and 1.1 -- using the pattern
"if pdb.gimp_whatever.nparams == n" to check if the img parameter
should be removed.
* plug-ins/pdbbrowse.py (BrowseWin.extension_pdb_browse): fixed
small bug.
1999-07-02 James Henstridge <james@daa.com.au>
* plug-ins/whirlpinch.py (python_whirl_pinch): adjusted plug in to
work with drawable changes.
* gimpmodule.c: removed the drawable type -- now only layer or channel
types are used. Also moved the drawable type's methods to both the
layer and channel object types. Also added some of the attributes of
the drawable object to layer and channel objects (some aren't needed
anymore, since layers are clearly defined as layers, and channels
as channels).
Make tile and pixel region objects keep a reference to their
associated drawable.
Added attributes has_alpha, is_colour, is_grey and is_indexed to
layer and channel objects.
1999-06-22 James Henstridge <james@daa.com.au>
* gimpplugin.py: renamed from plugin.py. This is mainly to reduce
namespace polution.
* getvals.py: removed file. It has been replaced by the much more
functional gimpfu module.
* plug-ins/gimpcons.py: added a browse button that will display the
pdbbrowse window, which can then be used to choose a pdb function.
The selected pdb function gets its prototype inserted on the
command line.
* plug-ins/pdbbrowse.py: converted to use GTK+ widgets and gimpfu.
* plug-ins/gimpcons.py: converted to use gimpfu and gtkcons.py.
* plug-ings/gtkcons.py: a GTK replacement for tkcons.py.
* plug-ins/whirlpinch.py, plug-ins/sphere.py: converted these two
to use gimpfu.
* gimpshelf.py (shelf): some changes so that the gimp internal types
will pickle correctly.
* gimpmodule.c (initgimp): export the type objects for gimpmodule's
internal types. This is mainly to help get pickling to work
correctly.
(_id2*): new functions to help convert id's to the builtin types.
* plug-ins/clothify.py: converted to use gimpfu module.
1999-06-21 James Henstridge <james@daa.com.au>
* gimpfu.py: a simplified interface to writing GIMP plugins. It
handles all the user interaction stuff and saving the last used
values. It uses pygtk, so should match the interface of the rest
of gimp.
* gimpui.py: new file that implements a number of useful widgets
for use with the interfaces of plugins. It requires pygtk.
* gimpmodule.c (tuple_to_GParam): accept None for layer, channel
or drawable arguments to PDB functions. This value gets treated
like an ID of -1.
(img_cmp, lay_cmp, chn_cmp, drw_cmp): added compare functions so
that the == operator works as expected with those object types.

View File

@ -0,0 +1,17 @@
SUBDIRS = doc plug-ins
INCLUDES = $(PYTHON_INCLUDES) $(PYTHON_CFLAGS) $(GIMP_CFLAGS_NOUI)
pyexec_PROGRAMS = gimpmodule$(SO)
gimpmodule__SO__SOURCES = gimpmodule.c
gimpmodule__SO__LDADD = $(GIMP_LIBS_NOUI)
gimpmodule__SO__LINK = $(PYTHON_LINK)
python_PYTHON = gimpplugin.py gimpenums.py gimpshelf.py \
gimpui.py gimpfu.py
EXTRA_DIST = pygimp.spec
snap:
$(MAKE) dist distdir=$(PACKAGE)-SNAP-`date +"%Y%m%d"`

457
plug-ins/pygimp/Makefile.in Normal file
View File

@ -0,0 +1,457 @@
# This has been modified slightly. The Makefile.am file has been moved to
# Makefile.am.14 because it uses some non standard extensions. This should
# be resolved when automake-1.5 comes out.
# Makefile.in generated automatically by automake 1.4 from Makefile.am
# Copyright (C) 1994, 1995-8, 1999 Free Software Foundation, Inc.
# This Makefile.in is free software; the Free Software Foundation
# gives unlimited permission to copy and/or distribute it,
# with or without modifications, as long as this notice is preserved.
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY, to the extent permitted by law; without
# even the implied warranty of MERCHANTABILITY or FITNESS FOR A
# PARTICULAR PURPOSE.
SHELL = @SHELL@
srcdir = @srcdir@
top_srcdir = @top_srcdir@
VPATH = @srcdir@
prefix = @prefix@
exec_prefix = @exec_prefix@
bindir = @bindir@
sbindir = @sbindir@
libexecdir = @libexecdir@
datadir = @datadir@
sysconfdir = @sysconfdir@
sharedstatedir = @sharedstatedir@
localstatedir = @localstatedir@
libdir = @libdir@
infodir = @infodir@
mandir = @mandir@
includedir = @includedir@
oldincludedir = /usr/include
DESTDIR =
pkgdatadir = $(datadir)/@PACKAGE@
pkglibdir = $(libdir)/@PACKAGE@
pkgincludedir = $(includedir)/@PACKAGE@
top_builddir = .
ACLOCAL = @ACLOCAL@
AUTOCONF = @AUTOCONF@
AUTOMAKE = @AUTOMAKE@
AUTOHEADER = @AUTOHEADER@
INSTALL = @INSTALL@
INSTALL_PROGRAM = @INSTALL_PROGRAM@ $(AM_INSTALL_PROGRAM_FLAGS)
INSTALL_DATA = @INSTALL_DATA@
INSTALL_SCRIPT = @INSTALL_SCRIPT@
transform = @program_transform_name@
NORMAL_INSTALL = :
PRE_INSTALL = :
POST_INSTALL = :
NORMAL_UNINSTALL = :
PRE_UNINSTALL = :
POST_UNINSTALL = :
CC = @CC@
GIMPTOOL = @GIMPTOOL@
GIMP_CFLAGS_NOUI = @GIMP_CFLAGS_NOUI@
GIMP_LIBS_NOUI = @GIMP_LIBS_NOUI@
MAKEINFO = @MAKEINFO@
OPT = @OPT@
PACKAGE = @PACKAGE@
PYTHON = @PYTHON@
PYTHON_CFLAGS = @PYTHON_CFLAGS@
PYTHON_INCLUDES = @PYTHON_INCLUDES@
PYTHON_LINK = @PYTHON_LINK@
SO = @SO@
VERSION = @VERSION@
pluginexecdir = @pluginexecdir@
pyexecdir = @pyexecdir@
pythondir = @pythondir@
SUBDIRS = doc plug-ins
INCLUDES = $(PYTHON_INCLUDES) $(PYTHON_CFLAGS) $(GIMP_CFLAGS_NOUI)
pyexec_PROGRAMS = gimpmodule$(SO)
gimpmodule__SO__SOURCES = gimpmodule.c
gimpmodule__SO__LDADD = $(GIMP_LIBS_NOUI)
gimpmodule__SO__LINK = $(PYTHON_LINK)
python_PYTHON = gimpplugin.py gimpenums.py gimpshelf.py gimpui.py gimpfu.py
EXTRA_DIST = pygimp.spec
ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
mkinstalldirs = $(SHELL) $(top_srcdir)/mkinstalldirs
CONFIG_CLEAN_FILES =
PROGRAMS = $(pyexec_PROGRAMS)
DEFS = @DEFS@ -I. -I$(srcdir)
CPPFLAGS = @CPPFLAGS@
LDFLAGS = @LDFLAGS@
LIBS = @LIBS@
gimpmodule__SO__OBJECTS = gimpmodule.o
gimpmodule__SO__DEPENDENCIES =
gimpmodule__SO__LDFLAGS =
CFLAGS = @CFLAGS@
COMPILE = $(CC) $(DEFS) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS)
CCLD = $(CC)
LINK = $(CCLD) $(AM_CFLAGS) $(CFLAGS) $(LDFLAGS) -o $@
PYTHONFILES = gimpplugin.py gimpenums.py gimpshelf.py gimpui.py \
gimpfu.py
py_compile = $(top_srcdir)/py-compile
DIST_COMMON = README $(PYTHONFILES) AUTHORS COPYING ChangeLog INSTALL \
Makefile.am.14 Makefile.in NEWS aclocal.m4 configure configure.in \
install-sh missing mkinstalldirs py-compile
DISTFILES = $(DIST_COMMON) $(SOURCES) $(HEADERS) $(TEXINFOS) $(EXTRA_DIST)
TAR = tar
GZIP_ENV = --best
SOURCES = $(gimpmodule__SO__SOURCES)
OBJECTS = $(gimpmodule__SO__OBJECTS)
all: all-redirect
.SUFFIXES:
.SUFFIXES: .S .c .o .s
Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status
cd $(top_builddir) \
&& CONFIG_FILES=$@ CONFIG_HEADERS= $(SHELL) ./config.status
$(ACLOCAL_M4): configure.in
cd $(srcdir) && $(ACLOCAL)
config.status: $(srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES)
$(SHELL) ./config.status --recheck
$(srcdir)/configure: $(srcdir)/configure.in $(ACLOCAL_M4) $(CONFIGURE_DEPENDENCIES)
cd $(srcdir) && $(AUTOCONF)
mostlyclean-pyexecPROGRAMS:
clean-pyexecPROGRAMS:
-test -z "$(pyexec_PROGRAMS)" || rm -f $(pyexec_PROGRAMS)
distclean-pyexecPROGRAMS:
maintainer-clean-pyexecPROGRAMS:
install-pyexecPROGRAMS: $(pyexec_PROGRAMS)
@$(NORMAL_INSTALL)
$(mkinstalldirs) $(DESTDIR)$(pyexecdir)
@list='$(pyexec_PROGRAMS)'; for p in $$list; do \
if test -f $$p; then \
echo " $(INSTALL_PROGRAM) $$p $(DESTDIR)$(pyexecdir)/`echo $$p|sed 's/$(EXEEXT)$$//'|sed '$(transform)'|sed 's/$$/$(EXEEXT)/'`"; \
$(INSTALL_PROGRAM) $$p $(DESTDIR)$(pyexecdir)/`echo $$p|sed 's/$(EXEEXT)$$//'|sed '$(transform)'|sed 's/$$/$(EXEEXT)/'`; \
else :; fi; \
done
uninstall-pyexecPROGRAMS:
@$(NORMAL_UNINSTALL)
list='$(pyexec_PROGRAMS)'; for p in $$list; do \
rm -f $(DESTDIR)$(pyexecdir)/`echo $$p|sed 's/$(EXEEXT)$$//'|sed '$(transform)'|sed 's/$$/$(EXEEXT)/'`; \
done
.c.o:
$(COMPILE) -c $<
.s.o:
$(COMPILE) -c $<
.S.o:
$(COMPILE) -c $<
mostlyclean-compile:
-rm -f *.o core *.core
clean-compile:
distclean-compile:
-rm -f *.tab.c
maintainer-clean-compile:
gimpmodule$(SO): $(gimpmodule__SO__OBJECTS) $(gimpmodule__SO__DEPENDENCIES)
@rm -f gimpmodule$(SO)
$(gimpmodule__SO__LINK) $(gimpmodule__SO__LDFLAGS) $(gimpmodule__SO__OBJECTS) $(gimpmodule__SO__LDADD) $(LIBS)
mostlyclean-pythonPYTHON:
clean-pythonPYTHON:
distclean-pythonPYTHON:
maintainer-clean-pythonPYTHON:
install-pythonPYTHON: $(python_PYTHON)
@$(NORMAL_INSTALL)
$(mkinstalldirs) $(DESTDIR)$(pythondir)
@list='$(python_PYTHON)'; for p in $$list; do\
if test -f $(srcdir)/$$p; then \
echo " $(INSTALL_PROGRAM) $(srcdir)/$$p $(DESTDIR)$(pythondir)/$$p"; \
$(INSTALL_DATA) $(srcdir)/$$p $(DESTDIR)$(pythondir)/$$p; \
else :; fi; \
done
@PYTHON=$(PYTHON) $(py_compile) --basedir $(DESTDIR)$(pythondir) $(python_PYTHON)
uninstall-pythonPYTHON:
@$(NORMAL_UNINSTALL)
list='$(python_PYTHON)'; for p in $$list; do \
rm -f $(DESTDIR)$(pythondir)/$$p; \
rm -f $(DESTDIR)$(pythondir)/$${p}c; \
rm -f $(DESTDIR)$(pythondir)/$${p}o; \
done
# This directory's subdirectories are mostly independent; you can cd
# into them and run `make' without going through this Makefile.
# To change the values of `make' variables: instead of editing Makefiles,
# (1) if the variable is set in `config.status', edit `config.status'
# (which will cause the Makefiles to be regenerated when you run `make');
# (2) otherwise, pass the desired values on the `make' command line.
@SET_MAKE@
all-recursive install-data-recursive install-exec-recursive \
installdirs-recursive install-recursive uninstall-recursive \
check-recursive installcheck-recursive info-recursive dvi-recursive:
@set fnord $(MAKEFLAGS); amf=$$2; \
dot_seen=no; \
target=`echo $@ | sed s/-recursive//`; \
list='$(SUBDIRS)'; for subdir in $$list; do \
echo "Making $$target in $$subdir"; \
if test "$$subdir" = "."; then \
dot_seen=yes; \
local_target="$$target-am"; \
else \
local_target="$$target"; \
fi; \
(cd $$subdir && $(MAKE) $(AM_MAKEFLAGS) $$local_target) \
|| case "$$amf" in *=*) exit 1;; *k*) fail=yes;; *) exit 1;; esac; \
done; \
if test "$$dot_seen" = "no"; then \
$(MAKE) $(AM_MAKEFLAGS) "$$target-am" || exit 1; \
fi; test -z "$$fail"
mostlyclean-recursive clean-recursive distclean-recursive \
maintainer-clean-recursive:
@set fnord $(MAKEFLAGS); amf=$$2; \
dot_seen=no; \
rev=''; list='$(SUBDIRS)'; for subdir in $$list; do \
rev="$$subdir $$rev"; \
test "$$subdir" = "." && dot_seen=yes; \
done; \
test "$$dot_seen" = "no" && rev=". $$rev"; \
target=`echo $@ | sed s/-recursive//`; \
for subdir in $$rev; do \
echo "Making $$target in $$subdir"; \
if test "$$subdir" = "."; then \
local_target="$$target-am"; \
else \
local_target="$$target"; \
fi; \
(cd $$subdir && $(MAKE) $(AM_MAKEFLAGS) $$local_target) \
|| case "$$amf" in *=*) exit 1;; *k*) fail=yes;; *) exit 1;; esac; \
done && test -z "$$fail"
tags-recursive:
list='$(SUBDIRS)'; for subdir in $$list; do \
test "$$subdir" = . || (cd $$subdir && $(MAKE) $(AM_MAKEFLAGS) tags); \
done
tags: TAGS
ID: $(HEADERS) $(SOURCES) $(LISP)
list='$(SOURCES) $(HEADERS)'; \
unique=`for i in $$list; do echo $$i; done | \
awk ' { files[$$0] = 1; } \
END { for (i in files) print i; }'`; \
here=`pwd` && cd $(srcdir) \
&& mkid -f$$here/ID $$unique $(LISP)
TAGS: tags-recursive $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) $(LISP)
tags=; \
here=`pwd`; \
list='$(SUBDIRS)'; for subdir in $$list; do \
if test "$$subdir" = .; then :; else \
test -f $$subdir/TAGS && tags="$$tags -i $$here/$$subdir/TAGS"; \
fi; \
done; \
list='$(SOURCES) $(HEADERS)'; \
unique=`for i in $$list; do echo $$i; done | \
awk ' { files[$$0] = 1; } \
END { for (i in files) print i; }'`; \
test -z "$(ETAGS_ARGS)$$unique$(LISP)$$tags" \
|| (cd $(srcdir) && etags $(ETAGS_ARGS) $$tags $$unique $(LISP) -o $$here/TAGS)
mostlyclean-tags:
clean-tags:
distclean-tags:
-rm -f TAGS ID
maintainer-clean-tags:
distdir = $(PACKAGE)-$(VERSION)
top_distdir = $(distdir)
# This target untars the dist file and tries a VPATH configuration. Then
# it guarantees that the distribution is self-contained by making another
# tarfile.
distcheck: dist
-rm -rf $(distdir)
GZIP=$(GZIP_ENV) $(TAR) zxf $(distdir).tar.gz
mkdir $(distdir)/=build
mkdir $(distdir)/=inst
dc_install_base=`cd $(distdir)/=inst && pwd`; \
cd $(distdir)/=build \
&& ../configure --srcdir=.. --prefix=$$dc_install_base \
&& $(MAKE) $(AM_MAKEFLAGS) \
&& $(MAKE) $(AM_MAKEFLAGS) dvi \
&& $(MAKE) $(AM_MAKEFLAGS) check \
&& $(MAKE) $(AM_MAKEFLAGS) install \
&& $(MAKE) $(AM_MAKEFLAGS) installcheck \
&& $(MAKE) $(AM_MAKEFLAGS) dist
-rm -rf $(distdir)
@banner="$(distdir).tar.gz is ready for distribution"; \
dashes=`echo "$$banner" | sed s/./=/g`; \
echo "$$dashes"; \
echo "$$banner"; \
echo "$$dashes"
dist: distdir
-chmod -R a+r $(distdir)
GZIP=$(GZIP_ENV) $(TAR) chozf $(distdir).tar.gz $(distdir)
-rm -rf $(distdir)
dist-all: distdir
-chmod -R a+r $(distdir)
GZIP=$(GZIP_ENV) $(TAR) chozf $(distdir).tar.gz $(distdir)
-rm -rf $(distdir)
distdir: $(DISTFILES)
-rm -rf $(distdir)
mkdir $(distdir)
-chmod 777 $(distdir)
@for file in $(DISTFILES); do \
d=$(srcdir); \
if test -d $$d/$$file; then \
cp -pr $$/$$file $(distdir)/$$file; \
else \
test -f $(distdir)/$$file \
|| ln $$d/$$file $(distdir)/$$file 2> /dev/null \
|| cp -p $$d/$$file $(distdir)/$$file || :; \
fi; \
done
for subdir in $(SUBDIRS); do \
if test "$$subdir" = .; then :; else \
test -d $(distdir)/$$subdir \
|| mkdir $(distdir)/$$subdir \
|| exit 1; \
chmod 777 $(distdir)/$$subdir; \
(cd $$subdir && $(MAKE) $(AM_MAKEFLAGS) top_distdir=../$(distdir) distdir=../$(distdir)/$$subdir distdir) \
|| exit 1; \
fi; \
done
gimpmodule.o: gimpmodule.c
info-am:
info: info-recursive
dvi-am:
dvi: dvi-recursive
check-am: all-am
check: check-recursive
installcheck-am:
installcheck: installcheck-recursive
install-exec-am: install-pyexecPROGRAMS
install-exec: install-exec-recursive
install-data-am: install-pythonPYTHON
install-data: install-data-recursive
install-am: all-am
@$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am
install: install-recursive
uninstall-am: uninstall-pyexecPROGRAMS uninstall-pythonPYTHON
uninstall: uninstall-recursive
all-am: Makefile $(PROGRAMS)
all-redirect: all-recursive
install-strip:
$(MAKE) $(AM_MAKEFLAGS) AM_INSTALL_PROGRAM_FLAGS=-s install
installdirs: installdirs-recursive
installdirs-am:
$(mkinstalldirs) $(DESTDIR)$(pyexecdir) $(DESTDIR)$(pythondir)
mostlyclean-generic:
clean-generic:
distclean-generic:
-rm -f Makefile $(CONFIG_CLEAN_FILES)
-rm -f config.cache config.log stamp-h stamp-h[0-9]*
maintainer-clean-generic:
mostlyclean-am: mostlyclean-pyexecPROGRAMS mostlyclean-compile \
mostlyclean-pythonPYTHON mostlyclean-tags \
mostlyclean-generic
mostlyclean: mostlyclean-recursive
clean-am: clean-pyexecPROGRAMS clean-compile clean-pythonPYTHON \
clean-tags clean-generic mostlyclean-am
clean: clean-recursive
distclean-am: distclean-pyexecPROGRAMS distclean-compile \
distclean-pythonPYTHON distclean-tags distclean-generic \
clean-am
distclean: distclean-recursive
-rm -f config.status
maintainer-clean-am: maintainer-clean-pyexecPROGRAMS \
maintainer-clean-compile maintainer-clean-pythonPYTHON \
maintainer-clean-tags maintainer-clean-generic \
distclean-am
@echo "This command is intended for maintainers to use;"
@echo "it deletes files that may require special tools to rebuild."
maintainer-clean: maintainer-clean-recursive
-rm -f config.status
.PHONY: mostlyclean-pyexecPROGRAMS distclean-pyexecPROGRAMS \
clean-pyexecPROGRAMS maintainer-clean-pyexecPROGRAMS \
uninstall-pyexecPROGRAMS install-pyexecPROGRAMS mostlyclean-compile \
distclean-compile clean-compile maintainer-clean-compile \
mostlyclean-pythonPYTHON distclean-pythonPYTHON clean-pythonPYTHON \
maintainer-clean-pythonPYTHON uninstall-pythonPYTHON \
install-pythonPYTHON install-data-recursive uninstall-data-recursive \
install-exec-recursive uninstall-exec-recursive installdirs-recursive \
uninstalldirs-recursive all-recursive check-recursive \
installcheck-recursive info-recursive dvi-recursive \
mostlyclean-recursive distclean-recursive clean-recursive \
maintainer-clean-recursive tags tags-recursive mostlyclean-tags \
distclean-tags clean-tags maintainer-clean-tags distdir info-am info \
dvi-am dvi check check-am installcheck-am installcheck install-exec-am \
install-exec install-data-am install-data install-am install \
uninstall-am uninstall all-redirect all-am all installdirs-am \
installdirs mostlyclean-generic distclean-generic clean-generic \
maintainer-clean-generic clean mostlyclean distclean maintainer-clean
snap:
$(MAKE) dist distdir=$(PACKAGE)-SNAP-`date +"%Y%m%d"`
# Tell versions [3.59,3.63) of GNU make to not export all variables.
# Otherwise a system limit (for SysV at least) may be exceeded.
.NOEXPORT:

65
plug-ins/pygimp/NEWS Normal file
View File

@ -0,0 +1,65 @@
pygimp-0.5: 8-July-1999
- Fixed some bugs that I missed in gimpui. It should actually work
on other people's systems now (I don't know why it worked on mine).
- Included the foggify.py and shadow_bevel.py plugins in the package.
- Added a timeout function to flush the displays in the gimpconsole
plugin. This way you can see the results of what you type easily.
pygimp-0.4: 5-July-1999
- Removed the drawable type -- now layer or channel objects are used
in its place. All drawable methods have been transfered to both
the channel and layer objects. The layer and channel objects have
the following attributes in common:
ID, bpp, has_alpha, height, image, is_color, is_colour, is_gray,
is_grey, is_indexed, mask_bounds, name, offsets, opacity
This means that the gimp.drawable(layer|channel) command is gone,
and so is the gimp.layer(drawable) and gimp.channel(drawable)
syntaxes (the gimp.layer and gimp.channel commands still exist).
I made this change because the previous setup was confusing, and
more complicated than it needed to be.
- Removed all tkinter code, and replaced it with pygtk code. There
is now also a convenience module gimpfu, which is a simpler
interface to
pygimp-0.3: 8-February-1999
- Some small build cleanups. Now you should be able to do the normal
./configure ; make ; make install. It should compile fine with
GIMP 1.0 (I haven't tested 1.1 series though).
- gimpmodule.c now prints exception messages, so now exceptions caused
by a plugin will print a stack trace to stdout, and cause gimp to
realise the plugin failed.
- The disable_undo and enable_undo methods of image now use the
stack based enable/disable functions.
- Added function names to PyArg_ParseTuple calls, so exceptions
are a little easier to understand.
- added a spec file for building RPMS for this package.
- added gimp.extension_ack, gimp.extension_process,
gimp.install_temp_proc and gimp.uninstall_temp_proc which will be
useful to implement an interface similar to script-fu's (ie. one
copy of python running in the background, responding to requests
from the gimp process every now and again).
- changed over to using glib's safe memory allocation routines g_new,
g_strdup and g_free.
- Converted documentation to docbook -- linuxdoc is just about dead.
pygimp-0.2.0: 19-Nov-1997
- implemented pixel regions. You can access them as a mapping. (ie.
pr[x,y] is get_pixel, pr[x1:x2,y] is get_row, pr[x, y1:y2] is get_col
and pr[x1:x2, y1:y2] is get_rect)
- to demonstrate the use of this low level object, I have included a
translation of the c plugin Whirl and Pinch.
- fixed a problem where I didn't check for a NULL when parsing
arguments for a plugin. This caused a crash when you ran a plugin
that took a string as an argument was run in interactive mode.
pygimp-0.1.0: 18-Nov-1997
- first public release.
- implements images, layers, channels, drawables, tiles, and just about
everything except pixel regions.
- I have included a number of example plugins:
- gimpcons is an interactive python console
- pdbbrowse is a browser for the PDB
- clothify is a translation of the Script-Fu script
- sphere is a translation of the Script-Fu script

29
plug-ins/pygimp/README Normal file
View File

@ -0,0 +1,29 @@
Gimp-Python - allows the writing of plugins for Gimp in Python.
Copyright (C) 1997-1999 James Henstridge <james@daa.com.au>
This is the Gimp-Python package. It is free software and is covered
by the GNU General Public Licence (A copy of which is in the file
COPYING in the distribution) with the exception that you may link
gimpmodule with the python program.
For more information, please see the documentation in the directory
doc. The documentation is in SGML, and translations to text, html and
texinfo are included in the distribution.
To build the program, you should be able to just type:
./configure --prefix=<gimp-prefix>
make
make install
Pregenerated HTML docs are included with the package in the doc
directory. If you want ps or pdf documentation, get Mark Galassi's
docbook SGML packages.
Here is a list of what you will find in the subdirectories of this
distribution:
. - The actual source code.
doc/ - The documentation.
plug-ins/ - The sample plugins. Contents are copied to GIMP plug-ins
directory.

View File

@ -0,0 +1,135 @@
## Find the install dirs for the python installation.
## By James Henstridge
# serial 1
AC_DEFUN(AM_PATH_PYTHON,
[AC_CHECK_PROGS(PYTHON, python python1.5 python1.4 python1.3,no)
if test "$PYTHON" != no; then
AC_MSG_CHECKING([where .py files should go])
changequote(, )dnl
pythondir=`$PYTHON -c '
import sys
if sys.version[0] > "1" or sys.version[2] > "4":
print "%s/lib/python%s/site-packages" % (sys.prefix, sys.version[:3])
else:
print "%s/lib/python%s" % (sys.prefix, sys.version[:3])'`
changequote([, ])dnl
AC_MSG_RESULT($pythondir)
AC_MSG_CHECKING([where python extensions should go])
changequote(, )dnl
pyexecdir=`$PYTHON -c '
import sys
if sys.version[0] > "1" or sys.version[2] > "4":
print "%s/lib/python%s/site-packages" % (sys.exec_prefix, sys.version[:3])
else:
print "%s/lib/python%s/sharedmodules" % (sys.exec_prefix, sys.version[:3])'`
changequote([, ])dnl
AC_MSG_RESULT($pyexecdir)
else
# these defaults are version independent ...
AC_MSG_CHECKING([where .py files should go])
pythondir='$(prefix)/lib/site-python'
AC_MSG_RESULT($pythondir)
AC_MSG_CHECKING([where python extensions should go])
pyexecdir='$(exec_prefix)/lib/site-python'
AC_MSG_RESULT($pyexecdir)
fi
AC_SUBST(pythondir)
AC_SUBST(pyexecdir)])
## this one is commonly used with AM_PATH_PYTHONDIR ...
dnl AM_CHECK_PYMOD(MODNAME [,SYMBOL [,ACTION-IF-FOUND [,ACTION-IF-NOT-FOUND]]])
dnl Check if a module containing a given symbol is visible to python.
AC_DEFUN(AM_CHECK_PYMOD,
[AC_REQUIRE([AM_PATH_PYTHON])
py_mod_var=`echo $1['_']$2 | sed 'y%./+-%__p_%'`
AC_MSG_CHECKING(for ifelse([$2],[],,[$2 in ])python module $1)
AC_CACHE_VAL(py_cv_mod_$py_mod_var, [
ifelse([$2],[], [prog="
import sys
try:
import $1
except ImportError:
sys.exit(1)
except:
sys.exit(0)
sys.exit(0)"], [prog="
import $1
$1.$2"])
if $PYTHON -c "$prog" 1>&AC_FD_CC 2>&AC_FD_CC
then
eval "py_cv_mod_$py_mod_var=yes"
else
eval "py_cv_mod_$py_mod_var=no"
fi
])
py_val=`eval "echo \`echo '$py_cv_mod_'$py_mod_var\`"`
if test "x$py_val" != xno; then
AC_MSG_RESULT(yes)
ifelse([$3], [],, [$3
])dnl
else
AC_MSG_RESULT(no)
ifelse([$4], [],, [$4
])dnl
fi
])
# serial 1
dnl finds information needed for compilation of shared library style python
dnl extensions. AM_PATH_PYTHON should be called before hand.
AC_DEFUN(AM_INIT_PYEXEC_MOD,
[AC_REQUIRE([AM_PATH_PYTHON])
AC_MSG_CHECKING([for python headers])
AC_CACHE_VAL(am_cv_python_includes,
[changequote(,)dnl
am_cv_python_includes="`$PYTHON -c '
import sys
includepy = \"%s/include/python%s\" % (sys.prefix, sys.version[:3])
if sys.version[0] > \"1\" or sys.version[2] > \"4\":
libpl = \"%s/include/python%s\" % (sys.exec_prefix, sys.version[:3])
else:
libpl = \"%s/lib/python%s/config\" % (sys.exec_prefix, sys.version[:3])
print \"-I%s -I%s\" % (includepy, libpl)'`"
changequote([, ])])
PYTHON_INCLUDES="$am_cv_python_includes"
AC_MSG_RESULT(found)
AC_SUBST(PYTHON_INCLUDES)
AC_MSG_CHECKING([definitions from Python makefile])
AC_CACHE_VAL(am_cv_python_makefile,
[changequote(,)dnl
py_makefile="`$PYTHON -c '
import sys
print \"%s/lib/python%s/config/Makefile\"%(sys.exec_prefix, sys.version[:3])'`"
if test ! -f "$py_makefile"; then
AC_MSG_ERROR([*** Couldn't find the python config makefile. Maybe you are
*** missing the development portion of the python installation])
fi
eval `sed -n \
-e "s/^CC=[ ]*\(.*\)/am_cv_python_CC='\1'/p" \
-e "s/^OPT=[ ]*\(.*\)/am_cv_python_OPT='\1'/p" \
-e "s/^CCSHARED=[ ]*\(.*\)/am_cv_python_CCSHARED='\1'/p" \
-e "s/^LDSHARED=[ ]*\(.*\)/am_cv_python_LDSHARED='\1'/p" \
-e "s/^SO=[ ]*\(.*\)/am_cv_python_SO='\1'/p" \
$py_makefile`
am_cv_python_makefile=found
changequote([, ])])
AC_MSG_RESULT(done)
CC="$am_cv_python_CC"
OPT="$am_cv_python_OPT"
SO="$am_cv_python_SO"
PYTHON_CFLAGS="$am_cv_python_CCSHARED \$(OPT)"
PYTHON_LINK="$am_cv_python_LDSHARED -o \[$]@"
AC_SUBST(CC)dnl
AC_SUBST(OPT)dnl
AC_SUBST(SO)dnl
AC_SUBST(PYTHON_CFLAGS)dnl
AC_SUBST(PYTHON_LINK)])

View File

@ -0,0 +1,26 @@
AC_INIT(gimpmodule.c)
AM_INIT_AUTOMAKE(pygimp, 0.5)
AM_PATH_PYTHON
AM_INIT_PYEXEC_MOD
AM_CHECK_PYMOD(gtk,,,AC_MSG_ERROR([You need the pygtk package to use pygimp]))
AC_PATH_PROG(GIMPTOOL, gimptool, no)
if test "x$GIMPTOOL" = xno; then
AC_MSG_ERROR([could not find gimptool script])
fi
GIMP_CFLAGS_NOUI=`$GIMPTOOL --cflags-noui`
GIMP_LIBS_NOUI=`$GIMPTOOL --libs-noui`
gimp_ver=`$GIMPTOOL --version | cut -d. -f 1-2 `
pluginexecdir=\${libdir}/gimp/$gimp_ver/plug-ins
AC_SUBST(GIMP_CFLAGS_NOUI)
AC_SUBST(GIMP_LIBS_NOUI)
AC_SUBST(pluginexecdir)
AC_OUTPUT(Makefile doc/Makefile plug-ins/Makefile)

View File

@ -0,0 +1,3 @@
Makefile
Makefile.in

View File

@ -0,0 +1,31 @@
noinst_DATA = pygimp.html
EXTRA_DIST = pygimp.sgml \
pygimp.html \
structure-of-plugin.html \
procedural-database.html \
gimp-module-procedures.html \
gimp-objects.html \
support-modules.html \
end-note.html
printed: pygimp.ps pygimp.pdf
clean:
rm -f *.html pygimp.ps pygimp.pdf
pygimp.ps: pygimp.sgml
db2ps $(srcdir)/pygimp.sgml
pygimp.pdf: pygimp.sgml
db2pdf $(srcdir)/pygimp.sgml
pygimp.html: pygimp.sgml
cd $(srcdir) && db2html pygimp.sgml
cd $(srcdir) && mv pygimp/*.html .
rm -rf $(srcdir)/pygimp
.PHONY: printed clean

View File

@ -0,0 +1,123 @@
<!DOCTYPE HTML PUBLIC "-//Norman Walsh//DTD DocBook HTML 1.0//EN">
<HTML
><HEAD
><TITLE
>End Note</TITLE
><META
NAME="GENERATOR"
CONTENT="Modular DocBook HTML Stylesheet"><LINK
REL="HOME"
TITLE="Gimp Python Documentation"
HREF="pygimp.html"><LINK
REL="PREVIOUS"
TITLE="Support Modules"
HREF="support-modules.html"></HEAD
><BODY
><DIV
CLASS="NAVHEADER"
><TABLE
WIDTH="100%"
BORDER="0"
CELLPADDING="0"
CELLSPACING="0"
><TR
><TH
COLSPAN="3"
ALIGN="center"
>Gimp Python Documentation</TH
></TR
><TR
><TD
WIDTH="10%"
ALIGN="left"
VALIGN="bottom"
><A
HREF="support-modules.html"
>Prev</A
></TD
><TD
WIDTH="80%"
ALIGN="center"
VALIGN="bottom"
></TD
><TD
WIDTH="10%"
ALIGN="right"
VALIGN="bottom"
>&nbsp;</TD
></TR
></TABLE
><HR
ALIGN="LEFT"
WIDTH="100%"></DIV
><DIV
CLASS="SECT1"
><H1
CLASS="SECT1"
><A
NAME="END-NOTE"
>End Note</A
></H1
><P
>This package is not yet complete, but it has enough in it to
be useful for writing plugins for Gimp. If you write any plugins
that might be useful as examples, please mail me at <A
HREF="mailto:james@daa.com.au"
TARGET="_top"
>james@daa.com.au</A
>.</P
></DIV
><DIV
CLASS="NAVFOOTER"
><HR
ALIGN="LEFT"
WIDTH="100%"><TABLE
WIDTH="100%"
BORDER="0"
CELLPADDING="0"
CELLSPACING="0"
><TR
><TD
WIDTH="33%"
ALIGN="left"
VALIGN="top"
><A
HREF="support-modules.html"
>Prev</A
></TD
><TD
WIDTH="34%"
ALIGN="center"
VALIGN="top"
><A
HREF="pygimp.html"
>Home</A
></TD
><TD
WIDTH="33%"
ALIGN="right"
VALIGN="top"
>&nbsp;</TD
></TR
><TR
><TD
WIDTH="33%"
ALIGN="left"
VALIGN="top"
>Support Modules</TD
><TD
WIDTH="34%"
ALIGN="center"
VALIGN="top"
>&nbsp;</TD
><TD
WIDTH="33%"
ALIGN="right"
VALIGN="top"
>&nbsp;</TD
></TR
></TABLE
></DIV
></BODY
></HTML
>

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,361 @@
<!DOCTYPE HTML PUBLIC "-//Norman Walsh//DTD DocBook HTML 1.0//EN">
<HTML
><HEAD
><TITLE
>The Procedural Database</TITLE
><META
NAME="GENERATOR"
CONTENT="Modular DocBook HTML Stylesheet"><LINK
REL="HOME"
TITLE="Gimp Python Documentation"
HREF="pygimp.html"><LINK
REL="PREVIOUS"
TITLE="The Structure Of A Plugin"
HREF="structure-of-plugin.html"><LINK
REL="NEXT"
TITLE="Gimp Module Procedures"
HREF="gimp-module-procedures.html"></HEAD
><BODY
><DIV
CLASS="NAVHEADER"
><TABLE
WIDTH="100%"
BORDER="0"
CELLPADDING="0"
CELLSPACING="0"
><TR
><TH
COLSPAN="3"
ALIGN="center"
>Gimp Python Documentation</TH
></TR
><TR
><TD
WIDTH="10%"
ALIGN="left"
VALIGN="bottom"
><A
HREF="structure-of-plugin.html"
>Prev</A
></TD
><TD
WIDTH="80%"
ALIGN="center"
VALIGN="bottom"
></TD
><TD
WIDTH="10%"
ALIGN="right"
VALIGN="bottom"
><A
HREF="gimp-module-procedures.html"
>Next</A
></TD
></TR
></TABLE
><HR
ALIGN="LEFT"
WIDTH="100%"></DIV
><DIV
CLASS="SECT1"
><H1
CLASS="SECT1"
><A
NAME="PROCEDURAL-DATABASE"
>The Procedural Database</A
></H1
><P
>The procedural database is a registry of things gimp and its
plugins can do. When you install a procedure for your plugin, you
are extending the procedural database.</P
><P
>The procedural database is self documenting, in that when
you install a procedure in it, you also add documentation for it,
its parameters and return values.</P
><DIV
CLASS="SECT2"
><H2
CLASS="SECT2"
><A
NAME="GIMP-PYTHON-MODEL"
>The Gimp-Python Model</A
></H2
><P
>In Gimp-Python, the procedural database is represented by
the object <TT
CLASS="PARAMETER"
><I
>gimp.pdb</I
></TT
>. In most of my
plugins, I make an assignment from <TT
CLASS="PARAMETER"
><I
>gimp.pdb</I
></TT
>
to <TT
CLASS="PARAMETER"
><I
>pdb</I
></TT
> for convenience.</P
><P
>You can query the procedural database with
<TT
CLASS="PARAMETER"
><I
>pdb</I
></TT
>'s method <TT
CLASS="FUNCTION"
><B
>query</B
></TT
>. Its
specification is:</P
><TABLE
BORDER="0"
BGCOLOR="#E0E0E0"
WIDTH="100%"
><TR
><TD
><PRE
CLASS="SCREEN"
>pdb.query(name, [blurb, [help, [author, [copyright, [date, [type]]]]]])</PRE
></TD
></TR
></TABLE
><P
>Each parameter is a regular expression that is checked
against the corresponding field in the procedural database. The
method returns a list of the names of matching procedures. If
<TT
CLASS="FUNCTION"
><B
>query</B
></TT
> is called without any arguments, it will
return every procedure in the database.</P
></DIV
><DIV
CLASS="SECT2"
><H2
CLASS="SECT2"
><A
NAME="PDB-PROCEDURES"
>Procedural Database Procedures</A
></H2
><P
>Procedures can be accessed as procedures, or by treating
<TT
CLASS="PARAMETER"
><I
>pdb</I
></TT
> as a mapping objest. As an example,
the probedure <TT
CLASS="FUNCTION"
><B
>gimp_edit_fill</B
></TT
> can be
accessed as either <TT
CLASS="FUNCTION"
><B
>pdb.gimp_edit_fill</B
></TT
> or
<TT
CLASS="FUNCTION"
><B
>pdb['gimp_edit_fill']</B
></TT
>. The second form is
mainly for procedures whose names are not valid Python names (eg
in script-fu-..., the dashes are interpreted as minuses).</P
><P
>These procedure objects have a number of attribute:</P
><P
></P
><DL
><DT
>proc_name</DT
><DD
><P
>The name of the procedure.</P
></DD
><DT
>proc_blurb</DT
><DD
><P
>A short peice of information about the procedure.</P
></DD
><DT
>proc_help</DT
><DD
><P
>More detailed information about the procedure.</P
></DD
><DT
>proc_author</DT
><DD
><P
>The author of the procedure.</P
></DD
><DT
>proc_copyright</DT
><DD
><P
>The copyright holder for the procedure (usually the
same as the author).</P
></DD
><DT
>proc_date</DT
><DD
><P
>The date when the procedure was written.</P
></DD
><DT
>proc_type</DT
><DD
><P
>The type of procedure. This will be one of
PROC_PLUG_IN, PROC_EXTENSION or PROC_TEMPORARY.</P
></DD
><DT
>nparams</DT
><DD
><P
>The number of parameters the procedure takes.</P
></DD
><DT
>nreturn_vals</DT
><DD
><P
>The number of return values the procedure gives.</P
></DD
><DT
>params</DT
><DD
><P
>A description of parameters of the procedure. It
takes the form of a tuple of 3-tuples, where each 3-tuple
describes a parameter. The items in the 3-tuple are a
parameter type (one of the PARAM_* constants), a
name for the parameter, and a description of the
parameter.</P
></DD
><DT
>return_vals</DT
><DD
><P
>A description of the return values. It takes the
same form as the <TT
CLASS="LITERAL"
>params</TT
>
attribute.</P
></DD
></DL
><P
>A procedure object may also be called. At this point,
Gimp-Python doesn't support keyword arguments for PDB
procedures. Arguments are passed to the procedure in the normal
method. The return depends on the number of return values:</P
><P
></P
><UL
><LI
><P
>If there are zero return values,
<TT
CLASS="LITERAL"
>None</TT
> is returned.</P
></LI
><LI
><P
>If there is only a single return value, it is
returned.</P
></LI
><LI
><P
>If there are more return values, then they are
returned as a tuple.</P
></LI
></UL
></DIV
><DIV
CLASS="SECT2"
><H2
CLASS="SECT2"
><A
NAME="MORE-INFORMATION"
>More Information</A
></H2
><P
>For more information on invoking PDB procedures, please
see the example plugins. For information on individual
procedures, please see the PDB Browser plugin (in the Xtns
menu). It alows you to peruse to the database
interactively.</P
></DIV
></DIV
><DIV
CLASS="NAVFOOTER"
><HR
ALIGN="LEFT"
WIDTH="100%"><TABLE
WIDTH="100%"
BORDER="0"
CELLPADDING="0"
CELLSPACING="0"
><TR
><TD
WIDTH="33%"
ALIGN="left"
VALIGN="top"
><A
HREF="structure-of-plugin.html"
>Prev</A
></TD
><TD
WIDTH="34%"
ALIGN="center"
VALIGN="top"
><A
HREF="pygimp.html"
>Home</A
></TD
><TD
WIDTH="33%"
ALIGN="right"
VALIGN="top"
><A
HREF="gimp-module-procedures.html"
>Next</A
></TD
></TR
><TR
><TD
WIDTH="33%"
ALIGN="left"
VALIGN="top"
>The Structure Of A Plugin</TD
><TD
WIDTH="34%"
ALIGN="center"
VALIGN="top"
>&nbsp;</TD
><TD
WIDTH="33%"
ALIGN="right"
VALIGN="top"
>Gimp Module Procedures</TD
></TR
></TABLE
></DIV
></BODY
></HTML
>

View File

@ -0,0 +1,232 @@
<!DOCTYPE HTML PUBLIC "-//Norman Walsh//DTD DocBook HTML 1.0//EN">
<HTML
><HEAD
><TITLE
>Gimp Python Documentation</TITLE
><META
NAME="GENERATOR"
CONTENT="Modular DocBook HTML Stylesheet"><LINK
REL="NEXT"
TITLE="The Structure Of A Plugin"
HREF="structure-of-plugin.html"></HEAD
><BODY
><DIV
CLASS="ARTICLE"
><DIV
CLASS="TITLEPAGE"
><H1
CLASS="TITLE"
>Gimp Python Documentation</H1
><P
CLASS="AUTHOR"
><I
>James Henstridge</I
></P
><DIV
CLASS="AFFILIATION"
><P
CLASS="LITERALLAYOUT"
>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<TT
CLASS="EMAIL"
>&#60;<A
HREF="mailto:james@daa.com.au"
>james@daa.com.au</A
>&#62;</TT
><br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</P
></DIV
><P
>Published <SPAN
CLASS="PUBDATE"
>v0.4, 5 July 1999</SPAN
></P
><DIV
CLASS="ABSTRACT"
><P
>This document outlines the interfaces to Gimp-Python,
which is a set of Python modules that act as a wrapper to
<TT
CLASS="FILENAME"
>libgimp</TT
> allowing the writing of
plug-ins for Gimp. In this way, Gimp-Python is similar to
Script-Fu, except that you can use the full set of Python
extension modules from the plug-in.</P
></DIV
><HR></DIV
><DIV
CLASS="TOC"
><DL
><DT
><B
>Table of Contents</B
></DT
><DT
><A
HREF="pygimp.html#INTRODUCTION"
>Introduction</A
></DT
><DT
><A
HREF="structure-of-plugin.html"
>The Structure Of A Plugin</A
></DT
><DT
><A
HREF="procedural-database.html"
>The Procedural Database</A
></DT
><DT
><A
HREF="gimp-module-procedures.html"
>Gimp Module Procedures</A
></DT
><DT
><A
HREF="gimp-objects.html"
>Gimp Objects</A
></DT
><DT
><A
HREF="support-modules.html"
>Support Modules</A
></DT
><DT
><A
HREF="end-note.html"
>End Note</A
></DT
></DL
></DIV
><DIV
CLASS="SECT1"
><H1
CLASS="SECT1"
><A
NAME="INTRODUCTION"
>Introduction</A
></H1
><DIV
CLASS="SECT2"
><H2
CLASS="SECT2"
><A
NAME="WHAT-IS-IT"
>What is it?</A
></H2
><P
>Gimp-Python is a scripting extension for Gimp, similar to
Script-Fu. The main difference is in what is called first. In
Script-Fu, the script-fu plugin executes the script, while in
Gimp-Python the script is in control.</P
><P
>In fact, you will find that the Gimp-Python scripts start
with the line <TT
CLASS="LITERAL"
>#!/usr/bin/python</TT
>. The
gimp extension is loaded with the familiar
<TT
CLASS="LITERAL"
>import</TT
> command.</P
><P
>Another point of difference between Gimp-Python and
Script-Fu is that Gimp-Python stores images, layers, channels
and other types as objects rather than just storing their ID.
This allows better type checking that is missing from Script-Fu,
and allows those types to act as objects, complete with
attributes and methods.</P
><P
>Also, Gimp-Python is not limited to just calling
procedures from the PDB. It also implements the rest of
<TT
CLASS="FILENAME"
>libgimp</TT
>, including tiles and pixel regions,
and access to other lower level functions.</P
></DIV
><DIV
CLASS="SECT2"
><H2
CLASS="SECT2"
><A
NAME="INSTALLATION"
>Installation</A
></H2
><P
>Gimp-python consists of a Python module written in C and
some native python support modules. You can build pygimp with
the commands:</P
><TABLE
BORDER="0"
BGCOLOR="#E0E0E0"
WIDTH="100%"
><TR
><TD
><PRE
CLASS="PROGRAMLISTING"
>./configure
make
make install</PRE
></TD
></TR
></TABLE
><P
>This will build and install gimpmodule and its supporting
modules, and install the sample plugins in gimp's plugin
directory.</P
></DIV
></DIV
></DIV
><DIV
CLASS="NAVFOOTER"
><HR
ALIGN="LEFT"
WIDTH="100%"><TABLE
WIDTH="100%"
BORDER="0"
CELLPADDING="0"
CELLSPACING="0"
><TR
><TD
WIDTH="33%"
ALIGN="left"
VALIGN="top"
>&nbsp;</TD
><TD
WIDTH="34%"
ALIGN="center"
VALIGN="top"
>&nbsp;</TD
><TD
WIDTH="33%"
ALIGN="right"
VALIGN="top"
><A
HREF="structure-of-plugin.html"
>Next</A
></TD
></TR
><TR
><TD
WIDTH="33%"
ALIGN="left"
VALIGN="top"
>&nbsp;</TD
><TD
WIDTH="34%"
ALIGN="center"
VALIGN="top"
>&nbsp;</TD
><TD
WIDTH="33%"
ALIGN="right"
VALIGN="top"
>The Structure Of A Plugin</TD
></TR
></TABLE
></DIV
></BODY
></HTML
>

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,573 @@
<!DOCTYPE HTML PUBLIC "-//Norman Walsh//DTD DocBook HTML 1.0//EN">
<HTML
><HEAD
><TITLE
>The Structure Of A Plugin</TITLE
><META
NAME="GENERATOR"
CONTENT="Modular DocBook HTML Stylesheet"><LINK
REL="HOME"
TITLE="Gimp Python Documentation"
HREF="pygimp.html"><LINK
REL="PREVIOUS"
TITLE="Gimp Python Documentation"
HREF="pygimp.html"><LINK
REL="NEXT"
TITLE="The Procedural Database"
HREF="procedural-database.html"></HEAD
><BODY
><DIV
CLASS="NAVHEADER"
><TABLE
WIDTH="100%"
BORDER="0"
CELLPADDING="0"
CELLSPACING="0"
><TR
><TH
COLSPAN="3"
ALIGN="center"
>Gimp Python Documentation</TH
></TR
><TR
><TD
WIDTH="10%"
ALIGN="left"
VALIGN="bottom"
><A
HREF="pygimp.html"
>Prev</A
></TD
><TD
WIDTH="80%"
ALIGN="center"
VALIGN="bottom"
></TD
><TD
WIDTH="10%"
ALIGN="right"
VALIGN="bottom"
><A
HREF="procedural-database.html"
>Next</A
></TD
></TR
></TABLE
><HR
ALIGN="LEFT"
WIDTH="100%"></DIV
><DIV
CLASS="SECT1"
><H1
CLASS="SECT1"
><A
NAME="STRUCTURE-OF-PLUGIN"
>The Structure Of A Plugin</A
></H1
><P
>The majority of code in this package resides in
<TT
CLASS="FILENAME"
>gimpmodule.c</TT
>, but this provides a poor
interface for implementing some portions of a plugin. For this
reason, there is a python module called
<TT
CLASS="FILENAME"
>plugin.py</TT
> that sets out a structure for
plugins and implements some things that were either too dificult
or impossible to do in C.</P
><P
>The main purpose of <TT
CLASS="FILENAME"
>plugin.py</TT
> was to
implement an object oriented structure for plug-ins. As well as
this, it handles tracebacks, which are otherwise ignored by
<TT
CLASS="FILENAME"
>libgimp</TT
>, and gives a method to call
other Gimp-Python plug-ins without going through the procedural
database.</P
><DIV
CLASS="SECT2"
><H2
CLASS="SECT2"
><A
NAME="EXAMPLE-PLUGIN"
>An Example Plugin</A
></H2
><P
>As in a lot of manuals, the first thing you examine is an
example, so here is an example. I have included it before
explaining what it does to allow more advanced programmers to
see the structure up front. It is a translation of the clothify
Script-Fu extension:</P
><DIV
CLASS="EXAMPLE"
><P
><B
>Example 1. A sample python plugin</B
></P
><TABLE
BORDER="0"
BGCOLOR="#E0E0E0"
WIDTH="100%"
><TR
><TD
><PRE
CLASS="PROGRAMLISTING"
>#!/usr/bin/python
import math
from gimpfu import *
have_gimp11 = gimp.major_version &#62; 1 or \
gimp.major_version == 1 and gimp.minor_version &#62;= 1
def python_clothify(timg, tdrawable, bx=9, by=9,
azimuth=135, elevation=45, depth=3):
bx = 9 ; by = 9 ; azimuth = 135 ; elevation = 45 ; depth = 3
width = tdrawable.width
height = tdrawable.height
img = gimp.image(width, height, RGB)
layer_one = gimp.layer(img, "X Dots", width, height, RGB_IMAGE,
100, NORMAL_MODE)
img.disable_undo()
if have_gimp11:
pdb.gimp_edit_fill(layer_one)
else:
pdb.gimp_edit_fill(img, layer_one)
img.add_layer(layer_one, 0)
pdb.plug_in_noisify(img, layer_one, 0, 0.7, 0.7, 0.7, 0.7)
layer_two = layer_one.copy()
layer_two.mode = MULTIPLY_MODE
layer_two.name = "Y Dots"
img.add_layer(layer_two, 0)
pdb.plug_in_gauss_rle(img, layer_one, bx, 1, 0)
pdb.plug_in_gauss_rle(img, layer_two, by, 0, 1)
img.flatten()
bump_layer = img.active_layer
pdb.plug_in_c_astretch(img, bump_layer)
pdb.plug_in_noisify(img, bump_layer, 0, 0.2, 0.2, 0.2, 0.2)
pdb.plug_in_bump_map(img, tdrawable, bump_layer, azimuth,
elevation, depth, 0, 0, 0, 0, TRUE, FALSE, 0)
gimp.delete(img)
register(
"python_fu_clothify",
"Make the specified layer look like it is printed on cloth",
"Make the specified layer look like it is printed on cloth",
"James Henstridge",
"James Henstridge",
"1997-1999",
"&#60;Image&#62;/Python-Fu/Alchemy/Clothify",
"RGB*, GRAY*",
[
(PF_INT, "x_blur", "X Blur", 9),
(PF_INT, "y_blur", "Y Blur", 9),
(PF_INT, "azimuth", "Azimuth", 135),
(PF_INT, "elevation", "elevation", 45),
(PF_INT, "depth", "Depth", 3)
],
[],
python_clothify)
main()</PRE
></TD
></TR
></TABLE
></DIV
></DIV
><DIV
CLASS="SECT2"
><H2
CLASS="SECT2"
><A
NAME="IMPORTANT-MODULES"
>Import Modules</A
></H2
><P
>In this plugin, a number of modules are imported. The
important ones are:</P
><P
></P
><UL
><LI
><P
><TT
CLASS="FILENAME"
>gimpfu</TT
>: this module provides a
simple interface for writing plugins, similar to what
script-fu provides. It provides the GUI for entering in
parameters in interactive mode and performs some sanity
checks when registering the plugin.</P
><P
>By using "from gimpfu import *", this module also
provides an easy way to get all the commonly used symbols
into the plugin's namespace.</P
></LI
><LI
><P
><TT
CLASS="FILENAME"
>gimp</TT
>: the main part of the gimp
extension. This is imported with gimpfu.</P
></LI
><LI
><P
><TT
CLASS="FILENAME"
>gimpenums</TT
>: a number of useful
constants. This is also automatically imported with
gimpfu.</P
></LI
></UL
><P
>The pdb variable is a variable for accessing the
procedural database. It is imported into the plugin's namespace
with gimpfu for convenience.</P
></DIV
><DIV
CLASS="SECT2"
><H2
CLASS="SECT2"
><A
NAME="PLUGIN-FRAMEWORK"
>Plugin Framework</A
></H2
><P
>With pygimp-0.4, the gimpfu module was introduced. It
simplifies writing plugins a lot. It handles the run mode
(interactive, non interactive or run with last values),
providing a GUI for interactive mode and saving the last used
settings.</P
><P
>Using the gimpfu plugin, all you need to do is write the
function that should be run, make a call to
<TT
CLASS="FUNCTION"
><B
>register</B
></TT
>, and finally a call to
<TT
CLASS="FUNCTION"
><B
>main</B
></TT
> to get the plugin started.</P
><P
>If the plugin is to be run on an image, the first
parameter to the plugin function should be the image, and the
second should be the current drawable (do not worry about the
run_mode parameter). Plugins that do not act on an existing
image (and hence go in the toolbox's menus) do not need these
parameters. Any other parameters are specific to the
plugin.</P
><P
>After defining the plugin function, you need to call
<TT
CLASS="FUNCTION"
><B
>register</B
></TT
> to register the plugin with gimp
(When the plugin is run to query it, this information is passed
to gimp. When it is run interactively, this information is used
to construct the GUI). The parameters to
<TT
CLASS="FUNCTION"
><B
>register</B
></TT
> are:</P
><P
></P
><TABLE
BORDER="0"
><TR
><TD
>name</TD
></TR
><TR
><TD
>blurb</TD
></TR
><TR
><TD
>help</TD
></TR
><TR
><TD
>author</TD
></TR
><TR
><TD
>copyright</TD
></TR
><TR
><TD
>date</TD
></TR
><TR
><TD
>menupath</TD
></TR
><TR
><TD
>imagetypes</TD
></TR
><TR
><TD
>params</TD
></TR
><TR
><TD
>results</TD
></TR
><TR
><TD
>function</TD
></TR
></TABLE
><P
></P
><P
>Most of these parameters are quite self explanatory. The
menupath option should start with &#60;Image%gt;/ for image
plugins and &#60;Toolbox&#62;/ for toolbox plugins. The remainder
of the menupath is a slash separated path to its menu item.</P
><P
>The params parameter holds a list parameters for the
function. It is a list of tuples. Note that you do not have to
specify the run_type, image or drawable parameters, as gimpfu
will add these automatically for you. The tuple format is
(type, name, description, default [, extra]). The allowed type
codes are:</P
><P
></P
><TABLE
BORDER="0"
><TR
><TD
>PF_INT8</TD
></TR
><TR
><TD
>PF_INT16</TD
></TR
><TR
><TD
>PF_INT32</TD
></TR
><TR
><TD
>PF_INT</TD
></TR
><TR
><TD
>PF_FLOAT</TD
></TR
><TR
><TD
>PF_STRING</TD
></TR
><TR
><TD
>PF_VALUE</TD
></TR
><TR
><TD
>PF_INT8ARRAY</TD
></TR
><TR
><TD
>PF_INT16ARRAY</TD
></TR
><TR
><TD
>PF_INT32ARRAY</TD
></TR
><TR
><TD
>PF_INTARRAY</TD
></TR
><TR
><TD
>PF_FLOATARRAY</TD
></TR
><TR
><TD
>PF_STRINGARRAY</TD
></TR
><TR
><TD
>PF_COLOR</TD
></TR
><TR
><TD
>PF_COLOUR</TD
></TR
><TR
><TD
>PF_REGION</TD
></TR
><TR
><TD
>PF_IMAGE</TD
></TR
><TR
><TD
>PF_LAYER</TD
></TR
><TR
><TD
>PF_CHANNEL</TD
></TR
><TR
><TD
>PF_DRAWABLE</TD
></TR
><TR
><TD
>PF_TOGGLE</TD
></TR
><TR
><TD
>PF_BOOL</TD
></TR
><TR
><TD
>PF_SLIDER</TD
></TR
><TR
><TD
>PF_SPINNER</TD
></TR
><TR
><TD
>PF_ADJUSTMENT</TD
></TR
><TR
><TD
>PF_FONT</TD
></TR
><TR
><TD
>PF_FILE</TD
></TR
><TR
><TD
>PF_BRUSH</TD
></TR
><TR
><TD
>PF_PATTERN</TD
></TR
><TR
><TD
>PF_GRADIENT</TD
></TR
></TABLE
><P
></P
><P
>These values map onto the standard PARAM_* constants. The
reason to use the extra constants is that they give gimpfu more
information, so it can produce a better interface (for instance,
the PF_FONT type is equivalent to PARAM_STRING, but in the GUI
you get a small button that will bring up a font selection
dialog).</P
><P
>The PF_SLIDER, PF_SPINNER and PF_ADJUSTMENT types require
the extra parameter. It is of the form (min, max, step), and
gives the limits for the spin button or slider.</P
><P
>The results parameter is a list of 3-tuples of the form
(type, name, description). It defines the return values for the
function. If there is only a single return value, the plugin
function should return just that value. If there is more than
one, the plugin function should return a tuple of results.</P
><P
>The final parameter to <TT
CLASS="FUNCTION"
><B
>register</B
></TT
> is
the plugin function itself.</P
><P
>After registering one or more plugin functions, you must
call the <TT
CLASS="FUNCTION"
><B
>main</B
></TT
> function. This will cause
the plugin to start running. A GUI will be displayed when
needed, and your plugin function will be called at the
appropriate times.</P
></DIV
></DIV
><DIV
CLASS="NAVFOOTER"
><HR
ALIGN="LEFT"
WIDTH="100%"><TABLE
WIDTH="100%"
BORDER="0"
CELLPADDING="0"
CELLSPACING="0"
><TR
><TD
WIDTH="33%"
ALIGN="left"
VALIGN="top"
><A
HREF="pygimp.html"
>Prev</A
></TD
><TD
WIDTH="34%"
ALIGN="center"
VALIGN="top"
><A
HREF="pygimp.html"
>Home</A
></TD
><TD
WIDTH="33%"
ALIGN="right"
VALIGN="top"
><A
HREF="procedural-database.html"
>Next</A
></TD
></TR
><TR
><TD
WIDTH="33%"
ALIGN="left"
VALIGN="top"
>Gimp Python Documentation</TD
><TD
WIDTH="34%"
ALIGN="center"
VALIGN="top"
>&nbsp;</TD
><TD
WIDTH="33%"
ALIGN="right"
VALIGN="top"
>The Procedural Database</TD
></TR
></TABLE
></DIV
></BODY
></HTML
>

View File

@ -0,0 +1,259 @@
<!DOCTYPE HTML PUBLIC "-//Norman Walsh//DTD DocBook HTML 1.0//EN">
<HTML
><HEAD
><TITLE
>Support Modules</TITLE
><META
NAME="GENERATOR"
CONTENT="Modular DocBook HTML Stylesheet"><LINK
REL="HOME"
TITLE="Gimp Python Documentation"
HREF="pygimp.html"><LINK
REL="PREVIOUS"
TITLE="Gimp Objects"
HREF="gimp-objects.html"><LINK
REL="NEXT"
TITLE="End Note"
HREF="end-note.html"></HEAD
><BODY
><DIV
CLASS="NAVHEADER"
><TABLE
WIDTH="100%"
BORDER="0"
CELLPADDING="0"
CELLSPACING="0"
><TR
><TH
COLSPAN="3"
ALIGN="center"
>Gimp Python Documentation</TH
></TR
><TR
><TD
WIDTH="10%"
ALIGN="left"
VALIGN="bottom"
><A
HREF="gimp-objects.html"
>Prev</A
></TD
><TD
WIDTH="80%"
ALIGN="center"
VALIGN="bottom"
></TD
><TD
WIDTH="10%"
ALIGN="right"
VALIGN="bottom"
><A
HREF="end-note.html"
>Next</A
></TD
></TR
></TABLE
><HR
ALIGN="LEFT"
WIDTH="100%"></DIV
><DIV
CLASS="SECT1"
><H1
CLASS="SECT1"
><A
NAME="SUPPORT-MODULES"
>Support Modules</A
></H1
><P
>This section describes the modules that help make using the
<TT
CLASS="FILENAME"
>gimp</TT
> module easier. These range from a set
of constants to storing persistent data.</P
><DIV
CLASS="SECT2"
><H2
CLASS="SECT2"
><A
NAME="GIMPENUMS-MODULE"
>The gimpenums Module</A
></H2
><P
>This module contains all the constants found in the header
<TT
CLASS="FILENAME"
>libgimp/gimpenums.h</TT
>, as well as some extra
constants that are available in Script-Fu.</P
></DIV
><DIV
CLASS="SECT2"
><H2
CLASS="SECT2"
><A
NAME="AEN1466"
>The gimpfu Module</A
></H2
><P
>This module was fully described in an earlier section. It
provides an easy interface for writing plugins, where you do not
need to worry about run_modes, GUI's and saving previous values.
It is the recommended module for writing plugins.</P
></DIV
><DIV
CLASS="SECT2"
><H2
CLASS="SECT2"
><A
NAME="GIMPPLUGIN-MODULE"
>The gimpplugin Module</A
></H2
><P
>This module provides the framework for writing Gimp
plugins in Python. It gives more flexibility for writing
plugins than the gimpfu module, but does not offer as many
features (such as automatic GUI building).</P
><P
>To use this framework you subclass
<TT
CLASS="FUNCTION"
><B
>gimpplugin.plugin</B
></TT
> like so:</P
><TABLE
BORDER="0"
BGCOLOR="#E0E0E0"
WIDTH="100%"
><TR
><TD
><PRE
CLASS="PROGRAMLISTING"
>import gimpplugin
class myplugin(gimpplugin.plugin):
def init(self):
# initialisation routines
# called when gimp starts.
def quit(self):
# clean up routines
# called when gimp exits (normally).
def query(self):
# called to find what functionality the plugin provides.
gimp.install_procedure("procname", ...)
# note that this method name matches the first arg of
# gimp.install_procedure
def procname(self, arg1, ...):
# do what ever this plugin should do</PRE
></TD
></TR
></TABLE
></DIV
><DIV
CLASS="SECT2"
><H2
CLASS="SECT2"
><A
NAME="GIMPSHELF-MODULE"
>The gimpshelf Module</A
></H2
><P
>This module gives a nicer interface to the persistent
storage interface for Gimp plugins. Due to the complicated
nature of Python objects (there is often a lot of connections
between them), it can be dificult to work out what to store in
gimp's persistent storage. The python interface only allows
storage of strings, so this module wraps pickle and unpickle to
allow persistentstorage of any python object.</P
><P
>Here is some examples of using this module:</P
><TABLE
BORDER="0"
BGCOLOR="#E0E0E0"
WIDTH="100%"
><TR
><TD
><PRE
CLASS="SCREEN"
>&#62;&#62;&#62; from gimpshelf import shelf
&#62;&#62;&#62; shelf['james'] = ['forty-two', (42, 42L, 42.0)]
&#62;&#62;&#62; shelf.has_key('james')
1
&#62;&#62;&#62; shelf['james']
['forty-two', (42, 42L, 42.0)]</PRE
></TD
></TR
></TABLE
><P
>Anything you store with
<TT
CLASS="FUNCTION"
><B
>gimpshelf.shelf</B
></TT
> will exist until Gimp
exits. This makes this interface perfect for when a plugin is
executed with the run mode
<TT
CLASS="LITERAL"
>RUN_WITH_LAST_VALS</TT
>.</P
></DIV
></DIV
><DIV
CLASS="NAVFOOTER"
><HR
ALIGN="LEFT"
WIDTH="100%"><TABLE
WIDTH="100%"
BORDER="0"
CELLPADDING="0"
CELLSPACING="0"
><TR
><TD
WIDTH="33%"
ALIGN="left"
VALIGN="top"
><A
HREF="gimp-objects.html"
>Prev</A
></TD
><TD
WIDTH="34%"
ALIGN="center"
VALIGN="top"
><A
HREF="pygimp.html"
>Home</A
></TD
><TD
WIDTH="33%"
ALIGN="right"
VALIGN="top"
><A
HREF="end-note.html"
>Next</A
></TD
></TR
><TR
><TD
WIDTH="33%"
ALIGN="left"
VALIGN="top"
>Gimp Objects</TD
><TD
WIDTH="34%"
ALIGN="center"
VALIGN="top"
>&nbsp;</TD
><TD
WIDTH="33%"
ALIGN="right"
VALIGN="top"
>End Note</TD
></TR
></TABLE
></DIV
></BODY
></HTML
>

View File

@ -0,0 +1,185 @@
# Gimp-Python - allows the writing of Gimp plugins in Python.
# Copyright (C) 1997 James Henstridge <james@daa.com.au>
#
# 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 2 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, write to the Free Software
# Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
# gimpenums.py -- constants for use with the gimp module
#
# this file contains constants that are useful for use in
# gimp plugins. Just add 'from gimpenums import *' to the top
# of the script
RGB = 0
GRAY = 1
INDEXED = 2
RGB_IMAGE = 0
RGBA_IMAGE = 1
GRAY_IMAGE = 2
GRAYA_IMAGE = 3
INDEXED_IMAGE = 4
INDEXEDA_IMAGE = 5
NORMAL_MODE = 0
DISSOLVE_MODE = 1
MULTIPLY_MODE = 3
SCREEN_MODE = 4
OVERLAY_MODE = 5
DIFFERENCE_MODE = 6
ADDITION_MODE = 7
SUBTACT_MODE = 8
DARKEN_ONLY_MODE = 9
LIGHTEN_ONLY_MODE = 10
HUE_MODE = 11
SATURATION_MODE = 12
COLOR_MODE = 13
VALUE_MODE = 14
BG_IMAGE_FILL = 0
WHITE_IMAGE_FILL = 1
TRANS_IMAGE_FILL = 2
PARAM_INT32 = 0
PARAM_INT16 = 1
PARAM_INT8 = 2
PARAM_FLOAT = 3
PARAM_STRING = 4
PARAM_INT32ARRAY = 5
PARAM_INT16ARRAY = 6
PARAM_INT8ARRAY = 7
PARAM_FLOATARRAY = 8
PARAM_STRINGARRAY = 9
PARAM_COLOR = 10
PARAM_REGION = 11
PARAM_DISPLAY = 12
PARAM_IMAGE = 13
PARAM_LAYER = 14
PARAM_CHANNEL = 15
PARAM_DRAWABLE = 16
PARAM_SELECTION = 17
PARAM_BOUNDARY = 18
PARAM_PATH = 19
PARAM_STATUS = 20
PARAM_END = 21
PROC_PLUG_IN = 1
PROC_EXTENSION = 2
PROC_TEMPORARY = 3
RUN_INTERACTIVE = 0
RUN_NONINTERACTIVE = 1
RUN_WITH_LAST_VALS = 2
STATUS_EXECUTION_ERROR = 0
STATUS_CALLING_ERROR = 1
STATUS_PASS_THROUGH = 2
STATUS_SUCCESS = 3
# extra constants
NORMAL = 0
DISSOLVE = 1
BEHIND = 2
MULTIPLY = 3
SCREEN = 4
OVERLAY = 5
DIFFERENCE = 6
ADDITION = 7
SUBTRACTION = 8
DARKEN_ONLY = 9
LIGHTEN_ONLY = 10
HUE = 11
SATURATION = 12
COLOR = 13
COLOUR = 13
VALUE = 14
FG_BG_RGB = 0
FG_BG_HSV = 1
FG_TRANS = 2
CUSTOM = 3
LINEAR = 0
BILINEAR = 1
RADIAL = 2
SQUARE = 3
CONICAL_SYMMETRIC = 4
CONNUCAL_ASYMMETRIC = 5
SHAPEBURST_ANGULAR = 6
SHAPEBURST_SPHERICAL = 7
SHAPEBURST_DIMPLED = 8
REPEAT_NONE = 0
REPEAT_SAWTOOTH = 1
REPEAT_TRIANGULAR = 2
FG_BUCKET_FILL = 0
BG_BUCKET_FILL = 1
PATTERN_BUCKET_FILL = 2
BG_IMAGE_FILL = 0
WHITE_IMAGE_FILL = 1
TRANS_IMAGE_FILL = 2
NO_IMAGE_FILL = 3
RED_CHANNEL = 0
GREEN_CHANNEL = 1
BLUE_CHANNEL = 2
GRAY_CHANNEL = 3
GREY_CHANNEL = 3
INDEXED_CHANNEL = 4
WHITE_MASK = 0
BLACK_MASK = 1
ALPHA_MASK = 2
APPLY = 0
DISCARD = 1
EXPAND_AS_NECESSARY = 0
CLIP_TO_IMAGE = 1
CLIP_TO_BOTTOM_LAYER = 2
ADD = 0
SUB = 1
REPLACE = 2
INTERSECT = 3
PIXELS = 0
POINTS = 1
IMAGE_CLONE = 0
PATTERN_CLONE = 1
BLUR = 0
SHARPEN = 1
TRUE = 1
FALSE = 0
import gimp
if gimp.major_version > 1 or gimp.major_version==1 and gimp.minor_version>=1:
PARASITE_PERSISTENT = 1
PARASITE_UNDOABLE = 2
PARASITE_ATTACH_PARENT = 0x80 << 8
PARASITE_PARENT_PERSISTENT = PARASITE_PERSISTENT << 8
PARASITE_PARENT_UNDOABLE = PARASITE_UNDOABLE << 8
PARASITE_ATTACH_GRANDPARENT = 0x80 << 16
PARASITE_GRANDPARENT_PERSISTENT = PARASITE_PERSISTENT << 16
PARASITE_GRANDPARENT_UNDOABLE = PARASITE_UNDOABLE << 16
ORIENTATION_UNKNOWN = 0
ORIENTATION_HORIZONTAL = 1
ORIENTATION_VERTICAL = 2
del gimp

495
plug-ins/pygimp/gimpfu.py Normal file
View File

@ -0,0 +1,495 @@
'''Simple interface to writing GIMP plugins in python.
Instead of worrying about all the user interaction, saving last used values
and everything, the gimpfu module can take care of it for you. It provides
a simple register() function that will register your plugin if needed, and
cause your plugin function to be called when needed.
Gimpfu will also handle showing a user interface for editing plugin parameters
if the plugin is called interactively, and will also save the last used
parameters, so the RUN_WITH_LAST_VALUES run_type will work correctly. It
will also make sure that the displays are flushed on completion if the plugin
was run interactively.
When registering the plugin, you do not need to worry about specifying
the run_type parameter. And if the plugin is an image plugin (the menu
path starts with <Image>/), the image and drawable parameters are also
automatically added.
A typical gimpfu plugin would look like this:
from gimpfu import *
def plugin_func(image, drawable, args):
#do what plugins do best
register(
"plugin_func",
"blurb",
"help message",
"author",
"copyright",
"year",
"<Image>/Somewhere/My plugin",
"*",
[(PF_STRING, "arg", "The argument", "default-value")],
[],
plugin_func)
main()
The call to "from gimpfu import *" will import all the gimp constants into
the plugin namespace, and also import the symbols gimp, pdb, register and
main. This should be just about all any plugin needs. You can use any
of the PF_* constants below as parameter types, and an appropriate user
interface element will be displayed when the plugin is run in interactive
mode. Note that the the PF_SPINNER and PF_SLIDER types expect a fifth
element in their description tuple -- a 3-tuple of the form (lower,upper,step),
which defines the limits for the slider or spinner.'''
import string; _string = string; del string
import gimp
from gimpenums import *
pdb = gimp.pdb
error = "gimpfu.error"
PF_INT8 = PARAM_INT8
PF_INT16 = PARAM_INT16
PF_INT32 = PARAM_INT32
PF_INT = PF_INT32
PF_FLOAT = PARAM_FLOAT
PF_STRING = PARAM_STRING
PF_VALUE = PF_STRING
PF_INT8ARRAY = PARAM_INT8ARRAY
PF_INT16ARRAY = PARAM_INT16ARRAY
PF_INT32ARRAY = PARAM_INT32ARRAY
PF_INTARRAY = PF_INT32ARRAY
PF_FLOATARRAY = PARAM_FLOATARRAY
PF_STRINGARRAY = PARAM_STRINGARRAY
PF_COLOR = PARAM_COLOR
PF_COLOUR = PF_COLOR
PF_REGION = PARAM_REGION
#PF_DISPLAY = PARAM_DISPLAY
PF_IMAGE = PARAM_IMAGE
PF_LAYER = PARAM_LAYER
PF_CHANNEL = PARAM_CHANNEL
PF_DRAWABLE = PARAM_DRAWABLE
#PF_SELECTION = PARAM_SELECTION
#PF_BOUNDARY = PARAM_BOUNDARY
#PF_PATH = PARAM_PATH
#PF_STATUS = PARAM_STATUS
PF_TOGGLE = 1000
PF_BOOL = PF_TOGGLE
PF_SLIDER = 1001
PF_SPINNER = 1002
PF_ADJUSTMENT = PF_SPINNER
PF_FONT = 1003
PF_FILE = 1004
PF_BRUSH = 1005
PF_PATTERN = 1006
PF_GRADIENT = 1007
_type_mapping = {
PF_INT8 : PARAM_INT8,
PF_INT16 : PARAM_INT16,
PF_INT32 : PARAM_INT32,
PF_FLOAT : PARAM_FLOAT,
PF_STRING : PARAM_STRING,
PF_INT8ARRAY : PARAM_INT8ARRAY,
PF_INT16ARRAY : PARAM_INT16ARRAY,
PF_INT32ARRAY : PARAM_INT32ARRAY,
PF_FLOATARRAY : PARAM_FLOATARRAY,
PF_STRINGARRAY : PARAM_STRINGARRAY,
PF_COLOUR : PARAM_COLOR,
PF_REGION : PARAM_REGION,
PF_IMAGE : PARAM_IMAGE,
PF_LAYER : PARAM_LAYER,
PF_CHANNEL : PARAM_CHANNEL,
PF_DRAWABLE : PARAM_DRAWABLE,
PF_TOGGLE : PARAM_INT32,
PF_SLIDER : PARAM_FLOAT,
PF_SPINNER : PARAM_INT32,
PF_FONT : PARAM_STRING,
PF_FILE : PARAM_STRING,
PF_BRUSH : PARAM_STRING,
PF_PATTERN : PARAM_STRING,
PF_GRADIENT : PARAM_STRING
}
_registered_plugins_ = {}
def register(func_name, blurb, help, author, copyright, date, menupath,
imagetypes, params, results, function):
'''This is called to register a new plugin.'''
# First perform some sanity checks on the data
def letterCheck(str):
allowed = _string.letters + _string.digits + '_'
for ch in str:
if not ch in allowed:
return 0
else:
return 1
if not letterCheck(func_name):
raise error, "function name contains ileagal characters"
for ent in params:
if len(ent) < 4:
raise error, "sequence not long enough for "+ent[0]
if type(ent[0]) != type(42):
raise error, "parameter types must be integers"
if not letterCheck(ent[1]):
raise error,"parameter name contains ilegal characters"
for ent in results:
if len(ent) < 3:
raise error, "sequence not long enough for "+ent[0]
if type(ent[0]) != type(42):
raise error, "result types must be integers"
if not letterCheck(ent[1]):
raise error,"result name contains ilegal characters"
if menupath[:8] == '<Image>/':
plugin_type = PROC_PLUG_IN
elif menupath[:10] == '<Toolbox>/':
plugin_type = PROC_EXTENSION
else:
raise error, "menu path must start with <Image> or <Toolbox>"
if not func_name[:7] == 'python_' and \
not func_name[:10] == 'extension_' and \
not func_name[:8] == 'plug_in_':
func_name = 'python_fu_' + func_name
_registered_plugins_[func_name] = (blurb, help, author, copyright,
date, menupath, imagetypes,
plugin_type, params, results,
function)
def _query():
for plugin in _registered_plugins_.keys():
(blurb, help, author, copyright, date,
menupath, imagetypes, plugin_type,
params, results, function) = _registered_plugins_[plugin]
fn = lambda x: (_type_mapping[x[0]], x[1], x[2])
params = map(fn, params)
# add the run mode argument ...
params.insert(0, (PARAM_INT32, "run_mode",
"Interactive, Non-Interactive"))
if plugin_type == PROC_PLUG_IN:
params.insert(1, (PARAM_IMAGE, "image",
"The image to work on"))
params.insert(2, (PARAM_DRAWABLE, "drawable",
"The drawable to work on"))
results = map(fn, results)
gimp.install_procedure(plugin, blurb, help, author, copyright,
date, menupath, imagetypes, plugin_type,
params, results)
def _get_defaults(func_name):
import gimpshelf
(blurb, help, author, copyright, date,
menupath, imagetypes, plugin_type,
params, results, function) = _registered_plugins_[func_name]
key = "python-fu-save--" + func_name
if gimpshelf.shelf.has_key(key):
return gimpshelf.shelf[key]
else:
# return the default values
return map(lambda x: x[3], params)
def _set_defaults(func_name, defaults):
import gimpshelf
key = "python-fu-save--" + func_name
gimpshelf.shelf[key] = defaults
def _interact(func_name):
(blurb, help, author, copyright, date,
menupath, imagetypes, plugin_type,
params, results, function) = _registered_plugins_[func_name]
# short circuit for no parameters ...
if len(params) == 0: return []
import gtk
import gimpui
gtk.rc_parse(gimp.gtkrc())
defaults = _get_defaults(func_name)
# define a mapping of param types to edit objects ...
class StringEntry(gtk.GtkEntry):
def __init__(self, default=''):
import gtk
gtk.GtkEntry.__init__(self)
self.set_text(str(default))
def get_value(self):
return self.get_text()
class IntEntry(StringEntry):
def get_value(self):
import string
return string.atoi(self.get_text())
class FloatEntry(StringEntry):
def get_value(self):
import string
return string.atof(self.get_text())
class ArrayEntry(StringEntry):
def get_value(self):
return eval(self.get_text())
class SliderEntry(gtk.GtkHScale):
# bounds is (upper, lower, step)
def __init__(self, default=0, bounds=(0, 100, 5)):
import gtk
self.adj = gtk.GtkAdjustment(default, bounds[0],
bounds[1], bounds[2],
bounds[2], bounds[2])
gtk.GtkHScale.__init__(self, self.adj)
def get_value(self):
return self.adj.value
class SpinnerEntry(gtk.GtkSpinButton):
# bounds is (upper, lower, step)
def __init__(self, default=0, bounds=(0, 100, 5)):
import gtk
self.adj = gtk.GtkAdjustment(default, bounds[0],
bounds[1], bounds[2],
bounds[2], bounds[2])
gtk.GtkSpinButton.__init__(self, self.adj, 1, 0)
def get_value(self):
return int(self.adj.value)
class ToggleEntry(gtk.GtkToggleButton):
def __init__(self, default=0):
import gtk
gtk.GtkToggleButton.__init__(self)
self.label = gtk.GtkLabel("No")
self.add(self.label)
self.label.show()
self.connect("toggled", self.changed)
self.set_active(default)
def changed(self, tog):
if tog.active:
self.label.set_text("Yes")
else:
self.label.set_text("No")
def get_value(self):
return self.get_active()
_edit_mapping = {
PF_INT8 : IntEntry,
PF_INT16 : IntEntry,
PF_INT32 : IntEntry,
PF_FLOAT : FloatEntry,
PF_STRING : StringEntry,
PF_INT8ARRAY : ArrayEntry,
PF_INT16ARRAY : ArrayEntry,
PF_INT32ARRAY : ArrayEntry,
PF_FLOATARRAY : ArrayEntry,
PF_STRINGARRAY : ArrayEntry,
PF_COLOUR : gimpui.ColourSelector,
PF_REGION : IntEntry, # should handle differently ...
PF_IMAGE : gimpui.ImageSelector,
PF_LAYER : gimpui.LayerSelector,
PF_CHANNEL : gimpui.ChannelSelector,
PF_DRAWABLE : gimpui.DrawableSelector,
PF_TOGGLE : ToggleEntry,
PF_SLIDER : SliderEntry,
PF_SPINNER : SpinnerEntry,
PF_FONT : gimpui.FontSelector,
PF_FILE : gimpui.FileSelector,
PF_BRUSH : gimpui.BrushSelector,
PF_PATTERN : gimpui.PatternSelector,
PF_GRADIENT : gimpui.GradientSelector,
}
tooltips = gtk.GtkTooltips()
dialog = gtk.GtkDialog()
dialog.set_title(func_name)
table = gtk.GtkTable(len(params), 3, gtk.FALSE)
table.set_border_width(5)
table.set_row_spacings(2)
table.set_col_spacings(10)
dialog.vbox.pack_start(table)
table.show()
vbox = gtk.GtkVBox(gtk.FALSE, 15)
table.attach(vbox, 0,1, 0,len(params), xoptions=gtk.FILL)
vbox.show()
pix = _get_logo(vbox.get_colormap())
vbox.pack_start(pix, expand=gtk.FALSE)
pix.show()
label = gtk.GtkLabel(blurb)
label.set_line_wrap(TRUE)
label.set_justify(gtk.JUSTIFY_LEFT)
label.set_usize(100, -1)
vbox.pack_start(label, expand=gtk.FALSE)
label.show()
edit_wids = []
for i in range(len(params)):
type = params[i][0]
name = params[i][1]
desc = params[i][2]
def_val = defaults[i]
label = gtk.GtkLabel(name)
label.set_alignment(1.0, 0.5)
table.attach(label, 1,2, i,i+1, xoptions=gtk.FILL)
label.show()
if type in (PF_SPINNER, PF_SLIDER):
wid = _edit_mapping[type](def_val, params[i][4])
else:
wid = _edit_mapping[type](def_val)
table.attach(wid, 2,3, i,i+1)
tooltips.set_tip(wid, desc, None)
wid.show()
edit_wids.append(wid)
def delete_event(win, event=None):
import gtk
win.hide()
gtk.mainquit()
return TRUE
# this is a hack ...
finished = [ 0 ]
def ok_clicked(button, win=dialog, finished=finished):
import gtk
win.hide()
finished[0] = 1
gtk.mainquit()
b = gtk.GtkButton("OK")
b.set_flags(gtk.CAN_DEFAULT)
dialog.action_area.pack_start(b)
b.grab_default()
b.connect("clicked", ok_clicked)
b.show()
b = gtk.GtkButton("Cancel")
b.set_flags(gtk.CAN_DEFAULT)
dialog.action_area.pack_start(b)
b.connect("clicked", delete_event)
b.show()
dialog.show()
tooltips.enable()
# run the main loop
gtk.mainloop()
ret = None
if finished[0]:
# OK was clicked
ret = map(lambda wid: wid.get_value(), edit_wids)
_set_defaults(func_name, ret)
dialog.destroy()
return ret
def _run(func_name, params):
run_mode = params[0]
plugin_type = _registered_plugins_[func_name][7]
func = _registered_plugins_[func_name][10]
if plugin_type == PROC_PLUG_IN:
start_params = params[1:3]
extra_params = params[3:]
else:
start_params = ()
extra_params = params[1:]
if run_mode == RUN_INTERACTIVE:
extra_params = _interact(func_name)
if extra_params == None:
return
elif run_mode == RUN_WITH_LAST_VALS:
extra_params = _get_defaults(func_name)
params = start_params + tuple(extra_params)
res = apply(func, params)
if run_mode != RUN_NONINTERACTIVE: gimp.displays_flush()
def main():
'''This should be called after registering the plugin.'''
gimp.main(None, None, _query, _run)
_python_image = [
"64 64 7 1",
" c #000000",
". c #00FF00",
"X c None",
"o c #FF0000",
"O c #FFFF00",
"+ c #808000",
"@ c #0000FF",
"XXXXXXXXXXXXXX XX XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX",
"XXXXXXXXXXXXXX XX XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX",
"XXXXXXXXXXXX ++++ ++++++ XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX",
"XXXXXXXXXXXX ++++ ++++++ XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX",
"XXXXXXXXXX ++++ XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX",
"XXXXXXXXXX ++++ XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX",
"XXXXXXXXXX OOOO OOOOOO ++ XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX",
"XXXXXXXXXX OOOO OOOOOO ++ XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX",
"XXXXXXXXXX OO@@ OO@@@@ ++ XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX",
"XXXXXXXXXX OO@@ OO@@@@ ++ XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX",
"XXXXXXXXXX OO@@ OO@@@@ ++ XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX",
"XXXXXXXXXX OO@@ OO@@@@ ++ XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX",
"XXXXXXXXXX OOOO OOOOOO ++ XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX",
"XXXXXXXXXX OOOO OOOOOO ++ XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX",
"XXXXXXXX ++ ++++++ XXXXXXXXXXXXXXXXXXXXXXXXXX",
"XXXXXXXX ++ ++++++ XXXXXXXXXXXXXXXXXXXXXXXXXX",
"XXXX ++++++++++++++++++++++ ++++++ XXXXXXXXXXXXXXXXXXXXXX",
"XXXX ++++++++++++++++++++++ ++++++ XXXXXXXXXXXXXXXXXXXXXX",
"XX ++++++++++++++++++++++++++++ ++++++++ XXXXXXXXXXXXXXXXXXXX",
"XX ++++++++++++++++++++++++++++ ++++++++ XXXXXXXXXXXXXXXXXXXX",
" ++++++++++++++++++++++++++++++++ ++++++++ XXXXXXXXXXXXXXXXXX",
" ++++++++++++++++++++++.+.+..++++ ++++++++ XXXXXXXXXXXXXXXXXX",
" ++ ++++ ++++++++++.+........++ ++++++++ XXXXXXXXXXXXXXXXXX",
" ++ ++++ ++++++++.+...........+ ++++++++ XXXXXXXXXXXXXXXXXX",
" ++++++++++++++++++.+.. ...... ++++++++++ XXXXXXXXXXXXXXXX",
" ++++++++++++++++.+... ...... ++++++++++ XXXXXXXXXXXXXXXX",
" .+.+.+.+.+.+.+.+.... ..++.. ..++++++++++ XXXXXXXXXXXXXXXX",
" .+.+.+.+.+.+.+..... ..++.. ...+++++++++ XXXXXXXXXXXXXXXX",
" ................ ++.... ......++++++++ XXXXXXXXXXXXXXXX",
" ............... +..... +......+++++++ XXXXXXXXXXXXXXXX",
"XX +.+.+.+.+..+ ++++.. ++++...+++++++ XXXXXXXXXXXXXXXX",
"XX ++++++++++++ +...... ++++...+++++++ XXXXXXXXXXXXXXXX",
"XXXX ooooo ++.... XX +......+++++++ XXXXXXXXXXXXXXXX",
"XXXX ooooo ++..... XX .......+++++++ XXXXXXXXXXXXXXXX",
"XXXX ooooo ++...... XXXX ++....++++++ XXXXXXXXXXXXXXXXXX",
"XXXX ooooo ++....... XXXX ++...+++++++ XXXXXXXXXXXXXXXXXX",
"XXXX ooooo.++...... XXXX +......+++++++ XXXXXXXXXXXXXXXXXX",
"XXXX ooooo..+....... XXXX ......++++++++ XXXXXXXXXXXXXXXXXX",
"XXXXooooo....... XXXX +++++....+++++++ XXXXXXXXXXXXXXXXXXXX",
"XXXooooo........ XXXX +++++..+++++++++ XXXXXXXXXXXXXXXXXXXX",
"XXoooo XXXXXX +.......++++++++ XXXXXXXXXXXXXXXXXXXXXX",
"Xooooo XXXXXX .......+++++++++ XXXXXXXXXXXXXXXXXXXXXX",
"oooXooXXXXXXXXXXXX +++++....+++++++++ XXXXXXXXXXXXXXXXXXXXXX ",
"ooXXooXXXXXXXXXXXX +++++...++++++++++ XXXXXXXXXXXXXXXXXXXXXX ",
"XXXXooXXXXXXXX ++.......+++++++++ XXXXXXXXXXXXXXXXXXXXXX ",
"XXXXooXXXXXXXX +.......++++++++++ XXXXXXXXXXXXXXXXXXXXXX ",
"XXXXXXXXXXXX ++++++.....+++++++++ XXXXXX XXXX ++ ",
"XXXXXXXXXXXX ++++++....++++++++++ XXXXXX XXXX ++ ",
"XXXXXXXXXXXX +........+++++++++ ++++++++ XX ++++++ ++++ ",
"XXXXXXXXXXXX ........++++++++++ ++++++++ XX ++++++ ++++ ",
"XXXXXXXXXX ..........++++++++ ++++++++++++ ++++++++++++++++ ",
"XXXXXXXXXX .........+++++++++ ++++++++++++ ++++++++++++++++ ",
"XXXXXXXXXX ++++....++++++++++++++++++++++++++++++++++++++++ XX",
"XXXXXXXXXX +++++...++++++++++++++++++++++++++++++++++++++++ XX",
"XXXXXXXXXX ++++....++++++++++++++++++++++++++++++ ..... XXXX",
"XXXXXXXXXX ........++++++++++++++++++++++++++++++ .... XXXX",
"XXXXXXXXXX .........+++++++++++..++++++++++++++ XXXX XXXXXX",
"XXXXXXXXXX .............+++++++..++++++++++++++ XXXX XXXXXX",
"XXXXXXXXXXXX +++++............ ............ XXXXXXXXXXXXXXXX",
"XXXXXXXXXXXX ++++++.......... .......... XXXXXXXXXXXXXXXX",
"XXXXXXXXXXXXXX +.....++.. XXXX XXXXXXXXXXXXXXXXXXXX",
"XXXXXXXXXXXXXX .....++++. XXXX XXXXXXXXXXXXXXXXXXXX",
"XXXXXXXXXXXXXXXX XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX",
"XXXXXXXXXXXXXXXX XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX"
]
def _get_logo(colormap):
import gtk
pix, mask = gtk.create_pixmap_from_xpm_d(colormap, None, _python_image)
return gtk.GtkPixmap(pix, mask)

4607
plug-ins/pygimp/gimpmodule.c Normal file

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,56 @@
# Gimp-Python - allows the writing of Gimp plugins in Python.
# Copyright (C) 1997 James Henstridge <james@daa.com.au>
#
# 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 2 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, write to the Free Software
# Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
# plugin.py -- helper for writing gimp plugins
# Copyright (C) 1997, James Henstridge.
#
# This is a small wrapper that makes plugins look like an object class that
# you can derive to create your plugin. With this wrapper, you are pretty
# much responsible for doing everything (checking run_mode, gui, etc). If
# you want to write a quick plugin, you probably want the gimpfu module.
#
# A plugin using this module would look something like this:
#
# import gimp, gimpplugin
# pdb = gimp.pdb
# class myplugin(gimpplugin.plugin):
# def query(self):
# gimp.install_procedure("plug_in_mine", ...)
# def plug_in_mine(self, par1, par2, par3,...):
# do_something()
#
# if __name__ == '__main__': myplugin().start()
import gimp
class plugin:
def start(self):
gimp.main(self.init, self.quit, self.query, self._run)
def init(self):
pass
def quit(self):
pass
def query(self):
pass
def _run(self, name, params):
if hasattr(self, name):
apply(getattr(self, name), params)
else:
raise AttributeError, name
if __name__ == '__main__': plugin().start()

View File

@ -0,0 +1,83 @@
# Gimp-Python - allows the writing of Gimp plugins in Python.
# Copyright (C) 1997 James Henstridge <james@daa.com.au>
#
# 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 2 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, write to the Free Software
# Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
# gimshelf.py -- a simple module to help gimp modules written in Python
# store persistent data.
#
# Copyright (C) 1997, James Henstridge
#
# The gimp module provides a basic method for storing information that persists
# for a whole gimp session, but only allows for the storage of strings. This
# is because other Python types usually have pointers to other Python objects,
# making it dificult to work out what to save. This module gives an interface
# to the gimp module's primitive interface, which resembles the shelve module.
try:
# use cPickle instead of pickle if it is available.
import cPickle
pickle = cPickle
del cPickle
except ImportError:
import pickle
import StringIO
import gimp
try:
# this will fail with python 1.4. All we lose is that the values
# for a plugin which takes extra image/drawables/etc will not be
# saved between invocations.
import copy_reg
def _image_id(obj):
return gimp._id2image, (obj.ID,)
def _drawable_id(obj):
return gimp._id2drawable, (obj.ID,)
def _display_id(obj):
return gimp._id2display, int(obj)
copy_reg.pickle(gimp.ImageType, _image_id, gimp._id2image)
copy_reg.pickle(gimp.LayerType, _drawable_id, gimp._id2drawable)
copy_reg.pickle(gimp.ChannelType, _drawable_id, gimp._id2drawable)
copy_reg.pickle(gimp.DisplayType, _display_id, gimp._id2display)
del copy_reg, _image_id, _drawable_id, _display_id
except ImportError:
pass
class Gimpshelf:
def has_key(self, key):
try:
s = gimp.get_data(key)
return 1
except gimp.error:
return 0
def __getitem__(self, key):
try:
s = gimp.get_data(key)
except gimp.error:
raise KeyError, key
f = StringIO.StringIO(s)
return pickle.Unpickler(f).load()
def __setitem__(self, key, value):
f = StringIO.StringIO()
p = pickle.Pickler(f)
p.dump(value)
gimp.set_data(key, f.getvalue())
def __delitem__(self, key):
gimp.set_data(key, '')
shelf = Gimpshelf()
del Gimpshelf

364
plug-ins/pygimp/gimpui.py Normal file
View File

@ -0,0 +1,364 @@
'''This module implements the UI items found in the libgimpui library.
It requires pygtk to work. These functions take use to callbacks -- one
is a constraint function, and the other is the callback object. The
constraint function takes an image object as its first argument, and
a drawable object as its second if appropriate. The callback functions
get the selected object as their first argument, and the user data as
the second.
It also implements a number of selector widgets, which can be used to select
various gimp data types. Each of these selectors takes default as an argument
to the constructor, and has a get_value() method for retrieving the result.
'''
import gtk, gimp
def _callbackWrapper(menu_item, callback, data):
callback(menu_item.get_data("Gimp-ID"), data)
def _createMenu(items, callback, data):
menu = gtk.GtkMenu()
if not items:
items = [("(none)", None)]
for label, id in items:
menu_item = gtk.GtkMenuItem(label)
menu_item.set_data("Gimp-ID", id)
menu.add(menu_item)
if callback:
menu_item.connect("activate", _callbackWrapper,
callback, data)
menu_item.show()
return menu
def ImageMenu(constraint=None, callback=None, data=None):
items = []
for img in gimp.query_images():
if constraint and not constraint(img):
continue
items.append((img.filename, img))
items.sort()
return _createMenu(items, callback, data)
def LayerMenu(constraint=None, callback=None, data=None):
items = []
for img in gimp.query_images():
filename = img.filename
for layer in img.layers:
if constraint and not constraint(img, layer):
continue
name = filename + "/" + layer.name
items.append((name, layer))
items.sort()
return _createMenu(items, callback, data)
def ChannelMenu(constraint=None, callback=None, data=None):
items = []
for img in gimp.query_images():
filename = img.filename
for channel in img.channels:
if constraint and not constraint(img, channel):
continue
name = filename + "/" + channel.name
items.append((name, channel))
items.sort()
return _createMenu(items, callback, data)
def DrawableMenu(constraint=None, callback=None, data=None):
items = []
for img in gimp.query_images():
filename = img.filename
for drawable in img.layers + img.channels:
if constraint and not constraint(img, drawable):
continue
name = filename + "/" + drawable.name
items.append((name, drawable))
items.sort()
return _createMenu(items, callback, data)
class ImageSelector(gtk.GtkOptionMenu):
def __init__(self, default=None):
gtk.GtkOptionMenu.__init__(self)
self.menu = ImageMenu(None, self.clicked)
self.set_menu(self.menu)
self.selected = default
children = self.menu.children()
for child in range(len(children)):
if children[child].get_data("Gimp-ID") == default:
self.set_history(child)
break
def clicked(self, img, data=None):
self.selected = img
def get_value(self):
return self.selected
class LayerSelector(gtk.GtkOptionMenu):
def __init__(self, default=None):
gtk.GtkOptionMenu.__init__(self)
self.menu = LayerMenu(None, self.clicked)
self.set_menu(self.menu)
self.selected = default
children = self.menu.children()
for child in range(len(children)):
if children[child].get_data("Gimp-ID") == default:
self.set_history(child)
break
def clicked(self, layer, data=None):
self.selected = layer
def get_value(self):
return self.selected
class ChannelSelector(gtk.GtkOptionMenu):
def __init__(self, default=None):
gtk.GtkOptionMenu.__init__(self)
self.menu = ChannelMenu(None, self.clicked)
self.set_menu(self.menu)
self.selected = default
children = self.menu.children()
for child in range(len(children)):
if children[child].get_data("Gimp-ID") == default:
self.set_history(child)
break
def clicked(self, channel, data=None):
self.selected = channel
def get_value(self):
return self.selected
class DrawableSelector(gtk.GtkOptionMenu):
def __init__(self, default=None):
gtk.GtkOptionMenu.__init__(self)
self.menu = DrawableMenu(None, self.clicked)
self.set_menu(self.menu)
self.selected = default
children = self.menu.children()
for child in range(len(children)):
if children[child].get_data("Gimp-ID") == default:
self.set_history(child)
break
def clicked(self, drawable, data=None):
self.selected = drawable
def get_value(self):
return self.selected
class ColourSelector(gtk.GtkButton):
def __init__(self, default=(255, 0, 0)):
gtk.GtkButton.__init__(self)
self.set_usize(100, 20)
self.colour = default
self.update_colour()
self.dialog = None
self.connect("clicked", self.show_dialog)
def update_colour(self):
r, g, b = self.colour
colour = self.get_colormap().alloc(r*256, g*256, b*256)
style = self.get_style().copy()
style.bg[gtk.STATE_NORMAL] = colour
style.bg[gtk.STATE_PRELIGHT] = colour
self.set_style(style)
self.queue_draw()
def show_dialog(self, button):
if self.dialog:
self.dialog.show()
return
self.dialog = gtk.GtkColorSelectionDialog("Colour")
self.dialog.colorsel.set_color(tuple(map(lambda x: x/255.0,
self.colour)))
def delete_event(win, event):
win.hide()
return gtk.TRUE
self.dialog.connect("delete_event", delete_event)
self.dialog.ok_button.connect("clicked", self.selection_ok)
self.dialog.cancel_button.connect("clicked", self.dialog.hide)
self.dialog.show()
def selection_ok(self, button):
colour = self.dialog.colorsel.get_color()
self.colour = tuple(map(lambda x: int(x*255.99), colour))
self.update_colour()
self.dialog.hide()
def get_value(self):
return self.colour
class _Selector(gtk.GtkHBox):
def __init__(self):
gtk.GtkHBox.__init__(self, gtk.FALSE, 5)
self.entry = gtk.GtkEntry()
self.pack_start(self.entry)
self.entry.show()
self.button = gtk.GtkButton("...")
self.button.connect("clicked", self.show_dialog)
self.pack_start(self.button, expand=gtk.FALSE)
self.button.show()
self.dialog = gtk.GtkDialog()
self.dialog.set_title(self.get_title())
def delete_event(win, event):
win.hide()
return gtk.TRUE
self.dialog.connect("delete_event", delete_event)
box = gtk.GtkVBox()
box.set_border_width(5)
self.dialog.vbox.pack_start(box)
box.show()
swin = gtk.GtkScrolledWindow()
swin.set_policy(gtk.POLICY_AUTOMATIC, gtk.POLICY_AUTOMATIC)
box.pack_start(swin)
swin.show()
items = map(None, self.get_list())
list = gtk.GtkList()
list.set_selection_mode(gtk.SELECTION_BROWSE)
self.selected = self.get_default()
self.entry.set_text(self.selected)
items.sort()
for s in items:
item = gtk.GtkListItem(s)
list.add(item)
if s == self.selected:
list.select_child(item)
item.show()
swin.add_with_viewport(list)
list.show()
b = gtk.GtkButton("OK")
self.dialog.action_area.pack_start(b)
b.set_flags(gtk.CAN_DEFAULT)
b.grab_default()
b.show()
b.connect("clicked", self.selection_ok, list)
b = gtk.GtkButton("Cancel")
self.dialog.action_area.pack_start(b)
b.set_flags(gtk.CAN_DEFAULT)
b.show()
b.connect("clicked", self.dialog.hide)
self.dialog.set_usize(300, 225)
def show_dialog(self, button):
self.dialog.show()
def selection_ok(self, button, list):
self.dialog.hide()
sel = list.get_selection()
if not sel: return
self.selected = sel[0].children()[0].get()
self.entry.set_text(self.selected)
def get_value(self):
return self.selected
class PatternSelector(_Selector):
def __init__(self, default=""):
self.default = default
_Selector.__init__(self)
def get_default(self):
return self.default
def get_title(self):
return "Patterns"
def get_list(self):
num, patterns = gimp.pdb.gimp_patterns_list()
return patterns
class BrushSelector(_Selector):
def __init__(self, default=""):
self.default = default
_Selector.__init__(self)
def get_default(self):
return self.default
def get_title(self):
return "Brushes"
def get_list(self):
num, brushes = gimp.pdb.gimp_brushes_list()
return brushes
class GradientSelector(_Selector):
def __init__(self, default=""):
self.default = default
_Selector.__init__(self)
def get_default(self):
return self.default
def get_title(self):
return "Gradients"
def get_list(self):
num, gradients = gimp.pdb.gimp_gradients_get_list()
return gradients
class FontSelector(gtk.GtkHBox):
def __init__(self, default="fixed"):
gtk.GtkHBox.__init__(self, gtk.FALSE, 5)
self.entry = gtk.GtkEntry()
self.pack_start(self.entry)
self.entry.show()
self.button = gtk.GtkButton("...")
self.button.connect("clicked", self.show_dialog)
self.pack_start(self.button, expand=gtk.FALSE)
self.button.show()
self.dialog = gtk.GtkFontSelectionDialog("Fonts")
self.dialog.set_default_size(400, 300)
def delete_event(win, event):
win.hide()
return gtk.TRUE
self.dialog.connect("delete_event", delete_event)
self.dialog.ok_button.connect("clicked", self.selection_ok)
self.dialog.cancel_button.connect("clicked", self.dialog.hide)
self.dialog.set_font_name(default)
self.selected = default
self.entry.set_text(self.selected)
def show_dialog(self, button):
self.dialog.show()
def selection_ok(self, button):
self.dialog.hide()
self.selected = self.dialog.get_font_name()
self.entry.set_text(self.selected)
def get_value(self):
return self.selected
class FileSelector(gtk.GtkHBox):
def __init__(self, default=""):
gtk.GtkHBox.__init__(self, gtk.FALSE, 5)
self.entry = gtk.GtkEntry()
self.pack_start(self.entry)
self.entry.show()
self.button = gtk.GtkButton("...")
self.button.connect("clicked", self.show_dialog)
self.pack_start(self.button, expand=gtk.FALSE)
self.button.show()
self.dialog = gtk.GtkFileSelection("Fonts")
self.dialog.set_default_size(400, 300)
def delete_event(win, event):
win.hide()
return gtk.TRUE
self.dialog.connect("delete_event", delete_event)
self.dialog.ok_button.connect("clicked", self.selection_ok)
self.dialog.cancel_button.connect("clicked", self.dialog.hide)
self.dialog.set_filename(default)
self.selected = self.dialog.get_filename()
self.entry.set_text(self.selected)
def show_dialog(self, button):
self.dialog.show()
def selection_ok(self, button):
self.dialog.hide()
self.selected = self.dialog.get_filename()
self.entry.set_text(self.selected)
def get_value(self):
return self.selected

View File

@ -0,0 +1,5 @@
Makefile
Makefile.in
*.pyc
*.pyo

View File

@ -0,0 +1,7 @@
pluginexec_SCRIPTS = clothify.py gimpcons.py pdbbrowse.py sphere.py \
whirlpinch.py foggify.py shadow_bevel.py
pluginexec_DATA = gtkcons.py
EXTRA_DIST = clothify.py gimpcons.py pdbbrowse.py sphere.py gtkcons.py \
whirlpinch.py foggify.py shadow_bevel.py

View File

@ -0,0 +1,74 @@
#!/usr/bin/env python
# Gimp-Python - allows the writing of Gimp plugins in Python.
# Copyright (C) 1997 James Henstridge <james@daa.com.au>
#
# 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 2 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, write to the Free Software
# Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
import math
from gimpfu import *
have_gimp11 = gimp.major_version > 1 or \
gimp.major_version == 1 and gimp.minor_version >= 1
def python_clothify(timg, tdrawable, bx=9, by=9,
azimuth=135, elevation=45, depth=3):
bx = 9 ; by = 9 ; azimuth = 135 ; elevation = 45 ; depth = 3
width = tdrawable.width
height = tdrawable.height
img = gimp.image(width, height, RGB)
layer_one = gimp.layer(img, "X Dots", width, height, RGB_IMAGE,
100, NORMAL_MODE)
img.disable_undo()
if have_gimp11:
pdb.gimp_edit_fill(layer_one)
else:
pdb.gimp_edit_fill(img, layer_one)
img.add_layer(layer_one, 0)
pdb.plug_in_noisify(img, layer_one, 0, 0.7, 0.7, 0.7, 0.7)
layer_two = layer_one.copy()
layer_two.mode = MULTIPLY_MODE
layer_two.name = "Y Dots"
img.add_layer(layer_two, 0)
pdb.plug_in_gauss_rle(img, layer_one, bx, 1, 0)
pdb.plug_in_gauss_rle(img, layer_two, by, 0, 1)
img.flatten()
bump_layer = img.active_layer
pdb.plug_in_c_astretch(img, bump_layer)
pdb.plug_in_noisify(img, bump_layer, 0, 0.2, 0.2, 0.2, 0.2)
pdb.plug_in_bump_map(img, tdrawable, bump_layer, azimuth,
elevation, depth, 0, 0, 0, 0, TRUE, FALSE, 0)
gimp.delete(img)
register(
"python_fu_clothify",
"Make the specified layer look like it is printed on cloth",
"Make the specified layer look like it is printed on cloth",
"James Henstridge",
"James Henstridge",
"1997-1999",
"<Image>/Python-Fu/Alchemy/Clothify",
"RGB*, GRAY*",
[
(PF_INT, "x_blur", "X Blur", 9),
(PF_INT, "y_blur", "Y Blur", 9),
(PF_INT, "azimuth", "Azimuth", 135),
(PF_INT, "elevation", "elevation", 45),
(PF_INT, "depth", "Depth", 3)
],
[],
python_clothify)
main()

View File

@ -0,0 +1,54 @@
#!/usr/bin/env python
from gimpfu import *
import time
have_gimp11 = gimp.major_version > 1 or \
gimp.major_version == 1 and gimp.minor_version >= 1
def python_foggify(img, layer, name, colour, turbulence, opacity):
img.disable_undo()
fog = gimp.layer(img, name, layer.width, layer.height, RGBA_IMAGE,
opacity, NORMAL_MODE)
oldbg = gimp.get_background()
gimp.set_background(colour)
if have_gimp11:
pdb.gimp_edit_fill(fog)
else:
pdb.gimp_edit_fill(img, fog)
gimp.set_background(oldbg)
img.add_layer(fog, 0)
# create a layer mask for the new layer
mask = fog.create_mask(0)
img.add_layer_mask(fog, mask)
# add some clouds to the layer
pdb.plug_in_plasma(img, mask, int(time.time()), turbulence)
# apply the clouds to the layer
img.remove_layer_mask(fog, APPLY)
img.enable_undo()
register(
"python_fu_foggify",
"Add a layer of fog to the image",
"Add a layer of fog to the image",
"James Henstridge",
"James Henstridge",
"1999",
"<Image>/Python-Fu/Effects/Add fog",
"RGB*, GRAY*",
[
(PF_STRING, "name", "The new layer name", "Clouds"),
(PF_COLOUR, "colour", "The colour of the fog", (240,180,70)),
(PF_SLIDER, "turbulence", "The turbulence", 1.0, (0, 10, 0.1)),
(PF_SLIDER, "opacity", "The opacity", 100, (0, 100, 1)),
],
[],
python_foggify)
main()

View File

@ -0,0 +1,81 @@
#!/usr/bin/env python
# Gimp-Python - allows the writing of Gimp plugins in Python.
# Copyright (C) 1997 James Henstridge <james@daa.com.au>
#
# 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 2 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, write to the Free Software
# Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
from gimpfu import *
import gtkcons
def extension_python_fu_console():
import gtk, gimpenums, gimpshelf
gtk.rc_parse(gimp.gtkrc())
namespace = {'__builtins__': __builtins__,
'__name__': '__main__', '__doc__': None,
'gimp': gimp, 'pdb': gimp.pdb,
'shelf': gimpshelf.shelf}
for s in gimpenums.__dict__.keys():
if s[0] != '_':
namespace[s] = getattr(gimpenums, s)
win = gtk.GtkWindow()
win.connect("destroy", gtk.mainquit)
win.set_title("Gimp-Python Console")
cons = gtkcons.Console(namespace=namespace,
copyright='Gimp Python Extensions - Copyright (C), 1997-1999' +
' James Henstridge\n', quit_cb=gtk.mainquit)
def browse(button, cons):
import gtk, pdbbrowse
def ok_clicked(button, browse, cons=cons):
cons.line.set_text(browse.cmd)
browse.destroy()
win = pdbbrowse.BrowseWin(ok_button=ok_clicked)
win.connect("destroy", gtk.mainquit)
win.set_modal(TRUE)
win.show()
gtk.mainloop()
button = gtk.GtkButton("Browse")
button.connect("clicked", browse, cons)
cons.inputbox.pack_end(button, expand=FALSE)
button.show()
win.add(cons)
cons.show()
win.set_default_size(475, 300)
win.show()
cons.init()
# flush the displays every half second
def timeout():
gimp.displays_flush()
return TRUE
gtk.timeout_add(500, timeout)
gtk.mainloop()
register(
"python_fu_console",
"Python interactive interpreter with gimp extensions",
"Type in commands and see results",
"James Henstridge",
"James Henstridge",
"1997-1999",
"<Toolbox>/Xtns/Python-Fu/Console",
"*",
[],
[],
extension_python_fu_console)
main()

View File

@ -0,0 +1,330 @@
#!/usr/bin/env python
# Interactive Python-GTK Console
# Copyright (C), 1998 James Henstridge <james@daa.com.au>
#
# 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 2 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, write to the Free Software
# Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
# This module implements an interactive python session in a GTK window. To
# start the session, use the gtk_console command. Its specification is:
# gtk_console(namespace, title, copyright)
# where namespace is a dictionary representing the namespace of the session,
# title is the title on the window and
# copyright is any additional copyright info to print.
#
# As well as the starting attributes in namespace, the session will also
# have access to the list __history__, which is the command history.
import sys, string, traceback
#sys.path.append('/home/james/.gimp/plug-ins')
from gtk import *
stdout = sys.stdout
if not hasattr(sys, 'ps1'): sys.ps1 = '>>> '
if not hasattr(sys, 'ps2'): sys.ps2 = '... '
# some functions to help recognise breaks between commands
def remQuotStr(s):
'''Returns s with any quoted strings removed (leaving quote marks)'''
r = ''
inq = 0
qt = ''
prev = '_'
while len(s):
s0, s = s[0], s[1:]
if inq and (s0 != qt or prev == '\\'):
prev = s0
continue
prev = s0
if s0 in '\'"':
if inq:
inq = 0
else:
inq = 1
qt = s0
r = r + s0
return r
def bracketsBalanced(s):
'''Returns true iff the brackets in s are balanced'''
s = filter(lambda x: x in '()[]{}', s)
stack = []
brackets = {'(':')', '[':']', '{':'}'}
while len(s) != 0:
if s[0] in ")]}":
if len(stack) != 0 and brackets[stack[-1]] == s[0]:
del stack[-1]
else:
return 0
else:
stack.append(s[0])
s = s[1:]
return len(stack) == 0
class gtkoutfile:
'''A fake output file object. It sends output to a TK test widget,
and if asked for a file number, returns one set on instance creation'''
def __init__(self, w, fn, font):
self.__fn = fn
self.__w = w
self.__font = font
def close(self): pass
flush = close
def fileno(self): return self.__fn
def isatty(self): return 0
def read(self, a): return ''
def readline(self): return ''
def readlines(self): return []
def write(self, s):
#stdout.write(str(self.__w.get_point()) + '\n')
self.__w.freeze()
self.__w.insert(self.__font, self.__w.fg,
self.__w.bg, s)
self.__w.thaw()
self.__w.queue_draw()
def writelines(self, l):
self.__w.freeze()
for s in l: self.__w.insert(self.__font,
self.__w.fg, self.__w.bg, s)
self.__w.thaw()
self.__w.queue_draw()
def seek(self, a): raise IOError, (29, 'Illegal seek')
def tell(self): raise IOError, (29, 'Illegal seek')
truncate = tell
class Console(GtkVBox):
def __init__(self, namespace={}, copyright='', quit_cb=None):
GtkVBox.__init__(self, spacing=2)
self.set_border_width(2)
self.copyright = copyright
#self.set_usize(475, 300)
self.quit_cb = quit_cb
#load the fonts we will use
self.normal = load_font(
"-*-helvetica-medium-r-normal-*-*-100-*-*-*-*-*-*")
self.title = load_font(
"-*-helvetica-bold-r-normal-*-*-100-*-*-*-*-*-*")
self.error = load_font(
"-*-helvetica-medium-o-normal-*-12-100-*-*-*-*-*-*")
self.command = load_font(
"-*-helvetica-bold-r-normal-*-*-100-*-*-*-*-*-*")
self.inp = GtkHBox()
self.pack_start(self.inp)
self.inp.show()
self.text = GtkText()
self.text.set_editable(FALSE)
self.text.set_word_wrap(TRUE)
self.text.set_usize(500, 400)
self.inp.pack_start(self.text, padding=1)
self.text.show()
self.vscroll = GtkVScrollbar(self.text.get_vadjustment())
self.vscroll.set_update_policy(POLICY_AUTOMATIC)
self.inp.pack_end(self.vscroll, expand=FALSE)
self.vscroll.show()
self.inputbox = GtkHBox(spacing=2)
self.pack_end(self.inputbox, expand=FALSE)
self.inputbox.show()
self.prompt = GtkLabel(sys.ps1)
self.prompt.set_padding(xp=2, yp=0)
self.prompt.set_usize(26, -1)
self.inputbox.pack_start(self.prompt, fill=FALSE, expand=FALSE)
self.prompt.show()
self.closer = GtkButton("Close")
self.closer.connect("clicked", self.quit)
self.inputbox.pack_end(self.closer, fill=FALSE, expand=FALSE)
self.closer.show()
self.line = GtkEntry()
self.line.set_usize(400,-1)
self.line.connect("key_press_event", self.key_function)
self.inputbox.pack_start(self.line, padding=2)
self.line.show()
# now let the text box be resized
self.text.set_usize(0, 0)
self.line.set_usize(0, -1)
self.namespace = namespace
self.cmd = ''
self.cmd2 = ''
# set up hooks for standard output.
self.stdout = gtkoutfile(self.text, sys.stdout.fileno(),
self.normal)
self.stderr = gtkoutfile(self.text, sys.stderr.fileno(),
self.error)
# set up command history
self.history = ['']
self.histpos = 0
self.namespace['__history__'] = self.history
def init(self):
self.text.realize()
self.text.style = self.text.get_style()
self.text.fg = self.text.style.fg[STATE_NORMAL]
self.text.bg = self.text.style.white
self.text.insert(self.title, self.text.fg,
self.text.bg, 'Python %s\n%s\n\n' %
(sys.version, sys.copyright) +
'Interactive Python-GTK Console - ' +
'Copyright (C) 1998 James Henstridge\n\n' +
self.copyright + '\n')
self.line.grab_focus()
def quit(self, *args):
self.hide()
self.destroy()
if self.quit_cb: self.quit_cb()
def key_function(self, entry, event):
if event.keyval == GDK.Return:
self.line.emit_stop_by_name("key_press_event")
self.eval()
if event.keyval == GDK.Tab:
self.line.emit_stop_by_name("key_press_event")
self.line.append_text('\t')
idle_add(self.focus_text)
elif event.keyval in (GDK.KP_Up, GDK.Up):
self.line.emit_stop_by_name("key_press_event")
self.historyUp()
idle_add(self.focus_text)
elif event.keyval in (GDK.KP_Down, GDK.Down):
self.line.emit_stop_by_name("key_press_event")
self.historyDown()
idle_add(self.focus_text)
elif event.keyval in (GDK.D, GDK.d) and \
event.state & GDK.CONTROL_MASK:
self.line.emit_stop_by_name("key_press_event")
self.ctrld()
def focus_text(self):
self.line.grab_focus()
return FALSE # don't requeue this handler
def ctrld(self):
#self.quit()
pass
def historyUp(self):
if self.histpos > 0:
l = self.line.get_text()
if len(l) > 0 and l[0] == '\n': l = l[1:]
if len(l) > 0 and l[-1] == '\n': l = l[:-1]
self.history[self.histpos] = l
self.histpos = self.histpos - 1
self.line.set_text(self.history[self.histpos])
def historyDown(self):
if self.histpos < len(self.history) - 1:
l = self.line.get_text()
if len(l) > 0 and l[0] == '\n': l = l[1:]
if len(l) > 0 and l[-1] == '\n': l = l[:-1]
self.history[self.histpos] = l
self.histpos = self.histpos + 1
self.line.set_text(self.history[self.histpos])
def eval(self):
l = self.line.get_text() + '\n'
if len(l) > 1 and l[0] == '\n': l = l[1:]
self.histpos = len(self.history) - 1
if len(l) > 0 and l[-1] == '\n':
self.history[self.histpos] = l[:-1]
else:
self.history[self.histpos] = l
self.line.set_text('')
self.text.freeze()
self.text.insert(self.command, self.text.fg, self.text.bg,
self.prompt.get() + l)
self.text.thaw()
if l == '\n':
self.run(self.cmd)
self.cmd = ''
self.cmd2 = ''
return
self.histpos = self.histpos + 1
self.history.append('')
self.cmd = self.cmd + l
self.cmd2 = self.cmd2 + remQuotStr(l)
l = string.rstrip(l)
if not bracketsBalanced(self.cmd2) or l[-1] == ':' or \
l[-1] == '\\' or l[0] in ' \11':
self.prompt.set_text(sys.ps2)
self.prompt.queue_draw()
return
self.run(self.cmd)
self.cmd = ''
self.cmd2 = ''
def run(self, cmd):
sys.stdout, self.stdout = self.stdout, sys.stdout
sys.stderr, self.stderr = self.stderr, sys.stderr
try:
try:
r = eval(cmd, self.namespace, self.namespace)
if r is not None:
print `r`
except SyntaxError:
exec cmd in self.namespace
except:
if hasattr(sys, 'last_type') and \
sys.last_type == SystemExit:
self.quit()
else:
traceback.print_exc()
self.prompt.set_text(sys.ps1)
self.prompt.queue_draw()
adj = self.text.get_vadjustment()
adj.set_value(adj.upper - adj.page_size)
sys.stdout, self.stdout = self.stdout, sys.stdout
sys.stderr, self.stderr = self.stderr, sys.stderr
def gtk_console(ns, title='Python', copyright='', menu=None):
win = GtkWindow()
win.set_usize(475, 300)
win.connect("destroy", mainquit)
win.connect("delete_event", mainquit)
win.set_title(title)
cons = Console(namespace=ns, copyright=copyright, quit_cb=mainquit)
if menu:
box = GtkVBox()
win.add(box)
box.show()
box.pack_start(menu, expand=FALSE)
menu.show()
box.pack_start(cons)
else:
win.add(cons)
cons.show()
win.show()
win.set_usize(0,0)
cons.init()
mainloop()
if __name__ == '__main__':
gtk_console({'__builtins__': __builtins__, '__name__': '__main__',
'__doc__': None})

View File

@ -0,0 +1,307 @@
#!/usr/bin/python
# Gimp-Python - allows the writing of Gimp plugins in Python.
# Copyright (C) 1997 James Henstridge <james@daa.com.au>
#
# 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 2 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, write to the Free Software
# Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
from gimpfu import *
import gimpenums
import gtk
import string
pars = filter(lambda x: x[:6] == 'PARAM_', dir(gimpenums))
partypes = [''] * len(pars)
for i in pars:
partypes[gimpenums.__dict__[i]] = i[6:]
del pars, i
class BrowseWin(gtk.GtkWindow):
def __init__(self, ok_button=None):
gtk.GtkWindow.__init__(self)
self.set_title("PDB Browser")
vbox = gtk.GtkVBox(FALSE, 5)
vbox.set_border_width(2)
self.add(vbox)
vbox.show()
paned = gtk.GtkHPaned()
vbox.pack_start(paned)
paned.show()
listsw = gtk.GtkScrolledWindow()
listsw.set_policy(gtk.POLICY_AUTOMATIC, gtk.POLICY_AUTOMATIC)
paned.add1(listsw)
listsw.show()
self.list = gtk.GtkCList(1)
self.list.set_column_auto_resize(0, TRUE)
self.list.set_selection_mode(gtk.SELECTION_BROWSE)
listsw.add(self.list)
self.list.show()
self.update_list()
self.list.connect("select_row", self.display)
self.infosw = gtk.GtkScrolledWindow()
self.infosw.set_policy(gtk.POLICY_AUTOMATIC,
gtk.POLICY_AUTOMATIC)
paned.add2(self.infosw)
self.infosw.show()
self.info = None
paned.set_position(150)
self.cmd = None
self.display(self.list, 0, -1, None)
hbox = gtk.GtkHBox(FALSE, 5)
vbox.pack_start(hbox, expand=FALSE)
hbox.show()
entry = gtk.GtkEntry()
hbox.pack_start(entry, expand=FALSE)
entry.show()
button = gtk.GtkButton("Search by Name")
button.connect("clicked", self.search_name, entry)
hbox.pack_start(button, expand=FALSE)
button.show()
button = gtk.GtkButton("Search by Blurb")
button.connect("clicked", self.search_blurb, entry)
hbox.pack_start(button, expand=FALSE)
button.show()
button = gtk.GtkButton("Close")
button.connect("clicked", self.destroy)
hbox.pack_end(button, expand=FALSE)
button.show()
if ok_button:
button = gtk.GtkButton("OK")
button.connect("clicked", ok_button, self)
hbox.pack_end(button, expand=FALSE)
button.show()
self.set_default_size(500, 300)
def search_name(self, button, entry):
self.update_list(name=entry.get_text())
def search_blurb(self, button, entry):
self.update_list(blurb=entry.get_text())
def update_list(self, name='.*', blurb='.*'):
self.pdblist = pdb.query(name,blurb,'.*','.*','.*','.*','.*')
self.pdblist.sort()
self.list.clear()
for item in self.pdblist:
self.list.append([item])
def display(self, clist, row, column, event):
proc = pdb[clist.get_text(row, 0)]
self.info = gtk.GtkTable(1, 5, FALSE);
row = 0
label = gtk.GtkLabel("Name:")
label.set_alignment(1.0, 0.5)
self.info.attach(label, 0,1, row,row+1,
xoptions=gtk.FILL, yoptions=gtk.FILL)
label.show()
label = gtk.GtkEntry()
label.set_text(proc.proc_name)
label.set_editable(FALSE)
self.info.attach(label, 1,4, row,row+1,
xoptions=gtk.FILL, yoptions=gtk.FILL)
label.show()
row = row + 1
label = gtk.GtkLabel("Blurb:")
label.set_alignment(1.0, 0.5)
self.info.attach(label, 0,1, row,row+1,
xoptions=gtk.FILL, yoptions=gtk.FILL)
label.show()
label = gtk.GtkLabel(proc.proc_blurb)
label.set_alignment(0.0, 0.5)
self.info.attach(label, 1,4, row,row+1,
yoptions=gtk.FILL)
label.show()
row = row + 1
label = gtk.GtkLabel("Copyright:")
label.set_alignment(1.0, 0.5)
self.info.attach(label, 0,1, row,row+1,
xoptions=gtk.FILL, yoptions=gtk.FILL)
label.show()
label = gtk.GtkLabel(proc.proc_date+", "+proc.proc_copyright)
label.set_alignment(0.0, 0.5)
self.info.attach(label, 1,4, row,row+1,
yoptions=gtk.FILL)
label.show()
row = row + 1
label = gtk.GtkLabel("Author:")
label.set_alignment(1.0, 0.5)
self.info.attach(label, 0,1, row,row+1,
xoptions=gtk.FILL, yoptions=gtk.FILL)
label.show()
label = gtk.GtkLabel(proc.proc_author)
label.set_alignment(0.0, 0.5)
self.info.attach(label, 1,4, row,row+1,
yoptions=gtk.FILL)
label.show()
row = row + 1
hsep = gtk.GtkHSeparator()
self.info.attach(hsep, 0,4, row,row+1,
yoptions=gtk.FILL)
hsep.show()
row = row + 1
if len(proc.params) > 0:
label = gtk.GtkLabel("In:")
label.set_alignment(1.0, 0.5)
self.info.attach(label, 0,1, row,row+len(proc.params),
xoptions=gtk.FILL, yoptions=gtk.FILL)
label.show()
for tp, name, desc in proc.params:
label = gtk.GtkLabel(name)
label.set_alignment(0.0, 0.5)
self.info.attach(label, 1,2, row,row+1,
xoptions=gtk.FILL,
yoptions=gtk.FILL)
label.show()
label = gtk.GtkLabel(partypes[tp])
label.set_alignment(0.0, 0.5)
self.info.attach(label, 2,3, row,row+1,
xoptions=gtk.FILL,
yoptions=gtk.FILL)
label.show()
label = gtk.GtkLabel(desc)
label.set_alignment(0.0, 0.5)
self.info.attach(label, 3,4, row,row+1,
yoptions=gtk.FILL)
label.show()
row = row + 1
hsep = gtk.GtkHSeparator()
self.info.attach(hsep, 0,4, row,row+1,
yoptions=gtk.FILL)
hsep.show()
row = row + 1
if len(proc.return_vals) > 0:
label = gtk.GtkLabel("Out:")
label.set_alignment(1.0, 0.5)
self.info.attach(label, 0,1,
row,row+len(proc.return_vals),
xoptions=gtk.FILL, yoptions=gtk.FILL)
label.show()
for tp, name, desc in proc.return_vals:
label = gtk.GtkLabel(name)
label.set_alignment(0.0, 0.5)
self.info.attach(label, 1,2, row,row+1,
xoptions=gtk.FILL,
yoptions=gtk.FILL)
label.show()
label = gtk.GtkLabel(partypes[tp])
label.set_alignment(0.0, 0.5)
self.info.attach(label, 2,3, row,row+1,
xoptions=gtk.FILL,
yoptions=gtk.FILL)
label.show()
label = gtk.GtkLabel(desc)
label.set_alignment(0.0, 0.5)
self.info.attach(label, 3,4, row,row+1,
yoptions=gtk.FILL)
label.show()
row = row + 1
hsep = gtk.GtkHSeparator()
self.info.attach(hsep, 0,4, row,row+1,
yoptions=gtk.FILL)
hsep.show()
row = row + 1
label = gtk.GtkLabel("Help:")
label.set_alignment(1.0, 0.5)
self.info.attach(label, 0,1, row,row+1,
xoptions=gtk.FILL, yoptions=gtk.FILL)
label.show()
label = gtk.GtkLabel(proc.proc_help)
label.set_alignment(0.0, 0.5)
label.set_justify(gtk.JUSTIFY_LEFT)
label.set_line_wrap(TRUE)
label.set_usize(300, -1)
self.info.attach(label, 1,4, row,row+1,
yoptions=gtk.FILL)
label.show()
row = row + 1
self.info.set_col_spacings(5)
self.info.set_row_spacings(3)
self.info.set_border_width(3)
children = self.infosw.children()
if children:
self.infosw.remove(children[0])
self.infosw.add_with_viewport(self.info)
self.info.show()
# now setup the self.cmd
self.cmd = ''
if len(proc.return_vals) > 0:
self.cmd = string.join(
map(lambda x: x[1], proc.return_vals), ', ') +\
' = '
if '-' in proc.proc_name:
self.cmd = self.cmd + "pdb['" + proc.proc_name + "']"
else:
self.cmd = self.cmd + "pdb." + proc.proc_name
if len(proc.params) > 0 and proc.params[0][1] == 'run_mode':
params = proc.params[1:]
else:
params = proc.params
self.cmd = self.cmd + "(" + string.join(
map(lambda x: x[1], params), ', ') + ")"
if __name__ == '__main__':
def extension_pdb_browse():
gtk.rc_parse(gimp.gtkrc())
win = BrowseWin()
win.connect("destroy", gtk.mainquit)
win.show()
gtk.mainloop()
register(
"python_fu_pdb_browse",
"Browse the Procedural Database",
"Pick a PDB proc, and read the information",
"James Henstridge",
"James Henstridge",
"1997-1999",
"<Toolbox>/Xtns/Python-Fu/PDB Browser",
"*",
[],
[],
extension_pdb_browse)
main()

View File

@ -0,0 +1,68 @@
#!/usr/bin/env python
from gimpfu import *
have_gimp11 = gimp.major_version > 1 or gimp.major_version == 1 and \
gimp.minor_version >= 1
def shadow_bevel(img, drawable, blur, bevel, do_shadow, drop_x, drop_y):
# disable undo for the image
img.disable_undo()
# copy the layer
shadow = drawable.copy(TRUE)
img.add_layer(shadow, img.layers.index(drawable)+1)
shadow.name = drawable.name + " shadow"
shadow.preserve_transparency = FALSE
# threshold the shadow layer to all white
if have_gimp11:
pdb.gimp_threshold(shadow, 0, 255)
else:
pdb.gimp_threshold(img, shadow, 0, 255)
# blur the shadow layer
pdb.plug_in_gauss_iir(img, shadow, blur, TRUE, TRUE)
# do the bevel thing ...
if bevel:
pdb.plug_in_bump_map(img, drawable, shadow, 135, 45, 3,
0, 0, 0, 0, TRUE, FALSE, 0)
# make the shadow layer black now ...
if have_gimp11:
pdb.gimp_invert(shadow)
else:
pdb.gimp_invert(img, shadow)
# translate the drop shadow
shadow.translate(drop_x, drop_y)
if not do_shadow:
# delete shadow ...
gimp.delete(shadow)
# enable undo again
img.enable_undo()
register(
"shadow_bevel",
"Add a drop shadow to a layer, and optionally bevel it.",
"Add a drop shadow to a layer, and optionally bevel it.",
"James Henstridge",
"James Henstridge",
"1999",
"<Image>/Python-Fu/Effects/Drop Shadow and Bevel",
"RGBA, GRAYA",
[
(PF_SLIDER, "blur", "Shadow Blur", 6, (1, 30, 1)),
(PF_BOOL, "bevel", "Bevel the image", TRUE),
(PF_BOOL, "shadow", "Make a drop shadow", TRUE),
(PF_INT, "drop_x", "Drop shadow X displacement", 3),
(PF_INT, "drop_y", "Drop shadow Y displacement", 6)
],
[],
shadow_bevel)
main()

View File

@ -0,0 +1,103 @@
#!/usr/bin/python
# Gimp-Python - allows the writing of Gimp plugins in Python.
# Copyright (C) 1997 James Henstridge <james@daa.com.au>
#
# 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 2 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, write to the Free Software
# Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
import math
from gimpfu import *
have_gimp11 = gimp.major_version > 1 or \
gimp.major_version == 1 and gimp.minor_version >= 1
def python_sphere(radius, light, shadow, bg_colour, sphere_colour):
width = radius * 3.75
height = radius * 2.5;
img = gimp.image(width, height, RGB)
drawable = gimp.layer(img, "Sphere Layer", width, height,
RGB_IMAGE, 100, NORMAL_MODE)
radians = light * math.pi / 180
cx = width / 2
cy = height / 2
light_x = cx + radius * 0.6 * math.cos(radians)
light_y = cy - radius * 0.6 * math.sin(radians)
light_end_x = cx + radius * math.cos(math.pi + radians)
light_end_y = cy - radius * math.sin(math.pi + radians)
offset = radius * 0.1
old_fg = gimp.get_foreground()
old_bg = gimp.get_background()
img.disable_undo()
img.add_layer(drawable, 0)
gimp.set_foreground(sphere_colour)
gimp.set_background(bg_colour)
if have_gimp11:
pdb.gimp_edit_fill(drawable)
else:
pdb.gimp_edit_fill(img, drawable)
gimp.set_background(20, 20, 20)
if (light >= 45 and light <= 75 or light <= 135 and
light >= 105) and shadow:
shadow_w = radius * 2.5 * math.cos(math.pi + radians)
shadow_h = radius * 0.5
shadow_x = cx
shadow_y = cy + radius * 0.65
if shadow_w < 0:
shadow_x = cx + shadow_w
shadow_w = -shadow_w
pdb.gimp_ellipse_select(img, shadow_x, shadow_y,
shadow_w, shadow_h, REPLACE, 1, 1, 7.5)
if have_gimp11:
pdb.gimp_bucket_fill(drawable, BG_BUCKET_FILL,
MULTIPLY_MODE, 100, 0, 0, 0, 0)
else:
pdb.gimp_bucket_fill(img, drawable, BG_BUCKET_FILL,
MULTIPLY_MODE, 100, 0, 0, 0, 0)
pdb.gimp_ellipse_select(img, cx - radius, cy - radius,
2 * radius, 2 * radius, REPLACE, 1, 0, 0)
if have_gimp11:
pdb.gimp_blend(drawable, FG_BG_RGB, NORMAL_MODE, RADIAL,
100, offset, REPEAT_NONE, 0, 0, 0, light_x,
light_y, light_end_x, light_end_y)
else:
pdb.gimp_blend(img, drawable, FG_BG_RGB, NORMAL_MODE, RADIAL,
100, offset, REPEAT_NONE, 0, 0, 0, light_x,
light_y, light_end_x, light_end_y)
pdb.gimp_selection_none(img)
gimp.set_background(old_bg)
gimp.set_foreground(old_fg)
img.enable_undo()
disp = gimp.display(img)
register(
"python_fu_sphere",
"Simple spheres with drop shadows",
"Simple spheres with drop shadows (based on script-fu version)",
"James Henstridge",
"James Henstridge",
"1997-1999",
"<Toolbox>/Xtns/Python-Fu/Misc/Sphere",
"RGB*, GRAY*, INDEXED*",
[
(PF_INT, "radius", "Radius for sphere", 100),
(PF_SLIDER, "light", "light angle", 45, (0,360,1)),
(PF_TOGGLE, "shadow", "shadow?", 1),
(PF_COLOR, "bg_colour", "background", (255,255,255)),
(PF_COLOR, "sphere_colour", "sphere", (255,0,0))
],
[],
python_sphere)
main()

View File

@ -0,0 +1,217 @@
#!/usr/bin/env python
# Gimp-Python - allows the writing of Gimp plugins in Python.
# Copyright (C) 1997 James Henstridge <james@daa.com.au>
#
# 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 2 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, write to the Free Software
# Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
# Algorithms stolen from the whirl and pinch plugin distributed with Gimp,
# by Federico Mena Quintero and Scott Goehring
#
# This version does the same thing, except there is no preview, and it is
# written in python and is slower.
import math, struct
from gimpfu import *
class pixel_fetcher:
def __init__(self, drawable):
self.col = -1
self.row = -1
self.img_width = drawable.width
self.img_height = drawable.height
self.img_bpp = drawable.bpp
self.img_has_alpha = drawable.has_alpha
self.tile_width = 64
self.tile_height = 64
self.bg_colour = '\0\0\0\0'
self.bounds = drawable.mask_bounds
self.drawable = drawable
self.tile = None
def set_bg_colour(self, r, g, b, a):
self.bg_colour = struct.pack('bbb', r,g,b)
if self.img_has_alpha:
self.bg_colour = self.bg_colour + chr(a)
def get_pixel(self, x, y):
sel_x1, sel_y1, sel_x2, sel_y2 = self.bounds
if x < sel_x1 or x >= sel_x2 or y < sel_y1 or y >= sel_y2:
return self.bg_colour
col = x / self.tile_width
coloff = x % self.tile_width
row = y / self.tile_height
rowoff = y % self.tile_height
if col != self.col or row != self.row or self.tile == None:
self.tile = self.drawable.get_tile(FALSE, row, col)
self.col = col
self.row = row
return self.tile[coloff, rowoff]
class Dummy:
pass
def python_whirl_pinch(image, drawable, whirl, pinch, radius):
self = Dummy()
self.width = drawable.width
self.height = drawable.height
self.bpp = drawable.bpp
self.has_alpha = drawable.has_alpha
self.bounds = drawable.mask_bounds
self.sel_x1, self.sel_y1, self.sel_x2, self.sel_y2 = \
drawable.mask_bounds
self.sel_w = self.sel_x2 - self.sel_x1
self.sel_h = self.sel_y2 - self.sel_y1
self.cen_x = (self.sel_x1 + self.sel_x2 - 1) / 2.0
self.cen_y = (self.sel_y1 + self.sel_y2 - 1) / 2.0
xhsiz = (self.sel_w - 1) / 2.0
yhsiz = (self.sel_h - 1) / 2.0
if xhsiz < yhsiz:
self.scale_x = yhsiz / xhsiz
self.scale_y = 1.0
elif xhsiz > yhsiz:
self.scale_x = 1.0
self.scale_y = xhsiz / yhsiz
else:
self.scale_x = 1.0
self.scale_y = 1.0
self.radius = max(xhsiz, yhsiz);
if not drawable.is_colour and not drawable.is_grey:
return
gimp.tile_cache_ntiles(2 * (self.width + 63) / 64)
whirl = whirl * math.pi / 180
dest_rgn = drawable.get_pixel_rgn(self.sel_x1, self.sel_y1,
self.sel_w, self.sel_h, TRUE, TRUE)
pft = pixel_fetcher(drawable)
pfb = pixel_fetcher(drawable)
bg_colour = gimp.get_background()
pft.set_bg_colour(bg_colour[0], bg_colour[1], bg_colour[2], 0)
pfb.set_bg_colour(bg_colour[0], bg_colour[1], bg_colour[2], 0)
progress = 0
max_progress = self.sel_w * self.sel_h
gimp.progress_init("Whirling and pinching...")
self.radius2 = self.radius * self.radius * radius
pixel = ['', '', '', '']
values = [0,0,0,0]
for row in range(self.sel_y1, (self.sel_y1+self.sel_y2)/2+1):
top_p = ''
bot_p = ''
for col in range(self.sel_x1, self.sel_x2):
q, cx, cy = calc_undistorted_coords(self, col,
row, whirl, pinch, radius)
if q:
if cx >= 0: ix = int(cx)
else: ix = -(int(-cx) + 1)
if cy >= 0: iy = int(cy)
else: iy = -(int(-cx) + 1)
pixel[0] = pft.get_pixel(ix, iy)
pixel[1] = pft.get_pixel(ix+1, iy)
pixel[2] = pft.get_pixel(ix, iy+1)
pixel[3] = pft.get_pixel(ix+1, iy+1)
for i in range(self.bpp):
values[0] = ord(pixel[0][i])
values[1] = ord(pixel[1][i])
values[2] = ord(pixel[2][i])
values[3] = ord(pixel[3][i])
top_p = top_p + bilinear(cx,cy, values)
cx = self.cen_x + (self.cen_x - cx)
cy = self.cen_y + (self.cen_y - cy)
if cx >= 0: ix = int(cx)
else: ix = -(int(-cx) + 1)
if cy >= 0: iy = int(cy)
else: iy = -(int(-cy) + 1)
pixel[0] = pfb.get_pixel(ix, iy)
pixel[1] = pfb.get_pixel(ix+1, iy)
pixel[2] = pfb.get_pixel(ix, iy+1)
pixel[3] = pfb.get_pixel(ix+1, iy+1)
tmp = ''
for i in range(self.bpp):
values[0] = ord(pixel[0][i])
values[1] = ord(pixel[1][i])
values[2] = ord(pixel[2][i])
values[3] = ord(pixel[3][i])
tmp = tmp + bilinear(cx,cy, values)
bot_p = tmp + bot_p
else:
top_p = top_p + pft.get_pixel(col, row)
bot_p = pfb.get_pixel((self.sel_x2 - 1) -
(col - self.sel_x1), (self.sel_y2-1) -
(row - self.sel_y1)) + bot_p
dest_rgn[self.sel_x1:self.sel_x2, row] = top_p
dest_rgn[self.sel_x1:self.sel_x2, (self.sel_y2 - 1)
- (row - self.sel_y1)] = bot_p
progress = progress + self.sel_w * 2
gimp.progress_update(float(progress) / max_progress)
drawable.flush()
drawable.merge_shadow(TRUE)
drawable.update(self.sel_x1,self.sel_y1,self.sel_w,self.sel_h)
def calc_undistorted_coords(self, wx, wy, whirl, pinch, radius):
dx = (wx - self.cen_x) * self.scale_x
dy = (wy - self.cen_y) * self.scale_y
d = dx * dx + dy * dy
inside = d < self.radius2
if inside:
dist = math.sqrt(d / radius) / self.radius
if (d == 0.0):
factor = 1.0
else:
factor = math.pow(math.sin(math.pi / 2 * dist),
-pinch)
dx = dx * factor
dy = dy * factor
factor = 1 - dist
ang = whirl * factor * factor
sina = math.sin(ang)
cosa = math.cos(ang)
x = (cosa * dx - sina * dy) / self.scale_x + self.cen_x
y = (sina * dx + cosa * dy) / self.scale_y + self.cen_y
else:
x = wx
y = wy
return inside, float(x), float(y)
def bilinear(x, y, values):
x = x % 1.0
y = y % 1.0
m0 = values[0] + x * (values[1] - values[0])
m1 = values[2] + x * (values[3] - values[2])
return chr(m0 + y * (m1 - m0))
register(
"python_fu_whirl_pinch",
"Distorts an image by whirling and pinching",
"Distorts an image by whirling and pinching",
"James Henstridge (translated from C plugin)",
"James Henstridge",
"1997-1999",
"<Image>/Python-Fu/Distorts/Whirl and Pinch",
"RGB*, GRAY*",
[
(PF_SLIDER, "whirl", "Whirl angle", 90, (-360, 360, 1)),
(PF_FLOAT, "pinch", "Pinch amount", 0),
(PF_FLOAT, "radius", "radius", 1)
],
[],
python_whirl_pinch)
main()

68
plug-ins/pygimp/py-compile Executable file
View File

@ -0,0 +1,68 @@
#!/bin/sh
# called as "py-compile [--basedir DIR] PY_FILES ...
if [ -z "$PYTHON" ]; then
PYTHON=python
fi
basedir=
case "$1" in
--basedir)
basedir=$2
shift 2
;;
--help)
echo "Usage: py-compile [--basedir DIR] PY_FILES ..."
echo "Byte compile some python scripts. This should be performed"
echo "after they have been moved to the final installation location"
exit 0
;;
--version)
echo "py-compile version 0.0"
exit 0
;;
esac
if [ $# = 0 ]; then
echo "No files given to $0" 1>&2
exit 1
fi
# if basedir was given, then it should be prepended to filenames before
# byte compilation.
if [ -z "$basedir" ]; then
trans="path = file"
else
trans="path = os.path.join('$basedir', file)"
fi
$PYTHON -c "
import sys, os, string, py_compile
files = '''$*'''
print 'Byte-compiling python modules...'
for file in string.split(files):
$trans
if not os.path.exists(path) or not (len(path) >= 3 and path[-3:] == '.py'):
continue
print file,
sys.stdout.flush()
py_compile.compile(path)
print" || exit $?
# this will fail for python < 1.5, but that doesn't matter ...
$PYTHON -O -c "
import sys, os, string, py_compile
files = '''$*'''
print 'Byte-compiling python modules (optimised versions) ...'
for file in string.split(files):
$trans
if not os.path.exists(path) or not (len(path) >= 3 and path[-3:] == '.py'):
continue
print file,
sys.stdout.flush()
py_compile.compile(path)
print" 2>/dev/null || :

View File

@ -0,0 +1,50 @@
%define ver 0.3
%define prefix /usr
%define py_ver 1.5
%define gimp_ver 1.0
Name: pygimp
Version: %ver
Release: 1
Summary: A python extension allowing you to write Gimp plugins in Python
Copyright: GPL
Group: X11/Applications/Graphics
Packager: James Henstridge <james@daa.com.au>
Requires: gimp python
Source: ftp://ftp.daa.com.au/pub/james/pygimp/pygimp-%{ver}.tar.gz
BuildRoot: /tmp/pygimp-root
%description
pygimp allows you to write Gimp plugins with the python language. Unlike
script-fu scripts which only have access to functions in the PDB (procedural
database), pygimp plugins have access to all functionality that C plugins
have, including direct pixel manipulation that is required for many plugins.
%prep
%setup
CFLAGS="$RPM_OPT_FLAGS" ./configure --prefix=%{prefix}
%build
make
%install
rm -rf $RPM_BUILD_ROOT
make DESTDIR=$RPM_BUILD_ROOT install
%files
%{prefix}/lib/python%{py_ver}/site-packages/gimpmodule.so
%{prefix}/lib/python%{py_ver}/site-packages/gimpenums.py*
%{prefix}/lib/python%{py_ver}/site-packages/plugin.py*
%{prefix}/lib/python%{py_ver}/site-packages/gimpshelf.py*
%{prefix}/lib/python%{py_ver}/site-packages/getvals.py*
%{prefix}/lib/gimp/%{gimp_ver}/plug-ins/clothify.py
%{prefix}/lib/gimp/%{gimp_ver}/plug-ins/tkcons.py
%{prefix}/lib/gimp/%{gimp_ver}/plug-ins/gimpcons.py
%{prefix}/lib/gimp/%{gimp_ver}/plug-ins/pdbbrowse.py
%{prefix}/lib/gimp/%{gimp_ver}/plug-ins/sphere.py
%{prefix}/lib/gimp/%{gimp_ver}/plug-ins/whirlpinch.py
%doc README NEWS COPYING doc/*.html