
\section{im-hax-14-26}
\filbreak \subsubsection{readme.txt}
.\newline{}
\begin{verbatim}

# Name:
#   readme.txt
#
# Author:
#   Ron Savage <ron@savage.net.au>
#
# Home:
#   http://savage.net.au/ImageMagick.html

Overview
--------
o   ImageMagick Hax are a set of Perl scripts aimed at people beginning to use
    the Perl module Image::Magick. The aim is to get you up and running as
    quickly as possible.

o   You are expected to study the scripts before running them. Hence the
    promise: No surprises.

o   Each hax is deliberately designed to be trivial, so as to help focus on
    one feature of ImageMagick. The name of the hax tells you the point of
    the exercise. Eg: im-hax-crop-1.pl demonstrates Crop(...).
    It's that simple. This helps deliver on the promise: No surprises.

o   *.cgi are CGI scripts, and *.pl are command line scripts. A simple menu
    script, im-hax-menu.cgi, is supplied to help run the CGI scripts.

o   Comments at the start of each hax list the assumed directory structure,
    input files and output files. These are also stored in variables at the
    start of each script, to facilitate installation anywhere.

o   All input files are either shipped with ImageMagick or output from a hax.
    Eg: The output of im-hax-rotate-1.pl is input to im-hax-composite-1.pl.

o   Only the generic TTF file, Generic.ttf is used to annotate images. Nothing
    would be gained here by using a different font file.

Files
-----
o   im-hax-1-13.tgz contains ImageMagick Hax 1 .. 13, as well as the CGI menu,
    licence.txt and this file, readme.txt.

o   im-hax-14-26.tgz contains ImageMagick Hax 14 .. 26, as well as the CGI menu,
    licence.txt and this file, readme.txt.

o   im-hax-27-39.tgz contains ImageMagick Hax 27 .. 39, as well as the CGI menu,
    licence.txt and this file, readme.txt.
\end{verbatim}
\filbreak \subsubsection{im-hax-button-1.cgi}
.\newline{}
\begin{verbatim}

#!/usr/bin/perl
#
# Name:
#   im-hax-button-1.cgi.
#
# Purpose:
#   Test Annotate, ImageToBlob, Write to STDOUT.
#
# V 1.01 20-Feb-2002
# ------------------
# o Don't use $ENV{'TT_FONT_PATH'} in IM V 5.4.3.
#   Put font in same dir as script
# o Patch Apache httpd.conf to match. Ie:
#   PassEnv MAGICK_HOME
# o Remove TT_FONT_PATH from environment
#
# V 1.00 17-Jan-2002
# ------------------
# o Initial version
#
# Test environment:
#   OS: WinNT 4 SP 6a
#   Web server: Apache V 1.3.26
#   IM: V 5.4.7
#
# Warning:
#   ImageToBlob only works after the call to
#   Set(magick => ...) or Write(...).
#
# Apache web server configuration patches:
#   o Add this line to /apache/conf/httpd.conf:
#   PassEnv MAGICK_HOME
#   o Doing this means we do not have to execute
#   chdir('ImageMagick bin dir')
#
# Program environment patches:
#   MAGICK_HOME = D:\ImageMagick\VisualMagick\bin
#
# Perl source patches:
#   I tried this:
#   BEGIN
#   {
#       $ENV{'MAGICK_HOME'} = ...;
#       use Image::Magick;
#   }
#   but it did not work :-(.
#
# Input files:
#   ./Generic.ttf.
#
# Output files:
#   /apache/htdocs/im-hax-button-1.gif.
#
# Note:
#   o CGI.pm is not needed
#   o tab = 4 spaces || die.
#   o Text reformatted to max 50 chars wide
#       so source can be converted to PDF
#
# Author:
#   Ron Savage <ron@savage.net.au>
#   http://savage.net.au/ImageMagick.html
#
# Licence:
#   Copyright (c) 1999-2002 Ron Savage
#
#   All Programs of mine are
#   'OSI Certified Open Source Software';
#   you can redistribute them and/or modify them
#   under the terms of the Artistic License,
#   a copy of which is available at:
#   http://www.opensource.org/licenses/index.html

use strict;
use warnings;

use Image::Magick;

# -----------------------------------------------

delete @ENV{'BASH_ENV', 'CDPATH', 'ENV', 'IFS',
    'PATH', 'SHELL'}; # For security.

my($doc_root_name)      = '/apache/htdocs';
my($image_type)         = 'gif';
my($output_file_name)   =
    "im-hax-button-1.$image_type";
my($output_path)        =
    "$doc_root_name/$output_file_name";
my($i)                  = Image::Magick -> new();
my($result)             =
    $i -> Set(size => '30x105');
warn "Set: $result" if $result;

$result = $i -> Set(magick => $image_type);
warn "Set: $result" if $result;

$result = $i -> Read('gradient:#00f685-#0083f8');
warn "Read: $result" if $result;

$result = $i -> Rotate(-90);
warn "Rotate: $result" if $result;

$result = $i -> Raise('6x6');
warn "Raise: $result" if $result;

$result = $i -> Annotate
(
    text        => 'Push Me Up',
    font        => 'Generic.ttf',
    fill        => 'black',
    gravity     => 'Center',
    pointsize   => 18,
);
warn "Annotate: $result" if $result;

# Warning:
#   ImageToBlob only works after the call to
#   Set(magick => ...) or Write(...).

$result = $i -> Set(magick => $image_type);
warn "Set: $result" if $result;

#$result = $i -> Write($output_file_name);
#warn "Set: $result" if $result;

my(@blob) = $i -> ImageToBlob();

binmode STDOUT;

print "Content-type: image/$image_type\r\n\r\n",
    $blob[0];
\end{verbatim}
\filbreak \subsubsection{im-hax-button-2.cgi}
.\newline{}
\begin{verbatim}

#!/usr/bin/perl
#
# Name:
#   im-hax-button-2.cgi.
#
# Purpose:
#   Test TT_FONT_PATH, Annotate, Write to STDOUT.
#
#   This CGI script can be run by itself, or
#   called from im-hax-button-4.cgi.
#
# V 1.01 20-Feb-2002
# ------------------
# o Don't use $ENV{'TT_FONT_PATH'} in IM V 5.4.3.
#   Put font in same dir as script
# o Patch Apache httpd.conf to match. Ie:
#   PassEnv MAGICK_HOME
# o Remove TT_FONT_PATH from environment
#
# V 1.01 20-Jun-2002
# ------------------
# o Change stroke => 'red' to stroke => 'none'
#   to get sharper text.
#
# V 1.00 17-Jan-2002
# ------------------
# o Initial version
#
# Test environment:
#   OS: WinNT 4 SP 6a
#   Web server: Apache V 1.3.26
#   IM: V 5.4.7
#
# Apache web server configuration patches:
#   o Add this line to /apache/conf/httpd.conf:
#   PassEnv MAGICK_HOME
#   o Doing this means we do not have to execute
#   chdir('ImageMagick bin dir')
#
# Program environment patches:
#   MAGICK_HOME = D:\ImageMagick\VisualMagick\bin
#
# Input files:
#   ./Generic.ttf.
#
# Output files:
#   None.
#
# Note:
#   o CGI.pm is not needed
#   o tab = 4 spaces || die.
#   o Text reformatted to max 50 chars wide
#       so source can be converted to PDF
#
# Author:
#   Ron Savage <ron@savage.net.au>
#   http://savage.net.au/ImageMagick.html
#
# Licence:
#   Copyright (c) 1999-2002 Ron Savage
#
#   All Programs of mine are
#   'OSI Certified Open Source Software';
#   you can redistribute them and/or modify them
#   under the terms of the Artistic License,
#   a copy of which is available at:
#   http://www.opensource.org/licenses/index.html

use strict;
use warnings;

use Image::Magick;

# -----------------------------------------------

delete @ENV{'BASH_ENV', 'CDPATH', 'ENV', 'IFS',
    'PATH', 'SHELL'}; # For security.

my($image, $result);

my($im_version) = $Image::Magick::VERSION;
$image          = Image::Magick->new;

$result = $image->Set(size=>'300x300');
warn $result if $result;

$result = $image->ReadImage('xc:green');
warn $result if $result;

# stroke => 'none', fill => 'red' produces
# sharper text than stroke => 'red',
# fill => 'red'.

$result = $image -> Annotate
(
    text        => "Hello, IM V $im_version",
    font        => 'Generic.ttf',
    pointsize   => 40,
    stroke      => 'none',
    fill        => 'red',
    x           => 10,  # In a bit.
    y           => 150, # Half way down.
);
warn $result if $result;

binmode STDOUT;

print "Content-type: image/png\r\n\r\n";

$result = $image->Write('png:-');
warn $result if $result;
\end{verbatim}
\filbreak \subsubsection{im-hax-button-3.cgi}
.\newline{}
\begin{verbatim}

#!/usr/bin/perl
#
# Name:
#   im-hax-button-3.cgi.
#
# Purpose:
#   Make simple beveled button and output to
#   STDOUT in GIF format.
#   To embed this image in a web page, see
#   im-hax-button-4.cgi.
#
#   This CGI script can be run by itself, or
#   called from im-hax-button-4.cgi.
#
# V 1.00 17-Jan-2002
# ------------------
# o Initial version
#
# Test environment:
#   OS: WinNT 4 SP 6a
#   Web server: Apache V 1.3.26
#   IM: V 5.4.7
#
# Apache web server configuration patches:
#   o Add this line to /apache/conf/httpd.conf:
#   PassEnv MAGICK_HOME
#   o Doing this means we do not have to execute
#   chdir('ImageMagick bin dir').
#
# Program environment patches:
#   MAGICK_HOME = D:\ImageMagick\VisualMagick\bin
#
# Input files:
#   None.
#
# Output files:
#   None.
#
# Note:
#   o CGI.pm is not needed
#   o tab = 4 spaces || die.
#   o Text reformatted to max 50 chars wide
#       so source can be converted to PDF
#
# Author:
#   Ron Savage <ron@savage.net.au>
#   http://savage.net.au/ImageMagick.html
#
# Licence:
#   Copyright (c) 1999-2002 Ron Savage
#
#   All Programs of mine are
#   'OSI Certified Open Source Software';
#   you can redistribute them and/or modify them
#   under the terms of the Artistic License,
#   a copy of which is available at:
#   http://www.opensource.org/licenses/index.html

use Image::Magick;

# -----------------------------------------------

delete @ENV{'BASH_ENV', 'CDPATH', 'ENV', 'IFS',
    'PATH', 'SHELL'}; # For security.

print "Content-type: image/gif\r\n\r\n";

my($image)  = Image::Magick -> new();
my($result) = $image -> Set(size => '30x180');
warn $result if $result;
my($g)  = '#ff0000-#0000ff';
$result = $image -> Read("gradient:$g");
warn $result if $result;
$result = $image -> Raise('3x3');
warn $result if $result;
$result = $image -> Rotate(-90);
warn $result if $result;
$result = $image -> Write('gif:-');
warn $result if $result;
\end{verbatim}
\filbreak \subsubsection{im-hax-button-4.cgi}
.\newline{}
\begin{verbatim}

#!/usr/bin/perl
#
# Name:
#   im-hax-button-4.cgi.
#
# Purpose:
#   Demonstrate creating a button with an
#   external script.
#
#   This CGI script can be edited to call
#   im-hax-button-[123].cgi.
#
# V 1.00 17-Jan-2002
# ------------------
# o Initial version
#
# Test environment:
#   OS: WinNT 4 SP 6a
#   Web server: Apache V 1.3.26
#   IM: V 5.4.7
#
# Input files:
#   None.
#
# Output files:
#   /apache/htdocs/im-hax-button-1.gif if we call
#   im-hax-button-1.cgi.
#
# Note:
#   o tab = 4 spaces || die.
#   o Text reformatted to max 50 chars wide
#       so source can be converted to PDF
#
# Author:
#   Ron Savage <ron@savage.net.au>
#   http://savage.net.au/ImageMagick.html
#
# Licence:
#   Copyright (c) 1999-2002 Ron Savage
#
#   All Programs of mine are
#   'OSI Certified Open Source Software';
#   you can redistribute them and/or modify them
#   under the terms of the Artistic License,
#   a copy of which is available at:
#   http://www.opensource.org/licenses/index.html

use strict;
use warnings;

use CGI;

# -----------------------------------------------

delete @ENV{'BASH_ENV', 'CDPATH', 'ENV', 'IFS',
    'PATH', 'SHELL'}; # For security.

my($q)              = CGI -> new();
my($button_cgi)     = 'im-hax-button-3.cgi';
my($output_path)    = '/cgi-bin/ImageMagick';

print   $q -> header
        ({
            type => 'text/html;charset=ISO-8859-1',
        }),
        $q -> start_html(),
        $q -> h3
        (
            {align => 'center',},
            'Test calling Perl to create image'
        ),
        $q -> img
        ({
            align   => 'center',
            src     =>"$output_path/$button_cgi",
            alt     => $button_cgi,
        }),
        $q -> end_html();
\end{verbatim}
\filbreak \subsubsection{im-hax-menu.cgi}
.\newline{}
\begin{verbatim}

#!/usr/bin/perl -T
#
# Name:
#   im-hax-menu.cgi.
#
# Purpose:
#   Provide a simple menu system for the hax.
#
# V 1.01 20-Feb-2002
# ------------------
# o Restrict menu to *.cgi files
#
# V 1.00 17-Jan-2002
# ------------------
# o Initial version
#
# Test environment:
#   OS: WinNT 4 SP 6a
#   Web server: Apache V 1.3.26
#   IM: V 5.4.7
#
# Input files:
#   None.
#
# Output files:
#   None.
#
# Note:
#   o tab = 4 spaces || die.
#   o Text reformatted to max 50 chars wide
#       so source can be converted to PDF
#
# Author:
#   Ron Savage <ron@savage.net.au>
#   http://savage.net.au/ImageMagick.html
#
# Licence:
#   Copyright (c) 1999-2002 Ron Savage
#
#   All Programs of mine are
#   'OSI Certified Open Source Software';
#   you can redistribute them and/or modify them
#   under the terms of the Artistic License,
#   a copy of which is available at:
#   http://www.opensource.org/licenses/index.html

use strict;
use warnings;

use CGI qw/nobr/;
use CGI::Carp qw/fatalsToBrowser/;

# -----------------------------------------------

my($inner_table_color)  = '#80c0ff';
my($outer_table_color)  = '#80ffff';

# -----------------------------------------------

delete @ENV{'BASH_ENV', 'CDPATH', 'ENV', 'IFS',
    'PATH', 'SHELL'}; # For security.

my($q)          = CGI -> new();
my($html)       = [];
my($title)      = 'ImageMagick Hax Menu';
my($dir_name)   = '/apache/cgi-bin/ImageMagick';

opendir(INX, $dir_name) ||
    die("Can't opendir($dir_name): $!");
my(@menu) = sort grep
                {
                    /^im-hax.+\.cgi$/ &&
                    ! /im-hax-menu/
                } readdir(INX);
closedir(INX);

# Put an even # of items into @menu.

if ( ($#menu % 2) == 0)
{
    my($script) = $q -> url();
    $script     =~ s/.+\///;

    push(@menu, $script);
}

print   $q -> header(),
        $q -> start_html({title => $title}),
        $q -> table
        (
            {
                align   => 'center',
                bgColor => $inner_table_color,
            },
            $q -> caption($title),
            $q -> Tr
            ([
                map
                {
                    my($i) = 2 * $_;

                    $q -> td
                    (
                        $q -> a
                        ({
                            href    => $menu[$i],
                        }, $menu[$i])
                    ) .
                    $q -> td
                    (
                        $q -> a
                        ({
                            href => $menu[$i+1],
                        }, $menu[$i + 1])
                    ),
                    $q -> td('&nbsp;')
                } 0 .. int($#menu / 2)
            ])
        ),
        $q -> end_html();
\end{verbatim}
\filbreak \subsubsection{im-hax-montage-2.pl}
.\newline{}
\begin{verbatim}

#!/usr/bin/perl
#
# Name:
#   im-hax-montage-2.pl.
#
# Purpose:
#   Demonstrate the Montage method.
#
# V 1.00 17-Jan-2002
# ------------------
# o Initial version
#
# Test environment:
#   OS: WinNT 4 SP 6a
#   Web server: Apache V 1.3.26
#   IM: V 5.4.7

#
# Input files:
#   /HomePage/Pictures/gray.png
#   /HomePage/Pictures/green.png
#   /HomePage/Pictures/maroon.png
#   /HomePage/Pictures/olive.png
#
# Output files:
#   /apache/htdocs/im-hax-montage-2.png
#
# Note:
#   o tab = 4 spaces || die.
#   o Text reformatted to max 50 chars wide
#       so source can be converted to PDF
#
# Author:
#   Ron Savage <ron@savage.net.au>
#   http://savage.net.au/ImageMagick.html
#
# Licence:
#   Copyright (c) 1999-2002 Ron Savage
#
#   All Programs of mine are
#   'OSI Certified Open Source Software';
#   you can redistribute them and/or modify them
#   under the terms of the Artistic License,
#   a copy of which is available at:
#   http://www.opensource.org/licenses/index.html

use strict;
use warnings;

use Image::Magick;

# ----------------------------------------------

my($i) = Image::Magick -> new();

my($result);

$result = $i -> Read
(
    '/HomePage/Pictures/olive.png',
    '/HomePage/Pictures/green.png',
    '/HomePage/Pictures/gray.png',
    '/HomePage/Pictures/maroon.png'
);
warn $result if ($result);

my($j) = $i -> Montage
(
    background  => 'white',
    frame       => '3x3',
    tile        => '2x2',
);
warn $result if ($result);

my($output_file_name)   =
    'png:/apache/htdocs/im-hax-montage-2.png';
$result                 =
    $j -> Write($output_file_name);
warn $result if ($result);

print "Wrote $output_file_name\n";
\end{verbatim}
\filbreak \subsubsection{im-hax-query-font-metrics-1.pl}
.\newline{}
\begin{verbatim}

#!/usr/bin/perl
#
# Name:
#   im-hax-query-font-metrics-1.pl.
#
# Purpose:
#   Demonstrate QueryFontMetrics.
#
# V 1.01 20-Feb-2002
# ------------------
# o Don't use $ENV{'TT_FONT_PATH'} in IM V 5.4.3.
#   Put font in same dir as script
# o Patch Apache httpd.conf to match. Ie:
#   PassEnv MAGICK_HOME
# o Remove TT_FONT_PATH from environment
#
# V 1.00 17-Jan-2002
# ------------------
# o Initial version
#
# Test environment:
#   OS: WinNT 4 SP 6a
#   Web server: Apache V 1.3.26
#   IM: V 5.4.7

#
# Input files:
#   ./Generic.ttf
#
# Output file:
#   im-hax-png:query-font-metrics-1.png
#
# Note:
#   o tab = 4 spaces || die.
#   o Text reformatted to max 50 chars wide
#       so source can be converted to PDF
#
# Expected output:
#   Script: im-hax-query-font-metrics-1.pl.
#   Image::Magick V 5.47.
#   Image: xc:blue. Size: 100 x 100.
#   Font: Generic.ttf.
#   Font metrics: 24, 24, 20, -6, 79, 30, 18.
#   png:/temp/im-hax-query-font-metrics-1.png.
#
# Author:
#   Ron Savage <ron@savage.net.au>
#   http://savage.net.au/ImageMagick.html
#
# Licence:
#   Copyright (c) 1999-2002 Ron Savage
#
#   All Programs of mine are
#   'OSI Certified Open Source Software';
#   you can redistribute them and/or modify them
#   under the terms of the Artistic License,
#   a copy of which is available at:
#   http://www.opensource.org/licenses/index.html

use strict;
use warnings;

use Image::Magick;

# -----------------------------------------------

my($script)     = $0;
$script         =~ tr|\\|/|;
$script         =~ s|.*/||;
my($im_version) = $Image::Magick::VERSION;

print "Script: $script. \n";
print "Image::Magick V $im_version. \n";

my($output_dir_name)    = '/temp';
my($output_file_name)   =
    "png:$output_dir_name/" .
    "im-hax-query-font-metrics-1.png";
my($image_name)         = 'xc:blue';
my($font)               = 'Generic.ttf';
my($image)              = new Image::Magick();
my($result)             =
    $image -> Set(size=>'100x100');
die $result if $result;

$result = $image -> Read($image_name);
die $result if $result;

my($x_size, $y_size) =
    $image -> Get('width', 'height');

print "Image: $image_name. Size: ",
    "$x_size x $y_size. \n";

my(%args) =
(
    text        => 'Text test',
    font        => $font,
    pointsize   => 24,
    gravity     => 'Center',
);

my(@metric) = $image -> QueryFontMetrics(%args);

print "Font: $font. \n";
print 'Font metrics: ',
    join(', ', @metric), ". \n";

$result = $image -> Annotate(%args);
die $result if $result;

$result = $image -> Write($output_file_name);
die $result if $result;

print "$output_file_name. \n";
\end{verbatim}
\filbreak \subsubsection{im-hax-query-font-metrics-2.pl}
.\newline{}
\begin{verbatim}

#!/usr/bin/perl
#
# Name:
#   im-hax-query-font-metrics-2.pl.
#
# Purpose:
#   Demonstrate QueryFontMetrics.
#
# V 1.00 17-Jan-2002
# ------------------
# o Initial version
#
# Test environment:
#   OS: WinNT 4 SP 6a
#   Web server: Apache V 1.3.26
#   IM: V 5.4.7

#
# Input files:
#   ./Generic.ttf
#   /apache/htdocs/smile.gif
#
# Output files:
#   None
#
# Note:
#   o tab = 4 spaces || die.
#   o Text reformatted to max 50 chars wide
#       so source can be converted to PDF
#
# Expected output:
#   Script: im-hax-query-font-metrics-2.pl.
#   Image::Magick V 5.47.
#   Background: /apache/htdocs/smile.gif.
#   Bkg size: 48 x 48.
#   Font: Generic.ttf.
#   Font metrics: 36, 36, 29, -10, 131, 45, 28
#
# Author:
#   Ron Savage <ron@savage.net.au>
#   http://savage.net.au/ImageMagick.html
#
# Licence:
#   Copyright (c) 1999-2002 Ron Savage
#
#   All Programs of mine are
#   'OSI Certified Open Source Software';
#   you can redistribute them and/or modify them
#   under the terms of the Artistic License,
#   a copy of which is available at:
#   http://www.opensource.org/licenses/index.html

use strict;
use warnings;

use Image::Magick;

# -----------------------------------------------

my($script)     = $0;
$script         =~ tr|\\|/|;
$script         =~ s|.*/||;
my($im_version) = $Image::Magick::VERSION;

print "Script: $script. \n";
print "Image::Magick V $im_version. \n";

my($bkg_name)   = '/apache/htdocs/smile.gif';
my($image_name) = 'xc:maroon';
my($font)       = 'Generic.ttf';
my($background) = Image::Magick -> new();
my($result)     = $background -> Read($bkg_name);
die $result if $result;

my($x_size, $y_size) =
    $background -> Get('width', 'height');

print "Background: $bkg_name. \nBkg size: ",
    "$x_size x $y_size. \n";

# Make the label image the same size as the
# background.

my($image) = Image::Magick -> new
(size => "${x_size}x$y_size");

# Warning: This program simply will not work
# without the next line.

$result     = $image -> Read($image_name);
die $result if $result;

$result = $image -> Set
(
    font        => $font,
    pointsize   => 36,
);
die $result if $result;

my($x_ppem, $y_ppem, $ascender, $descender,
$text_width, $text_height, $max_advance) =
$image -> QueryFontMetrics
(
    text    => 'Test test',
    font    => $font,
);

print "Font: $font. \n";
print "Font metrics: $x_ppem, $y_ppem, ",
    "$ascender, $descender, $text_width, ",
    "$text_height, $max_advance\n";
\end{verbatim}
\filbreak \subsubsection{im-hax-tile-1.pl}
.\newline{}
\begin{verbatim}

#!/usr/bin/perl
#
# Name:
#   im-hax-tile-1.pl.
#
# Purpose:
#   Create a tiled image.
#
# V 1.00 17-Jan-2002
# ------------------
# o Initial version
#
# Test environment:
#   OS: WinNT 4 SP 6a
#   Web server: Apache V 1.3.26
#   IM: V 5.4.7

#
# Input files:
#   /apache/htdocs/smile.gif.
#
# Output files:
#   /apache/htdocs/im-hax-tile-1.gif.
#
# Note:
#   o tab = 4 spaces || die.
#   o Text reformatted to max 50 chars wide
#       so source can be converted to PDF
#
# Author:
#   Ron Savage <ron@savage.net.au>
#   http://savage.net.au/ImageMagick.html
#
# Licence:
#   Copyright (c) 1999-2002 Ron Savage
#
#   All Programs of mine are
#   'OSI Certified Open Source Software';
#   you can redistribute them and/or modify them
#   under the terms of the Artistic License,
#   a copy of which is available at:
#   http://www.opensource.org/licenses/index.html

use strict;
use warnings;

use Image::Magick;

# -----------------------------------------------

my($doc_root_name)      = '/apache/htdocs';
my($output_file_name)   =
    "$doc_root_name/im-hax-tile-1.gif";
my($image)              = Image::Magick -> new();
my($result)             =
    $image -> Set(size => '200x200');
warn $result if $result;

$result =
$image -> Read("tile:$doc_root_name/smile.gif");
warn $result if $result;

$result = $image -> Write($output_file_name);
warn $result if $result;

print "Wrote $output_file_name. \n";
\end{verbatim}
\filbreak \subsubsection{im-hax-transparent-2.pl}
.\newline{}
\begin{verbatim}

#!/usr/bin/perl
#
# Name:
#   im-hax-transparent-2.pl.
#
# Purpose:
#   Create a transparent image.
#
# V 1.01 20-Feb-2002
# ------------------
# o Add a border round the image
#
# V 1.00 17-Jan-2002
# ------------------
# o Initial version
#
# Test environment:
#   OS: WinNT 4 SP 6a
#   Web server: Apache V 1.3.26
#   IM: V 5.4.7

#
# Input files:
#   None.
#
# Output files:
#   /apache/htdocs/im-hax-transparent-2.gif.
#
# Note:
#   o tab = 4 spaces || die.
#   o Text reformatted to max 50 chars wide
#       so source can be converted to PDF
#
# Author:
#   Ron Savage <ron@savage.net.au>
#   http://savage.net.au/ImageMagick.html
#
# Licence:
#   Copyright (c) 1999-2002 Ron Savage
#
#   All Programs of mine are
#   'OSI Certified Open Source Software';
#   you can redistribute them and/or modify them
#   under the terms of the Artistic License,
#   a copy of which is available at:
#   http://www.opensource.org/licenses/index.html

use strict;
use warnings;

use Image::Magick;

# -----------------------------------------------

my($doc_root_name)      = '/apache/htdocs';
my($output_file_name)   =
    "$doc_root_name/im-hax-transparent-2.gif";
my($image)              = Image::Magick -> new();
my($width)              = 30;
my($height)             = 30;
my($result)             =
    $image -> Set(size => "${width}x$height");
warn $result if $result;

$result = $image -> Read('xc:red');
warn $result if $result;

$result = $image -> Draw
(
    primitive   => 'matte',
    method      => 'replace',
    points      => '0,0',
);
warn $result if $result;

$result = $image -> Border
(
    width   => 2,
    height  => 2,
    fill    => 'cyan',
);
warn $result if $result;

$result = $image -> Write($output_file_name);
warn $result if $result;

print "Wrote $output_file_name. \n";
\end{verbatim}
\filbreak \subsubsection{im-hax-transparent-3.pl}
.\newline{}
\begin{verbatim}

#!/usr/bin/perl
#
# Name:
#   im-hax-transparent-3.pl.
#
# Purpose:
#   Create a transparent image.
#
# V 1.01 20-Feb-2002
# ------------------
# o Add a border round the image
#
# V 1.00 17-Jan-2002
# ------------------
# o Initial version
#
# Test environment:
#   OS: WinNT 4 SP 6a
#   Web server: Apache V 1.3.26
#   IM: V 5.4.7

#
# Input files:
#   None.
#
# Output files:
#   /apache/htdocs/im-hax-transparent-3.gif.
#
# Note:
#   o tab = 4 spaces || die.
#   o Text reformatted to max 50 chars wide
#       so source can be converted to PDF
#
# Author:
#   Ron Savage <ron@savage.net.au>
#   http://savage.net.au/ImageMagick.html
#
# Licence:
#   Copyright (c) 1999-2002 Ron Savage
#
#   All Programs of mine are
#   'OSI Certified Open Source Software';
#   you can redistribute them and/or modify them
#   under the terms of the Artistic License,
#   a copy of which is available at:
#   http://www.opensource.org/licenses/index.html

use strict;
use warnings;

use Image::Magick;

# -----------------------------------------------

my($doc_root_name)      = '/apache/htdocs';
my($output_file_name)   =
    "$doc_root_name/im-hax-transparent-3.gif";
my($width)              = 30;
my($height)             = 30;
my($image)              = Image::Magick -> new();
my($result)             =
    $image -> Set(size => "${width}x$height");
warn $result if $result;

$result = $image -> Read('xc:#000000FF');
warn $result if $result;

$result = $image -> Border
(
    width   => 2,
    height  => 2,
    fill    => 'cyan',
);
warn $result if $result;

$result = $image -> Write($output_file_name);
warn $result if $result;

print "Wrote $output_file_name. \n";
\end{verbatim}
\filbreak \subsubsection{im-hax-upload-1.cgi}
.\newline{}
\begin{verbatim}

#!/usr/bin/perl
#
# Name:
#   im-hax-upload-1.cgi.
#
# Purpose:
#   Upload an image and then display it.
#
# Version:
#   1.00    17-Jan-2002
#
# Test environment:
#   OS: WinNT 4 SP 6a
#   Web server: Apache V 1.3.26
#   IM: V 5.4.7
#
# Warning:
#   ImageToBlob only works after the call to
#   Set(magick => ...) or Write(...).
#
# Input files:
#   Whatever you upload, eg smile.gif.
#
# Output files:
#   /apache/htdocs/upload.gif.
#   /apache/htdocs/new-upload.gif.
#   /apache/htdocs/junk-upload.gif.
#
# Note:
#   o tab = 4 spaces || die.
#   o Text reformatted to max 50 chars wide
#       so source can be converted to PDF
#
# Author:
#   Ron Savage <ron@savage.net.au>
#   http://savage.net.au/ImageMagick.html
#
# Licence:
#   Copyright (c) 1999-2002 Ron Savage
#
#   All Programs of mine are
#   'OSI Certified Open Source Software';
#   you can redistribute them and/or modify them
#   under the terms of the Artistic License,
#   a copy of which is available at:
#   http://www.opensource.org/licenses/index.html

use strict;
use warnings;

use CGI;
use CGI::Carp qw/fatalsToBrowser/;
use File::Basename;
use Image::Magick;

# -----------------------------------------------

sub css
{
    my($bg_color) = @_;

    return <<EOS;
<style type = 'text/css'>
<!--
.submit
{
background:$bg_color;
border-top-width:1px;
border-bottom-width:1px;
border-left-width:1px;
border-right-width:1px;
color:navy;
font-family:Verdana, Helvetica, sans-serif;
font-size:8pt;
font-weight:bold;
width:auto;
}
-->
</style>
EOS

}   # End of css.

# -----------------------------------------------
# Parameters:
#   $self           A CGI::DBI object.
#   $file_name      A user's file name,
#       as returned from a form submit.
#       However, if you look closely, you'll see
#       we use $file_name both as a string and as
#       a file handle. This may be the most
#       confusing aspect of uploading.
#
# Returns:
#   (@$content, $file_basename)

sub upload_file
{
    my($file_name) = @_;

    # Validate the file name.

    die('Error in CGI::DBI -> upload_file(): ' .
        'Please enter a real file name')
        if (! $file_name);

    # Split the path so we can use the last part.

    if ($file_name =~ /\\/)
    {
        fileparse_set_fstype("MSDOS");
    }
    elsif ($file_name =~ /:/)
    {
        fileparse_set_fstype("MacOS");
    }

    # NB: 1 of 2:
    # At this point, $file_name is a string.

    my($file_base, $file_path, $file_suffix)    =
        fileparse($file_name, '');
    my($file_basename)                          =
        "$file_base$file_suffix";
    my($content)                                =
        '';

    my($bytes, $buf);

    # NB: 2 of 2:
    # At this point $file_name is a file handle.

    $content .= $buf while
    (
        $bytes = read($file_name, $buf, 2048)
    );

    close($file_name);

    # Warning: The following deletes the original
    #   file, not the temp file.

    #unlink($file_name);

    ($content, $file_basename);

}   # End of upload_file.

# -----------------------------------------------

delete @ENV{'BASH_ENV', 'CDPATH', 'ENV', 'IFS',
    'PATH', 'SHELL'}; # For security.

my($q)              = CGI -> new();
my($file_name)      = $q -> param('file_name')  || '';
my($output_path)    = '/cgi-bin/ImageMagick';
my($html)           = [];
my($title)          = 'Image Viewer';
my($bg_color)       = '#80c0ff';

if ($file_name)
{
    my($content, $basename)         =
        upload_file($file_name);
    my($image_type)                 =
        ($basename =~ /^.+\.(.+)$/)
        ? $1
        : die("Unknown image type: $basename");
    my($temp_file_prefix)           = 'upload';
    my($document_root_name)         =
        '/apache/htdocs';
    my($temp_cgi_name)              =
        "/$temp_file_prefix.$image_type";
    my($temp_file_name)             =
        "$document_root_name$temp_cgi_name";
    my($new_cgi_name)               =
        "/new-$temp_file_prefix.$image_type";
    my($new_file_name)              =
        "$document_root_name$new_cgi_name";
    my($junk_cgi_name)              =
        "/junk-$temp_file_prefix.$image_type";
    my($junk_file_name)             =
        "$document_root_name$junk_cgi_name";

    open(OUT, "> $temp_file_name")
    || die("Can't open(> $temp_file_name): $!");
    binmode(OUT);
    print OUT $content;
    close(OUT);

    my($i)      = Image::Magick -> new();
    my($result) = $i -> Read($temp_file_name);
    warn "Read: $result" if $result;

    # Warning:
    #   ImageToBlob only works after the call to
    #   Set(magick => ...) or Write(...).

    $result = $i -> Set(magick => $image_type);
    warn "Write: $result" if $result;

    #$result = $i -> Write($junk_file_name);
    #warn "Write: $result" if $result;

    my(@blob) = $i -> ImageToBlob();

    open(OUT, "> $new_file_name")
    || die("Can't open(> $new_file_name): $!");
    binmode(OUT);
    print OUT $blob[0];
    close(OUT);

    push(@$html, $q -> th('Image file name') .
        $q -> td($file_name) );
    push(@$html, $q -> th('Image type') .
        $q -> td($image_type) );
    push(@$html, $q -> th('Temp file name') .
        $q -> td($temp_file_name) );
    push(@$html, $q -> th('Temp CGI name') .
        $q -> td($temp_cgi_name) );
    push(@$html, $q -> th('New file name') .
        $q -> td($new_file_name) );
    push(@$html, $q -> th('New CGI name') .
        $q -> td($new_cgi_name) );
    push(@$html, $q -> th('Junk file name') .
        $q -> td($junk_file_name) );
    push(@$html, $q -> th('Junk CGI name') .
        $q -> td($junk_cgi_name) );
    push(@$html, $q -> th('Native image') .
        $q -> td
        (
            $q -> img
            ({
                src => $temp_cgi_name,
                alt => $temp_cgi_name,
            })
        ) );
    push(@$html, $q -> th('ImageMagick image') .
        $q -> td
        (
            $q -> img
            ({
                src => $new_cgi_name,
                alt => $new_cgi_name,
            })
        ) );
    push(@$html, $q -> th('&nbsp;') .
        $q -> td('&nbsp;') );
    push(@$html, $q -> th('Main Menu') .
        $q -> td
        (
            $q -> a
            ({
                class   => 'submit',
                href    =>
                "$output_path/im-hax-menu.cgi",
            },  'im-hax-menu.cgi') ) );
}
else
{
    push(@$html, $q -> start_multipart_form
        ({
            action  => $q -> url(),
            name    => 'upload_form',
        }) );
    push(@$html, $q -> th('Image file') .
        $q -> td
        (
            $q -> filefield
            ({
                name    => 'file_name',
                size    => 40,
            })
        ) );
    push(@$html, $q -> th('&nbsp;') .
        $q -> td
        (
            $q -> submit({class => 'submit'})
        ) );
    push(@$html, $q -> end_form() );
}

print   $q -> header
        ({
        type => 'text/html;charset=ISO-8859-1',
        }),
        $q -> start_html({title => $title}),
        css($bg_color),
        $q -> h1({align => 'center'}, $title),
        $q -> table
        (
            {
                align   => 'center',
                bgColor => $bg_color,
            },
            $q -> Tr($html)
        ),
        $q -> end_html();
\end{verbatim}
\filbreak \subsubsection{im-hax-upload-2.cgi}
.\newline{}
\begin{verbatim}

#!/usr/bin/perl
#
# Name:
#   im-hax-upload-2.cgi.
#
# Purpose:
#   Upload an image and then display it.
#
# V 1.01 17-Jan-2002
# ------------------
# o Initial version
#
# Test environment:
#   OS: WinNT 4 SP 6a
#   Web server: Apache V 1.3.26
#   IM: V 5.4.7
#
# Warning:
#   ImageToBlob only works after the call to
#   Set(magick => ...) or Write(...).
#
# Input files:
#   Whatever you upload, eg smile.gif.
#
# Output files:
#   /apache/htdocs/upload.gif.
#   /apache/htdocs/junk-upload.gif.
#
# Note:
#   o tab = 4 spaces || die.
#   o Text reformatted to max 50 chars wide
#       so source can be converted to PDF
#
# Author:
#   Ron Savage <ron@savage.net.au>
#   http://savage.net.au/ImageMagick.html
#
# Licence:
#   Copyright (c) 1999-2002 Ron Savage
#
#   All Programs of mine are
#   'OSI Certified Open Source Software';
#   you can redistribute them and/or modify them
#   under the terms of the Artistic License,
#   a copy of which is available at:
#   http://www.opensource.org/licenses/index.html

use strict;
use warnings;

use CGI;
use CGI::Carp qw/fatalsToBrowser/;
use File::Basename;
use Image::Magick;

# -----------------------------------------------

sub css
{
    my($bg_color) = @_;

    return <<EOS;
<style type = 'text/css'>
<!--
.submit
{
background:$bg_color;
border-top-width:1px;
border-bottom-width:1px;
border-left-width:1px;
border-right-width:1px;
color:navy;
font-family:Verdana, Helvetica, sans-serif;
font-size:8pt;
font-weight:bold;
width:auto;
}
-->
</style>
EOS

}   # End of css.

# -----------------------------------------------
# Parameters:
#   $self           A CGI::DBI object.
#   $file_name      A user's file name,
#       as returned from a form submit.
#       However, if you look closely, you'll see
#       we use $file_name both as a string and as
#       a file handle. This may be the most
#       confusing aspect of uploading.
#
# Returns:
#   (@$content, $file_basename)

sub upload_file
{
    my($file_name) = @_;

    # Validate the file name.

    die('Error in CGI::DBI -> upload_file(): ' .
        'Please enter a real file name')
        if (! $file_name);

    # Split the path so we can use the last part.

    if ($file_name =~ /\\/)
    {
        fileparse_set_fstype("MSDOS");
    }
    elsif ($file_name =~ /:/)
    {
        fileparse_set_fstype("MacOS");
    }

    # NB: 1 of 2:
    # At this point, $file_name is a string.

    my($file_base, $file_path, $file_suffix)    =
        fileparse($file_name, '');
    my($file_basename)                          =
        "$file_base$file_suffix";
    my($content)                                =
        '';

    my($bytes, $buf);

    # NB: 2 of 2:
    # At this point $file_name is a file handle.

    $content .= $buf while
    (
        $bytes = read($file_name, $buf, 2048)
    );

    close($file_name);

    # Warning: The following deletes the original
    #   file, not the temp file.

    #unlink($file_name);

    ($content, $file_basename);

}   # End of upload_file.

# -----------------------------------------------

delete @ENV{'BASH_ENV', 'CDPATH', 'ENV', 'IFS',
    'PATH', 'SHELL'}; # For security.

my($q)              = CGI -> new();
my($file_name)      = $q -> param('file_name')  || '';
my($html)           = [];
my($title)          = 'Image Viewer';
my($bg_color)       = '#80c0ff';

if ($file_name)
{
    my($content, $basename)         =
        upload_file($file_name);
    my($image_type)                 =
        ($basename =~ /^.+\.(.+)$/)
        ? $1
        : die("Unknown image type: $basename");
    my($temp_file_prefix)           = 'upload';
    my($temp_cgi_name)              =
        "/$temp_file_prefix.$image_type";
    my($document_root_name)         =
        '/apache/htdocs';
    my($temp_file_name)             =
        "$document_root_name$temp_cgi_name";

    open(OUT, "> $temp_file_name")
    || die("Can't open(> $temp_file_name): $!");
    binmode(OUT);
    print OUT $content;
    close(OUT);

    my($i)      = Image::Magick -> new();
    my($result) = $i -> Read($temp_file_name);
    warn "Read: $result" if $result;

    # Warning:
    #   ImageToBlob only works after the call to
    #   Set(magick => ...) or Write(...).

    $result = $i -> Set(magick => $image_type);
    warn "Write: $result" if $result;

    #$result = $i -> Write($junk_file_name);
    #warn "Write: $result" if $result;

    my(@blob) = $i -> ImageToBlob();

    binmode STDOUT;

    print
    "Content-type: image/$image_type\r\n\r\n",
    $blob[0];
}
else
{
    push(@$html, $q -> start_multipart_form
    ({
        action  => $q -> url(),
        name    => 'upload_form',
    }) );
    push(@$html, $q -> th('Image file') .
        $q -> td
        (
            $q -> filefield
            ({
                name    => 'file_name',
                size    => 40,
            })
        ) );
    push(@$html, $q -> th('&nbsp;') .
        $q -> td
        (
            $q -> submit
            ({class => 'submit'})
        ) );
    push(@$html, $q -> end_form() );

    print
        $q -> header
        ({
        type => 'text/html;charset=ISO-8859-1',
        }),
        $q -> start_html({title => $title}),
        css($bg_color),
        $q -> h1({align => 'center'}, $title),
        $q -> table
        (
            {
                align   => 'center',
                bgColor => $bg_color,
            },
            $q -> Tr($html)
        ),
        $q -> end_html();
}
\end{verbatim}
\filbreak \subsubsection{im-hax-vertical-shift-1.pl}
.\newline{}
\begin{verbatim}

#!/usr/bin/perl
#
# Name:
#   im-hax-vertical-shift-1.pl.
#
# Purpose:
#   Shift an image down N pixels.
#
# V 1.01 20-Feb-2002
# ------------------
# o Output to same dir as other hax
# o Report names of output files
#
# V 1.00 17-Jan-2002
# ------------------
# o Initial version
#
# Test environment:
#   OS: WinNT 4 SP 6a
#   Web server: Apache V 1.3.26
#   IM: V 5.4.7

#
# Input files:
#   None.
#
# Output files:
#   /apache/htdocs/im-hax-vertical-shift-1.png
#   /apache/htdocs/im-hax-vertical-shift-2.png
#
# Note:
#   o tab = 4 spaces || die.
#   o Text reformatted to max 50 chars wide
#       so source can be converted to PDF
#
# Author:
#   Ron Savage <ron@savage.net.au>
#   http://savage.net.au/ImageMagick.html
#
# Licence:
#   Copyright (c) 1999-2002 Ron Savage
#
#   All Programs of mine are
#   'OSI Certified Open Source Software';
#   you can redistribute them and/or modify them
#   under the terms of the Artistic License,
#   a copy of which is available at:
#   http://www.opensource.org/licenses/index.html

use strict;
use warnings;

use Image::Magick;

# -----------------------------------------------

my($doc_root_name)      = '/apache/htdocs';
my($output_file_name_a) =
    "$doc_root_name/im-hax-vertical-shift-1.png";
my($output_file_name_b) =
    "$doc_root_name/im-hax-vertical-shift-2.png";
my($vertical_offset)    = shift || 50; # pixels.
my($width)              = 17;
my($height_1)           = 22;
my($height_2)           =
    $height_1 + $vertical_offset;
my($image_1)            =
    Image::Magick -> new
    (size => "${width}x$height_1"); # Remember:
my($image_2)            =           # No spaces
    Image::Magick -> new            # around the
    (size => "${width}x$height_2"); # 'x'.

my($result);

$result = $image_1 -> Read('xc:green');
warn $result if $result;
$result = $image_2 -> Read('xc:white');
warn $result if $result;

$result = $image_1 -> Border
(
    geometry    => '1x1',
    fill        => 'red',
);
warn $result if $result;
$result = $image_2 -> Border
(
    geometry    => '1x1',
    fill        => 'red',
);
warn $result if $result;

$result = $image_2 -> Composite
(
    compose => 'Over',
    image   => $image_1,
    x       => 0,
    y       => $vertical_offset,
);
warn $result if $result;

$result = $image_1 -> Write($output_file_name_a);
warn $result if $result;

print "Wrote: $output_file_name_a. \n";

$result = $image_2 -> Write($output_file_name_b);
warn $result if $result;

print "Wrote: $output_file_name_b. \n";
\end{verbatim}


