|
Packit |
78deda |
This file is a concatenation of two HTML files that John Walker wrote for the
|
|
Packit |
78deda |
original 'pnmshadow' program. It is not all relevant to the current
|
|
Packit |
78deda |
'ppmshadow' program.
|
|
Packit |
78deda |
|
|
Packit |
78deda |
<html>
|
|
Packit |
78deda |
<head>
|
|
Packit |
78deda |
<title>pnmshadow: How it Works</title>
|
|
Packit |
78deda |
|
|
Packit |
78deda |
</head>
|
|
Packit |
78deda |
|
|
Packit |
78deda |
<body>
|
|
Packit |
78deda |
|
|
Packit |
78deda |
<center>
|
|
Packit |
78deda |
|
|
Packit |
78deda |
</center>
|
|
Packit |
78deda |
|
|
Packit |
78deda |
|
|
Packit |
78deda |
|
|
Packit |
78deda |
|
|
Packit |
78deda |
This document describes the process, including PBMplus commands
|
|
Packit |
78deda |
and the intermediate images they create, by
|
|
Packit |
78deda |
which pnmshadow
|
|
Packit |
78deda |
adds black shadows to source images.
|
|
Packit |
78deda |
A companion document
|
|
Packit |
78deda |
describes how translucent shadows are created when the
|
|
Packit |
78deda |
-t option is specified.
|
|
Packit |
78deda |
|
|
Packit |
78deda |
The Starting Point
|
|
Packit |
78deda |
|
|
Packit |
78deda |
Let's start with the following source image, 536 pixels wide and 141
|
|
Packit |
78deda |
pixels high. We convert the image from whatever form in which
|
|
Packit |
78deda |
it was originally created (GIF, JPEG, etc.) to a PPM file before
|
|
Packit |
78deda |
processing it with pnmshadow.
|
|
Packit |
78deda |
|
|
Packit |
78deda |
|
|
Packit |
78deda |
<center>
|
|
Packit |
78deda |
|
|
Packit |
78deda |
|
|
Packit |
78deda |
|
|
Packit |
78deda |
|
|
Packit |
78deda |
</center>
|
|
Packit |
78deda |
|
|
Packit |
78deda |
The Blank Background
|
|
Packit |
78deda |
|
|
Packit |
78deda |
We start by determining the size of the input image with
|
|
Packit |
78deda |
pnmfile and then constructing an image with the same
|
|
Packit |
78deda |
size as the input image consisting entirely of the background
|
|
Packit |
78deda |
color, which is defined as the color of the pixel at the upper
|
|
Packit |
78deda |
left corner of the source image. This is performed by the
|
|
Packit |
78deda |
command:
|
|
Packit |
78deda |
|
|
Packit |
78deda |
|
|
Packit |
78deda |
|
|
Packit |
78deda |
pnmcut 0 0 1 1 ifile | pnmscale -xsize xsize -ysize ysize >fname-5.ppm
|
|
Packit |
78deda |
|
|
Packit |
78deda |
|
|
Packit |
78deda |
|
|
Packit |
78deda |
yielding the image:
|
|
Packit |
78deda |
|
|
Packit |
78deda |
|
|
Packit |
78deda |
<center>
|
|
Packit |
78deda |
|
|
Packit |
78deda |
|
|
Packit |
78deda |
|
|
Packit |
78deda |
|
|
Packit |
78deda |
</center>
|
|
Packit |
78deda |
|
|
Packit |
78deda |
The Positive Mask
|
|
Packit |
78deda |
|
|
Packit |
78deda |
A positive mask image is created in which all pixels of the background
|
|
Packit |
78deda |
color are set to white and all other pixels are black. This is accomplished
|
|
Packit |
78deda |
by subtracting the blank background image from the input (using the
|
|
Packit |
78deda |
<tt>-difference</tt> option on pnmarith to avoid clipping at
|
|
Packit |
78deda |
zero or the maximum pixel value), then inverting the result and
|
|
Packit |
78deda |
thresholding it to a monochrome bitmap.
|
|
Packit |
78deda |
|
|
Packit |
78deda |
|
|
Packit |
78deda |
|
|
Packit |
78deda |
pnmarith -difference ifile fname-5.ppm | pnminvert | ppmtopgm | pgmtopbm -thresh -value 1.0 >fname-1.ppm
|
|
Packit |
78deda |
|
|
Packit |
78deda |
|
|
Packit |
78deda |
|
|
Packit |
78deda |
This produces the following mask image.
|
|
Packit |
78deda |
|
|
Packit |
78deda |
|
|
Packit |
78deda |
<center>
|
|
Packit |
78deda |
|
|
Packit |
78deda |
|
|
Packit |
78deda |
|
|
Packit |
78deda |
|
|
Packit |
78deda |
</center>
|
|
Packit |
78deda |
|
|
Packit |
78deda |
The Blurred Image
|
|
Packit |
78deda |
|
|
Packit |
78deda |
Since we wish to simulate a shadow from a nearby extended
|
|
Packit |
78deda |
light source rather than a sharp shadow as cast by the
|
|
Packit |
78deda |
Sun, we need to prepare a blurred version of the original
|
|
Packit |
78deda |
image. If the -t option is not specified on
|
|
Packit |
78deda |
pnmshadow the shadow cast by an object of any color
|
|
Packit |
78deda |
is always black, so the positive mask serves as the source image
|
|
Packit |
78deda |
when preparing the shadow. A convolution kernel which averages
|
|
Packit |
78deda |
the number of pixels specified by the -b option
|
|
Packit |
78deda |
(default 11), written into the temporary file <tt>fname-2.ppm</tt>
|
|
Packit |
78deda |
in ASCII PGM format, and then the blurred image is created with
|
|
Packit |
78deda |
the command:
|
|
Packit |
78deda |
|
|
Packit |
78deda |
|
|
Packit |
78deda |
|
|
Packit |
78deda |
pnmconvol fname-2.ppm fname-1.ppm >fname-3.ppm
|
|
Packit |
78deda |
|
|
Packit |
78deda |
|
|
Packit |
78deda |
|
|
Packit |
78deda |
With the default blur setting of 11 pixels, the blurred image
|
|
Packit |
78deda |
below is generated.
|
|
Packit |
78deda |
|
|
Packit |
78deda |
|
|
Packit |
78deda |
<center>
|
|
Packit |
78deda |
|
|
Packit |
78deda |
|
|
Packit |
78deda |
|
|
Packit |
78deda |
|
|
Packit |
78deda |
</center>
|
|
Packit |
78deda |
|
|
Packit |
78deda |
Shadow on Background Color
|
|
Packit |
78deda |
|
|
Packit |
78deda |
Having generated the blurred shadow from the monochrome mask image,
|
|
Packit |
78deda |
it will consist of pixels ranging from white to black on a white
|
|
Packit |
78deda |
background. In order to preserve the background color in the
|
|
Packit |
78deda |
original image, we multiply the shadow by the blank background color
|
|
Packit |
78deda |
image created previously. White pixels take on the background color
|
|
Packit |
78deda |
and pixels belonging to the shadow are scaled to be relative to the
|
|
Packit |
78deda |
background.
|
|
Packit |
78deda |
|
|
Packit |
78deda |
|
|
Packit |
78deda |
|
|
Packit |
78deda |
pnmarith -multiply fname-3.ppm fname-5.ppm >fname-10.ppm
|
|
Packit |
78deda |
|
|
Packit |
78deda |
|
|
Packit |
78deda |
|
|
Packit |
78deda |
This yields the following shadow, with the background of the
|
|
Packit |
78deda |
original image.
|
|
Packit |
78deda |
|
|
Packit |
78deda |
|
|
Packit |
78deda |
<center>
|
|
Packit |
78deda |
|
|
Packit |
78deda |
|
|
Packit |
78deda |
|
|
Packit |
78deda |
|
|
Packit |
78deda |
</center>
|
|
Packit |
78deda |
|
|
Packit |
78deda |
Offset Shadow Clip
|
|
Packit |
78deda |
|
|
Packit |
78deda |
Shadows, even bogus ones like we're generating, usually look best when
|
|
Packit |
78deda |
cast by a light source diagonally displaced from the centre of the
|
|
Packit |
78deda |
shadow-casting object. To achieve this effect, we first cut a
|
|
Packit |
78deda |
rectangle from the blurred shadow image reduced in size by the
|
|
Packit |
78deda |
the number of pixels specified by the -b option
|
|
Packit |
78deda |
which default to half the blur (-b) setting. The
|
|
Packit |
78deda |
xsize and ysize arguments in the following
|
|
Packit |
78deda |
command are the size of the input image in pixels less the shadow
|
|
Packit |
78deda |
displacement in the respective axis.
|
|
Packit |
78deda |
|
|
Packit |
78deda |
|
|
Packit |
78deda |
|
|
Packit |
78deda |
pnmcut 0 0 xsize ysize fname-10.ppm >fname-4.ppm
|
|
Packit |
78deda |
|
|
Packit |
78deda |
|
|
Packit |
78deda |
|
|
Packit |
78deda |
The shadow clip is the identical to the shadow on background color, but
|
|
Packit |
78deda |
smaller by the offset in each direction.
|
|
Packit |
78deda |
|
|
Packit |
78deda |
|
|
Packit |
78deda |
<center>
|
|
Packit |
78deda |
|
|
Packit |
78deda |
|
|
Packit |
78deda |
|
|
Packit |
78deda |
|
|
Packit |
78deda |
</center>
|
|
Packit |
78deda |
|
|
Packit |
78deda |
Offset Shadow
|
|
Packit |
78deda |
|
|
Packit |
78deda |
Now we're ready to assemble the shadow offset by the specified number
|
|
Packit |
78deda |
of pixels. We do this by pasting the image cut in the previous step
|
|
Packit |
78deda |
into the blank background, yielding an image the same size as the
|
|
Packit |
78deda |
source image with the blurred shadow displaced to the right and
|
|
Packit |
78deda |
down.
|
|
Packit |
78deda |
|
|
Packit |
78deda |
|
|
Packit |
78deda |
|
|
Packit |
78deda |
pnmpaste -replace fname-4.ppm xoffset yoffset fname-5.ppm >fname-6.ppm
|
|
Packit |
78deda |
|
|
Packit |
78deda |
|
|
Packit |
78deda |
|
|
Packit |
78deda |
This gives the following result:
|
|
Packit |
78deda |
|
|
Packit |
78deda |
|
|
Packit |
78deda |
<center>
|
|
Packit |
78deda |
|
|
Packit |
78deda |
|
|
Packit |
78deda |
|
|
Packit |
78deda |
|
|
Packit |
78deda |
</center>
|
|
Packit |
78deda |
|
|
Packit |
78deda |
Inverse Mask
|
|
Packit |
78deda |
|
|
Packit |
78deda |
In order to stitch everything together, we need an inverse of the
|
|
Packit |
78deda |
mask prepared earlier--one where black pixels represent the background
|
|
Packit |
78deda |
and all other material is white. This is easily accomplished by
|
|
Packit |
78deda |
running the positive mask through pnminvert:
|
|
Packit |
78deda |
|
|
Packit |
78deda |
|
|
Packit |
78deda |
|
|
Packit |
78deda |
pnminvert fname-1.ppm >fname-7.ppm
|
|
Packit |
78deda |
|
|
Packit |
78deda |
|
|
Packit |
78deda |
|
|
Packit |
78deda |
yielding:
|
|
Packit |
78deda |
|
|
Packit |
78deda |
|
|
Packit |
78deda |
<center>
|
|
Packit |
78deda |
|
|
Packit |
78deda |
|
|
Packit |
78deda |
|
|
Packit |
78deda |
|
|
Packit |
78deda |
</center>
|
|
Packit |
78deda |
|
|
Packit |
78deda |
Masked Input Image
|
|
Packit |
78deda |
|
|
Packit |
78deda |
Now we use the inverse mask prepared in the previous step to create
|
|
Packit |
78deda |
an image containing all non-background pixels from the source image,
|
|
Packit |
78deda |
with background pixels set to black. We simply multiply the
|
|
Packit |
78deda |
inverse mask by the source image:
|
|
Packit |
78deda |
|
|
Packit |
78deda |
|
|
Packit |
78deda |
|
|
Packit |
78deda |
pnmarith -multiply ifile fname-7.ppm >fname-8.ppm
|
|
Packit |
78deda |
|
|
Packit |
78deda |
|
|
Packit |
78deda |
|
|
Packit |
78deda |
et voilĂ :
|
|
Packit |
78deda |
|
|
Packit |
78deda |
|
|
Packit |
78deda |
<center>
|
|
Packit |
78deda |
|
|
Packit |
78deda |
|
|
Packit |
78deda |
|
|
Packit |
78deda |
|
|
Packit |
78deda |
</center>
|
|
Packit |
78deda |
|
|
Packit |
78deda |
Shadow with Source Masked
|
|
Packit |
78deda |
|
|
Packit |
78deda |
Our last intermediate step before joining the image with its
|
|
Packit |
78deda |
shadow is preparing a shadow image with all non-background pixels
|
|
Packit |
78deda |
in the source image set to black. This ensures that when we add
|
|
Packit |
78deda |
the image and the shadow, the shadow will not override any pixel
|
|
Packit |
78deda |
in the source image.
|
|
Packit |
78deda |
|
|
Packit |
78deda |
|
|
Packit |
78deda |
|
|
Packit |
78deda |
pnmarith -multiply fname-6.ppm fname-1.ppm >fname-9.ppm
|
|
Packit |
78deda |
|
|
Packit |
78deda |
|
|
Packit |
78deda |
|
|
Packit |
78deda |
This is accomplished by multiplying the shadow by the positive
|
|
Packit |
78deda |
mask image, which sets all non-background pixels in the source
|
|
Packit |
78deda |
image to black:
|
|
Packit |
78deda |
|
|
Packit |
78deda |
|
|
Packit |
78deda |
<center>
|
|
Packit |
78deda |
|
|
Packit |
78deda |
|
|
Packit |
78deda |
|
|
Packit |
78deda |
|
|
Packit |
78deda |
</center>
|
|
Packit |
78deda |
|
|
Packit |
78deda |
The Final Product
|
|
Packit |
78deda |
|
|
Packit |
78deda |
At long last, we're ready to put together the pieces and deliver
|
|
Packit |
78deda |
the result to our ever-patient user. This amounts simply to
|
|
Packit |
78deda |
adding the masked input image (consisting solely of non-background
|
|
Packit |
78deda |
pixels from the original image) to the shadow with source masked
|
|
Packit |
78deda |
(in which all source pixels are black):
|
|
Packit |
78deda |
|
|
Packit |
78deda |
|
|
Packit |
78deda |
|
|
Packit |
78deda |
pnmarith -add fname-8.ppm fname-9.ppm
|
|
Packit |
78deda |
|
|
Packit |
78deda |
|
|
Packit |
78deda |
|
|
Packit |
78deda |
The resulting image, with shadow, is as follows:
|
|
Packit |
78deda |
|
|
Packit |
78deda |
|
|
Packit |
78deda |
<center>
|
|
Packit |
78deda |
|
|
Packit |
78deda |
|
|
Packit |
78deda |
|
|
Packit |
78deda |
|
|
Packit |
78deda |
</center>
|
|
Packit |
78deda |
|
|
Packit |
78deda |
Smooth Operator
|
|
Packit |
78deda |
|
|
Packit |
78deda |
Since many computer graphics programs create sharp edges on
|
|
Packit |
78deda |
text, it's often best to create an image at a greater resolution
|
|
Packit |
78deda |
than that used for presentation, then scale it to the final
|
|
Packit |
78deda |
resolution with a tool which resamples the image, thus
|
|
Packit |
78deda |
minimising jagged edges by averaging adjacent
|
|
Packit |
78deda |
pixels. Using the output of pnmshadow as the starting
|
|
Packit |
78deda |
point and scaling to half size with pnmscale, we arrive at
|
|
Packit |
78deda |
the following smoothed image, with shadow, ready to adorn a
|
|
Packit |
78deda |
Web page:
|
|
Packit |
78deda |
|
|
Packit |
78deda |
|
|
Packit |
78deda |
<center>
|
|
Packit |
78deda |
|
|
Packit |
78deda |
|
|
Packit |
78deda |
|
|
Packit |
78deda |
|
|
Packit |
78deda |
</center>
|
|
Packit |
78deda |
|
|
Packit |
78deda |
|
|
Packit |
78deda |
|
|
Packit |
78deda |
|
|
Packit |
78deda |
|
|
Packit |
78deda |
|
|
Packit |
78deda |
|
|
Packit |
78deda |
<address>
|
|
Packit |
78deda |
by John Walker
|
|
Packit |
78deda |
August 8th, 1997
|
|
Packit |
78deda |
</address>
|
|
Packit |
78deda |
|
|
Packit |
78deda |
</body>
|
|
Packit |
78deda |
</html>
|
|
Packit |
78deda |
<html>
|
|
Packit |
78deda |
<head>
|
|
Packit |
78deda |
<title>pnmshadow: How it Works in Translucent Mode</title>
|
|
Packit |
78deda |
|
|
Packit |
78deda |
</head>
|
|
Packit |
78deda |
|
|
Packit |
78deda |
<body>
|
|
Packit |
78deda |
|
|
Packit |
78deda |
<center>
|
|
Packit |
78deda |
|
|
Packit |
78deda |
</center>
|
|
Packit |
78deda |
|
|
Packit |
78deda |
|
|
Packit |
78deda |
|
|
Packit |
78deda |
|
|
Packit |
78deda |
|
|
Packit |
78deda |
This document describes the process, including PBMplus commands
|
|
Packit |
78deda |
and the intermediate images they create, by
|
|
Packit |
78deda |
which pnmshadow
|
|
Packit |
78deda |
adds translucent shadows when the -t command line
|
|
Packit |
78deda |
option is specified. A companion document
|
|
Packit |
78deda |
describes how the default black shadows are generated.
|
|
Packit |
78deda |
|
|
Packit |
78deda |
The Starting Point
|
|
Packit |
78deda |
|
|
Packit |
78deda |
Let's start with the following source image, 536 pixels wide and 141
|
|
Packit |
78deda |
pixels high. We convert the image from whatever form in which
|
|
Packit |
78deda |
it was originally created (GIF, JPEG, etc.) to a PPM file before
|
|
Packit |
78deda |
processing it with pnmshadow.
|
|
Packit |
78deda |
|
|
Packit |
78deda |
|
|
Packit |
78deda |
<center>
|
|
Packit |
78deda |
|
|
Packit |
78deda |
|
|
Packit |
78deda |
|
|
Packit |
78deda |
|
|
Packit |
78deda |
</center>
|
|
Packit |
78deda |
|
|
Packit |
78deda |
The Blank Background
|
|
Packit |
78deda |
|
|
Packit |
78deda |
We start by determining the size of the input image with
|
|
Packit |
78deda |
pnmfile and then constructing an image with the same
|
|
Packit |
78deda |
size as the input image consisting entirely of the background
|
|
Packit |
78deda |
color, which is defined as the color of the pixel at the upper
|
|
Packit |
78deda |
left corner of the source image. This is performed by the
|
|
Packit |
78deda |
command:
|
|
Packit |
78deda |
|
|
Packit |
78deda |
|
|
Packit |
78deda |
|
|
Packit |
78deda |
pnmcut 0 0 1 1 ifile | pnmscale -xsize xsize -ysize ysize >fname-5.ppm
|
|
Packit |
78deda |
|
|
Packit |
78deda |
|
|
Packit |
78deda |
|
|
Packit |
78deda |
yielding the image:
|
|
Packit |
78deda |
|
|
Packit |
78deda |
|
|
Packit |
78deda |
<center>
|
|
Packit |
78deda |
|
|
Packit |
78deda |
|
|
Packit |
78deda |
|
|
Packit |
78deda |
|
|
Packit |
78deda |
</center>
|
|
Packit |
78deda |
|
|
Packit |
78deda |
The Positive Mask
|
|
Packit |
78deda |
|
|
Packit |
78deda |
A positive mask image is created in which all pixels of the background
|
|
Packit |
78deda |
color are set to white and all other pixels are black. This is accomplished
|
|
Packit |
78deda |
by subtracting the blank background image from the input (using the
|
|
Packit |
78deda |
<tt>-difference</tt> option on pnmarith to avoid clipping at
|
|
Packit |
78deda |
zero or the maximum pixel value), then inverting the result and
|
|
Packit |
78deda |
thresholding it to a monochrome bitmap.
|
|
Packit |
78deda |
|
|
Packit |
78deda |
|
|
Packit |
78deda |
|
|
Packit |
78deda |
pnmarith -difference ifile fname-5.ppm | pnminvert | ppmtopgm | pgmtopbm -thresh -value 1.0 >fname-1.ppm
|
|
Packit |
78deda |
|
|
Packit |
78deda |
|
|
Packit |
78deda |
|
|
Packit |
78deda |
This produces the following mask image.
|
|
Packit |
78deda |
|
|
Packit |
78deda |
|
|
Packit |
78deda |
<center>
|
|
Packit |
78deda |
|
|
Packit |
78deda |
|
|
Packit |
78deda |
|
|
Packit |
78deda |
|
|
Packit |
78deda |
</center>
|
|
Packit |
78deda |
|
|
Packit |
78deda |
The Blurred Image
|
|
Packit |
78deda |
|
|
Packit |
78deda |
Since we wish to simulate a shadow from a nearby extended
|
|
Packit |
78deda |
light source rather than a sharp shadow as cast by the
|
|
Packit |
78deda |
Sun, we need to prepare a blurred version of the original
|
|
Packit |
78deda |
image.
|
|
Packit |
78deda |
A convolution kernel which averages
|
|
Packit |
78deda |
the number of pixels specified by the -b option
|
|
Packit |
78deda |
(default 11), written into the temporary file <tt>fname-2.ppm</tt>
|
|
Packit |
78deda |
in ASCII PGM format, and then the blurred image is created with
|
|
Packit |
78deda |
the command:
|
|
Packit |
78deda |
|
|
Packit |
78deda |
|
|
Packit |
78deda |
|
|
Packit |
78deda |
pnmconvol fname-2.ppm ifile >fname-10.ppm
|
|
Packit |
78deda |
|
|
Packit |
78deda |
|
|
Packit |
78deda |
|
|
Packit |
78deda |
With the default blur setting of 11 pixels, the blurred image
|
|
Packit |
78deda |
below is generated.
|
|
Packit |
78deda |
|
|
Packit |
78deda |
|
|
Packit |
78deda |
<center>
|
|
Packit |
78deda |
|
|
Packit |
78deda |
|
|
Packit |
78deda |
|
|
Packit |
78deda |
|
|
Packit |
78deda |
</center>
|
|
Packit |
78deda |
|
|
Packit |
78deda |
Offset Shadow Clip
|
|
Packit |
78deda |
|
|
Packit |
78deda |
Shadows, even bogus ones like we're generating, usually look best when
|
|
Packit |
78deda |
cast by a light source diagonally displaced from the centre of the
|
|
Packit |
78deda |
shadow-casting object. To achieve this effect, we first cut a
|
|
Packit |
78deda |
rectangle from the blurred shadow image reduced in size by the
|
|
Packit |
78deda |
the number of pixels specified by the -b option
|
|
Packit |
78deda |
which default to half the blur (-b) setting. The
|
|
Packit |
78deda |
xsize and ysize arguments in the following
|
|
Packit |
78deda |
command are the size of the input image in pixels less the shadow
|
|
Packit |
78deda |
displacement in the respective axis.
|
|
Packit |
78deda |
|
|
Packit |
78deda |
|
|
Packit |
78deda |
|
|
Packit |
78deda |
pnmcut 0 0 xsize ysize fname-10.ppm >fname-4.ppm
|
|
Packit |
78deda |
|
|
Packit |
78deda |
|
|
Packit |
78deda |
|
|
Packit |
78deda |
The shadow clip is the identical to the shadow on background color, but
|
|
Packit |
78deda |
smaller by the offset in each direction.
|
|
Packit |
78deda |
|
|
Packit |
78deda |
|
|
Packit |
78deda |
<center>
|
|
Packit |
78deda |
|
|
Packit |
78deda |
|
|
Packit |
78deda |
|
|
Packit |
78deda |
|
|
Packit |
78deda |
</center>
|
|
Packit |
78deda |
|
|
Packit |
78deda |
Offset Shadow
|
|
Packit |
78deda |
|
|
Packit |
78deda |
Now we're ready to assemble the shadow offset by the specified number
|
|
Packit |
78deda |
of pixels. We do this by pasting the image cut in the previous step
|
|
Packit |
78deda |
into the blank background, yielding an image the same size as the
|
|
Packit |
78deda |
source image with the blurred shadow displaced to the right and
|
|
Packit |
78deda |
down.
|
|
Packit |
78deda |
|
|
Packit |
78deda |
|
|
Packit |
78deda |
|
|
Packit |
78deda |
pnmpaste -replace fname-4.ppm xoffset yoffset fname-5.ppm >fname-6.ppm
|
|
Packit |
78deda |
|
|
Packit |
78deda |
|
|
Packit |
78deda |
|
|
Packit |
78deda |
This gives the following result:
|
|
Packit |
78deda |
|
|
Packit |
78deda |
|
|
Packit |
78deda |
<center>
|
|
Packit |
78deda |
|
|
Packit |
78deda |
|
|
Packit |
78deda |
|
|
Packit |
78deda |
|
|
Packit |
78deda |
</center>
|
|
Packit |
78deda |
|
|
Packit |
78deda |
Inverse Mask
|
|
Packit |
78deda |
|
|
Packit |
78deda |
In order to stitch everything together, we need an inverse of the
|
|
Packit |
78deda |
mask prepared earlier--one where black pixels represent the background
|
|
Packit |
78deda |
and all other material is white. This is easily accomplished by
|
|
Packit |
78deda |
running the positive mask through pnminvert:
|
|
Packit |
78deda |
|
|
Packit |
78deda |
|
|
Packit |
78deda |
|
|
Packit |
78deda |
pnminvert fname-1.ppm >fname-7.ppm
|
|
Packit |
78deda |
|
|
Packit |
78deda |
|
|
Packit |
78deda |
|
|
Packit |
78deda |
yielding:
|
|
Packit |
78deda |
|
|
Packit |
78deda |
|
|
Packit |
78deda |
<center>
|
|
Packit |
78deda |
|
|
Packit |
78deda |
|
|
Packit |
78deda |
|
|
Packit |
78deda |
|
|
Packit |
78deda |
</center>
|
|
Packit |
78deda |
|
|
Packit |
78deda |
Masked Input Image
|
|
Packit |
78deda |
|
|
Packit |
78deda |
Now we use the inverse mask prepared in the previous step to create
|
|
Packit |
78deda |
an image containing all non-background pixels from the source image,
|
|
Packit |
78deda |
with background pixels set to black. We simply multiply the
|
|
Packit |
78deda |
inverse mask by the source image:
|
|
Packit |
78deda |
|
|
Packit |
78deda |
|
|
Packit |
78deda |
|
|
Packit |
78deda |
pnmarith -multiply ifile fname-7.ppm >fname-8.ppm
|
|
Packit |
78deda |
|
|
Packit |
78deda |
|
|
Packit |
78deda |
|
|
Packit |
78deda |
et voilĂ :
|
|
Packit |
78deda |
|
|
Packit |
78deda |
|
|
Packit |
78deda |
<center>
|
|
Packit |
78deda |
|
|
Packit |
78deda |
|
|
Packit |
78deda |
|
|
Packit |
78deda |
|
|
Packit |
78deda |
</center>
|
|
Packit |
78deda |
|
|
Packit |
78deda |
Shadow with Source Masked
|
|
Packit |
78deda |
|
|
Packit |
78deda |
Our last intermediate step before joining the image with its
|
|
Packit |
78deda |
shadow is preparing a shadow image with all non-background pixels
|
|
Packit |
78deda |
in the source image set to black. This ensures that when we add
|
|
Packit |
78deda |
the image and the shadow, the shadow will not override any pixel
|
|
Packit |
78deda |
in the source image.
|
|
Packit |
78deda |
|
|
Packit |
78deda |
|
|
Packit |
78deda |
|
|
Packit |
78deda |
pnmarith -multiply fname-6.ppm fname-1.ppm >fname-9.ppm
|
|
Packit |
78deda |
|
|
Packit |
78deda |
|
|
Packit |
78deda |
|
|
Packit |
78deda |
This is accomplished by multiplying the shadow by the positive
|
|
Packit |
78deda |
mask image, which sets all non-background pixels in the source
|
|
Packit |
78deda |
image to black:
|
|
Packit |
78deda |
|
|
Packit |
78deda |
|
|
Packit |
78deda |
<center>
|
|
Packit |
78deda |
|
|
Packit |
78deda |
|
|
Packit |
78deda |
|
|
Packit |
78deda |
|
|
Packit |
78deda |
</center>
|
|
Packit |
78deda |
|
|
Packit |
78deda |
The Final Product
|
|
Packit |
78deda |
|
|
Packit |
78deda |
At long last, we're ready to put together the pieces and deliver
|
|
Packit |
78deda |
the image to our ever-patient user. This amounts simply to
|
|
Packit |
78deda |
adding the masked input image (consisting solely of non-background
|
|
Packit |
78deda |
pixels from the original image) to the shadow with source masked
|
|
Packit |
78deda |
(in which all source pixels are black):
|
|
Packit |
78deda |
|
|
Packit |
78deda |
|
|
Packit |
78deda |
|
|
Packit |
78deda |
pnmarith -add fname-8.ppm fname-9.ppm
|
|
Packit |
78deda |
|
|
Packit |
78deda |
|
|
Packit |
78deda |
|
|
Packit |
78deda |
The resulting image, with shadow, is as follows:
|
|
Packit |
78deda |
|
|
Packit |
78deda |
|
|
Packit |
78deda |
<center>
|
|
Packit |
78deda |
|
|
Packit |
78deda |
|
|
Packit |
78deda |
|
|
Packit |
78deda |
|
|
Packit |
78deda |
</center>
|
|
Packit |
78deda |
|
|
Packit |
78deda |
Smooth Operator
|
|
Packit |
78deda |
|
|
Packit |
78deda |
Since many computer graphics programs create sharp edges on
|
|
Packit |
78deda |
text, it's often best to create an image at a greater resolution
|
|
Packit |
78deda |
than that used for presentation, then scale it to the final
|
|
Packit |
78deda |
resolution with a tool which resamples the image, thus
|
|
Packit |
78deda |
minimising jagged edges by averaging adjacent
|
|
Packit |
78deda |
pixels. Using the output of pnmshadow as the starting
|
|
Packit |
78deda |
point and scaling to half size with pnmscale, we arrive at
|
|
Packit |
78deda |
the following smoothed image, with shadow, ready to adorn a
|
|
Packit |
78deda |
Web page:
|
|
Packit |
78deda |
|
|
Packit |
78deda |
|
|
Packit |
78deda |
<center>
|
|
Packit |
78deda |
|
|
Packit |
78deda |
|
|
Packit |
78deda |
|
|
Packit |
78deda |
|
|
Packit |
78deda |
</center>
|
|
Packit |
78deda |
|
|
Packit |
78deda |
|
|
Packit |
78deda |
|
|
Packit |
78deda |
|
|
Packit |
78deda |
|
|
Packit |
78deda |
|
|
Packit |
78deda |
|
|
Packit |
78deda |
<address>
|
|
Packit |
78deda |
by John Walker
|
|
Packit |
78deda |
August 8th, 1997
|
|
Packit |
78deda |
</address>
|
|
Packit |
78deda |
|
|
Packit |
78deda |
</body>
|
|
Packit |
78deda |
</html>
|