home *** CD-ROM | disk | FTP | other *** search
- /****************************************************************
- * FILE: morph.c
- * DESC: Create a metamorphosing sequence between two given
- * images. This program lets you specify two files to
- * morph, then prompts you for control lines. It uses
- * the lines to warp the underlying images a step at
- * a time, combine them, and optionally save them as
- * numbered PCX files.
- *
- * HISTORY: Created 1/13/1993
- * LAST CHANGED: 5/ 6/1993
- *
- * Copyright (c) 1993 by Scott Anderson
- *
- ****************************************************************/
-
- /* ----------------------INCLUDES----------------------------- */
-
- #include <conio.h>
- #include <stdio.h>
- #include <io.h>
- #include <math.h>
- #include <graph.h>
- #include <malloc.h>
- #include <memory.h>
- #include <string.h>
-
- #include "define.h"
-
- /* ----------------------DEFINES------------------------------ */
-
- #define MORPH_TWEENS 1
-
- /* ----------------------PROTOTYPES--------------------------- */
-
- int tweenMorph(PICTURE *src, PICTURE *dst);
-
- /* ----------------------EXTERNALS---------------------------- */
-
- /**** color routines ****/
- extern int closestColor(int r, int g, int b, PALETTE *palPtr);
- extern void collapseColors(PALETTE *palPtr);
-
- /**** line routines ****/
- extern int setLength(LINE *line);
- extern int sumLines(PICTURE *picture, COLOR *color,
- LINE *origline, POINT *warp, LINE *warpline);
-
- /**** io routines ****/
- extern LINE_LIST *loadLines(char *filename, char *extension);
- extern void saveLines(char *filename,
- LINE_LIST *lineList, char *extension);
-
- /***** variables used to compute intermediate images ****/
-
- /* number of colors in tweened image before reduction*/
- extern int Ncolors;
-
- /* r, g, b frequency counter array */
- extern unsigned int far Freq[MAX_COMP][MAX_COMP][MAX_COMP];
-
- /* tweened images red, grn, and blu components*/
- extern unsigned char far Red[MAX_WIDE][MAX_TALL];
- extern unsigned char far Grn[MAX_WIDE][MAX_TALL];
- extern unsigned char far Blu[MAX_WIDE][MAX_TALL];
-
- extern PALETTE TweenPal; /* resulting palette */
-
- /**** other variables ****/
- extern char *OutFilename;
- /* set from last picture loaded */
- extern int Xmin, Ymin, Xmax, Ymax;
- /* ID of palette currently being displayed */
- extern int CurrentPal;
-
- /* ----------------------GLOBAL DATA-------------------------- */
-
- PICTURE *Src; /* source & destination picture pointers */
- PICTURE *Dst;
-
- LINE SrcLine[MAX_LINES];
- LINE DstLine[MAX_LINES];
-
- int Tweens;
- int NumLines;
-
- /*****************************************************************
- * FUNC: main (int argc, char *argv[])
- *
- * DESC: Read in a filename to load
- *****************************************************************/
-
- main (int argc, char *argv[])
- {
- int segment;
- LINE_LIST *lineSrcList;
- LINE_LIST *lineDstList;
- char answer;
-
- /* load the pcx file if one is given */
- if ((3 > argc) || (argc > 5)) {
- printf("Usage: morph <source> <dest> [<steps> [<output>]]\n\n");
- printf("Where: <source> is the source PCX filename\n");
- printf(" <dest> is the destination filename\n");
- printf(" <steps> is the optional sequence size\n");
- printf(" (the max is %d, the default is %d)\n",
- MAX_TWEENS, MORPH_TWEENS+2);
- printf(" <output> is the optional output filename\n");
- printf(" (defaults to no output)\n\n");
- printf("Note: The output filename can be at most %d characters long.\n",
- MAX_NAME_SIZE);
- printf(" The PCX extension is added automatically, so don't\n");
- printf(" include it in the filename.\n");
- printf(" Morph only accepts PCX files with %d X %d resolution\n",
- MAX_WIDE, MAX_TALL);
- printf(" and %d colors.\n", COLORS);
- exit(0);
- }
- if (argc > 3) {
- /* subtract two from the series count to get the tweens
- * since the starting and ending frame are included. */
- Tweens = clip (atoi(argv[3]) - 2, 1, MAX_TWEENS);
- if (argc > 4)
- OutFilename = argv[4];
- }
- else
- Tweens = MORPH_TWEENS;
-
- printf("Loading the file %s\n", argv[1]);
- Src = loadPicture(argv[1]);
- if (Src == NULL)
- quit(MEMORY_ERR, "");
-
- printf("Loading the file %s\n", argv[2]);
- Dst = loadPicture(argv[2]);
- if (Dst == NULL)
- quit(MEMORY_ERR, "");
- lineSrcList = loadLines(argv[1], EXT_LINE1);
- if (lineSrcList->number != 0) {
- if (lineAsk(argv[1]) == 'N')
- createLines(Src, lineSrcList);
- else
- editLines(Src, lineSrcList);
- }
- else
- createLines(Src, lineSrcList);
-
- TargFlag = 1; /* For the screen intro message */
- NumLines = lineSrcList->number;
- if (NumLines) {
- lineDstList = loadLines(argv[2], EXT_LINE1);
- /* inconsistent warp target*/
- if (lineDstList->number != NumLines)
- lineDstList->number = 0;
- if (lineDstList->number) { /* ask what he wants to do */
- if (lineAsk(argv[2]) == 'N')
- lineDstList->number = 0;
- }
- if (lineDstList->number == 0) { /* create a warp target */
- /* copy the source lines */
- lineDstList->number = NumLines;
- for (segment = 0; segment < NumLines; segment++)
- lineDstList->line[segment]
- = lineSrcList->line[segment];
- }
-
- editLines(Dst, lineDstList);
- saveLines(argv[1], lineSrcList, EXT_LINE1);
- saveLines(argv[2], lineDstList, EXT_LINE1);
- beep();
- for (segment = 0; segment < NumLines; segment++) {
- DstLine[segment].p[0]=lineDstList->line[segment].p[0];
- DstLine[segment].p[1]=lineDstList->line[segment].p[1];
- setLength(&DstLine[segment]);
- SrcLine[segment].p[0]=lineSrcList->line[segment].p[0];
- SrcLine[segment].p[1]=lineSrcList->line[segment].p[1];
- setLength(&SrcLine[segment]);
- }
- }
-
- tweenMorph(Src, Dst);
- setTextMode();
- }
-
- /*****************************************************************
- * FUNC: int tweenMorph(PICTURE *src, PICTURE *dst)
- *
- * DESC: calculate a pixel to plot, from the warping function
- *****************************************************************/
-
- #define TOTAL_WEIGHT (100) /* Good for up to 99 tweens */
-
- tweenMorph(PICTURE *src, PICTURE *dst)
- {
- int color;
- POINT warp;
- int x,y;
- COLOR scolor, dcolor;
- LINE warpLine[MAX_LINES];
- int t, i, p;
- int r, g, b;
- unsigned int srcweight, srcpaletteindex;
- unsigned int dstweight, dstpaletteindex;
-
- displayPicture(src);
- saveScreen(&src->pal);
-
- /* src is on screen, now tween to the target */
- for (t = 1; t <= Tweens; t++) {
- /* Tween the lines used to warp the images */
- for (i = 0; i < NumLines; i++) {
- for (p = 0; p < 2; p++) {
- warpLine[i].p[p].x = SrcLine[i].p[p].x +
- ((DstLine[i].p[p].x - SrcLine[i].p[p].x) * t)
- /(Tweens+1);
- warpLine[i].p[p].y = SrcLine[i].p[p].y +
- ((DstLine[i].p[p].y - SrcLine[i].p[p].y) * t)
- /(Tweens+1);
- }
- setLength(&warpLine[i]);
- }
-
- dstweight = t * TOTAL_WEIGHT / (Tweens+1);
- srcweight = TOTAL_WEIGHT - dstweight;
-
- /* Zero out the buffers */
- initFreq();
- /* set background to black */
- _fmemset(Red, 0, sizeof Red);
- _fmemset(Grn, 0, sizeof Grn);
- _fmemset(Blu, 0, sizeof Blu);
-
- /* Go through the screen and get warped source pixels */
- for (warp.y = Ymin; warp.y <= Ymax; warp.y++) {
- if (quitCheck())
- quit(0, "");
- for (warp.x = Xmin; warp.x <= Xmax; warp.x++) {
- sumLines(src, &scolor, SrcLine, &warp, warpLine);
- sumLines(dst, &dcolor, DstLine, &warp, warpLine);
- r = (scolor.r * srcweight + dcolor.r * dstweight)
- / TOTAL_WEIGHT;
- g = (scolor.g * srcweight + dcolor.g * dstweight)
- / TOTAL_WEIGHT;
- b = (scolor.b * srcweight + dcolor.b * dstweight)
- / TOTAL_WEIGHT;
- if (Freq[r][g][b] == 0) /* A new color */
- Ncolors++;
- /* Keep it to one byte */
- if (Freq[r][g][b] < MAX_FREQ)
- Freq[r][g][b]++;
- /* put RGB components into temporary buffer */
- Red[warp.x][warp.y] = r;
- Grn[warp.x][warp.y] = g;
- Blu[warp.x][warp.y] = b;
- }
- }
- collapseColors(&TweenPal);
- setPalette(&TweenPal);
-
- for (y = Ymin; y <= Ymax; y++) {
- if (quitCheck())
- quit(0, "");
- for (x = Xmin; x <= Xmax; x++) {
- color = closestColor( Red[x][y],
- Grn[x][y],
- Blu[x][y],
- &TweenPal);
- _setcolor (color);
- _setpixel (x, y);
- }
- }
- /* no output file name on command line */
- if (!OutFilename) {
- beep();
- waitForKey(); /* so pause to enjoy the pictures */
- }
- else
- saveScreen(&TweenPal);
- }
- if (OutFilename) { /* save the last pic in this series */
- CurrentPal = 0; /* force a new palette */
- displayPicture(dst);
- saveScreen(&dst->pal);
- }
- }
-
-