File: script-fu.tex

package info (click to toggle)
gimp 1.0.2-3
  • links: PTS
  • area: main
  • in suites: slink
  • size: 17,116 kB
  • ctags: 16,070
  • sloc: ansic: 226,067; lisp: 8,497; sh: 4,965; makefile: 4,543
file content (935 lines) | stat: -rw-r--r-- 42,876 bytes parent folder | download | duplicates (3)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
\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-disable-undo 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-enable-undo 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-disable-undo 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-color 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-enable-undo 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}