\documentclass{article}

\setlength{\oddsidemargin}{0in}
\setlength{\evensidemargin}{0in}
\setlength{\headsep}{0pt}
\setlength{\topmargin}{0in}
\setlength{\textheight}{8.75in}
\setlength{\textwidth}{6.5in}
\setlength{\parindent}{0in}
\setlength{\parskip}{2ex}

\usepackage{tabularx}
\usepackage{multicol}
\usepackage{epsf}
\usepackage{amstex}
\usepackage{array}
\usepackage{xspace}
\usepackage{float}

\newcommand{\figref}[1]{{\em Figure ~\ref{#1}}\xspace}
\renewcommand{\labelenumi}{\theenumi.}

\floatstyle{ruled}
\newfloat{code}{h}{loc}
\floatname{code}{Example Code}

\newcommand{\myfigone}[3]{
	\def\@captype{figure}
	\begin{table}
	\bigskip
        \begin{center}
	\leavevmode
	\epsfysize=#2 \epsfbox{#1.eps}
	\caption{#3} \label{#1}
	\end{center}
	\end{table}}

\newcommand{\myfigtwo}[3]{
	\def\@captype{figure}
	\begin{table*}
	\bigskip
        \begin{center}
	\leavevmode
	\epsfysize=#2 \epsfbox{#1.eps}
	\caption{#3} \label{#1}
	\end{center}
	\end{table*}}

\begin{document}

\twocolumn

\begin{titlepage}
\title{{\bf Script-Fu: Graphic Art for Everyone}}
\author{Spencer Kimball\\
eXperimental Computing Facility\\
University of California at Berkeley\\
spencer@@xcf.berkeley.edu}
\maketitle

\thispagestyle{empty}
\begin{abstract}
With the advent of the World Wide Web (WWW), individuals
have an unprecedented ability to disseminate information at little or
no cost.  Because of its accessibility, the flow of information on the
WWW is staggering, and appears to be sustaining its incredible rate of
growth.  With so much competing information, presentation becomes
as--or even more--important than content; visually appealing web pages
are likely to attract the most attention.  {\bf Script-Fu} is a newly
developed application which automatically creates the graphics
necessary to present information compellingly.  Script-Fu is designed
to maximize power and flexibility and it accomplishes this goal using
a three-component architecture.  This architecture is composed of an
image manipulation engine (for the computations necessary to create
graphics), a scripting language (for precisely describing the
algorithms required to create the graphics), and a
facilitator/management program (for user-interface and communication
between the components).  This choice of components maximizes the
power of Script-Fu, but in some cases lessens the accessibility.  For
example, the image manipulation engine, GIMP, runs only on UNIX
workstations, not on Macintoshes or PCs.  A fourth component, Net-Fu,
solves this dilemma by providing an alternate interface to Script-Fu,
making its functionality available to anyone who has access to a WWW
browser application such as {\it Netscape} or {\it Microsoft Internet
Explorer}.  Using both Script-Fu and the WWW, virtually anyone can
present information compellingly, and at low cost.
\end{abstract}

\end{titlepage}

\section{Introduction}

Company logos, product names, and eye-catching slogans are as
ubiquitous as they are necessary for successful marketing.
Traditionally, this sort of graphic design work lay squarely in the
realm of the professional artist.  A company which required art for
magazine ads, CD or record labels, book covers, posters, or product
brochures would contract the services of a graphic design firm.
Individuals not associated with large companies had little use for
such artwork, because both the cost of advertising and the cost of
graphic design were prohibitive.

Things have changed.  The cost of advertising has gone through the
floor, while the cost of graphic design remains high.  Individuals now
have the ability to advertise products, ideas, and opinions, but lack
the means to present them in a compelling fashion.  {\bf Script-Fu}, a
piece of computer software developed to address this situation, makes
high-quality graphic design an option available to everyone.

The advent of the World Wide Web (WWW) is rapidly changing the face of
the world's information infrastructure.  The WWW is a conglomeration
of distinct ``web sites'' linked together by what are known as
``hyperlinks''.  It is built on the ``internet'', a global
communications network for computer-based communications.  If the WWW
were compared to a railway system, web sites would correspond to train
stations, and hyperlinks to tracks.  Web sites contain publicly
available information including text, images, animations, and sound.
Users travel from web site to web site to find information of
interest, using a program known as a ``browser'' ({\it Netscape} and
{\it Microsoft Internet Expolorer} are examples of widely available
browsers).  The browser, then, is like a train that carries the user
from one depot of information to the next, following hyperlinks
between web sites.

What makes the WWW so revolutionary is the cost at which it allows
individuals to disseminate information.  Because of the distributed
architecture of the internet\footnote{The internet was originally
intended as a network to inter-connect research facilities and
universities. It was designed so that each participant would have to
contribute to the overall operation.  For example, a computer on the
internet in Michigan might help forward information from Berkeley to
MIT.} and the low cost of personal computers, anyone can establish a
presence on the World Wide Web for under \$10,000.  On the WWW,
individuals have as much right and recourse to advertising as large
corporations.  In this context, ``advertise'' has a wide range of
meanings--from actual product marketing to information exchange and
the publication of ideas and opinions.

As recently as 1985, the internet consisted of roughly 50 sites.
Today, the count is higher than 100,000, and is rapidly increasing.
In fact, the naming conventions which assign each site on the internet
a unique, identifying name, have to be changed to account for the
unexpected magnitude of expansion \cite{ipv6}.

This expansion of the internet is blamed by most on the staggering
growth of the world wide web, as universities, companies,
organizations, and individuals race to take advantage of this nascent
means of mass-communication.  In the confusion of this mad scramble,
attention spans for web-surfers (users who access the information on
the WWW) have reached all time lows.  Like more traditional forms of
mass-media--radio and TV, for example--the format and appeal of
packaging is becoming as important or more important than the actual
content.  Imagine a TV with literally millions of channels available
and an efficient interface for searching them for items of interest.
The importance of high quality, eye-catching presentations assumes an
unprecedented magnitude in this context.  It would be a rare
web-surfer indeed, who would bother with a web page that contained no
concessions to visual or auditory stimulation.

\myfigtwo{timeline}{6cm}{There is an emerging need for graphic art
solutions that support the needs of individuals, who can't afford
professional graphic designers.}

While the cost of advertising has plummeted with the World Wide Web,
the cost of graphic design has not decreased.  If anything, the
extreme demand generated by the WWW has pushed the price of graphic
design through the roof in the short-term; prices will remain high
until the graphic design industry can grow large enough to satisfy
current and future demand.

The World Wide Web is here to stay.  Its growth continues at an almost
impossible rate and the exploration of its benefits is just beginning.
The WWW will certainly be here for the next five years, and what the
future holds is undoubtedly even more surprising than the recent
advances in information exchange.  Through it all, the requirement
that information be presented compellingly is unlikely to change, as
human nature seems constant in that regard.  Script-Fu targets the
problem of information packaging and is therefore well-suited to the
needs of both the present and the immediate future.

\section{Requirements}

What is ``high-quality graphic art''?  This term needs to be defined
before an application purported to automatically generate graphic art
is described.  Where Script-Fu is concerned, the definition is limited
to the current standard for {\it logos} typically found on
professionally designed web pages\footnote {The term should, in fact,
describe the overall composition of graphics, text and background
which make up a web page.}.  Logos should have the option to be
generated from a wide range of typefaces, sizes, colors, backgrounds,
and styles, including such exotic motifs as neon, chrome, crystal, and
carved marble or wood.  The task that Script-Fu tackles is simply put:
to generate logos in a wide variety of styles with configurable
options, at a level of quality comparable to professionally done
graphic design work.  Additionally, the graphic art should be
generated automatically, and in tens of seconds, where traditional
artists painstakingly produce artwork on a timescale of hours.
\figref{logo} is a \emph{very} simple example of a logo which
Script-Fu might generate\footnote {We will discuss the creation of
this logo in detail throughout the following sections.  For an actual
Script-Fu {\it scheme} script that generates similar logos, refer to
Appendix A.  {\bf Warning:} Unless you are familiar with both
programming languages and typical {\it Photoshop}\cite{photoshop}/{\it
GIMP}\cite{GIMP} usage, the code listed in the appendix will be
confusing.}.

Many factors must be considered in the design of an application which
meets the requirements discussed above.  Most important are
flexibility and power.  To meet the requirement that it generate
``high-quality'' graphic art, Script-Fu must be flexible and easy to
expand upon; new and more impressive logo designs are constantly
evolving and must be incorporated into the system as they emerge.
Script-Fu must also be extremely powerful, as impressive logos
typically involve a complex process which--in the case of automated
logo creation--requires that software make decisions that were
formerly made by human artists.  Sections 3 and 4 in this paper
discuss the architecture necessary to achieve these goals, as well as
how the components of the architecture interact to get the job done.

One factor which is easily overlooked, but of utmost importance, is
the user-interface.  Script-Fu has a traditional user interface in the
sense that when you run the software on a computer, it displays a
window with the necessary options for logo generation.  However, to
maximize the availability and appeal of Script-Fu, a secondary
interface called {\bf Net-Fu} was designed.  Section 5 discusses this
additional interface in detail.

\myfigone{logo}{6cm}{A simple example of a composited logo.  The logo
consists of highlights, the logo text, and shadows.}

\section{Architecture}

The architecture of Script-Fu is carefully designed with the goals of
flexibility and power in mind.  The architecture consists of three
primary components and is illustrated in \figref{architecture}:
\begin{itemize}
\item An underlying image manipulation engine for computing each step
of the logo generation process.
\item A mechanism for automating the logo creation process.
\item An intermediary which oversees the progress of the other two
components and facilities communication between them.
\end{itemize}

\subsection{GIMP--Image Manipulation Engine}

In theory, Script-Fu could include all of the necessary image
manipulation operations for creating logos.  However, this would
involve hundreds of thousands of lines of program code and immense
amounts of development time.  Instead, the architecture calls for the
leveraging of an existing image manipulation ``engine''--in the
context of our simple logo example (\figref{logo}), this is a piece of
software that actually performs the computations necessary to create
highlights, text, and shadows and then combine them into a final logo.

\myfigone{architecture}{6cm}{Script-Fu and GIMP are stand-alone
executables running on one machine, communicating with each other.}

Professional graphic design artists have long used Photoshop
\cite{photoshop}, a software package from Adobe for their image
manipulation needs.  Photoshop is a complicated, powerful, and
highly-respected piece of software that is employed in nearly all
computer-based image manipulation tasks (such as photo-retouching,
graphic art design, and image composition).  Photoshop was not chosen
for use with Script-Fu.  There are a number of reasons for this
decision.  Among them are the price point of Photoshop--around \$500,
the lack of support for UNIX platforms--which are better suited to
batch processing, and most importantly, the lack of a facility for
supporting complex, automated control.  In plain English, Photoshop
does not have the necessary means through which other applications can
direct its actions.

Instead, Script-Fu was implemented using an image manipulation engine
known as the GNU Image Manipulation Program (GIMP) \cite{GIMP}.  GIMP
is free software (meaning both its source code, and the runnable
application can be downloaded and used free of
charge)\footnote{ftp://ftp.xcf.berkeley.edu/pub/gimp}, making it
possible to offer Script-Fu without a restrictive usage policy or the
requirement of commercial software.  GIMP runs on nearly all UNIX
platforms, the ideal setting for large batch processing operations.
Finally, GIMP has a facility for supporting extensions, which are
perfectly suited to the needs of Script-Fu.  A GIMP extension is a
stand-alone program that extends the functionality of the main
application.  The extension and GIMP communicate with each other, and
through this line of communication, the extension can command GIMP to
execute any operation\footnote{See appendix B for a discussion of
extensions and how they interact with GIMP}.

\subsection{Scheme--Scripting Language}

There are two primary mechanisms typically employed for automated
processing of the type used in Script-Fu: batch processing and
scripting.  Batch processing is used primarily for automating only the
most simplistic procedures--tasks in which nothing changes from one
invocation to the next, and no decisions need to be made based on
variable input values.  This is not a suitable solution for Script-Fu.
Based on the name {\bf Script}-Fu, it should be obvious that scripting
is the solution of choice.

Scripting allows far more flexibility than batch processing because it
often incorporates an actual programming language.  A programming
language is a means to specify an algorithm (a list of steps for the
computer to complete) with complex, language-like control structures.
For example, decisions can be made by evaluating whether a given
condition is true and executing one command if it is, and another
command if it is not.  Here is a good example of such a control
structure, commonly referred to as an {\it if-then-else} structure:

{\scriptsize
\begin{verbatim}
        if (image_is_color (img)) then
            set_color (RED)
        else
            set_color (BLACK)
\end{verbatim}}

The {\it if-then-else} structure demonstrated in the example above
evaluates whether the image contained in the {\it img} variable is a
color image.  {\it If} it is, then the color is set to red; otherwise,
the color is set to black.  This simple example would be extended in an
actual script to make complex decisions based on the user's specified
logo preferences.

This short {\it if-then-else} example also includes what is known in
programming languages as a ``variable''.  A variable in programming is
quite similar to a variable in algebra.  It is simply a symbol that
represents a value.  Variables are used both in algebra and in
programming because it is more convenient (and more powerful) to
substitute variables for actual values in an expression.

Loops are another example of control that is available when a
programming language is used to specify the steps the computer must
take to complete an algorithm.  Loops allow a given operation to be
repeated.  In batch processing, this simply isn't possible without
explicitly requesting the operation as many times as you'd like it
done.  Here is a comparison of the commands necessary in both batch
processing and scripting to draw five circles:

\begin{itemize}
\item Batch Processing\\
{\scriptsize
\begin{verbatim}
        draw_circle (100, 50, 50)
        draw_circle (200, 50, 50)
        draw_circle (300, 50, 50)
        draw_circle (400, 50, 50)
        draw_circle (500, 50, 50)
\end{verbatim}}
\item Scripting\\
{\scriptsize
\begin{verbatim}
        for (i = 1 to 5)
            draw_circle (i * 100, 50, 50)
\end{verbatim}}
\end{itemize}

Script-Fu uses a programming language known as {\bf
Scheme}\footnote{Script-Fu actually uses SIOD, a small implementation
of Scheme \cite{siod}} \cite{scheme} to implement its scripting.
Scheme is a compact, but fully-featured programming language.  It
affords the programmer the flexibility necessary for automatic logo
generation, without burdening him with unnecessary complexity.  Logo
scripts are written in Scheme and a program called an interpreter
reads through them, evaluating each expression as it goes.  This
scheme interpreter is not actually a separate program in the Script-Fu
architecture.  Instead, it is part of the Script-Fu program, which
simplifies the overall architecture.  The scheme interpreter is quite
small, and therefore does not add significant clutter to Script-Fu.

\subsection{Script-Fu--Management}

The final component is the Script-Fu program itself.  Script-Fu is
implemented as a GIMP extension.  In essence, it acts as manager and
facilitator between the scheme interpreter and GIMP.  It establishes
the lines of communication and forwards messages between them.  It
also presents the user with an interface for selecting which script to
run, and which parameters to run the script with.  Parameters for
running a script typically include things like the typeface, the size,
the text string, and colors.  After the user has selected a script and
entered the input parameters, Script-Fu formulates a command and sends
it to the scheme interpreter, which in turn begins to process the
script.

\section{Component Interaction}

The three components that comprise Script-Fu work together to generate
a logo.  Their interaction is fairly straightforward and consists of
six steps:

\begin{enumerate}
\item Script-Fu presents the user with an interface allowing a
style of logo to be selected and input parameters associated with that
style to be set.
\item Once a logo is selected, Script-Fu formulates a command based on
the user inputs and sends it to the Scheme interpreter.  The
interpreter begins to process the selected script.
\item The Scheme interpreter reads a command from the script,
and if it is GIMP-related, forwards it to Script-Fu.  Otherwise goto
step 6.
\item If the interpreter forwarded a command, Script-Fu parses it and
reformats it so that GIMP will accept it.  Script-Fu then requests
that GIMP execute the command and waits for GIMP to signal success or
failure.
\item GIMP executes the command incoming from Script-Fu, and on
success, returns any values which the command requires as outputs.  On
failure, GIMP returns an error message.
\item The Scheme interpreter checks if the script has been fully
processed.  If so, then the logo is finished; otherwise, goto step 3.
\end{enumerate}

\section{Net-Fu}

Script-Fu and GIMP run on UNIX workstations, which severely limit the
breadth of the user base.  The users who would most benefit from the
advent of an automated graphic design utility are primarily PC users
running either Apple's MacOS or Microsoft's Windows NT and Windows 95.
Therefore, a fourth and final component is necessary to complete
Script-Fu.

\myfigone{net-fu}{6cm}{Net-Fu adds one additional component to the
Script-fu/GIMP architecture: A WWW user interface written as a {\it
Java} applet, and capable of running on any {\it Java}-equipped web browser.}

This additional component is called {\bf Net-Fu}, and serves to bridge
the gap between the UNIX-based Script-Fu and the masses.  Instead of
porting Script-Fu to MacOS or Windows 95, Net-Fu solves the problem of
usability by providing an additional interface to Script-Fu's
functionality.  Net-Fu is implemented as a Java applet--programs which
can be downloaded on the World Wide Web and run on any kind of
computer, from UNIX machines to Macintoshes to PCs.  Java applets can
be run from within web browsers, which means that anyone with access
to the WWW (which is just about everyone these days), can use Net-Fu.

Net-Fu provides an interface similar to the one which Script-Fu
normally provides on the local UNIX machine\footnote{Refer to appendix
D for images of the Net-Fu user interface}: it allows a style of
script to be selected and then prompts the user for logo parameters
such as typeface, size, and the text string.  While Script-Fu simply
takes the user input and feeds it directly to the Scheme interpreter,
Net-Fu must transmit its request to Script-Fu, which then feeds it to
the Scheme interpreter.

When Script-Fu is run, it can be instructed not to display an
interface, but instead to act as a server to which any other program
can send commands which will be processed as if they were entered by
Script-Fu's normal user-interface.  If Net-Fu is the intended
interface, Script-Fu will be instructed to enter server-mode and will
then simply await commands from programs such as Net-Fu.  To clarify,
here is a typical sequence of events that occur using Net-Fu:

\begin{enumerate}
\item A user in Sweden wants to create a title logo that appears to be
made from green, neon tubing and reads ``Jens' Cocktails''.  The user
directs his web browser to the Net-Fu address: {\it
http://scheme.xcf.berkeley.edu/net-fu/}.
\item Jens' browser will now display a table containing the various
styles of logos available for creation through Net-Fu.  Each logo style
entry in the table contains a short description of the style and a
preview.
\item Jens selects the ``Neon'' style and is subsequently presented
with a user interface which prompts him for the following inputs:
\begin{itemize}
\item {\it Text}--He enters ``Jens' Cocktails''
\item {\it Text Size}--He keeps the default value of 100 pixels
\item {\it Typeface}--He keeps the default, ``Blippo'', a font with
evenly rounded characters--quite appropriate for neon.
\item {\it Tube Color}--He selects a bright green with a hint of yellow.
\end{itemize}
\item Jens then clicks the ``Run'' button in the Net-Fu interface and
waits patiently for his logo.
\item As soon as the ``Run'' button is clicked, Net-Fu gathers all of
the information entered by Jens and opens a connection to the
Script-Fu server running on a machine in Berkeley, CA.  Net-Fu then
forwards Jens' command to Script-Fu and waits until Script-Fu returns.
\item Script-Fu receives Jens' command and enters active
processing mode, where it no longer listens for commands, but instead
begins to process the Neon script to Jens' specifications.  When it has
finished the logo, Script-Fu returns the location.
\item Net-Fu receives the location of the logo from Script-Fu
and directs Jens' browser there.
\item Jens claps his hands in glee, as he has created the logo of his
dreams in seconds, without an ounce of effort, and certainly without
straining his limited artistic talents.
\end{enumerate}

\section{Conclusions}

With the advent of the World Wide Web (WWW), mass communication is
available to the average individual at a fraction of its historical
price.  This unprecedented development makes it possible for anyone to
advertise products, exchange information, and communicate ideas.
However, the massive volume of information which flows through the WWW
is a mixed blessing: while it does allow anyone to contribute, it also
reduces the liklihood that a particular piece of information will be
absorbed by a significant number of people.  Like other more
traditional means of mass media--such as TV and radio--the content on
the WWW must be accompanied by attractive packaging to have a large
impact.

Script-Fu delivers this attractive packaging at no cost, in mere
seconds, and without requiring artistic talent.  Script-Fu is capable
of delivering artwork which rivals the quality of that done by
professional graphic designers.  Using Script-Fu and the WWW,
virtually anyone can advertise compellingly, and at almost no cost.

Script-Fu consists of three primary components.  The first is GIMP, an
image manipulation engine which does the actual computations necessary
in creating a logo.  The second is the scripting language (Scheme),
which specifies the algorithms which define the process that leads to
a logo.  The third and final component is a GIMP extension called
Script-Fu, which manages the entire process of creating a logo--from
communication between the Scheme interpreter and GIMP, to a user
interface.

Net-Fu is an optional fourth component and provides an additional user
interface which is accessible to nearly everyone.  It is implemented
as a Java applet and can be accessed through the World Wide Web.
Net-Fu allows anyone with a web browser to access the power of
Script-Fu.

\section{Acknowledgements}
Special thanks to Yaroslav Faybishenko for his speedy implementation
of the Net-Fu Java applet.  Beyond this inadequate mention, Peter
Mattis should be recognized for his work on GIMP.  The software has
come a long way in two years.

\begin{flushleft}
\begin{thebibliography}{References}
\bibitem{photoshop} Adobe Systems, Inc.  Photoshop (tm) 3.0,
 Computer Program, 1994.
\bibitem{foley} J. D. Foley, A. Dam, S. K. Feiner, J. F. Hughes,
 \emph{Computer Graphics: Principles and Practice},
 Addison-Wesley, NY, 1992.
\bibitem{GIMP} S. Kimball, P. Mattis, GNU Image Manipulation
 Program (GIMP), Computer Program, 1996-1997.
\bibitem{hearn} D. Hearn, M. P. Baker,
 \emph{Computer Graphics},
 Prentice Hall, NJ, 1994.
\bibitem{ipv6} R. M. Hinden, ``IP Next Generation Overview'',
 \emph{Communications of the ACM},
 June 1996/Vol 39, No. 6.
\bibitem{scheme} H. Abelson, G. J. Sussman,
 \emph{Structure and Interpretation of Computer Programs},
 The MIT Press, MA, 1985.
\bibitem{siod} G. J. Carrette, Scheme In One Defun (SIOD),
 Computer Program, 1996.
\end{thebibliography}
\end{flushleft}

\onecolumn
\appendix

\section{Example Scripts}

\subsection{Simple Script for HDS Logos}
{\scriptsize
\begin{verbatim}
;  HIGHLIGHT-DROP-SHADOW-LOGO
;  draw the specified text over a background with a drop shadow and a highlight

(define (color-highlight color)
  (let ((r (car color))
        (g (cadr color))
        (b (caddr color)))
    (set! r (+ r (* (- 255 r) 0.75)))
    (set! g (+ g (* (- 255 g) 0.75)))
    (set! b (+ b (* (- 255 b) 0.75)))
    (list r g b)))

(define (hds-logo text size font bg-color text-color)
  (let* ((img (car (gimp-image-new 256 256 RGB)))
         (text-layer (car (gimp-text img -1 0 0 text 10 TRUE size PIXELS "*" font "*" "*" "*" "*")))
         (width (car (gimp-drawable-width text-layer)))
         (height (car (gimp-drawable-height text-layer)))
         (bg-layer (car (gimp-layer-new img width height RGB_IMAGE "Background" 100 NORMAL)))
         (highlight-layer (car (gimp-layer-copy text-layer TRUE)))
         (shadow-layer (car (gimp-layer-new img width height RGBA_IMAGE "Shadow" 100 MULTIPLY)))
         (old-fg (car (gimp-palette-get-foreground)))
         (old-bg (car (gimp-palette-get-background))))
    (gimp-image-undo-disable img)
    (gimp-image-resize img width height 0 0)
    (gimp-image-add-layer img bg-layer 1)
    (gimp-image-add-layer img shadow-layer 1)
    (gimp-image-add-layer img highlight-layer 1)
    (gimp-palette-set-background text-color)
    (gimp-layer-set-preserve-trans text-layer TRUE)
    (gimp-edit-fill img text-layer)
    (gimp-edit-clear img shadow-layer)
    (gimp-palette-set-background (color-highlight text-color))
    (gimp-layer-set-preserve-trans highlight-layer TRUE)
    (gimp-edit-fill img highlight-layer)
    (gimp-palette-set-background bg-color)
    (gimp-drawable-fill bg-layer BG-IMAGE-FILL)
    (gimp-selection-layer-alpha img text-layer)
    (gimp-palette-set-background '(0 0 0))
    (gimp-selection-feather img 7.5)
    (gimp-edit-fill img shadow-layer)
    (gimp-selection-none img)
    (gimp-palette-set-foreground '(255 255 255))
    (gimp-blend img text-layer FG-BG-RGB MULTIPLY RADIAL 100 20 FALSE 0 0 width height)
    (gimp-layer-translate shadow-layer 3 3)
    (gimp-layer-translate highlight-layer -2 -2)
    (gimp-layer-set-name text-layer text)
    (gimp-layer-set-name highlight-layer "Highlight")
    (gimp-palette-set-background old-bg)
    (gimp-palette-set-foreground old-fg)
    (gimp-image-undo-enable img)
    (gimp-display-new img)))
\end{verbatim}}

\subsection{Complex Script for Crystal Logos}

{\scriptsize
\begin{verbatim}
;  CRYSTAL
;  Create a text effect that simulates crystal

(define (set-pt a index x y)
  (prog1
   (aset a (* index 2) x)
   (aset a (+ (* index 2) 1) y)))

(define (spline1)
  (let* ((a (cons-array 18 'byte)))
    (set-pt a 0 0 0)
    (set-pt a 1 31 235)
    (set-pt a 2 63 23)
    (set-pt a 3 95 230)
    (set-pt a 4 127 25)
    (set-pt a 5 159 210)
    (set-pt a 6 191 20)
    (set-pt a 7 223 240)
    (set-pt a 8 255 31)
    a))

(define (crystal-brush brush-size)
  (cond ((<= brush-size 5) "Circle (05)")
        ((<= brush-size 7) "Circle (07)")
        ((<= brush-size 9) "Circle (09)")
        ((<= brush-size 11) "Circle (11)")
        ((<= brush-size 13) "Circle (13)")
        ((<= brush-size 15) "Circle (15)")
        ((<= brush-size 17) "Circle (17)")
        (else "Circle Fuzzy (19)")))

(define (shadows val)
  (/ (* 0.96 val) 2.55))

(define (midtones val)
  (/ val 2.55))

(define (highlights val)
  (/ (* 1.108 val) 2.55))

(define (rval col)
  (car col))

(define (gval col)
  (cadr col))

(define (bval col)
  (caddr col))

(define (sota-scale val scale chrome-factor)
  (* (sqrt val) (* scale chrome-factor)))

(define (crystal-logo chrome-factor text size font bg-img env-map)
  (let* ((img (car (gimp-image-new 256 256 GRAY)))
         (back-img (car (gimp-file-load 1 bg-img bg-img)))
         (back-layer (car (gimp-image-active-drawable back-img)))
         (banding-img (car (gimp-file-load 1 env-map env-map)))
         (banding-layer (car (gimp-image-active-drawable banding-img)))
         (b-size (sota-scale size 2 chrome-factor))
         (offx1 (sota-scale size 0.33 chrome-factor))
         (offy1 (sota-scale size 0.25 chrome-factor))
         (offx2 (sota-scale size (- 0.33) chrome-factor))
         (offy2 (sota-scale size (- 0.25) chrome-factor))
         (feather (sota-scale size 0.5 chrome-factor))
         (blur (sota-scale size 0.5 chrome-factor))
         (displace (sota-scale size 0.25 chrome-factor))
         (brush-size (sota-scale size 0.5 chrome-factor))
         (text-layer (car (gimp-text img -1 0 0 text b-size TRUE size PIXELS "*" font "*" "*" "*" "*")))
         (width (car (gimp-drawable-width text-layer)))
         (height (car (gimp-drawable-height text-layer)))
         (tile-ret (plug-in-tile 1 back-img back-layer width height))
         (tile-img (car tile-ret))
         (tile-layer (cadr tile-ret))
         (bg-layer (car (gimp-layer-copy tile-layer TRUE)))
         (layer1 (car (gimp-layer-copy banding-layer TRUE)))
         (layer2 (car (gimp-layer-new img width height GRAYA_IMAGE "Layer 2" 100 DIFFERENCE)))
         (layer3 (car (gimp-layer-new img width height GRAYA_IMAGE "Layer 3" 100 NORMAL)))
         (layer-mask 0)
         (layer-mask2 0)
         (disp-map 0)
         (old-fg (car (gimp-palette-get-foreground)))
         (old-bg (car (gimp-palette-get-background)))
         (old-brush (car (gimp-brushes-get-brush))))
    (gimp-image-delete banding-img)
    (gimp-image-delete back-img)
    (gimp-image-delete tile-img)
    (gimp-image-undo-disable img)
    (gimp-image-resize img width height 0 0)
    (gimp-image-add-layer img layer3 0)
    (gimp-image-add-layer img layer2 0)
    (gimp-palette-set-background '(255 255 255))
    (gimp-selection-none img)
    (gimp-edit-fill img layer2)
    (gimp-edit-fill img layer3)
    (gimp-layer-set-visible text-layer FALSE)

    (gimp-selection-layer-alpha img text-layer)
    (gimp-palette-set-background '(0 0 0))
    (gimp-selection-translate img offx1 offy1)
    (gimp-selection-feather img feather)
    (gimp-edit-fill img layer2)
    (gimp-selection-translate img (* 2 offx2) (* 2 offy2))
    (gimp-edit-fill img layer3)
    (gimp-selection-none img)
    (set! layer2 (car (gimp-image-merge-visible-layers img CLIP-TO-IMAGE)))
    (gimp-invert img layer2)

    (gimp-image-add-layer img layer1 0)
    (gimp-layer-scale layer1 width height FALSE)
    (plug-in-gauss-iir 1 img layer1 10 TRUE TRUE)
    (gimp-layer-set-opacity layer1 50)
    (set! layer1 (car (gimp-image-merge-visible-layers img CLIP-TO-IMAGE)))
    (gimp-curves-spline img layer1 0 18 (spline1))

    (set! layer-mask (car (gimp-layer-create-mask layer1 BLACK-MASK)))
    (gimp-image-add-layer-mask img layer1 layer-mask)
    (gimp-selection-layer-alpha img text-layer)
    (gimp-palette-set-background '(255 255 255))
    (gimp-edit-fill img layer-mask)

    (set! disp-map (car (gimp-selection-save img)))
    (gimp-brushes-set-brush (crystal-brush brush-size))
    (gimp-palette-set-foreground '(0 0 0))
    (gimp-edit-stroke img disp-map)
    (gimp-selection-none img)

    (plug-in-gauss-rle 1 img disp-map blur TRUE TRUE)
    (gimp-levels img disp-map 0 0 255 1.0 96 255)

    (if (= (car (gimp-drawable-is-rgb bg-layer)) 1)
        (gimp-convert-rgb img))

    (gimp-image-add-layer img bg-layer 2)
    (set! layer2 (car (gimp-layer-copy bg-layer TRUE)))
    (gimp-image-add-layer img layer2 1)

    (plug-in-displace 1 img layer2 displace displace TRUE TRUE disp-map disp-map 0)
    (set! layer-mask2 (car (gimp-layer-create-mask layer2 BLACK-MASK)))
    (gimp-image-add-layer-mask img layer2 layer-mask2)
    (gimp-selection-layer-alpha img text-layer)
    (gimp-palette-set-background '(255 255 255))
    (gimp-edit-fill img layer-mask2)

    (gimp-selection-none img)
    (gimp-levels img layer2 0 0 200 1.5 50 255)
    (gimp-layer-set-mode layer1 OVERLAY)

    (plug-in-gauss-rle 1 img text-layer blur TRUE TRUE)
    (gimp-layer-set-preserve-trans text-layer TRUE)
    (gimp-palette-set-background '(0 0 0))
    (gimp-edit-fill img text-layer)
    (gimp-layer-set-mode text-layer OVERLAY)
    (gimp-layer-translate text-layer offx1 offy1)

    (gimp-image-remove-channel img disp-map)

    (gimp-layer-set-visible text-layer TRUE)
    (gimp-layer-set-name layer1 "Crystal")
    (gimp-layer-set-name layer2 "Interior")
    (gimp-layer-set-name bg-layer "Background")
    (gimp-layer-set-name text-layer "Shadow")

    (gimp-palette-set-foreground old-fg)
    (gimp-palette-set-background old-bg)
    (gimp-brushes-set-brush old-brush)
    (gimp-image-undo-enable img)
    (gimp-display-new img)))
\end{verbatim}}
\twocolumn

\section{GIMP Extensions}

A computer application is generally a stand-alone program, whose
source code contains everything necessary for full functionality.  In
this common case, adding additional features to the application
requires that the original source code be modified, recompiled, and
finally redistributed to its users.  This process of introducing new
features is highly prone to programmer error, often resulting in a
host of new problems, sometimes even with pre-existing features.  A
superior method for extending the functionality of an application is
through extension modules: independent applications which implement
additional features and then make them available to the main
application.

The GIMP and its extensions communicate by invoking commands from a
database of procedures.  Procedures are pieces of functionality
provided by GIMP, its plug-ins, and its extensions.  Procedures take
as input a list of arguments, execute based on the values of those
arguments, and finally return a list of values.  There are procedures
for every piece of internal functionality in the GIMP as well as for
every plug-in written to date.  In total, there are over 275
procedures stored in GIMP's ``procedural database''.  The following are
examples of procedures called by the simple script from Appendix A:

\begin{itemize}
\item {\scriptsize{\bf gimp\_image\_new} {\it width, height, type}\\
Creates a new image, undisplayed with the specified extents and type.
A layer should be created and added before this image is displayed, or
subsequent calls to 'gimp\_display\_new' with this image as an argument
will fail.  Layers can be created using the 'gimp\_layer\_new' commands.
They can be added to an image using the 'gimp\_image\_add\_layer'
command.\\
\bf Inputs \rm
\begin{itemize}
\item {\it width} (PDB\_INT32)--The width of the image
\item {\it height} (PDB\_INT32)--The height of the image
\item {\it type} (PDB\_INT32)--The type of image: \{ RGB (0), GRAY (1), INDEXED (2) \}
\end{itemize}
\bf Outputs \rm
\begin{itemize}
\item {\it image} (PDB\_IMAGE)--The ID of the newly created image
\end{itemize}}

\item {\scriptsize{\bf gimp\_text} {\it image, drawable, x, y, text, border, antialias, size, size\_type, foundry, family, weight, slant, set\_width, spacing}\\
This tool requires font information in the form of seven parameters:
\{size, foundry, family, weight, slant, set\_width, spacing\}.  The
font size can either be specified in units of pixels or points, and
the appropriate metric is specified using the size\_type argument.  The
x and y parameters together control the placement of the new text by
specifying the upper left corner of the text bounding box.  If the
antialias parameter is non-zero, the generated text will blend more
smoothly with underlying layers.  This option requires more time and
memory to compute than non-antialiased text; the resulting floating
selection or layer, however, will require the same amount of memory
with or without antialiasing.  If the specified drawable parameter is
valid, the text will be created as a floating selection attached to
the drawable.  If the drawable parameter is not valid (-1), the text
will appear as a new layer.  Finally, a border can be specified around
the final rendered text.  The border is measured in pixels.\\
\bf Inputs \rm
\begin{itemize}
\item {\it image} (PDB\_IMAGE)--The image
\item {\it drawable} (PDB\_DRAWABLE)--The affected drawable: (-1 for a new text layer)
\item {\it x} (PDB\_FLOAT)--The x coordinate for the left side of text bounding box
\item {\it y} (PDB\_FLOAT)--The y coordinate for the top of text bounding box
\item {\it text} (PDB\_STRING)--The text to generate
\item {\it border} (PDB\_INT32)--The size of the border: border >= 0
\item {\it antialias} (PDB\_INT32)--Generate antialiased text
\item {\it size} (PDB\_FLOAT)--The size of text in either pixels or points
\item {\it size\_type} (PDB\_INT32)--The units of the specified size: \{ PIXELS (0), POINTS (1) \}
\item {\it foundry} (PDB\_STRING)--The font foundry, "*" for any
\item {\it family} (PDB\_STRING)--The font family, "*" for any
\item {\it weight} (PDB\_STRING)--The font weight, "*" for any
\item {\it slant} (PDB\_STRING)--The font slant, "*" for any
\item {\it set\_width} (PDB\_STRING)--The font set-width parameter, "*" for any
\item {\it spacing} (PDB\_STRING)--The font spacing, "*" for any
\end{itemize}
\bf Outputs \rm
\begin{itemize}
\item {\it text\_layer} (PDB\_LAYER)--The new text layer
\end{itemize}}

\item {\scriptsize{\bf gimp\_blend} {\it image, drawable, blend\_mode, paint\_mode, gradient\_type, opacity, offset, repeat, x1, y1, x2, y2}\\
This tool requires information on the paint application mode, the
blend mode, and the gradient type.  It creates the specified variety
of blend using the starting and ending coordinates as defined for each
gradient type.\\
\bf Inputs \rm
\begin{itemize}
\item {\it image} (PDB\_IMAGE)--The image
\item {\it drawable} (PDB\_DRAWABLE)--The affected drawable
\item {\it blend\_mode} (PDB\_INT32)--The type of blend: \{ FG-BG-RGB (0), FG-BG-HSV (1), FG-TRANS (2), CUSTOM (3) \}
\item {\it paint\_mode} (PDB\_INT32)--The paint application mode: \{ NORMAL (0), DISSOLVE (1), BEHIND (2), MULTIPLY (3), SCREEN (4), OVERLAY (5) DIFFERENCE (6), ADDITION (7), SUBTRACT (8), DARKEN-ONLY (9), LIGHTEN-ONLY (10), HUE (11), SATURATION (12), COLOR (13), VALUE (14) \}
\item {\it gradient\_type} (PDB\_INT32)--The type of gradient: \{ LINEAR (0), BILINEAR (1), RADIAL (2), SQUARE (3), CONICAL-SYMMETRIC (4), CONICAL-ASYMMETRIC (5), SHAPEBURST-ANGULAR (6), SHAPEBURST-SPHERICAL (7), SHAPEBURST-DIMPLED (8) \}
\item {\it opacity} (PDB\_FLOAT)--The opacity of the final blend (0 <= opacity <= 100)
\item {\it offset} (PDB\_FLOAT)--Offset relates to the starting and ending coordinates specified for the blend.  This parameter is mode depndent (0 <= offset)
\item {\it repeat} (PDB\_INT32)--Repeat the gradient indefinitely along the direction vector
\item {\it x1} (PDB\_FLOAT)--The x coordinate of this blend's starting point
\item {\it y1} (PDB\_FLOAT)--The y coordinate of this blend's starting point
\item {\it x2} (PDB\_FLOAT)--The x coordinate of this blend's ending point
\item {\it y2} (PDB\_FLOAT)--The y coordinate of this blend's ending point
\end{itemize}}
\end{itemize}
\onecolumn

\section{Script-Fu Logos}

Plates 1-4 are example outputs of Script-Fu scripts:
\begin{itemize}
\item {\bf Carve-It}
  \begin{itemize}
  \item {\bf Image}:
  http://scheme.xcf.berkeley.edu/net-fu/images/plates1-2.jpg
  \item {\bf Script}:
  http://scheme.xcf.berkeley.edu/net-fu/scripts/carve.scm
  \item {\bf Net-Fu Logo}:
  http://scheme.xcf.berkeley.edu/net-fu/carve.html
  \end{itemize}
\item {\bf Starscape Nova}
  \begin{itemize}
  \item {\bf Image}:
  http://scheme.xcf.berkeley.edu/net-fu/images/plates1-2.jpg
  \item {\bf Script}:
  http://scheme.xcf.berkeley.edu/net-fu/scripts/starscape.scm
  \item {\bf Net-Fu Logo}:
  http://scheme.xcf.berkeley.edu/net-fu/starscape.html
  \end{itemize}
\item {\bf Chrome}
  \begin{itemize}
  \item {\bf Image}:
  http://scheme.xcf.berkeley.edu/net-fu/images/plates3-4.jpg
  \item {\bf Script}:
  http://scheme.xcf.berkeley.edu/net-fu/scripts/chrome2.scm
  \item {\bf Net-Fu Logo}:
  http://scheme.xcf.berkeley.edu/net-fu/chrome2.html
  \end{itemize}
\item {\bf Crystal/Gel}
  \begin{itemize}
  \item {\bf Image}:
  http://scheme.xcf.berkeley.edu/net-fu/images/plates3-4.jpg
  \item {\bf Script}:
  http://scheme.xcf.berkeley.edu/net-fu/scripts/crystal.scm
  \item {\bf Net-Fu Logo}:
  http://scheme.xcf.berkeley.edu/net-fu/crystal.html
  \end{itemize}
\end{itemize}

\section{Net-Fu WWW Interface}

{\bf http://scheme.xcf.berkeley.edu/net-fu/}

\end{document}
