home *** CD-ROM | disk | FTP | other *** search
/ Fresh Fish 8 / FreshFishVol8-CD1.bin / new / gfx / edit / tsmorph / src / tsmorph-render.c < prev    next >
C/C++ Source or Header  |  1994-02-27  |  101KB  |  3,265 lines

  1. // TSMorph - Amiga Morphing program
  2. // Copyright (C) © 1993  Topicsave Limited
  3.  
  4. // This program is free software; you can redistribute it and/or modify
  5. // it under the terms of the GNU General Public License as published by
  6. // the Free Software Foundation; either version 2 of the License, or
  7. // any later version.
  8.  
  9. // This program is distributed in the hope that it will be useful,
  10. // but WITHOUT ANY WARRANTY; without even the implied warranty of
  11. // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  12. // GNU General Public License for more details.
  13.  
  14. // You should have received a copy of the GNU General Public License
  15. // along with this program; if not, write to the Free Software
  16. // Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  17.  
  18. // mpaddock@cix.compulink.co.uk
  19.  
  20. /* Amiga headers */
  21. #define INTUI_V36_NAMES_ONLY
  22. #define INTUITION_IOBSOLETE_H
  23.  
  24. // Include correct math library
  25. #ifdef MY68881
  26. #include <m68881.h>
  27. extern int rand(void);
  28. #else
  29. #ifdef MY68881_6
  30. #include <math.h>
  31. #include <m68881.h>
  32. #else
  33. #include <math.h>
  34. #endif
  35. #endif
  36.  
  37.  
  38. // prevent inclusion of another math library
  39. #define LIBRARIES_MATHFFP_H
  40.  
  41. // other headers, define some non 2.02 header stuff
  42. #include <exec/types.h>
  43. #include <exec/memory.h>
  44. #include <intuition/intuition.h>
  45. #include <intuition/intuitionbase.h>
  46. #include <intuition/gadgetclass.h>
  47. #ifndef PGA_NewLook
  48. #define PGA_NewLook (PGA_Dummy + 0x000A)
  49. #endif
  50. #include <intuition/imageclass.h>
  51. #include <intuition/icclass.h>
  52. #include <devices/input.h>
  53. #include <workbench/workbench.h>
  54. #include <workbench/startup.h>
  55. #include <libraries/gadtools.h>
  56. #ifndef GTMN_FullMenu
  57. #define GTMN_FullMenu GT_TagBase+62
  58. #endif
  59. #include <libraries/asl.h>
  60.  
  61. #include <clib/exec_protos.h>
  62. #include <clib/dos_protos.h>
  63. #include <clib/layers_protos.h>
  64. #include <clib/graphics_protos.h>
  65. #include <clib/intuition_protos.h>
  66. #include <clib/input_protos.h>
  67. #include <clib/gadtools_protos.h>
  68. #include <clib/asl_protos.h>
  69. #include <clib/utility_protos.h>
  70. #include <clib/alib_protos.h>
  71.  
  72. #include <pragmas/exec_pragmas.h>
  73. #include <pragmas/dos_pragmas.h>
  74. #include <pragmas/layers_pragmas.h>
  75. #include <pragmas/graphics_pragmas.h>
  76. #include <pragmas/intuition_pragmas.h>
  77. #include <pragmas/input_pragmas.h>
  78. #include <pragmas/gadtools_pragmas.h>
  79. #include <pragmas/asl_pragmas.h>
  80. #include <pragmas/utility_pragmas.h>
  81.  
  82. #include <proto/diskfont.h>
  83. #include <proto/icon.h>
  84.  
  85. #include <devices/timer.h>
  86.  
  87. #include <clib/timer_protos.h>
  88. #include <pragmas/timer_pragmas.h>
  89.  
  90. #include <clib/alib_protos.h>
  91.  
  92. #include <rexx/errors.h>
  93. #include <pragmas/rexxsyslib_pragmas.h>
  94. #include <clib/rexxsyslib_protos.h>
  95.  
  96. #include <libraries/amigaguide.h>
  97. #include <clib/amigaguide_protos.h>
  98. #include <pragmas/amigaguide_pragmas.h>
  99.  
  100. #include <libraries/reqtools.h>
  101. #include <clib/reqtools_protos.h>
  102. #include <pragmas/reqtools.h>
  103.  
  104. #include <opal/opallib.h>
  105.  
  106. #include <libraries/dctv.h>
  107. #include <clib/dctv_protos.h>
  108. #include <pragmas/dctv_pragmas.h>
  109.  
  110. #include <libraries/nofrag.h>
  111. #include <clib/nofrag_protos.h>
  112. #ifdef LIBRARIES_NOFRAG_H
  113. #undef LIBRARIES_NOFRAG_H
  114. #endif
  115. #include <pragmas/nofrag_pragmas.h>
  116. #ifndef LIBRARIES_NOFRAG_H
  117. #define LIBRARIES_NOFRAG_H 1
  118. #endif
  119.  
  120. #include <stddef.h>
  121. #include <string.h>
  122. #include <stdio.h>
  123. #include <stdlib.h>
  124.  
  125. /* Below is not in the 2.02 version of clib/utility_protos.h
  126.                                        pragmas/utility_pragmas.h */
  127. #if INCLUDE_VERSION < 37
  128. LONG Stricmp(UBYTE *string1,UBYTE *string2);
  129. #pragma libcall UtilityBase Stricmp A2 9802
  130. #endif
  131.  
  132. /* EGS Stuff    */
  133. #include <egs/clib/egs_protos.h>
  134. #include <egs/pragmas/egs_pragmas.h>
  135.  
  136. #include <egs/clib/egsintui_protos.h>
  137. #include <egs/pragmas/egsintui_pragmas.h>
  138.  
  139. #include <egs/clib/egsgfx_protos.h>
  140. #include <egs/pragmas/egsgfx_pragmas.h>
  141.  
  142. #include <egs/egsintui.h>
  143.  
  144. extern struct Library *EGSIntuiBase    = NULL;
  145. extern struct Library *EGSGfxBase    = NULL;
  146. extern struct Library *EGSBase        = NULL;
  147.  
  148. // IFF header
  149. #include "iffp/ILBMapp.h"
  150.  
  151. // Progress requester
  152. #include "progress.h"
  153.  
  154. // JPEG load stuff
  155. #include "JPEG_LS/jinclude.h"
  156.  
  157. // Help nodes
  158. STRPTR context[] = {
  159.     "",
  160.     "Main",
  161.     "Err-IFFBMHD",
  162.     "Err-IFFRaster",
  163.     "Err-IFFBODY",
  164.     "Err-IFFCLIP",
  165.     "Err-IFFILBM",
  166.     "Err-IFFFileS",
  167.     "Err-IFFTop",
  168.     "Err-IFFMemory",
  169.     "Req-Progress",
  170.     "Err-LibraryR",
  171.     "Err-Saving",
  172.     "Err-AllocVec",
  173.     "Err-OpenPoints",
  174.     "Err-Progress",
  175.     "Err-AllocPlanes",
  176.     "Err-24",
  177.     "Err-Load",
  178.     "Err-AllocIFF",
  179.     "Err-AllocILBM",
  180.     "Err-FileFormat",
  181.     "Err-SizeMatch",
  182.     "Err-Range",
  183.     "Err-MemPointsR",
  184.     "Err-CloseFile",
  185.     "Err-3Points",
  186.     "Err-OpenFile",
  187.     "Err-ARexx",
  188.     "Req-Really_quit",
  189.     "Err-OldFormat",
  190.     "Err-OpalVision",
  191.     "Err-NoOpal",
  192. };
  193.  
  194. #define H_Help         10
  195. #define H_Library        11
  196. #define H_ESave        12
  197. #define H_AllocVec    13
  198. #define H_OpenPoints    14
  199. #define H_Progress    15
  200. #define H_AllocPlanes 16
  201. #define H_24            17
  202. #define H_Load            18
  203. #define H_AllocIFF    19
  204. #define H_AllocILBM    20
  205. #define H_FileFormat    21
  206. #define H_SizeMatch    22
  207. #define H_Range        23
  208. #define H_MemPointsR    24
  209. #define H_CloseFile    25
  210. #define H_3Points        26
  211. #define H_Open            27
  212. #define H_ARexx        28
  213. #define H_Really        29
  214. #define HE_OldFormat    30
  215. #define HE_OpalVision 31
  216. #define HE_NoOpal        32
  217.  
  218. // Disable Ctrl-C checking
  219. int CXBRK(void) { return(0); }
  220. int chkabort(void) { return(0); }
  221. int __regargs __chkabort(void) { return(0); }
  222.  
  223. // Libraries
  224. extern struct ExecBase *SysBase;
  225. extern struct DosLibrary *DOSBase;
  226. struct IntuitionBase *IntuitionBase;
  227. struct Library *GfxBase, *LayersBase, *IFFParseBase;
  228. struct Library *GadToolsBase, *AslBase, *UtilityBase;
  229. struct Library *RexxSysBase;
  230. struct Library *AmigaGuideBase;
  231. struct Library *TimerBase=NULL;
  232. struct Library *ReqToolsBase;
  233. struct Library *DCTVBase;
  234. struct NoFragBase *NoFragBase = NULL;
  235.  
  236. struct OpalBase *OpalBase = NULL;
  237.  
  238. extern struct List InfoList={0}; // List of messages
  239.  
  240. // Help stuff
  241. extern AMIGAGUIDECONTEXT handle = {NULL};
  242. extern struct NewAmigaGuide nag = {NULL};
  243. extern ULONG ASig = 0;
  244.  
  245. /* Version string for CLI version */
  246. #ifdef MY68881
  247. char *Version = "$VER: TSMorph-render_881 3.0 (25.2.94)";
  248. #else
  249. #ifdef _M68040
  250. char *Version = "$VER: TSMorph-render_040 3.0 (25.2.94)";
  251. #else
  252. #ifdef MY68881_6
  253. char *Version = "$VER: TSMorph-render_881 3.0 (25.2.94)";
  254. #else
  255. char *Version = "$VER: TSMorph-render 3.0 (25.2.94)";
  256. #endif
  257. #endif
  258. #endif
  259.  
  260. BOOL Pic1_Open = FALSE;                // 1st image open OK
  261. BOOL Pic2_Open = FALSE;                // 2nd image open OK
  262.  
  263. struct MsgPort        *WMsgPortp;        // Message port for Picture Windows
  264.  
  265. // Properties for IFF read
  266. LONG props[] = {    ID_ILBM,    ID_BMHD,
  267.                         ID_ILBM,    ID_CAMG,
  268.                         ID_ILBM, ID_CMAP,
  269.                         TAG_DONE };
  270. LONG stops[] = {    ID_ILBM,    ID_BODY,
  271.                         TAG_DONE };
  272. LONG nowt[] = { TAG_DONE };
  273.  
  274. struct EI_NewWindow    EGS_NewWindow = {0};    // EGS New window
  275. struct EI_Window        *EGS_Win=NULL;            // EGS Window
  276. struct E_EBitMap        *EGS_BitMap=NULL;
  277.  
  278. // Protos
  279. BOOL SaveFile(void);
  280. BOOL Load24bit(char *filename,struct Picture *pic,BOOL GUI);
  281. void Close24bit(struct Picture *pic);
  282. void DeleteAllPoints(void);
  283. static void __regargs FindPoint(struct MyPoint *RetPoint,BOOL Everything);
  284. BOOL MyOpen(char *filename,BOOL JustPoints);
  285. static UWORD __regargs intersect(struct MyPoint *Pointa,struct MyPoint *Pointb);
  286. static void __regargs CalcDiffs(struct MyPoint *a,struct MyPoint *bb,double *ab1,double *ab2,double *ab);
  287. static void __regargs Triangle(struct MyPoint *p,struct MyPoint *a,struct MyPoint *bb,struct MyPoint *c);
  288. static void __regargs Triangle_I(struct MyPoint *p,struct MyPoint *a,struct MyPoint *bb,struct MyPoint *c);
  289. extern void MyArgArrayInit(int argc,char **argv);
  290. extern void MyArgArrayDone(void);
  291. extern UBYTE *MyArgString(UBYTE *arg2,UBYTE *arg3,BOOL reopen);
  292. extern LONG MyArgInt(UBYTE *arg2, long arg3,BOOL reopen);
  293. extern BOOL MyFindToolType(UBYTE *arg2,BOOL reopen);
  294. void OpenNewArgs(UBYTE *filename);
  295. void help(ULONG hnum);
  296. BOOL LoadFrames(BOOL points,BOOL image1,BOOL image2);
  297. void CopyEGS(int line, UBYTE **er,UBYTE **eg,UBYTE **eb);
  298. int cmpX(struct MyPoint **A,struct MyPoint **B);
  299. int cmpY(struct MyPoint **A,struct MyPoint **B);
  300. int cmpDiff(struct MyPoint **A,struct MyPoint **B);
  301. BOOL    GenerateTriangles(void);
  302. void    FreeTriangles(void);
  303. int   *IntVect(int ncols);
  304. void  MyFreeVecti(int *vectptr);
  305. int   **IntMatrix(int nrows,int ncols);
  306. void  FreeMatrixi(int **matptr);
  307. double **DoubleMatrix(int nrows,int ncols);
  308. void  FreeMatrixd(double **matptr);
  309. BOOL AddTri(int aa,int bb,int cc);
  310. void AddMessage(UBYTE *message);
  311.  
  312. // Args.c
  313. void argArrayDone( void );
  314. char **argArrayInit( LONG argc, char **argv );
  315.  
  316. // RenderSub.c
  317. void DisableWindow(void);
  318. void EnableWindow(void);
  319. APTR MyAllocVec(ULONG size,ULONG requirements);
  320. void MyFreeVec(APTR memptr);
  321. APTR MyAllocMem(ULONG size,ULONG requirements);
  322. void MyFreeMem(APTR memptr,ULONG size);
  323. APTR Mymalloc(ULONG size);
  324. APTR Mystrdup(UBYTE *str);
  325. void Error(char *ErrorMessage, char *Gadget,char *extra,ULONG hnum);
  326. LONG SendRxMsg(char *msgtxt,BOOL IgnoreError);
  327.  
  328. // some work buffers
  329. extern char buffer[256]="";
  330. extern char buffer1[512]="";
  331.  
  332. // Image structure
  333. struct Picture {
  334.     struct ILBMInfo    *ilbm;        // For IFF read
  335.     UBYTE                    *red;            // Read chunky pixels    Must be RGB for Opal OVtoRGB
  336.     UBYTE                    *green;        // Green
  337.     UBYTE                    *blue;        // Blue
  338.     UBYTE                    filename[256];    // filename
  339.     struct OpalScreen *OScrn;        // OpalScreen
  340.     BOOL                    rgbonelot;    // Is red,green,blue one AllocVec
  341. };
  342.  
  343. struct Picture Pic1={0},Pic2={0};// 1st and 2nd image
  344.  
  345. extern UBYTE *plane0=NULL;                    // Planes for temporary bit maps
  346. extern UBYTE *plane1=NULL;
  347. extern UBYTE *plane2=NULL;
  348. extern UBYTE *plane3=NULL;
  349. extern UBYTE *plane4=NULL;
  350. extern UBYTE *plane5=NULL;
  351. extern UBYTE *plane6=NULL;
  352. extern UBYTE *plane7=NULL;
  353.  
  354. // nofrag.library stuff
  355. extern struct MemoryChain *Chain = NULL;
  356. #define MAXMEM 1000
  357.  
  358. // Point structure
  359. struct MyPoint {
  360.     struct MinNode MyNode;    // linked into list
  361.     WORD x,y;        // Coordinates in 1st image
  362.     WORD x1,y1;        // 2nd image
  363.     WORD Cx,Cy;        // Current image
  364.     LONG Cdiff;        // seperation between two points (squared)
  365.     WORD xdiff;        // x difference
  366.     WORD ydiff;        // y difference
  367.     double xd,yd;    // double coords for AntiAlias
  368.     double x1d,y1d;// 2nd image
  369.     BOOL Used;        // Is it being used?
  370.     struct List TList;    // List of triangles;
  371. };
  372.  
  373. struct Triangle {
  374.     struct MinNode TNode;    // Linked into list
  375.     struct MyPoint *Point1;
  376.     struct MyPoint *Point2;
  377. };
  378.  
  379. // 24 bitplane bitmap
  380. struct MyBitMap {
  381.     struct BitMap BitMap;
  382.     PLANEPTR xplanes[16];
  383. };
  384.  
  385. // List of points
  386. struct List            PointList;
  387.  
  388. // Size of image
  389. extern USHORT    width=0, height=0, pwidth=0, pheight=0, pmode=0;
  390.  
  391. char AnimName[256]="";    // Buffer for file name to save
  392.  
  393. char *Loadscript;        // ARexx load script
  394.  
  395. extern WORD x=0,y=0;                // Current coords
  396.  
  397. struct MyPoint **Points = NULL;    // Pointer to points
  398. struct MyPoint **PointsAlloc = NULL;    // The actual allocated pointer
  399. struct MyPoint **PointsX = NULL;    // Pointer to points horizontal
  400. struct MyPoint **PointsY = NULL;    // Pointer to points vertical
  401.  
  402. WORD    Depth;    // Number of points to check each time
  403.  
  404. UWORD Mode;        // Mode = 0 use 3 closest if no others, choose 1st 3
  405.                     // Mode = 1 leave points stationary, choose 1st 3
  406.                     // Mode = 2 choose 3 closet, always use
  407.                     // Mode = 3 leave points stationary, choose 3 closest
  408.                     // Mode = 4 Binary search ,5,6,7 as above
  409.                     // Mode = 8 Delaunay Triangle algorithm
  410.                     // Mode = 16 Only calculate points once
  411.  
  412.  
  413.                                 // SET/UNSET
  414. #define MODE_STAT        1    // Stationary if no triangle/Use 3 points anyway
  415. #define MODE_CLOSEST    2    // Choose 3 closest/Choose 1st 3 found
  416. #define MODE_SEARCH    4    // Binary Search/Look at all points
  417. #define MODE_DELAU    8    // Delaunay Triangle/Normal mode (sets DEPTH to 0)
  418. #define MODE_ONCE        16    // Only calculate once
  419.  
  420. LONG PointCount = 0;            // Number of points
  421.  
  422. struct MyPoint BigPoint;    // Point far away
  423.  
  424. char MyFileName[257];
  425.  
  426. // Settings stuff
  427. char **ArgArray;
  428. char **ArgArraySettings;
  429.  
  430. // OpalVision screen
  431. extern struct OpalScreen *OScrn = NULL;
  432.  
  433. extern char                 *OVFormat=NULL;    // Format of OpalVision save JPG or IFF (or anything) default
  434. BOOL                AntiAlias;    // AntiAlias points
  435.  
  436. // Table of parameters
  437. extern struct {
  438.     LONG xf;                // Current frame
  439.     LONG xFrames;        // Number of frames
  440.     LONG xSingle;        // Warp or Morph
  441.     LONG xmove;            // Movement 1 to 2
  442.     LONG xr;                // red of image 1
  443.     LONG xg;                // green
  444.     LONG xb;                // blue
  445.     LONG xr2;            // red of image 2
  446.     LONG xg2;            // green
  447.     LONG xb2;            // blue
  448.     LONG xDo;            // Produce this image
  449.     LONG xrplus;        // Add red
  450.     LONG xgplus;        // green
  451.     LONG xbplus;        // blue
  452.     LONG xrminus;        // subtract red
  453.     LONG xgminus;        // subtract green
  454.     LONG xbminus;        // subtract blue
  455.     LONG xDX;            // X skip
  456.     LONG xDY;            // Y skip
  457.     LONG xStart;        // Start Frame number
  458.     LONG FILLER[32];    // Filler for future expansion
  459. } Arexx = {0};
  460.  
  461. #define f Arexx.xf
  462. #define Frames Arexx.xFrames
  463. #define Single Arexx.xSingle
  464. #define move Arexx.xmove
  465. #define r Arexx.xr
  466. #define g Arexx.xg
  467. #define b Arexx.xb
  468. #define r2 Arexx.xr2
  469. #define g2 Arexx.xg2
  470. #define b2 Arexx.xb2
  471. #define Do Arexx.xDo
  472. #define rplus Arexx.xrplus
  473. #define gplus Arexx.xgplus
  474. #define bplus Arexx.xbplus
  475. #define rminus Arexx.xrminus
  476. #define gminus Arexx.xgminus
  477. #define bminus Arexx.xbminus
  478. #define DX Arexx.xDX
  479. #define DY Arexx.xDY
  480. #define Start Arexx.xStart
  481.  
  482. // Display help if available
  483. void
  484. help(ULONG hnum) {
  485.     if (handle) {
  486.         SetAmigaGuideContext(handle,hnum,NULL);
  487.         SendAmigaGuideContext(handle,NULL);
  488.     }
  489. }
  490.  
  491. extern char                 FileName[256]="";    // File name buffer
  492. extern long                    OVQuality=0;    // OpalVision JPG quality
  493. extern BOOL                    OVFast=FALSE;        // OpalVision fast format IFF
  494. extern BOOL                    OVThumb=FALSE;        // OpalVision Thumbail
  495. extern BOOL                    HAM6=FALSE;
  496. extern BOOL                    HAM8=FALSE;
  497. extern BOOL                    BW16=FALSE;
  498. extern BOOL                    BW256=FALSE;
  499. extern BOOL                    DCTV3 = FALSE;
  500. extern BOOL                    DCTV4 = FALSE;
  501. extern UBYTE                 *arrayr=NULL,        // Pointers to red,green and blue
  502.                                   *arrayg=NULL,
  503.                                   *arrayb=NULL;
  504. extern BOOL                    PPM=FALSE;            // PPM save ?
  505. extern BOOL                    EGS=FALSE;            // EGS Preview
  506. extern UBYTE        *p[3] = {NULL,NULL,NULL};// chunky pointers - order for OpalVision
  507. #define RED p[0]
  508. #define BLUE p[2]
  509. #define GREEN p[1]
  510. extern UWORD        swidth=0;        // scaled width (in full words)
  511. extern struct RastPort     RP={0},            // Work Rast Ports
  512.                          TRP={0};
  513. extern struct MyBitMap     MyBitMap={0};    // Real bit map
  514. extern PLANEPTR             Planes[24] = {NULL};    // Bit planes
  515. extern BOOL                    CreateIcons=FALSE;// Create Icons on pictures?
  516.  
  517. extern char                     *Postscript=NULL;// ARexx postscript
  518. BOOL                    Integer = FALSE;
  519.  
  520. /* Main program    */
  521. int
  522. main(int argc,char **argv) {
  523.  BOOL     OkFlag    = TRUE;    // Is it working ?
  524.  char     *e            = NULL;    // error message
  525.  struct MyPoint     MyPoint;        // Points to work with
  526.  struct MyPoint     *MyPointp;
  527.  BOOL                 Opened;        // has file been opened
  528.  struct WBStartup *argmsg;        // Workbench stuff
  529.  struct WBArg         *wb_arg;
  530.  char                 *e1;            // The rest of the error message
  531.  struct Window     *oldWindowPtr;    // Redirect the system requesters
  532.  struct Process     *process;
  533.  char                 *filename;    // file name
  534.  ULONG                 offset,        // 2d to 1d array offsets
  535.                          offset1;
  536.  char                 *Prescript;    // Rexx script names
  537.  UWORD                myx,            // indexes for skipping
  538.                          myy;
  539.  UBYTE                xr,            // more skipping stuff
  540.                          xg,
  541.                          xb;
  542.  struct AmigaGuideMsg *agm;    // help stuff
  543.  struct timeval    time1,        // To display time per image
  544.                          time2;
  545.  struct timerequest tr;
  546.  BOOL                 t2    = FALSE;    // Set when the times calculated
  547.  char                 tbuffer[30];// buffer for time message
  548.  ULONG                hnum = 0;    // Help number for error
  549.  BOOL                    Alloced=FALSE;    // Allocated memory?
  550.  char                    *Tstr;        // Temp string for parameter
  551.  UWORD                xbig;
  552.  double                xsmall;        // Int and rest of coords
  553.  UWORD                ybig;
  554.  double                ysmall;        // y coords
  555.  WORD                    right,down;    // move right and down?
  556.  UWORD                xbig1;
  557.  double                xsmall1;        // Int and rest of coords
  558.  UWORD                ybig1;
  559.  double                ysmall1;        // y coords
  560.  WORD                    right1,down1;// move right and down?
  561.  double                a,bb,c,d,a1,b1,c1,d1;    // AntiAlias stuff
  562.  UBYTE                *er,*eg,*eb;// EGS pointers
  563.  
  564.  // Set up BigPoint
  565.  BigPoint.Cdiff = 0x7FFFFFFF;
  566.  // Initialise points list
  567.  NewList(&PointList);
  568.  // Try and open reqtools.library and dctv.library and nofrag.library
  569.  ReqToolsBase = OpenLibrary("reqtools.library",38);
  570.  DCTVBase = OpenLibrary("dctv.library",3);
  571.  if (NoFragBase = (struct NoFragBase *) OpenLibrary("nofrag.library",2L)) {
  572.   if (!(Chain = GetMemoryChain(MAXMEM+20))) {
  573.    CloseLibrary((struct Library *)NoFragBase);
  574.    NoFragBase = NULL;
  575.   }
  576.  }
  577.  // Set up amigaguide (if available)
  578.  if (AmigaGuideBase = OpenLibrary ("amigaguide.library", 33L)) {
  579.   nag.nag_BaseName = "TSMorph";
  580.   nag.nag_Name = "TSMorph.guide";
  581.   nag.nag_ClientPort = "TSMorph-render_HELP";
  582.   nag.nag_Context = context;
  583.   if (handle = OpenAmigaGuideAsync (&nag, NULL)) {
  584.    ASig = AmigaGuideSignal(handle);
  585.   }
  586.  }
  587.  // Try and open the timer
  588.  if (!OpenDevice(TIMERNAME,UNIT_MICROHZ,(struct IORequest *) &tr, 0L)) {
  589.   TimerBase = (struct Library *)tr.tr_node.io_Device;
  590.  }
  591.  // Try and open OpalVision library
  592.  OpalBase = (struct OpalBase *)OpenLibrary("opal.library",0L);
  593.  // Open all the libraries
  594.  if (IntuitionBase = (struct IntuitionBase *)OpenLibrary("intuition.library",37L)) {
  595.   if (RexxSysBase = OpenLibrary("rexxsyslib.library",0)) {
  596.    if (IFFParseBase = OpenLibrary("iffparse.library",37L)) {
  597.     if (GfxBase = OpenLibrary("graphics.library",37L)) {
  598.      if (LayersBase = OpenLibrary("layers.library",37L)) {
  599.       if (GadToolsBase = OpenLibrary("gadtools.library",37L)) {
  600.        if (AslBase = OpenLibrary("asl.library",37L)) {
  601.         if (UtilityBase = OpenLibrary("utility.library",37)) {
  602.          if (IconBase = OpenLibrary("icon.library",37L)) {
  603.           if (DiskfontBase = OpenLibrary("diskfont.library",36)) {
  604.             // Read and process the parameters
  605.             MyArgArrayInit(argc,argv);
  606.             if (MatchToolValue(MyArgString("EGS","NO",FALSE),"YES")) {
  607.                     if ((EGSBase = OpenLibrary("egs.library",0)) &&
  608.                            (EGSGfxBase = OpenLibrary("egsgfx.library", 0)) &&
  609.                         (EGSIntuiBase = OpenLibrary("egsintui.library", 0))) {
  610.                         EGS = TRUE;
  611.                     }
  612.                 }
  613.             if (MatchToolValue(MyArgString("REQTOOLS","YES",FALSE),"NO")) {
  614.              if (ReqToolsBase) {
  615.               CloseLibrary(ReqToolsBase);
  616.               ReqToolsBase = NULL;
  617.              }
  618.             }
  619.             PubScreenName = MyArgString("PUBSCREENR",NULL,FALSE);
  620.             // Open the progress window
  621.                if ((!SetupScreen())  && (!OpenProgressWindow())) {
  622.                    // redirect requesters
  623.              process = (struct Process *)FindTask(NULL);
  624.              oldWindowPtr = process->pr_WindowPtr;
  625.              process->pr_WindowPtr = ProgressWnd;
  626.              // Open the project file (CLI or WB)
  627.              DisableWindow();
  628.                   AddMessage("Opening points file");
  629.              if (argc) {
  630.                 if (filename = ArgString(ArgArray,"FILES",NULL)) {
  631.                Opened = MyOpen(filename,FALSE);
  632.               }
  633.               else {
  634.                 Opened = MyOpen(NULL,FALSE);
  635.               }
  636.              }
  637.              else {
  638.               argmsg = (struct WBStartup *)argv;
  639.                  if (argmsg->sm_NumArgs > 1) {
  640.                 wb_arg = argmsg->sm_ArgList;
  641.                 wb_arg++;
  642.                 if (wb_arg->wa_Lock) {
  643.                   NameFromLock(wb_arg->wa_Lock,buffer,256);
  644.                  }
  645.                   if (AddPart(buffer,wb_arg->wa_Name,256)) {
  646.                    Opened = MyOpen(buffer,FALSE);
  647.                }
  648.               }
  649.               else {
  650.                   Opened = MyOpen(NULL,FALSE);
  651.                  }
  652.                 }
  653.                 if (Opened) {
  654.                  // Get a few parameters
  655.                  Tstr = MyArgString("SAVEFORMAT","ILBM24",FALSE);
  656.                  if (OpalBase) {
  657.                   if (MatchToolValue(Tstr,"OPAL24") || MatchToolValue(Tstr,"OPAL24T") ||
  658.                       MatchToolValue(Tstr,"OPAL24F") || MatchToolValue(Tstr,"OPAL24FT")) {
  659.                    OVFormat = "IFF";
  660.                   }
  661.                   else {
  662.                    if (MatchToolValue(Tstr,"JPEG") || MatchToolValue(Tstr,"JPEGT")) {
  663.                     OVFormat = "JPG";
  664.                    }
  665.                    else {
  666.                     OVFormat = NULL;
  667.                    }
  668.                   }
  669.                  }
  670.                  else {
  671.                   OVFormat = NULL;
  672.                  }
  673.                  PPM = MatchToolValue(Tstr,"PPM");
  674.                  HAM6 = MatchToolValue(Tstr,"HAM6");
  675.                  HAM8 = MatchToolValue(Tstr,"HAM8");
  676.                  BW16 = MatchToolValue(Tstr,"BW16");
  677.                  BW256 = MatchToolValue(Tstr,"BW256");
  678.                  if (DCTVBase) {
  679.                   DCTV3 = MatchToolValue(Tstr,"DCTV3");
  680.                   DCTV4 = MatchToolValue(Tstr,"DCTV4");
  681.                  }
  682.               OVQuality = MyArgInt("QUALITY",75,FALSE);
  683.               if (MatchToolValue(Tstr,"OPAL24T") || MatchToolValue(Tstr,"JPEGT")) {
  684.                OVThumb = TRUE;
  685.               }
  686.               else {
  687.                OVThumb = FALSE;
  688.               }
  689.               if (MatchToolValue(Tstr,"OPAL24F") || MatchToolValue(Tstr,"OPAL24FT")) {
  690.                OVFast = TRUE;
  691.               }
  692.               else {
  693.                OVFast = FALSE;
  694.               }
  695.               Prescript = MyArgString("PRESCRIPT","Rexx/Prescript",FALSE);
  696.               Postscript = MyArgString("POSTSCRIPT","Rexx/Postscript",FALSE);
  697.               Loadscript = MyArgString("LOADSCRIPT","Rexx/Loadscript",FALSE);
  698.               DX = MyArgInt("DX",0,FALSE);
  699.               DY = MyArgInt("DY",0,FALSE);
  700. //            Depth = min(MyArgInt("DEPTH",2,FALSE),20);    Set in Open()
  701. //            Mode = MyArgInt("MODE",0,FALSE);
  702.               CreateIcons = MatchToolValue(MyArgString("CREATEICONSR","NO",FALSE),"YES");
  703.               AntiAlias = MatchToolValue(MyArgString("ANTIALIAS","NO",FALSE),"YES");
  704.               Integer = MatchToolValue(MyArgString("INTEGER","NO",FALSE),"YES");
  705.               if (Integer) {
  706.                AntiAlias = FALSE;
  707.               }
  708.                  // File has been opened, cache width in full words
  709.                  swidth = (((width+15)>>4)<<4);
  710.                    AddMessage("Allocating work memory");
  711.                    // Allocate chunky and ILBM bit maps
  712.                  if ((RED = AllocVec((swidth*height),MEMF_CLEAR)) &&
  713.                          (GREEN = AllocVec((swidth*height),MEMF_CLEAR)) &&
  714.                          (BLUE =  AllocVec((swidth*height),MEMF_CLEAR)) &&
  715.                          ((OpalBase && OVFormat && !PPM && (OScrn = CreateScreen24(0,width,height))) ||
  716.                           PPM ||
  717.                           (!OVFormat && !PPM &&
  718.                           (Planes[0] = AllocRaster(width,height)) &&
  719.                           (Planes[1] = AllocRaster(width,height)) &&
  720.                           (Planes[2] = AllocRaster(width,height)) &&
  721.                           (DCTV3 ||
  722.                            ((Planes[3] = AllocRaster(width,height)) &&
  723.                            (DCTV4 || BW16 ||
  724.                             ((Planes[4] = AllocRaster(width,height)) &&
  725.                              (Planes[5] = AllocRaster(width,height)) &&
  726.                              (HAM6 ||
  727.                               ((Planes[6] = AllocRaster(width,height)) &&
  728.                                (Planes[7] = AllocRaster(width,height)) &&
  729.                                (HAM8 || BW256 ||
  730.                                 ((Planes[8] = AllocRaster(width,height)) &&
  731.                                  (Planes[9] = AllocRaster(width,height)) &&
  732.                                  (Planes[10] = AllocRaster(width,height)) &&
  733.                                  (Planes[11] = AllocRaster(width,height)) &&
  734.                                  (Planes[12] = AllocRaster(width,height)) &&
  735.                                  (Planes[13] = AllocRaster(width,height)) &&
  736.                                  (Planes[14] = AllocRaster(width,height)) &&
  737.                                  (Planes[15] = AllocRaster(width,height)) &&
  738.                                  (Planes[16] = AllocRaster(width,height)) &&
  739.                                  (Planes[17] = AllocRaster(width,height)) &&
  740.                                  (Planes[18] = AllocRaster(width,height)) &&
  741.                                  (Planes[19] = AllocRaster(width,height)) &&
  742.                                  (Planes[20] = AllocRaster(width,height)) &&
  743.                                  (Planes[21] = AllocRaster(width,height)) &&
  744.                                  (Planes[22] = AllocRaster(width,height)) &&
  745.                                  (Planes[23] = AllocRaster(width,height))))))))))))) { // Looks like LISP!!!!
  746.                      Alloced = TRUE;
  747.                      // Update the progress
  748.                     EnableWindow();
  749.                     GT_SetGadgetAttrs(ProgressGadgets[GDX_Frame],ProgressWnd,NULL,
  750.                                            GTSL_Min,1,
  751.                                           GTSL_Max,Frames,TAG_END);
  752.                     GT_SetGadgetAttrs(ProgressGadgets[GDX_Line],ProgressWnd,NULL,
  753.                                            GTSL_Min,0,
  754.                                           GTSL_Max,height-1,TAG_END);
  755.                    // Pass to ARexx for processing
  756.                     if (strcmp(Prescript,"OFF")) {
  757.                     AddMessage("Prescript for frame 0");
  758.                    f = 0;
  759.                    Do = 0;
  760.                      strcpy(buffer,Prescript);
  761.                      strcat(buffer," %ld");
  762.                      sprintf(buffer1,buffer,&Arexx);
  763.                      OkFlag = !SendRxMsg(buffer1,FALSE);
  764.                      if (!OkFlag) {
  765.                        e = (char *)-1;
  766.                      }
  767.                      if (Do && OkFlag) {
  768.                       OkFlag = LoadFrames(FALSE,TRUE,FALSE);
  769.                       if (!OkFlag) {
  770.                        e = (char *)-1;
  771.                       }
  772.                       else {
  773.                       AddMessage("Saving frame 0");
  774.                        memcpy(RED,Pic1.red,swidth*height);
  775.                        memcpy(GREEN,Pic1.green,swidth*height);
  776.                        memcpy(BLUE,Pic1.blue,swidth*height);
  777.                        OkFlag = SaveFile();
  778.                      if (!OkFlag) {
  779.                       e = (char *)-1;
  780.                      }
  781.                       }
  782.                      }
  783.                     }
  784.                     if ((Mode & MODE_ONCE) && OkFlag) {
  785.                      AddMessage("Precalculating points");
  786.                      Points = PointsAlloc;
  787.                       for (MyPointp = (struct MyPoint *)PointList.lh_Head;
  788.                             MyPointp->MyNode.mln_Succ;
  789.                            MyPointp = (struct MyPoint *)MyPointp->MyNode.mln_Succ) {
  790.                        MyPointp->Cx = (MyPointp->x1+MyPointp->x)>>1;
  791.                        MyPointp->Cy = (MyPointp->y1+MyPointp->y)>>1;
  792.                      }
  793.                         for (y=0;
  794.                         ((y<height) && OkFlag);
  795.                         y++) {
  796.                          // Loop thru columns
  797.                       for (x=0;
  798.                       x < width;
  799.                        x++) {
  800.                       // Determine coordinates on end image(s)
  801.                       FindPoint(&MyPoint,FALSE);
  802.                       Points += (Depth+4);
  803.                         if (DX) {
  804.                          x++;
  805.                          for (myx = 0;
  806.                                   (myx < DX) && (x < width);
  807.                                   x++,myx++) {
  808.                          Points += (Depth+4);
  809.                          }
  810.                          x--;
  811.                         }
  812.                         }
  813.                         // end of line, check 'Stop' and 'Help'
  814.                         OkFlag = HandleProgressIDCMP();
  815.                    if (handle) {
  816.                      while (agm = GetAmigaGuideMsg(handle)) {
  817.                        ReplyAmigaGuideMsg(agm);
  818.                      }
  819.                     }
  820.                         if (DY) {
  821.                          y++;
  822.                           for (myy = 0;
  823.                               (myy < DY) && (y<height);
  824.                               y++, myy++) {
  825.                        Points += ((Depth+4)*width);
  826.                          }
  827.                          y--;
  828.                     }
  829.                    }
  830.                       // not ok - already displayed an error
  831.                       if (!OkFlag) {
  832.                        e = (char *)-1;
  833.                   }
  834.                   else {
  835.                        if (Mode & MODE_DELAU) {
  836.                       AddMessage("Calculating triangles");
  837.                         OkFlag = GenerateTriangles();
  838.                         if (!OkFlag) {
  839.                     Error("Out of memory for points","Quit",NULL,H_MemPointsR);
  840.                         }
  841.                        }
  842.                       }
  843.                     }
  844.                     // Determine start time
  845.                     if (TimerBase) {
  846.                      GetSysTime(&time1);
  847.                     }
  848.                     // Loop thru frames
  849.                 for (f=1;
  850.                       (f < (Frames+1)) && OkFlag;        // no of Frames
  851.                         f++) {
  852.                      // Update progress
  853.                      AddMessage("Prescript processing");
  854.                    GT_SetGadgetAttrs(ProgressGadgets[GDX_Frame],ProgressWnd,NULL,
  855.                                             GTSL_Level,f,TAG_END);
  856.                    // calculate default image parameters
  857.                      rplus = gplus = bplus = rminus = gminus = bminus = 0;
  858.                      if ((Single == 1) || (Single == 3)) {
  859.                       move = ((Frames-f) << 10)/Frames;
  860.                       r = g = b = 1024;
  861.                       r2 = g2 = b2 = 0;
  862.                       Do = 1;
  863.                      }
  864.                      else {
  865.                       r = g = b = move = ((Frames-f+1) << 10)/(Frames + 1);
  866.                       r2 = g2 = b2 = (1024 - r);
  867.                       Do = 1;
  868.                      }
  869.                      // Pass to ARexx for processing
  870.                      if (strcmp(Prescript,"OFF")) {
  871.                       strcpy(buffer,Prescript);
  872.                       strcat(buffer," %ld");
  873.                       sprintf(buffer1,buffer,&Arexx);
  874.                       OkFlag = !SendRxMsg(buffer1,FALSE);
  875.                       if (!OkFlag) {
  876.                        e = (char *)-1;
  877.                       }
  878.                      }
  879.                    if (OkFlag && Do && ((!Pic1_Open) || (Single == 2) || (Single == 3))) {
  880.                  if (Pic2_Open) {
  881.                     Close24bit(&Pic2);
  882.                     Pic2_Open = FALSE;
  883.                    }
  884.                   if (Pic1_Open) {
  885.                    Close24bit(&Pic1);
  886.                    Pic1_Open = FALSE;
  887.                   }
  888.                       OkFlag = LoadFrames(TRUE,TRUE,TRUE);
  889.                       if (!OkFlag) {
  890.                        e = (char *)-1;
  891.                       }
  892.                      }
  893.                      else {    // Version 2.4 - Open frame 2 if not yet open
  894.                       if (OkFlag && Do && !Pic2_Open && (Single == 0)) {
  895.                        OkFlag = LoadFrames(FALSE,FALSE,TRUE);
  896.                       }
  897.                      }
  898.                      if ((PointCount < 3) && OkFlag) {
  899.                       Error("Must have at least 3 points","Quit",NULL,H_3Points);
  900.                       OkFlag = FALSE;
  901.                      }
  902.                      if (Do && OkFlag) {
  903.                       // If we have calculated time per image the display it, update other gadgets
  904.                       if (t2) {
  905.                        sprintf(tbuffer,"%ld.%02ld Seconds for last image",time2.tv_secs,time2.tv_micro/10000);
  906.                      AddMessage(tbuffer);
  907.                       }
  908.                       else {
  909.                      AddMessage("Rendering image");
  910.                     }
  911.                     if (TimerBase) {
  912.                      GetSysTime(&time1);
  913.                     }
  914.                       // We want to do this image so calculate coordinates in this image
  915.                       if ((Single == 1) || (Single == 3)) {
  916.                        for (MyPointp = (struct MyPoint *)PointList.lh_Head;
  917.                             MyPointp->MyNode.mln_Succ;
  918.                            MyPointp = (struct MyPoint *)MyPointp->MyNode.mln_Succ) {
  919.                            MyPointp->Cx = (MyPointp->x1*(1024-move)+MyPointp->x*move)>>10;
  920.                            MyPointp->Cy = (MyPointp->y1*(1024-move)+MyPointp->y*move)>>10;
  921.                      }
  922.                     }
  923.                     else {
  924.                        for (MyPointp = (struct MyPoint *)PointList.lh_Head;
  925.                              MyPointp->MyNode.mln_Succ;
  926.                             MyPointp = (struct MyPoint *)MyPointp->MyNode.mln_Succ) {
  927.                             MyPointp->Cx = (MyPointp->x1*(1024-move)+MyPointp->x*move)>>10;
  928.                             MyPointp->Cy = (MyPointp->y1*(1024-move)+MyPointp->y*move)>>10;
  929.                      }
  930.                     }
  931.                       if (Mode & MODE_SEARCH) {
  932.                      AddMessage("Sorting points");
  933.                         qsort((char *)PointsX,PointCount,sizeof(struct MyPoint *),cmpX);
  934.                         qsort((char *)PointsY,PointCount,sizeof(struct MyPoint *),cmpY);
  935.                       }
  936.                       if ((Mode & MODE_DELAU) && (!MODE_ONCE)) {
  937.                      AddMessage("Calculating triangles");
  938.                        OkFlag = GenerateTriangles();
  939.                        if (!OkFlag) {
  940.                    Error("Out of memory for points","Quit",NULL,H_MemPointsR);
  941.                        }
  942.                       }
  943.                     // Initialise chunky pointers
  944.                      er = arrayr=RED;
  945.                      eg = arrayg=GREEN;
  946.                      eb = arrayb=BLUE;
  947.                      Points = PointsAlloc;
  948.                      // loop thru lines
  949.                         for (y=0;
  950.                         (y<height) && OkFlag;
  951.                         y++) {
  952.                         // Update progress
  953.                       GT_SetGadgetAttrs(ProgressGadgets[GDX_Line],ProgressWnd,NULL,
  954.                                                  GTSL_Level,(ULONG)y,TAG_END);
  955.                          // Loop thru columns
  956.                       for (x=0;
  957.                       x < width;
  958.                        x++) {
  959.                       // Determine coordinates on end image(s)
  960.                       FindPoint(&MyPoint,TRUE);
  961.                       if (Mode & MODE_ONCE) {
  962.                           Points += (Depth+4);
  963.                        }
  964.                       if (AntiAlias) {
  965.                        // Horrible AntiAlias stuff
  966.                        xbig = floor(MyPoint.xd + 0.5);
  967.                        xsmall = MyPoint.xd - (double)xbig;
  968.                        if (xsmall > 0) {
  969.                         right = 1;
  970.                        }
  971.                        else {
  972.                         xsmall = -xsmall;
  973.                         right = -1;
  974.                        }
  975.                        ybig = floor(MyPoint.yd + 0.5);
  976.                        ysmall = MyPoint.yd - (double)ybig;
  977.                        if (ysmall > 0) {
  978.                         down = swidth;
  979.                        }
  980.                        else {
  981.                         ysmall = -ysmall;
  982.                         down = -swidth;
  983.                        }
  984.                        offset = ybig*swidth+xbig;
  985.                        a = 1.0 + (xsmall * ysmall) - xsmall - ysmall;
  986.                        bb = xsmall * (1.0 - ysmall);
  987.                        c = ysmall * (1.0 - xsmall);
  988.                        d = xsmall * ysmall;
  989.                        if ((Single != 1) && (Single != 3)) {
  990.                       xbig1 = floor(MyPoint.x1d + 0.5);
  991.                         xsmall1 = MyPoint.x1d - (double)xbig1;
  992.                         if (xsmall1 > 0) {
  993.                          right1 = 1;
  994.                         }
  995.                         else {
  996.                          xsmall1 = -xsmall1;
  997.                          right1 = -1;
  998.                         }
  999.                         ybig1 = floor(MyPoint.y1d + 0.5);
  1000.                         ysmall1 = MyPoint.y1d - (double)ybig1;
  1001.                         if (ysmall1 > 0) {
  1002.                          down1 = swidth;
  1003.                         }
  1004.                         else {
  1005.                          ysmall1 = -ysmall1;
  1006.                          down1 = -swidth;
  1007.                         }
  1008.                         offset1 = ybig1*swidth+xbig1;
  1009.                         a1 = 1.0 + (xsmall1 * ysmall1) - xsmall1 - ysmall1;
  1010.                         b1 = xsmall1 * (1.0 - ysmall1);
  1011.                         c1 = ysmall1 * (1.0 - xsmall1);
  1012.                         d1 = xsmall1 * ysmall1;
  1013.                         (*arrayr) = min(max((((ULONG)
  1014.                                                         ((((double)  Pic1.red[offset])*a + ((double)  Pic1.red[offset+right])*bb+
  1015.                                                      ((double)  Pic1.red[offset+down])*c+((double)  Pic1.red[offset+down+right])*d)*((double)r) +
  1016.                                                         (((double)  Pic2.red[offset1])*a1 + ((double)  Pic2.red[offset1+right1])*b1+
  1017.                                                      ((double)  Pic2.red[offset1+down1])*c1+((double)  Pic2.red[offset1+down1+right1])*d1)*((double)r2))
  1018.                                                     )>>10) + rplus - rminus,0),255);
  1019.                         (*arrayg) = min(max((((ULONG)
  1020.                                                         ((((double)Pic1.green[offset])*a + ((double)Pic1.green[offset+right])*bb+
  1021.                                                      ((double)Pic1.green[offset+down])*c+((double)Pic1.green[offset+down+right])*d)*((double)g) +
  1022.                                                         (((double)Pic2.green[offset1])*a1 + ((double)Pic2.green[offset1+right1])*b1+
  1023.                                                      ((double)Pic2.green[offset1+down1])*c1+((double)Pic2.green[offset1+down1+right1])*d1)*((double)g2))
  1024.                                                     )>>10) + gplus - gminus,0),255);
  1025.                         (*arrayb) = min(max((((ULONG)
  1026.                                                         ((((double) Pic1.blue[offset])*a + ((double) Pic1.blue[offset+right])*bb+
  1027.                                                      ((double) Pic1.blue[offset+down])*c+((double) Pic1.blue[offset+down+right])*d)*((double)b) +
  1028.                                                         (((double) Pic2.blue[offset1])*a1 + ((double) Pic2.blue[offset1+right1])*b1+
  1029.                                                      ((double) Pic2.blue[offset1+down1])*c1+((double) Pic2.blue[offset1+down1+right1])*d1)*((double)b2))
  1030.                                                     )>>10) + bplus - bminus,0),255);
  1031.                        }
  1032.                        else {
  1033.                         (*arrayr) = min(max(((ULONG)
  1034.                                                         (((((double)Pic1.red[offset])*a + ((double)Pic1.red[offset+right])*bb+
  1035.                                                      ((double)Pic1.red[offset+down])*c+((double)Pic1.red[offset+down+right])*d)
  1036.                                                     )*((double)r))>>10) + rplus - rminus,0),255);
  1037.                           (*arrayg) = min(max(((ULONG)
  1038.                                                     (((((double)Pic1.green[offset])*a + ((double)Pic1.green[offset+1])*bb+
  1039.                                                      ((double)Pic1.green[offset+down])*c+((double)Pic1.green[offset+down+right])*d)
  1040.                                                       )*((double)g))>>10) + gplus - gminus,0),255);
  1041.                            (*arrayb) = min(max(((ULONG)
  1042.                                                         (((((double)Pic1.blue[offset])*a + ((double)Pic1.blue[offset+1])*bb+
  1043.                                                      ((double)Pic1.blue[offset+down])*c+((double)Pic1.blue[offset+down+right])*d)
  1044.                                                        )*((double)b))>>10) + bplus - bminus,0),255);
  1045.                        }
  1046.                       }
  1047.                       else {
  1048.                        // Calculate new colours (without AntiAlias)
  1049.                        offset = MyPoint.y*swidth+MyPoint.x;
  1050.                        if ((Single == 1) || (Single == 3)) {
  1051.                         (*arrayr) = min(max(((Pic1.red[offset]*r)>>10) + rplus - rminus,0),255);
  1052.                           (*arrayg) = min(max(((Pic1.green[offset]*g)>>10) + gplus - gminus,0),255);
  1053.                            (*arrayb) = min(max(((Pic1.blue[offset]*b)>>10) + bplus - bminus,0),255);
  1054.                          }
  1055.                          else {
  1056.                       offset1 = MyPoint.y1*swidth+MyPoint.x1;
  1057.                         (*arrayr) = min(max((((Pic2.red[offset1]*r2) +
  1058.                                              (Pic1.red[offset]*r))>>10) + rplus - rminus,0),255);
  1059.                           (*arrayg) = min(max((((Pic2.green[offset1]*g2) +
  1060.                                          (Pic1.green[offset]*g))>>10) + gplus - gminus,0),255);
  1061.                            (*arrayb) = min(max((((Pic2.blue[offset1]*b2) +
  1062.                                              (Pic1.blue[offset]*b))>>10) + bplus - bminus,0),255);
  1063.                          }
  1064.                         }
  1065.                         // If we are skipping columns then copy colour forward
  1066.                         if (DX) {
  1067.                            xr = *arrayr;
  1068.                          xg = *arrayg;
  1069.                          xb = *arrayb;
  1070.                          x++;
  1071.                          for (myx = 0;
  1072.                                   (myx < DX) && (x < width);
  1073.                                   x++,myx++) {
  1074.                            if (Mode & MODE_ONCE) {
  1075.                              Points += (Depth+4);
  1076.                           }
  1077.                            arrayr++;
  1078.                           *arrayr = xr;
  1079.                        arrayg++;
  1080.                           *arrayg = xg;
  1081.                           arrayb++;
  1082.                           *arrayb = xb;
  1083.                          }
  1084.                          x--;
  1085.                         }
  1086.                         // next column (if not already there)
  1087.                         if (x < width) {
  1088.                          arrayr++;
  1089.                       arrayg++;
  1090.                          arrayb++;
  1091.                         }
  1092.                         }
  1093.                         // end of line, check 'Stop' and 'Help'
  1094.                         OkFlag = HandleProgressIDCMP();
  1095.                    if (handle) {
  1096.                      while (agm = GetAmigaGuideMsg(handle)) {
  1097.                        ReplyAmigaGuideMsg(agm);
  1098.                      }
  1099.                     }
  1100.                     // skip part word at end of line
  1101.                         arrayr += (swidth - width);
  1102.                         arrayg += (swidth - width);
  1103.                         arrayb += (swidth - width);
  1104.                         if (EGS_Win) {
  1105.                             CopyEGS(y,&er,&eg,&eb);
  1106.                         }
  1107.                         // if skipping lines then copy previous line
  1108.                         if (DY) {
  1109.                          y++;
  1110.                           for (myy = 0;
  1111.                               (myy < DY) && (y<height);
  1112.                               y++, myy++) {
  1113.                           memcpy(arrayr, arrayr - swidth, swidth);
  1114.                           arrayr += swidth;
  1115.                           memcpy(arrayg, arrayg - swidth, swidth);
  1116.                           arrayg += swidth;
  1117.                           memcpy(arrayb, arrayb - swidth, swidth);
  1118.                           arrayb += swidth;
  1119.                            if (EGS_Win) {
  1120.                             CopyEGS(y,&er,&eg,&eb);
  1121.                            }
  1122.                           if (Mode & MODE_ONCE) {
  1123.                            Points += ((Depth+4)*width);
  1124.                         }
  1125.                          }
  1126.                          y--;
  1127.                         }
  1128.                       }
  1129.                       if ((Mode & MODE_DELAU) && (!MODE_ONCE)) {
  1130.                        FreeTriangles();
  1131.                  }
  1132.                       // not ok - already displayed an error
  1133.                       if (!OkFlag) {
  1134.                        e = (char *)-1;
  1135.                   }
  1136.                       else {
  1137.                        // Save image
  1138.                        OkFlag = SaveFile();
  1139.                        // Caclulate time (if we have not already)
  1140.                       if (TimerBase) {
  1141.                         GetSysTime(&time2);
  1142.                         t2 = TRUE;
  1143.                         SubTime(&time2,&time1);
  1144.                         }
  1145.                         // Not ok - already displayed error message
  1146.                         if (!OkFlag) {
  1147.                         e = (char *)-1;
  1148.                        }
  1149.                          }
  1150.                   }
  1151.                  }
  1152.                  if (OkFlag && ((Single == 0) || (Single == 2))) {
  1153.                      // Pass to ARexx for processing
  1154.                       if (strcmp(Prescript,"OFF")) {
  1155.                      AddMessage("Prescript for last frame");
  1156.                     f = Frames+1;
  1157.                     Do = 0;
  1158.                       strcpy(buffer,Prescript);
  1159.                       strcat(buffer," %ld");
  1160.                       sprintf(buffer1,buffer,&Arexx);
  1161.                       OkFlag = !SendRxMsg(buffer1,FALSE);
  1162.                       if (!OkFlag) {
  1163.                        e = (char *)-1;
  1164.                       }
  1165.                     if (OkFlag && Do && ((!Pic1_Open) || (Single == 2))) {
  1166.                   if (Pic2_Open) {
  1167.                      Close24bit(&Pic2);
  1168.                      Pic2_Open = FALSE;
  1169.                     }
  1170.                    if (Pic1_Open) {
  1171.                     Close24bit(&Pic1);
  1172.                     Pic1_Open = FALSE;
  1173.                    }
  1174.                        OkFlag = LoadFrames(FALSE,FALSE,TRUE);
  1175.                        if (!OkFlag) {
  1176.                         e = (char *)-1;
  1177.                        }
  1178.                       }
  1179.                       if (OkFlag && Do) {
  1180.                       AddMessage("Saving last frame");
  1181.                        memcpy(RED,Pic2.red,swidth*height);
  1182.                        memcpy(GREEN,Pic2.green,swidth*height);
  1183.                        memcpy(BLUE,Pic2.blue,swidth*height);
  1184.                        OkFlag = SaveFile();
  1185.                      if (!OkFlag) {
  1186.                       e = (char *)-1;
  1187.                      }
  1188.                       }
  1189.                      }
  1190.                     }
  1191.                 }
  1192.                    AddMessage("Cleaning up");
  1193.                    if ((Mode & MODE_DELAU) && (MODE_ONCE)) {
  1194.                    FreeTriangles();
  1195.               }
  1196.                    DeleteAllPoints();
  1197.                    if (RED) FreeVec(RED);
  1198.                    if (GREEN) FreeVec(GREEN);
  1199.                if (BLUE) FreeVec(BLUE);
  1200.                if (OScrn) {
  1201.                 FreeScreen24(OScrn);
  1202.                }
  1203.                else {    // Should not need this if else
  1204.                    if (!PPM) {
  1205.                   if (Planes[0]) FreeRaster(Planes[0],width,height);
  1206.                  if (Planes[1]) FreeRaster(Planes[1],width,height);
  1207.                  if (Planes[2]) FreeRaster(Planes[2],width,height);
  1208.                  if (!DCTV3) {
  1209.                   if (Planes[3]) FreeRaster(Planes[3],width,height);
  1210.                   if (!BW16 && !DCTV4) {
  1211.                    if (Planes[4]) FreeRaster(Planes[4],width,height);
  1212.                    if (Planes[5]) FreeRaster(Planes[5],width,height);
  1213.                    if (!HAM6) {
  1214.                     if (Planes[6]) FreeRaster(Planes[6],width,height);
  1215.                     if (Planes[7]) FreeRaster(Planes[7],width,height);
  1216.                     if (!HAM8 && !BW256) {
  1217.                      if (Planes[8]) FreeRaster(Planes[8],width,height);
  1218.                      if (Planes[9]) FreeRaster(Planes[9],width,height);
  1219.                      if (Planes[10]) FreeRaster(Planes[10],width,height);
  1220.                      if (Planes[11]) FreeRaster(Planes[11],width,height);
  1221.                      if (Planes[12]) FreeRaster(Planes[12],width,height);
  1222.                      if (Planes[13]) FreeRaster(Planes[13],width,height);
  1223.                      if (Planes[14]) FreeRaster(Planes[14],width,height);
  1224.                      if (Planes[15]) FreeRaster(Planes[15],width,height);
  1225.                      if (Planes[16]) FreeRaster(Planes[16],width,height);
  1226.                      if (Planes[17]) FreeRaster(Planes[17],width,height);
  1227.                      if (Planes[18]) FreeRaster(Planes[18],width,height);
  1228.                      if (Planes[19]) FreeRaster(Planes[19],width,height);
  1229.                      if (Planes[20]) FreeRaster(Planes[20],width,height);
  1230.                      if (Planes[21]) FreeRaster(Planes[21],width,height);
  1231.                      if (Planes[22]) FreeRaster(Planes[22],width,height);
  1232.                      if (Planes[23]) FreeRaster(Planes[23],width,height);
  1233.                     }
  1234.                    }
  1235.                   }
  1236.                  }
  1237.                 }
  1238.                }
  1239.                 if (!Alloced && !e) {
  1240.                  e = "Error AllocVec for output";
  1241.                  e1 = NULL;
  1242.                  hnum = H_AllocVec;
  1243.                 }
  1244.                }
  1245.                else {
  1246.                 e = (char *)-1;
  1247.                }
  1248.                if (OkFlag) {
  1249.                 e = (char *)-1;
  1250.                }
  1251.                if (!e) {
  1252.                  e = "Error Opening points file";
  1253.                 e1 = NULL;
  1254.                 hnum = H_OpenPoints;
  1255.                }
  1256.                if (Pic2_Open) {
  1257.                 Close24bit(&Pic2);
  1258.                 Pic2_Open = FALSE;
  1259.                }
  1260.               if (Pic1_Open) {
  1261.                Close24bit(&Pic1);
  1262.                Pic1_Open = FALSE;
  1263.               }
  1264.                 if (plane0) MyFreeVec(plane0);
  1265.                 if (plane1) MyFreeVec(plane1);
  1266.                 if (plane2) MyFreeVec(plane2);
  1267.                 if (plane3) MyFreeVec(plane3);
  1268.                 if (plane4) MyFreeVec(plane4);
  1269.                 if (plane5) MyFreeVec(plane5);
  1270.                 if (plane6) MyFreeVec(plane6);
  1271.                 if (plane7) MyFreeVec(plane7);
  1272.                 // reset requesters
  1273.               process->pr_WindowPtr = oldWindowPtr;
  1274.              }
  1275.              else {
  1276.               e = "Error opening progress window";
  1277.               e1 = NULL;
  1278.               hnum = H_Progress;
  1279.              }
  1280.              // close down everything
  1281.              CloseProgressWindow();
  1282.              CloseDownScreen();
  1283.                MyArgArrayDone();
  1284.             if (EGS) {
  1285.                     if (EGS_Win) {
  1286.                         EI_CloseWindow(EGS_Win);
  1287.                     }
  1288.                     if (EGS_BitMap) {
  1289.                         E_DisposeBitMap(EGS_BitMap);
  1290.                     }
  1291.                 }
  1292.                 if (EGSIntuiBase) {
  1293.                  CloseLibrary(EGSIntuiBase);
  1294.                 }
  1295.                 if (EGSGfxBase) {
  1296.                  CloseLibrary(EGSGfxBase);
  1297.                 }
  1298.                 if (EGSBase) {
  1299.                  CloseLibrary(EGSBase);
  1300.                 }
  1301.             CloseLibrary(DiskfontBase);
  1302.           }
  1303.           if (!e) {
  1304.            e = "Unable to Open %s";
  1305.            e1 = "diskfont.library(36)";
  1306.            hnum = H_Library;
  1307.           }
  1308.           CloseLibrary(IconBase);
  1309.           }
  1310.           if (!e) {
  1311.            e = "Unable to Open %s";
  1312.            e1 = "icon.library(37)";
  1313.            hnum = H_Library;
  1314.           }
  1315.           CloseLibrary(UtilityBase);
  1316.          }
  1317.         if (!e) {
  1318.          e = "Unable to Open %s";
  1319.          e1= "utility.library(37)";
  1320.          hnum = H_Library;
  1321.         }
  1322.         CloseLibrary(AslBase);
  1323.        }
  1324.        if (!e) {
  1325.         e = "Unable to Open %s";
  1326.         e1 = "asl.library(37)";
  1327.         hnum = H_Library;
  1328.        }
  1329.        CloseLibrary(GadToolsBase);
  1330.       }
  1331.       if (!e) {
  1332.        e = "Unable to Open %s";
  1333.        e1 = "gadtools.library(37)";
  1334.        hnum = H_Library;
  1335.       }
  1336.       CloseLibrary(LayersBase);
  1337.      }
  1338.      if (!e) {
  1339.       e = "Unable to Open %s";
  1340.       e1 = "layers.library(37)";
  1341.       hnum = H_Library;
  1342.      }
  1343.      CloseLibrary(GfxBase);
  1344.     }
  1345.     if (!e) {
  1346.      e = "Unable to Open %s";
  1347.      e1 = "graphics.library(37)";
  1348.      hnum = H_Library;
  1349.     }
  1350.     CloseLibrary(IFFParseBase);
  1351.    }
  1352.    if (!e) {
  1353.     e = "Unable to Open %s";
  1354.     e1 = "iffparse.library(37)";
  1355.     hnum = H_Library;
  1356.    }
  1357.    CloseLibrary(RexxSysBase);
  1358.   }
  1359.   if (!e) {
  1360.    e = "Unable to Open %s";
  1361.    e1 = "rexxsyslib.library(0)";
  1362.    hnum = H_Library;
  1363.   }
  1364.   // Display an error message
  1365.   if (e != (char *)-1) {
  1366.    Error(e,"Quit",e1,hnum);
  1367.   }
  1368.  }
  1369.  if (OpalBase) {
  1370.   CloseLibrary((struct Library *)OpalBase);
  1371.  }
  1372.  if (TimerBase) {
  1373.   CloseDevice((struct IORequest *) &tr);
  1374.  }
  1375.  if (AmigaGuideBase) {
  1376.   if (handle) {
  1377.      CloseAmigaGuide(handle);
  1378.   }
  1379.   CloseLibrary(AmigaGuideBase);
  1380.  }
  1381.  if (NoFragBase) {
  1382.   FreeMemoryChain(Chain,TRUE);
  1383.   CloseLibrary((struct Library *)NoFragBase);
  1384.  }
  1385.  if (DCTVBase) {
  1386.   CloseLibrary(DCTVBase);
  1387.  }
  1388.  if (ReqToolsBase) {
  1389.   CloseLibrary(ReqToolsBase);
  1390.  }
  1391.  if (IntuitionBase) {
  1392.   CloseLibrary((struct Library *)IntuitionBase);
  1393.  }
  1394.  return 0;
  1395. }
  1396.  
  1397. extern UWORD FileFormat = 0;
  1398.  
  1399. /* recognized file formats */
  1400. #define FORMAT_IFF    1
  1401. #define FORMAT_JPEG    2
  1402. #define FORMAT_GIF    3
  1403. #define FORMAT_PPM    4
  1404. #define FORMAT_TARGA    5
  1405.  
  1406. /* Opens a 24 bit image
  1407.  * filename = name of file
  1408.  * pic        = structure to update
  1409.  * GUI        = TRUE to display error message
  1410.  * Returns      TRUE if ok
  1411.  */
  1412. BOOL
  1413. Load24bit(char *filename,struct Picture *pic,BOOL GUI) {
  1414.     char                     *e     = NULL;    // Error message main text
  1415.     char                    *e1     = NULL;    // sub text,
  1416.     struct RastPort     RP,                // Rastport
  1417.                             TRP;                // Temp rastport
  1418.     struct BitMap         BM,                // Bitmap
  1419.                             TBM;                // Temp bitmap
  1420.     ULONG                    hnum    = 0;        // Help on error
  1421.     BOOL                    OkFlag=TRUE;    // Still OK?
  1422.     char                    buffer[256],    // For Rexx Scripts
  1423.                             buffer1[256];
  1424.     long                    Err;                // Opal error
  1425.     BPTR                    fh;
  1426.     UBYTE zbuffer[5]="\0\0\0\0";
  1427.     decompress_info_ptr info;            // Load JPEG stuff
  1428.     UWORD i,j;
  1429.     LONG penno;
  1430.     struct RastPort    Rp;                // Rast port for conversion
  1431.     UBYTE *rx,*gx,*bx;
  1432.     UBYTE rr,gg,bb;
  1433.     UWORD EHB;
  1434.     BOOL isHAM6 = FALSE;
  1435.     BOOL isHAM8 = FALSE;
  1436.     BOOL isEHB = FALSE;
  1437.     struct DisplayInfo queryinfo;
  1438.     DisplayInfoHandle dhandle;
  1439.     struct DCTVCvtHandle    *chandle;    // DCTV conversion stuff
  1440.     UWORD                    *DCTVcolors;    // DCTV palette
  1441.  
  1442.     if (filename) {
  1443.        // Load image processing
  1444.         if (strcmp(Loadscript,"OFF")) {
  1445.             strcpy(buffer,Loadscript);
  1446.             strcat(buffer," %ld %ld %ld %ld %s");
  1447.             sprintf(buffer1,buffer,f+Start-1,Frames,Single,(pic==&Pic1)?0:1,filename);
  1448.              AddMessage("Loadscript processing");
  1449.           OkFlag = !SendRxMsg(buffer1,FALSE);
  1450.           if (!OkFlag) {
  1451.               e = (char *)-1;
  1452.               GUI = FALSE;    // Do not display error
  1453.           }
  1454.        }
  1455.         pic->rgbonelot = FALSE;
  1456.        if (!e) {
  1457.            // determine file format
  1458.             if (fh = Open(filename,MODE_OLDFILE)) {
  1459.                 FRead(fh,zbuffer,4,1);
  1460.                 if ((!strcmp(zbuffer,"FORM")) ||
  1461.                      (!strcmp(zbuffer,"CAT ")) ||
  1462.                      (!strcmp(zbuffer,"LIST"))) {
  1463.                     FileFormat = FORMAT_IFF;
  1464.                 }
  1465.                 else {
  1466.                     if ((zbuffer[0] == 0xFF) &&
  1467.                          (zbuffer[1] == 0xD8)) {
  1468.                         FileFormat = FORMAT_JPEG;
  1469.                     }
  1470.                     else {
  1471.                         if ((zbuffer[0] == 'G') &&
  1472.                              (zbuffer[1] == 'I') &&
  1473.                              (zbuffer[2] == 'F')) {
  1474.                             FileFormat = FORMAT_GIF;
  1475.                         }
  1476.                         else {
  1477.                             if ((zbuffer[0] == 'P') &&
  1478.                                  ((zbuffer[1] == '2') ||
  1479.                                   (zbuffer[1] == '3') ||
  1480.                                   (zbuffer[1] == '5') ||
  1481.                                   (zbuffer[1] == '6'))) {
  1482.                                 FileFormat = FORMAT_PPM;
  1483.                             }
  1484.                             else {
  1485.                                 FileFormat = FORMAT_TARGA;
  1486.                             }
  1487.                         }
  1488.                     }
  1489.                 }
  1490.                 Close(fh);
  1491.             }
  1492.             else {
  1493.                 e = "Error opening file '%s'";
  1494.                 e1 = filename;
  1495.                 hnum = H_Open;
  1496.                 OkFlag = FALSE;
  1497.             }
  1498.         }
  1499.         if (OkFlag) {
  1500.             AddMessage((pic == &Pic2)?"Loading image 2":"Loading image 1");
  1501.         }
  1502.        // We have a file name
  1503.         if (OkFlag && (FileFormat != FORMAT_IFF)) {
  1504.             // Not an IFF file so use JPEG code
  1505.            AddMessage((FileFormat == FORMAT_JPEG)?"Loading JFIF":
  1506.                            (FileFormat == FORMAT_GIF)?"Loading GIF":
  1507.                            (FileFormat == FORMAT_PPM)?"Loading PPM":
  1508.                            (FileFormat == FORMAT_TARGA)?"Loading Targa?":
  1509.                            "Loading ?");
  1510.             if ((info = LoadJPEG(filename,0,NULL,NULL,NULL,NULL)) &&
  1511.                  (info->output_file)) {
  1512.                AddMessage("Allocating work memory");
  1513.                 pic->rgbonelot = TRUE;
  1514.                 pic->red = (UBYTE *)info->output_file;
  1515.                 pic->green = pic->red + (((info->image_width+15)>>4)<<4) * info->image_height;
  1516.                 pic->blue = pic->green + (((info->image_width+15)>>4)<<4) * info->image_height;
  1517.                 // Allocate temp bit maps if first image and no OpalVision save
  1518.                 if ((OVFormat) || (plane0) ||
  1519.                            ((plane0 = MyAllocVec((((width+15)>>4)<<4),MEMF_CHIP|MEMF_CLEAR)) &&
  1520.                             (plane1 = MyAllocVec((((width+15)>>4)<<4),MEMF_CHIP|MEMF_CLEAR)) &&
  1521.                             (plane2 = MyAllocVec((((width+15)>>4)<<4),MEMF_CHIP|MEMF_CLEAR)) &&
  1522.                             (plane3 = MyAllocVec((((width+15)>>4)<<4),MEMF_CHIP|MEMF_CLEAR)) &&
  1523.                             (plane4 = MyAllocVec((((width+15)>>4)<<4),MEMF_CHIP|MEMF_CLEAR)) &&
  1524.                             (plane5 = MyAllocVec((((width+15)>>4)<<4),MEMF_CHIP|MEMF_CLEAR)) &&
  1525.                             (plane6 = MyAllocVec((((width+15)>>4)<<4),MEMF_CHIP|MEMF_CLEAR)) &&
  1526.                             (plane7 = MyAllocVec((((width+15)>>4)<<4),MEMF_CHIP|MEMF_CLEAR)))) {
  1527.                        return TRUE;
  1528.                  }
  1529.                  else {
  1530.                  e = "Unable to %s";
  1531.                   e1 = "allocate memory for bitmap";
  1532.                   hnum = H_AllocPlanes;
  1533.                  }
  1534.             }
  1535.         }
  1536.         if (OkFlag && (FileFormat == FORMAT_IFF)) {
  1537.             // Load iff
  1538.            AddMessage("Loading IFF");
  1539.             if (pic->ilbm = (struct ILBMInfo *)MyAllocMem(sizeof(struct ILBMInfo),MEMF_PUBLIC|MEMF_CLEAR)) {
  1540.                 // IFF stuff
  1541.                if (pic->ilbm->ParseInfo.iff = AllocIFF()) {
  1542.                    // more iff stuff
  1543.                     pic->ilbm->ParseInfo.propchks = props;
  1544.                     pic->ilbm->ParseInfo.collectchks = nowt;
  1545.                     pic->ilbm->ParseInfo.stopchks = stops;
  1546.                     // Load the image using IFF routines
  1547.                     if (!(loadbrush(pic->ilbm,filename))) {
  1548.                         // Close the file and validate
  1549.                         closeifile(&(pic->ilbm->ParseInfo));
  1550.                         pwidth  = width  < 320 ? 320 : width;
  1551.                      pheight = height < 200 ? 200 : height;
  1552.                             pmode   = pwidth >= 640  ? HIRES : 0L;
  1553.                      pmode  |= pheight >= 400 ? LACE  : 0L;
  1554.     // ??????        width = pic->ilbm->Bmhd.w;
  1555.                         // Allocate chunky bit maps
  1556.                        AddMessage("Allocating Bitmaps");
  1557.                         if ((pic->red = AllocVec(((((pic->ilbm->Bmhd.w+15)>>4)<<4)*pic->ilbm->Bmhd.h),MEMF_CLEAR)) &&
  1558.                              (pic->green = AllocVec(((((pic->ilbm->Bmhd.w+15)>>4)<<4)*pic->ilbm->Bmhd.h),MEMF_CLEAR)) &&
  1559.                              (pic->blue = AllocVec(((((pic->ilbm->Bmhd.w+15)>>4)<<4)*pic->ilbm->Bmhd.h),MEMF_CLEAR)) &&
  1560.                                // Allocate temp bit maps if first image and no OpalVision save
  1561.                                ((OVFormat && (pic->ilbm->Bmhd.nPlanes != 24)) || (plane0) ||
  1562.                                ((plane0 = MyAllocVec((((width+15)>>4)<<4),MEMF_CHIP|MEMF_CLEAR)) &&
  1563.                                 (plane1 = MyAllocVec((((width+15)>>4)<<4),MEMF_CHIP|MEMF_CLEAR)) &&
  1564.                                 (plane2 = MyAllocVec((((width+15)>>4)<<4),MEMF_CHIP|MEMF_CLEAR)) &&
  1565.                                 (plane3 = MyAllocVec((((width+15)>>4)<<4),MEMF_CHIP|MEMF_CLEAR)) &&
  1566.                                 (plane4 = MyAllocVec((((width+15)>>4)<<4),MEMF_CHIP|MEMF_CLEAR)) &&
  1567.                                 (plane5 = MyAllocVec((((width+15)>>4)<<4),MEMF_CHIP|MEMF_CLEAR)) &&
  1568.                                 (plane6 = MyAllocVec((((width+15)>>4)<<4),MEMF_CHIP|MEMF_CLEAR)) &&
  1569.                                 (plane7 = MyAllocVec((((width+15)>>4)<<4),MEMF_CHIP|MEMF_CLEAR))))) {
  1570.                             if (pic->ilbm->Bmhd.nPlanes == 24) {
  1571.                                 // Convert 24 bit planar to chunky
  1572.                                AddMessage("Converting 24 bit to Chunky");
  1573.                                 // Initialise rast ports/bitmaps
  1574.                                 InitRastPort(&RP);
  1575.                                 InitRastPort(&TRP);
  1576.                               InitBitMap(&TBM,8,pic->ilbm->Bmhd.w,1);
  1577.                                TRP.BitMap = &TBM;
  1578.                               TBM.Planes[0]=plane0;
  1579.                               TBM.Planes[1]=plane1;
  1580.                               TBM.Planes[2]=plane2;
  1581.                               TBM.Planes[3]=plane3;
  1582.                               TBM.Planes[4]=plane4;
  1583.                               TBM.Planes[5]=plane5;
  1584.                               TBM.Planes[6]=plane6;
  1585.                               TBM.Planes[7]=plane7;
  1586.                               InitBitMap(&BM,8,pic->ilbm->Bmhd.w,pic->ilbm->Bmhd.h);
  1587.                               RP.BitMap = &BM;
  1588.                                  BM.Planes[0] = pic->ilbm->brbitmap->Planes[0];
  1589.                               BM.Planes[1] = pic->ilbm->brbitmap->Planes[1];
  1590.                               BM.Planes[2] = pic->ilbm->brbitmap->Planes[2];
  1591.                               BM.Planes[3] = pic->ilbm->brbitmap->Planes[3];
  1592.                               BM.Planes[4] = pic->ilbm->brbitmap->Planes[4];
  1593.                               BM.Planes[5] = pic->ilbm->brbitmap->Planes[5];
  1594.                               BM.Planes[6] = pic->ilbm->brbitmap->Planes[6];
  1595.                               BM.Planes[7] = pic->ilbm->brbitmap->Planes[7];
  1596.                               // Convert red to chunky
  1597.                               ReadPixelArray8(&RP,0,0,pic->ilbm->Bmhd.w-1,pic->ilbm->Bmhd.h-1,pic->red,&TRP);
  1598.                             WaitBlit();
  1599.                                 BM.Planes[0] = pic->ilbm->brbitmap->Planes[8];
  1600.                               BM.Planes[1] = pic->ilbm->brbitmap->Planes[9];
  1601.                               BM.Planes[2] = pic->ilbm->brbitmap->Planes[10];
  1602.                               BM.Planes[3] = pic->ilbm->brbitmap->Planes[11];
  1603.                               BM.Planes[4] = pic->ilbm->brbitmap->Planes[12];
  1604.                               BM.Planes[5] = pic->ilbm->brbitmap->Planes[13];
  1605.                               BM.Planes[6] = pic->ilbm->brbitmap->Planes[14];
  1606.                               BM.Planes[7] = pic->ilbm->brbitmap->Planes[15];
  1607.                               // and green
  1608.                               ReadPixelArray8(&RP,0,0,pic->ilbm->Bmhd.w-1,pic->ilbm->Bmhd.h-1,pic->green,&TRP);
  1609.                             WaitBlit();
  1610.                               BM.Planes[0] = pic->ilbm->brbitmap->Planes[16];
  1611.                               BM.Planes[1] = pic->ilbm->brbitmap->Planes[17];
  1612.                               BM.Planes[2] = pic->ilbm->brbitmap->Planes[18];
  1613.                               BM.Planes[3] = pic->ilbm->brbitmap->Planes[19];
  1614.                               BM.Planes[4] = pic->ilbm->brbitmap->Planes[20];
  1615.                               BM.Planes[5] = pic->ilbm->brbitmap->Planes[21];
  1616.                               BM.Planes[6] = pic->ilbm->brbitmap->Planes[22];
  1617.                               BM.Planes[7] = pic->ilbm->brbitmap->Planes[23];
  1618.                               // and blue
  1619.                               ReadPixelArray8(&RP,0,0,pic->ilbm->Bmhd.w-1,pic->ilbm->Bmhd.h-1,pic->blue,&TRP);
  1620.                             WaitBlit();
  1621.                                AddMessage("Cleaning up");
  1622.                             // Set up stuff to write image
  1623.     // ????                    width = pic->ilbm->Bmhd.w;
  1624.     //    ????                    height = pic->ilbm->Bmhd.h;
  1625.                              // Unload everything and exit cleanly
  1626.                                 unloadbrush(pic->ilbm);
  1627.                                 FreeIFF(pic->ilbm->ParseInfo.iff);
  1628.                                 MyFreeMem(pic->ilbm,sizeof(struct ILBMInfo));
  1629.                               return TRUE;
  1630.                            }
  1631.                            else {
  1632.                                 if (DCTVBase && TestDCTVSignature(pic->ilbm->brbitmap)) {
  1633.                                     // Convert DCTV to chunky
  1634.                                     if (DCTVcolors = MyAllocVec(2L<<pic->ilbm->Bmhd.nPlanes,MEMF_CLEAR)) {
  1635.                                         for (i=0; i < (1L<<pic->ilbm->Bmhd.nPlanes); ++i) {
  1636.                                             DCTVcolors[i] = ((pic->ilbm->RGB[i*4+1] & 0xf0) << 4) |
  1637.                                                                  ((pic->ilbm->RGB[i*4+2] & 0xf0)) |
  1638.                                                                  ((pic->ilbm->RGB[i*4+3] & 0xf0) >> 4);
  1639.                                         }
  1640.                                        AddMessage("Converting DCTV to Chunky");
  1641.                                         if (chandle = AllocDCTVCvtTags(pic->ilbm->brbitmap,
  1642.                                                         DCTVCVTA_Type, DCTVCVTT_DCTVtoRGB,
  1643.                                                         DCTVCVTA_Width, (((pic->ilbm->Bmhd.w+15)>>4)<<4),
  1644.                                                         DCTVCVTA_Height, pic->ilbm->Bmhd.h,
  1645.                                                         DCTVCVTA_Flags, ((pic->ilbm->camg & LACE)?DCTVCVTF_Lace:0)|
  1646.                                                                             DCTVCVTF_CustomRGBBuf,
  1647.                                                         DCTVCVTA_ColorTable, DCTVcolors,
  1648.                                                         TAG_END)) {
  1649.                                             chandle->Red = pic->red;
  1650.                                             chandle->Green = pic->green;
  1651.                                             chandle->Blue = pic->blue;
  1652.                                             while (chandle->DstLineNum < chandle->Height) {
  1653.                                                 CvtDCTVLine(chandle);
  1654.                                                 if ((chandle->DstLineNum > 0) &&
  1655.                                                      (chandle->DstLineNum <= chandle->Height)) {
  1656.                                                     chandle->Red += (((pic->ilbm->Bmhd.w+15)>>4)<<4);
  1657.                                                     chandle->Green += (((pic->ilbm->Bmhd.w+15)>>4)<<4);
  1658.                                                     chandle->Blue += (((pic->ilbm->Bmhd.w+15)>>4)<<4);
  1659.                                                 }
  1660.                                             }
  1661.                                             MyFreeVec(DCTVcolors);
  1662.                                             FreeDCTVCvt(chandle);
  1663.                                          // Unload everything and exit cleanly
  1664.                                             unloadbrush(pic->ilbm);
  1665.                                             FreeIFF(pic->ilbm->ParseInfo.iff);
  1666.                                             MyFreeMem(pic->ilbm,sizeof(struct ILBMInfo));
  1667.                                             return TRUE;
  1668.                                         }
  1669.                                         MyFreeVec(DCTVcolors);
  1670.                                     }
  1671.                                 }
  1672.                                 else {
  1673.                                     // determine special IFF mode
  1674.                                     if ((dhandle = FindDisplayInfo(pic->ilbm->camg)) &&
  1675.                                          (GetDisplayInfoData(dhandle,(UBYTE *)&queryinfo,sizeof(queryinfo),DTAG_DISP,NULL))) {
  1676.                                         if ((pic->ilbm->Bmhd.nPlanes == 6) && (queryinfo.PropertyFlags & DIPF_IS_HAM)) {
  1677.                                            AddMessage("Converting HAM6 to Chunky");
  1678.                                             isHAM6 = TRUE;
  1679.                                         }
  1680.                                         else {
  1681.                                             if ((pic->ilbm->Bmhd.nPlanes == 8) && (queryinfo.PropertyFlags & DIPF_IS_HAM)) {
  1682.                                                 isHAM8 = TRUE;
  1683.                                                AddMessage("Converting HAM8 to Chunky");
  1684.                                             }
  1685.                                             else {
  1686.                                                   if ((pic->ilbm->Bmhd.nPlanes == 6) && (queryinfo.PropertyFlags & DIPF_IS_EXTRAHALFBRITE)) {
  1687.                                                       isEHB = TRUE;
  1688.                                                    AddMessage("Converting EHB to Chunky");
  1689.                                                   }
  1690.                                                   else {
  1691.                                                    AddMessage("Converting ILBM to Chunky");
  1692.                                                   }
  1693.                                             }
  1694.                                         }
  1695.                                     }
  1696.                                     // Convert to chunky
  1697.                                     InitRastPort(&Rp);
  1698.                                     Rp.BitMap = pic->ilbm->brbitmap;
  1699.                                     rx = pic->red;
  1700.                                     gx = pic->green;
  1701.                                     bx = pic->blue;
  1702.                                     // For each line
  1703.                                     for (j = 0;
  1704.                                          j < height;
  1705.                                          ++j) {
  1706.                                         // Convert each column
  1707.                                         // Note: this is very ineffecient in that it uses
  1708.                                         // ReadPixel().
  1709.                                         // But the cost is fairly small compared to the render time
  1710.                                         if (isHAM6) {
  1711.                                               rr = gg = bb = 0;
  1712.                                            for (i = 0;
  1713.                                                     i < width;
  1714.                                                  ++i) {
  1715.                                                penno = ReadPixel(&Rp,i,j);
  1716.                                                switch (penno & 0x30) {
  1717.                                                case 0:
  1718.                                                    *rx++ = rr = pic->ilbm->RGB[penno*4+1];
  1719.                                                    *gx++ = gg = pic->ilbm->RGB[penno*4+2];
  1720.                                                    *bx++ = bb = pic->ilbm->RGB[penno*4+3];
  1721.                                                    break;
  1722.                                                case 0x10:
  1723.                                                    *rx++ = rr;
  1724.                                                    *gx++ = gg;
  1725.                                                    *bx++ = bb = (penno&0xf)|((penno&0xf)<<4);
  1726.                                                    break;
  1727.                                                case 0x20:
  1728.                                                    *rx++ = rr = (penno&0xf)|((penno&0xf)<<4);
  1729.                                                    *gx++ = gg;
  1730.                                                    *bx++ = bb;
  1731.                                                    break;
  1732.                                                case 0x30:
  1733.                                                    *rx++ = rr;
  1734.                                                    *gx++ = gg = (penno&0xf)|((penno&0xf)<<4);
  1735.                                                    *bx++ = bb;
  1736.                                                    break;
  1737.                                                }
  1738.                                             }
  1739.                                           }
  1740.                                           else {
  1741.                                               if (isHAM8) {
  1742.                                                 rr = gg = bb = 0;
  1743.                                                for (i = 0;
  1744.                                                         i < width;
  1745.                                                      ++i) {
  1746.                                                    penno = ReadPixel(&Rp,i,j);
  1747.                                                    switch (penno & 0xc0) {
  1748.                                                    case 0:
  1749.                                                        *rx++ = rr = pic->ilbm->RGB[penno*4+1];
  1750.                                                        *gx++ = gg = pic->ilbm->RGB[penno*4+2];
  1751.                                                        *bx++ = bb = pic->ilbm->RGB[penno*4+3];
  1752.                                                        break;
  1753.                                                    case 0x40:
  1754.                                                        *rx++ = rr;
  1755.                                                        *gx++ = gg;
  1756.                                                        *bx++ = bb = (penno&0x3f)<<2;
  1757.                                                        break;
  1758.                                                    case 0x80:
  1759.                                                        *rx++ = rr = (penno&0x3f)<<2;
  1760.                                                        *gx++ = gg;
  1761.                                                        *bx++ = bb;
  1762.                                                        break;
  1763.                                                    case 0xc0:
  1764.                                                        *rx++ = rr;
  1765.                                                        *gx++ = gg = (penno&0x3f)<<2;
  1766.                                                        *bx++ = bb;
  1767.                                                        break;
  1768.                                                    }
  1769.                                                 }
  1770.                                               }
  1771.                                               else {
  1772.                                                   if (isEHB) {
  1773.                                                    for (i = 0;
  1774.                                                             i < width;
  1775.                                                          ++i) {
  1776.                                                        penno = ReadPixel(&Rp,i,j);
  1777.                                                        EHB = (penno & 0x20)?1:0;
  1778.                                                        penno &= 0x1f;
  1779.                                                        *rx++ = pic->ilbm->RGB[penno*4+1]>>EHB;
  1780.                                                        *gx++ = pic->ilbm->RGB[penno*4+2]>>EHB;
  1781.                                                        *bx++ = pic->ilbm->RGB[penno*4+3]>>EHB;
  1782.                                                     }
  1783.                                                   }
  1784.                                                   else {
  1785.                                                    for (i = 0;
  1786.                                                             i < width;
  1787.                                                          ++i) {
  1788.                                                        penno = ReadPixel(&Rp,i,j);
  1789.                                                        *rx++ = pic->ilbm->RGB[penno*4+1];
  1790.                                                        *gx++ = pic->ilbm->RGB[penno*4+2];
  1791.                                                        *bx++ = pic->ilbm->RGB[penno*4+3];
  1792.                                                     }
  1793.                                                 }
  1794.                                             }
  1795.                                        }
  1796.                                         rx += ((((width+15)>>4)<<4)-width);
  1797.                                         gx += ((((width+15)>>4)<<4)-width);
  1798.                                         bx += ((((width+15)>>4)<<4)-width);
  1799.                                     }
  1800.                                    AddMessage("Cleaning up");
  1801.                                     unloadbrush(pic->ilbm);
  1802.                                     FreeIFF(pic->ilbm->ParseInfo.iff);
  1803.                                     MyFreeMem(pic->ilbm,sizeof(struct ILBMInfo));
  1804.                                   return TRUE;
  1805.                                }
  1806.                             }
  1807.                         }
  1808.                           if (!e) {
  1809.                          e = "Unable to %s";
  1810.                           e1 = "allocate memory for bitmap";
  1811.                           hnum = H_AllocPlanes;
  1812.                        }
  1813.                     }
  1814.                     if (!e) {
  1815.                        e = "Error loading '%s'";
  1816.                        e1 = filename;
  1817.                        hnum = H_Load;
  1818.                    }
  1819.                     unloadbrush(pic->ilbm);
  1820.                     FreeIFF(pic->ilbm->ParseInfo.iff);
  1821.                 }
  1822.                if (!e) {
  1823.                    e = "Unable to %s";
  1824.                     e1 = "AllocIFF";
  1825.                     hnum = H_AllocIFF;
  1826.                 }
  1827.                 MyFreeMem(pic->ilbm,sizeof(struct ILBMInfo));
  1828.             }
  1829.             if (!e) {
  1830.                 e = "Unable to '%s'";
  1831.                    e1 = "AllocMem for ILBMInfo";
  1832.                    hnum = H_AllocILBM;
  1833.            }
  1834.        }
  1835.         if (OkFlag && OpalBase) {
  1836.             // If we still have not loaded the image then try opal.library as a last resort
  1837.            AddMessage("Loading using opal.library");
  1838.             Err = LoadImage24(NULL,filename,VIRTUALSCREEN24|FORCE24);
  1839.             if (Err < OL_ERR_MAXERR) {
  1840.                 switch (Err) {
  1841.                 case OL_ERR_OUTOFMEM:
  1842.                     e = "Failure - Out of memory - loading '%s'";
  1843.                     break;
  1844.                 case OL_ERR_OPENFILE:
  1845.                     e = "Failure - Opening file - loading '%s'";
  1846.                     break;
  1847.                 case OL_ERR_FORMATUNKNOWN:
  1848.                     e = "Failure - Unknown Format - loading '%s'";
  1849.                     break;
  1850.                 case OL_ERR_NOTILBM:
  1851.                     e = "Failure - Not an ILBM file - loading '%s'";
  1852.                     break;
  1853.                 case OL_ERR_FILEREAD:
  1854.                     e = "Failure - Reading file - loading '%s'";
  1855.                     break;
  1856.                 case OL_ERR_BADIFF:
  1857.                     e = "Failure - Bad IFF Format - loading '%s'";
  1858.                     break;
  1859.                 case OL_ERR_CANTCLOSE:
  1860.                     e = "Failure - Can not Close - loading '%s'";
  1861.                     break;
  1862.                 case OL_ERR_BADJPEG:
  1863.                     e = "Failure - Bad JPEG Format - loading '%s'";
  1864.                     break;
  1865.                 case OL_ERR_UNSUPPORTED:
  1866.                     e = "Failure - Unsupported Format - loading '%s'";
  1867.                     break;
  1868.                 case OL_ERR_CTRLC:
  1869.                 case OL_ERR_NOTHUMBNAIL:
  1870.                 case OL_ERR_OPENSCREEN:
  1871.                 case OL_ERR_FILEWRITE:
  1872.                 default:
  1873.                     e = "Failure - Unknown problem - loading '%s'";
  1874.                     break;
  1875.                 }
  1876.                 e1 = filename;
  1877.                 hnum = HE_OpalVision;
  1878.             }
  1879.             else {
  1880.                AddMessage("Allocating Bitmaps");
  1881.                 pic->OScrn = (struct OpalScreen *)Err;
  1882.                 // Allocate chunky bit maps
  1883.                 if ((pic->red = AllocVec(((((pic->OScrn->Width+15)>>4)<<4)*pic->OScrn->Height),MEMF_CLEAR)) &&
  1884.                      (pic->green = AllocVec(((((pic->OScrn->Width+15)>>4)<<4)*pic->OScrn->Height),MEMF_CLEAR)) &&
  1885.                      (pic->blue = AllocVec(((((pic->OScrn->Width+15)>>4)<<4)*pic->OScrn->Height),MEMF_CLEAR)) &&
  1886.                            // Allocate temp bit maps if first image and no OpalVision save
  1887.                            ((OVFormat) || (plane0) ||
  1888.                            ((plane0 = MyAllocVec((((width+15)>>4)<<4),MEMF_CHIP|MEMF_CLEAR)) &&
  1889.                             (plane1 = MyAllocVec((((width+15)>>4)<<4),MEMF_CHIP|MEMF_CLEAR)) &&
  1890.                             (plane2 = MyAllocVec((((width+15)>>4)<<4),MEMF_CHIP|MEMF_CLEAR)) &&
  1891.                             (plane3 = MyAllocVec((((width+15)>>4)<<4),MEMF_CHIP|MEMF_CLEAR)) &&
  1892.                             (plane4 = MyAllocVec((((width+15)>>4)<<4),MEMF_CHIP|MEMF_CLEAR)) &&
  1893.                             (plane5 = MyAllocVec((((width+15)>>4)<<4),MEMF_CHIP|MEMF_CLEAR)) &&
  1894.                             (plane6 = MyAllocVec((((width+15)>>4)<<4),MEMF_CHIP|MEMF_CLEAR)) &&
  1895.                             (plane7 = MyAllocVec((((width+15)>>4)<<4),MEMF_CHIP|MEMF_CLEAR))))) {
  1896.                    AddMessage("Converting Opal to Chunky");
  1897.                      OVtoRGB(pic->OScrn,&(pic->red),0,0,((pic->OScrn->Width+15)>>4)<<4,pic->OScrn->Height);
  1898.                  }
  1899.                  else {
  1900.                  e = "Unable to %s";
  1901.                   e1 = "allocate memory for bitmap";
  1902.                   hnum = H_AllocPlanes;
  1903.                  }
  1904.                 FreeScreen24(pic->OScrn);
  1905.                 if (!e) {
  1906.                     return TRUE;
  1907.                 }
  1908.             }
  1909.         }
  1910.         else {
  1911.             if (!e) {
  1912.                 e = "No opal.library";
  1913.                 hnum = HE_NoOpal;
  1914.             }
  1915.         }
  1916.     }
  1917.     Close24bit(pic);
  1918.     // Display an error message if required
  1919.     if (GUI)
  1920.         Error(e,"Quit",e1,hnum);
  1921.     return(FALSE);
  1922. }
  1923.  
  1924. /* Close an image clearing everything down    */
  1925. void
  1926. Close24bit(struct Picture *pic) {
  1927.     if (pic) {
  1928.         if (pic->rgbonelot) {
  1929.             if (pic->red) {
  1930.                 FreeVec(pic->red);
  1931.             }
  1932.             pic->red = NULL;
  1933.             pic->green = NULL;
  1934.             pic->blue = NULL;
  1935.         }
  1936.         else {
  1937.             if (pic->red) {
  1938.                 FreeVec(pic->red);
  1939.                 pic->red = NULL;
  1940.             }
  1941.             if (pic->green) {
  1942.                 FreeVec(pic->green);
  1943.                 pic->green = NULL;
  1944.             }
  1945.             if (pic->blue) {
  1946.                 FreeVec(pic->blue);
  1947.                 pic->blue = NULL;
  1948.             }
  1949.         }
  1950.     }
  1951. }
  1952.  
  1953. /* Open a file
  1954.  * Returns    : TRUE if ok
  1955.  * filename    : name of file, or NULL for requester
  1956.  */
  1957. BOOL
  1958. MyOpen(char *filename,BOOL JustPoints) {
  1959.     char dirname[257];
  1960.     char rtfilename[108] = "\0";    // reqtools filename from requester
  1961.     char *ifilename=NULL;
  1962.     BOOL ok=TRUE;
  1963.     BPTR fh;
  1964.     char buffer[257];
  1965.     LONG w,h;
  1966.     LONG xx,x1,yy,y1;
  1967.     UWORD                i;                // General index
  1968.  
  1969.     struct FileRequester *filereq;    // For file requester
  1970.     struct rtFileRequester    *rtfilereq;
  1971.     struct MyPoint *MyPoint;
  1972.     // If filename supplied then use it otherwise use file requester
  1973.     if (filename) {
  1974.         ifilename = filename;
  1975.     }
  1976.     else {
  1977.         if (MatchToolValue(MyArgString("REQTOOLS","YES",FALSE),"ALL") &&
  1978.              (rtfilereq = (struct rtFileRequester *)rtAllocRequestA(RT_FILEREQ,NULL))) {
  1979.             if (rtFileRequestA(rtfilereq,rtfilename,"TSMorph-render - Pick project",NULL)) {
  1980.                 strncpy(dirname,rtfilereq->Dir,256);
  1981.                 if (AddPart(dirname,rtfilename,256)) {
  1982.                     ifilename=dirname;
  1983.                 }
  1984.            }
  1985.             rtFreeRequest(rtfilereq);
  1986.         }
  1987.         else {
  1988.             if (filereq = (struct FileRequester *)AllocFileRequest()) {
  1989.                 if (AslRequestTags((APTR) filereq,ASL_Hail,(Tag) "TSMorph-render - Pick project",TAG_DONE)) {
  1990.                     strncpy(dirname,filereq->rf_Dir,256);
  1991.                     if (AddPart(dirname,filereq->rf_File,256)) {
  1992.                         ifilename=dirname;
  1993.                     }
  1994.                 }
  1995.              FreeFileRequest(filereq);
  1996.              }
  1997.         }
  1998.     }
  1999.     // If user did not cancel
  2000.     if (ifilename) {
  2001.         OpenNewArgs(ifilename);        // Load new parameters
  2002.         // Open file and skip the WB displayable names
  2003.         if (fh=Open(ifilename,MODE_OLDFILE)) {
  2004.             FGets(fh,buffer,256);
  2005.             if (JustPoints && strcmp(buffer,"TSMorph 2.0\n")) {
  2006.                 Error("Invalid file format\nLine '%s'","Quit",buffer,H_FileFormat);
  2007.                 ok = FALSE;
  2008.             }
  2009.             else {
  2010.                 if (!JustPoints) {
  2011.                     Pic1.filename[0]=0;
  2012.                     Pic2.filename[0]=0;
  2013.                     // Keep file name
  2014.                     strcpy(MyFileName,ifilename);
  2015.                     strcat(MyFileName,".%03ld");
  2016.                     if (strcmp(buffer,"TSMorph 1.2\n")) {
  2017.                         Error("Assuming version 1.0 file format","OK",NULL,HE_OldFormat);
  2018.                     }
  2019.                     else {
  2020.                         FGets(fh,buffer,256);
  2021.                     }
  2022.                     if (strlen(buffer)) {
  2023.                         buffer[strlen(buffer)-1]=0;
  2024.                     }
  2025.                     strcpy(Pic1.filename,buffer);
  2026.                     FGets(fh,buffer,256);
  2027.                     if (strlen(buffer)) {
  2028.                         buffer[strlen(buffer)-1]=0;
  2029.                     }
  2030.                     strcpy(Pic2.filename,buffer);
  2031.                     // Get file name, set progress and try and load image
  2032.                     FGets(fh,buffer,256);
  2033.                     if (strlen(buffer)) {
  2034.                         buffer[strlen(buffer)-1]=0;
  2035.                     }
  2036.                     if (buffer[0]) {
  2037.                         strcpy(Pic1.filename,buffer);
  2038.                     }
  2039.                     FGets(fh,buffer,256);
  2040.                     if (strlen(buffer)) {
  2041.                         buffer[strlen(buffer)-1]=0;
  2042.                     }
  2043.                     if (buffer[0]) {
  2044.                         strcpy(Pic2.filename,buffer);
  2045.                     }
  2046.                     // Loaded both so get anim name
  2047.                     FGets(fh,AnimName,256);
  2048.                     if (strlen(AnimName)) {
  2049.                         AnimName[strlen(AnimName)-1]=0;
  2050.                     }
  2051.                     // Read and validate general information
  2052.                     FGets(fh,buffer,256);
  2053.                     if (ok && (sscanf(buffer,"w=%ld,h=%ld,Frames=%ld,Single=%ld,Start=%ld",&w,&h,&Frames,&Single,&Start) != 5)) {
  2054.                         Error("Invalid file format\nLine '%s'","Quit",buffer,H_FileFormat);
  2055.                     }
  2056.                     else {
  2057.                         width = w;        // ???????
  2058.                         height = h;    // ???????
  2059.                         if (ok &&
  2060.                             ((w != width) ||
  2061.                              (h != height))) {
  2062.                             Error("Size does not match image\nLine '%s'","Quit",buffer,H_SizeMatch);
  2063.                             ok = FALSE;
  2064.                         }
  2065.                     }
  2066.                 }
  2067.             }
  2068.             if (ok) {
  2069.                 PointCount = 0;
  2070.                 // Read and store all the points
  2071.                 while (ok &&
  2072.                         FGets(fh,buffer,256) &&
  2073.                         (sscanf(buffer,"x=%ld,y=%ld,x1=%ld,y1=%ld",&xx,&yy,&x1,&y1) == 4)) {
  2074.                     if ((xx<0)||(xx>(width-1)) ||
  2075.                          (yy<0)||(yy>(height-1))) {
  2076.                         Error("Point out of range\nLine '%s'","Quit",buffer,H_Range);
  2077.                         ok = FALSE;
  2078.                     }
  2079.                     if (MyPoint = MyAllocMem(sizeof(struct MyPoint),MEMF_CLEAR)) {
  2080.                         MyPoint->x = xx;
  2081.                         MyPoint->y = yy;
  2082.                         MyPoint->x1 = x1;
  2083.                         MyPoint->y1 = y1;
  2084.                         AddTail(&PointList,(struct Node *)MyPoint);
  2085.                         ++PointCount;
  2086.                     }
  2087.                     else {
  2088.                         ok = FALSE;
  2089.                     }
  2090.                 }
  2091.             }
  2092.          Depth = MyArgInt("DEPTH",2,FALSE);
  2093.          Depth = min(Depth,20);
  2094.          Mode = MyArgInt("MODE",0,FALSE);
  2095.          if ((Single == 2) || (Single == 3)) {
  2096.              Mode &= ~MODE_ONCE;                        // Irrelevant for anims
  2097.          }
  2098.             if (ok) {
  2099. //                if ((PointsAlloc = MyAllocVec((max(PointCount,23) + 3)*sizeof(struct MyPoint *) *
  2100.                 if ((PointsAlloc = MyAllocVec((Depth + 4)*sizeof(struct MyPoint *) *        // + 1 = NumPoints
  2101.                                         ((Mode & MODE_ONCE)?width*height:1),MEMF_CLEAR)) &&
  2102.                      (PointsX = MyAllocVec((max(PointCount,23) + 3)*sizeof(struct MyPoint *),MEMF_CLEAR)) &&
  2103.                      (PointsY = MyAllocVec((max(PointCount,23) + 3)*sizeof(struct MyPoint *),MEMF_CLEAR))) {
  2104.                     // Set up x and y order
  2105.                     Points = PointsAlloc;
  2106.                     i = 0;
  2107.                    for (MyPoint = (struct MyPoint *)PointList.lh_Head;
  2108.                           MyPoint->MyNode.mln_Succ;
  2109.                          MyPoint = (struct MyPoint *)MyPoint->MyNode.mln_Succ) {
  2110.                         PointsX[i] = MyPoint;
  2111.                         PointsY[i] = MyPoint;
  2112.                         ++i;
  2113.                     }
  2114.                 }
  2115.                 else {
  2116.                     Error("Out of memory for points","Quit",NULL,H_MemPointsR);
  2117.                     ok = FALSE;
  2118.                 }
  2119.             }
  2120.             // Close file and cleanup
  2121.             if (!Close(fh)) {
  2122.                 if (ok) {
  2123.                     Error("Error closing file '%s'","Quit",filename,H_CloseFile);
  2124.                     ok = FALSE;
  2125.                 }
  2126.             }
  2127.         }
  2128.         else {
  2129.             Error("Error opening file '%s'","Quit",filename,H_Open);
  2130.             ok = FALSE;
  2131.         }
  2132.     }
  2133.     else {
  2134.         ok = FALSE;
  2135.     }
  2136.     return ok;
  2137. }
  2138.  
  2139. /* Delete all the points from the list    */
  2140. void
  2141. DeleteAllPoints(void) {
  2142.     struct MyPoint *MyPoint;
  2143.     // Loops looking at the head every time and deletes it
  2144.     while ((MyPoint =(struct MyPoint *)PointList.lh_Head)->MyNode.mln_Succ) {
  2145.         Remove((struct Node *)MyPoint);
  2146.         MyFreeMem(MyPoint,sizeof(struct MyPoint));
  2147.     }
  2148.     if (PointsAlloc) {
  2149.         MyFreeVec(PointsAlloc);
  2150.         PointsAlloc = NULL;
  2151.     }
  2152.     if (PointsX) {
  2153.         MyFreeVec(PointsX);
  2154.         PointsX = NULL;
  2155.     }
  2156.     if (PointsY) {
  2157.         MyFreeVec(PointsY);
  2158.         PointsY = NULL;
  2159.     }
  2160. }
  2161.  
  2162. // The following is the alogrithm stuff!!!!!
  2163. // and is not particularly well commented!
  2164.  
  2165. /* Given a point, returns the coordinates in the first and last image    */
  2166. static void __regargs
  2167. FindPoint(struct MyPoint *RetPoint,BOOL Everything) {
  2168.     UWORD KeepCount;
  2169.     struct MyPoint *MyPoint,*MyPoint1,*MyPoint2;
  2170.     struct MyPoint **p,**p1,**p2,**p3;
  2171.     UWORD i1,i2;
  2172.     UWORD i,j,k;
  2173.     LONG checkdiff;
  2174.     BOOL flag;
  2175.     UWORD NumPoints;
  2176.     UWORD add;
  2177.     struct Triangle *T;
  2178.     UWORD                MinX,MaxX,CurX;    //    Pointers to X array
  2179.     UWORD                MinY,MaxY,CurY;    //    Pointers to Y array
  2180.     int l;
  2181.  
  2182.     if (!(Mode & MODE_ONCE) || !Everything) {
  2183.         if (Mode & MODE_SEARCH) {
  2184.             p = PointsX;
  2185.             for (i = 0;
  2186.                   i < PointCount;
  2187.                   ++i) {
  2188.                 (*p)->Used = FALSE;
  2189.                 ++p;
  2190.             }
  2191.             flag = FALSE;
  2192.             CurX = PointCount>>1;
  2193.             add = CurX>>1;
  2194.             if (!add) {
  2195.                 add = 1;
  2196.             }
  2197.             p = &(PointsX[CurX]);
  2198.             p2 = &(PointsX[PointCount -1]);
  2199.             while (!flag) {
  2200.                 if ((*p)->Cx == x) {
  2201.                     flag = TRUE;
  2202.                     MinX = CurX-1;
  2203.                     MaxX = CurX+1;
  2204.                 }
  2205.                 else {
  2206.                     if ((*p)->Cx < x) {
  2207.                         ++p;
  2208.                         if ((*p)->Cx > x) {
  2209.                             flag = TRUE;
  2210.                             MinX = CurX;
  2211.                             MaxX = CurX+1;
  2212.                         }
  2213.                         else {
  2214.                             CurX += add;
  2215.                             p += (add-1);
  2216.                             if (p == p2) {
  2217.                                 flag = TRUE;
  2218.                                 MinX = CurX-1;
  2219.                                 MaxX = CurX;
  2220.                             }
  2221.                         }
  2222.                     }
  2223.                     else {
  2224.                         CurX -= add;
  2225.                         if (!CurX) {
  2226.                             flag = TRUE;
  2227.                             MinX = 0;
  2228.                             MaxX = 1;
  2229.                         }
  2230.                         else {
  2231.                             p -= add;
  2232.                         }
  2233.                     }
  2234.                 }
  2235.                 if (!flag) {
  2236.                     add >>= 1;
  2237.                     if (!add) {
  2238.                         add = 1;
  2239.                     }
  2240.                 }
  2241.             }
  2242.             flag = FALSE;
  2243.             CurY = PointCount>>1;
  2244.             add = CurY>>1;
  2245.             if (!add) {
  2246.                 add = 1;
  2247.             }
  2248.             p = &(PointsY[CurY]);
  2249.             p2 = &(PointsY[PointCount -1]);
  2250.             while (!flag) {
  2251.                 if ((*p)->Cy == y) {
  2252.                     flag = TRUE;
  2253.                     MinY = CurY-1;
  2254.                     MaxY = CurY+1;
  2255.                 }
  2256.                 else {
  2257.                     if ((*p)->Cy < y) {
  2258.                         ++p;
  2259.                         if ((*p)->Cy > y) {
  2260.                             flag = TRUE;
  2261.                             MinY = CurY;
  2262.                             MaxY = CurY+1;
  2263.                         }
  2264.                         else {
  2265.                             CurY += add;
  2266.                             p += (add-1);
  2267.                             if (p == p2) {
  2268.                                 flag = TRUE;
  2269.                                 MinY = CurY-1;
  2270.                                 MaxY = CurY;
  2271.                             }
  2272.                         }
  2273.                     }
  2274.                     else {
  2275.                         CurY -= add;
  2276.                         if (!CurY) {
  2277.                             flag = TRUE;
  2278.                             MinY = 0;
  2279.                             MaxY = 1;
  2280.                         }
  2281.                         else {
  2282.                             p -= add;
  2283.                         }
  2284.                     }
  2285.                 }
  2286.                 if (!flag) {
  2287.                     add >>= 1;
  2288.                     if (!add) {
  2289.                         add = 1;
  2290.                     }
  2291.                 }
  2292.             }
  2293.             NumPoints = 0;    // Count of points found so far
  2294.             while ((NumPoints < (Depth+3)) && (NumPoints < PointCount)) {
  2295.                 p = &(PointsX[MinX]);
  2296.                 for (i = MinX;
  2297.                       (i <= MaxX) && (NumPoints < (Depth+3));
  2298.                       ++i,++p) {
  2299.                     if (!(*p)->Used) {
  2300.                         flag = TRUE;
  2301.                         MyPoint = *p;
  2302.                         p1 = &(PointsY[MinY]);
  2303.                         for (j = MinY;
  2304.                               (j <= MaxY) && flag;
  2305.                               ++j,++p1) {
  2306.                             if (MyPoint == *p1) {
  2307.                                 if (x < MyPoint->Cx) {
  2308.                                    MyPoint->xdiff = MyPoint->Cx - x;
  2309.                                }
  2310.                                else {
  2311.                                    MyPoint->xdiff = x - MyPoint->Cx;
  2312.                                }
  2313.                                 if (y < MyPoint->Cy) {
  2314.                                     MyPoint->ydiff = MyPoint->Cy - y;
  2315.                                 }
  2316.                                 else {
  2317.                                     MyPoint->ydiff = y - MyPoint->Cy;
  2318.                                }
  2319.                                MyPoint->Cdiff = MyPoint->xdiff * MyPoint->xdiff +
  2320.                                                       MyPoint->ydiff * MyPoint->ydiff;
  2321.                                 flag = TRUE;
  2322.                                 p2 = Points;
  2323.                                 for (k = 0;
  2324.                                       flag && (k < NumPoints);
  2325.                                       ++k,++p2) {
  2326.                                     if ((*p2)->Cdiff > MyPoint->Cdiff) {
  2327.                                         MyPoint1 = *p2;
  2328.                                         *p2 = MyPoint;
  2329.                                         p3 = p2;
  2330.                                         ++p3;
  2331.                                         for (l = k+1;
  2332.                                               l < NumPoints;
  2333.                                               ++l,++p3) {
  2334.                                             MyPoint2 = *p3;
  2335.                                             *p3 = MyPoint1;
  2336.                                             MyPoint1 = MyPoint2;
  2337.                                         }
  2338.                                         flag = FALSE;
  2339.                                     }
  2340.                                 }
  2341.                                 if (flag) {
  2342.                                     *p2 = MyPoint;
  2343.                                 }
  2344.                                 MyPoint->Used = TRUE;
  2345.                                 NumPoints++;
  2346.                                 flag = FALSE;
  2347.                             }
  2348.                         }
  2349.                     }
  2350.                 }
  2351.                 if (MinX > 0) {
  2352.                     --MinX;
  2353.                 }
  2354.                 if (MinY > 0) {
  2355.                     --MinY;
  2356.                 }
  2357.                 if (MaxX < (PointCount -1)) {
  2358.                     ++MaxX;
  2359.                 }
  2360.                 if (MaxY < (PointCount -1)) {
  2361.                     ++MaxY;
  2362.                 }
  2363.             }
  2364.         }
  2365.         else {
  2366.             NumPoints = Depth+3;
  2367.             p = Points;
  2368.             for (i = 0;
  2369.                   i < NumPoints;
  2370.                   ++i) {
  2371.                 *(p++) = &BigPoint;
  2372.             }
  2373.             // Set up differences
  2374.             p2 = &(Points[Depth+2]);
  2375.             for (MyPoint = (struct MyPoint *)PointList.lh_Head;
  2376.                     MyPoint->MyNode.mln_Succ;
  2377.                    MyPoint = (struct MyPoint *)MyPoint->MyNode.mln_Succ) {
  2378.                if (x < MyPoint->Cx) {
  2379.                    MyPoint->xdiff = MyPoint->Cx - x;
  2380.                }
  2381.                else {
  2382.                    MyPoint->xdiff = x - MyPoint->Cx;
  2383.                }
  2384.                if (y < MyPoint->Cy) {
  2385.                    MyPoint->ydiff = MyPoint->Cy - y;
  2386.                }
  2387.                else {
  2388.                    MyPoint->ydiff = y - MyPoint->Cy;
  2389.                }
  2390.                 if ((MyPoint->xdiff + MyPoint->ydiff) < (*p2)->Cdiff) {
  2391.                    MyPoint->Cdiff = MyPoint->xdiff * MyPoint->xdiff +
  2392.                                           MyPoint->ydiff * MyPoint->ydiff;
  2393.                     flag = TRUE;
  2394.                     p = Points;
  2395.                     for (i = 0;
  2396.                           flag && (i < NumPoints);
  2397.                           ++i,++p) {
  2398.                         if ((*p)->Cdiff > MyPoint->Cdiff) {
  2399.                             MyPoint1 = *p;
  2400.                             *p = MyPoint;
  2401.                             p1 = p;
  2402.                             ++p1;
  2403.                             for (j = i+1;
  2404.                                   j < (Depth + 3);
  2405.                                   ++j,++p1) {
  2406.                                 MyPoint2 = *p1;
  2407.                                 *p1 = MyPoint1;
  2408.                                 MyPoint1 = MyPoint2;
  2409.                             }
  2410.                             flag = FALSE;
  2411.                         }
  2412.                     }
  2413.                 }
  2414.             }
  2415.         }
  2416.         if (!Everything) {
  2417.             Points[Depth+3] = (struct MyPoint *)NumPoints;
  2418.             return;
  2419.         }
  2420.     }
  2421.     else {
  2422.         p = Points;
  2423.         NumPoints = (ULONG)Points[Depth+3];
  2424.         for (i = 0;
  2425.                 ((i < Depth+3) && *p);
  2426.                 ++i,++p) {
  2427.             MyPoint = *p;
  2428.            if (x < MyPoint->Cx) {
  2429.                   MyPoint->xdiff = MyPoint->Cx - x;
  2430.            }
  2431.            else {
  2432.                MyPoint->xdiff = x - MyPoint->Cx;
  2433.            }
  2434.            if (y < MyPoint->Cy) {
  2435.                MyPoint->ydiff = MyPoint->Cy - y;
  2436.            }
  2437.            else {
  2438.                   MyPoint->ydiff = y - MyPoint->Cy;
  2439.               }
  2440.            MyPoint->Cdiff = MyPoint->xdiff * MyPoint->xdiff +
  2441.                                   MyPoint->ydiff * MyPoint->ydiff;
  2442.         }
  2443.     }
  2444.    // If on an actual point then easy
  2445.    if (!Points[0]->Cdiff) {
  2446.        if (AntiAlias) {
  2447.             RetPoint->xd = Points[0]->x;
  2448.             RetPoint->x1d = Points[0]->x1;
  2449.             RetPoint->yd = Points[0]->y;
  2450.             RetPoint->y1d = Points[0]->y1;
  2451.        }
  2452.        else {
  2453.             RetPoint->x = Points[0]->x;
  2454.             RetPoint->x1 = Points[0]->x1;
  2455.             RetPoint->y = Points[0]->y;
  2456.             RetPoint->y1 = Points[0]->y1;
  2457.         }
  2458.         return;
  2459.    }
  2460.    // otherwise try and find a triangle with the other points
  2461.     if (!Depth && !(Mode & (MODE_STAT | MODE_DELAU))) {
  2462.         // Special case, only have 3 points
  2463.         MyPoint = Points[0];
  2464.         MyPoint1 = Points[1];
  2465.         MyPoint2 = Points[2];
  2466.     }
  2467.     else {
  2468.         KeepCount = 0;
  2469.        if (Mode & MODE_DELAU) {
  2470.            MyPoint = Points[0];
  2471.             for (T = (struct Triangle *)MyPoint->TList.lh_Head;
  2472.                     T->TNode.mln_Succ && !KeepCount;
  2473.                    T = (struct Triangle *)T->TNode.mln_Succ) {
  2474.                 i1 = intersect(MyPoint,T->Point1);
  2475.                if (i1 + (i2 = intersect(T->Point1,T->Point2)) < 2) {
  2476.                     if ((i1 + i2 + intersect(T->Point2,MyPoint)) == 1) {
  2477.                         MyPoint1 = T->Point1;
  2478.                         MyPoint2 = T->Point2;
  2479.                         KeepCount = 1;
  2480.                     }
  2481.                 }
  2482.            }
  2483.        }
  2484.        else {
  2485.               if (Mode & MODE_CLOSEST) {
  2486.                 checkdiff = 0x7FFFFFFF;
  2487.                 for (p = Points, i=0;
  2488.                       i<(NumPoints-2);
  2489.                       ++i,++p) {
  2490.                     if ((*p)->Cdiff < checkdiff) {
  2491.                         for (p1 = p+1, j=i;
  2492.                               j<(NumPoints-2);
  2493.                               ++j,++p1) {
  2494.                             if (((*p)->Cdiff + (*p1)->Cdiff) < checkdiff) {
  2495.                                 i1 = intersect(*p,*p1);
  2496.                                 for (p2 = p1+1, k=j;
  2497.                                       k<(NumPoints-2);
  2498.                                       ++k,++p2) {
  2499.                                     // loop thru 3 point combinations finding smallest triangle
  2500.                                     if (((*p)->Cdiff + (*p1)->Cdiff + (*p2)->Cdiff) < checkdiff) {
  2501.                                        if (i1 + (i2 = intersect(*p1,*p2)) < 2) {
  2502.                                            if ((i1 + i2 + intersect(*p2,*p)) == 1) {
  2503.                                                KeepCount = 1;
  2504.                                                MyPoint = *p;
  2505.                                                 MyPoint1 = *p1;
  2506.                                                 MyPoint2 = *p2;
  2507.                                                 checkdiff = (*p)->Cdiff + (*p1)->Cdiff + (*p2)->Cdiff;
  2508.                                             }
  2509.                                         }
  2510.                                     }
  2511.                                }
  2512.                            }
  2513.                        }
  2514.                    }
  2515.                   }
  2516.               }
  2517.               else {
  2518.                 for (p = Points, i=0;
  2519.                       !KeepCount && (i<(NumPoints-2));
  2520.                       ++i,++p) {
  2521.                     for (p1 = p+1, j=i;
  2522.                           !KeepCount && (j<(NumPoints-2));
  2523.                           ++j,++p1) {
  2524.                         i1 = intersect(*p,*p1);
  2525.                         for (p2 = p1+1, k=j;
  2526.                               !KeepCount && (k<(NumPoints-2));
  2527.                               ++k,++p2) {
  2528.                             // loop thru 3 point combinations finding smallest triangle
  2529.                            if (i1 + (i2 = intersect(*p1,*p2)) < 2) {
  2530.                                if ((i1 + i2 + intersect(*p2,*p)) == 1) {
  2531.                                    MyPoint = *p;
  2532.                                    MyPoint1 = *p1;
  2533.                                    MyPoint2 = *p2;
  2534.                                    KeepCount = 1;
  2535.                                }
  2536.                            }
  2537.                        }
  2538.                    }
  2539.                   }
  2540.             }
  2541.         }
  2542.           // If still no triangle then assume stationary
  2543.           if (!KeepCount && (Mode & MODE_STAT)) {
  2544.            if (AntiAlias) {
  2545.                 RetPoint->xd = x;
  2546.                 RetPoint->x1d = x;
  2547.                 RetPoint->yd = y;
  2548.                 RetPoint->y1d = y;
  2549.            }
  2550.            else {
  2551.                   RetPoint->x = x;
  2552.                   RetPoint->y = y;
  2553.                   RetPoint->x1 = x;
  2554.                   RetPoint->y1 = y;
  2555.               }
  2556.               return;
  2557.           }
  2558.           if (!KeepCount) {
  2559.               MyPoint = Points[0];
  2560.               MyPoint1 = Points[1];
  2561.               MyPoint2 = Points[2];
  2562.           }
  2563.     }
  2564.     // Otherwise do the triangle calculation
  2565.     if (Integer) {
  2566.         Triangle_I(RetPoint,MyPoint,MyPoint1,MyPoint2);
  2567.     }
  2568.     else {
  2569.         Triangle(RetPoint,MyPoint,MyPoint1,MyPoint2);
  2570.     }
  2571.    // Check the point is actually on the image
  2572.       if (AntiAlias) {
  2573.        if (RetPoint->xd < 0) {
  2574.            RetPoint->xd = 0;
  2575.        }
  2576.        if (RetPoint->yd < 0) {
  2577.            RetPoint->yd = 0;
  2578.        }
  2579.        if (RetPoint->x1d < 0) {
  2580.            RetPoint->x1d = 0;
  2581.        }
  2582.        if (RetPoint->y1d < 0) {
  2583.            RetPoint->y1d = 0;
  2584.        }
  2585.        if (RetPoint->xd > (width-1)) {
  2586.            RetPoint->xd = width-1;
  2587.        }
  2588.        if (RetPoint->yd > (height-1)) {
  2589.            RetPoint->yd = height-1;
  2590.        }
  2591.        if (RetPoint->x1d > (width-1)) {
  2592.            RetPoint->x1d = width-1;
  2593.        }
  2594.        if (RetPoint->y1d > (height-1)) {
  2595.            RetPoint->y1d = height-1;
  2596.        }
  2597.       }
  2598.       else {
  2599.        if (RetPoint->x < 0) {
  2600.            RetPoint->x = 0;
  2601.        }
  2602.        if (RetPoint->y < 0) {
  2603.            RetPoint->y = 0;
  2604.        }
  2605.        if (RetPoint->x1 < 0) {
  2606.            RetPoint->x1 = 0;
  2607.        }
  2608.        if (RetPoint->y1 < 0) {
  2609.            RetPoint->y1 = 0;
  2610.        }
  2611.        if (RetPoint->x > (width-1)) {
  2612.            RetPoint->x = width-1;
  2613.        }
  2614.        if (RetPoint->y > (height-1)) {
  2615.            RetPoint->y = height-1;
  2616.        }
  2617.        if (RetPoint->x1 > (width-1)) {
  2618.            RetPoint->x1 = width-1;
  2619.        }
  2620.        if (RetPoint->y1 > (height-1)) {
  2621.            RetPoint->y1 = height-1;
  2622.        }
  2623.     }
  2624. }
  2625.  
  2626. /* Used to determine if a point lies on a line,
  2627.  * or in triangle of 3 points
  2628.  */
  2629. static UWORD __regargs
  2630. #ifdef __SASC_60
  2631. __inline
  2632. #endif
  2633. intersect(struct MyPoint *Pointa,struct MyPoint *Pointb) {
  2634. // Draws line between a and b and sees if line from x,0 to x,y intersects
  2635. // returns 1 if intersects, 0 if not intersect
  2636.     if (Pointb->Cx == Pointa->Cx) {                                // Vertical a to b
  2637.         if ((Pointb->x == x) &&                                        // x,y on a to b
  2638.              (((Pointb->Cy > y) && (Pointa->Cy < y)) ||
  2639.               ((Pointb->Cy < y) && (Pointa->Cy > y)))) {
  2640.             return 1;                                                    // Beteen a and b
  2641.         }
  2642.         return 0;
  2643.     }
  2644.     if (((Pointb->Cy > y) && (Pointa->Cy > y)) ||
  2645.          ((Pointb->Cx > x) && (Pointa->Cx > x)) ||
  2646.          ((Pointb->Cx < x) && (Pointa->Cx < x))) {        // Can not possibly cross 
  2647.         return 0;
  2648.     }
  2649.     if ((Pointb->Cy < y) && (Pointa->Cy < y)) {
  2650.         return 1;
  2651.     }
  2652.     if (Pointa->Cx == x) {
  2653.         if (Pointa->Cy > y) {
  2654.             return 0;
  2655.         }
  2656.         return 1;
  2657.     }
  2658.     if (Pointb->Cx == x) {
  2659.         if (Pointb->Cy > y) {
  2660.             return 0;
  2661.         }
  2662.         return 1;
  2663.     }
  2664.     if (Pointb->Cy == Pointa->Cy) {
  2665.         if (Pointa->Cy > y) {
  2666.             return 0;
  2667.         }
  2668.         return 1;
  2669.     }
  2670.     if ((((Pointa->Cx < x)?(x - Pointa->Cx):(Pointa->Cx - x)) * Pointb->Cy +
  2671.           ((Pointb->Cx < x)?(x - Pointb->Cx):(Pointb->Cx - x)) * Pointa->Cy) /
  2672.           ((Pointb->Cx < Pointa->Cx)?(Pointa->Cx - Pointb->Cx):(Pointb->Cx - Pointa->Cx)) > y) {
  2673.         return 0;
  2674.     }
  2675.     return 1;
  2676. }
  2677.  
  2678. /* Given 3 points (a,b,c) with a point (p) in the triangle
  2679.  * determine the coordinates of point (p) on the first and last frame
  2680.  */
  2681. static void __regargs
  2682. #ifdef __SASC_60
  2683. __inline
  2684. #endif
  2685. Triangle(struct MyPoint *p,struct MyPoint *a,struct MyPoint *bb,struct MyPoint *c) {
  2686.     double AB1,AB2,BC1,BC2,CA1,CA2;
  2687.     double AB,BC,CA;
  2688.     double ABBCCA2;
  2689.     double ABCA,BCCA,ABBC;
  2690.     double BC1BC2,AB1AB2,CA1CA2;
  2691.     CalcDiffs(a,bb,&AB1,&AB2,&AB);
  2692.     CalcDiffs(bb,c,&BC1,&BC2,&BC);
  2693.     CalcDiffs(c,a,&CA1,&CA2,&CA);
  2694.     ABBCCA2 = 2 * (AB + BC + CA);
  2695.     ABCA = AB+CA;
  2696.     BCCA = BC+CA;
  2697.     ABBC = AB+BC;
  2698.     BC1BC2 = BC1+BC2;
  2699.     AB1AB2 = AB1+AB2;
  2700.     CA1CA2 = CA1+CA2;
  2701.     if (AntiAlias) {
  2702.         p->xd = x +
  2703.                     (ABCA*(BC1*(c->x - c->Cx) + BC2*(bb->x - bb->Cx)) / BC1BC2 +
  2704.                      BCCA*(AB1*(bb->x - bb->Cx) + AB2*(a->x - a->Cx)) / AB1AB2 +
  2705.                      ABBC*(CA1*(a->x - a->Cx) + CA2*(c->x - c->Cx)) / CA1CA2) /
  2706.                     ABBCCA2;
  2707.         p->x1d = x +
  2708.                     (ABCA*(BC1*(c->x1 - c->Cx) + BC2*(bb->x1 - bb->Cx)) / BC1BC2 +
  2709.                      BCCA*(AB1*(bb->x1 - bb->Cx) + AB2*(a->x1 - a->Cx)) / AB1AB2 +
  2710.                      ABBC*(CA1*(a->x1 - a->Cx) + CA2*(c->x1 - c->Cx)) / CA1CA2) /
  2711.                     ABBCCA2;
  2712.         p->y1d = y +
  2713.                     (ABCA*(BC1*(c->y1 - c->Cy) + BC2*(bb->y1 - bb->Cy)) / BC1BC2 +
  2714.                      BCCA*(AB1*(bb->y1 - bb->Cy) + AB2*(a->y1 - a->Cy)) / AB1AB2 +
  2715.                      ABBC*(CA1*(a->y1 - a->Cy) + CA2*(c->y1 - c->Cy)) / CA1CA2) /
  2716.                     ABBCCA2;
  2717.         p->yd = y +
  2718.                     (ABCA*(BC1*(c->y - c->Cy) + BC2*(bb->y - bb->Cy)) / BC1BC2 +
  2719.                      BCCA*(AB1*(bb->y - bb->Cy) + AB2*(a->y - a->Cy)) / AB1AB2 +
  2720.                      ABBC*(CA1*(a->y - a->Cy) + CA2*(c->y - c->Cy)) / CA1CA2) /
  2721.                     ABBCCA2;
  2722.     }
  2723.     else {
  2724.         p->x = x +
  2725.                     (ABCA*(BC1*(c->x - c->Cx) + BC2*(bb->x - bb->Cx)) / BC1BC2 +
  2726.                      BCCA*(AB1*(bb->x - bb->Cx) + AB2*(a->x - a->Cx)) / AB1AB2 +
  2727.                      ABBC*(CA1*(a->x - a->Cx) + CA2*(c->x - c->Cx)) / CA1CA2) /
  2728.                     ABBCCA2;
  2729.         p->x1 = x +
  2730.                     (ABCA*(BC1*(c->x1 - c->Cx) + BC2*(bb->x1 - bb->Cx)) / BC1BC2 +
  2731.                      BCCA*(AB1*(bb->x1 - bb->Cx) + AB2*(a->x1 - a->Cx)) / AB1AB2 +
  2732.                      ABBC*(CA1*(a->x1 - a->Cx) + CA2*(c->x1 - c->Cx)) / CA1CA2) /
  2733.                     ABBCCA2;
  2734.         p->y1 = y +
  2735.                     (ABCA*(BC1*(c->y1 - c->Cy) + BC2*(bb->y1 - bb->Cy)) / BC1BC2 +
  2736.                      BCCA*(AB1*(bb->y1 - bb->Cy) + AB2*(a->y1 - a->Cy)) / AB1AB2 +
  2737.                      ABBC*(CA1*(a->y1 - a->Cy) + CA2*(c->y1 - c->Cy)) / CA1CA2) /
  2738.                     ABBCCA2;
  2739.         p->y = y +
  2740.                     (ABCA*(BC1*(c->y - c->Cy) + BC2*(bb->y - bb->Cy)) / BC1BC2 +
  2741.                      BCCA*(AB1*(bb->y - bb->Cy) + AB2*(a->y - a->Cy)) / AB1AB2 +
  2742.                      ABBC*(CA1*(a->y - a->Cy) + CA2*(c->y - c->Cy)) / CA1CA2) /
  2743.                     ABBCCA2;
  2744.     }
  2745. }
  2746.  
  2747. /* Caclulate the distances between various points    */
  2748. static void __regargs
  2749. #ifdef __SASC_60
  2750. __inline
  2751. #endif
  2752. CalcDiffs(struct MyPoint *a,struct MyPoint *bb,double *ab1,double *ab2,double *ab) {
  2753.     // ab is length x,y to line ab
  2754.     // ab1 is length x,y to intersect of ab
  2755.     // ab2 is length intersect of ab to bb
  2756.     double m;
  2757.     double c;        // y = mx+c line a to bb
  2758.     double n;
  2759.     double d;        // y = nx+d line perp to y=mx+c thru x,y
  2760.     double xsolve,ysolve;
  2761.     if (a->Cx == bb->Cx) {
  2762.         *ab  = a->xdiff;
  2763.         *ab1 = a->ydiff;
  2764.         *ab2 = bb->ydiff;
  2765.     }
  2766.     else {
  2767.         if (a->Cy == bb->Cy) {
  2768.             *ab1 = a->xdiff;
  2769.             *ab2 = bb->xdiff;
  2770.             *ab  = a->ydiff;
  2771.         }
  2772.         else {
  2773.             m = (double)(bb->Cy - a->Cy) / (double)(bb->Cx - a->Cx);
  2774.             c = bb->Cy - (bb->Cx * m);
  2775.             n = (-1) / m;
  2776.             d = y - n * x;
  2777.             xsolve = (d - c)/(m - n);
  2778.             ysolve = m * xsolve + c;
  2779.             *ab1 = sqrt(((a->Cy - ysolve) * (a->Cy - ysolve) + (a->Cx - xsolve) * (a->Cx - xsolve)));
  2780.             *ab2 = sqrt(((bb->Cy - ysolve) * (bb->Cy - ysolve) + (bb->Cx - xsolve) * (bb->Cx - xsolve)));
  2781.             *ab  = sqrt(((y - ysolve) * (y - ysolve) + (x - xsolve) * (x - xsolve)));
  2782.         }
  2783.     }
  2784. }
  2785.  
  2786. /* Given 3 points (a,b,c) with a point (p) in the triangle
  2787.  * determine the coordinates of point (p) on the first and last frame
  2788.  * Integer version
  2789.  * Completely different to the real version
  2790.  */
  2791. static void __regargs
  2792. #ifdef __SASC_60
  2793. __inline
  2794. #endif
  2795. Triangle_I(struct MyPoint *p,struct MyPoint *a,struct MyPoint *bb,struct MyPoint *c) {
  2796.     LONG ABBCCA2;
  2797.     ABBCCA2 = 2 * (a->Cdiff + bb->Cdiff + c->Cdiff);
  2798.     p->x = x +
  2799.                 ((a->x - a->Cx) * (bb->Cdiff + c->Cdiff) +
  2800.                  (bb->x - bb->Cx) * (a->Cdiff + c->Cdiff) +
  2801.                  (c->x - c->Cx) * (a->Cdiff + bb->Cdiff)) /
  2802.                  ABBCCA2;
  2803.     p->x1 = x +
  2804.                 ((a->x1 - a->Cx) * (bb->Cdiff + c->Cdiff) +
  2805.                  (bb->x1 - bb->Cx) * (a->Cdiff + c->Cdiff) +
  2806.                  (c->x1 - c->Cx) * (a->Cdiff + bb->Cdiff)) /
  2807.                 ABBCCA2;
  2808.     p->y = y +
  2809.                 ((a->y - a->Cy) * (bb->Cdiff + c->Cdiff) +
  2810.                  (bb->y - bb->Cy) * (a->Cdiff + c->Cdiff) +
  2811.                  (c->y - c->Cy) * (a->Cdiff + bb->Cdiff)) /
  2812.                 ABBCCA2;
  2813.     p->y1 = y +
  2814.                 ((a->y1 - a->Cy) * (bb->Cdiff + c->Cdiff) +
  2815.                  (bb->y1 - bb->Cy) * (a->Cdiff + c->Cdiff) +
  2816.                  (c->y1 - c->Cy) * (a->Cdiff + bb->Cdiff)) /
  2817.                 ABBCCA2;
  2818. }
  2819.  
  2820. // Load some image(s) for a frame
  2821. BOOL
  2822. LoadFrames(BOOL points,BOOL image1,BOOL image2) {
  2823.     char buffer[257];
  2824.     BOOL ok=TRUE;
  2825.     UBYTE *er,*eg,*eb;
  2826.     int i;
  2827.     if ((Single == 2) || (Single == 3)) {
  2828.         if (points) {
  2829.             AddMessage("Loading points");
  2830.             DeleteAllPoints();
  2831.             sprintf(buffer,MyFileName,f+Start-1);
  2832.             ok = MyOpen(buffer,TRUE);
  2833.         }
  2834.         sprintf(buffer,Pic1.filename,f+Start-1);
  2835.     }
  2836.     else {
  2837.         strcpy(buffer,Pic1.filename);
  2838.     }
  2839.     if (ok) {
  2840.         if (image1) {
  2841.             ok = Pic1_Open = Load24bit(buffer,&Pic1,TRUE);
  2842.             if (ok && EGS && !EGS_BitMap) {
  2843.                 if (EGS_BitMap = E_AllocBitMap(swidth,1,24,E_PIXELMAP,E_EB_NOTSWAPABLE,NULL)) {
  2844.                     EGS_NewWindow.LeftEdge = 0;
  2845.                     EGS_NewWindow.TopEdge = 20;
  2846.                     EGS_NewWindow.Width = width;
  2847.                     EGS_NewWindow.Height = height;
  2848.                     EGS_NewWindow.MinWidth = 20;
  2849.                     EGS_NewWindow.MinHeight = 20;
  2850.                     EGS_NewWindow.MaxWidth = width;
  2851.                     EGS_NewWindow.MaxHeight = height;
  2852.                     EGS_NewWindow.Screen = NULL;
  2853.                     EGS_NewWindow.Bordef.SysGadgets = EI_WINDOWSIZE | EI_WINDOWFRONT | EI_WINDOWFLIP |
  2854.                                                                  EI_WINDOWARROWL | EI_WINDOWARROWR | EI_WINDOWARROWU | EI_WINDOWARROWD |
  2855.                                                                  EI_WINDOWSCROLLH | EI_WINDOWSCROLLV | EI_WINDOWDRAG;
  2856.                     EGS_NewWindow.FirstGadgets = NULL;
  2857.                     EGS_NewWindow.Title = "TSMorph-render output";
  2858.                     EGS_NewWindow.Flags = EI_GIMMEZEROZERO | EI_SUPER_BITMAP | EI_WINDOWACTIVE | EI_REPORTMOUSE | EI_QUICKSCROLL | EI_RMBTRAP;
  2859.                     EGS_NewWindow.IDCMPFlags = NULL;
  2860.                     EGS_NewWindow.Port = NULL;
  2861.                 // EGS_NewWindow.Colors = ??;
  2862.                     EGS_NewWindow.Menu = NULL;
  2863.                     EGS_NewWindow.Render = NULL;
  2864.                     if (EGS_Win = EI_OpenWindow(&EGS_NewWindow)) {
  2865.                         EI_SetWindowTitles(EGS_Win,(UBYTE *)-1,"TSMorph-render");
  2866.                         E_ActivateEGSScreen();
  2867.                         er = Pic1.red;
  2868.                         eg = Pic1.green;
  2869.                         eb = Pic1.blue;
  2870.                         for (i = 0; i<height; ++i) {
  2871.                             CopyEGS(i,&er,&eg,&eb);
  2872.                         }
  2873.                     }
  2874.                 }
  2875.             }
  2876.         }
  2877.         if (image2 && ok && ((Single == 0) || (Single == 2))) {
  2878.             // If we loaded the 1st image then try the second
  2879.             if (Single == 2) {
  2880.                 sprintf(buffer,Pic2.filename,f+Start-1);
  2881.             }
  2882.             else {
  2883.                 strcpy(buffer,Pic2.filename);
  2884.             }
  2885.             ok = Pic2_Open = Load24bit(buffer,&Pic2,TRUE);
  2886.         }
  2887.     }
  2888.     return ok;
  2889. }
  2890.  
  2891. void
  2892. CopyEGS(int line, UBYTE **er,UBYTE **eg,UBYTE **eb) {
  2893.     int j;
  2894.     UBYTE *plane;
  2895.     plane = EGS_BitMap->Typekey.PixelMap.Planes.Dest;
  2896.     for (j = 0; j<swidth; ++j) {
  2897.         *plane++ = *((*er)++);
  2898.         *plane++ = *((*eg)++);
  2899.         *plane++ = *((*eb)++);
  2900.         ++plane;
  2901.     }
  2902.     EG_CopyBitMapRastPort(EGS_BitMap,EGS_Win->RPort,0,0,width,1,0,line);
  2903. }
  2904.  
  2905. int
  2906. cmpX(struct MyPoint **A,struct MyPoint **B) {
  2907.     if ((*A)->Cx < (*B)->Cx) {
  2908.         return -1;
  2909.     }
  2910.     if ((*A)->Cx > (*B)->Cx) {
  2911.         return 1;
  2912.     }
  2913.     return 0;
  2914. }
  2915.  
  2916. int
  2917. cmpY(struct MyPoint **A,struct MyPoint **B) {
  2918.     if ((*A)->Cy < (*B)->Cy) {
  2919.         return -1;
  2920.     }
  2921.     if ((*A)->Cy > (*B)->Cy) {
  2922.         return 1;
  2923.     }
  2924.     return 0;
  2925. }
  2926.  
  2927. int
  2928. cmpDiff(struct MyPoint **A,struct MyPoint **B) {
  2929.     if ((*A)->Cdiff < (*B)->Cdiff) {
  2930.         return -1;
  2931.     }
  2932.     if ((*A)->Cdiff > (*B)->Cdiff) {
  2933.         return 1;
  2934.     }
  2935.     return 0;
  2936. }
  2937.  
  2938. /* nsort() was written by Dave Watson and uses the algorithm described in -
  2939.  *    Watson, D.F., 1981, Computing the n-dimensional Delaunay tessellation with 
  2940.  *          application to Voronoi polytopes: The Computer J., 24(2), p. 167-172. 
  2941.  */
  2942.  
  2943. #define SQ(x)                (x) * (x)
  2944. #define BIGNUM                1E37
  2945. #define EPSILON         0.00001
  2946. #define TSIZE                75                  /* temporary storage size factor*/
  2947. #define  XRANGE          10.0                /* factor (>=1) for radius of control points */
  2948. #define FILENAMELEN     32
  2949. #define AND             &&
  2950. #define OR              ||
  2951. #define EQ              ==
  2952. #define NE              !=
  2953.  
  2954. BOOL
  2955. GenerateTriangles(void) {
  2956.     BOOL ok = FALSE;
  2957.     BOOL flag = TRUE;
  2958.    double xx, bgs, **mxy, **wrk, **pts, **ccr;
  2959.    int i0, i1, i2, i3, i4, i5, i6, i7, i8, i9, i11, ii[3], 
  2960.        dm, nts, tsz, *id, **tmp, **a3s;
  2961.  
  2962.    if (mxy = DoubleMatrix(2, 2)) {
  2963.        for (i0=0; i0<2; i0++) {
  2964.               mxy[0][i0] = - (mxy[1][i0] = BIGNUM);
  2965.        }
  2966.        if (wrk = DoubleMatrix(2, 3)) {
  2967.            for (i0=0; i0<2; i0++) {
  2968.                for (i1=0; i1<3; i1++) {
  2969.                    wrk[i0][i1] = -XRANGE;
  2970.                }
  2971.            }
  2972.            for (i0=0; i0<2; i0++) {
  2973.                wrk[i0][i0] = XRANGE * (3 * 2 - 1);
  2974.            }
  2975.             if (pts = DoubleMatrix(PointCount + 3, 2)) {
  2976.                 for (i0=0; i0<PointCount; i0++) {
  2977.                    NewList(&(PointsX[i0]->TList));
  2978.                     pts[i0][0] = PointsX[i0]->Cx;
  2979.                     pts[i0][1] = PointsX[i0]->Cy;
  2980.                     for (i1=0; i1<2; i1++) {
  2981.                         if (mxy[0][i1] < pts[i0][i1]) {
  2982.                             mxy[0][i1] = pts[i0][i1];
  2983.                         }
  2984.                         if (mxy[1][i1] > pts[i0][i1]) {
  2985.                             mxy[1][i1] = pts[i0][i1];
  2986.                         }
  2987.                     }
  2988.                 }
  2989.                 for (bgs=0, i0=0; i0<2; i0++) {
  2990.                     mxy[0][i0] -= mxy[1][i0];
  2991.                   if (bgs < mxy[0][i0]) {
  2992.                       bgs = mxy[0][i0];
  2993.                   }
  2994.                }
  2995.                 bgs *= EPSILON;
  2996.                for (i0=0; i0<PointCount; i0++) {
  2997.                    for (i1=0; i1<2; i1++) {
  2998.                         pts[i0][i1] += bgs * (0.5 - (double)rand() / 0x7fffffff);
  2999.                     }
  3000.                 }
  3001.                 for (i0=0; i0<3; i0++) {
  3002.                     for (i1=0; i1<2; i1++) {
  3003.                         pts[PointCount+i0][i1] = mxy[1][i1] + wrk[i1][i0] * mxy[0][i1];
  3004.                     }
  3005.                 }
  3006.                for (i1=1, i0=2; i0<3; i0++) {
  3007.                    i1 *= i0;
  3008.                }
  3009.                tsz = TSIZE * i1;
  3010.                if (tmp = IntMatrix(tsz + 1, 2)) {
  3011.                    i1 *= (PointCount + i1);
  3012.                    if (id = IntVect(i1)) {
  3013.                        for (i0=0; i0<i1; i0++) {
  3014.                            id[i0] = i0;
  3015.                        }
  3016.                         if (a3s = IntMatrix(i1,3)) {
  3017.                               if (ccr = DoubleMatrix(i1,3)) {
  3018.                                   for (a3s[0][0]=PointCount, i0=1; i0<3; i0++) {
  3019.                                       a3s[0][i0] = a3s[0][i0-1] + 1;
  3020.                                   }
  3021.                                 for (ccr[0][2]=BIGNUM, i0=0; i0<2; i0++) {
  3022.                                     ccr[0][i0] = 0;
  3023.                                 }
  3024.                                nts = i4 = 1;
  3025.                                dm = 2 - 1;
  3026.                                for (i0=0; i0<PointCount; i0++) {
  3027.                                   i1 = i7 = -1;
  3028.                                   i9 = 0;
  3029.                                   for (i11=0; i11<nts; i11++) {
  3030.                                      i1++;
  3031.                                      while (a3s[i1][0] < 0) { 
  3032.                                          i1++;
  3033.                                      }
  3034.                                      xx = ccr[i1][2];
  3035.                                      for (i2=0; i2<2; i2++) {
  3036.                                         xx -= SQ(pts[i0][i2] - ccr[i1][i2]);
  3037.                                            if (xx<0) {
  3038.                                                goto Corner3;
  3039.                                            }
  3040.                                      }
  3041.                                      i9--;
  3042.                                         i4--;
  3043.                                         id[i4] = i1;
  3044.                                         for (i2=0; i2<3; i2++) {
  3045.                                            ii[0] = 0;
  3046.                                         if (ii[0] EQ i2) {
  3047.                                             ii[0]++;
  3048.                                         }
  3049.                                         for (i3=1; i3<2; i3++) {
  3050.                                            ii[i3] = ii[i3-1] + 1;
  3051.                                            if (ii[i3] EQ i2) {
  3052.                                                ii[i3]++;
  3053.                                            }
  3054.                                         }
  3055.                                         if (i7>dm) {
  3056.                                                i8 = i7;
  3057.                                                 for (i3=0; i3<=i8; i3++) {
  3058.                                                    for (i5=0; i5<2; i5++) {
  3059.                                                        if (a3s[i1][ii[i5]] NE tmp[i3][i5]) {
  3060.                                                            goto Corner1;
  3061.                                                        }
  3062.                                                    }
  3063.                                                     for (i6=0; i6<2; i6++) {
  3064.                                                         tmp[i3][i6] = tmp[i8][i6];
  3065.                                                     }
  3066.                                                     i7--;
  3067.                                                     goto Corner2;
  3068. Corner1:;
  3069.                                                 }
  3070.                                             }
  3071.                                             if (++i7 > tsz) {
  3072.                                                 goto returnfail;
  3073.                                             }
  3074.                                             for (i3=0; i3<2; i3++) {
  3075.                                                 tmp[i7][i3] = a3s[i1][ii[i3]];
  3076.                                             }
  3077. Corner2:;
  3078.                                         }
  3079.                                       a3s[i1][0] = -1;
  3080. Corner3:;
  3081.                                    }
  3082.                                    for (i1=0; i1<=i7; i1++) {
  3083.                                       for (i2=0; i2<2; i2++) {
  3084.                                            for (wrk[i2][2]=0, i3=0; i3<2; i3++) {
  3085.                                             wrk[i2][i3] = pts[tmp[i1][i2]][i3] - pts[i0][i3];
  3086.                                                wrk[i2][2] += wrk[i2][i3] * (pts[tmp[i1][i2]][i3] + pts[i0][i3]) / 2;
  3087.                                             }
  3088.                                         }
  3089.                                         xx = wrk[0][0] * wrk[1][1] - wrk[1][0] * wrk[0][1];
  3090.                                         ccr[id[i4]][0] = (wrk[0][2] * wrk[1][1] - wrk[1][2] * wrk[0][1]) / xx;
  3091.                                         ccr[id[i4]][1] = (wrk[0][0] * wrk[1][2] - wrk[1][0] * wrk[0][2]) / xx;
  3092.                                       for (ccr[id[i4]][2]=0, i2=0; i2<2; i2++) {
  3093.                                             ccr[id[i4]][2] += SQ(pts[i0][i2] - ccr[id[i4]][i2]);
  3094.                                            a3s[id[i4]][i2] = tmp[i1][i2];
  3095.                                       }
  3096.                                         a3s[id[i4]][2] = i0;
  3097.                                         i4++;
  3098.                                       i9++;
  3099.                                    }
  3100.                                    nts += i9;
  3101.                                 }
  3102.                                 i0 = -1;
  3103.                                 for (i11=0; flag && (i11<nts); i11++) {
  3104.                                     i0++;
  3105.                                    while (a3s[i0][0] < 0) {
  3106.                                        i0++;
  3107.                                    }
  3108.                                    if (a3s[i0][0] < PointCount) {
  3109.                                         for (i1=0; i1<2; i1++) for (i2=0; i2<2; i2++)  {
  3110.                                           wrk[i1][i2] = pts[a3s[i0][i1]][i2] - pts[a3s[i0][2]][i2];
  3111.                                       }
  3112.                                       xx = wrk[0][0] * wrk[1][1] - wrk[0][1] * wrk[1][0];
  3113.                                       if (fabs(xx) > EPSILON) {
  3114.                                             flag = AddTri(a3s[i0][0],a3s[i0][2],a3s[i0][1]);
  3115.                                       }
  3116.                                    }
  3117.                                 }
  3118.                                ok = flag;
  3119. returnfail:
  3120.                                 FreeMatrixd(ccr);
  3121.                             }
  3122.                             FreeMatrixi(a3s);
  3123.                         }
  3124.                         MyFreeVecti(id);
  3125.                     }
  3126.                    FreeMatrixi(tmp);
  3127.                 }
  3128.                 FreeMatrixd(pts);
  3129.             }
  3130.             FreeMatrixd(wrk);
  3131.         }
  3132.         FreeMatrixd(mxy);
  3133.     }
  3134.     return ok;
  3135. }
  3136.     
  3137. int
  3138. *IntVect(int ncols) {  
  3139.     return (int *) MyAllocVec(ncols * sizeof(int),0);
  3140. }
  3141.  
  3142. void
  3143. MyFreeVecti(int *vectptr) {
  3144.     if (vectptr) {
  3145.         MyFreeVec(vectptr);
  3146.     }
  3147. }
  3148.  
  3149. int
  3150. **IntMatrix(int nrows, int ncols) {
  3151.    int i0;
  3152.    int **matptr;
  3153.    if (nrows<2) nrows = 2;
  3154.    if (ncols<2) ncols = 2;
  3155.    if ((matptr = (int **) MyAllocVec(nrows * sizeof(int *),0)) EQ NULL) {
  3156.        return NULL;
  3157.    }
  3158.    if ((matptr[0] = (int *) MyAllocVec(nrows * ncols * sizeof(int),0)) EQ NULL) {
  3159.        MyFreeVec(matptr);
  3160.        return NULL;
  3161.    }
  3162.    for (i0=1; i0<nrows; i0++) {
  3163.        matptr[i0] = matptr[0] + i0 * ncols;
  3164.    }
  3165.    return matptr;
  3166. }
  3167.  
  3168. void
  3169. FreeMatrixi(int **matptr) {  
  3170.     if (matptr) {
  3171.         if (matptr[0]) {
  3172.             MyFreeVec(matptr[0]);
  3173.         }
  3174.         MyFreeVec(matptr);
  3175.     }
  3176. }
  3177.  
  3178. double
  3179. **DoubleMatrix(int nrows, int ncols) {
  3180.    int i0;
  3181.    double **matptr;
  3182.    if (nrows<2) nrows = 2;
  3183.    if (ncols<2) ncols = 2;
  3184.    if ((matptr = (double **) MyAllocVec(nrows * sizeof(double *),0)) EQ NULL) {
  3185.        return NULL;
  3186.    }
  3187.    if ((matptr[0] = (double *) MyAllocVec(nrows * ncols * sizeof(double),0)) EQ NULL) {
  3188.        MyFreeVec(matptr);
  3189.        return NULL;
  3190.    }
  3191.    for (i0=1; i0<nrows; i0++) {
  3192.        matptr[i0] = matptr[0] + i0 * ncols;
  3193.     }
  3194.    return matptr;
  3195. }
  3196.  
  3197. void
  3198. FreeMatrixd(double **matptr) {
  3199.     if (matptr) {
  3200.         if (matptr[0]) {
  3201.            MyFreeVec(matptr[0]);
  3202.         }
  3203.         MyFreeVec(matptr);
  3204.     }
  3205. }
  3206.  
  3207. void
  3208. FreeTriangles(void) {
  3209.     int i;
  3210.     struct Triangle *T;
  3211.     struct MyPoint *P;
  3212.     for (i=0; i<PointCount; i++) {
  3213.         P = PointsX[i];
  3214.         while ((T =(struct Triangle *)(P->TList.lh_Head))->TNode.mln_Succ) {
  3215.             Remove((struct Node *)T);
  3216.             MyFreeVec(T);
  3217.         }
  3218.     }
  3219. }
  3220.  
  3221. BOOL AddTri(int aa,int bb,int cc) {
  3222.     struct Triangle *T1,*T2=NULL,*T3;
  3223.     if ((T1 = (struct Triangle *)MyAllocVec(sizeof (struct Triangle),0)) &&
  3224.          (T2 = (struct Triangle *)MyAllocVec(sizeof (struct Triangle),0)) &&
  3225.          (T3 = (struct Triangle *)MyAllocVec(sizeof (struct Triangle),0))) {
  3226.         T1->Point1 = PointsX[bb];
  3227.         T1->Point2 = PointsX[cc];
  3228.         AddTail(&(PointsX[aa]->TList),(struct Node *)T1);
  3229.         T2->Point1 = PointsX[aa];
  3230.         T2->Point2 = PointsX[cc];
  3231.         AddTail(&(PointsX[bb]->TList),(struct Node *)T2);
  3232.         T3->Point1 = PointsX[aa];
  3233.         T3->Point2 = PointsX[bb];
  3234.         AddTail(&(PointsX[cc]->TList),(struct Node *)T3);
  3235.         return TRUE;
  3236.     }
  3237.     if (T1) {
  3238.         MyFreeVec(T1);
  3239.     }
  3240.     if (T2) {
  3241.         MyFreeVec(T2);
  3242.     }
  3243.     return FALSE;
  3244. }
  3245.  
  3246. static UWORD top = 0;
  3247.  
  3248. // add a message to the progress list
  3249. void
  3250. AddMessage(UBYTE *message) {
  3251.     struct Node *node;
  3252.     if ((node = (struct Node *)Mymalloc(sizeof(struct Node))) &&
  3253.          (node->ln_Name = Mystrdup(message))) {;
  3254.         GT_SetGadgetAttrs(ProgressGadgets[GDX_Info],ProgressWnd,NULL,
  3255.                              GTLV_Labels, ~0,
  3256.                             TAG_END);
  3257.         AddTail(&InfoList,node);
  3258.         GT_SetGadgetAttrs(ProgressGadgets[GDX_Info],ProgressWnd,NULL,
  3259.                              GTLV_Labels, &InfoList,
  3260.                              GTLV_Top, top,
  3261.                             TAG_END);
  3262.           top++;
  3263.     }
  3264. }
  3265.