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(¬def, &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