/usr/bin/ppmshadow is in netpbm 2:10.0-15ubuntu2.
This file is owned by root:root, with mode 0o755.
The actual contents of the file can be viewed below.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 | #!/usr/bin/perl
# Change the path name in the line above to wherever Perl lives
# on your system. This script was tested with Perl 4.0, patch
# level 36.
# P P M S H A D O W
# by John Walker -- http://www.fourmilab.ch/
$version = 1.2;
# --> with minor changes by Bryan Henderson. See above web site for
# the real John Walker work, named pnmshadow.
# Pnmshadow is a brutal sledgehammer implemented in Perl which
# adds attractive shadows to images, as often seen in titles
# of World-Wide Web pages. This program does not actually
# *do* any image processing--it simply invokes components of
# Jef Poskanzer's PBMplus package (which must be present on
# the path when this script is run) to bludgeon the source
# image into a plausible result.
#
# This program is in the public domain.
#
#
# Process command line options
$convolve = 11; # Default blur convolution kernel size
$purge = 1; # Set to 0 to preserve intermediate files
$translucent = 0; # Default not translucent
while (@ARGV) {
$arg = shift;
if ((substr($arg, 0, 1) eq '-') && (length($arg) > 1)) {
$opt = substr($arg, 1, 1);
$opt =~ tr/A-Z/a-z/;
if ($opt eq 'b') { # -B n -- Blur size
if (!defined($convolve = shift)) {
die("Argument missing after -b option\n");
}
if (($convolve < 11) && (($convolve & 1) == 0)) {
$convolve++; # Round up even kernel specification
}
} elsif ($opt eq 'k') { # -K -- Keep temporary files
$purge = 0;
} elsif ($opt eq 't') { # -T -- Translucent image
$translucent = 1;
} elsif ($opt eq 'u' || $opt eq '?') {
print(STDERR "ppmshadow -- Add simulated shadow to anymap.\n");
if (defined $version) {
print(STDERR " Version $version.\n");
}
print(STDERR "Usage: ppmshadow [options] [pnmfile] \n");
print(STDERR "Options:\n");
print(STDERR " -B n Set blur size to n pixels\n");
print(STDERR " -K Keep intermediate temporary files from run\n");
print(STDERR " -T Cast shadows of translucent objects\n");
print(STDERR " -U Print this message\n");
print(STDERR " -X n Shift shadow n pixels to the right\n");
print(STDERR " -Y n Shift shadow n pixels down\n");
exit(0);
} elsif ($opt eq 'x') { # -X n -- X offset
if (!defined($xoffset = shift)) {
die("Argument missing after -x option\n");
}
if ($xoffset < 0) {
$xoffset = -$xoffset;
}
} elsif ($opt eq 'y') { # -Y n -- Y offset
if (!defined($yoffset = shift)) {
die("Argument missing after -x option\n");
}
if ($yoffset < 0) {
$yoffset = -$xoffset;
}
}
} else {
if (defined $ifile) {
die("Duplicate input file specification.");
}
$ifile = $arg; # Input file name
}
}
# Apply defaults for arguments not specified
if (!(defined $xoffset)) {
# Xoffset defaults to half the blur distance
$xoffset = int($convolve / 2);
}
if (!(defined $yoffset)) {
# Yoffset defaults to Xoffset, however specified
$yoffset = $xoffset;
}
use File::Temp "tempdir";
my $fname = tempdir("PPMshadow.XXXXXXX", CLEANUP => $purge)
|| die "Cant create tmpdir"; #219019
$stdin = 0;
if ((!(defined $ifile)) || ($ifile eq '-')) {
# Input default to standard input
$stdin = 1;
$ifile = "$fname/0.ppm";
system("cat >$fname/0.ppm");
}
# Determine the size of the source image
$a = `pnmfile $ifile`;
$a =~ m/.*\sP[BGP]M\s.*,\s*(\d*)\sby\s(\d*)/;
$xsize = $1;
$ysize = $2;
# Create a blank background bitmap the size of the source bitmap
system("pnmcut 0 0 1 1 $ifile | pnmscale -xsize $xsize -ysize $ysize >$fname/5.ppm");
# Create positive mask file from input image
system("pnmarith -difference $ifile $fname/5.ppm | pnminvert | ppmtopgm | pgmtopbm -thresh -value 1.0 >$fname/1.ppm");
# Create convolution kernel file to generate shadow
open(OF, ">$fname/2.ppm");
$ckern = $convolve <= 11 ? $convolve : 11;
printf(OF "P2\n$ckern $ckern\n%d\n", $ckern * $ckern * 2);
$a = ($ckern * $ckern) + 1;
for ($i = 0; $i < $ckern; $i++) {
for ($j = 0; $j < $ckern; $j++) {
printf(OF "%d%s", $a, ($j < ($ckern - 1)) ? " " : "\n");
}
}
close(OF);
if ($translucent) {
# Convolve the input colour image with the kernel
# to create a translucent shadow image.
system("pnmconvol $fname/2.ppm $ifile >$fname/10.ppm");
while ($ckern < $convolve) {
system("pnmsmooth $fname/10.ppm >$fname/10a.ppm");
system("mv $fname/10a.ppm $fname/10.ppm");
$ckern++;
}
} else {
# Convolve the positive mask with the kernel to create shadow
system("pnmconvol $fname/2.ppm $fname/1.ppm >$fname/3.ppm");
while ($ckern < $convolve) {
system("pnmsmooth $fname/3.ppm >$fname/3a.ppm");
system("mv $fname/3a.ppm $fname/3.ppm");
$ckern++;
}
# Multiply the shadow by the background colour
system("pnmarith -multiply $fname/3.ppm $fname/5.ppm >$fname/10.ppm");
}
# Cut an offset rectangle from the shadow image
$i = $xsize - $xoffset;
$j = $ysize - $yoffset;
system("pnmcut 0 0 $i $j $fname/10.ppm >$fname/4.ppm");
# Create offset shadow image
system("pnmpaste -replace $fname/4.ppm $xoffset $yoffset $fname/5.ppm >$fname/6.ppm");
# Create inverse mask
system("pnminvert $fname/1.ppm >$fname/7.ppm");
# Multiply original image by inverse mask
system("pnmarith -multiply $ifile $fname/7.ppm >$fname/8.ppm");
# Multiply shadow by mask
system("pnmarith -multiply $fname/6.ppm $fname/1.ppm >$fname/9.ppm");
# Add masked image and shadow to obtain result, which this
# last call on pnmarith sends to standard output.
system("pnmarith -add $fname/8.ppm $fname/9.ppm");
# temporary files are automatically removed by tempdir
|