From 1fd361a1ea06e44286c213ca1f814f49306fdc43 Mon Sep 17 00:00:00 2001 From: giraffedata Date: Sat, 19 Aug 2006 03:12:28 +0000 Subject: Create Subversion repository git-svn-id: http://svn.code.sf.net/p/netpbm/code/trunk@1 9d0c8265-081b-0410-96cb-a4ca84ce46f8 --- editor/ppmshadow.doc | 627 +++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 627 insertions(+) create mode 100644 editor/ppmshadow.doc (limited to 'editor/ppmshadow.doc') diff --git a/editor/ppmshadow.doc b/editor/ppmshadow.doc new file mode 100644 index 00000000..1539c708 --- /dev/null +++ b/editor/ppmshadow.doc @@ -0,0 +1,627 @@ + + +pnmshadow: How it Works + + + + + +
+

pnmshadow: How it Works

+
+ +
+

+ +This document describes the process, including PBMplus commands +and the intermediate images they create, by +which pnmshadow +adds black shadows to source images. +A companion document +describes how translucent shadows are created when the +-t option is specified. + +

The Starting Point

+ +Let's start with the following source image, 536 pixels wide and 141 +pixels high. We convert the image from whatever form in which +it was originally created (GIF, JPEG, etc.) to a PPM file before +processing it with pnmshadow. + +

+

+ +
+Input image +
+
+ +

The Blank Background

+ +We start by determining the size of the input image with +pnmfile and then constructing an image with the same +size as the input image consisting entirely of the background +color, which is defined as the color of the pixel at the upper +left corner of the source image. This is performed by the +command: + +

+

+    pnmcut 0 0 1 1 ifile | pnmscale -xsize xsize -ysize ysize >fname-5.ppm
+
+

+ +yielding the image: + +

+

+ +
+Blank background image +
+
+ +

The Positive Mask

+ +A positive mask image is created in which all pixels of the background +color are set to white and all other pixels are black. This is accomplished +by subtracting the blank background image from the input (using the +-difference option on pnmarith to avoid clipping at +zero or the maximum pixel value), then inverting the result and +thresholding it to a monochrome bitmap. + +

+

+    pnmarith -difference ifile fname-5.ppm | pnminvert | ppmtopgm | pgmtopbm -thresh -value 1.0 >fname-1.ppm
+
+

+ +This produces the following mask image. + +

+

+ +
+Positive mask image +
+
+ +

The Blurred Image

+ +Since we wish to simulate a shadow from a nearby extended +light source rather than a sharp shadow as cast by the +Sun, we need to prepare a blurred version of the original +image. If the -t option is not specified on +pnmshadow the shadow cast by an object of any color +is always black, so the positive mask serves as the source image +when preparing the shadow. A convolution kernel which averages +the number of pixels specified by the -b option +(default 11), written into the temporary file fname-2.ppm +in ASCII PGM format, and then the blurred image is created with +the command: + +

+

+    pnmconvol fname-2.ppm fname-1.ppm >fname-3.ppm
+
+

+ +With the default blur setting of 11 pixels, the blurred image +below is generated. + +

+

+ +
+Blurred shadow +
+
+ +

Shadow on Background Color

+ +Having generated the blurred shadow from the monochrome mask image, +it will consist of pixels ranging from white to black on a white +background. In order to preserve the background color in the +original image, we multiply the shadow by the blank background color +image created previously. White pixels take on the background color +and pixels belonging to the shadow are scaled to be relative to the +background. + +

+

+    pnmarith -multiply fname-3.ppm fname-5.ppm >fname-10.ppm
+
+

+ +This yields the following shadow, with the background of the +original image. + +

+

+ +
+Shadow with background color +
+
+ +

Offset Shadow Clip

+ +Shadows, even bogus ones like we're generating, usually look best when +cast by a light source diagonally displaced from the centre of the +shadow-casting object. To achieve this effect, we first cut a +rectangle from the blurred shadow image reduced in size by the +the number of pixels specified by the -b option +which default to half the blur (-b) setting. The +xsize and ysize arguments in the following +command are the size of the input image in pixels less the shadow +displacement in the respective axis. + +

+

+    pnmcut 0 0 xsize ysize fname-10.ppm >fname-4.ppm
+
+

+ +The shadow clip is the identical to the shadow on background color, but +smaller by the offset in each direction. + +

+

+ +
+Offset shadow clip +
+
+ +

Offset Shadow

+ +Now we're ready to assemble the shadow offset by the specified number +of pixels. We do this by pasting the image cut in the previous step +into the blank background, yielding an image the same size as the +source image with the blurred shadow displaced to the right and +down. + +

+

+    pnmpaste -replace fname-4.ppm xoffset yoffset fname-5.ppm >fname-6.ppm
+
+

+ +This gives the following result: + +

+

+ +
+Offset shadow +
+
+ +

Inverse Mask

+ +In order to stitch everything together, we need an inverse of the +mask prepared earlier--one where black pixels represent the background +and all other material is white. This is easily accomplished by +running the positive mask through pnminvert: + +

+

+    pnminvert fname-1.ppm >fname-7.ppm
+
+

+ +yielding: + +

+

+ +
+Inverse mask +
+
+ +

Masked Input Image

+ +Now we use the inverse mask prepared in the previous step to create +an image containing all non-background pixels from the source image, +with background pixels set to black. We simply multiply the +inverse mask by the source image: + +

+

+    pnmarith -multiply ifile fname-7.ppm >fname-8.ppm
+
+

+ +et voilą: + +

+

+ +
+Masked Input Image +
+
+ +

Shadow with Source Masked

+ +Our last intermediate step before joining the image with its +shadow is preparing a shadow image with all non-background pixels +in the source image set to black. This ensures that when we add +the image and the shadow, the shadow will not override any pixel +in the source image. + +

+

+    pnmarith -multiply fname-6.ppm fname-1.ppm >fname-9.ppm
+
+

+ +This is accomplished by multiplying the shadow by the positive +mask image, which sets all non-background pixels in the source +image to black: + +

+

+ +
+Shadow with Source Masked +
+
+ +

The Final Product

+ +At long last, we're ready to put together the pieces and deliver +the result to our ever-patient user. This amounts simply to +adding the masked input image (consisting solely of non-background +pixels from the original image) to the shadow with source masked +(in which all source pixels are black): + +

+

+    pnmarith -add fname-8.ppm fname-9.ppm
+
+

+ +The resulting image, with shadow, is as follows: + +

+

+ +
+Output: Image with shadow +
+
+ +

Smooth Operator

+ +Since many computer graphics programs create sharp edges on +text, it's often best to create an image at a greater resolution +than that used for presentation, then scale it to the final +resolution with a tool which resamples the image, thus +minimising jagged edges by averaging adjacent +pixels. Using the output of pnmshadow as the starting +point and scaling to half size with pnmscale, we arrive at +the following smoothed image, with shadow, ready to adorn a +Web page: + +

+

+ +
+Half scale image with shadow +
+
+ +

How it works with translucent shadows

+

pnmshadow main page

+ +

+


+

+

+by John Walker
+August 8th, 1997 +
+ + + + + +pnmshadow: How it Works in Translucent Mode + + + + + +
+

pnmshadow: How it Works in Translucent Mode

+
+ +
+ +

+ +This document describes the process, including PBMplus commands +and the intermediate images they create, by +which pnmshadow +adds translucent shadows when the -t command line +option is specified. A companion document +describes how the default black shadows are generated. + +

The Starting Point

+ +Let's start with the following source image, 536 pixels wide and 141 +pixels high. We convert the image from whatever form in which +it was originally created (GIF, JPEG, etc.) to a PPM file before +processing it with pnmshadow. + +

+

+ +
+Input image +
+
+ +

The Blank Background

+ +We start by determining the size of the input image with +pnmfile and then constructing an image with the same +size as the input image consisting entirely of the background +color, which is defined as the color of the pixel at the upper +left corner of the source image. This is performed by the +command: + +

+

+    pnmcut 0 0 1 1 ifile | pnmscale -xsize xsize -ysize ysize >fname-5.ppm
+
+

+ +yielding the image: + +

+

+ +
+Blank background image +
+
+ +

The Positive Mask

+ +A positive mask image is created in which all pixels of the background +color are set to white and all other pixels are black. This is accomplished +by subtracting the blank background image from the input (using the +-difference option on pnmarith to avoid clipping at +zero or the maximum pixel value), then inverting the result and +thresholding it to a monochrome bitmap. + +

+

+    pnmarith -difference ifile fname-5.ppm | pnminvert | ppmtopgm | pgmtopbm -thresh -value 1.0 >fname-1.ppm
+
+

+ +This produces the following mask image. + +

+

+ +
+Positive mask image +
+
+ +

The Blurred Image

+ +Since we wish to simulate a shadow from a nearby extended +light source rather than a sharp shadow as cast by the +Sun, we need to prepare a blurred version of the original +image. +A convolution kernel which averages +the number of pixels specified by the -b option +(default 11), written into the temporary file fname-2.ppm +in ASCII PGM format, and then the blurred image is created with +the command: + +

+

+    pnmconvol fname-2.ppm ifile >fname-10.ppm
+
+

+ +With the default blur setting of 11 pixels, the blurred image +below is generated. + +

+

+ +
+Blurred shadow +
+
+ +

Offset Shadow Clip

+ +Shadows, even bogus ones like we're generating, usually look best when +cast by a light source diagonally displaced from the centre of the +shadow-casting object. To achieve this effect, we first cut a +rectangle from the blurred shadow image reduced in size by the +the number of pixels specified by the -b option +which default to half the blur (-b) setting. The +xsize and ysize arguments in the following +command are the size of the input image in pixels less the shadow +displacement in the respective axis. + +

+

+    pnmcut 0 0 xsize ysize fname-10.ppm >fname-4.ppm
+
+

+ +The shadow clip is the identical to the shadow on background color, but +smaller by the offset in each direction. + +

+

+ +
+Offset shadow clip +
+
+ +

Offset Shadow

+ +Now we're ready to assemble the shadow offset by the specified number +of pixels. We do this by pasting the image cut in the previous step +into the blank background, yielding an image the same size as the +source image with the blurred shadow displaced to the right and +down. + +

+

+    pnmpaste -replace fname-4.ppm xoffset yoffset fname-5.ppm >fname-6.ppm
+
+

+ +This gives the following result: + +

+

+ +
+Offset shadow +
+
+ +

Inverse Mask

+ +In order to stitch everything together, we need an inverse of the +mask prepared earlier--one where black pixels represent the background +and all other material is white. This is easily accomplished by +running the positive mask through pnminvert: + +

+

+    pnminvert fname-1.ppm >fname-7.ppm
+
+

+ +yielding: + +

+

+ +
+Inverse mask +
+
+ +

Masked Input Image

+ +Now we use the inverse mask prepared in the previous step to create +an image containing all non-background pixels from the source image, +with background pixels set to black. We simply multiply the +inverse mask by the source image: + +

+

+    pnmarith -multiply ifile fname-7.ppm >fname-8.ppm
+
+

+ +et voilą: + +

+

+ +
+Masked Input Image +
+
+ +

Shadow with Source Masked

+ +Our last intermediate step before joining the image with its +shadow is preparing a shadow image with all non-background pixels +in the source image set to black. This ensures that when we add +the image and the shadow, the shadow will not override any pixel +in the source image. + +

+

+    pnmarith -multiply fname-6.ppm fname-1.ppm >fname-9.ppm
+
+

+ +This is accomplished by multiplying the shadow by the positive +mask image, which sets all non-background pixels in the source +image to black: + +

+

+ +
+Shadow with Source Masked +
+
+ +

The Final Product

+ +At long last, we're ready to put together the pieces and deliver +the image to our ever-patient user. This amounts simply to +adding the masked input image (consisting solely of non-background +pixels from the original image) to the shadow with source masked +(in which all source pixels are black): + +

+

+    pnmarith -add fname-8.ppm fname-9.ppm
+
+

+ +The resulting image, with shadow, is as follows: + +

+

+ +
+Output: Image with translucent shadow +
+
+ +

Smooth Operator

+ +Since many computer graphics programs create sharp edges on +text, it's often best to create an image at a greater resolution +than that used for presentation, then scale it to the final +resolution with a tool which resamples the image, thus +minimising jagged edges by averaging adjacent +pixels. Using the output of pnmshadow as the starting +point and scaling to half size with pnmscale, we arrive at +the following smoothed image, with shadow, ready to adorn a +Web page: + +

+

+ +
+Half scale image with translucent shadow +
+
+ +

How it works with black shadows

+

pnmshadow main page

+ +

+


+

+

+by John Walker
+August 8th, 1997 +
+ + + -- cgit 1.4.1