about summary refs log tree commit diff
path: root/editor/ppmfade
diff options
context:
space:
mode:
Diffstat (limited to 'editor/ppmfade')
-rwxr-xr-xeditor/ppmfade631
1 files changed, 386 insertions, 245 deletions
diff --git a/editor/ppmfade b/editor/ppmfade
index dcd7bf26..4e2c8367 100755
--- a/editor/ppmfade
+++ b/editor/ppmfade
@@ -35,12 +35,22 @@ exec perl -w -x -S -- "$0" "$@"
 #
 #  Inspired by the program Pbmfade by Wesley C. Barris of AHPCRC,
 #  Minnesota Supercomputer Center, Inc. January 7, 1994.  Pbmfade does
-#  much the same thing, but handles non-Netpbm formats too, and is 
+#  much the same thing, but handles non-Netpbm formats too, and is
 #  implemented in a more primitive language.
 #
 ##############################################################################
 use strict;
 
+use File::Temp;
+
+#
+#  Define a couple linear ramps.
+#
+# We don't use element 0 of these arrays.
+my @spline10 = (0, 0, 0.11, 0.22, 0.33, 0.44, 0.55, 0.66, 0.77, 0.88, 1.0);
+my @spline20 = (0, 0, 0.05, 0.11, 0.16, 0.21, 0.26, 0.32, 0.37, 0.42, 0.47,
+                0.53, 0.58, 0.63, 0.69, 0.74, 0.79, 0.84, 0.89, 0.95, 1.0);
+
 sub doVersionHack($) {
     my ($argvR) = @_;
 
@@ -52,280 +62,411 @@ sub doVersionHack($) {
     }
 }
 
+my $tmpdir;
 
+$tmpdir = File::Temp::tempdir("ppmfade.XXXXXX", CLEANUP => 1);
 
-my $SPREAD =  1;
-my $SHIFT =   2;
-my $RELIEF =  3;
-my $OIL =     4;
-my $EDGE =    5;
-my $BENTLEY = 6;
-my $BLOCK =   7;
-my $MIX =     8;
-#
-#  Set some defaults.
-#
-my $nframes = 30;			# total number of files created (1 sec)
-my $first_file = "undefined";
-my $last_file = "undefined";
-my $base_name = "fade";		# default base name of output files
-my $image = "ppm";		# default output storage format
-my $mode = $SPREAD;		# default fading mode
+sub commandLineArgs() {
 
-doVersionHack(\@ARGV);
+    my ($firstFileNm, $lastFileNm, $mode, $baseNm);
 
-my $n;  # argument number
+    for (my $i = 0; $i < @ARGV; ++$i) {
+        my $arg = $ARGV[$i];
 
-for ($n = 0; $n < @ARGV; $n++) {
-    if ("$ARGV[$n]" eq "-f") {
-        $n++;
-        $first_file = $ARGV[$n];
-        if (-e $first_file) {
+        if (0) {
+        } elsif ($arg eq "-f") {
+            ++$i;
+            $firstFileNm = $ARGV[$i];
+        } elsif ($arg eq "-l") {
+            ++$i;
+            $lastFileNm = $ARGV[$i];
+        } elsif ($arg eq "-base") {
+            ++$i;
+            $baseNm = $ARGV[$i];
+        } elsif ($arg eq "-spread") {
+            $mode = 'SPREAD';
+        } elsif ($arg eq "-shift") {
+            $mode = 'SHIFT';
+        } elsif ($arg eq "-relief") {
+            $mode = 'RELIEF';
+        } elsif ($arg eq "-oil") {
+            $mode = 'OIL';
+        } elsif ($arg eq "-edge") {
+            $mode = 'EDGE';
+        } elsif ($arg eq "-bentley") {
+            $mode ='BENTLEY';
+        } elsif ($arg eq "-block") {
+            $mode = 'BLOCK';
+        } elsif ($arg eq "-mix") {
+            $mode = 'MIX';
         } else {
-            print "I can't find first file '$first_file'\n";
-            exit 20;
+            if (substr($arg, 0, 1) eq '-') {
+                   print STDERR ("Unknown option '$arg'.  " .
+                                 "We understand -f, -l, -base, " .
+                                 "-spread, -shift, -relief, -oil, -edge, " .
+                                 "-bentley, -block, and -mix\n");
+            } else {
+                print STDERR ("There are no non-option arguments possible.  " .
+                              "You specified '$arg'\n");
+            }
+            exit 100;
         }
-    } elsif ($ARGV[$n] eq "-l") {
-        $n++;
-        $last_file = $ARGV[$n];
-        if (-e $last_file) {
+    }
+
+    if (!defined($firstFileNm) && !defined($lastFileNm)) {
+        print STDERR ("You must specify -f or -l (or both)\n");
+        exit 90;
+    }
+
+    if (!defined($mode)) {
+        $mode = 'SPREAD';
+    }
+
+    if (!defined($baseNm)) {
+        $baseNm = 'fade';
+    }
+
+    return $mode, $firstFileNm, $lastFileNm, $baseNm;
+}
+
+
+
+sub imageDimensions($$) {
+    my ($firstFileNm, $lastFileNm) = @_;
+
+    my ($width, $height);
+
+    if (defined($firstFileNm)) {
+        if ((`pnmfile $firstFileNm` =~ m{\b(\d+)\sby\s(\d+)} )) {
+            $width = $1; $height = $2;
         } else {
-            print "I can't find last file '$last_file'\n";
-            exit 20;
+            print STDERR
+                ("Unrecognized results from pnmfile on $firstFileNm.\n");
+            exit(50);
         }
-    } elsif ($ARGV[$n] eq "-base") {
-        $n++;
-        $base_name = $ARGV[$n];
-    } elsif ($ARGV[$n] eq "-spread") {
-        $mode = $SPREAD;
-    } elsif ($ARGV[$n] eq "-shift") {
-        $mode = $SHIFT;
-    } elsif ($ARGV[$n] eq "-relief") {
-        $mode = $RELIEF;
-    } elsif ($ARGV[$n] eq "-oil") {
-        $mode = $OIL;
-    } elsif ("$ARGV[$n]" eq "-edge") {
-        $mode = $EDGE;
-    } elsif ("$ARGV[$n]" eq "-bentley") {
-        $mode = $BENTLEY;
-    } elsif ("$ARGV[$n]" eq "-block") {
-        $mode = $BLOCK;
-    } elsif ("$ARGV[$n]" eq "-mix") {
-        $mode = $MIX;
     } else {
-        print "Unknown argument: $ARGV[$n]\n";
-        exit 100;
-    } 
+        # $lastFileNm is defined
+        if ((`pnmfile $lastFileNm` =~ m{\b(\d+)\sby\s(\d+)} )) {
+            $width = $1; $height = $2;
+        } else {
+            print STDERR
+                ("Unrecognized results from pnmfile on $firstFileNm.\n");
+            exit(50);
+        }
+    }
+    return $width, $height;
 }
-#
-#  Define a couple linear ramps.
-#
-# We don't use element 0 of these arrays.
-my @spline10 = (0, 0, 0.11, 0.22, 0.33, 0.44, 0.55, 0.66, 0.77, 0.88, 1.0);
-my @spline20 = (0, 0, 0.05, 0.11, 0.16, 0.21, 0.26, 0.32, 0.37, 0.42, 0.47, 
-                0.53, 0.58, 0.63, 0.69, 0.74, 0.79, 0.84, 0.89, 0.95, 1.0);
-#
-#  Just what are we supposed to do?
-#
-my ($height, $width);    # width and height of our frames
-if ($first_file ne "undefined") {
-    if ((`pnmfile $first_file` =~ m{\b(\d+)\sby\s(\d+)} )) { 
-        $width = $1; $height = $2;
+
+
+
+sub spreadOne($) {
+    my ($frameNum) = @_;
+
+    if ($frameNum <= 10) {
+        my $n = $spline20[$frameNum] * 100;
+        system("ppmspread $n $tmpdir/first.ppm >$tmpdir/this.ppm");
+    } elsif ($frameNum <= 20) {
+        my $n;
+        $n = $spline20[$frameNum] * 100;
+        system("ppmspread $n $tmpdir/first.ppm >$tmpdir/junk1a.ppm");
+        $n = (1-$spline20[$frameNum-10]) * 100;
+        system("ppmspread $n $tmpdir/last.ppm >$tmpdir/junk2a.ppm");
+        $n = $spline10[$frameNum-10];
+        system("ppmmix $n $tmpdir/junk1a.ppm $tmpdir/junk2a.ppm " .
+               ">$tmpdir/this.ppm");
     } else {
-        print("Unrecognized results from pnmfile on $first_file.\n");
-        exit(50);
+        my $n = (1-$spline20[$frameNum-10])*100;
+        system("ppmspread $n $tmpdir/last.ppm >$tmpdir/this.ppm");
     }
-} elsif ($last_file ne "undefined") {
-    if ((`pnmfile $last_file` =~ m{\b(\d+)\sby\s(\d+)} )) { 
-        $width = $1; $height = $2;
+}
+
+
+
+sub shiftOne($) {
+    my ($frameNum) = @_;
+
+    if ($frameNum <= 10) {
+        my $n = $spline20[$frameNum] * 100;
+        system("ppmshift $n $tmpdir/first.ppm >$tmpdir/this.ppm");
+    } elsif ($frameNum <= 20) {
+        my $n;
+        $n = $spline20[$frameNum] * 100;
+        system("ppmshift $n $tmpdir/first.ppm >$tmpdir/junk1a.ppm");
+        $n = (1-$spline20[$frameNum-10])*100;
+        system("ppmshift $n $tmpdir/last.ppm >$tmpdir/junk2a.ppm");
+        $n = $spline10[$frameNum-10];
+        system("ppmmix $n $tmpdir/junk1a.ppm $tmpdir/junk2a.ppm " .
+               ">$tmpdir/this.ppm");
     } else {
-        print("Unrecognized results from pnmfile on $first_file.\n");
-        exit(50);
+        my $n = (1-$spline20[$frameNum-10]) * 100;
+        system("ppmshift $n $tmpdir/last.ppm >$tmpdir/this.ppm");
     }
-} else {
-    print("ppmfade:  You must specify -f or -l (or both)\n");
-    exit(90);
 }
 
-print("Frames are " . $width . "W x " . $height . "H\n");
 
-if ($first_file eq "undefined") {
-    print "Fading from black to ";
-    system("ppmmake \\#000 $width $height >junk1$$.ppm");
-} else {
-    print "Fading from $first_file to ";
-    system("cp", $first_file, "junk1$$.ppm");
+
+sub reliefOne($) {
+    my ($frameNum) = @_;
+
+    if ($frameNum == 1) {
+        system("ppmrelief $tmpdir/first.ppm >$tmpdir/junk1r.ppm");
+    }
+    if ($frameNum <= 10) {
+        my $n = $spline10[$frameNum];
+        system("ppmmix $n $tmpdir/first.ppm $tmpdir/junk1r.ppm " .
+               ">$tmpdir/this.ppm");
+    } elsif ($frameNum <= 20) {
+        my $n = $spline10[$frameNum-10];
+        system("ppmmix $n $tmpdir/junk1r.ppm $tmpdir/junk2r.ppm " .
+               ">$tmpdir/this.ppm");
+    } else {
+        my $n = $spline10[$frameNum-20];
+        system("ppmmix $n $tmpdir/junk2r.ppm $tmpdir/last.ppm " .
+               ">$tmpdir/this.ppm");
+    }
+    if ($frameNum == 10) {
+        system("ppmrelief $tmpdir/last.ppm >$tmpdir/junk2r.ppm");
+    }
 }
 
-if ($last_file eq "undefined") {
-    print "black.\n";
-    system("ppmmake \\#000 $width $height >junk2$$.ppm");
-} else {
-    print "$last_file\n";
-    system("cp", $last_file, "junk2$$.ppm");
+
+
+sub oilOne($) {
+    my ($frameNum) = @_;
+
+    if ($frameNum == 1) {
+        system("ppmtopgm $tmpdir/first.ppm | pgmoil >$tmpdir/junko.ppm");
+        system("rgb3toppm " .
+               "$tmpdir/junko.ppm $tmpdir/junko.ppm $tmpdir/junko.ppm " .
+               ">$tmpdir/junk1o.ppm");
+    }
+    if ($frameNum <= 10) {
+        my $n = $spline10[$frameNum];
+        system("ppmmix $n $tmpdir/first.ppm $tmpdir/junk1o.ppm " .
+               ">$tmpdir/this.ppm");
+    } elsif ($frameNum <= 20) {
+        my $n = $spline10[$frameNum-10];
+        system("ppmmix $n $tmpdir/junk1o.ppm $tmpdir/junk2o.ppm " .
+               ">$tmpdir/this.ppm");
+    } else {
+        my $n = $spline10[$frameNum-20];
+        system("ppmmix $n $tmpdir/junk2o.ppm $tmpdir/last.ppm " .
+               ">$tmpdir/this.ppm");
+    }
+    if ($frameNum == 10) {
+        system("ppmtopgm $tmpdir/last.ppm | pgmoil >$tmpdir/junko.ppm");
+        system("rgb3toppm " .
+               "$tmpdir/junko.ppm $tmpdir/junko.ppm $tmpdir/junko.ppm " .
+               ">$tmpdir/junk2o.ppm");
+    }
 }
 
-#
-#  Perform the fade.
-#
 
-# Here's what our temporary files are:
-#   junk1$$.ppm: The original (fade-from) image
-#   junk2$$.ppm: The target (fade-from) image
-#   junk3$$.ppm: The frame of the fade for the current iteration of the 
-#                the for loop.
-#   junk1a$$.ppm: If the fade involves a ppmmix sequence from one intermediate
-#                 image to another, this is the first frame of that 
-#                 sequence.
-#   junk2a$$.ppm: This is the last frame of the above-mentioned ppmmix sequence
-
-my $i;    # Frame number
-for ($i = 1; $i <= $nframes; $i++) {
-    print("Creating $i of $nframes...\n");
-    if ($mode eq $SPREAD) {
-        if ($i <= 10) {
-            my $n = $spline20[$i] * 100;
-            system("ppmspread $n junk1$$.ppm >junk3$$.ppm");
-        } elsif ($i <= 20) {
-            my $n;
-            $n = $spline20[$i] * 100;
-            system("ppmspread $n junk1$$.ppm >junk1a$$.ppm");
-            $n = (1-$spline20[$i-10]) * 100;
-            system("ppmspread $n junk2$$.ppm >junk2a$$.ppm");
-            $n = $spline10[$i-10];
-            system("ppmmix $n junk1a$$.ppm junk2a$$.ppm >junk3$$.ppm");
-        } else {
-            my $n = (1-$spline20[$i-10])*100;
-            system("ppmspread $n junk2$$.ppm >junk3$$.ppm");
-        }
-    } elsif ($mode eq $SHIFT) {
-        if ($i <= 10) {
-            my $n = $spline20[$i] * 100;
-            system("ppmshift $n junk1$$.ppm >junk3$$.ppm");
-        } elsif ($i <= 20) {
-            my $n;
-            $n = $spline20[$i] * 100;
-            system("ppmshift $n junk1$$.ppm >junk1a$$.ppm");
-            $n = (1-$spline20[$i-10])*100;
-            system("ppmshift $n junk2$$.ppm >junk2a$$.ppm");
-            $n = $spline10[$i-10];
-            system("ppmmix $n junk1a$$.ppm junk2a$$.ppm >junk3$$.ppm");
-        } else {
-            my $n = (1-$spline20[$i-10]) * 100;
-            system("ppmshift $n junk2$$.ppm >junk3$$.ppm");
-        }
-    } elsif ($mode eq $RELIEF) {
-        if ($i == 1) {
-            system("ppmrelief junk1$$.ppm >junk1r$$.ppm");
-        }
-        if ($i <= 10) {
-            my $n = $spline10[$i];
-            system("ppmmix $n junk1$$.ppm junk1r$$.ppm >junk3$$.ppm");
-        } elsif ($i <= 20) {
-            my $n = $spline10[$i-10];
-            system("ppmmix $n junk1r$$.ppm junk2r$$.ppm >junk3$$.ppm");
-        } else {
-            my $n = $spline10[$i-20];
-            system("ppmmix $n junk2r$$.ppm junk2$$.ppm >junk3$$.ppm");
-        }
-        if ($i == 10) {
-            system("ppmrelief junk2$$.ppm >junk2r$$.ppm");
-        }
-    } elsif ($mode eq $OIL) {
-        if ($i == 1) {
-            system("ppmtopgm junk1$$.ppm | pgmoil >junko$$.ppm");
-            system("rgb3toppm junko$$.ppm junko$$.ppm junko$$.ppm " .
-                   ">junk1o$$.ppm");
-        }
-        if ($i <= 10) {
-            my $n = $spline10[$i];
-            system("ppmmix $n junk1$$.ppm junk1o$$.ppm >junk3$$.ppm");
-        } elsif ($i <= 20) {
-            my $n = $spline10[$i-10];
-            system("ppmmix $n junk1o$$.ppm junk2o$$.ppm >junk3$$.ppm");
-        } else {
-            my $n = $spline10[$i-20];
-            system("ppmmix $n junk2o$$.ppm junk2$$.ppm >junk3$$.ppm");
-        }
-        if ($i == 10) {
-            system("ppmtopgm junk2$$.ppm | pgmoil >junko$$.ppm");
-            system("rgb3toppm junko$$.ppm junko$$.ppm junko$$.ppm " .
-                   ">junk2o$$.ppm");
-        }
-    } elsif ($mode eq $EDGE) {
-        if ($i == 1) {
-            system("ppmtopgm junk1$$.ppm | pgmedge >junko$$.ppm");
-            system("rgb3toppm junko$$.ppm junko$$.ppm junko$$.ppm " .
-                   ">junk1o$$.ppm");
-        }
-        if ($i <= 10) {
-            my $n = $spline10[$i];
-            system("ppmmix $n junk1$$.ppm junk1o$$.ppm >junk3$$.ppm");
-        } elsif ($i <= 20) {
-            my $n = $spline10[$i-10];
-            system("ppmmix $n junk1o$$.ppm junk2o$$.ppm >junk3$$.ppm");
-        } else {
-            my $n = $spline10[$i-20];
-            system("ppmmix $n junk2o$$.ppm junk2$$.ppm >junk3$$.ppm");
-        }
-        if ($i == 10) {
-            system("ppmtopgm junk2$$.ppm | pgmedge >junko$$.ppm");
-            system("rgb3toppm junko$$.ppm junko$$.ppm junko$$.ppm " .
-                   ">junk2o$$.ppm");
-        } 
-    } elsif ($mode eq $BENTLEY) {
-        if ($i == 1) {
-            system("ppmtopgm junk1$$.ppm | pgmbentley >junko$$.ppm");
-            system("rgb3toppm junko$$.ppm junko$$.ppm junko$$.ppm " .
-                   ">junk1o$$.ppm");
-        }
-        if ($i <= 10) {
-            my $n = $spline10[$i];
-            system("ppmmix $n junk1$$.ppm junk1o$$.ppm >junk3$$.ppm");
-        } elsif ($i <= 20) {
-            my $n = $spline10[$i-10];
-            system("ppmmix $n junk1o$$.ppm junk2o$$.ppm >junk3$$.ppm");
-        } else {
-            my $n = $spline10[$i-20];
-            system("ppmmix $n junk2o$$.ppm junk2$$.ppm >junk3$$.ppm");
-        }
-        if ($i == 10) {
-            system("ppmtopgm junk2$$.ppm | pgmbentley >junko$$.ppm");
-            system("rgb3toppm junko$$.ppm junko$$.ppm junko$$.ppm " .
-                   ">junk2o$$.ppm");
-        }
-    } elsif ($mode eq $BLOCK) {
-        if ($i <= 10) {
-            my $n = 1 - 1.9*$spline20[$i];
-            system("pamscale $n junk1$$.ppm | " .
-                   "pamscale -width $width -height $height >junk3$$.ppm");
-        } elsif ($i <= 20) {
-            my $n = $spline10[$i-10];
-            system("ppmmix $n junk1a$$.ppm junk2a$$.ppm >junk3$$.ppm");
-        } else {
-            my $n = 1 - 1.9*$spline20[31-$i];
-            system("pamscale $n junk2$$.ppm | " .
-                   "pamscale -width $width -height $height >junk3$$.ppm");
+
+sub edgeOne($) {
+    my ($frameNum) = @_;
+
+    if ($frameNum == 1) {
+        system("ppmtopgm $tmpdir/first.ppm | pgmedge >$tmpdir/junko.ppm");
+        system("rgb3toppm " .
+               "$tmpdir/junko.ppm $tmpdir/junko.ppm $tmpdir/junko.ppm " .
+               ">$tmpdir/junk1o.ppm");
+    }
+    if ($frameNum <= 10) {
+        my $n = $spline10[$frameNum];
+        system("ppmmix $n $tmpdir/first.ppm $tmpdir/junk1o.ppm " .
+               ">$tmpdir/this.ppm");
+    } elsif ($frameNum <= 20) {
+        my $n = $spline10[$frameNum-10];
+        system("ppmmix $n $tmpdir/junk1o.ppm $tmpdir/junk2o.ppm " .
+               ">$tmpdir/this.ppm");
+    } else {
+        my $n = $spline10[$frameNum-20];
+        system("ppmmix $n $tmpdir/junk2o.ppm $tmpdir/last.ppm " .
+               ">$tmpdir/this.ppm");
+    }
+    if ($frameNum == 10) {
+        system("ppmtopgm $tmpdir/last.ppm | pgmedge >$tmpdir/junko.ppm");
+        system("rgb3toppm " .
+               "$tmpdir/junko.ppm $tmpdir/junko.ppm $tmpdir/junko.ppm " .
+               ">$tmpdir/junk2o.ppm");
+    }
+}
+
+
+
+sub bentleyOne($) {
+    my ($frameNum) = @_;
+
+    if ($frameNum == 1) {
+        system("ppmtopgm $tmpdir/first.ppm | pgmbentley >$tmpdir/junko.ppm");
+        system("rgb3toppm " .
+               "$tmpdir/junko.ppm $tmpdir/junko.ppm $tmpdir/junko.ppm " .
+               ">$tmpdir/junk1o.ppm");
+    }
+    if ($frameNum <= 10) {
+        my $n = $spline10[$frameNum];
+        system("ppmmix $n $tmpdir/first.ppm $tmpdir/junk1o.ppm " .
+               ">$tmpdir/this.ppm");
+    } elsif ($frameNum <= 20) {
+        my $n = $spline10[$frameNum-10];
+        system("ppmmix $n $tmpdir/junk1o.ppm $tmpdir/junk2o.ppm " .
+               ">$tmpdir/this.ppm");
+    } else {
+        my $n = $spline10[$frameNum-20];
+        system("ppmmix $n $tmpdir/junk2o.ppm $tmpdir/last.ppm " .
+               ">$tmpdir/this.ppm");
+    }
+    if ($frameNum == 10) {
+        system("ppmtopgm $tmpdir/last.ppm | pgmbentley " .
+               ">$tmpdir/junko.ppm");
+        system("rgb3toppm $tmpdir/junko.ppm $tmpdir/junko.ppm " .
+               "$tmpdir/junko.ppm " .
+               ">$tmpdir/junk2o.ppm");
+    }
+}
+
+
+
+sub blockOne($$$) {
+    my ($frameNum, $width, $height) = @_;
+
+    if ($frameNum <= 10) {
+        my $n = 1 - 1.9*$spline20[$frameNum];
+        system("pamscale $n $tmpdir/first.ppm | " .
+               "pamscale -width $width -height $height " .
+               ">$tmpdir/this.ppm");
+        if ($frameNum == 10) {
+            system("cp", "$tmpdir/this.ppm", "$tmpdir/junk1a.ppm");
+            system("pamscale $n $tmpdir/last.ppm | " .
+                   "pamscale -width $width -height $height " .
+                   ">$tmpdir/junk2a.ppm");
         }
-        if ($i == 10) {
-            system("cp", "junk3$$.ppm", "junk1a$$.ppm");
-            system("pamscale $n junk2$$.ppm | " .
-                   "pamscale -width $width -height $height >junk2a$$.ppm");
-        }    
-    } elsif ($mode eq $MIX) {
-        my $fade_factor = sqrt(1/($nframes-$i+1));
-        system("ppmmix $fade_factor junk1$$.ppm junk2$$.ppm >junk3$$.ppm");
+    } elsif ($frameNum <= 20) {
+        my $n = $spline10[$frameNum-10];
+        system("ppmmix $n $tmpdir/junk1a.ppm $tmpdir/junk2a.ppm " .
+               ">$tmpdir/this.ppm");
     } else {
-        print("Internal error: impossible mode value '$mode'\n");
+        my $n = 1 - 1.9*$spline20[31-$frameNum];
+        system("pamscale $n $tmpdir/last.ppm | " .
+               "pamscale -width $width -height $height " .
+               ">$tmpdir/this.ppm");
     }
+}
+
+
+
+sub mixOne($$) {
+    my ($frameNum, $nFrame) = @_;
 
-    my $outfile = sprintf("%s.%04d.ppm", $base_name, $i);
-    system("cp", "junk3$$.ppm", $outfile);
+    my $fadeFactor = sqrt(1/($nFrame - $frameNum + 1));
+
+    system("ppmmix $fadeFactor $tmpdir/first.ppm $tmpdir/last.ppm " .
+           ">$tmpdir/this.ppm");
 }
 
+
+
+sub fade($$$$$) {
+    my ($nFrame, $mode, $width, $height, $baseNm) = @_;
+#-----------------------------------------------------------------------------
+#  Do the fade starting, from image "first.ppm" in the temporary direct
+#  $tmpdir and ending up at "last.ppm", creating $nFrame frames, including
+#  the first and last.
 #
-#  Clean up shop.
+#  Make the outputs $width by $height.
 #
-system("rm junk*$$.ppm");
+#  Name the result files $baseNm.NNNN.ppm.
+#-----------------------------------------------------------------------------
+
+    # Here's what our temporary files are:
+    #   first.ppm: The original (fade-from) image
+    #   last.ppm: The target (fade-from) image
+    #   this.ppm: The frame of the fade for the current iteration of the
+    #             the for loop.
+    #   junk1a.ppm: If the fade involves a ppmmix sequence from one
+    #               intermediate image to another, this is the first frame
+    #               of that sequence.
+    #   junk2a.ppm: This is the last frame of the above-mentioned
+    #               ppmmix sequence
+
+    my $frameNum;    # Frame number
+    for ($frameNum = 1; $frameNum <= $nFrame; ++$frameNum) {
+
+        print("Creating Frame $frameNum of $nFrame...\n");
+
+        if ($mode eq 'SPREAD') {
+            spreadOne($frameNum);
+        } elsif ($mode eq 'SHIFT') {
+            shiftOne($frameNum);
+        } elsif ($mode eq 'RELIEF') {
+            reliefOne($frameNum);
+        } elsif ($mode eq 'OIL') {
+            oilOne($frameNum);
+        } elsif ($mode eq 'EDGE') {
+            edgeOne($frameNum);
+        } elsif ($mode eq 'BENTLEY') {
+            bentleyOne($frameNum);
+        } elsif ($mode eq 'BLOCK') {
+            blockOne($frameNum, $width, $height);
+        } elsif ($mode eq 'MIX') {
+            mixOne($frameNum, $nFrame);
+        } else {
+            print("INTERNAL ERROR: impossible mode value '$mode'\n");
+        }
+
+        my $outFileNm = sprintf("%s.%04d.ppm", $baseNm, $frameNum);
+        system("cp", "$tmpdir/this.ppm", $outFileNm);
+    }
+}
+
+
+
+#-----------------------------------------------------------------------------
+#  MAINLINE
+#-----------------------------------------------------------------------------
+
+my $nFrame = 30;
+    # Number of images in created sequence, including the fade-from and
+    # fade-to images.  In standard video, 30 frames is one second.
+
+doVersionHack(\@ARGV);
+
+my ($mode, $firstFileNm, $lastFileNm, $baseNm) = commandLineArgs();
+
+if (defined($firstFileNm) && !-e($firstFileNm)) {
+    print STDERR ("First file '$firstFileNm' does not exist\n");
+    exit 20;
+}
+
+if (defined($lastFileNm) && !-e($lastFileNm)) {
+    print STDERR ("Last file '$lastFileNm' does not exist\n");
+    exit 20;
+}
+
+my ($width, $height) = imageDimensions($firstFileNm, $lastFileNm);
+
+    # width and height of our frames in pixels
+
+print("Frames are " . $width . "W x " . $height . "H\n");
+
+my $fromDesc = defined($firstFileNm) ? "'$firstFileNm'" : "black";
+my $toDesc   = defined($lastFileNm)  ? "'$lastFileNm'"  : "black";
+
+if (!defined($firstFileNm)) {
+    system("ppmmake \\#000 $width $height >$tmpdir/first.ppm");
+} else {
+    system("cp", $firstFileNm, "$tmpdir/first.ppm");
+}
+
+if (!defined($lastFileNm)) {
+    system("ppmmake \\#000 $width $height >$tmpdir/last.ppm");
+} else {
+    system("cp", $lastFileNm, "$tmpdir/last.ppm");
+}
+
+print("Fading from $fromDesc to $toDesc\n");
+
+fade($nFrame, $mode, $width, $height, $baseNm);
 
 exit(0);