1 /* Quat - A 3D fractal generation program */
2 /* Copyright (C) 1997-2000 Dirk Meyer */
3 /* (email: dirk.meyer@studserv.uni-stuttgart.de) */
4 /* mail:  Dirk Meyer */
5 /*        Marbacher Weg 29 */
6 /*        D-71334 Waiblingen */
7 /*        Germany */
8 /* */
9 /* This program is free software; you can redistribute it and/or */
10 /* modify it under the terms of the GNU General Public License */
11 /* as published by the Free Software Foundation; either version 2 */
12 /* of the License, or (at your option) any later version. */
13 /* */
14 /* This program is distributed in the hope that it will be useful, */
15 /* but WITHOUT ANY WARRANTY; without even the implied warranty of */
16 /* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the */
17 /* GNU General Public License for more details. */
18 /* */
19 /* You should have received a copy of the GNU General Public License */
20 /* along with this program; if not, write to the Free Software */
21 /* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA. */
22 
23 #ifdef HAVE_CONFIG_H
24 #include <config.h>
25 #endif
26 
27 #include <string.h>
28 #include <stdio.h>
29 #include <stdlib.h>
30 #include <math.h>  /* fmod */
31 #include <time.h> /* time */
32 #include <ctype.h> /* tolower */
33 #include "quat.h"  /* includes also common.h */
34 #include "iter.h"
35 #include "files.h"
36 #include "colors.h"
37 #include "calculat.h"
38 
39 #ifndef GUI
40     unsigned char *TEXTVER_zbuf;
41 #endif
42 
43 char orbite(double *a, const double *b);
44 char orbitj(double *a, const double *b);
45 char orbitk(double *a, const double *b);
46 char orbitl(double *a, const double *b);
47 int PrepareKeywords(char *colorscheme, struct frac_struct *f, struct view_struct *v);
48 int CopyIDAT(int copy, /*struct disppal_struct *disppal, struct vidinfo_struct *vidinfo,*/
49    struct png_internal_struct *i, struct png_internal_struct *i2,
50    unsigned char *Buf, int ystart, int zflag, int zres);
51 int InitGraphics(char *Error, struct view_struct *view, struct realpal_struct *realpal,
52    int ready, struct vidinfo_struct *vidinfo, struct disppal_struct *disppal,
53    int *xadd, int *yadd, int zbufflag);
54 int AllocBufs(struct view_struct *v, int zflag, int pal, float **CBuf, float **BBuf,
55    float **LBufR, float **LBufL, unsigned char **line, unsigned char **line2,
56    unsigned char **line3);
57 int FreeBufs(float **a, float **g, float **b, float **c, unsigned char **d,
58    unsigned char **e, unsigned char **f);
59 int LBuf_ZBuf(struct view_struct *v, float *LBuf, unsigned char *line, long ii,
60    long imax, long aa_line, int offs);
61 int CalculateFractal(char *Error, char *pngfile, FILE **png,/* struct png_info_struct *png_info, */
62    struct png_internal_struct *png_internal, int zflag, int *xstart, int *ystart,
63    /*int xadd, int yadd,*/ int no, struct basestruct *rbase, struct basestruct *srbase,
64    struct basestruct *lbase, struct basestruct *slbase, struct frac_struct *f,
65    struct view_struct *v, struct realpal_struct *realpal,/* char *colscheme,*/ double *cutbuf,
66    struct vidinfo_struct *vidinfo, struct disppal_struct *disppal);
67 int CalculateINI(const char *inifile, const char *pngfile, char *Error, int zflag);
68 int CalculatePNG(const char *pngfile1, const char *pngfile2, char *Error, const char *ini, int zflag);
69 
70 struct progtype prog;
71 
72 struct parameter_struct Parameters[64];
73 struct keyword_struct Keywords[25];
74 time_t calc_time;
75 
76 point *orbit = 0;
77 
78 /* This variables (functions) have to be declared in the special version files ! */
79 /* use an extern statement like "extern VER_Done Done;" */
80 VER_ReturnVideoInfo ReturnVideoInfo = DUMMY_ReturnVideoInfo;
81 VER_SetColors SetColors = DUMMY_SetColors;
82 VER_Initialize Initialize = DUMMY_Initialize;
83 VER_Done Done = DUMMY_Done;
84 VER_update_bitmap update_bitmap = DUMMY_update_bitmap;
85 VER_getline QU_getline = DUMMY_getline;
86 VER_putline putline = DUMMY_putline;
87 VER_check_event check_event = DUMMY_check_event;
88 VER_Change_Name Change_Name = DUMMY_Change_Name;
89 VER_Debug Debug = DUMMY_Debug;
90 VER_eol eol = DUMMY_eol;
91 VER_update_parameters update_parameters = DUMMY_update_parameters;
92 
93 char slash = '/';
94 
95 /* DUMMY functions which do nothing / Available to all versions */
DUMMY_ReturnVideoInfo(struct vidinfo_struct * v)96 int DUMMY_ReturnVideoInfo(struct vidinfo_struct* v)
97 { return(0); }
DUMMY_SetColors(struct disppal_struct * d)98 int DUMMY_SetColors(struct disppal_struct* d)
99 { return(0); }
DUMMY_Initialize(int x,int y,char * c)100 int DUMMY_Initialize(int x, int y, char* c)
101 { return(0); }
DUMMY_Done(void)102 int DUMMY_Done(void)
103 { return(0); }
DUMMY_update_bitmap(long a,long b,long c,int d,unsigned char * e,int f)104 int DUMMY_update_bitmap(long a, long b, long c, int d, unsigned char *e, int f)
105 { return(0); }
DUMMY_getline(unsigned char * a,int b,long c,int d)106 int DUMMY_getline(unsigned char *a, int b, long c, int d)
107 { return(0); }
DUMMY_putline(long a,long b,long c,int d,unsigned char * e,int f)108 int DUMMY_putline(long a, long b, long c, int d, unsigned char* e, int f)
109 { return(0); }
DUMMY_check_event(void)110 int DUMMY_check_event(void)
111 { return(0); }
DUMMY_Change_Name(char * a)112 int DUMMY_Change_Name(char* a)
113 { return(0); }
DUMMY_Debug(char * a)114 void DUMMY_Debug(char* a)
115 { return; }
DUMMY_eol(int a)116 void DUMMY_eol(int a)
117 { return; }
DUMMY_update_parameters(struct frac_struct * a,struct view_struct * b,struct realpal_struct * c,char * d,double * e)118 void DUMMY_update_parameters(struct frac_struct* a, struct view_struct* b,
119    struct realpal_struct* c, char* d, double* e)
120 { return;  }
121 
SetSlash(char s)122 void SetSlash(char s)
123 {
124    slash = s;
125    return;
126 }
127 
ConvertPath(char * Path)128 void ConvertPath(char *Path)
129 {
130    size_t i;
131    for (i=0; i<strlen(Path); i++)
132       if (Path[i] == '/' || Path[i] == '\\') Path[i] = slash;
133 }
134 
PrepareKeywords(char * colorscheme,struct frac_struct * f,struct view_struct * v)135 int PrepareKeywords(char *colorscheme, struct frac_struct *f, struct view_struct *v)
136 {
137    int i, j;
138    static char s[20];
139 
140    /* The parameters for the keywords */
141    /* No semicolon behind STDDOUBLE, STDINT, they're macros */
142    Parameters[0].type = T_STRING;
143    Parameters[0].mem = VVPTR(*colorscheme);
144    Parameters[0].max = 250;
145 
146    /* 3 * resolution */
147    for (i=1; i<4; i++)
148    {
149       Parameters[i].type = T_INTEGER;
150       Parameters[i].min = 1;
151       Parameters[i].max = 100000;   /* old : 32767, 8192, 2048 */
152    }
153    Parameters[1].mem = VVPTR(v->xres);
154    Parameters[2].mem = VVPTR(v->yres);
155    Parameters[3].mem = VVPTR(v->zres);
156 
157    /* CE, CJ, CK, CL, bailout, lvalue */
158    for (i=4; i<10; i++)
159       STDDOUBLE(Parameters, i)
160    Parameters[4].mem = VVPTR(f->c[0]);
161    Parameters[5].mem = VVPTR(f->c[1]);
162    Parameters[6].mem = VVPTR(f->c[2]);
163    Parameters[7].mem = VVPTR(f->c[3]);
164    Parameters[8].mem = VVPTR(f->bailout);
165    Parameters[8].min = 0.1; Parameters[8].max = 1E20;
166    Parameters[9].mem = VVPTR(f->lvalue);
167 
168    /* maxiter, formula */
169    for (i=10; i<12; i++)
170       STDINT(Parameters, i)
171    Parameters[10].mem = VVPTR(f->maxiter);
172    Parameters[10].min = 2;
173    Parameters[11].mem = VVPTR(f->formula);
174    Parameters[11].max = 4;
175 
176    /* 3 * viewpoint, 3 * up, 3 * light, 2 * mov, LXR */
177    for (i=12; i<24; i++)
178       STDDOUBLE(Parameters, i)
179    for (i=0; i<3; i++)
180    {
181       Parameters[12+i].mem = VVPTR(v->s[i]);
182       Parameters[15+i].mem = VVPTR(v->up[i]);
183       Parameters[18+i].mem = VVPTR(v->light[i]);
184    }
185    Parameters[21].mem = VVPTR(v->Mov[0]);
186    Parameters[22].mem = VVPTR(v->Mov[1]);
187    Parameters[23].mem = VVPTR(v->LXR);
188    Parameters[23].min = 0;
189 
190    /* phongmax */
191    Parameters[24].type = T_DOUBLE;
192    Parameters[24].min = 0.0;
193    Parameters[24].max = 1.0;
194    Parameters[24].mem = VVPTR(v->phongmax);
195    /* phongsharp */
196    STDDOUBLE(Parameters, 25)
197    Parameters[25].mem = VVPTR(v->phongsharp);
198    /* ambient */
199    Parameters[26].type = T_DOUBLE;
200    Parameters[26].min = 0.0;
201    Parameters[26].max = 1.0;
202    Parameters[26].mem = VVPTR(v->ambient);
203    /* antialiasing */
204    Parameters[27].type = T_INTEGER;
205    Parameters[27].min = 1;
206    Parameters[27].max = 5;
207    Parameters[27].mem = VVPTR(v->antialiasing);
208 
209    for (i=28; i<39; i++)
210    {
211       Parameters[i].type = T_DOUBLE;
212       Parameters[i].min = 0;
213       Parameters[i].max = 1000;
214    }
215 
216    Parameters[28].max = 1000000;
217    Parameters[32].max = 1000000;
218 
219    for (i=39; i<45; i++)
220       STDDOUBLE(Parameters, i);
221 
222    Parameters[46].type = T_STRING;
223    Parameters[46].mem = NULL;  /* Set before parsing a line by parsing function ! */
224    Parameters[46].max = 250;
225 
226    Parameters[47].type = T_DOUBLE;
227    Parameters[47].min = 0;
228    Parameters[47].max = 1000000;
229    Parameters[47].mem = VVPTR(v->interocular);
230 
231    for (i=48; i<64; i++)
232       STDDOUBLE(Parameters, i)
233 	for (j=0; j<4; ++j) for (i = 0; i<4; ++i)
234 	   Parameters[48+j*4+i].mem = VVPTR(f->p[j][i]);
235 
236    /* Now the keywords for parsing */
237    for (i=0; i<19; i++) Keywords[i].which_buf = NO_BUF;
238    Keywords[0].name = "colorscheme";
239    Keywords[0].paramcount = 1;
240    Keywords[0].param = &Parameters[0];
241    Keywords[1].name = "resolution";
242    Keywords[1].paramcount = 3;
243    Keywords[1].param = &Parameters[1];
244 
245    Keywords[2].name = "c";
246    Keywords[2].paramcount = 4;
247    Keywords[2].param = &Parameters[4];
248 
249    Keywords[3].name = "bailout";
250    Keywords[3].paramcount = 1;
251    Keywords[3].param = &Parameters[8];
252 
253    Keywords[4].name = "lvalue";
254    Keywords[4].paramcount = 1;
255    Keywords[4].param = &Parameters[9];
256 
257    Keywords[5].name = "maxiter";
258    Keywords[5].paramcount = 1;
259    Keywords[5].param = &Parameters[10];
260 
261    Keywords[6].name = "formula";
262    Keywords[6].paramcount = 1;
263    Keywords[6].param = &Parameters[11];
264 
265    Keywords[7].name = "viewpoint";
266    Keywords[7].paramcount = 3;
267    Keywords[7].param = &Parameters[12];
268 
269    Keywords[8].name = "up";
270    Keywords[8].paramcount = 3;
271    Keywords[8].param = &Parameters[15];
272 
273    Keywords[9].name = "light";
274    Keywords[9].paramcount = 3;
275    Keywords[9].param = &Parameters[18];
276 
277    Keywords[10].name = "move";
278    Keywords[10].paramcount = 2;
279    Keywords[10].param = &Parameters[21];
280 
281    Keywords[11].name = "lxr";
282    Keywords[11].paramcount = 1;
283    Keywords[11].param = &Parameters[23];
284 
285    Keywords[12].name = "phong";
286    Keywords[12].paramcount = 2;
287    Keywords[12].param = &Parameters[24];
288 
289    Keywords[13].name = "ambient";
290    Keywords[13].paramcount = 1;
291    Keywords[13].param = &Parameters[26];
292 
293    Keywords[14].name = "antialiasing";
294    Keywords[14].paramcount = 1;
295    Keywords[14].param = &Parameters[27];
296 
297    Keywords[15].name = "color";
298    Keywords[15].paramcount = 4;
299    Keywords[15].param = &Parameters[28];
300    Keywords[15].format_string = "%1%2%3%4%2%3%4";
301    Keywords[15].which_buf = COL_BUF;
302 
303    Keywords[16].name = "colorrange";
304    Keywords[16].paramcount = 7;
305    Keywords[16].param = &Parameters[32];
306    Keywords[16].format_string = "%1%2%3%4%5%6%7";
307    Keywords[16].which_buf = COL_BUF;
308 
309    Keywords[17].name = "plane";
310    Keywords[17].paramcount = 6;
311    Keywords[17].param = &Parameters[39];
312    sprintf(s, "%s", "%b01d%1%2%3%4%5%6\0");
313    s[4] = CUT_PLANE;
314    Keywords[17].format_string = &s[0];
315    /*Keywords[17].format_string[4] = CUT_PLANE;*/
316    Keywords[17].which_buf = CUT_BUF;
317 
318    Keywords[18].name = "include";
319    Keywords[18].paramcount = 1;
320    Keywords[18].param = &Parameters[46];
321 
322    Keywords[19].name = "interocular";
323    Keywords[19].paramcount = 1;
324    Keywords[19].param = &Parameters[47];
325 
326 	Keywords[20].name = "p1";
327 	Keywords[20].paramcount = 4;
328 	Keywords[20].param = &Parameters[48];
329 
330 	Keywords[21].name = "p2";
331 	Keywords[21].paramcount = 4;
332 	Keywords[21].param = &Parameters[52];
333 
334 	Keywords[22].name = "p3";
335 	Keywords[22].paramcount = 4;
336 	Keywords[22].param = &Parameters[56];
337 
338 	Keywords[23].name = "p4";
339 	Keywords[23].paramcount = 4;
340 	Keywords[23].param = &Parameters[60];
341 
342    Keywords[24].name = "";
343 
344    /* Phew, all done. */
345 
346    return(0);
347 }
348 
IsStereo(struct view_struct * view)349 int IsStereo(struct view_struct *view)
350 {
351    if (view->interocular > 0.0001) return(-1);
352    else return(0);
353 }
354 
CopyIDAT(int copy,struct png_internal_struct * i,struct png_internal_struct * i2,unsigned char * Buf,int ystart,int zflag,int zres)355 int CopyIDAT(int copy, /*struct disppal_struct *disppal, struct vidinfo_struct *vidinfo,*/
356    struct png_internal_struct *i, struct png_internal_struct *i2,
357    unsigned char *Buf, int ystart,/* int xadd, int yadd, */int zflag, int zres)
358 /* "copy" decides whether a new IDAT chunk is written */
359 {
360    int j;
361 
362    while ((strncmp(i->chunk_type, "IDAT", 4)!=0) && (strncmp(i->chunk_type, "IEND", 4)!=0))
363       GetNextChunk(i);
364    if (strncmp(i->chunk_type, "IEND", 4)==0) return(-1); /* No IDAT chunk found */
365    for (j=0; j<ystart; j++)
366    {
367       if (ReadPNGLine(i, Buf)) return(-2);
368       if (copy) WritePNGLine(i2, Buf);
369       /* store line */
370       if (zflag==0) putline(0L, (long)i->width-1, (long)i->width, j, &Buf[1], 0);   /* to image buffer */
371       else putline(0L, (long)i->width-1, (long)i->width, j, &Buf[1], 1);  /* to zbuffer */
372       /* display line */
373       if (zflag==0) update_bitmap(0L, (long)i->width-1, (long)i->width, j, &Buf[1], 0);
374       else if (zflag==1) update_bitmap(0L, (long)i->width-1, (long)i->width, j, &Buf[1], zres);
375       check_event();
376       /*eol(j+1);*/
377    }
378    return(0);
379 }
380 
SetDefaults(struct frac_struct * frac,struct view_struct * view,struct realpal_struct * realpal,char * colscheme,double * cutbuf)381 int SetDefaults(struct frac_struct *frac, struct view_struct *view, struct realpal_struct *realpal, char *colscheme,
382    double *cutbuf)
383 {
384    int i, j;
385 
386    frac->c[0] = 0; frac->c[1] = 0; frac->c[2] = 0; frac->c[3] = 0;
387    frac->bailout = 16;
388    frac->maxiter = 12;
389    frac->lvalue = 0;
390    frac->formula = 0;
391 	for (j=0; j<4; ++j) for (i=0; i<4; ++i)
392 		frac->p[j][i] = 0.0;
393 
394    view->s[0] = 0;
395    view->s[1] = 0;
396    view->s[2] = -2;
397    view->up[0] = 0; view->up[1] = -1; view->up[2] = 0;
398    view->light[0] = -2; view->light[1] = -5; view->light[2] = -5;
399    view->Mov[0] = 0; view->Mov[1] = 0;
400    view->LXR = 2.8;
401    view->xres = 160; view->yres = 120; view->zres = 120;
402    view->interocular = 0;
403    view->phongmax = 0.6; view->phongsharp = 30;
404    view->ambient = 0.04;
405    view->antialiasing = 1;
406 
407    realpal->cols[0].col1[0] = 0; realpal->cols[0].col1[1] = 0; realpal->cols[0].col1[2] = 1;
408    realpal->cols[0].col2[0] = 1; realpal->cols[0].col2[1] = 0; realpal->cols[0].col2[2] = 0;
409    realpal->cols[0].weight = 1;
410    realpal->colnum = 1;
411 
412    strcpy(colscheme, "0");
413    for (i=0; i<140; i++) cutbuf[i] = 0;
414    *(char *)&cutbuf[0] = CUT_TERMINATOR;
415    return(0);
416 }
417 
colorizepoint(struct calc_struct * c)418 float colorizepoint(/*float diffr, int closest_iteration,*/ struct calc_struct *c)
419 /* finds color for the point c->xq */
420 {
421    /* Handles for variables */
422    static unsigned char xh=255, yh=255, zh=255; /*, xbh=255, ybh=255, zbh=255 */
423     /*, diffrh=255, eorbith = 255, jorbith = 255, korbith = 255; */
424   /* static unsigned char lorbith = 255, closestith = 255; */
425 /*   double x, y, z; */
426    float CBuf;
427    char notdef;
428 
429    /* Init(&prog);*/  /* !!!!!!!! Really necessary??? */
430    SetVariable("x", &xh, c->xq[0], &prog);
431    SetVariable("y", &yh, c->xq[1], &prog);
432    SetVariable("z", &zh, c->xq[2], &prog);
433 /*   SetVariable("xb", &xbh, lastorbit[0], &prog);
434    SetVariable("yb", &ybh, lastorbit[1], &prog);
435    SetVariable("zb", &zbh, lastorbit[2], &prog);*/
436 /*   SetVariable("diffr", &diffrh, diffr, &prog);
437    SetVariable("eorbit", &eorbith, lastorbit[0], &prog);
438    SetVariable("jorbit", &jorbith, lastorbit[1], &prog);
439    SetVariable("korbit", &korbith, lastorbit[2], &prog);
440    SetVariable("lorbit", &lorbith, lastorbit[3], &prog);
441    SetVariable("closestit", &closestith, closest_iteration, &prog); */
442    CBuf = (float)calculate(&notdef, &prog);
443 
444    /* Make sure result is between 0 and 1 */
445    CBuf = (float)fmod((double)CBuf, (double)1.0);
446    if (CBuf<0) CBuf = 1 + CBuf;
447    return(CBuf);
448 }
449 
ParseINI(const char * fil,char * Error,struct frac_struct * frac,struct view_struct * view,struct realpal_struct * realpal,char * colscheme,double * cutbuf)450 int ParseINI(const char *fil, char *Error, struct frac_struct *frac, struct view_struct *view,
451    struct realpal_struct *realpal, char *colscheme, double *cutbuf)
452 /* file is an ini with path & suffix */
453 {
454    char inipath[256], file[256], ErrorMSG[200], *s;
455    int blen, i, colbufc;
456    char rc;
457 
458    strcpy(inipath, fil);
459    ConvertPath(inipath);
460    strcpy(file, inipath);
461    s = strrchr(inipath, slash);
462    if (s==NULL) inipath[0]=0;
463    else *(++s) = 0;
464    PrepareKeywords(colscheme, frac, view);
465    rc = 0;
466   /* realpal->colnum = 0; */ blen = 0; colbufc = 0;
467    if ((i = ParseFile(file, inipath, Keywords, (char *)realpal->cols, 30*sizeof(struct col_struct),
468       &colbufc, cutbuf, 140, &blen, &rc, ErrorMSG)) != 0)
469    {
470       sprintf(Error, "INI file '%s' error:\n%s\n", file, ErrorMSG);
471       return(-1);
472    }
473    /* Don't clear intersection objects if none defined in INI */
474    if (blen != 0) cutbuf[blen] = CUT_TERMINATOR;
475    if (colscheme[0]==0) strcpy(colscheme, "0");
476    if (colbufc!=0) realpal->colnum = colbufc / 56;
477 
478 
479    return(0);
480 }
481 
orbite(double * a,const double * b)482 char orbite(double *a, const double *b)
483 {
484 	int max = (int)orbit[0][0];
485 	int i = (int)*b;
486 	if (i > max) i = max;
487 	if (i < 0) i = 0;
488 	*a = orbit[i+1][0];
489 	return 0;
490 }
491 
orbitj(double * a,const double * b)492 char orbitj(double *a, const double *b)
493 {
494 	int max = (int)orbit[0][0];
495 	int i = (int)*b;
496 	if (i > max) i = max;
497 	if (i < 0) i = 0;
498 	*a = orbit[i+1][1];
499 	return 0;
500 }
501 
orbitk(double * a,const double * b)502 char orbitk(double *a, const double *b)
503 {
504 	int max = (int)orbit[0][0];
505 	int i = (int)*b;
506 	if (i > max) i = max;
507 	if (i < 0) i = 0;
508 	*a = orbit[i+1][2];
509 	return 0;
510 }
511 
orbitl(double * a,const double * b)512 char orbitl(double *a, const double *b)
513 {
514 	int max = (int)orbit[0][0];
515 	int i = (int)*b;
516 	if (i > max) i = max;
517 	if (i < 0) i = 0;
518 	*a = orbit[i+1][3];
519 	return 0;
520 }
521 
TranslateColorFormula(char * colscheme,char * ErrorMSG)522 int TranslateColorFormula(char *colscheme, char *ErrorMSG)
523 {
524    unsigned char dummy;
525    double ddummy;
526 
527    Init(&prog);
528 	DeclareFunction("orbite", orbite, &prog);
529 	DeclareFunction("orbitj", orbitj, &prog);
530 	DeclareFunction("orbitk", orbitk, &prog);
531 	DeclareFunction("orbitl", orbitl, &prog);
532    ddummy = 0;
533    dummy = 255; SetVariable("x", &dummy, ddummy, &prog);
534    dummy = 255; SetVariable("y", &dummy, ddummy, &prog);
535    dummy = 255; SetVariable("z", &dummy, ddummy, &prog);
536 /*   dummy = 255; SetVariable("xb", &dummy, ddummy, &prog);
537    dummy = 255; SetVariable("yb", &dummy, ddummy, &prog);
538    dummy = 255; SetVariable("zb", &dummy, ddummy, &prog);*/
539 /*   dummy = 255; SetVariable("diffr", &dummy, ddummy, &prog); */
540  /*  dummy = 255; SetVariable("eorbit", &dummy, ddummy, &prog);
541    dummy = 255; SetVariable("jorbit", &dummy, ddummy, &prog);
542    dummy = 255; SetVariable("korbit", &dummy, ddummy, &prog);
543    dummy = 255; SetVariable("lorbit", &dummy, ddummy, &prog);
544    dummy = 255; SetVariable("closestit", &dummy, ddummy, &prog);  */
545    if (Translate(ErrorMSG, colscheme, &prog)!=0) return(-1);
546    return(0);
547 }
548 
FormatExternToIntern(struct frac_struct * frac,struct view_struct * view)549 int FormatExternToIntern(struct frac_struct *frac, struct view_struct *view)
550 {
551    /* This is to change the input format to internal format */
552    /* Input: light relative to viewers position (for convenience of user) */
553    /* Internal: light absolute in space (for convenience of programmer) */
554    int i;
555    struct basestruct base;
556    vec3 ltmp;
557 
558    if (calcbase(&base, NULL, *view, 0)!= 0) return(-1);
559    forall(i,3) ltmp[i] = view->light[0]*base.x[i] + view->light[1]*base.y[i] +
560       view->light[2]*base.z[i];
561    forall(i,3) view->light[i] = view->s[i]+ltmp[i]
562       + view->Mov[0]*base.x[i] + view->Mov[1]*base.y[i];
563    /* bailout */
564    /* Input: real bailout value */
565    /* Internal: square of bailout value (saves some time) */
566    frac->bailout *= frac->bailout;
567    return(0);
568 }
569 
FormatInternToExtern(struct frac_struct * frac,struct view_struct * view)570 int FormatInternToExtern(struct frac_struct *frac, struct view_struct *view)
571 {
572    /* Reverse process of "FormatExternToIntern". see above */
573    int i;
574    struct basestruct base;
575    vec3 ltmp;
576 
577    if (calcbase(&base, NULL, *view, 0)!= 0) return(-1);
578    frac->bailout = sqrt(frac->bailout);
579    forall(i,3) ltmp[i] = view->light[i] - view->s[i];
580    view->light[0] = scalarprod(ltmp, base.x) - view->Mov[0];
581    view->light[1] = scalarprod(ltmp, base.y) - view->Mov[1];
582    view->light[2] = scalarprod(ltmp, base.z);
583 
584    return(0);
585 }
586 
InitGraphics(char * Error,struct view_struct * view,struct realpal_struct * realpal,int ready,struct vidinfo_struct * vidinfo,struct disppal_struct * disppal,int * xadd,int * yadd,int zbufflag)587 int InitGraphics(char *Error, struct view_struct *view, struct realpal_struct *realpal, int ready,
588    struct vidinfo_struct *vidinfo, struct disppal_struct *disppal, int *xadd, int *yadd, int zbufflag)
589 {
590    /* ready ... 0: not ready */
591    /* zbufflag ... 0: no zbuffer (reason: AA) */
592    int i, j;
593 
594    /* Do graphics initialization &  return mode info (in vidinfo) in different versions */
595    *yadd = 0; *xadd = 0;
596    i = view->xres; if (IsStereo(view)) i *= 2;
597    j = view->yres;
598    if (zbufflag) { i *= view->antialiasing; j *= view->antialiasing; }
599 
600 /* X11
601    X_initialize(i, j);
602    X_ReturnVideoInfo(vidinfo);
603    if (vidinfo->maxcol!=-1)
604    {
605       disppal->btoc = 1;
606       if (CreateDispPal(disppal, realpal, vidinfo->maxcol, view->phongmax,
607 	 vidinfo->rdepth, vidinfo->gdepth, vidinfo->bdepth)==-1)
608       {
609 	 sprintf(Error, "Too many colours for this display.\n Use text only version.\n");
610 	 return(-1);
611       }
612       {
613 	 int nc;
614 	 if ((nc=X_SetColors(disppal, 0))!=disppal->maxcol)
615 	 {
616 	    printf("Could only allocate %i colors (out of %i).\n", nc, disppal->maxcol);
617 	    if (ready) printf("XV can probably do a better job. Hope it reads PNG... (patched versions do!)\n");
618 	 }
619       }
620    }
621    else CalcWeightsum(realpal);
622 */
623 
624    if (Initialize!=NULL) if (Initialize(i, j, Error)!=0) return(-1);
625    if (ReturnVideoInfo!=NULL) ReturnVideoInfo(vidinfo);
626    if (vidinfo->maxcol!=-1)
627    {
628       int r = 0;
629       disppal->btoc = 1;
630       if (!zbufflag)
631 	 r = CreateDispPal(disppal, realpal, vidinfo->maxcol, view->phongmax,
632 	    vidinfo->rdepth, vidinfo->gdepth, vidinfo->bdepth);
633       else
634       {
635 	 struct realpal_struct rp;
636 	 rp.colnum = 1;
637 	 rp.cols[0].weight = 1;
638 	 rp.cols[0].col1[0] = 1; rp.cols[0].col1[1] = 1; rp.cols[0].col1[2] = 1;
639 	 rp.cols[0].col2[0] = 1; rp.cols[0].col2[1] = 1; rp.cols[0].col2[2] = 1;
640 	 r = CreateDispPal(disppal, &rp, vidinfo->maxcol, view->phongmax,
641 	    vidinfo->rdepth, vidinfo->gdepth, vidinfo->bdepth);
642       }
643       if (r==-1)
644       {
645 	 sprintf(Error, "Too many colours for this display (%i).\nUse text only version.\n",vidinfo->maxcol);
646 	 return(-1);
647       }
648       if (SetColors!=NULL) SetColors(disppal);
649    }
650    else CalcWeightsum(realpal);
651 
652    return(0);
653 }
654 
AllocBufs(struct view_struct * v,int zflag,int pal,float ** CBuf,float ** BBuf,float ** LBufR,float ** LBufL,unsigned char ** line,unsigned char ** line2,unsigned char ** line3)655 int AllocBufs(struct view_struct *v, int zflag, int pal, float **CBuf, float **BBuf, float **LBufR,
656    float **LBufL, unsigned char **line, unsigned char **line2, unsigned char **line3)
657 /* zflag ... whether img (0), zbuf (1) or zbuf->img (2) is calculated */
658 /* pal ... whether palette or not */
659 {
660    long LBufSize;
661    unsigned int st;
662 
663    if (IsStereo(v)) st = 2; else st = 1;
664    LBufSize = (long)v->xres*v->antialiasing*(v->antialiasing+1L)*(long)sizeof(float)+10L;
665 /*#if _MSC_VER <= 800
666    if (LBufSize>65535) return(-2);
667   #endif */
668    switch (zflag)
669    {
670       case 0:   /* create an image without ZBuffer */
671 	 *LBufR = calloc((size_t)LBufSize, 1);
672 	 *line = calloc(3*v->xres*st+1+10, 1);
673 	 if (pal) *line2 = calloc(v->xres*st+10, 1);
674 	 *CBuf = calloc(v->xres*st*sizeof(float)+10, 1);
675 	 *BBuf = calloc(v->xres*st*sizeof(float)+10, 1);
676 	 if (st==2) *LBufL = calloc((size_t)LBufSize+10, 1);
677 	 if (pal && !*line2) return(-1);
678 	 if (st==2 && !*LBufL) return(-1);
679 	 if (!*LBufR || !*line || !*CBuf || !*BBuf) return(-1);
680 	 break;
681       case 1:   /* create a ZBuffer only */
682 	 /* LBufR and LBufL each hold aa lines (mono) */
683 	 *LBufR = calloc((size_t)LBufSize, 1);
684 	 /* line only holds a single stereo line for transferring of LBuf->global ZBuffer */
685 	 *line = calloc(3*v->xres*v->antialiasing*st+1+10, 1);
686 	 if (st==2) *LBufL = calloc((size_t)LBufSize, 1);
687 	 if (st==2 && !*LBufL) return(-1);
688 	 if (!*LBufR || !*line) return(-1);
689 	 break;
690       case 2:   /* create an image using a ZBuffer */
691 	 *LBufR = calloc((size_t)LBufSize, 1);
692 	 *line = calloc(3*v->xres*st+1+10, 1);
693 	 if (pal) *line2 = calloc(v->xres*st+10, 1);
694 	 *CBuf = calloc(v->xres*st*sizeof(float)+10, 1);
695 	 *BBuf = calloc(v->xres*st*sizeof(float)+10, 1);
696 	 *line3 = calloc(3*v->xres*v->antialiasing*st+10, 1);
697 	 if (st == 2) *LBufL = calloc((size_t)LBufSize, 1);
698 	 if (pal && !*line2) return(-1);
699 	 if (st == 2 && !*LBufL) return(-1);
700 	 if (!*LBufR || !*line || !*line3 || !*CBuf || !*BBuf) return(-1);
701 	 break;
702    }
703    return(0);
704 }
705 
FreeBufs(float ** a,float ** g,float ** b,float ** c,unsigned char ** d,unsigned char ** e,unsigned char ** f)706 int FreeBufs(float **a, float **g, float **b, float **c, unsigned char **d,
707    unsigned char **e, unsigned char **f)
708 {
709 	free(orbit);
710    if (*f) free(*f);
711    if (*e) free(*e);
712    if (*d) free(*d);
713    if (*a) free(*a);
714    if (*c) free(*c);
715    if (*b) free(*b);
716    if (*g) free(*g);
717    return(0);
718 }
719 
LBuf_ZBuf(struct view_struct * v,float * LBuf,unsigned char * line,long ii,long imax,long aa_line,int offs)720 int LBuf_ZBuf(struct view_struct *v, float *LBuf, unsigned char *line, long ii,
721    long imax, long aa_line, int offs)
722 {
723    int tmp;
724    long l, i, k;
725 
726    for (k=0; k<v->antialiasing; k++)
727    for (i=ii; i<=imax; i++)
728    {
729       tmp = i*v->antialiasing+k+offs;
730       l = (long)floor(LBuf[((size_t)i+(size_t)aa_line*(size_t)v->xres)
731 	 *(size_t)v->antialiasing+(size_t)k]*100+0.5);
732       line[tmp*3+1] = (unsigned char)(l>>16 & 0xFF);
733       line[tmp*3+2] = (unsigned char)(l>>8  & 0xFF);
734       line[tmp*3+3] = (unsigned char)(l     & 0xFF);
735    }
736    return(0);
737 }
738 
CalculateFractal(char * Error,char * pngfile,FILE ** png,struct png_internal_struct * png_internal,int zflag,int * xstart,int * ystart,int no,struct basestruct * rbase,struct basestruct * srbase,struct basestruct * lbase,struct basestruct * slbase,struct frac_struct * f,struct view_struct * v,struct realpal_struct * realpal,double * cutbuf,struct vidinfo_struct * vidinfo,struct disppal_struct * disppal)739 int CalculateFractal(char *Error, char *pngfile, FILE **png,/* struct png_info_struct *png_info,*/
740    struct png_internal_struct *png_internal,
741    int zflag, int *xstart, int *ystart,/* int xadd, int yadd, */int no, struct basestruct *rbase, struct basestruct *srbase,
742    struct basestruct *lbase, struct basestruct *slbase,
743    struct frac_struct *f, struct view_struct *v, struct realpal_struct *realpal,/* char *colscheme,*/ double *cutbuf,
744    struct vidinfo_struct *vidinfo, struct disppal_struct *disppal)
745 /* pngfile: string of filename, without path (only for title bar) */
746 /* png: _opened_ png file */
747 /* png file returns _closed_ */
748 /*      and initialized (png_info, png_internal) */
749 /* if png==NULL, no file is written */
750 /* also closes graphics, resets keyboard mode */
751 /* wants external format for light-source and bailout */
752 /* zflag: decides what to calculate,
753       0..image from scratch, size view.xres*view.yres
754       1..ZBuffer from scratch, size view.xres*view.yres*AA^2
755       2..image from ZBuffer, size img: xres*yres, buffer *AA^2
756       for every case take into account that images can be stereo! */
757 {
758    long i, j;
759    long xres_st, xres_aa, xres_st_aa;
760    float *LBufR, *LBufL, *CBuf, *BBuf;
761    unsigned char *line, *line2, *line3;
762    struct calc_struct cr, cl;
763    unsigned long my_time;
764    time_t dummytime;
765    char MSG[300];
766    long ii, imax, k, kk;
767    struct frac_struct frac;
768    struct view_struct view;
769    int rrv=0, firstline;
770 
771    frac = *f; view = *v;
772 
773    xres_st = view.xres;
774    if (IsStereo(v)) xres_st *= 2;
775    xres_aa = view.xres*view.antialiasing;
776    xres_st_aa = xres_aa;
777    if (IsStereo(v)) xres_st_aa *= 2;
778 
779    if (FormatExternToIntern(&frac, &view)!=0)
780    {
781       sprintf(Error, "Error in view struct!");
782       return(-1);
783    }
784    /* Allocate some memory */
785    CBuf = NULL; BBuf = NULL; LBufR = NULL; LBufL = NULL; line = NULL; line2 = NULL; line3 = NULL;
786 	orbit = NULL;
787 	orbit = calloc(frac.maxiter+2, 4*sizeof(double));  /* freed by FreeBufs */
788 	/* "+2", because orbit[0] is special flag for orbite,j,k,l */
789    if (AllocBufs(v, zflag, (vidinfo->maxcol!=-1), &CBuf, &BBuf, &LBufR, &LBufL, &line,
790       &line2, &line3)!=0 || orbit == NULL)
791    {
792       FreeBufs(&LBufR, &LBufL, &CBuf, &BBuf, &line, &line2, &line3);
793       sprintf(Error, "Not enough memory.");
794       return(-1);
795    }
796 
797    my_time = (long)time((time_t)NULL);
798    if (frac.formula==0)
799    {
800       cr.iterate = iterate_0; cr.iternorm = iternorm_0;
801       cl.iterate = iterate_0; cl.iternorm = iternorm_0;
802    }
803    if (frac.formula==1)
804    {
805       cr.iterate = iterate_1; cr.iternorm = iternorm_1;
806       cl.iterate = iterate_1; cl.iternorm = iternorm_1;
807    }
808    if (frac.formula==2) {
809    	cr.iterate = iterate_2; cr.iternorm = 0;
810 	cl.iterate = iterate_2; cl.iternorm = 0;
811    }
812 
813    if (frac.formula==3) {
814    	cr.iterate = iterate_3; cr.iternorm = 0;
815 	cl.iterate = iterate_3; cl.iternorm = 0;
816    }
817    if (frac.formula==4) {
818    	cr.iterate = iterate_4; cr.iternorm = 0;
819 	cl.iterate = iterate_4; cl.iternorm = 0;
820    }
821 
822    /* Initialize variables for calcline (those which don�t change from line to line) */
823    cr.v = view; cr.f = frac; cr.sbase = *srbase; cr.base = *rbase; cr.cutbuf = cutbuf;
824    cr.absx = sqrt(scalarprod(cr.sbase.x,cr.sbase.x))/(double)cr.v.antialiasing;
825    cr.absy = sqrt(scalarprod(cr.sbase.y,cr.sbase.y))/(double)cr.v.antialiasing;
826    cr.absz = sqrt(scalarprod(cr.sbase.z,cr.sbase.z));
827    cr.aabase = cr.sbase;
828    if ((zflag==0 || zflag==1) && cr.v.antialiasing > 1)
829    {
830       forall(i,3) cr.aabase.x[i] /= (double)cr.v.antialiasing;
831       forall(i,3) cr.aabase.y[i] /= (double)cr.v.antialiasing;
832    }
833    if (IsStereo(&view))
834    {
835       cl.v = view; cl.f = frac; cl.sbase = *slbase; cl.base = *lbase; cl.cutbuf = cutbuf;
836       cl.absx = sqrt(scalarprod(cl.sbase.x,cl.sbase.x))/(double)cl.v.antialiasing;
837       cl.absy = sqrt(scalarprod(cl.sbase.y,cl.sbase.y))/(double)cl.v.antialiasing;
838       cl.absz = sqrt(scalarprod(cl.sbase.z,cl.sbase.z));
839       cl.aabase = cl.sbase;
840       if ((zflag==0 || zflag==1) && cl.v.antialiasing > 1)
841       {
842 	 forall(i,3) cl.aabase.x[i] /= (double)cl.v.antialiasing;
843 	 forall(i,3) cl.aabase.y[i] /= (double)cl.v.antialiasing;
844       }
845    }
846    /* recalculate last line when resuming an image without ZBuffer */
847    firstline = 0;
848    if (zflag==0)
849    {
850       (*ystart)--; *xstart = 0; firstline = 1;
851       Change_Name("recalc.");
852    }
853    for (j=*ystart; j<view.yres; j++)
854    {
855       /* Initialize variables for calcline (which change from line to line) */
856       cr.xp[3] = frac.lvalue; cr.xs[3] = frac.lvalue;
857       forall(i,3) cr.xp[i] = srbase->O[i] + j*srbase->y[i];
858       if (IsStereo(&view))
859       {
860 	 cl.xp[3] = frac.lvalue; cl.xs[3] = frac.lvalue;
861 	 forall(i,3) cl.xp[i] = slbase->O[i] + j*slbase->y[i];
862       }
863       /* Initialize LBufs from ZBuffer */
864       memcpy(&LBufR[0], &LBufR[view.antialiasing*xres_aa], xres_aa*sizeof(float));
865       if (IsStereo(&view)) memcpy(&LBufL[0], &LBufL[view.antialiasing*xres_aa], xres_aa*sizeof(float));
866       if (zflag==2)
867       {
868 	 for (ii=0; ii<view.antialiasing+1; ii++)
869 	 {
870 	    if (j+ii>0)   /* this doesn�t work for the 1st line */
871 	    {
872 	       QU_getline(line3, j*view.antialiasing+ii-1, xres_st_aa, 1);
873 	       for (i=0; i<xres_aa; i++) LBufR[(size_t)i+(size_t)ii*(size_t)xres_aa]
874 		  = (float)((long)line3[i*3]<<16 |
875 		  (long)line3[i*3+1]<<8 | (long)line3[i*3+2])/100;
876 	       if (IsStereo(&view))
877 	       {
878 		  for (i=0; i<xres_aa; i++) LBufL[(size_t)i+(size_t)ii*(size_t)xres_aa] =
879 		     (float)((long)line3[(i+xres_aa)*3]<<16
880 		     | (long)line3[(i+xres_aa)*3+1]<<8 | (long)line3[(i+xres_aa)*3+2])/100;
881 	       }
882 	    }
883 	    else
884 	    {
885 	       for (k=0; k<xres_aa; k++) LBufR[(size_t)k] = (float)view.zres;
886 	       if (IsStereo(&view)) for (k=0; k<xres_aa; k++) LBufL[(size_t)k] = (float)view.zres;
887 	    }
888 	 }
889       }
890       for (ii=*xstart; ii<view.xres; ii+=no)
891       {
892 	 imax = ii+no-1; if (imax>view.xres-1) imax = view.xres-1;
893 	 calcline(ii, imax, j, LBufR, BBuf, CBuf, &cr, zflag);    /* right eye image */
894 
895 	 if ((zflag==0 || zflag==2) && !firstline)  /* image to calculate */
896 	 {
897 	    if (vidinfo->maxcol!=-1) PixelvaluePalMode(ii, imax, disppal->colnum-1,
898 	       disppal->brightnum-1, line2, CBuf, BBuf);
899 	    PixelvalueTrueMode(ii, imax, 255, 255, 255, realpal, &(line[1]), CBuf, BBuf);
900 	 }
901 	 if (IsStereo(&view))
902 	 {
903 	    calcline(ii, imax, j, LBufL, &BBuf[view.xres], &CBuf[view.xres],
904 	       &cl, zflag);   /* left eye image */
905 	    if ((zflag==0 || zflag==2) && !firstline)   /* image to calculate */
906 	    {
907 	       if (vidinfo->maxcol!=-1) PixelvaluePalMode(ii, imax, disppal->colnum-1,
908 		  disppal->brightnum-1, &line2[view.xres], &CBuf[view.xres], &BBuf[view.xres]);
909 	       PixelvalueTrueMode(ii, imax, 255, 255, 255, realpal, &(line[3*view.xres+1]),
910 		  &CBuf[view.xres], &BBuf[view.xres]);
911 	    }
912 	 }
913 	 /* Display and Transfer */
914 	 if (zflag==1)   /* the ZBuffer */
915 	 {
916 	    for (kk=1; kk<view.antialiasing+1; kk++)
917 	    {
918 	       LBuf_ZBuf(&view, LBufR, line, ii, imax, kk, 0);
919 	       putline(ii*view.antialiasing, (imax+1)*view.antialiasing-1,
920 		  xres_st_aa, j*view.antialiasing+kk-1, line+1, 1);
921 	       update_bitmap(ii*view.antialiasing, (imax+1)*view.antialiasing-1,
922 		      xres_st_aa, j*view.antialiasing+kk-1, line+1, view.zres);
923 	    }
924 	    if (IsStereo(&view))
925             {
926 	       for (kk=1; kk<view.antialiasing+1; kk++)
927 	       {
928 		  LBuf_ZBuf(&view, LBufL, line, ii, imax, kk, xres_aa);
929 		  putline(ii*view.antialiasing+xres_aa,
930 		     (imax+1)*view.antialiasing-1+xres_aa,
931 		     xres_st_aa, j*view.antialiasing+kk-1, line+1, 1);
932 		  update_bitmap(ii*view.antialiasing+xres_aa,
933 		     (imax+1)*view.antialiasing-1+xres_aa,
934 		     xres_st_aa, j*view.antialiasing+kk-1, line+1, view.zres);
935 	       }
936             }
937 	 }
938 	 else if (!firstline)   /* the image */
939 	 {
940 	    putline(ii, imax, xres_st, j, line+1, 0);
941 	    if (IsStereo(&view)) putline(ii+view.xres, imax+view.xres, xres_st, j, line+1, 0);
942 	    update_bitmap(ii, imax, xres_st, j, line+1, 0);
943 	    if (IsStereo(&view)) update_bitmap(ii+view.xres, imax+view.xres, xres_st, j, &(line[1]),
944 	       0);
945 	 }
946 	 if ((imax==view.xres-1) && !firstline) eol(j+1);
947 	 rrv = check_event();
948 	 if (rrv!=0)
949 	 {
950 	    i = view.xres*3; if (IsStereo(&view)) i *= 2;
951 	    memset(line, 0, (size_t)i+1);
952 	    calc_time += (long)time((time_t)NULL) - my_time;
953 	    if (png != NULL)
954 	    {
955 	       PNGEnd(png_internal, line, 0, j);
956 	       fclose(*png);
957 	       EndPNG(png_internal);
958 	    }
959 	    FreeBufs(&LBufR, &LBufL, &CBuf, &BBuf, &line, &line2, &line3);
960 	    *ystart = j; *xstart = ii+1;
961 	    if (*xstart==view.xres)
962 	    {
963 	       *xstart=0; (*ystart)++;
964 	    }
965 	    Done();
966             return(rrv);  /* return code from check event. (win destroyed / calc stopped) */
967 	 }
968       }
969       *xstart = 0;
970       /* Write to PNG file */
971       if (png)
972       {
973          switch (zflag)
974 	 {
975             case 0: if (!firstline)
976             {
977                line[0] = 0;       /* Set filter method */
978                DoFiltering(png_internal, line);
979                WritePNGLine(png_internal, line);
980             }
981             break;
982             case 1: if (!firstline)
983             {
984                for (kk=1; kk<view.antialiasing+1; kk++)
985 	       {
986                   LBuf_ZBuf(&view, LBufR, line, 0, view.xres-1, kk, 0);
987                   if (IsStereo(&view)) LBuf_ZBuf(&view, LBufL, line, 0, view.xres-1,
988                      kk, xres_aa);
989                   line[0] = 0;
990                   DoFiltering(png_internal, line);
991                   WritePNGLine(png_internal, line);
992 	       }
993             }
994             break;
995             case 2:
996                line[0] = 0;      /* Set filter method */
997                DoFiltering(png_internal, line);
998                WritePNGLine(png_internal, line);
999          }
1000       }
1001       firstline = 0;
1002    }
1003 
1004    calc_time += (long)time(&dummytime) - my_time;
1005    if (png != NULL)
1006    {
1007       PNGEnd(png_internal, line, 0, j);
1008       fclose(*png);
1009       EndPNG(png_internal);
1010    }
1011    FreeBufs(&LBufR, &LBufL, &CBuf, &BBuf, &line, &line2, &line3);
1012 
1013    if (pngfile!=NULL)
1014    {
1015       sprintf(MSG, "%s", pngfile);
1016       Change_Name(MSG);
1017    }
1018    if (Done!=NULL) Done();
1019    *xstart = 0;
1020    *ystart = j;
1021    return(0);
1022 }
1023 
CalculateINI(const char * inif,const char * pngf,char * Error,int zflag)1024 int CalculateINI(const char *inif, const char *pngf, char *Error, int zflag)
1025 {
1026    struct frac_struct frac;
1027    struct view_struct view;
1028    struct realpal_struct realpal;
1029    char colscheme[251];
1030    double cutbuf[140];
1031    struct basestruct rbase, srbase, lbase, slbase, cbase;
1032    struct vidinfo_struct vidinfo;
1033    struct disppal_struct disppal;
1034    int xadd, yadd, xstart, ystart;
1035    FILE *png;
1036    struct png_info_struct png_info;
1037    struct png_internal_struct png_internal;
1038    char ErrorMSG[256], inifile[256], pngfile[256];
1039    int i;
1040 
1041    strcpy(inifile, inif); strcpy(pngfile, pngf);
1042    ConvertPath(inifile); ConvertPath(pngfile);
1043 
1044    SetDefaults(&frac, &view, &realpal, colscheme, &cutbuf[0]);
1045 
1046    if (ParseINI(inifile, Error, &frac, &view, &realpal, colscheme, &cutbuf[0])!=0)
1047       return(-1);
1048 
1049    if (TranslateColorFormula(colscheme, ErrorMSG)!=0)
1050    {
1051       sprintf(Error, "INI file '%s':\nError in color scheme formula:\n%s\n",inifile,ErrorMSG);
1052       return(-1);
1053    }
1054 
1055    if (calcbase(&cbase, &srbase, view, 0)!= 0)
1056    {
1057       sprintf(Error, "file '%s':\nError in view_struct!\n",inifile);
1058       return(-1);
1059    }
1060    rbase = cbase;
1061    if (IsStereo(&view))
1062    {
1063       if (calcbase(&rbase, &srbase, view, 1)!= 0)
1064       {
1065 	 sprintf(Error, "file '%s':\nError in view_struct (right eye)!\n",inifile);
1066 	 return(-1);
1067       }
1068       if (calcbase(&lbase, &slbase, view, -1) != 0)
1069       {
1070 	 sprintf(Error, "file '%s':\nError in view_struct (left eye)!\n", inifile);
1071 	 return(-1);
1072       }
1073    }
1074    /* FormatExternToIntern(&frac, &view, &cbase); */
1075 #ifdef GUI
1076    update_parameters(&frac, &view, &realpal, colscheme, cutbuf);
1077 #endif
1078 
1079 #ifndef GUI
1080    if (zflag==1)
1081    {
1082       size_t xres = view.xres;
1083       xres *= view.antialiasing;
1084       if (IsStereo(&view)) xres *= 2;
1085       TEXTVER_zbuf = calloc((size_t)xres*(size_t)view.yres*(size_t)view.antialiasing*3L, 1);
1086       if (!TEXTVER_zbuf)
1087       {
1088 	 sprintf(Error, "Not enough memory for ZBuffer!");
1089 	 return(-1);
1090       }
1091    }
1092 #endif
1093 
1094    if (InitGraphics(Error, &view, &realpal, 0, &vidinfo, &disppal, &xadd, &yadd, zflag)!=0) return(-1);
1095 
1096    if (PNGInitialization(pngfile, 1, &png, &png_info, &png_internal, 0, 0, 0L, &frac, &view,
1097 	 &disppal, &realpal, colscheme, cutbuf, zflag))
1098    {
1099       sprintf(Error, "Could not create file '%s'\n", pngfile);
1100 #ifndef GUI
1101       if (zflag==1) free(TEXTVER_zbuf);
1102 #endif
1103       return(-1);
1104    }
1105    sprintf(Error, "\nCreated file '%s'\n", pngfile);
1106 
1107    xstart = 0; ystart = 0;
1108    calc_time = 0;
1109    i = CalculateFractal(Error, pngfile, &png, /*&png_info,*/ &png_internal,
1110       zflag, &xstart, &ystart,/* xadd, yadd,*/ 4, &rbase, &srbase, &lbase, &slbase, &frac, &view,
1111       &realpal,/* colscheme,*/ &cutbuf[0], &vidinfo, &disppal);
1112 
1113    return(i);
1114 }
1115 
CreateImage(char * Error,int * xstart,int * ystart,struct frac_struct * frac,struct view_struct * view,struct realpal_struct * realpal,char * colscheme,double * cutbuf,int noev,int zflag)1116 int CreateImage(char *Error, int *xstart, int *ystart, struct frac_struct *frac, struct view_struct *view,
1117    struct realpal_struct *realpal, char *colscheme, double *cutbuf, int noev, int zflag)
1118 /* Creates/Continues image from given parameters. Wants external format of frac & view */
1119 {
1120    struct basestruct rbase, srbase, lbase, slbase, cbase;
1121    struct vidinfo_struct vidinfo;
1122    struct disppal_struct disppal;
1123    int xadd, yadd;
1124    char ErrorMSG[256];
1125    int i;
1126 
1127    if (TranslateColorFormula(colscheme, ErrorMSG)!=0)
1128    {
1129       sprintf(Error, "Error in color scheme formula:\n%s\n", ErrorMSG);
1130       return(-1);
1131    }
1132    Error[0] = 0;
1133    if (calcbase(&cbase, &srbase, *view, 0)!= 0)
1134    {
1135       sprintf(Error, "Error in view_struct!\n");
1136       return(-1);
1137    }
1138    rbase = cbase;
1139    if (IsStereo(view))
1140    {
1141       if (calcbase(&rbase, &srbase, *view, 1) != 0)
1142       {
1143 	 sprintf(Error, "Error in view_struct (right eye)!\n");
1144 	 return(-1);
1145       }
1146       if (calcbase(&lbase, &slbase, *view, -1) != 0)
1147       {
1148 	 sprintf(Error, "Error in view_struct (left eye)!\n");
1149 	 return(-1);
1150       }
1151    }
1152 
1153    /* MSWIN_Initialize will recognize if it is already initialized. Needing vidinfo, disppal...*/
1154    if (InitGraphics(Error, view, realpal, 0, &vidinfo, &disppal, &xadd, &yadd, (zflag==1))!=0)
1155       return(-1);
1156 
1157  /*  FormatExternToIntern(&frac, &view, &cbase); */
1158 
1159    if (ystart==0 && xstart==0) calc_time = 0;
1160    i = CalculateFractal(Error, NULL, NULL,/* NULL,*/ NULL,
1161       zflag, xstart, ystart,/* xadd, yadd,*/ noev, &rbase, &srbase, &lbase, &slbase, frac, view, realpal,
1162       /*colscheme,*/ &cutbuf[0], &vidinfo, &disppal);
1163 
1164    return(i);
1165 }
1166 
CreateZBuf(char * Error,int * xstart,int * ystart,struct frac_struct * frac,struct view_struct * view,double * cutbuf,int noev)1167 int CreateZBuf(char *Error, int *xstart, int *ystart, struct frac_struct *frac, struct view_struct *view,
1168    double *cutbuf, int noev)
1169 /* Creates/Continues ZBuffer from given parameters. Wants external format of frac & view */
1170 {
1171    struct basestruct rbase, srbase, lbase, slbase, cbase;
1172    struct realpal_struct realpal;
1173    struct vidinfo_struct vidinfo;
1174    struct disppal_struct disppal;
1175    int xadd, yadd;
1176    int i;
1177 
1178    /* Set a grayscale palette */
1179    realpal.colnum = 1;
1180    realpal.cols[0].weight = 1;
1181    for (i=0; i<3; i++)
1182    {
1183       realpal.cols[0].col1[i] = 1;
1184       realpal.cols[0].col2[i] = 1;
1185    }
1186 
1187    Error[0] = 0;
1188    if (calcbase(&cbase, &srbase, *view, 0)!= 0)
1189    {
1190       sprintf(Error, "Error in view_struct!\n");
1191       return(-1);
1192    }
1193    rbase = cbase;
1194    if (IsStereo(view))
1195    {
1196       if (calcbase(&rbase, &srbase, *view, 1) != 0)
1197       {
1198 	 sprintf(Error, "Error in view_struct (right eye)!\n");
1199 	 return(-1);
1200       }
1201       if (calcbase(&lbase, &slbase, *view, -1) != 0)
1202       {
1203 	 sprintf(Error, "Error in view_struct (left eye)!\n");
1204 	 return(-1);
1205       }
1206    }
1207    /* MSWIN_Initialize will recognize if it is already initialized. Needing vidinfo, disppal...*/
1208    if (InitGraphics(Error, view, &realpal, 0, &vidinfo, &disppal, &xadd, &yadd, 1)!=0) return(-1);
1209 
1210    i = CalculateFractal(Error, NULL, NULL, NULL,
1211       1, xstart, ystart, noev, &rbase, &srbase, &lbase, &slbase, frac, view, &realpal, /*"", */
1212       &cutbuf[0], &vidinfo, &disppal);
1213 
1214    return(i);
1215 }
1216 
CalculatePNG(const char * pngf1,const char * pngf2,char * Error,const char * ini,int zflag)1217 int CalculatePNG(const char *pngf1, const char *pngf2, char *Error, const char *ini, int zflag)
1218 /* if zflag==0 || zflag==1: */
1219 /* pngf1 ... file to read from */
1220 /* pngf2 ... file to create ("" if no name available) */
1221 /* else: */
1222 /* pngf1 ... ZBuffer */
1223 /* pngf2 ... file to create */
1224 /* ini      ... ini file with parameters to replace ZBuffer parameters */
1225 {
1226    struct frac_struct frac, f;
1227    struct view_struct view, v;
1228    struct realpal_struct realpal, rp;
1229    char colscheme[251], cols[251];
1230    double cutbuf[140], cbuf[140];
1231    struct basestruct rbase, srbase, lbase, slbase, cbase;
1232    struct vidinfo_struct vidinfo;
1233    struct disppal_struct disppal;
1234    int xadd, yadd, xstart, ystart;
1235    FILE *png1, *png2;
1236    struct png_info_struct png_info1, png_info2;
1237    struct png_internal_struct png_internal1, png_internal2;
1238    unsigned char *line;
1239    int i;
1240    char ErrorMSG[256], pngfile1[256], pngfile2[256], ready;
1241    int ys;
1242 
1243    strcpy(pngfile1, pngf1); strcpy(pngfile2, pngf2);
1244    ConvertPath(pngfile1); ConvertPath(pngfile2);
1245 
1246    SetDefaults(&frac, &view, &realpal, colscheme, &cutbuf[0]);
1247 
1248    /* Do PNG-Init for loading */
1249    if ((png1 = fopen(pngfile1, "rb")) == NULL)
1250    {
1251       sprintf(Error, "Cannot open file '%s'.'\n", pngfile1);
1252       return(-1);
1253    }
1254    if (InitPNG(png1, &png_info1, &png_internal1)==-1)
1255    {
1256       sprintf(Error, "File '%s' is not a valid png-file.\n", pngfile1);
1257       fclose(png1);
1258       EndPNG(&png_internal1);
1259       return(-1);
1260    }
1261 
1262    i = ReadParameters(Error, &xstart, &ystart, &png_internal1,
1263       &frac, &view, &realpal, colscheme, &cutbuf[0]);
1264    /* if (i==-128) sprintf(Error, "Warning: File version higher than %s.\n",PROGVERSION); */
1265    if (i<0 && i>-128)
1266    {
1267       fclose(png1); EndPNG(&png_internal1);
1268       return(-1);
1269    }
1270    if (zflag==2 && ystart!=view.yres)
1271    {
1272       sprintf(Error, "Calculation of ZBuffer '%s' is not ready.\n",pngfile1);
1273       return(-1);
1274    }
1275    else if (ystart==view.yres)
1276    {
1277       sprintf(Error, "Calculation of image '%s' was complete.\n",pngfile1);
1278       ready = 1;
1279    }
1280    else ready = 0;
1281 
1282    if (ready==0 && pngfile2[0]==0)
1283    {
1284       sprintf(Error, "Couldn't find a free filename based on '%s'\n",pngfile1);
1285       fclose(png1);
1286       EndPNG(&png_internal1);
1287       return(-1);
1288    }
1289 
1290    rp = realpal;
1291    if (zflag==2 && ini[0]!=0)
1292    {
1293       f = frac; v = view; strncpy(cols, colscheme, 251);
1294       i = ParseINI(ini, Error, &f, &v, &rp, cols, cbuf);
1295       if (i)
1296       {
1297 	 fclose(png1);
1298 	 EndPNG(&png_internal1);
1299 	 return(-1);
1300       }
1301       for (i=0; i<3; i++) view.light[i] = v.light[i];
1302       view.ambient = v.ambient;
1303       view.phongmax = v.phongmax;
1304       view.phongsharp = v.phongsharp;
1305       realpal = rp;
1306       strncpy(colscheme, cols, 251);
1307    }
1308 
1309    if (TranslateColorFormula(colscheme, ErrorMSG)!=0)
1310    {
1311       sprintf(Error, "Strange error:\nPNG-File '%s':\nError in color scheme formula:\n%s\n",
1312 	 pngfile1, ErrorMSG);
1313       fclose(png1);
1314       EndPNG(&png_internal1);
1315       return(-1);
1316    }
1317 
1318    if (calcbase(&cbase, &srbase, view, 0)!= 0)
1319    {
1320       sprintf(Error, "file '%s':\nError in view_struct!\n", pngfile1);
1321       fclose(png1); EndPNG(&png_internal1);
1322       return(-1);
1323    }
1324    rbase = cbase;
1325    if (IsStereo(&view))
1326    {
1327       if (calcbase(&rbase, &srbase, view, 1) != 0)
1328       {
1329 	 sprintf(Error, "file '%s':\nError in view_struct (right eye)!\n", pngfile1);
1330 	 fclose(png1); EndPNG(&png_internal1);
1331 	 return(-1);
1332       }
1333       if (calcbase(&lbase, &slbase, view, -1) != 0)
1334       {
1335 	 sprintf(Error, "file '%s':\nError in view_struct (left eye)!\n", pngfile1);
1336 	 fclose(png1); EndPNG(&png_internal1);
1337 	 return(-1);
1338       }
1339    }
1340 
1341 #ifdef GUI
1342    update_parameters(&frac, &view, &realpal, colscheme, cutbuf);
1343 #else
1344    if (zflag==2 || zflag==1)
1345    {
1346       size_t xres = view.xres;
1347 
1348       xres *= view.antialiasing;
1349       if (IsStereo(&view)) xres *= 2;
1350       TEXTVER_zbuf = calloc((size_t)xres*(size_t)view.yres*(size_t)view.antialiasing*3L, 1);
1351       if (!TEXTVER_zbuf)
1352       {
1353 	 sprintf(Error, "Not enough memory for ZBuffer!");
1354 	 fclose(png1); EndPNG(&png_internal1);
1355 	 return(-1);
1356       }
1357    }
1358 #endif
1359    if (InitGraphics(Error, &view, &rp, ready, &vidinfo, &disppal, &xadd, &yadd, zflag)!=0)
1360       return(-1);
1361 
1362    /* Allocate memory for "CopyIDAT" */
1363    i = view.xres; if (IsStereo(&view)) i *= 2;
1364    if (zflag==1 || zflag==2) i *= view.antialiasing;
1365    line = malloc((size_t)i*3+1);
1366    if (!line)
1367    {
1368       sprintf(Error, "Not enough memory for CopyIDAT");
1369       return(-1);
1370    }
1371    ys = ystart; if (zflag==1 || zflag==2) ys *= view.antialiasing;
1372 
1373    if (zflag==2)
1374    {
1375       if (PNGInitialization(pngfile2, 1, &png2, &png_info2, &png_internal2, 0, 0, 0L, &frac, &view,
1376          &disppal, &realpal, colscheme, cutbuf, zflag))
1377       {
1378          sprintf(Error, "Could not create file '%s'\n", pngfile2);
1379 #ifndef GUI
1380          free(TEXTVER_zbuf);
1381 #endif
1382          return(-1);
1383       }
1384       sprintf(Error, "\nCreated new file '%s'\n", pngfile2);
1385       ystart = 0; xstart = 0;
1386    }
1387 
1388    if (!ready)
1389    {
1390       if (PNGInitialization(pngfile2, 1, &png2, &png_info2, &png_internal2, 0, 0, 0L, &frac, &view,
1391 	 &disppal, &realpal, colscheme, cutbuf, zflag))
1392       {
1393          sprintf(Error, "Could not create file '%s'\n", pngfile2);
1394          return(-1);
1395       }
1396       CopyIDAT(1, /*&disppal, &vidinfo,*/ &png_internal1, &png_internal2, line, ys, zflag, view.zres);
1397       sprintf(Error, "\nCreated new file '%s'\n", pngfile2);
1398    }
1399    else
1400    {
1401       if (zflag==0) CopyIDAT(0, /*&disppal, &vidinfo,*/ &png_internal1, &png_internal2, line, ys, 0, view.zres);
1402       else CopyIDAT(0, /*&disppal, &vidinfo,*/ &png_internal1, &png_internal2, line, ys, 1, view.zres);
1403       if (zflag!=2) Done();
1404    }
1405    free(line);
1406 
1407    i = 0;
1408    if (!ready || zflag==2)
1409    {
1410       fclose(png1);
1411       EndPNG(&png_internal1);
1412       if (zflag==2 && vidinfo.maxcol != -1)
1413       {
1414          InitGraphics(Error, &view, &rp, ready, &vidinfo, &disppal, &xadd,
1415             &yadd, 0);
1416       }
1417       i = CalculateFractal(Error, pngfile2, &png2, /*&png_info2,*/ &png_internal2,
1418          zflag, &xstart, &ystart,/* xadd, yadd,*/ 4, &rbase, &srbase, &lbase, &slbase, &frac, &view, &realpal,
1419 	 /*colscheme,*/ &cutbuf[0], &vidinfo, &disppal);
1420    }
1421    else
1422    {
1423 /*      i = CalculateFractal(Error, pngfile1, &png1, &png_info1, &png_internal1,
1424          zflag, &xstart, &ystart, xadd, yadd, 4, &rbase, &srbase, &lbase, &slbase, &frac, &view, &realpal,
1425          colscheme, &cutbuf[0], &vidinfo, &disppal);  */
1426    }
1427   /* Done();*/
1428 #ifndef GUI
1429    if (zflag==2 || zflag==1) free(TEXTVER_zbuf);
1430 #endif
1431    return(i);
1432 }
1433 
ParseAndCalculate(const char * fil,char * Error,char zflag)1434 int ParseAndCalculate(const char *fil, char *Error, char zflag)
1435 /* file is an ini or a png file, which gets calculated/continued */
1436 /* called by command-line versions (non-Windows), which are given just a file */
1437 /* which can be both ini and png */
1438 {
1439    char inifile[256], pngfile1[256], pngfile2[256], inipath[256];
1440    char *s, *s2, file[256];
1441 
1442    strcpy(inipath, fil);
1443    ConvertPath(inipath);
1444    strcpy(file, inipath);
1445    s = strrchr(inipath, slash);
1446    if (s==NULL) inipath[0]=0;
1447    else *(++s) = 0;
1448    inifile[0]=0;
1449    pngfile1[0]=0;
1450    pngfile2[0]=0;
1451 
1452    /* Check if file is INI-, ZPN- or PNG-file */
1453    if (strncmp(&file[strlen(file)-4], ".png", 4)==0) strncpy(pngfile1, file, 256);
1454    else if (strncmp(&file[strlen(file)-4], ".zpn", 4)==0) strncpy(pngfile1, file, 256);
1455    else strncpy(inifile, file, 256);
1456 
1457    if (inifile[0]!=0)   /* it is an INI file */
1458    {
1459       strncpy(pngfile2, inifile, 256);
1460       /* Make a pointer to the filename (without path) */
1461       if ((s2=strrchr(pngfile2, slash)) == NULL) s2 = pngfile2;
1462       else s2++;
1463       /* Delete suffixes and append .png or .zpn */
1464       if (zflag==0)
1465       {
1466 	 if ((s=strstr(s2, "."))==NULL) strcat(pngfile2, ".png");
1467 	 else strcpy(s, ".png");
1468       }
1469       else if (zflag==1)
1470       {
1471 	 if ((s=strstr(s2, "."))==NULL) strcat(pngfile2, ".zpn");
1472 	 else strcpy(s, ".zpn");
1473       }
1474       /* zflag==2 should never occur here, because file is an ini file */
1475       if (GetNextName(pngfile2, NULL)!=0)
1476       {
1477 	 sprintf(Error, "Couldn't find a free filename based on '%s'\n",pngfile2);
1478 	 return(-1);
1479       }
1480       return(CalculateINI(inifile, pngfile2, Error, zflag));
1481    }
1482    else    /* it�s a PNG */
1483    {
1484       strncpy(pngfile2, pngfile1, 256);
1485       if (GetNextName(pngfile2, NULL)!=0) pngfile2[0]=0;
1486       return(CalculatePNG(pngfile1, pngfile2, Error, "", zflag));
1487    }
1488 }
1489 
ReadParametersAndImage(char * Error,const char * pngf,unsigned char * ready,int * xstart,int * ystart,struct frac_struct * frac,struct view_struct * view,struct realpal_struct * realpal,char * colscheme,double * cutbuf,int zflag)1490 int ReadParametersAndImage(char *Error, const char *pngf,
1491    unsigned char *ready, int *xstart, int *ystart, struct frac_struct *frac, struct view_struct *view,
1492    struct realpal_struct *realpal, char *colscheme, double *cutbuf, int zflag)
1493 /* Opens pngfile, reads parameters from it (no checking if valid)
1494    it initializes graphics and shows image data line per line (using ???_update_bitmap)  */
1495 {
1496    FILE *png;
1497    struct png_info_struct png_info;
1498    struct png_internal_struct png_internal;
1499    struct vidinfo_struct vidinfo;
1500    struct disppal_struct disppal;
1501    int xadd, yadd, i, xres, yr;
1502    struct basestruct base, sbase;
1503    unsigned char *line;
1504    char pngfile[256];
1505 
1506    strcpy(pngfile, pngf); ConvertPath(pngfile);
1507 
1508    SetDefaults(frac, view, realpal, colscheme, cutbuf);
1509 
1510    /* Do PNG-Init for loading */
1511    if ((png = fopen(pngfile, "rb")) == NULL)
1512    {
1513       sprintf(Error, "Cannot open png-file '%s'.'\n", pngfile);
1514       return(-1);
1515    }
1516    if (InitPNG(png, &png_info, &png_internal)==-1)
1517    {
1518       sprintf(Error, "File '%s' is not a valid png-file.\n", pngfile);
1519       fclose(png);
1520       EndPNG(&png_internal);
1521       return(-1);
1522    }
1523    i = ReadParameters(Error, xstart, ystart, &png_internal,
1524       frac, view, realpal, colscheme, cutbuf);
1525    /* if (i==-128) sprintf(Error, "Warning: File version higher than %s.\n",PROGVERSION); */
1526    if (i<0 && i>-128)
1527    {
1528       fclose(png); EndPNG(&png_internal);
1529       return(-1);
1530    }
1531    if (calcbase(&base, &sbase, *view, 0)!= 0)
1532    {
1533       fclose(png); EndPNG(&png_internal);
1534       sprintf(Error, "file '%s':\nError in view_struct!\n",pngfile);
1535       return(-1);
1536    }
1537    if (*ystart==view->yres) *ready = 1; else *ready = 0;
1538    xres = view->xres; if (IsStereo(view)) xres *= 2;
1539    if (zflag==1) xres *= view->antialiasing;
1540    line = malloc((size_t)xres*3+1);
1541    if (!line)
1542    {
1543       sprintf(Error, "Not enough memory to hold a line");
1544       fclose(png); EndPNG(&png_internal);
1545       return(-1);
1546    }
1547    if (InitGraphics(Error, view, realpal, *ready, &vidinfo, &disppal, &xadd, &yadd, zflag)!=0)
1548    {
1549       free(line); fclose(png); EndPNG(&png_internal);
1550       return(-1);
1551    }
1552    yr = *ystart;
1553    if (zflag==1) yr *= view->antialiasing;
1554    if (CopyIDAT(0, /*&disppal, &vidinfo,*/ &png_internal, NULL, line, yr, zflag, view->zres)!=0)
1555    {
1556       free(line); fclose(png); EndPNG(&png_internal);
1557       sprintf(Error, "Error reading file '%s'.", pngfile);
1558       return(-1);
1559    }
1560    free(line);
1561    fclose(png);
1562    EndPNG(&png_internal);
1563    return(0);
1564 }
1565 
SavePNG(char * Error,const char * pngf,int xstart,int ystart,struct disppal_struct * disppal,struct frac_struct * f,struct view_struct * v,struct realpal_struct * realpal,char * colscheme,double * cutbuf,int zflag)1566 int SavePNG(char *Error, const char *pngf, int xstart, int ystart,
1567    struct disppal_struct *disppal, struct frac_struct *f, struct view_struct *v,
1568    struct realpal_struct *realpal, char *colscheme, double *cutbuf, int zflag)
1569 {
1570    FILE *png;
1571    struct png_info_struct png_info;
1572    struct png_internal_struct png_internal;
1573    struct frac_struct frac;
1574    struct view_struct view;
1575 /*   basestruct base, sbase; */
1576    unsigned char *line, dummy;
1577    int xres, yres, i;
1578    char pngfile[256];
1579 
1580    strcpy(pngfile, pngf); ConvertPath(pngfile);
1581 
1582    if (ystart < 0) ystart = 0;	/* Else bug when saving empty image. */
1583 
1584    frac = *f; view = *v;
1585    xres = v->xres; if (IsStereo(v)) xres *= 2;
1586    if (zflag == 1) xres *= view.antialiasing;
1587    yres = v->yres; if (zflag == 1) yres *= view.antialiasing;
1588    line = malloc((size_t)xres*3+2);
1589    if (!line)
1590    {
1591       sprintf(Error, "Not enough memory to save a line.");
1592       return(-1);
1593    }
1594 
1595    if (PNGInitialization(pngfile, 1, &png, &png_info, &png_internal, xstart, ystart, calc_time,
1596       &frac, &view, disppal, realpal, colscheme, cutbuf, zflag))
1597    {
1598       sprintf(Error, "Error writing file '%s'\n", pngfile);
1599       free(line);
1600       return(-1);
1601    }
1602 
1603    for (i=0; i<yres; i++)
1604    {
1605       QU_getline(&line[1], i, xres, zflag);
1606       line[0] = 0; /* Set filter method */
1607       DoFiltering(&png_internal, line);
1608       if (WritePNGLine(&png_internal, line))
1609       {
1610 	 sprintf(Error, "Error writing file '%s'\n", pngfile);
1611 	 EndPNG(&png_internal);
1612 	 free(line);
1613 	 return(-1);
1614       }
1615    }
1616 
1617    i = EndIDAT(&png_internal);
1618    png_internal.length = 0;
1619    strncpy(png_internal.chunk_type, "IEND", 4);
1620    i += WriteChunk(&png_internal, &dummy);
1621    i += fclose(png);
1622    EndPNG(&png_internal);
1623    free(line);
1624 
1625    if (i!=0)
1626    {
1627       sprintf(Error, "Error writing file '%s'\n", pngfile);
1628       return(-1);
1629    }
1630 
1631    return(0);
1632 }
1633 
BuildName(char * name,char * namewop,const char * ext,const char * file,char * Error)1634 int BuildName(char *name, char *namewop, const char *ext, const char *file, char *Error)
1635 {
1636    char *c;
1637 
1638    strncpy(name, file, 256); c = strrchr(name, '.');
1639    if (c) strcpy(c, ext); else strcat(name, ext);
1640    if (GetNextName(name, namewop))
1641    {
1642       sprintf(Error, "Couldn't find a free filename based on '%s'.\n", name);
1643       return(-1);
1644    }
1645    return(0);
1646 }
1647 
CleanNumberString(char * s)1648 int CleanNumberString(char *s)
1649 {
1650    int i;
1651 
1652    if (strrchr(s,'.')!=NULL)
1653    {
1654       i = strlen(s)-1;
1655       while (s[i]=='0') i--;
1656       s[i+1] = 0;
1657       if (s[i]=='.') s[i] = 0;
1658    }
1659    if (strlen(s) == 0) strcpy(s, "0");
1660    return(0);
1661 }
1662 
ReadParametersPNG(const char * fil,char * Error,struct frac_struct * frac,struct view_struct * view,struct realpal_struct * realpal,char * colscheme,double * cutbuf)1663 int ReadParametersPNG(const char *fil, char *Error, struct frac_struct *frac, struct view_struct *view,
1664    struct realpal_struct *realpal, char *colscheme, double *cutbuf)
1665 {
1666    FILE *png;
1667    struct png_info_struct png_info;
1668    struct png_internal_struct png_internal;
1669    int xstart, ystart;
1670    int i;
1671    struct basestruct base, sbase;
1672    char file[256];
1673 
1674    strcpy(file, fil); ConvertPath(file);
1675 
1676    SetDefaults(frac, view, realpal, colscheme, cutbuf);
1677    if ((png = fopen(file, "rb")) == NULL)
1678    {
1679       sprintf(Error, "Cannot open png-file '%s'.'", file);
1680       return(-1);
1681    }
1682    if (InitPNG(png, &png_info, &png_internal)==-1)
1683    {
1684       sprintf(Error, "File '%s' is not a valid png-file.", file);
1685       fclose(png);
1686       EndPNG(&png_internal);
1687       return(-1);
1688    }
1689    i = ReadParameters(Error, &xstart, &ystart, &png_internal, frac, view, realpal, colscheme, cutbuf);
1690    /* if (i==-128) sprintf(Error, "Warning: File version higher than %s.",PROGVERSION); */
1691    if (i<0 && i>-128) return(-1);
1692 
1693    if (calcbase(&base, &sbase, *view, 0)!= 0)
1694    {
1695       sprintf(Error, "Strange error in '%s'\nError in view_struct!",file);
1696       return(-1);
1697    }
1698    fclose(png);
1699    EndPNG(&png_internal);
1700 
1701    return(0);
1702 }
1703 
WriteINI(char * Error,const char * fil,int mode,struct frac_struct * frac,struct view_struct * view,struct realpal_struct * realpal,char * colscheme,double * cut_buf)1704 int WriteINI(char *Error, const char *fil, int mode, struct frac_struct *frac, struct view_struct *view,
1705    struct realpal_struct *realpal, char *colscheme, double *cut_buf)
1706 {
1707    FILE *txt;
1708    int i, pos;
1709    vec3 n, p;
1710    char s1[30], s2[30], s3[30], s4[30], s5[30], s6[30], s7[30];
1711    char file[256];
1712 
1713    strcpy(file, fil); ConvertPath(file);
1714 
1715    if ((txt = fopen(file, "w")) == NULL)
1716    {
1717       sprintf(Error, "Could not create file '%s'.",file);
1718       return(-1);
1719    }
1720    fprintf(txt, "# This file was generated by '%s %s'.\n\n", PROGNAME, PROGVERSION);
1721    if ((mode & PS_OTHER)!=0)
1722    {
1723       fprintf(txt, "resolution %i %i %i\n", view->xres, view->yres, view->zres);
1724       sprintf(s1, "%.15f", view->phongmax); CleanNumberString(s1);
1725       sprintf(s2, "%.15f", view->phongsharp); CleanNumberString(s2);
1726       sprintf(s3, "%.15f", view->ambient); CleanNumberString(s3);
1727       fprintf(txt, "phong %s %s\nambient %s\n", s1, s2, s3);
1728       fprintf(txt, "antialiasing %i\n", view->antialiasing);
1729    }
1730 
1731    if ((mode & PS_OBJ)!=0)
1732    {
1733       fprintf(txt, "\n# OBJ\n");
1734       sprintf(s1, "%.15f", frac->c[0]); CleanNumberString(s1);
1735       sprintf(s2, "%.15f", frac->c[1]); CleanNumberString(s2);
1736       sprintf(s3, "%.15f", frac->c[2]); CleanNumberString(s3);
1737       sprintf(s4, "%.15f", frac->c[3]); CleanNumberString(s4);
1738       fprintf(txt, "c %s %s %s %s\n\n", s1, s2, s3, s4);
1739       sprintf(s1, "%.15f", frac->bailout); CleanNumberString(s1);
1740       sprintf(s2, "%.15f", frac->lvalue); CleanNumberString(s2);
1741       fprintf(txt, "bailout %s\nmaxiter %i\nlvalue %s\nformula %i\n\n",
1742 	 s1, frac->maxiter, s2, frac->formula);
1743       for (i=0; i<4; ++i) {
1744 		sprintf(s1, "%.15f", frac->p[i][0]); CleanNumberString(s1);
1745 		sprintf(s2, "%.15f", frac->p[i][1]); CleanNumberString(s2);
1746 		sprintf(s3, "%.15f", frac->p[i][2]); CleanNumberString(s3);
1747 		sprintf(s4, "%.15f", frac->p[i][3]); CleanNumberString(s4);
1748 		fprintf(txt, "p%i %s %s %s %s\n", i+1, s1, s2, s3, s4);
1749       }
1750       fprintf(txt, "\n");
1751 
1752    }
1753    if ((mode & PS_VIEW)!=0)
1754    {
1755       sprintf(s1, "%.15f", view->s[0]); CleanNumberString(s1);
1756       sprintf(s2, "%.15f", view->s[1]); CleanNumberString(s2);
1757       sprintf(s3, "%.15f", view->s[2]); CleanNumberString(s3);
1758       fprintf(txt, "viewpoint %s %s %s\n", s1, s2, s3);
1759       sprintf(s1, "%.15f", view->up[0]); CleanNumberString(s1);
1760       sprintf(s2, "%.15f", view->up[1]); CleanNumberString(s2);
1761       sprintf(s3, "%.15f", view->up[2]); CleanNumberString(s3);
1762       fprintf(txt, "up %s %s %s\n", s1, s2, s3);
1763       sprintf(s1, "%.15f", view->light[0]); CleanNumberString(s1);
1764       sprintf(s2, "%.15f", view->light[1]); CleanNumberString(s2);
1765       sprintf(s3, "%.15f", view->light[2]); CleanNumberString(s3);
1766       fprintf(txt, "light %s %s %s\n\n", s1, s2, s3);
1767       sprintf(s1, "%.15f", view->Mov[0]); CleanNumberString(s1);
1768       sprintf(s2, "%.15f", view->Mov[1]); CleanNumberString(s2);
1769       sprintf(s3, "%.15f", view->LXR); CleanNumberString(s3);
1770       sprintf(s4, "%.15f", view->interocular); CleanNumberString(s4);
1771       fprintf(txt, "move %s %s\nlxr %s\ninterocular %s\n\n", s1, s2, s3, s4);
1772    }
1773    if ((mode & PS_COL)!=0)
1774    {
1775       fprintf(txt, "# COL\n");
1776       fprintf(txt, "colorscheme %s\n", colscheme);
1777       for (i=0; i<realpal->colnum; i++)
1778       {
1779 	 sprintf(s1, "%.15f", realpal->cols[i].weight); CleanNumberString(s1);
1780 	 sprintf(s2, "%.15f", realpal->cols[i].col1[0]); CleanNumberString(s2);
1781 	 sprintf(s3, "%.15f", realpal->cols[i].col1[1]); CleanNumberString(s3);
1782 	 sprintf(s4, "%.15f", realpal->cols[i].col1[2]); CleanNumberString(s4);
1783 	 if (realpal->cols[i].col1[0]==realpal->cols[i].col2[0]
1784 	    && realpal->cols[i].col1[1]==realpal->cols[i].col2[1]
1785 	    && realpal->cols[i].col1[2]==realpal->cols[i].col2[2])
1786 	    fprintf(txt, "color  %s   %s %s %s\n", s1, s2, s3, s4);
1787 	 else
1788 	 {
1789 	    sprintf(s5, "%.15f", realpal->cols[i].col2[0]); CleanNumberString(s5);
1790 	    sprintf(s6, "%.15f", realpal->cols[i].col2[1]); CleanNumberString(s6);
1791 	    sprintf(s7, "%.15f", realpal->cols[i].col2[2]); CleanNumberString(s7);
1792 	    fprintf(txt, "colorrange %s   %s %s %s    %s %s %s\n", s1, s2, s3, s4, s5, s6, s7);
1793 	 }
1794       }
1795    }
1796    if (*(char *)&cut_buf[0]!=CUT_TERMINATOR && ((mode & PS_OTHER)!=0))
1797    {
1798       fprintf(txt, "\n# Intersection\n");
1799       pos = 0;
1800       while (*(char *)&cut_buf[pos]!=CUT_TERMINATOR)
1801       {
1802 	 switch (*(char *)&cut_buf[pos])
1803 	 {
1804 	    case CUT_PLANE:
1805 	       forall(i,3) n[i] = cut_buf[pos+i+1];
1806 	       forall(i,3) p[i] = cut_buf[pos+i+4];
1807 	       pos += 7;
1808 	       sprintf(s1, "%.15f", n[0]); CleanNumberString(s1);
1809 	       sprintf(s2, "%.15f", n[1]); CleanNumberString(s2);
1810 	       sprintf(s3, "%.15f", n[2]); CleanNumberString(s3);
1811 	       sprintf(s4, "%.15f", p[0]); CleanNumberString(s4);
1812 	       sprintf(s5, "%.15f", p[1]); CleanNumberString(s5);
1813 	       sprintf(s6, "%.15f", p[2]); CleanNumberString(s6);
1814 	       fprintf(txt, "plane  %s %s %s   %s %s %s\n", s1, s2, s3, s4, s5, s6);
1815 	       break;
1816 	    default : pos++;
1817 	 }
1818       }
1819    }
1820    fclose(txt);
1821    return(0);
1822 }
1823 
GetParameters(const char * afile,char * Error)1824 int GetParameters(const char *afile, char *Error)
1825 {
1826    char file[256], ini[256], *filewop;
1827    struct frac_struct frac;
1828    struct view_struct view;
1829    struct realpal_struct realpal;
1830    char colscheme[251];
1831    double cutbuf[140];
1832 
1833    strcpy(file, afile); ConvertPath(file);
1834 /*   for (i=0; i<(int)strlen(afile)+1; i++) file[i] = tolower((int)afile[i]);
1835 */
1836    filewop = strrchr(file, slash);
1837    if (filewop==NULL) filewop = file; else filewop++;
1838 
1839    if (ReadParametersPNG(file, Error, &frac, &view, &realpal, colscheme, &cutbuf[0])!=0)
1840       return(-1);
1841 
1842    if (BuildName(ini, NULL, ".ini", filewop, Error)) return(-1);
1843    if (!WriteINI(Error, ini, PS_OTHER | PS_OBJ | PS_VIEW | PS_COL,
1844       &frac, &view, &realpal, colscheme, cutbuf))
1845       sprintf(Error, "Generated file '%s'.", ini);
1846    else return(-1);
1847    return(0);
1848 }
1849 
ImgFromZBuf(const char * file,const char * file2,char * Error)1850 int ImgFromZBuf(const char *file, const char *file2, char *Error)
1851 /* file is a ZBuffer, which gets turned into an image */
1852 /* called by command-line versions (non-Windows), which are given just a file */
1853 {
1854    char zpnfile[256], pngfile[256];
1855    char *s, *s2;
1856 
1857    strcpy(zpnfile, file); ConvertPath(zpnfile);
1858    strcpy(pngfile, zpnfile);
1859 /*   i = i;
1860    strncpy(zpnpath, file, 256);
1861    s = strrchr(zpnpath, '/');
1862    if (s==NULL) zpnpath[0]=0;
1863    else *(++s) = 0; */
1864 /*   zpnfile[0]=0;
1865    pngfile[0]=0;
1866 */
1867 
1868 /*   strncpy(zpnfile, file, 256);
1869    strncpy(pngfile, file, 256);
1870 */
1871    /* Make a pointer to the filename (without path) */
1872    if ((s2=strrchr(pngfile, slash)) == NULL) s2 = pngfile;
1873    else s2++;
1874    /* Delete suffixes and append .png */
1875    if ((s=strstr(s2, "."))==NULL) strcat(pngfile, ".png");
1876    else strcpy(s, ".png");
1877    if (GetNextName(pngfile, NULL)!=0)
1878    {
1879       sprintf(Error, "Couldn't find a free filename based on '%s'\n",pngfile);
1880       return(-1);
1881    }
1882 
1883    return(CalculatePNG(zpnfile, pngfile, Error, file2, 2));
1884 }
1885 
1886