335 lines
19 KiB
HTML
335 lines
19 KiB
HTML
<!--startcut ==========================================================-->
|
|
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
|
|
<HTML>
|
|
<HEAD>
|
|
<META HTTP-EQUIV="Content-Type" CONTENT="text/html; charset=iso-8859-1">
|
|
<META NAME="GENERATOR" CONTENT="Mozilla/4.06 [en] (X11; I; Linux 2.0.30 i486) [Netscape]">
|
|
<TITLE>Graphics Muse
|
|
</TITLE>
|
|
</HEAD>
|
|
<BODY TEXT="#000000" BGCOLOR="#FFFFFF" LINK="#0000FA" VLINK="#FA3333" ALINK="#33CC33">
|
|
<!--endcut ============================================================-->
|
|
<!-- =============================================================
|
|
This Page Designed by Michael J. Hammel.
|
|
Permission to use all graphics and other content for private,
|
|
non-commerical use is granted provided you give me (or the
|
|
original authors/artists) credit for the work.
|
|
|
|
CD-ROM distributors and commercial ventures interested in
|
|
providing the Graphics Muse for a fee must contact me,
|
|
Michael J. Hammel (mjhammel@csn.net), for permission.
|
|
============================================================= !--><A NAME="musings"></A>
|
|
<TABLE>
|
|
<TR>
|
|
<TD>
|
|
<H2>
|
|
More...</H2>
|
|
<IMG SRC="../gx/hammel/musings.gif" ALT="Musings" HEIGHT=52 WIDTH=247 ALIGN=LEFT></TD>
|
|
</TR>
|
|
</TABLE>
|
|
|
|
<TABLE>
|
|
<TR>
|
|
<TD></TD>
|
|
</TR>
|
|
</TABLE>
|
|
<IMG SRC="../gx/hammel/cleardot.gif" ALT="indent" VSPACE=5 HEIGHT=1 WIDTH=1 ALIGN=LEFT>
|
|
<TABLE WIDTH="100%" >
|
|
<TR>
|
|
<TD ALIGN=RIGHT WIDTH="100%"><FONT SIZE=-2>© 1998 <A HREF="mailto:mjhammel@graphics-muse.org">Michael
|
|
J. Hammel</A></FONT></TD>
|
|
</TR>
|
|
|
|
<TR>
|
|
<TD VALIGN=TOP BGCOLOR="#000000" cellpadding="0" cellspacing="0"><IMG SRC="../gx/hammel/cleardot.gif" ALT="indent" ALIGN=LEFT></TD>
|
|
</TR>
|
|
</TABLE>
|
|
<A NAME="1"></A>
|
|
<H2>
|
|
Managing your Perl scripts: using 'require' - continued</H2>
|
|
Ok, so now you know how to make a subroutine and how to include it in your
|
|
Perl cgi script. What does this have to do with building common HTML
|
|
code for multiple pages? Simple: by assigning the HTML constructs,
|
|
plus any associated database information, to global variables you can then
|
|
simply add the variable to your main pages at the point of interest.
|
|
For example, lets say you want to include an advertising banner across
|
|
the top of all pages. You can write a small module that builds a
|
|
table for the ad, centers it on the page and assigns it to the global variable
|
|
$adbanner. This might look something like this:
|
|
<UL><TT><FONT SIZE=-1>#!/usr/bin/perl5</FONT></TT>
|
|
<BR><TT><FONT SIZE=-1># Include the CGI.pm and Msql modules</FONT></TT>
|
|
<BR><TT><FONT SIZE=-1>use CGI qw/:standard :html3 :netscape/;</FONT></TT>
|
|
<BR><TT><FONT SIZE=-1>use Msql;</FONT></TT>
|
|
<P><TT><FONT SIZE=-1># The subroutine to create a table for our ads.</FONT></TT>
|
|
<BR><TT><FONT SIZE=-1>sub setads</FONT></TT>
|
|
<BR><TT><FONT SIZE=-1>{</FONT></TT>
|
|
<BR><TT><FONT SIZE=-1> # Open a connection to the database.</FONT></TT>
|
|
<BR><TT><FONT SIZE=-1> my $dbh1 = Msql->connect();</FONT></TT>
|
|
<BR><TT><FONT SIZE=-1> $dbh1->selectdb('mydb');</FONT></TT>
|
|
<P><TT><FONT SIZE=-1> # Get the ads from the database.
|
|
We assume</FONT></TT>
|
|
<BR><TT><FONT SIZE=-1> # here that there is at least 1 ad in
|
|
the</FONT></TT>
|
|
<BR><TT><FONT SIZE=-1> # "ads" table. We also assume
|
|
the table has</FONT></TT>
|
|
<BR><TT><FONT SIZE=-1> # the format of</FONT></TT>
|
|
<BR><TT><FONT SIZE=-1> # 1. imagename</FONT></TT>
|
|
<BR><TT><FONT SIZE=-1> # 2. URL</FONT></TT>
|
|
<BR><TT><FONT SIZE=-1> # The results from the database query
|
|
are stored</FONT></TT>
|
|
<BR><TT><FONT SIZE=-1> # in the @results variable. This
|
|
list variable</FONT></TT>
|
|
<BR><TT><FONT SIZE=-1> # will contain one array element for
|
|
each field</FONT></TT>
|
|
<BR><TT><FONT SIZE=-1> # in the "ads" table.</FONT></TT>
|
|
<P><TT><FONT SIZE=-1> $sth2 = $dbh1->query("SELECT * FROM ads");</FONT></TT>
|
|
<BR><TT><FONT SIZE=-1> while ( (@result = $sth->fetchrow)</FONT></TT>
|
|
<BR><TT><FONT SIZE=-1> {</FONT></TT>
|
|
<BR><TT><FONT SIZE=-1> # Add a <td> entry
|
|
with the image for the ad</FONT></TT>
|
|
<BR><TT><FONT SIZE=-1> # linked to the specified
|
|
URL. The "a({-href"</FONT></TT>
|
|
<BR><TT><FONT SIZE=-1> # portion is where
|
|
we use the CGI.pm</FONT></TT>
|
|
<BR><TT><FONT SIZE=-1> # a() function to
|
|
establish the hyperlink.</FONT></TT>
|
|
<BR><TT><FONT SIZE=-1> push</FONT></TT>
|
|
<BR><TT><FONT SIZE=-1>
|
|
(@tableelments,</FONT></TT>
|
|
<BR><TT><FONT SIZE=-1>
|
|
td({-align=>'CENTER', -valign=>'CENTER'},</FONT></TT>
|
|
<BR><TT><FONT SIZE=-1>
|
|
a({-href=>"$result[1]"},</FONT></TT>
|
|
<BR><TT><FONT SIZE=-1>
|
|
img( { -src=>"/images/$result[0]",</FONT></TT>
|
|
<BR><TT><FONT SIZE=-1>
|
|
-alt=>"$results[1]",</FONT></TT>
|
|
<BR><TT><FONT SIZE=-1>
|
|
-border=>'0',</FONT></TT>
|
|
<BR><TT><FONT SIZE=-1>
|
|
-hspace=>'0', -vspace=>'0' }</FONT></TT>
|
|
<BR><TT><FONT SIZE=-1>
|
|
)</FONT></TT>
|
|
<BR><TT><FONT SIZE=-1>
|
|
)</FONT></TT>
|
|
<BR><TT><FONT SIZE=-1>
|
|
)</FONT></TT>
|
|
<BR><TT><FONT SIZE=-1>
|
|
)</FONT></TT>
|
|
<BR><TT><FONT SIZE=-1> }</FONT></TT>
|
|
<UL> </UL>
|
|
<TT><FONT SIZE=-1> # Now assign a table to our global variable
|
|
and include the</FONT></TT>
|
|
<BR><TT><FONT SIZE=-1> # table elements we just created.</FONT></TT>
|
|
<BR><TT><FONT SIZE=-1> $adbanner = center(</FONT></TT>
|
|
<BR><TT><FONT SIZE=-1> table( {-border=>1,
|
|
-width=>'100%', -height=>'60'},</FONT></TT>
|
|
<BR><TT><FONT SIZE=-1>
|
|
Tr( @tableelements ),</FONT></TT>
|
|
<BR><TT><FONT SIZE=-1> )</FONT></TT>
|
|
<BR><TT><FONT SIZE=-1> );</FONT></TT>
|
|
<BR><TT><FONT SIZE=-1>}</FONT></TT>
|
|
<BR><TT><FONT SIZE=-1># Return true from included modules.</FONT></TT>
|
|
<BR><TT><FONT SIZE=-1>1</FONT></TT></UL>
|
|
Since embedding one Perl function inside another, especially with the use
|
|
of the CGI.pm functions, is such a common occurance I tend to align the
|
|
closing paranthesis so that I can keep track of which function has been
|
|
closed. You'll note in this example that the img() function (which
|
|
will print an HTML IMG tag) is an argument to the a() function (which assigns
|
|
a hypertext link to the image). This in turn is an argument to the
|
|
td() function. Such multilayer embedding becomes quite extensive
|
|
when you use CGI.pm table function (table(), Tr(), td()) to align elements
|
|
of your HTML pages. This is why you will often find yourself using
|
|
variables to which you assign Tr() and td() constructs and then simply
|
|
reference the variables within the table() construct. At a minimum
|
|
this makes the code easier to read. But even more important is that
|
|
you can create lists of td() constructs to stuff inside a Tr() construct
|
|
later by simply referencing the list variable.
|
|
<P>If we now include this module in our main script we can then print out
|
|
the advertisement table at any time we wish:
|
|
<UL><TT><FONT SIZE=-1>require 'setads.pl';</FONT></TT>
|
|
<BR><TT><FONT SIZE=-1>&setads();</FONT></TT>
|
|
<P><TT><FONT SIZE=-1>print header,</FONT></TT>
|
|
<BR><TT><FONT SIZE=-1> start_html(</FONT></TT>
|
|
<BR><TT><FONT SIZE=-1> -author=>'webmaster@graphics-muse.org',</FONT></TT>
|
|
<BR><TT><FONT SIZE=-1> -title=>'Our Little
|
|
Web Site',</FONT></TT>
|
|
<BR><TT><FONT SIZE=-1> -bgcolor=>'#000000',
|
|
-text=>'#000000'</FONT></TT>
|
|
<BR><TT><FONT SIZE=-1> ),</FONT></TT>
|
|
<P><TT><FONT SIZE=-1> $adbanner,</FONT></TT>
|
|
<P><TT><FONT SIZE=-1> table(</FONT></TT>
|
|
<BR><TT><FONT SIZE=-1> {-border=>0, -width=>'100%',
|
|
-height=>'97%',</FONT></TT>
|
|
<BR><TT><FONT SIZE=-1>
|
|
-cellpadding=>0, -cellspacing=>0},</FONT></TT>
|
|
<BR><TT><FONT SIZE=-1> Tr(</FONT></TT>
|
|
<BR><TT><FONT SIZE=-1>
|
|
td({-align=>'LEFT', -valign=>'TOP',</FONT></TT>
|
|
<BR><TT><FONT SIZE=-1>
|
|
-rowspan=>2, -width=>'110',</FONT></TT>
|
|
<BR><TT><FONT SIZE=-1>
|
|
-bgcolor=>'#FFCC00'},</FONT></TT>
|
|
<BR><TT><FONT SIZE=-1>
|
|
$news_table),</FONT></TT>
|
|
<BR><TT><FONT SIZE=-1>
|
|
td({-align=>'CENTER', -valign=>'CENTER',</FONT></TT>
|
|
<BR><TT><FONT SIZE=-1>
|
|
-width=>'78%',</FONT></TT>
|
|
<BR><TT><FONT SIZE=-1>
|
|
-bgcolor=>'#FFCC00'},</FONT></TT>
|
|
<BR><TT><FONT SIZE=-1>
|
|
$nav_bar),</FONT></TT>
|
|
<BR><TT><FONT SIZE=-1>
|
|
td({-align=>'CENTER', -valign=>'TOP',</FONT></TT>
|
|
<BR><TT><FONT SIZE=-1>
|
|
-rowspan=>2,</FONT></TT>
|
|
<BR><TT><FONT SIZE=-1>
|
|
-bgcolor=>'#FFCC00'},</FONT></TT>
|
|
<BR><TT><FONT SIZE=-1>
|
|
$book_table)</FONT></TT>
|
|
<BR><TT><FONT SIZE=-1> ),</FONT></TT>
|
|
<BR><TT><FONT SIZE=-1> Tr(</FONT></TT>
|
|
<BR><TT><FONT SIZE=-1>
|
|
td({-align=>'CENTER', -valign=>'TOP',</FONT></TT>
|
|
<BR><TT><FONT SIZE=-1>
|
|
-height=>'80%',</FONT></TT>
|
|
<BR><TT><FONT SIZE=-1>
|
|
-bgcolor=>'#ffffff'}, $qd_table</FONT></TT>
|
|
<BR><TT><FONT SIZE=-1>
|
|
)</FONT></TT>
|
|
<BR><TT><FONT SIZE=-1> )</FONT></TT>
|
|
<BR><TT><FONT SIZE=-1> );</FONT></TT>
|
|
<BR><TT><FONT SIZE=-1> end_html;</FONT></TT></UL>
|
|
Here we printed out the ad banner right above another table that will contain
|
|
other information for this page. The variables $news_table, $nav_bar,
|
|
$book_table, and $qd_table were filled in by parts of the code not shown
|
|
here. They could just as easily have been filled in by other external
|
|
modules, just like $adbanner was.
|
|
<P>This last bit of code actually comes from the code I'm writing for the
|
|
new Graphics Muse web site. I have a common table definition for
|
|
all pages (the table printed after the $adbanner in the last example),
|
|
and modules for assigning HTML formats and data to the $news_table, $nav_bar
|
|
and $book_table. Then each main CGI script fills in the $qd_table
|
|
variable with page specific data. In this way I can make modifications
|
|
to the way data is displayed in, for example, the news_table by only having
|
|
to edit one script. Management of the site becomes much more simple
|
|
than having to edit all the scripts each time a single change to news_table
|
|
needs to be made and I avoid annoying many users by avoiding the use of
|
|
frames.
|
|
<P>In the short time I've been using Perl I've grown to truly appreciate
|
|
both its sophistication and its simplicity. Things that should be
|
|
simple to do are simple. Additional tools like CGI.pm and Msql make
|
|
integrating Perl with my Web site a breeze. I've managed to rebuild
|
|
my Web site from the ground up in less than a a couple of weeks and I'm
|
|
not even making full use of what Perl can do for me. If you manage
|
|
a Web site and have access to the cgi directory you should definitely consider
|
|
learning Perl, CGI.pm, and one of the many databases which Perl supports.
|
|
<BR>
|
|
<TABLE WIDTH="100%" >
|
|
<TR>
|
|
<TD VALIGN=TOP COLSPAN="4" BGCOLOR="#000000" cellpadding="0" cellspacing="0"><IMG SRC="../gx/hammel/cleardot.gif" ALT="indent" ALIGN=LEFT></TD>
|
|
</TR>
|
|
</TABLE>
|
|
<!-- ------------------------------------------------------------- --><!-- Part 2, if any --><!-- ------------------------------------------------------------- --><A NAME="2"></A>
|
|
<H2>
|
|
Fun with Qbist</H2>
|
|
<IMG SRC="./gx/hammel/qbist-example-1.jpg" HSPACE=15 VSPACE=10 BORDER=3 HEIGHT=400 WIDTH=400 ALIGN=RIGHT>One
|
|
of the more interesting plug-ins in the Gimp is <B><I><FONT COLOR="#993300">Qbist</FONT></I></B><FONT COLOR="#000000">,
|
|
written by <A HREF="mailto:jchrr@hrz.uni-bielefeld.de">Jens Ch. Restemeier</A>
|
|
and based on an algorithm from Jörn Loviscach that appeared in the
|
|
magazine <B><U>c't</U></B> in October 1995</FONT>. I've had quite
|
|
a good time playing with this plug-in creating backgrounds for logos and
|
|
other images. The filter is really pretty easy to use. The
|
|
plug-in dialog is made up of a set of 9 preview windows. By clicking
|
|
on any one of these the entire set is updated with new previews and the
|
|
preview you clicked on is displayed as the new middle preview. This
|
|
central preview is used as a <I>basis</I> to generate the rest of the previews.
|
|
You can generate a set of previews that are somewhat similar to the basis
|
|
preview by clicking on the middle preview. In most cases, at least
|
|
one of the previews will be significantly different from the basis.
|
|
Selecting another preview usually generates quite different previews, but
|
|
this isn't always guaranteed. <IMG SRC="./gx/hammel/qbist-dialog.jpg" HSPACE=15 VSPACE=10 HEIGHT=314 WIDTH=293 ALIGN=LEFT>The
|
|
algorithm is sufficiently random to make it possible that not only can
|
|
the other non-basis previews be radically different, they can also be nearly
|
|
exactly the same as the orginal. From a creative standpoint, I find
|
|
this rather interesting. At times, when I'm tired of coding or writing,
|
|
I pull this filter up and start to become creative. The patterns
|
|
it generates are on the edge of randomness, with just enough recognizable
|
|
geometry to make you say "No, thats not quite right, but its close".
|
|
The problem, of course, is it keeps you saying this ad infinitum until
|
|
you realize its long past midnight and you have just enough time for one
|
|
cup of coffee and a shower before you have to be to work. But this
|
|
is the kind of creativity I used to feel with coding when I first got my
|
|
hands on PC (ok, it was a TRS-80, but you get the point). Its refreshing
|
|
to feel it again.
|
|
<P>Once you've selected the preview you want in your image, making sure
|
|
its been selected and is displayed as the basis preview, you can add it
|
|
to the current layer of your Image Window by clicking on OK. <IMG SRC="./gx/hammel/qbist-example-2.jpg" HSPACE=15 VSPACE=10 BORDER=2 HEIGHT=400 WIDTH=400 ALIGN=RIGHT>Qbist
|
|
will fill the entire layer, or the active selection, with a scaled version
|
|
of the basis preview. Since there are no blend modes for Qbist the
|
|
selection/layer will be completely overwritten with the Qbist pattern.
|
|
The real trick to using these patterns comes from being able to make selections
|
|
out of the geometrically connected pieces, creating drop shadows from the
|
|
selections and slipping other images or text inbetween the layers.
|
|
<BR>
|
|
<H3>
|
|
Some drawbacks and limitations</H3>
|
|
Although I really like this filter, it does have a few drawbacks.
|
|
First, opening the dialog doesn't always get you the same set of previews
|
|
as the last time you opened the window, although the basis is the same.
|
|
It would be nice if you could get the same set of previews since you may
|
|
see another preview in the current Qbist session that you'd like to use
|
|
after selecting the current basis. Unfortunately you won't be able
|
|
to do that since the dialog closes after you click on the OK button.
|
|
You can save the basis preview, but reloading it later has the same effect
|
|
- the rest of the previews are random and not likely to be the same as
|
|
the ones you had seen originally with that basis.
|
|
<P>Another problem is that the Save/Load options don't deal with a Qbist-specific
|
|
directory. A number of other plug-ins manage saved files within directories
|
|
under the users $HOME/.gimp directory. It shouldn't be difficult
|
|
to update Qbist to do the same. Its just a matter of getting around
|
|
to updating the code.
|
|
<P>Speaking of the code, a quick examination of the source to Qbist shows
|
|
some hard coded values used in various places that appear to be the sort
|
|
of values that should be user configurable. The interface could be
|
|
expanded to allow the user to change these. I may try this sometime
|
|
soon, just as an experiment to see how changes to these values affect the
|
|
previews. <IMG SRC="./gx/hammel/qbist-example-3.jpg" HSPACE=15 VSPACE=10 HEIGHT=400 WIDTH=400 ALIGN=LEFT>Since
|
|
I'm not familiar with the algorithm its unclear if these values are necessarily
|
|
specific or just good initial seed values. Another option might be
|
|
to allow the user to choose some color sets from which Qbist could render
|
|
its patterns. Right now Qbist chooses colors on its own, without
|
|
input from the user.
|
|
<P>Finally, probably the most annoying aspect to Qbist is that there are
|
|
no blend modes available. I'd love to be able to render a Qbist pattern
|
|
in one selection and then use another selection to blend a different pattern
|
|
over a corner of the first selection. I can do this with multiple
|
|
layers, but it would be more convenient to be able to do this from within
|
|
Qbist itself. Qbist renders it patterns in both the previews and
|
|
the image window fairly quickly, so changes like adding blend modes shouldn't
|
|
cause serious performance problems.
|
|
<P>Qbist is a plain fun filter. Like many of the Render menu filters,
|
|
Qbist gives you a chance to explore some of your true creativeness.
|
|
By letting you wander through a random collection of patterns it lets you
|
|
play with your computer in a way that a game can never quite equal.
|
|
Although your control over these patterns is a bit limited, the patterns
|
|
themselves are sufficiently fascinating to make Qbist a filter well worth
|
|
exploring.<BR CLEAR=BOTH>
|
|
<BR>
|
|
<TABLE WIDTH="100%" >
|
|
<TR>
|
|
<TD VALIGN=TOP COLSPAN="4" BGCOLOR="#000000" cellpadding="0" cellspacing="0"><IMG SRC="../gx/hammel/cleardot.gif" ALT="indent" ALIGN=LEFT></TD>
|
|
</TR>
|
|
</TABLE>
|
|
|
|
<TABLE WIDTH="100%" >
|
|
<TR>
|
|
<TD ALIGN=RIGHT><FONT SIZE=-2>© 1997 by <A HREF="mailto:mjhammel@graphics-muse.org">Michael
|
|
J. Hammel</A></FONT></TD>
|
|
</TR>
|
|
</TABLE>
|
|
|
|
</BODY>
|
|
</HTML>
|