home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Fresh Fish 8
/
FreshFishVol8-CD1.bin
/
new
/
gfx
/
edit
/
tsmorph
/
src
/
tsmorph-render.c
< prev
next >
Wrap
C/C++ Source or Header
|
1994-02-27
|
101KB
|
3,265 lines
// TSMorph - Amiga Morphing program
// Copyright (C) © 1993 Topicsave Limited
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation; either version 2 of the License, or
// any later version.
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
// mpaddock@cix.compulink.co.uk
/* Amiga headers */
#define INTUI_V36_NAMES_ONLY
#define INTUITION_IOBSOLETE_H
// Include correct math library
#ifdef MY68881
#include <m68881.h>
extern int rand(void);
#else
#ifdef MY68881_6
#include <math.h>
#include <m68881.h>
#else
#include <math.h>
#endif
#endif
// prevent inclusion of another math library
#define LIBRARIES_MATHFFP_H
// other headers, define some non 2.02 header stuff
#include <exec/types.h>
#include <exec/memory.h>
#include <intuition/intuition.h>
#include <intuition/intuitionbase.h>
#include <intuition/gadgetclass.h>
#ifndef PGA_NewLook
#define PGA_NewLook (PGA_Dummy + 0x000A)
#endif
#include <intuition/imageclass.h>
#include <intuition/icclass.h>
#include <devices/input.h>
#include <workbench/workbench.h>
#include <workbench/startup.h>
#include <libraries/gadtools.h>
#ifndef GTMN_FullMenu
#define GTMN_FullMenu GT_TagBase+62
#endif
#include <libraries/asl.h>
#include <clib/exec_protos.h>
#include <clib/dos_protos.h>
#include <clib/layers_protos.h>
#include <clib/graphics_protos.h>
#include <clib/intuition_protos.h>
#include <clib/input_protos.h>
#include <clib/gadtools_protos.h>
#include <clib/asl_protos.h>
#include <clib/utility_protos.h>
#include <clib/alib_protos.h>
#include <pragmas/exec_pragmas.h>
#include <pragmas/dos_pragmas.h>
#include <pragmas/layers_pragmas.h>
#include <pragmas/graphics_pragmas.h>
#include <pragmas/intuition_pragmas.h>
#include <pragmas/input_pragmas.h>
#include <pragmas/gadtools_pragmas.h>
#include <pragmas/asl_pragmas.h>
#include <pragmas/utility_pragmas.h>
#include <proto/diskfont.h>
#include <proto/icon.h>
#include <devices/timer.h>
#include <clib/timer_protos.h>
#include <pragmas/timer_pragmas.h>
#include <clib/alib_protos.h>
#include <rexx/errors.h>
#include <pragmas/rexxsyslib_pragmas.h>
#include <clib/rexxsyslib_protos.h>
#include <libraries/amigaguide.h>
#include <clib/amigaguide_protos.h>
#include <pragmas/amigaguide_pragmas.h>
#include <libraries/reqtools.h>
#include <clib/reqtools_protos.h>
#include <pragmas/reqtools.h>
#include <opal/opallib.h>
#include <libraries/dctv.h>
#include <clib/dctv_protos.h>
#include <pragmas/dctv_pragmas.h>
#include <libraries/nofrag.h>
#include <clib/nofrag_protos.h>
#ifdef LIBRARIES_NOFRAG_H
#undef LIBRARIES_NOFRAG_H
#endif
#include <pragmas/nofrag_pragmas.h>
#ifndef LIBRARIES_NOFRAG_H
#define LIBRARIES_NOFRAG_H 1
#endif
#include <stddef.h>
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
/* Below is not in the 2.02 version of clib/utility_protos.h
pragmas/utility_pragmas.h */
#if INCLUDE_VERSION < 37
LONG Stricmp(UBYTE *string1,UBYTE *string2);
#pragma libcall UtilityBase Stricmp A2 9802
#endif
/* EGS Stuff */
#include <egs/clib/egs_protos.h>
#include <egs/pragmas/egs_pragmas.h>
#include <egs/clib/egsintui_protos.h>
#include <egs/pragmas/egsintui_pragmas.h>
#include <egs/clib/egsgfx_protos.h>
#include <egs/pragmas/egsgfx_pragmas.h>
#include <egs/egsintui.h>
extern struct Library *EGSIntuiBase = NULL;
extern struct Library *EGSGfxBase = NULL;
extern struct Library *EGSBase = NULL;
// IFF header
#include "iffp/ILBMapp.h"
// Progress requester
#include "progress.h"
// JPEG load stuff
#include "JPEG_LS/jinclude.h"
// Help nodes
STRPTR context[] = {
"",
"Main",
"Err-IFFBMHD",
"Err-IFFRaster",
"Err-IFFBODY",
"Err-IFFCLIP",
"Err-IFFILBM",
"Err-IFFFileS",
"Err-IFFTop",
"Err-IFFMemory",
"Req-Progress",
"Err-LibraryR",
"Err-Saving",
"Err-AllocVec",
"Err-OpenPoints",
"Err-Progress",
"Err-AllocPlanes",
"Err-24",
"Err-Load",
"Err-AllocIFF",
"Err-AllocILBM",
"Err-FileFormat",
"Err-SizeMatch",
"Err-Range",
"Err-MemPointsR",
"Err-CloseFile",
"Err-3Points",
"Err-OpenFile",
"Err-ARexx",
"Req-Really_quit",
"Err-OldFormat",
"Err-OpalVision",
"Err-NoOpal",
};
#define H_Help 10
#define H_Library 11
#define H_ESave 12
#define H_AllocVec 13
#define H_OpenPoints 14
#define H_Progress 15
#define H_AllocPlanes 16
#define H_24 17
#define H_Load 18
#define H_AllocIFF 19
#define H_AllocILBM 20
#define H_FileFormat 21
#define H_SizeMatch 22
#define H_Range 23
#define H_MemPointsR 24
#define H_CloseFile 25
#define H_3Points 26
#define H_Open 27
#define H_ARexx 28
#define H_Really 29
#define HE_OldFormat 30
#define HE_OpalVision 31
#define HE_NoOpal 32
// Disable Ctrl-C checking
int CXBRK(void) { return(0); }
int chkabort(void) { return(0); }
int __regargs __chkabort(void) { return(0); }
// Libraries
extern struct ExecBase *SysBase;
extern struct DosLibrary *DOSBase;
struct IntuitionBase *IntuitionBase;
struct Library *GfxBase, *LayersBase, *IFFParseBase;
struct Library *GadToolsBase, *AslBase, *UtilityBase;
struct Library *RexxSysBase;
struct Library *AmigaGuideBase;
struct Library *TimerBase=NULL;
struct Library *ReqToolsBase;
struct Library *DCTVBase;
struct NoFragBase *NoFragBase = NULL;
struct OpalBase *OpalBase = NULL;
extern struct List InfoList={0}; // List of messages
// Help stuff
extern AMIGAGUIDECONTEXT handle = {NULL};
extern struct NewAmigaGuide nag = {NULL};
extern ULONG ASig = 0;
/* Version string for CLI version */
#ifdef MY68881
char *Version = "$VER: TSMorph-render_881 3.0 (25.2.94)";
#else
#ifdef _M68040
char *Version = "$VER: TSMorph-render_040 3.0 (25.2.94)";
#else
#ifdef MY68881_6
char *Version = "$VER: TSMorph-render_881 3.0 (25.2.94)";
#else
char *Version = "$VER: TSMorph-render 3.0 (25.2.94)";
#endif
#endif
#endif
BOOL Pic1_Open = FALSE; // 1st image open OK
BOOL Pic2_Open = FALSE; // 2nd image open OK
struct MsgPort *WMsgPortp; // Message port for Picture Windows
// Properties for IFF read
LONG props[] = { ID_ILBM, ID_BMHD,
ID_ILBM, ID_CAMG,
ID_ILBM, ID_CMAP,
TAG_DONE };
LONG stops[] = { ID_ILBM, ID_BODY,
TAG_DONE };
LONG nowt[] = { TAG_DONE };
struct EI_NewWindow EGS_NewWindow = {0}; // EGS New window
struct EI_Window *EGS_Win=NULL; // EGS Window
struct E_EBitMap *EGS_BitMap=NULL;
// Protos
BOOL SaveFile(void);
BOOL Load24bit(char *filename,struct Picture *pic,BOOL GUI);
void Close24bit(struct Picture *pic);
void DeleteAllPoints(void);
static void __regargs FindPoint(struct MyPoint *RetPoint,BOOL Everything);
BOOL MyOpen(char *filename,BOOL JustPoints);
static UWORD __regargs intersect(struct MyPoint *Pointa,struct MyPoint *Pointb);
static void __regargs CalcDiffs(struct MyPoint *a,struct MyPoint *bb,double *ab1,double *ab2,double *ab);
static void __regargs Triangle(struct MyPoint *p,struct MyPoint *a,struct MyPoint *bb,struct MyPoint *c);
static void __regargs Triangle_I(struct MyPoint *p,struct MyPoint *a,struct MyPoint *bb,struct MyPoint *c);
extern void MyArgArrayInit(int argc,char **argv);
extern void MyArgArrayDone(void);
extern UBYTE *MyArgString(UBYTE *arg2,UBYTE *arg3,BOOL reopen);
extern LONG MyArgInt(UBYTE *arg2, long arg3,BOOL reopen);
extern BOOL MyFindToolType(UBYTE *arg2,BOOL reopen);
void OpenNewArgs(UBYTE *filename);
void help(ULONG hnum);
BOOL LoadFrames(BOOL points,BOOL image1,BOOL image2);
void CopyEGS(int line, UBYTE **er,UBYTE **eg,UBYTE **eb);
int cmpX(struct MyPoint **A,struct MyPoint **B);
int cmpY(struct MyPoint **A,struct MyPoint **B);
int cmpDiff(struct MyPoint **A,struct MyPoint **B);
BOOL GenerateTriangles(void);
void FreeTriangles(void);
int *IntVect(int ncols);
void MyFreeVecti(int *vectptr);
int **IntMatrix(int nrows,int ncols);
void FreeMatrixi(int **matptr);
double **DoubleMatrix(int nrows,int ncols);
void FreeMatrixd(double **matptr);
BOOL AddTri(int aa,int bb,int cc);
void AddMessage(UBYTE *message);
// Args.c
void argArrayDone( void );
char **argArrayInit( LONG argc, char **argv );
// RenderSub.c
void DisableWindow(void);
void EnableWindow(void);
APTR MyAllocVec(ULONG size,ULONG requirements);
void MyFreeVec(APTR memptr);
APTR MyAllocMem(ULONG size,ULONG requirements);
void MyFreeMem(APTR memptr,ULONG size);
APTR Mymalloc(ULONG size);
APTR Mystrdup(UBYTE *str);
void Error(char *ErrorMessage, char *Gadget,char *extra,ULONG hnum);
LONG SendRxMsg(char *msgtxt,BOOL IgnoreError);
// some work buffers
extern char buffer[256]="";
extern char buffer1[512]="";
// Image structure
struct Picture {
struct ILBMInfo *ilbm; // For IFF read
UBYTE *red; // Read chunky pixels Must be RGB for Opal OVtoRGB
UBYTE *green; // Green
UBYTE *blue; // Blue
UBYTE filename[256]; // filename
struct OpalScreen *OScrn; // OpalScreen
BOOL rgbonelot; // Is red,green,blue one AllocVec
};
struct Picture Pic1={0},Pic2={0};// 1st and 2nd image
extern UBYTE *plane0=NULL; // Planes for temporary bit maps
extern UBYTE *plane1=NULL;
extern UBYTE *plane2=NULL;
extern UBYTE *plane3=NULL;
extern UBYTE *plane4=NULL;
extern UBYTE *plane5=NULL;
extern UBYTE *plane6=NULL;
extern UBYTE *plane7=NULL;
// nofrag.library stuff
extern struct MemoryChain *Chain = NULL;
#define MAXMEM 1000
// Point structure
struct MyPoint {
struct MinNode MyNode; // linked into list
WORD x,y; // Coordinates in 1st image
WORD x1,y1; // 2nd image
WORD Cx,Cy; // Current image
LONG Cdiff; // seperation between two points (squared)
WORD xdiff; // x difference
WORD ydiff; // y difference
double xd,yd; // double coords for AntiAlias
double x1d,y1d;// 2nd image
BOOL Used; // Is it being used?
struct List TList; // List of triangles;
};
struct Triangle {
struct MinNode TNode; // Linked into list
struct MyPoint *Point1;
struct MyPoint *Point2;
};
// 24 bitplane bitmap
struct MyBitMap {
struct BitMap BitMap;
PLANEPTR xplanes[16];
};
// List of points
struct List PointList;
// Size of image
extern USHORT width=0, height=0, pwidth=0, pheight=0, pmode=0;
char AnimName[256]=""; // Buffer for file name to save
char *Loadscript; // ARexx load script
extern WORD x=0,y=0; // Current coords
struct MyPoint **Points = NULL; // Pointer to points
struct MyPoint **PointsAlloc = NULL; // The actual allocated pointer
struct MyPoint **PointsX = NULL; // Pointer to points horizontal
struct MyPoint **PointsY = NULL; // Pointer to points vertical
WORD Depth; // Number of points to check each time
UWORD Mode; // Mode = 0 use 3 closest if no others, choose 1st 3
// Mode = 1 leave points stationary, choose 1st 3
// Mode = 2 choose 3 closet, always use
// Mode = 3 leave points stationary, choose 3 closest
// Mode = 4 Binary search ,5,6,7 as above
// Mode = 8 Delaunay Triangle algorithm
// Mode = 16 Only calculate points once
// SET/UNSET
#define MODE_STAT 1 // Stationary if no triangle/Use 3 points anyway
#define MODE_CLOSEST 2 // Choose 3 closest/Choose 1st 3 found
#define MODE_SEARCH 4 // Binary Search/Look at all points
#define MODE_DELAU 8 // Delaunay Triangle/Normal mode (sets DEPTH to 0)
#define MODE_ONCE 16 // Only calculate once
LONG PointCount = 0; // Number of points
struct MyPoint BigPoint; // Point far away
char MyFileName[257];
// Settings stuff
char **ArgArray;
char **ArgArraySettings;
// OpalVision screen
extern struct OpalScreen *OScrn = NULL;
extern char *OVFormat=NULL; // Format of OpalVision save JPG or IFF (or anything) default
BOOL AntiAlias; // AntiAlias points
// Table of parameters
extern struct {
LONG xf; // Current frame
LONG xFrames; // Number of frames
LONG xSingle; // Warp or Morph
LONG xmove; // Movement 1 to 2
LONG xr; // red of image 1
LONG xg; // green
LONG xb; // blue
LONG xr2; // red of image 2
LONG xg2; // green
LONG xb2; // blue
LONG xDo; // Produce this image
LONG xrplus; // Add red
LONG xgplus; // green
LONG xbplus; // blue
LONG xrminus; // subtract red
LONG xgminus; // subtract green
LONG xbminus; // subtract blue
LONG xDX; // X skip
LONG xDY; // Y skip
LONG xStart; // Start Frame number
LONG FILLER[32]; // Filler for future expansion
} Arexx = {0};
#define f Arexx.xf
#define Frames Arexx.xFrames
#define Single Arexx.xSingle
#define move Arexx.xmove
#define r Arexx.xr
#define g Arexx.xg
#define b Arexx.xb
#define r2 Arexx.xr2
#define g2 Arexx.xg2
#define b2 Arexx.xb2
#define Do Arexx.xDo
#define rplus Arexx.xrplus
#define gplus Arexx.xgplus
#define bplus Arexx.xbplus
#define rminus Arexx.xrminus
#define gminus Arexx.xgminus
#define bminus Arexx.xbminus
#define DX Arexx.xDX
#define DY Arexx.xDY
#define Start Arexx.xStart
// Display help if available
void
help(ULONG hnum) {
if (handle) {
SetAmigaGuideContext(handle,hnum,NULL);
SendAmigaGuideContext(handle,NULL);
}
}
extern char FileName[256]=""; // File name buffer
extern long OVQuality=0; // OpalVision JPG quality
extern BOOL OVFast=FALSE; // OpalVision fast format IFF
extern BOOL OVThumb=FALSE; // OpalVision Thumbail
extern BOOL HAM6=FALSE;
extern BOOL HAM8=FALSE;
extern BOOL BW16=FALSE;
extern BOOL BW256=FALSE;
extern BOOL DCTV3 = FALSE;
extern BOOL DCTV4 = FALSE;
extern UBYTE *arrayr=NULL, // Pointers to red,green and blue
*arrayg=NULL,
*arrayb=NULL;
extern BOOL PPM=FALSE; // PPM save ?
extern BOOL EGS=FALSE; // EGS Preview
extern UBYTE *p[3] = {NULL,NULL,NULL};// chunky pointers - order for OpalVision
#define RED p[0]
#define BLUE p[2]
#define GREEN p[1]
extern UWORD swidth=0; // scaled width (in full words)
extern struct RastPort RP={0}, // Work Rast Ports
TRP={0};
extern struct MyBitMap MyBitMap={0}; // Real bit map
extern PLANEPTR Planes[24] = {NULL}; // Bit planes
extern BOOL CreateIcons=FALSE;// Create Icons on pictures?
extern char *Postscript=NULL;// ARexx postscript
BOOL Integer = FALSE;
/* Main program */
int
main(int argc,char **argv) {
BOOL OkFlag = TRUE; // Is it working ?
char *e = NULL; // error message
struct MyPoint MyPoint; // Points to work with
struct MyPoint *MyPointp;
BOOL Opened; // has file been opened
struct WBStartup *argmsg; // Workbench stuff
struct WBArg *wb_arg;
char *e1; // The rest of the error message
struct Window *oldWindowPtr; // Redirect the system requesters
struct Process *process;
char *filename; // file name
ULONG offset, // 2d to 1d array offsets
offset1;
char *Prescript; // Rexx script names
UWORD myx, // indexes for skipping
myy;
UBYTE xr, // more skipping stuff
xg,
xb;
struct AmigaGuideMsg *agm; // help stuff
struct timeval time1, // To display time per image
time2;
struct timerequest tr;
BOOL t2 = FALSE; // Set when the times calculated
char tbuffer[30];// buffer for time message
ULONG hnum = 0; // Help number for error
BOOL Alloced=FALSE; // Allocated memory?
char *Tstr; // Temp string for parameter
UWORD xbig;
double xsmall; // Int and rest of coords
UWORD ybig;
double ysmall; // y coords
WORD right,down; // move right and down?
UWORD xbig1;
double xsmall1; // Int and rest of coords
UWORD ybig1;
double ysmall1; // y coords
WORD right1,down1;// move right and down?
double a,bb,c,d,a1,b1,c1,d1; // AntiAlias stuff
UBYTE *er,*eg,*eb;// EGS pointers
// Set up BigPoint
BigPoint.Cdiff = 0x7FFFFFFF;
// Initialise points list
NewList(&PointList);
// Try and open reqtools.library and dctv.library and nofrag.library
ReqToolsBase = OpenLibrary("reqtools.library",38);
DCTVBase = OpenLibrary("dctv.library",3);
if (NoFragBase = (struct NoFragBase *) OpenLibrary("nofrag.library",2L)) {
if (!(Chain = GetMemoryChain(MAXMEM+20))) {
CloseLibrary((struct Library *)NoFragBase);
NoFragBase = NULL;
}
}
// Set up amigaguide (if available)
if (AmigaGuideBase = OpenLibrary ("amigaguide.library", 33L)) {
nag.nag_BaseName = "TSMorph";
nag.nag_Name = "TSMorph.guide";
nag.nag_ClientPort = "TSMorph-render_HELP";
nag.nag_Context = context;
if (handle = OpenAmigaGuideAsync (&nag, NULL)) {
ASig = AmigaGuideSignal(handle);
}
}
// Try and open the timer
if (!OpenDevice(TIMERNAME,UNIT_MICROHZ,(struct IORequest *) &tr, 0L)) {
TimerBase = (struct Library *)tr.tr_node.io_Device;
}
// Try and open OpalVision library
OpalBase = (struct OpalBase *)OpenLibrary("opal.library",0L);
// Open all the libraries
if (IntuitionBase = (struct IntuitionBase *)OpenLibrary("intuition.library",37L)) {
if (RexxSysBase = OpenLibrary("rexxsyslib.library",0)) {
if (IFFParseBase = OpenLibrary("iffparse.library",37L)) {
if (GfxBase = OpenLibrary("graphics.library",37L)) {
if (LayersBase = OpenLibrary("layers.library",37L)) {
if (GadToolsBase = OpenLibrary("gadtools.library",37L)) {
if (AslBase = OpenLibrary("asl.library",37L)) {
if (UtilityBase = OpenLibrary("utility.library",37)) {
if (IconBase = OpenLibrary("icon.library",37L)) {
if (DiskfontBase = OpenLibrary("diskfont.library",36)) {
// Read and process the parameters
MyArgArrayInit(argc,argv);
if (MatchToolValue(MyArgString("EGS","NO",FALSE),"YES")) {
if ((EGSBase = OpenLibrary("egs.library",0)) &&
(EGSGfxBase = OpenLibrary("egsgfx.library", 0)) &&
(EGSIntuiBase = OpenLibrary("egsintui.library", 0))) {
EGS = TRUE;
}
}
if (MatchToolValue(MyArgString("REQTOOLS","YES",FALSE),"NO")) {
if (ReqToolsBase) {
CloseLibrary(ReqToolsBase);
ReqToolsBase = NULL;
}
}
PubScreenName = MyArgString("PUBSCREENR",NULL,FALSE);
// Open the progress window
if ((!SetupScreen()) && (!OpenProgressWindow())) {
// redirect requesters
process = (struct Process *)FindTask(NULL);
oldWindowPtr = process->pr_WindowPtr;
process->pr_WindowPtr = ProgressWnd;
// Open the project file (CLI or WB)
DisableWindow();
AddMessage("Opening points file");
if (argc) {
if (filename = ArgString(ArgArray,"FILES",NULL)) {
Opened = MyOpen(filename,FALSE);
}
else {
Opened = MyOpen(NULL,FALSE);
}
}
else {
argmsg = (struct WBStartup *)argv;
if (argmsg->sm_NumArgs > 1) {
wb_arg = argmsg->sm_ArgList;
wb_arg++;
if (wb_arg->wa_Lock) {
NameFromLock(wb_arg->wa_Lock,buffer,256);
}
if (AddPart(buffer,wb_arg->wa_Name,256)) {
Opened = MyOpen(buffer,FALSE);
}
}
else {
Opened = MyOpen(NULL,FALSE);
}
}
if (Opened) {
// Get a few parameters
Tstr = MyArgString("SAVEFORMAT","ILBM24",FALSE);
if (OpalBase) {
if (MatchToolValue(Tstr,"OPAL24") || MatchToolValue(Tstr,"OPAL24T") ||
MatchToolValue(Tstr,"OPAL24F") || MatchToolValue(Tstr,"OPAL24FT")) {
OVFormat = "IFF";
}
else {
if (MatchToolValue(Tstr,"JPEG") || MatchToolValue(Tstr,"JPEGT")) {
OVFormat = "JPG";
}
else {
OVFormat = NULL;
}
}
}
else {
OVFormat = NULL;
}
PPM = MatchToolValue(Tstr,"PPM");
HAM6 = MatchToolValue(Tstr,"HAM6");
HAM8 = MatchToolValue(Tstr,"HAM8");
BW16 = MatchToolValue(Tstr,"BW16");
BW256 = MatchToolValue(Tstr,"BW256");
if (DCTVBase) {
DCTV3 = MatchToolValue(Tstr,"DCTV3");
DCTV4 = MatchToolValue(Tstr,"DCTV4");
}
OVQuality = MyArgInt("QUALITY",75,FALSE);
if (MatchToolValue(Tstr,"OPAL24T") || MatchToolValue(Tstr,"JPEGT")) {
OVThumb = TRUE;
}
else {
OVThumb = FALSE;
}
if (MatchToolValue(Tstr,"OPAL24F") || MatchToolValue(Tstr,"OPAL24FT")) {
OVFast = TRUE;
}
else {
OVFast = FALSE;
}
Prescript = MyArgString("PRESCRIPT","Rexx/Prescript",FALSE);
Postscript = MyArgString("POSTSCRIPT","Rexx/Postscript",FALSE);
Loadscript = MyArgString("LOADSCRIPT","Rexx/Loadscript",FALSE);
DX = MyArgInt("DX",0,FALSE);
DY = MyArgInt("DY",0,FALSE);
// Depth = min(MyArgInt("DEPTH",2,FALSE),20); Set in Open()
// Mode = MyArgInt("MODE",0,FALSE);
CreateIcons = MatchToolValue(MyArgString("CREATEICONSR","NO",FALSE),"YES");
AntiAlias = MatchToolValue(MyArgString("ANTIALIAS","NO",FALSE),"YES");
Integer = MatchToolValue(MyArgString("INTEGER","NO",FALSE),"YES");
if (Integer) {
AntiAlias = FALSE;
}
// File has been opened, cache width in full words
swidth = (((width+15)>>4)<<4);
AddMessage("Allocating work memory");
// Allocate chunky and ILBM bit maps
if ((RED = AllocVec((swidth*height),MEMF_CLEAR)) &&
(GREEN = AllocVec((swidth*height),MEMF_CLEAR)) &&
(BLUE = AllocVec((swidth*height),MEMF_CLEAR)) &&
((OpalBase && OVFormat && !PPM && (OScrn = CreateScreen24(0,width,height))) ||
PPM ||
(!OVFormat && !PPM &&
(Planes[0] = AllocRaster(width,height)) &&
(Planes[1] = AllocRaster(width,height)) &&
(Planes[2] = AllocRaster(width,height)) &&
(DCTV3 ||
((Planes[3] = AllocRaster(width,height)) &&
(DCTV4 || BW16 ||
((Planes[4] = AllocRaster(width,height)) &&
(Planes[5] = AllocRaster(width,height)) &&
(HAM6 ||
((Planes[6] = AllocRaster(width,height)) &&
(Planes[7] = AllocRaster(width,height)) &&
(HAM8 || BW256 ||
((Planes[8] = AllocRaster(width,height)) &&
(Planes[9] = AllocRaster(width,height)) &&
(Planes[10] = AllocRaster(width,height)) &&
(Planes[11] = AllocRaster(width,height)) &&
(Planes[12] = AllocRaster(width,height)) &&
(Planes[13] = AllocRaster(width,height)) &&
(Planes[14] = AllocRaster(width,height)) &&
(Planes[15] = AllocRaster(width,height)) &&
(Planes[16] = AllocRaster(width,height)) &&
(Planes[17] = AllocRaster(width,height)) &&
(Planes[18] = AllocRaster(width,height)) &&
(Planes[19] = AllocRaster(width,height)) &&
(Planes[20] = AllocRaster(width,height)) &&
(Planes[21] = AllocRaster(width,height)) &&
(Planes[22] = AllocRaster(width,height)) &&
(Planes[23] = AllocRaster(width,height))))))))))))) { // Looks like LISP!!!!
Alloced = TRUE;
// Update the progress
EnableWindow();
GT_SetGadgetAttrs(ProgressGadgets[GDX_Frame],ProgressWnd,NULL,
GTSL_Min,1,
GTSL_Max,Frames,TAG_END);
GT_SetGadgetAttrs(ProgressGadgets[GDX_Line],ProgressWnd,NULL,
GTSL_Min,0,
GTSL_Max,height-1,TAG_END);
// Pass to ARexx for processing
if (strcmp(Prescript,"OFF")) {
AddMessage("Prescript for frame 0");
f = 0;
Do = 0;
strcpy(buffer,Prescript);
strcat(buffer," %ld");
sprintf(buffer1,buffer,&Arexx);
OkFlag = !SendRxMsg(buffer1,FALSE);
if (!OkFlag) {
e = (char *)-1;
}
if (Do && OkFlag) {
OkFlag = LoadFrames(FALSE,TRUE,FALSE);
if (!OkFlag) {
e = (char *)-1;
}
else {
AddMessage("Saving frame 0");
memcpy(RED,Pic1.red,swidth*height);
memcpy(GREEN,Pic1.green,swidth*height);
memcpy(BLUE,Pic1.blue,swidth*height);
OkFlag = SaveFile();
if (!OkFlag) {
e = (char *)-1;
}
}
}
}
if ((Mode & MODE_ONCE) && OkFlag) {
AddMessage("Precalculating points");
Points = PointsAlloc;
for (MyPointp = (struct MyPoint *)PointList.lh_Head;
MyPointp->MyNode.mln_Succ;
MyPointp = (struct MyPoint *)MyPointp->MyNode.mln_Succ) {
MyPointp->Cx = (MyPointp->x1+MyPointp->x)>>1;
MyPointp->Cy = (MyPointp->y1+MyPointp->y)>>1;
}
for (y=0;
((y<height) && OkFlag);
y++) {
// Loop thru columns
for (x=0;
x < width;
x++) {
// Determine coordinates on end image(s)
FindPoint(&MyPoint,FALSE);
Points += (Depth+4);
if (DX) {
x++;
for (myx = 0;
(myx < DX) && (x < width);
x++,myx++) {
Points += (Depth+4);
}
x--;
}
}
// end of line, check 'Stop' and 'Help'
OkFlag = HandleProgressIDCMP();
if (handle) {
while (agm = GetAmigaGuideMsg(handle)) {
ReplyAmigaGuideMsg(agm);
}
}
if (DY) {
y++;
for (myy = 0;
(myy < DY) && (y<height);
y++, myy++) {
Points += ((Depth+4)*width);
}
y--;
}
}
// not ok - already displayed an error
if (!OkFlag) {
e = (char *)-1;
}
else {
if (Mode & MODE_DELAU) {
AddMessage("Calculating triangles");
OkFlag = GenerateTriangles();
if (!OkFlag) {
Error("Out of memory for points","Quit",NULL,H_MemPointsR);
}
}
}
}
// Determine start time
if (TimerBase) {
GetSysTime(&time1);
}
// Loop thru frames
for (f=1;
(f < (Frames+1)) && OkFlag; // no of Frames
f++) {
// Update progress
AddMessage("Prescript processing");
GT_SetGadgetAttrs(ProgressGadgets[GDX_Frame],ProgressWnd,NULL,
GTSL_Level,f,TAG_END);
// calculate default image parameters
rplus = gplus = bplus = rminus = gminus = bminus = 0;
if ((Single == 1) || (Single == 3)) {
move = ((Frames-f) << 10)/Frames;
r = g = b = 1024;
r2 = g2 = b2 = 0;
Do = 1;
}
else {
r = g = b = move = ((Frames-f+1) << 10)/(Frames + 1);
r2 = g2 = b2 = (1024 - r);
Do = 1;
}
// Pass to ARexx for processing
if (strcmp(Prescript,"OFF")) {
strcpy(buffer,Prescript);
strcat(buffer," %ld");
sprintf(buffer1,buffer,&Arexx);
OkFlag = !SendRxMsg(buffer1,FALSE);
if (!OkFlag) {
e = (char *)-1;
}
}
if (OkFlag && Do && ((!Pic1_Open) || (Single == 2) || (Single == 3))) {
if (Pic2_Open) {
Close24bit(&Pic2);
Pic2_Open = FALSE;
}
if (Pic1_Open) {
Close24bit(&Pic1);
Pic1_Open = FALSE;
}
OkFlag = LoadFrames(TRUE,TRUE,TRUE);
if (!OkFlag) {
e = (char *)-1;
}
}
else { // Version 2.4 - Open frame 2 if not yet open
if (OkFlag && Do && !Pic2_Open && (Single == 0)) {
OkFlag = LoadFrames(FALSE,FALSE,TRUE);
}
}
if ((PointCount < 3) && OkFlag) {
Error("Must have at least 3 points","Quit",NULL,H_3Points);
OkFlag = FALSE;
}
if (Do && OkFlag) {
// If we have calculated time per image the display it, update other gadgets
if (t2) {
sprintf(tbuffer,"%ld.%02ld Seconds for last image",time2.tv_secs,time2.tv_micro/10000);
AddMessage(tbuffer);
}
else {
AddMessage("Rendering image");
}
if (TimerBase) {
GetSysTime(&time1);
}
// We want to do this image so calculate coordinates in this image
if ((Single == 1) || (Single == 3)) {
for (MyPointp = (struct MyPoint *)PointList.lh_Head;
MyPointp->MyNode.mln_Succ;
MyPointp = (struct MyPoint *)MyPointp->MyNode.mln_Succ) {
MyPointp->Cx = (MyPointp->x1*(1024-move)+MyPointp->x*move)>>10;
MyPointp->Cy = (MyPointp->y1*(1024-move)+MyPointp->y*move)>>10;
}
}
else {
for (MyPointp = (struct MyPoint *)PointList.lh_Head;
MyPointp->MyNode.mln_Succ;
MyPointp = (struct MyPoint *)MyPointp->MyNode.mln_Succ) {
MyPointp->Cx = (MyPointp->x1*(1024-move)+MyPointp->x*move)>>10;
MyPointp->Cy = (MyPointp->y1*(1024-move)+MyPointp->y*move)>>10;
}
}
if (Mode & MODE_SEARCH) {
AddMessage("Sorting points");
qsort((char *)PointsX,PointCount,sizeof(struct MyPoint *),cmpX);
qsort((char *)PointsY,PointCount,sizeof(struct MyPoint *),cmpY);
}
if ((Mode & MODE_DELAU) && (!MODE_ONCE)) {
AddMessage("Calculating triangles");
OkFlag = GenerateTriangles();
if (!OkFlag) {
Error("Out of memory for points","Quit",NULL,H_MemPointsR);
}
}
// Initialise chunky pointers
er = arrayr=RED;
eg = arrayg=GREEN;
eb = arrayb=BLUE;
Points = PointsAlloc;
// loop thru lines
for (y=0;
(y<height) && OkFlag;
y++) {
// Update progress
GT_SetGadgetAttrs(ProgressGadgets[GDX_Line],ProgressWnd,NULL,
GTSL_Level,(ULONG)y,TAG_END);
// Loop thru columns
for (x=0;
x < width;
x++) {
// Determine coordinates on end image(s)
FindPoint(&MyPoint,TRUE);
if (Mode & MODE_ONCE) {
Points += (Depth+4);
}
if (AntiAlias) {
// Horrible AntiAlias stuff
xbig = floor(MyPoint.xd + 0.5);
xsmall = MyPoint.xd - (double)xbig;
if (xsmall > 0) {
right = 1;
}
else {
xsmall = -xsmall;
right = -1;
}
ybig = floor(MyPoint.yd + 0.5);
ysmall = MyPoint.yd - (double)ybig;
if (ysmall > 0) {
down = swidth;
}
else {
ysmall = -ysmall;
down = -swidth;
}
offset = ybig*swidth+xbig;
a = 1.0 + (xsmall * ysmall) - xsmall - ysmall;
bb = xsmall * (1.0 - ysmall);
c = ysmall * (1.0 - xsmall);
d = xsmall * ysmall;
if ((Single != 1) && (Single != 3)) {
xbig1 = floor(MyPoint.x1d + 0.5);
xsmall1 = MyPoint.x1d - (double)xbig1;
if (xsmall1 > 0) {
right1 = 1;
}
else {
xsmall1 = -xsmall1;
right1 = -1;
}
ybig1 = floor(MyPoint.y1d + 0.5);
ysmall1 = MyPoint.y1d - (double)ybig1;
if (ysmall1 > 0) {
down1 = swidth;
}
else {
ysmall1 = -ysmall1;
down1 = -swidth;
}
offset1 = ybig1*swidth+xbig1;
a1 = 1.0 + (xsmall1 * ysmall1) - xsmall1 - ysmall1;
b1 = xsmall1 * (1.0 - ysmall1);
c1 = ysmall1 * (1.0 - xsmall1);
d1 = xsmall1 * ysmall1;
(*arrayr) = min(max((((ULONG)
((((double) Pic1.red[offset])*a + ((double) Pic1.red[offset+right])*bb+
((double) Pic1.red[offset+down])*c+((double) Pic1.red[offset+down+right])*d)*((double)r) +
(((double) Pic2.red[offset1])*a1 + ((double) Pic2.red[offset1+right1])*b1+
((double) Pic2.red[offset1+down1])*c1+((double) Pic2.red[offset1+down1+right1])*d1)*((double)r2))
)>>10) + rplus - rminus,0),255);
(*arrayg) = min(max((((ULONG)
((((double)Pic1.green[offset])*a + ((double)Pic1.green[offset+right])*bb+
((double)Pic1.green[offset+down])*c+((double)Pic1.green[offset+down+right])*d)*((double)g) +
(((double)Pic2.green[offset1])*a1 + ((double)Pic2.green[offset1+right1])*b1+
((double)Pic2.green[offset1+down1])*c1+((double)Pic2.green[offset1+down1+right1])*d1)*((double)g2))
)>>10) + gplus - gminus,0),255);
(*arrayb) = min(max((((ULONG)
((((double) Pic1.blue[offset])*a + ((double) Pic1.blue[offset+right])*bb+
((double) Pic1.blue[offset+down])*c+((double) Pic1.blue[offset+down+right])*d)*((double)b) +
(((double) Pic2.blue[offset1])*a1 + ((double) Pic2.blue[offset1+right1])*b1+
((double) Pic2.blue[offset1+down1])*c1+((double) Pic2.blue[offset1+down1+right1])*d1)*((double)b2))
)>>10) + bplus - bminus,0),255);
}
else {
(*arrayr) = min(max(((ULONG)
(((((double)Pic1.red[offset])*a + ((double)Pic1.red[offset+right])*bb+
((double)Pic1.red[offset+down])*c+((double)Pic1.red[offset+down+right])*d)
)*((double)r))>>10) + rplus - rminus,0),255);
(*arrayg) = min(max(((ULONG)
(((((double)Pic1.green[offset])*a + ((double)Pic1.green[offset+1])*bb+
((double)Pic1.green[offset+down])*c+((double)Pic1.green[offset+down+right])*d)
)*((double)g))>>10) + gplus - gminus,0),255);
(*arrayb) = min(max(((ULONG)
(((((double)Pic1.blue[offset])*a + ((double)Pic1.blue[offset+1])*bb+
((double)Pic1.blue[offset+down])*c+((double)Pic1.blue[offset+down+right])*d)
)*((double)b))>>10) + bplus - bminus,0),255);
}
}
else {
// Calculate new colours (without AntiAlias)
offset = MyPoint.y*swidth+MyPoint.x;
if ((Single == 1) || (Single == 3)) {
(*arrayr) = min(max(((Pic1.red[offset]*r)>>10) + rplus - rminus,0),255);
(*arrayg) = min(max(((Pic1.green[offset]*g)>>10) + gplus - gminus,0),255);
(*arrayb) = min(max(((Pic1.blue[offset]*b)>>10) + bplus - bminus,0),255);
}
else {
offset1 = MyPoint.y1*swidth+MyPoint.x1;
(*arrayr) = min(max((((Pic2.red[offset1]*r2) +
(Pic1.red[offset]*r))>>10) + rplus - rminus,0),255);
(*arrayg) = min(max((((Pic2.green[offset1]*g2) +
(Pic1.green[offset]*g))>>10) + gplus - gminus,0),255);
(*arrayb) = min(max((((Pic2.blue[offset1]*b2) +
(Pic1.blue[offset]*b))>>10) + bplus - bminus,0),255);
}
}
// If we are skipping columns then copy colour forward
if (DX) {
xr = *arrayr;
xg = *arrayg;
xb = *arrayb;
x++;
for (myx = 0;
(myx < DX) && (x < width);
x++,myx++) {
if (Mode & MODE_ONCE) {
Points += (Depth+4);
}
arrayr++;
*arrayr = xr;
arrayg++;
*arrayg = xg;
arrayb++;
*arrayb = xb;
}
x--;
}
// next column (if not already there)
if (x < width) {
arrayr++;
arrayg++;
arrayb++;
}
}
// end of line, check 'Stop' and 'Help'
OkFlag = HandleProgressIDCMP();
if (handle) {
while (agm = GetAmigaGuideMsg(handle)) {
ReplyAmigaGuideMsg(agm);
}
}
// skip part word at end of line
arrayr += (swidth - width);
arrayg += (swidth - width);
arrayb += (swidth - width);
if (EGS_Win) {
CopyEGS(y,&er,&eg,&eb);
}
// if skipping lines then copy previous line
if (DY) {
y++;
for (myy = 0;
(myy < DY) && (y<height);
y++, myy++) {
memcpy(arrayr, arrayr - swidth, swidth);
arrayr += swidth;
memcpy(arrayg, arrayg - swidth, swidth);
arrayg += swidth;
memcpy(arrayb, arrayb - swidth, swidth);
arrayb += swidth;
if (EGS_Win) {
CopyEGS(y,&er,&eg,&eb);
}
if (Mode & MODE_ONCE) {
Points += ((Depth+4)*width);
}
}
y--;
}
}
if ((Mode & MODE_DELAU) && (!MODE_ONCE)) {
FreeTriangles();
}
// not ok - already displayed an error
if (!OkFlag) {
e = (char *)-1;
}
else {
// Save image
OkFlag = SaveFile();
// Caclulate time (if we have not already)
if (TimerBase) {
GetSysTime(&time2);
t2 = TRUE;
SubTime(&time2,&time1);
}
// Not ok - already displayed error message
if (!OkFlag) {
e = (char *)-1;
}
}
}
}
if (OkFlag && ((Single == 0) || (Single == 2))) {
// Pass to ARexx for processing
if (strcmp(Prescript,"OFF")) {
AddMessage("Prescript for last frame");
f = Frames+1;
Do = 0;
strcpy(buffer,Prescript);
strcat(buffer," %ld");
sprintf(buffer1,buffer,&Arexx);
OkFlag = !SendRxMsg(buffer1,FALSE);
if (!OkFlag) {
e = (char *)-1;
}
if (OkFlag && Do && ((!Pic1_Open) || (Single == 2))) {
if (Pic2_Open) {
Close24bit(&Pic2);
Pic2_Open = FALSE;
}
if (Pic1_Open) {
Close24bit(&Pic1);
Pic1_Open = FALSE;
}
OkFlag = LoadFrames(FALSE,FALSE,TRUE);
if (!OkFlag) {
e = (char *)-1;
}
}
if (OkFlag && Do) {
AddMessage("Saving last frame");
memcpy(RED,Pic2.red,swidth*height);
memcpy(GREEN,Pic2.green,swidth*height);
memcpy(BLUE,Pic2.blue,swidth*height);
OkFlag = SaveFile();
if (!OkFlag) {
e = (char *)-1;
}
}
}
}
}
AddMessage("Cleaning up");
if ((Mode & MODE_DELAU) && (MODE_ONCE)) {
FreeTriangles();
}
DeleteAllPoints();
if (RED) FreeVec(RED);
if (GREEN) FreeVec(GREEN);
if (BLUE) FreeVec(BLUE);
if (OScrn) {
FreeScreen24(OScrn);
}
else { // Should not need this if else
if (!PPM) {
if (Planes[0]) FreeRaster(Planes[0],width,height);
if (Planes[1]) FreeRaster(Planes[1],width,height);
if (Planes[2]) FreeRaster(Planes[2],width,height);
if (!DCTV3) {
if (Planes[3]) FreeRaster(Planes[3],width,height);
if (!BW16 && !DCTV4) {
if (Planes[4]) FreeRaster(Planes[4],width,height);
if (Planes[5]) FreeRaster(Planes[5],width,height);
if (!HAM6) {
if (Planes[6]) FreeRaster(Planes[6],width,height);
if (Planes[7]) FreeRaster(Planes[7],width,height);
if (!HAM8 && !BW256) {
if (Planes[8]) FreeRaster(Planes[8],width,height);
if (Planes[9]) FreeRaster(Planes[9],width,height);
if (Planes[10]) FreeRaster(Planes[10],width,height);
if (Planes[11]) FreeRaster(Planes[11],width,height);
if (Planes[12]) FreeRaster(Planes[12],width,height);
if (Planes[13]) FreeRaster(Planes[13],width,height);
if (Planes[14]) FreeRaster(Planes[14],width,height);
if (Planes[15]) FreeRaster(Planes[15],width,height);
if (Planes[16]) FreeRaster(Planes[16],width,height);
if (Planes[17]) FreeRaster(Planes[17],width,height);
if (Planes[18]) FreeRaster(Planes[18],width,height);
if (Planes[19]) FreeRaster(Planes[19],width,height);
if (Planes[20]) FreeRaster(Planes[20],width,height);
if (Planes[21]) FreeRaster(Planes[21],width,height);
if (Planes[22]) FreeRaster(Planes[22],width,height);
if (Planes[23]) FreeRaster(Planes[23],width,height);
}
}
}
}
}
}
if (!Alloced && !e) {
e = "Error AllocVec for output";
e1 = NULL;
hnum = H_AllocVec;
}
}
else {
e = (char *)-1;
}
if (OkFlag) {
e = (char *)-1;
}
if (!e) {
e = "Error Opening points file";
e1 = NULL;
hnum = H_OpenPoints;
}
if (Pic2_Open) {
Close24bit(&Pic2);
Pic2_Open = FALSE;
}
if (Pic1_Open) {
Close24bit(&Pic1);
Pic1_Open = FALSE;
}
if (plane0) MyFreeVec(plane0);
if (plane1) MyFreeVec(plane1);
if (plane2) MyFreeVec(plane2);
if (plane3) MyFreeVec(plane3);
if (plane4) MyFreeVec(plane4);
if (plane5) MyFreeVec(plane5);
if (plane6) MyFreeVec(plane6);
if (plane7) MyFreeVec(plane7);
// reset requesters
process->pr_WindowPtr = oldWindowPtr;
}
else {
e = "Error opening progress window";
e1 = NULL;
hnum = H_Progress;
}
// close down everything
CloseProgressWindow();
CloseDownScreen();
MyArgArrayDone();
if (EGS) {
if (EGS_Win) {
EI_CloseWindow(EGS_Win);
}
if (EGS_BitMap) {
E_DisposeBitMap(EGS_BitMap);
}
}
if (EGSIntuiBase) {
CloseLibrary(EGSIntuiBase);
}
if (EGSGfxBase) {
CloseLibrary(EGSGfxBase);
}
if (EGSBase) {
CloseLibrary(EGSBase);
}
CloseLibrary(DiskfontBase);
}
if (!e) {
e = "Unable to Open %s";
e1 = "diskfont.library(36)";
hnum = H_Library;
}
CloseLibrary(IconBase);
}
if (!e) {
e = "Unable to Open %s";
e1 = "icon.library(37)";
hnum = H_Library;
}
CloseLibrary(UtilityBase);
}
if (!e) {
e = "Unable to Open %s";
e1= "utility.library(37)";
hnum = H_Library;
}
CloseLibrary(AslBase);
}
if (!e) {
e = "Unable to Open %s";
e1 = "asl.library(37)";
hnum = H_Library;
}
CloseLibrary(GadToolsBase);
}
if (!e) {
e = "Unable to Open %s";
e1 = "gadtools.library(37)";
hnum = H_Library;
}
CloseLibrary(LayersBase);
}
if (!e) {
e = "Unable to Open %s";
e1 = "layers.library(37)";
hnum = H_Library;
}
CloseLibrary(GfxBase);
}
if (!e) {
e = "Unable to Open %s";
e1 = "graphics.library(37)";
hnum = H_Library;
}
CloseLibrary(IFFParseBase);
}
if (!e) {
e = "Unable to Open %s";
e1 = "iffparse.library(37)";
hnum = H_Library;
}
CloseLibrary(RexxSysBase);
}
if (!e) {
e = "Unable to Open %s";
e1 = "rexxsyslib.library(0)";
hnum = H_Library;
}
// Display an error message
if (e != (char *)-1) {
Error(e,"Quit",e1,hnum);
}
}
if (OpalBase) {
CloseLibrary((struct Library *)OpalBase);
}
if (TimerBase) {
CloseDevice((struct IORequest *) &tr);
}
if (AmigaGuideBase) {
if (handle) {
CloseAmigaGuide(handle);
}
CloseLibrary(AmigaGuideBase);
}
if (NoFragBase) {
FreeMemoryChain(Chain,TRUE);
CloseLibrary((struct Library *)NoFragBase);
}
if (DCTVBase) {
CloseLibrary(DCTVBase);
}
if (ReqToolsBase) {
CloseLibrary(ReqToolsBase);
}
if (IntuitionBase) {
CloseLibrary((struct Library *)IntuitionBase);
}
return 0;
}
extern UWORD FileFormat = 0;
/* recognized file formats */
#define FORMAT_IFF 1
#define FORMAT_JPEG 2
#define FORMAT_GIF 3
#define FORMAT_PPM 4
#define FORMAT_TARGA 5
/* Opens a 24 bit image
* filename = name of file
* pic = structure to update
* GUI = TRUE to display error message
* Returns TRUE if ok
*/
BOOL
Load24bit(char *filename,struct Picture *pic,BOOL GUI) {
char *e = NULL; // Error message main text
char *e1 = NULL; // sub text,
struct RastPort RP, // Rastport
TRP; // Temp rastport
struct BitMap BM, // Bitmap
TBM; // Temp bitmap
ULONG hnum = 0; // Help on error
BOOL OkFlag=TRUE; // Still OK?
char buffer[256], // For Rexx Scripts
buffer1[256];
long Err; // Opal error
BPTR fh;
UBYTE zbuffer[5]="\0\0\0\0";
decompress_info_ptr info; // Load JPEG stuff
UWORD i,j;
LONG penno;
struct RastPort Rp; // Rast port for conversion
UBYTE *rx,*gx,*bx;
UBYTE rr,gg,bb;
UWORD EHB;
BOOL isHAM6 = FALSE;
BOOL isHAM8 = FALSE;
BOOL isEHB = FALSE;
struct DisplayInfo queryinfo;
DisplayInfoHandle dhandle;
struct DCTVCvtHandle *chandle; // DCTV conversion stuff
UWORD *DCTVcolors; // DCTV palette
if (filename) {
// Load image processing
if (strcmp(Loadscript,"OFF")) {
strcpy(buffer,Loadscript);
strcat(buffer," %ld %ld %ld %ld %s");
sprintf(buffer1,buffer,f+Start-1,Frames,Single,(pic==&Pic1)?0:1,filename);
AddMessage("Loadscript processing");
OkFlag = !SendRxMsg(buffer1,FALSE);
if (!OkFlag) {
e = (char *)-1;
GUI = FALSE; // Do not display error
}
}
pic->rgbonelot = FALSE;
if (!e) {
// determine file format
if (fh = Open(filename,MODE_OLDFILE)) {
FRead(fh,zbuffer,4,1);
if ((!strcmp(zbuffer,"FORM")) ||
(!strcmp(zbuffer,"CAT ")) ||
(!strcmp(zbuffer,"LIST"))) {
FileFormat = FORMAT_IFF;
}
else {
if ((zbuffer[0] == 0xFF) &&
(zbuffer[1] == 0xD8)) {
FileFormat = FORMAT_JPEG;
}
else {
if ((zbuffer[0] == 'G') &&
(zbuffer[1] == 'I') &&
(zbuffer[2] == 'F')) {
FileFormat = FORMAT_GIF;
}
else {
if ((zbuffer[0] == 'P') &&
((zbuffer[1] == '2') ||
(zbuffer[1] == '3') ||
(zbuffer[1] == '5') ||
(zbuffer[1] == '6'))) {
FileFormat = FORMAT_PPM;
}
else {
FileFormat = FORMAT_TARGA;
}
}
}
}
Close(fh);
}
else {
e = "Error opening file '%s'";
e1 = filename;
hnum = H_Open;
OkFlag = FALSE;
}
}
if (OkFlag) {
AddMessage((pic == &Pic2)?"Loading image 2":"Loading image 1");
}
// We have a file name
if (OkFlag && (FileFormat != FORMAT_IFF)) {
// Not an IFF file so use JPEG code
AddMessage((FileFormat == FORMAT_JPEG)?"Loading JFIF":
(FileFormat == FORMAT_GIF)?"Loading GIF":
(FileFormat == FORMAT_PPM)?"Loading PPM":
(FileFormat == FORMAT_TARGA)?"Loading Targa?":
"Loading ?");
if ((info = LoadJPEG(filename,0,NULL,NULL,NULL,NULL)) &&
(info->output_file)) {
AddMessage("Allocating work memory");
pic->rgbonelot = TRUE;
pic->red = (UBYTE *)info->output_file;
pic->green = pic->red + (((info->image_width+15)>>4)<<4) * info->image_height;
pic->blue = pic->green + (((info->image_width+15)>>4)<<4) * info->image_height;
// Allocate temp bit maps if first image and no OpalVision save
if ((OVFormat) || (plane0) ||
((plane0 = MyAllocVec((((width+15)>>4)<<4),MEMF_CHIP|MEMF_CLEAR)) &&
(plane1 = MyAllocVec((((width+15)>>4)<<4),MEMF_CHIP|MEMF_CLEAR)) &&
(plane2 = MyAllocVec((((width+15)>>4)<<4),MEMF_CHIP|MEMF_CLEAR)) &&
(plane3 = MyAllocVec((((width+15)>>4)<<4),MEMF_CHIP|MEMF_CLEAR)) &&
(plane4 = MyAllocVec((((width+15)>>4)<<4),MEMF_CHIP|MEMF_CLEAR)) &&
(plane5 = MyAllocVec((((width+15)>>4)<<4),MEMF_CHIP|MEMF_CLEAR)) &&
(plane6 = MyAllocVec((((width+15)>>4)<<4),MEMF_CHIP|MEMF_CLEAR)) &&
(plane7 = MyAllocVec((((width+15)>>4)<<4),MEMF_CHIP|MEMF_CLEAR)))) {
return TRUE;
}
else {
e = "Unable to %s";
e1 = "allocate memory for bitmap";
hnum = H_AllocPlanes;
}
}
}
if (OkFlag && (FileFormat == FORMAT_IFF)) {
// Load iff
AddMessage("Loading IFF");
if (pic->ilbm = (struct ILBMInfo *)MyAllocMem(sizeof(struct ILBMInfo),MEMF_PUBLIC|MEMF_CLEAR)) {
// IFF stuff
if (pic->ilbm->ParseInfo.iff = AllocIFF()) {
// more iff stuff
pic->ilbm->ParseInfo.propchks = props;
pic->ilbm->ParseInfo.collectchks = nowt;
pic->ilbm->ParseInfo.stopchks = stops;
// Load the image using IFF routines
if (!(loadbrush(pic->ilbm,filename))) {
// Close the file and validate
closeifile(&(pic->ilbm->ParseInfo));
pwidth = width < 320 ? 320 : width;
pheight = height < 200 ? 200 : height;
pmode = pwidth >= 640 ? HIRES : 0L;
pmode |= pheight >= 400 ? LACE : 0L;
// ?????? width = pic->ilbm->Bmhd.w;
// Allocate chunky bit maps
AddMessage("Allocating Bitmaps");
if ((pic->red = AllocVec(((((pic->ilbm->Bmhd.w+15)>>4)<<4)*pic->ilbm->Bmhd.h),MEMF_CLEAR)) &&
(pic->green = AllocVec(((((pic->ilbm->Bmhd.w+15)>>4)<<4)*pic->ilbm->Bmhd.h),MEMF_CLEAR)) &&
(pic->blue = AllocVec(((((pic->ilbm->Bmhd.w+15)>>4)<<4)*pic->ilbm->Bmhd.h),MEMF_CLEAR)) &&
// Allocate temp bit maps if first image and no OpalVision save
((OVFormat && (pic->ilbm->Bmhd.nPlanes != 24)) || (plane0) ||
((plane0 = MyAllocVec((((width+15)>>4)<<4),MEMF_CHIP|MEMF_CLEAR)) &&
(plane1 = MyAllocVec((((width+15)>>4)<<4),MEMF_CHIP|MEMF_CLEAR)) &&
(plane2 = MyAllocVec((((width+15)>>4)<<4),MEMF_CHIP|MEMF_CLEAR)) &&
(plane3 = MyAllocVec((((width+15)>>4)<<4),MEMF_CHIP|MEMF_CLEAR)) &&
(plane4 = MyAllocVec((((width+15)>>4)<<4),MEMF_CHIP|MEMF_CLEAR)) &&
(plane5 = MyAllocVec((((width+15)>>4)<<4),MEMF_CHIP|MEMF_CLEAR)) &&
(plane6 = MyAllocVec((((width+15)>>4)<<4),MEMF_CHIP|MEMF_CLEAR)) &&
(plane7 = MyAllocVec((((width+15)>>4)<<4),MEMF_CHIP|MEMF_CLEAR))))) {
if (pic->ilbm->Bmhd.nPlanes == 24) {
// Convert 24 bit planar to chunky
AddMessage("Converting 24 bit to Chunky");
// Initialise rast ports/bitmaps
InitRastPort(&RP);
InitRastPort(&TRP);
InitBitMap(&TBM,8,pic->ilbm->Bmhd.w,1);
TRP.BitMap = &TBM;
TBM.Planes[0]=plane0;
TBM.Planes[1]=plane1;
TBM.Planes[2]=plane2;
TBM.Planes[3]=plane3;
TBM.Planes[4]=plane4;
TBM.Planes[5]=plane5;
TBM.Planes[6]=plane6;
TBM.Planes[7]=plane7;
InitBitMap(&BM,8,pic->ilbm->Bmhd.w,pic->ilbm->Bmhd.h);
RP.BitMap = &BM;
BM.Planes[0] = pic->ilbm->brbitmap->Planes[0];
BM.Planes[1] = pic->ilbm->brbitmap->Planes[1];
BM.Planes[2] = pic->ilbm->brbitmap->Planes[2];
BM.Planes[3] = pic->ilbm->brbitmap->Planes[3];
BM.Planes[4] = pic->ilbm->brbitmap->Planes[4];
BM.Planes[5] = pic->ilbm->brbitmap->Planes[5];
BM.Planes[6] = pic->ilbm->brbitmap->Planes[6];
BM.Planes[7] = pic->ilbm->brbitmap->Planes[7];
// Convert red to chunky
ReadPixelArray8(&RP,0,0,pic->ilbm->Bmhd.w-1,pic->ilbm->Bmhd.h-1,pic->red,&TRP);
WaitBlit();
BM.Planes[0] = pic->ilbm->brbitmap->Planes[8];
BM.Planes[1] = pic->ilbm->brbitmap->Planes[9];
BM.Planes[2] = pic->ilbm->brbitmap->Planes[10];
BM.Planes[3] = pic->ilbm->brbitmap->Planes[11];
BM.Planes[4] = pic->ilbm->brbitmap->Planes[12];
BM.Planes[5] = pic->ilbm->brbitmap->Planes[13];
BM.Planes[6] = pic->ilbm->brbitmap->Planes[14];
BM.Planes[7] = pic->ilbm->brbitmap->Planes[15];
// and green
ReadPixelArray8(&RP,0,0,pic->ilbm->Bmhd.w-1,pic->ilbm->Bmhd.h-1,pic->green,&TRP);
WaitBlit();
BM.Planes[0] = pic->ilbm->brbitmap->Planes[16];
BM.Planes[1] = pic->ilbm->brbitmap->Planes[17];
BM.Planes[2] = pic->ilbm->brbitmap->Planes[18];
BM.Planes[3] = pic->ilbm->brbitmap->Planes[19];
BM.Planes[4] = pic->ilbm->brbitmap->Planes[20];
BM.Planes[5] = pic->ilbm->brbitmap->Planes[21];
BM.Planes[6] = pic->ilbm->brbitmap->Planes[22];
BM.Planes[7] = pic->ilbm->brbitmap->Planes[23];
// and blue
ReadPixelArray8(&RP,0,0,pic->ilbm->Bmhd.w-1,pic->ilbm->Bmhd.h-1,pic->blue,&TRP);
WaitBlit();
AddMessage("Cleaning up");
// Set up stuff to write image
// ???? width = pic->ilbm->Bmhd.w;
// ???? height = pic->ilbm->Bmhd.h;
// Unload everything and exit cleanly
unloadbrush(pic->ilbm);
FreeIFF(pic->ilbm->ParseInfo.iff);
MyFreeMem(pic->ilbm,sizeof(struct ILBMInfo));
return TRUE;
}
else {
if (DCTVBase && TestDCTVSignature(pic->ilbm->brbitmap)) {
// Convert DCTV to chunky
if (DCTVcolors = MyAllocVec(2L<<pic->ilbm->Bmhd.nPlanes,MEMF_CLEAR)) {
for (i=0; i < (1L<<pic->ilbm->Bmhd.nPlanes); ++i) {
DCTVcolors[i] = ((pic->ilbm->RGB[i*4+1] & 0xf0) << 4) |
((pic->ilbm->RGB[i*4+2] & 0xf0)) |
((pic->ilbm->RGB[i*4+3] & 0xf0) >> 4);
}
AddMessage("Converting DCTV to Chunky");
if (chandle = AllocDCTVCvtTags(pic->ilbm->brbitmap,
DCTVCVTA_Type, DCTVCVTT_DCTVtoRGB,
DCTVCVTA_Width, (((pic->ilbm->Bmhd.w+15)>>4)<<4),
DCTVCVTA_Height, pic->ilbm->Bmhd.h,
DCTVCVTA_Flags, ((pic->ilbm->camg & LACE)?DCTVCVTF_Lace:0)|
DCTVCVTF_CustomRGBBuf,
DCTVCVTA_ColorTable, DCTVcolors,
TAG_END)) {
chandle->Red = pic->red;
chandle->Green = pic->green;
chandle->Blue = pic->blue;
while (chandle->DstLineNum < chandle->Height) {
CvtDCTVLine(chandle);
if ((chandle->DstLineNum > 0) &&
(chandle->DstLineNum <= chandle->Height)) {
chandle->Red += (((pic->ilbm->Bmhd.w+15)>>4)<<4);
chandle->Green += (((pic->ilbm->Bmhd.w+15)>>4)<<4);
chandle->Blue += (((pic->ilbm->Bmhd.w+15)>>4)<<4);
}
}
MyFreeVec(DCTVcolors);
FreeDCTVCvt(chandle);
// Unload everything and exit cleanly
unloadbrush(pic->ilbm);
FreeIFF(pic->ilbm->ParseInfo.iff);
MyFreeMem(pic->ilbm,sizeof(struct ILBMInfo));
return TRUE;
}
MyFreeVec(DCTVcolors);
}
}
else {
// determine special IFF mode
if ((dhandle = FindDisplayInfo(pic->ilbm->camg)) &&
(GetDisplayInfoData(dhandle,(UBYTE *)&queryinfo,sizeof(queryinfo),DTAG_DISP,NULL))) {
if ((pic->ilbm->Bmhd.nPlanes == 6) && (queryinfo.PropertyFlags & DIPF_IS_HAM)) {
AddMessage("Converting HAM6 to Chunky");
isHAM6 = TRUE;
}
else {
if ((pic->ilbm->Bmhd.nPlanes == 8) && (queryinfo.PropertyFlags & DIPF_IS_HAM)) {
isHAM8 = TRUE;
AddMessage("Converting HAM8 to Chunky");
}
else {
if ((pic->ilbm->Bmhd.nPlanes == 6) && (queryinfo.PropertyFlags & DIPF_IS_EXTRAHALFBRITE)) {
isEHB = TRUE;
AddMessage("Converting EHB to Chunky");
}
else {
AddMessage("Converting ILBM to Chunky");
}
}
}
}
// Convert to chunky
InitRastPort(&Rp);
Rp.BitMap = pic->ilbm->brbitmap;
rx = pic->red;
gx = pic->green;
bx = pic->blue;
// For each line
for (j = 0;
j < height;
++j) {
// Convert each column
// Note: this is very ineffecient in that it uses
// ReadPixel().
// But the cost is fairly small compared to the render time
if (isHAM6) {
rr = gg = bb = 0;
for (i = 0;
i < width;
++i) {
penno = ReadPixel(&Rp,i,j);
switch (penno & 0x30) {
case 0:
*rx++ = rr = pic->ilbm->RGB[penno*4+1];
*gx++ = gg = pic->ilbm->RGB[penno*4+2];
*bx++ = bb = pic->ilbm->RGB[penno*4+3];
break;
case 0x10:
*rx++ = rr;
*gx++ = gg;
*bx++ = bb = (penno&0xf)|((penno&0xf)<<4);
break;
case 0x20:
*rx++ = rr = (penno&0xf)|((penno&0xf)<<4);
*gx++ = gg;
*bx++ = bb;
break;
case 0x30:
*rx++ = rr;
*gx++ = gg = (penno&0xf)|((penno&0xf)<<4);
*bx++ = bb;
break;
}
}
}
else {
if (isHAM8) {
rr = gg = bb = 0;
for (i = 0;
i < width;
++i) {
penno = ReadPixel(&Rp,i,j);
switch (penno & 0xc0) {
case 0:
*rx++ = rr = pic->ilbm->RGB[penno*4+1];
*gx++ = gg = pic->ilbm->RGB[penno*4+2];
*bx++ = bb = pic->ilbm->RGB[penno*4+3];
break;
case 0x40:
*rx++ = rr;
*gx++ = gg;
*bx++ = bb = (penno&0x3f)<<2;
break;
case 0x80:
*rx++ = rr = (penno&0x3f)<<2;
*gx++ = gg;
*bx++ = bb;
break;
case 0xc0:
*rx++ = rr;
*gx++ = gg = (penno&0x3f)<<2;
*bx++ = bb;
break;
}
}
}
else {
if (isEHB) {
for (i = 0;
i < width;
++i) {
penno = ReadPixel(&Rp,i,j);
EHB = (penno & 0x20)?1:0;
penno &= 0x1f;
*rx++ = pic->ilbm->RGB[penno*4+1]>>EHB;
*gx++ = pic->ilbm->RGB[penno*4+2]>>EHB;
*bx++ = pic->ilbm->RGB[penno*4+3]>>EHB;
}
}
else {
for (i = 0;
i < width;
++i) {
penno = ReadPixel(&Rp,i,j);
*rx++ = pic->ilbm->RGB[penno*4+1];
*gx++ = pic->ilbm->RGB[penno*4+2];
*bx++ = pic->ilbm->RGB[penno*4+3];
}
}
}
}
rx += ((((width+15)>>4)<<4)-width);
gx += ((((width+15)>>4)<<4)-width);
bx += ((((width+15)>>4)<<4)-width);
}
AddMessage("Cleaning up");
unloadbrush(pic->ilbm);
FreeIFF(pic->ilbm->ParseInfo.iff);
MyFreeMem(pic->ilbm,sizeof(struct ILBMInfo));
return TRUE;
}
}
}
if (!e) {
e = "Unable to %s";
e1 = "allocate memory for bitmap";
hnum = H_AllocPlanes;
}
}
if (!e) {
e = "Error loading '%s'";
e1 = filename;
hnum = H_Load;
}
unloadbrush(pic->ilbm);
FreeIFF(pic->ilbm->ParseInfo.iff);
}
if (!e) {
e = "Unable to %s";
e1 = "AllocIFF";
hnum = H_AllocIFF;
}
MyFreeMem(pic->ilbm,sizeof(struct ILBMInfo));
}
if (!e) {
e = "Unable to '%s'";
e1 = "AllocMem for ILBMInfo";
hnum = H_AllocILBM;
}
}
if (OkFlag && OpalBase) {
// If we still have not loaded the image then try opal.library as a last resort
AddMessage("Loading using opal.library");
Err = LoadImage24(NULL,filename,VIRTUALSCREEN24|FORCE24);
if (Err < OL_ERR_MAXERR) {
switch (Err) {
case OL_ERR_OUTOFMEM:
e = "Failure - Out of memory - loading '%s'";
break;
case OL_ERR_OPENFILE:
e = "Failure - Opening file - loading '%s'";
break;
case OL_ERR_FORMATUNKNOWN:
e = "Failure - Unknown Format - loading '%s'";
break;
case OL_ERR_NOTILBM:
e = "Failure - Not an ILBM file - loading '%s'";
break;
case OL_ERR_FILEREAD:
e = "Failure - Reading file - loading '%s'";
break;
case OL_ERR_BADIFF:
e = "Failure - Bad IFF Format - loading '%s'";
break;
case OL_ERR_CANTCLOSE:
e = "Failure - Can not Close - loading '%s'";
break;
case OL_ERR_BADJPEG:
e = "Failure - Bad JPEG Format - loading '%s'";
break;
case OL_ERR_UNSUPPORTED:
e = "Failure - Unsupported Format - loading '%s'";
break;
case OL_ERR_CTRLC:
case OL_ERR_NOTHUMBNAIL:
case OL_ERR_OPENSCREEN:
case OL_ERR_FILEWRITE:
default:
e = "Failure - Unknown problem - loading '%s'";
break;
}
e1 = filename;
hnum = HE_OpalVision;
}
else {
AddMessage("Allocating Bitmaps");
pic->OScrn = (struct OpalScreen *)Err;
// Allocate chunky bit maps
if ((pic->red = AllocVec(((((pic->OScrn->Width+15)>>4)<<4)*pic->OScrn->Height),MEMF_CLEAR)) &&
(pic->green = AllocVec(((((pic->OScrn->Width+15)>>4)<<4)*pic->OScrn->Height),MEMF_CLEAR)) &&
(pic->blue = AllocVec(((((pic->OScrn->Width+15)>>4)<<4)*pic->OScrn->Height),MEMF_CLEAR)) &&
// Allocate temp bit maps if first image and no OpalVision save
((OVFormat) || (plane0) ||
((plane0 = MyAllocVec((((width+15)>>4)<<4),MEMF_CHIP|MEMF_CLEAR)) &&
(plane1 = MyAllocVec((((width+15)>>4)<<4),MEMF_CHIP|MEMF_CLEAR)) &&
(plane2 = MyAllocVec((((width+15)>>4)<<4),MEMF_CHIP|MEMF_CLEAR)) &&
(plane3 = MyAllocVec((((width+15)>>4)<<4),MEMF_CHIP|MEMF_CLEAR)) &&
(plane4 = MyAllocVec((((width+15)>>4)<<4),MEMF_CHIP|MEMF_CLEAR)) &&
(plane5 = MyAllocVec((((width+15)>>4)<<4),MEMF_CHIP|MEMF_CLEAR)) &&
(plane6 = MyAllocVec((((width+15)>>4)<<4),MEMF_CHIP|MEMF_CLEAR)) &&
(plane7 = MyAllocVec((((width+15)>>4)<<4),MEMF_CHIP|MEMF_CLEAR))))) {
AddMessage("Converting Opal to Chunky");
OVtoRGB(pic->OScrn,&(pic->red),0,0,((pic->OScrn->Width+15)>>4)<<4,pic->OScrn->Height);
}
else {
e = "Unable to %s";
e1 = "allocate memory for bitmap";
hnum = H_AllocPlanes;
}
FreeScreen24(pic->OScrn);
if (!e) {
return TRUE;
}
}
}
else {
if (!e) {
e = "No opal.library";
hnum = HE_NoOpal;
}
}
}
Close24bit(pic);
// Display an error message if required
if (GUI)
Error(e,"Quit",e1,hnum);
return(FALSE);
}
/* Close an image clearing everything down */
void
Close24bit(struct Picture *pic) {
if (pic) {
if (pic->rgbonelot) {
if (pic->red) {
FreeVec(pic->red);
}
pic->red = NULL;
pic->green = NULL;
pic->blue = NULL;
}
else {
if (pic->red) {
FreeVec(pic->red);
pic->red = NULL;
}
if (pic->green) {
FreeVec(pic->green);
pic->green = NULL;
}
if (pic->blue) {
FreeVec(pic->blue);
pic->blue = NULL;
}
}
}
}
/* Open a file
* Returns : TRUE if ok
* filename : name of file, or NULL for requester
*/
BOOL
MyOpen(char *filename,BOOL JustPoints) {
char dirname[257];
char rtfilename[108] = "\0"; // reqtools filename from requester
char *ifilename=NULL;
BOOL ok=TRUE;
BPTR fh;
char buffer[257];
LONG w,h;
LONG xx,x1,yy,y1;
UWORD i; // General index
struct FileRequester *filereq; // For file requester
struct rtFileRequester *rtfilereq;
struct MyPoint *MyPoint;
// If filename supplied then use it otherwise use file requester
if (filename) {
ifilename = filename;
}
else {
if (MatchToolValue(MyArgString("REQTOOLS","YES",FALSE),"ALL") &&
(rtfilereq = (struct rtFileRequester *)rtAllocRequestA(RT_FILEREQ,NULL))) {
if (rtFileRequestA(rtfilereq,rtfilename,"TSMorph-render - Pick project",NULL)) {
strncpy(dirname,rtfilereq->Dir,256);
if (AddPart(dirname,rtfilename,256)) {
ifilename=dirname;
}
}
rtFreeRequest(rtfilereq);
}
else {
if (filereq = (struct FileRequester *)AllocFileRequest()) {
if (AslRequestTags((APTR) filereq,ASL_Hail,(Tag) "TSMorph-render - Pick project",TAG_DONE)) {
strncpy(dirname,filereq->rf_Dir,256);
if (AddPart(dirname,filereq->rf_File,256)) {
ifilename=dirname;
}
}
FreeFileRequest(filereq);
}
}
}
// If user did not cancel
if (ifilename) {
OpenNewArgs(ifilename); // Load new parameters
// Open file and skip the WB displayable names
if (fh=Open(ifilename,MODE_OLDFILE)) {
FGets(fh,buffer,256);
if (JustPoints && strcmp(buffer,"TSMorph 2.0\n")) {
Error("Invalid file format\nLine '%s'","Quit",buffer,H_FileFormat);
ok = FALSE;
}
else {
if (!JustPoints) {
Pic1.filename[0]=0;
Pic2.filename[0]=0;
// Keep file name
strcpy(MyFileName,ifilename);
strcat(MyFileName,".%03ld");
if (strcmp(buffer,"TSMorph 1.2\n")) {
Error("Assuming version 1.0 file format","OK",NULL,HE_OldFormat);
}
else {
FGets(fh,buffer,256);
}
if (strlen(buffer)) {
buffer[strlen(buffer)-1]=0;
}
strcpy(Pic1.filename,buffer);
FGets(fh,buffer,256);
if (strlen(buffer)) {
buffer[strlen(buffer)-1]=0;
}
strcpy(Pic2.filename,buffer);
// Get file name, set progress and try and load image
FGets(fh,buffer,256);
if (strlen(buffer)) {
buffer[strlen(buffer)-1]=0;
}
if (buffer[0]) {
strcpy(Pic1.filename,buffer);
}
FGets(fh,buffer,256);
if (strlen(buffer)) {
buffer[strlen(buffer)-1]=0;
}
if (buffer[0]) {
strcpy(Pic2.filename,buffer);
}
// Loaded both so get anim name
FGets(fh,AnimName,256);
if (strlen(AnimName)) {
AnimName[strlen(AnimName)-1]=0;
}
// Read and validate general information
FGets(fh,buffer,256);
if (ok && (sscanf(buffer,"w=%ld,h=%ld,Frames=%ld,Single=%ld,Start=%ld",&w,&h,&Frames,&Single,&Start) != 5)) {
Error("Invalid file format\nLine '%s'","Quit",buffer,H_FileFormat);
}
else {
width = w; // ???????
height = h; // ???????
if (ok &&
((w != width) ||
(h != height))) {
Error("Size does not match image\nLine '%s'","Quit",buffer,H_SizeMatch);
ok = FALSE;
}
}
}
}
if (ok) {
PointCount = 0;
// Read and store all the points
while (ok &&
FGets(fh,buffer,256) &&
(sscanf(buffer,"x=%ld,y=%ld,x1=%ld,y1=%ld",&xx,&yy,&x1,&y1) == 4)) {
if ((xx<0)||(xx>(width-1)) ||
(yy<0)||(yy>(height-1))) {
Error("Point out of range\nLine '%s'","Quit",buffer,H_Range);
ok = FALSE;
}
if (MyPoint = MyAllocMem(sizeof(struct MyPoint),MEMF_CLEAR)) {
MyPoint->x = xx;
MyPoint->y = yy;
MyPoint->x1 = x1;
MyPoint->y1 = y1;
AddTail(&PointList,(struct Node *)MyPoint);
++PointCount;
}
else {
ok = FALSE;
}
}
}
Depth = MyArgInt("DEPTH",2,FALSE);
Depth = min(Depth,20);
Mode = MyArgInt("MODE",0,FALSE);
if ((Single == 2) || (Single == 3)) {
Mode &= ~MODE_ONCE; // Irrelevant for anims
}
if (ok) {
// if ((PointsAlloc = MyAllocVec((max(PointCount,23) + 3)*sizeof(struct MyPoint *) *
if ((PointsAlloc = MyAllocVec((Depth + 4)*sizeof(struct MyPoint *) * // + 1 = NumPoints
((Mode & MODE_ONCE)?width*height:1),MEMF_CLEAR)) &&
(PointsX = MyAllocVec((max(PointCount,23) + 3)*sizeof(struct MyPoint *),MEMF_CLEAR)) &&
(PointsY = MyAllocVec((max(PointCount,23) + 3)*sizeof(struct MyPoint *),MEMF_CLEAR))) {
// Set up x and y order
Points = PointsAlloc;
i = 0;
for (MyPoint = (struct MyPoint *)PointList.lh_Head;
MyPoint->MyNode.mln_Succ;
MyPoint = (struct MyPoint *)MyPoint->MyNode.mln_Succ) {
PointsX[i] = MyPoint;
PointsY[i] = MyPoint;
++i;
}
}
else {
Error("Out of memory for points","Quit",NULL,H_MemPointsR);
ok = FALSE;
}
}
// Close file and cleanup
if (!Close(fh)) {
if (ok) {
Error("Error closing file '%s'","Quit",filename,H_CloseFile);
ok = FALSE;
}
}
}
else {
Error("Error opening file '%s'","Quit",filename,H_Open);
ok = FALSE;
}
}
else {
ok = FALSE;
}
return ok;
}
/* Delete all the points from the list */
void
DeleteAllPoints(void) {
struct MyPoint *MyPoint;
// Loops looking at the head every time and deletes it
while ((MyPoint =(struct MyPoint *)PointList.lh_Head)->MyNode.mln_Succ) {
Remove((struct Node *)MyPoint);
MyFreeMem(MyPoint,sizeof(struct MyPoint));
}
if (PointsAlloc) {
MyFreeVec(PointsAlloc);
PointsAlloc = NULL;
}
if (PointsX) {
MyFreeVec(PointsX);
PointsX = NULL;
}
if (PointsY) {
MyFreeVec(PointsY);
PointsY = NULL;
}
}
// The following is the alogrithm stuff!!!!!
// and is not particularly well commented!
/* Given a point, returns the coordinates in the first and last image */
static void __regargs
FindPoint(struct MyPoint *RetPoint,BOOL Everything) {
UWORD KeepCount;
struct MyPoint *MyPoint,*MyPoint1,*MyPoint2;
struct MyPoint **p,**p1,**p2,**p3;
UWORD i1,i2;
UWORD i,j,k;
LONG checkdiff;
BOOL flag;
UWORD NumPoints;
UWORD add;
struct Triangle *T;
UWORD MinX,MaxX,CurX; // Pointers to X array
UWORD MinY,MaxY,CurY; // Pointers to Y array
int l;
if (!(Mode & MODE_ONCE) || !Everything) {
if (Mode & MODE_SEARCH) {
p = PointsX;
for (i = 0;
i < PointCount;
++i) {
(*p)->Used = FALSE;
++p;
}
flag = FALSE;
CurX = PointCount>>1;
add = CurX>>1;
if (!add) {
add = 1;
}
p = &(PointsX[CurX]);
p2 = &(PointsX[PointCount -1]);
while (!flag) {
if ((*p)->Cx == x) {
flag = TRUE;
MinX = CurX-1;
MaxX = CurX+1;
}
else {
if ((*p)->Cx < x) {
++p;
if ((*p)->Cx > x) {
flag = TRUE;
MinX = CurX;
MaxX = CurX+1;
}
else {
CurX += add;
p += (add-1);
if (p == p2) {
flag = TRUE;
MinX = CurX-1;
MaxX = CurX;
}
}
}
else {
CurX -= add;
if (!CurX) {
flag = TRUE;
MinX = 0;
MaxX = 1;
}
else {
p -= add;
}
}
}
if (!flag) {
add >>= 1;
if (!add) {
add = 1;
}
}
}
flag = FALSE;
CurY = PointCount>>1;
add = CurY>>1;
if (!add) {
add = 1;
}
p = &(PointsY[CurY]);
p2 = &(PointsY[PointCount -1]);
while (!flag) {
if ((*p)->Cy == y) {
flag = TRUE;
MinY = CurY-1;
MaxY = CurY+1;
}
else {
if ((*p)->Cy < y) {
++p;
if ((*p)->Cy > y) {
flag = TRUE;
MinY = CurY;
MaxY = CurY+1;
}
else {
CurY += add;
p += (add-1);
if (p == p2) {
flag = TRUE;
MinY = CurY-1;
MaxY = CurY;
}
}
}
else {
CurY -= add;
if (!CurY) {
flag = TRUE;
MinY = 0;
MaxY = 1;
}
else {
p -= add;
}
}
}
if (!flag) {
add >>= 1;
if (!add) {
add = 1;
}
}
}
NumPoints = 0; // Count of points found so far
while ((NumPoints < (Depth+3)) && (NumPoints < PointCount)) {
p = &(PointsX[MinX]);
for (i = MinX;
(i <= MaxX) && (NumPoints < (Depth+3));
++i,++p) {
if (!(*p)->Used) {
flag = TRUE;
MyPoint = *p;
p1 = &(PointsY[MinY]);
for (j = MinY;
(j <= MaxY) && flag;
++j,++p1) {
if (MyPoint == *p1) {
if (x < MyPoint->Cx) {
MyPoint->xdiff = MyPoint->Cx - x;
}
else {
MyPoint->xdiff = x - MyPoint->Cx;
}
if (y < MyPoint->Cy) {
MyPoint->ydiff = MyPoint->Cy - y;
}
else {
MyPoint->ydiff = y - MyPoint->Cy;
}
MyPoint->Cdiff = MyPoint->xdiff * MyPoint->xdiff +
MyPoint->ydiff * MyPoint->ydiff;
flag = TRUE;
p2 = Points;
for (k = 0;
flag && (k < NumPoints);
++k,++p2) {
if ((*p2)->Cdiff > MyPoint->Cdiff) {
MyPoint1 = *p2;
*p2 = MyPoint;
p3 = p2;
++p3;
for (l = k+1;
l < NumPoints;
++l,++p3) {
MyPoint2 = *p3;
*p3 = MyPoint1;
MyPoint1 = MyPoint2;
}
flag = FALSE;
}
}
if (flag) {
*p2 = MyPoint;
}
MyPoint->Used = TRUE;
NumPoints++;
flag = FALSE;
}
}
}
}
if (MinX > 0) {
--MinX;
}
if (MinY > 0) {
--MinY;
}
if (MaxX < (PointCount -1)) {
++MaxX;
}
if (MaxY < (PointCount -1)) {
++MaxY;
}
}
}
else {
NumPoints = Depth+3;
p = Points;
for (i = 0;
i < NumPoints;
++i) {
*(p++) = &BigPoint;
}
// Set up differences
p2 = &(Points[Depth+2]);
for (MyPoint = (struct MyPoint *)PointList.lh_Head;
MyPoint->MyNode.mln_Succ;
MyPoint = (struct MyPoint *)MyPoint->MyNode.mln_Succ) {
if (x < MyPoint->Cx) {
MyPoint->xdiff = MyPoint->Cx - x;
}
else {
MyPoint->xdiff = x - MyPoint->Cx;
}
if (y < MyPoint->Cy) {
MyPoint->ydiff = MyPoint->Cy - y;
}
else {
MyPoint->ydiff = y - MyPoint->Cy;
}
if ((MyPoint->xdiff + MyPoint->ydiff) < (*p2)->Cdiff) {
MyPoint->Cdiff = MyPoint->xdiff * MyPoint->xdiff +
MyPoint->ydiff * MyPoint->ydiff;
flag = TRUE;
p = Points;
for (i = 0;
flag && (i < NumPoints);
++i,++p) {
if ((*p)->Cdiff > MyPoint->Cdiff) {
MyPoint1 = *p;
*p = MyPoint;
p1 = p;
++p1;
for (j = i+1;
j < (Depth + 3);
++j,++p1) {
MyPoint2 = *p1;
*p1 = MyPoint1;
MyPoint1 = MyPoint2;
}
flag = FALSE;
}
}
}
}
}
if (!Everything) {
Points[Depth+3] = (struct MyPoint *)NumPoints;
return;
}
}
else {
p = Points;
NumPoints = (ULONG)Points[Depth+3];
for (i = 0;
((i < Depth+3) && *p);
++i,++p) {
MyPoint = *p;
if (x < MyPoint->Cx) {
MyPoint->xdiff = MyPoint->Cx - x;
}
else {
MyPoint->xdiff = x - MyPoint->Cx;
}
if (y < MyPoint->Cy) {
MyPoint->ydiff = MyPoint->Cy - y;
}
else {
MyPoint->ydiff = y - MyPoint->Cy;
}
MyPoint->Cdiff = MyPoint->xdiff * MyPoint->xdiff +
MyPoint->ydiff * MyPoint->ydiff;
}
}
// If on an actual point then easy
if (!Points[0]->Cdiff) {
if (AntiAlias) {
RetPoint->xd = Points[0]->x;
RetPoint->x1d = Points[0]->x1;
RetPoint->yd = Points[0]->y;
RetPoint->y1d = Points[0]->y1;
}
else {
RetPoint->x = Points[0]->x;
RetPoint->x1 = Points[0]->x1;
RetPoint->y = Points[0]->y;
RetPoint->y1 = Points[0]->y1;
}
return;
}
// otherwise try and find a triangle with the other points
if (!Depth && !(Mode & (MODE_STAT | MODE_DELAU))) {
// Special case, only have 3 points
MyPoint = Points[0];
MyPoint1 = Points[1];
MyPoint2 = Points[2];
}
else {
KeepCount = 0;
if (Mode & MODE_DELAU) {
MyPoint = Points[0];
for (T = (struct Triangle *)MyPoint->TList.lh_Head;
T->TNode.mln_Succ && !KeepCount;
T = (struct Triangle *)T->TNode.mln_Succ) {
i1 = intersect(MyPoint,T->Point1);
if (i1 + (i2 = intersect(T->Point1,T->Point2)) < 2) {
if ((i1 + i2 + intersect(T->Point2,MyPoint)) == 1) {
MyPoint1 = T->Point1;
MyPoint2 = T->Point2;
KeepCount = 1;
}
}
}
}
else {
if (Mode & MODE_CLOSEST) {
checkdiff = 0x7FFFFFFF;
for (p = Points, i=0;
i<(NumPoints-2);
++i,++p) {
if ((*p)->Cdiff < checkdiff) {
for (p1 = p+1, j=i;
j<(NumPoints-2);
++j,++p1) {
if (((*p)->Cdiff + (*p1)->Cdiff) < checkdiff) {
i1 = intersect(*p,*p1);
for (p2 = p1+1, k=j;
k<(NumPoints-2);
++k,++p2) {
// loop thru 3 point combinations finding smallest triangle
if (((*p)->Cdiff + (*p1)->Cdiff + (*p2)->Cdiff) < checkdiff) {
if (i1 + (i2 = intersect(*p1,*p2)) < 2) {
if ((i1 + i2 + intersect(*p2,*p)) == 1) {
KeepCount = 1;
MyPoint = *p;
MyPoint1 = *p1;
MyPoint2 = *p2;
checkdiff = (*p)->Cdiff + (*p1)->Cdiff + (*p2)->Cdiff;
}
}
}
}
}
}
}
}
}
else {
for (p = Points, i=0;
!KeepCount && (i<(NumPoints-2));
++i,++p) {
for (p1 = p+1, j=i;
!KeepCount && (j<(NumPoints-2));
++j,++p1) {
i1 = intersect(*p,*p1);
for (p2 = p1+1, k=j;
!KeepCount && (k<(NumPoints-2));
++k,++p2) {
// loop thru 3 point combinations finding smallest triangle
if (i1 + (i2 = intersect(*p1,*p2)) < 2) {
if ((i1 + i2 + intersect(*p2,*p)) == 1) {
MyPoint = *p;
MyPoint1 = *p1;
MyPoint2 = *p2;
KeepCount = 1;
}
}
}
}
}
}
}
// If still no triangle then assume stationary
if (!KeepCount && (Mode & MODE_STAT)) {
if (AntiAlias) {
RetPoint->xd = x;
RetPoint->x1d = x;
RetPoint->yd = y;
RetPoint->y1d = y;
}
else {
RetPoint->x = x;
RetPoint->y = y;
RetPoint->x1 = x;
RetPoint->y1 = y;
}
return;
}
if (!KeepCount) {
MyPoint = Points[0];
MyPoint1 = Points[1];
MyPoint2 = Points[2];
}
}
// Otherwise do the triangle calculation
if (Integer) {
Triangle_I(RetPoint,MyPoint,MyPoint1,MyPoint2);
}
else {
Triangle(RetPoint,MyPoint,MyPoint1,MyPoint2);
}
// Check the point is actually on the image
if (AntiAlias) {
if (RetPoint->xd < 0) {
RetPoint->xd = 0;
}
if (RetPoint->yd < 0) {
RetPoint->yd = 0;
}
if (RetPoint->x1d < 0) {
RetPoint->x1d = 0;
}
if (RetPoint->y1d < 0) {
RetPoint->y1d = 0;
}
if (RetPoint->xd > (width-1)) {
RetPoint->xd = width-1;
}
if (RetPoint->yd > (height-1)) {
RetPoint->yd = height-1;
}
if (RetPoint->x1d > (width-1)) {
RetPoint->x1d = width-1;
}
if (RetPoint->y1d > (height-1)) {
RetPoint->y1d = height-1;
}
}
else {
if (RetPoint->x < 0) {
RetPoint->x = 0;
}
if (RetPoint->y < 0) {
RetPoint->y = 0;
}
if (RetPoint->x1 < 0) {
RetPoint->x1 = 0;
}
if (RetPoint->y1 < 0) {
RetPoint->y1 = 0;
}
if (RetPoint->x > (width-1)) {
RetPoint->x = width-1;
}
if (RetPoint->y > (height-1)) {
RetPoint->y = height-1;
}
if (RetPoint->x1 > (width-1)) {
RetPoint->x1 = width-1;
}
if (RetPoint->y1 > (height-1)) {
RetPoint->y1 = height-1;
}
}
}
/* Used to determine if a point lies on a line,
* or in triangle of 3 points
*/
static UWORD __regargs
#ifdef __SASC_60
__inline
#endif
intersect(struct MyPoint *Pointa,struct MyPoint *Pointb) {
// Draws line between a and b and sees if line from x,0 to x,y intersects
// returns 1 if intersects, 0 if not intersect
if (Pointb->Cx == Pointa->Cx) { // Vertical a to b
if ((Pointb->x == x) && // x,y on a to b
(((Pointb->Cy > y) && (Pointa->Cy < y)) ||
((Pointb->Cy < y) && (Pointa->Cy > y)))) {
return 1; // Beteen a and b
}
return 0;
}
if (((Pointb->Cy > y) && (Pointa->Cy > y)) ||
((Pointb->Cx > x) && (Pointa->Cx > x)) ||
((Pointb->Cx < x) && (Pointa->Cx < x))) { // Can not possibly cross
return 0;
}
if ((Pointb->Cy < y) && (Pointa->Cy < y)) {
return 1;
}
if (Pointa->Cx == x) {
if (Pointa->Cy > y) {
return 0;
}
return 1;
}
if (Pointb->Cx == x) {
if (Pointb->Cy > y) {
return 0;
}
return 1;
}
if (Pointb->Cy == Pointa->Cy) {
if (Pointa->Cy > y) {
return 0;
}
return 1;
}
if ((((Pointa->Cx < x)?(x - Pointa->Cx):(Pointa->Cx - x)) * Pointb->Cy +
((Pointb->Cx < x)?(x - Pointb->Cx):(Pointb->Cx - x)) * Pointa->Cy) /
((Pointb->Cx < Pointa->Cx)?(Pointa->Cx - Pointb->Cx):(Pointb->Cx - Pointa->Cx)) > y) {
return 0;
}
return 1;
}
/* Given 3 points (a,b,c) with a point (p) in the triangle
* determine the coordinates of point (p) on the first and last frame
*/
static void __regargs
#ifdef __SASC_60
__inline
#endif
Triangle(struct MyPoint *p,struct MyPoint *a,struct MyPoint *bb,struct MyPoint *c) {
double AB1,AB2,BC1,BC2,CA1,CA2;
double AB,BC,CA;
double ABBCCA2;
double ABCA,BCCA,ABBC;
double BC1BC2,AB1AB2,CA1CA2;
CalcDiffs(a,bb,&AB1,&AB2,&AB);
CalcDiffs(bb,c,&BC1,&BC2,&BC);
CalcDiffs(c,a,&CA1,&CA2,&CA);
ABBCCA2 = 2 * (AB + BC + CA);
ABCA = AB+CA;
BCCA = BC+CA;
ABBC = AB+BC;
BC1BC2 = BC1+BC2;
AB1AB2 = AB1+AB2;
CA1CA2 = CA1+CA2;
if (AntiAlias) {
p->xd = x +
(ABCA*(BC1*(c->x - c->Cx) + BC2*(bb->x - bb->Cx)) / BC1BC2 +
BCCA*(AB1*(bb->x - bb->Cx) + AB2*(a->x - a->Cx)) / AB1AB2 +
ABBC*(CA1*(a->x - a->Cx) + CA2*(c->x - c->Cx)) / CA1CA2) /
ABBCCA2;
p->x1d = x +
(ABCA*(BC1*(c->x1 - c->Cx) + BC2*(bb->x1 - bb->Cx)) / BC1BC2 +
BCCA*(AB1*(bb->x1 - bb->Cx) + AB2*(a->x1 - a->Cx)) / AB1AB2 +
ABBC*(CA1*(a->x1 - a->Cx) + CA2*(c->x1 - c->Cx)) / CA1CA2) /
ABBCCA2;
p->y1d = y +
(ABCA*(BC1*(c->y1 - c->Cy) + BC2*(bb->y1 - bb->Cy)) / BC1BC2 +
BCCA*(AB1*(bb->y1 - bb->Cy) + AB2*(a->y1 - a->Cy)) / AB1AB2 +
ABBC*(CA1*(a->y1 - a->Cy) + CA2*(c->y1 - c->Cy)) / CA1CA2) /
ABBCCA2;
p->yd = y +
(ABCA*(BC1*(c->y - c->Cy) + BC2*(bb->y - bb->Cy)) / BC1BC2 +
BCCA*(AB1*(bb->y - bb->Cy) + AB2*(a->y - a->Cy)) / AB1AB2 +
ABBC*(CA1*(a->y - a->Cy) + CA2*(c->y - c->Cy)) / CA1CA2) /
ABBCCA2;
}
else {
p->x = x +
(ABCA*(BC1*(c->x - c->Cx) + BC2*(bb->x - bb->Cx)) / BC1BC2 +
BCCA*(AB1*(bb->x - bb->Cx) + AB2*(a->x - a->Cx)) / AB1AB2 +
ABBC*(CA1*(a->x - a->Cx) + CA2*(c->x - c->Cx)) / CA1CA2) /
ABBCCA2;
p->x1 = x +
(ABCA*(BC1*(c->x1 - c->Cx) + BC2*(bb->x1 - bb->Cx)) / BC1BC2 +
BCCA*(AB1*(bb->x1 - bb->Cx) + AB2*(a->x1 - a->Cx)) / AB1AB2 +
ABBC*(CA1*(a->x1 - a->Cx) + CA2*(c->x1 - c->Cx)) / CA1CA2) /
ABBCCA2;
p->y1 = y +
(ABCA*(BC1*(c->y1 - c->Cy) + BC2*(bb->y1 - bb->Cy)) / BC1BC2 +
BCCA*(AB1*(bb->y1 - bb->Cy) + AB2*(a->y1 - a->Cy)) / AB1AB2 +
ABBC*(CA1*(a->y1 - a->Cy) + CA2*(c->y1 - c->Cy)) / CA1CA2) /
ABBCCA2;
p->y = y +
(ABCA*(BC1*(c->y - c->Cy) + BC2*(bb->y - bb->Cy)) / BC1BC2 +
BCCA*(AB1*(bb->y - bb->Cy) + AB2*(a->y - a->Cy)) / AB1AB2 +
ABBC*(CA1*(a->y - a->Cy) + CA2*(c->y - c->Cy)) / CA1CA2) /
ABBCCA2;
}
}
/* Caclulate the distances between various points */
static void __regargs
#ifdef __SASC_60
__inline
#endif
CalcDiffs(struct MyPoint *a,struct MyPoint *bb,double *ab1,double *ab2,double *ab) {
// ab is length x,y to line ab
// ab1 is length x,y to intersect of ab
// ab2 is length intersect of ab to bb
double m;
double c; // y = mx+c line a to bb
double n;
double d; // y = nx+d line perp to y=mx+c thru x,y
double xsolve,ysolve;
if (a->Cx == bb->Cx) {
*ab = a->xdiff;
*ab1 = a->ydiff;
*ab2 = bb->ydiff;
}
else {
if (a->Cy == bb->Cy) {
*ab1 = a->xdiff;
*ab2 = bb->xdiff;
*ab = a->ydiff;
}
else {
m = (double)(bb->Cy - a->Cy) / (double)(bb->Cx - a->Cx);
c = bb->Cy - (bb->Cx * m);
n = (-1) / m;
d = y - n * x;
xsolve = (d - c)/(m - n);
ysolve = m * xsolve + c;
*ab1 = sqrt(((a->Cy - ysolve) * (a->Cy - ysolve) + (a->Cx - xsolve) * (a->Cx - xsolve)));
*ab2 = sqrt(((bb->Cy - ysolve) * (bb->Cy - ysolve) + (bb->Cx - xsolve) * (bb->Cx - xsolve)));
*ab = sqrt(((y - ysolve) * (y - ysolve) + (x - xsolve) * (x - xsolve)));
}
}
}
/* Given 3 points (a,b,c) with a point (p) in the triangle
* determine the coordinates of point (p) on the first and last frame
* Integer version
* Completely different to the real version
*/
static void __regargs
#ifdef __SASC_60
__inline
#endif
Triangle_I(struct MyPoint *p,struct MyPoint *a,struct MyPoint *bb,struct MyPoint *c) {
LONG ABBCCA2;
ABBCCA2 = 2 * (a->Cdiff + bb->Cdiff + c->Cdiff);
p->x = x +
((a->x - a->Cx) * (bb->Cdiff + c->Cdiff) +
(bb->x - bb->Cx) * (a->Cdiff + c->Cdiff) +
(c->x - c->Cx) * (a->Cdiff + bb->Cdiff)) /
ABBCCA2;
p->x1 = x +
((a->x1 - a->Cx) * (bb->Cdiff + c->Cdiff) +
(bb->x1 - bb->Cx) * (a->Cdiff + c->Cdiff) +
(c->x1 - c->Cx) * (a->Cdiff + bb->Cdiff)) /
ABBCCA2;
p->y = y +
((a->y - a->Cy) * (bb->Cdiff + c->Cdiff) +
(bb->y - bb->Cy) * (a->Cdiff + c->Cdiff) +
(c->y - c->Cy) * (a->Cdiff + bb->Cdiff)) /
ABBCCA2;
p->y1 = y +
((a->y1 - a->Cy) * (bb->Cdiff + c->Cdiff) +
(bb->y1 - bb->Cy) * (a->Cdiff + c->Cdiff) +
(c->y1 - c->Cy) * (a->Cdiff + bb->Cdiff)) /
ABBCCA2;
}
// Load some image(s) for a frame
BOOL
LoadFrames(BOOL points,BOOL image1,BOOL image2) {
char buffer[257];
BOOL ok=TRUE;
UBYTE *er,*eg,*eb;
int i;
if ((Single == 2) || (Single == 3)) {
if (points) {
AddMessage("Loading points");
DeleteAllPoints();
sprintf(buffer,MyFileName,f+Start-1);
ok = MyOpen(buffer,TRUE);
}
sprintf(buffer,Pic1.filename,f+Start-1);
}
else {
strcpy(buffer,Pic1.filename);
}
if (ok) {
if (image1) {
ok = Pic1_Open = Load24bit(buffer,&Pic1,TRUE);
if (ok && EGS && !EGS_BitMap) {
if (EGS_BitMap = E_AllocBitMap(swidth,1,24,E_PIXELMAP,E_EB_NOTSWAPABLE,NULL)) {
EGS_NewWindow.LeftEdge = 0;
EGS_NewWindow.TopEdge = 20;
EGS_NewWindow.Width = width;
EGS_NewWindow.Height = height;
EGS_NewWindow.MinWidth = 20;
EGS_NewWindow.MinHeight = 20;
EGS_NewWindow.MaxWidth = width;
EGS_NewWindow.MaxHeight = height;
EGS_NewWindow.Screen = NULL;
EGS_NewWindow.Bordef.SysGadgets = EI_WINDOWSIZE | EI_WINDOWFRONT | EI_WINDOWFLIP |
EI_WINDOWARROWL | EI_WINDOWARROWR | EI_WINDOWARROWU | EI_WINDOWARROWD |
EI_WINDOWSCROLLH | EI_WINDOWSCROLLV | EI_WINDOWDRAG;
EGS_NewWindow.FirstGadgets = NULL;
EGS_NewWindow.Title = "TSMorph-render output";
EGS_NewWindow.Flags = EI_GIMMEZEROZERO | EI_SUPER_BITMAP | EI_WINDOWACTIVE | EI_REPORTMOUSE | EI_QUICKSCROLL | EI_RMBTRAP;
EGS_NewWindow.IDCMPFlags = NULL;
EGS_NewWindow.Port = NULL;
// EGS_NewWindow.Colors = ??;
EGS_NewWindow.Menu = NULL;
EGS_NewWindow.Render = NULL;
if (EGS_Win = EI_OpenWindow(&EGS_NewWindow)) {
EI_SetWindowTitles(EGS_Win,(UBYTE *)-1,"TSMorph-render");
E_ActivateEGSScreen();
er = Pic1.red;
eg = Pic1.green;
eb = Pic1.blue;
for (i = 0; i<height; ++i) {
CopyEGS(i,&er,&eg,&eb);
}
}
}
}
}
if (image2 && ok && ((Single == 0) || (Single == 2))) {
// If we loaded the 1st image then try the second
if (Single == 2) {
sprintf(buffer,Pic2.filename,f+Start-1);
}
else {
strcpy(buffer,Pic2.filename);
}
ok = Pic2_Open = Load24bit(buffer,&Pic2,TRUE);
}
}
return ok;
}
void
CopyEGS(int line, UBYTE **er,UBYTE **eg,UBYTE **eb) {
int j;
UBYTE *plane;
plane = EGS_BitMap->Typekey.PixelMap.Planes.Dest;
for (j = 0; j<swidth; ++j) {
*plane++ = *((*er)++);
*plane++ = *((*eg)++);
*plane++ = *((*eb)++);
++plane;
}
EG_CopyBitMapRastPort(EGS_BitMap,EGS_Win->RPort,0,0,width,1,0,line);
}
int
cmpX(struct MyPoint **A,struct MyPoint **B) {
if ((*A)->Cx < (*B)->Cx) {
return -1;
}
if ((*A)->Cx > (*B)->Cx) {
return 1;
}
return 0;
}
int
cmpY(struct MyPoint **A,struct MyPoint **B) {
if ((*A)->Cy < (*B)->Cy) {
return -1;
}
if ((*A)->Cy > (*B)->Cy) {
return 1;
}
return 0;
}
int
cmpDiff(struct MyPoint **A,struct MyPoint **B) {
if ((*A)->Cdiff < (*B)->Cdiff) {
return -1;
}
if ((*A)->Cdiff > (*B)->Cdiff) {
return 1;
}
return 0;
}
/* nsort() was written by Dave Watson and uses the algorithm described in -
* Watson, D.F., 1981, Computing the n-dimensional Delaunay tessellation with
* application to Voronoi polytopes: The Computer J., 24(2), p. 167-172.
*/
#define SQ(x) (x) * (x)
#define BIGNUM 1E37
#define EPSILON 0.00001
#define TSIZE 75 /* temporary storage size factor*/
#define XRANGE 10.0 /* factor (>=1) for radius of control points */
#define FILENAMELEN 32
#define AND &&
#define OR ||
#define EQ ==
#define NE !=
BOOL
GenerateTriangles(void) {
BOOL ok = FALSE;
BOOL flag = TRUE;
double xx, bgs, **mxy, **wrk, **pts, **ccr;
int i0, i1, i2, i3, i4, i5, i6, i7, i8, i9, i11, ii[3],
dm, nts, tsz, *id, **tmp, **a3s;
if (mxy = DoubleMatrix(2, 2)) {
for (i0=0; i0<2; i0++) {
mxy[0][i0] = - (mxy[1][i0] = BIGNUM);
}
if (wrk = DoubleMatrix(2, 3)) {
for (i0=0; i0<2; i0++) {
for (i1=0; i1<3; i1++) {
wrk[i0][i1] = -XRANGE;
}
}
for (i0=0; i0<2; i0++) {
wrk[i0][i0] = XRANGE * (3 * 2 - 1);
}
if (pts = DoubleMatrix(PointCount + 3, 2)) {
for (i0=0; i0<PointCount; i0++) {
NewList(&(PointsX[i0]->TList));
pts[i0][0] = PointsX[i0]->Cx;
pts[i0][1] = PointsX[i0]->Cy;
for (i1=0; i1<2; i1++) {
if (mxy[0][i1] < pts[i0][i1]) {
mxy[0][i1] = pts[i0][i1];
}
if (mxy[1][i1] > pts[i0][i1]) {
mxy[1][i1] = pts[i0][i1];
}
}
}
for (bgs=0, i0=0; i0<2; i0++) {
mxy[0][i0] -= mxy[1][i0];
if (bgs < mxy[0][i0]) {
bgs = mxy[0][i0];
}
}
bgs *= EPSILON;
for (i0=0; i0<PointCount; i0++) {
for (i1=0; i1<2; i1++) {
pts[i0][i1] += bgs * (0.5 - (double)rand() / 0x7fffffff);
}
}
for (i0=0; i0<3; i0++) {
for (i1=0; i1<2; i1++) {
pts[PointCount+i0][i1] = mxy[1][i1] + wrk[i1][i0] * mxy[0][i1];
}
}
for (i1=1, i0=2; i0<3; i0++) {
i1 *= i0;
}
tsz = TSIZE * i1;
if (tmp = IntMatrix(tsz + 1, 2)) {
i1 *= (PointCount + i1);
if (id = IntVect(i1)) {
for (i0=0; i0<i1; i0++) {
id[i0] = i0;
}
if (a3s = IntMatrix(i1,3)) {
if (ccr = DoubleMatrix(i1,3)) {
for (a3s[0][0]=PointCount, i0=1; i0<3; i0++) {
a3s[0][i0] = a3s[0][i0-1] + 1;
}
for (ccr[0][2]=BIGNUM, i0=0; i0<2; i0++) {
ccr[0][i0] = 0;
}
nts = i4 = 1;
dm = 2 - 1;
for (i0=0; i0<PointCount; i0++) {
i1 = i7 = -1;
i9 = 0;
for (i11=0; i11<nts; i11++) {
i1++;
while (a3s[i1][0] < 0) {
i1++;
}
xx = ccr[i1][2];
for (i2=0; i2<2; i2++) {
xx -= SQ(pts[i0][i2] - ccr[i1][i2]);
if (xx<0) {
goto Corner3;
}
}
i9--;
i4--;
id[i4] = i1;
for (i2=0; i2<3; i2++) {
ii[0] = 0;
if (ii[0] EQ i2) {
ii[0]++;
}
for (i3=1; i3<2; i3++) {
ii[i3] = ii[i3-1] + 1;
if (ii[i3] EQ i2) {
ii[i3]++;
}
}
if (i7>dm) {
i8 = i7;
for (i3=0; i3<=i8; i3++) {
for (i5=0; i5<2; i5++) {
if (a3s[i1][ii[i5]] NE tmp[i3][i5]) {
goto Corner1;
}
}
for (i6=0; i6<2; i6++) {
tmp[i3][i6] = tmp[i8][i6];
}
i7--;
goto Corner2;
Corner1:;
}
}
if (++i7 > tsz) {
goto returnfail;
}
for (i3=0; i3<2; i3++) {
tmp[i7][i3] = a3s[i1][ii[i3]];
}
Corner2:;
}
a3s[i1][0] = -1;
Corner3:;
}
for (i1=0; i1<=i7; i1++) {
for (i2=0; i2<2; i2++) {
for (wrk[i2][2]=0, i3=0; i3<2; i3++) {
wrk[i2][i3] = pts[tmp[i1][i2]][i3] - pts[i0][i3];
wrk[i2][2] += wrk[i2][i3] * (pts[tmp[i1][i2]][i3] + pts[i0][i3]) / 2;
}
}
xx = wrk[0][0] * wrk[1][1] - wrk[1][0] * wrk[0][1];
ccr[id[i4]][0] = (wrk[0][2] * wrk[1][1] - wrk[1][2] * wrk[0][1]) / xx;
ccr[id[i4]][1] = (wrk[0][0] * wrk[1][2] - wrk[1][0] * wrk[0][2]) / xx;
for (ccr[id[i4]][2]=0, i2=0; i2<2; i2++) {
ccr[id[i4]][2] += SQ(pts[i0][i2] - ccr[id[i4]][i2]);
a3s[id[i4]][i2] = tmp[i1][i2];
}
a3s[id[i4]][2] = i0;
i4++;
i9++;
}
nts += i9;
}
i0 = -1;
for (i11=0; flag && (i11<nts); i11++) {
i0++;
while (a3s[i0][0] < 0) {
i0++;
}
if (a3s[i0][0] < PointCount) {
for (i1=0; i1<2; i1++) for (i2=0; i2<2; i2++) {
wrk[i1][i2] = pts[a3s[i0][i1]][i2] - pts[a3s[i0][2]][i2];
}
xx = wrk[0][0] * wrk[1][1] - wrk[0][1] * wrk[1][0];
if (fabs(xx) > EPSILON) {
flag = AddTri(a3s[i0][0],a3s[i0][2],a3s[i0][1]);
}
}
}
ok = flag;
returnfail:
FreeMatrixd(ccr);
}
FreeMatrixi(a3s);
}
MyFreeVecti(id);
}
FreeMatrixi(tmp);
}
FreeMatrixd(pts);
}
FreeMatrixd(wrk);
}
FreeMatrixd(mxy);
}
return ok;
}
int
*IntVect(int ncols) {
return (int *) MyAllocVec(ncols * sizeof(int),0);
}
void
MyFreeVecti(int *vectptr) {
if (vectptr) {
MyFreeVec(vectptr);
}
}
int
**IntMatrix(int nrows, int ncols) {
int i0;
int **matptr;
if (nrows<2) nrows = 2;
if (ncols<2) ncols = 2;
if ((matptr = (int **) MyAllocVec(nrows * sizeof(int *),0)) EQ NULL) {
return NULL;
}
if ((matptr[0] = (int *) MyAllocVec(nrows * ncols * sizeof(int),0)) EQ NULL) {
MyFreeVec(matptr);
return NULL;
}
for (i0=1; i0<nrows; i0++) {
matptr[i0] = matptr[0] + i0 * ncols;
}
return matptr;
}
void
FreeMatrixi(int **matptr) {
if (matptr) {
if (matptr[0]) {
MyFreeVec(matptr[0]);
}
MyFreeVec(matptr);
}
}
double
**DoubleMatrix(int nrows, int ncols) {
int i0;
double **matptr;
if (nrows<2) nrows = 2;
if (ncols<2) ncols = 2;
if ((matptr = (double **) MyAllocVec(nrows * sizeof(double *),0)) EQ NULL) {
return NULL;
}
if ((matptr[0] = (double *) MyAllocVec(nrows * ncols * sizeof(double),0)) EQ NULL) {
MyFreeVec(matptr);
return NULL;
}
for (i0=1; i0<nrows; i0++) {
matptr[i0] = matptr[0] + i0 * ncols;
}
return matptr;
}
void
FreeMatrixd(double **matptr) {
if (matptr) {
if (matptr[0]) {
MyFreeVec(matptr[0]);
}
MyFreeVec(matptr);
}
}
void
FreeTriangles(void) {
int i;
struct Triangle *T;
struct MyPoint *P;
for (i=0; i<PointCount; i++) {
P = PointsX[i];
while ((T =(struct Triangle *)(P->TList.lh_Head))->TNode.mln_Succ) {
Remove((struct Node *)T);
MyFreeVec(T);
}
}
}
BOOL AddTri(int aa,int bb,int cc) {
struct Triangle *T1,*T2=NULL,*T3;
if ((T1 = (struct Triangle *)MyAllocVec(sizeof (struct Triangle),0)) &&
(T2 = (struct Triangle *)MyAllocVec(sizeof (struct Triangle),0)) &&
(T3 = (struct Triangle *)MyAllocVec(sizeof (struct Triangle),0))) {
T1->Point1 = PointsX[bb];
T1->Point2 = PointsX[cc];
AddTail(&(PointsX[aa]->TList),(struct Node *)T1);
T2->Point1 = PointsX[aa];
T2->Point2 = PointsX[cc];
AddTail(&(PointsX[bb]->TList),(struct Node *)T2);
T3->Point1 = PointsX[aa];
T3->Point2 = PointsX[bb];
AddTail(&(PointsX[cc]->TList),(struct Node *)T3);
return TRUE;
}
if (T1) {
MyFreeVec(T1);
}
if (T2) {
MyFreeVec(T2);
}
return FALSE;
}
static UWORD top = 0;
// add a message to the progress list
void
AddMessage(UBYTE *message) {
struct Node *node;
if ((node = (struct Node *)Mymalloc(sizeof(struct Node))) &&
(node->ln_Name = Mystrdup(message))) {;
GT_SetGadgetAttrs(ProgressGadgets[GDX_Info],ProgressWnd,NULL,
GTLV_Labels, ~0,
TAG_END);
AddTail(&InfoList,node);
GT_SetGadgetAttrs(ProgressGadgets[GDX_Info],ProgressWnd,NULL,
GTLV_Labels, &InfoList,
GTLV_Top, top,
TAG_END);
top++;
}
}