File: common\encoder.c

    1 /*
    2         encoder.c - GIF Encoder and associated routines
    3 */
    4 
    5 #include <string.h>
    6 #include <limits.h>
    7 #ifndef XFRACT
    8 #include <io.h>
    9 #endif
   10   /* see Fractint.c for a description of the "include"  hierarchy */
   11 #include "port.h"
   12 #include "prototyp.h"
   13 #include "fractype.h"
   14 
   15 static int compress(int rowlimit);
   16 static int _fastcall shftwrite(BYTE far * color, int numcolors);
   17 static int _fastcall extend_blk_len(int datalen);
   18 static int _fastcall put_extend_blk(int block_id, int block_len, char far * block_data);
   19 static int _fastcall store_item_name(char *);
   20 static void _fastcall setup_save_info(struct fractal_info far * save_info);
   21 
   22 /*
   23                         Save-To-Disk Routines (GIF)
   24 
   25 The following routines perform the GIF encoding when the 's' key is pressed.
   26 
   27 The compression logic in this file has been replaced by the classic
   28 UNIX compress code. We have extensively modified the sources to fit
   29 Fractint's needs, but have left the original credits where they
   30 appear. Thanks to the original authors for making available these
   31 classic and reliable sources. Of course, they are not responsible for 
   32 all the changes we have made to integrate their sources into Fractint.
   33 
   34 MEMORY ALLOCATION
   35 
   36 There are two large arrays:
   37 
   38    long htab[HSIZE]              (5003*4 = 20012 bytes)
   39    unsigned short codetab[HSIZE] (5003*2 = 10006 bytes)
   40    
   41 At the moment these arrays reuse extraseg and strlocn, respectively.
   42 
   43 */
   44 
   45 static int numsaves = 0;        /* For adjusting 'save-to-disk' filenames */
   46 static FILE *g_outfile;
   47 static int last_colorbar;
   48 static int save16bit;
   49 static int outcolor1s, outcolor2s;
   50 static int startbits;
   51 
   52 static BFCODE paletteBW[] =
   53 {                               /* B&W palette */
   54    0, 0, 0, 63, 63, 63,
   55 };
   56 
   57 #ifndef XFRACT
   58 static BFCODE paletteCGA[] =
   59 {                               /* 4-color (CGA) palette  */
   60    0, 0, 0, 21, 63, 63, 63, 21, 63, 63, 63, 63,
   61 };
   62 #endif
   63 
   64 static BFCODE paletteEGA[] =
   65 {                               /* 16-color (EGA/CGA) pal */
   66    0, 0, 0, 0, 0, 42, 0, 42, 0, 0, 42, 42,
   67    42, 0, 0, 42, 0, 42, 42, 21, 0, 42, 42, 42,
   68    21, 21, 21, 21, 21, 63, 21, 63, 21, 21, 63, 63,
   69    63, 21, 21, 63, 21, 63, 63, 63, 21, 63, 63, 63,
   70 };
   71 
   72 int savetodisk(char *filename)      /* save-to-disk routine */
   73 {
   74    char tmpmsg[41];                 /* before openfile in case of overrun */
   75    char openfile[FILE_MAX_PATH], openfiletype[10];
   76    char tmpfile[FILE_MAX_PATH];
   77    char *period;
   78    int newfile;
   79    int i, j, interrupted, outcolor1, outcolor2;
   80 restart:
   81 
   82    save16bit = disk16bit;
   83    if (gif87a_flag)             /* not storing non-standard fractal info */
   84       save16bit = 0;
   85 
   86    strcpy(openfile, filename);  /* decode and open the filename */
   87    strcpy(openfiletype, DEFAULTFRACTALTYPE);    /* determine the file
   88                                                  * extension */
   89    if (save16bit)
   90       strcpy(openfiletype, ".pot");
   91 
   92    if ((period = has_ext(openfile)) != NULL)
   93    {
   94       strcpy(openfiletype, period);
   95       *period = 0;
   96    }
   97    if (resave_flag != 1)
   98       updatesavename(filename); /* for next time */
   99 
  100    strcat(openfile, openfiletype);
  101 
  102    strcpy(tmpfile, openfile);
  103    if (access(openfile, 0) != 0)/* file doesn't exist */
  104       newfile = 1;
  105    else
  106    {                                  /* file already exists */
  107       static FCODE fractint_tmp[] = {"fractint.tmp"};
  108       if (overwrite == 0)
  109       {
  110          if (resave_flag == 0)
  111             goto restart;
  112          if (started_resaves == 0)
  113          {                      /* first save of a savetime set */
  114             updatesavename(filename);
  115             goto restart;
  116          }
  117       }
  118       if (access(openfile, 2) != 0)
  119       {
  120          sprintf(tmpmsg, s_cantwrite, openfile);
  121          stopmsg(0, tmpmsg);
  122          return -1;
  123       }
  124       newfile = 0;
  125       i = strlen(tmpfile);
  126       while (--i >= 0 && tmpfile[i] != SLASHC)
  127          tmpfile[i] = 0;
  128       far_strcat(tmpfile, fractint_tmp);
  129    }
  130 
  131    started_resaves = (resave_flag == 1) ? 1 : 0;
  132    if (resave_flag == 2)        /* final save of savetime set? */
  133       resave_flag = 0;
  134 
  135    if ((g_outfile = fopen(tmpfile, "wb")) == NULL)
  136    {
  137       sprintf(tmpmsg, s_cantcreate, tmpfile);
  138       stopmsg(0, tmpmsg);
  139       return -1;
  140    }
  141 
  142    if (dotmode == 11)
  143    {                            /* disk-video */
  144       char buf[61];
  145       extract_filename(tmpmsg, openfile);
  146 
  147       sprintf(buf, "Saving %s", tmpmsg);
  148       dvid_status(1, buf);
  149    }
  150 #ifdef XFRACT
151 else 152 { 153 putstring(3, 0, 0, "Saving to:"); 154 putstring(4, 0, 0, openfile); 155 putstring(5, 0, 0, " "); 156 }
157 #endif 158 159 busy = 1; 160 161 if (debugflag != 200) 162 interrupted = encoder(); 163 else 164 interrupted = timer(2, NULL); /* invoke encoder() via timer */ 165 166 busy = 0; 167 168 fclose(g_outfile); 169 170 if (interrupted) 171 { 172 static FCODE s_delete[] = 173 {"delete the file,\ncontinue to keep the partial image."}; 174 static FCODE s_retain[] = 175 {"retain the original file,\ncontinue to replace original with new partial image."}; 176 177 char buf[200]; 178 sprintf(buf, "Save of %s interrupted.\nCancel to ", openfile); 179 if (newfile) 180 far_strcat(buf,s_delete); 181 else 182 far_strcat(buf,s_retain); 183 interrupted = 1; 184 if (stopmsg(2, buf) < 0) 185 { 186 interrupted = -1; 187 unlink(tmpfile); 188 } 189 } 190 191 if (newfile == 0 && interrupted >= 0) 192 { /* replace the real file */ 193 unlink(openfile); /* success assumed since we checked */ 194 rename(tmpfile, openfile);/* earlier with access */ 195 } 196 197 if (dotmode != 11) 198 { /* supress this on disk-video */ 199 if (active_system == 0) 200 { /* no bars in Windows version */ 201 outcolor1 = outcolor1s; 202 outcolor2 = outcolor2s; 203 for (j = 0; j <= last_colorbar; j++) 204 { 205 if ((j & 4) == 0) 206 { 207 if (++outcolor1 >= colors) 208 outcolor1 = 0; 209 if (++outcolor2 >= colors) 210 outcolor2 = 0; 211 } 212 for (i = 0; 250 * i < xdots; i++) 213 { /* clear vert status bars */ 214 putcolor(i, j, getcolor(i, j) ^ outcolor1); 215 putcolor(xdots - 1 - i, j, 216 getcolor(xdots - 1 - i, j) ^ outcolor2); 217 } 218 } 219 } 220 #ifdef XFRACT
221 putstring(5, 0, 0, "Saving done\n");
222 #endif 223 } 224 else /* disk-video */ 225 dvid_status(1, ""); 226 227 if (interrupted) 228 { 229 static FCODE msg[] = {" *interrupted* save "}; 230 texttempmsg(msg); 231 if (initbatch >= 1) 232 initbatch = 3; /* if batch mode, set error level */ 233 return -1; 234 } 235 if (timedsave == 0) 236 { 237 buzzer(0); 238 if (initbatch == 0) 239 { 240 extract_filename(tmpfile, openfile); 241 sprintf(tmpmsg, " File saved as %s ", tmpfile); 242 texttempmsg(tmpmsg); 243 } 244 } 245 if (initsavetime < 0) 246 goodbye(); 247 return 0; 248 } 249 250 int encoder() 251 { 252 int i, width, rowlimit, interrupted; 253 BYTE bitsperpixel, x; 254 struct fractal_info save_info; 255 256 if (initbatch) /* flush any impending keystrokes */ 257 while (keypressed()) 258 getakey(); 259 260 setup_save_info(&save_info); 261 262 #ifndef XFRACT 263 bitsperpixel = 0; /* calculate bits / pixel */ 264 for (i = colors; i >= 2; i /= 2) 265 bitsperpixel++; 266 267 startbits = bitsperpixel + 1;/* start coding with this many bits */ 268 if (colors == 2) 269 startbits++; /* B&W Klooge */
270 #else 271 if (colors == 2) 272 { 273 bitsperpixel = 1; 274 startbits = 3; 275 } 276 else 277 { 278 bitsperpixel = 8; 279 startbits = 9; 280 }
281 #endif 282 283 if (gif87a_flag == 1) 284 { 285 if (fwrite("GIF87a", 6, 1, g_outfile) != 1) 286 goto oops; /* old GIF Signature */ 287 } 288 else 289 { 290 if (fwrite("GIF89a", 6, 1, g_outfile) != 1) 291 goto oops; /* new GIF Signature */ 292 } 293 294 width = xdots; 295 rowlimit = ydots; 296 if (save16bit) 297 { 298 /* pot16bit info is stored as: file: double width rows, right side 299 * of row is low 8 bits diskvid: ydots rows of colors followed by ydots 300 * rows of low 8 bits decoder: returns (row of color info then row of 301 * low 8 bits) * ydots */ 302 rowlimit <<= 1; 303 width <<= 1; 304 } 305 if (write2(&width, 2, 1, g_outfile) != 1) 306 goto oops; /* screen descriptor */ 307 if (write2(&ydots, 2, 1, g_outfile) != 1) 308 goto oops; 309 x = (BYTE) (128 + ((6 - 1) << 4) + (bitsperpixel - 1)); /* color resolution == 6 310 * bits worth */ 311 if (write1(&x, 1, 1, g_outfile) != 1) 312 goto oops; 313 if (fputc(0, g_outfile) != 0) 314 goto oops; /* background color */ 315 i = 0; 316 317 if (viewwindow /* less than full screen? */ 318 && (viewxdots == 0 || viewydots == 0)) /* and we picked the dots? */ 319 i = (int) (((double) sydots / (double) sxdots) * 64.0 / screenaspect - 14.5); 320 else /* must risk loss of precision if numbers low */ 321 i = (int) ((((double) ydots / (double) xdots) / finalaspectratio) * 64 - 14.5); 322 if (i < 1) 323 i = 1; 324 if (i > 255) 325 i = 255; 326 if (gif87a_flag) 327 i = 0; /* for some decoders which can't handle 328 * aspect */ 329 if (fputc(i, g_outfile) != i) 330 goto oops; /* pixel aspect ratio */ 331 332 #ifndef XFRACT 333 if (colors == 256) 334 { /* write out the 256-color palette */ 335 if (gotrealdac) 336 { /* got a DAC - must be a VGA */ 337 if (!shftwrite((BYTE far *) dacbox, colors)) 338 goto oops;
339 #else 340 if (colors > 2) 341 { 342 if (gotrealdac || fake_lut) 343 { /* got a DAC - must be a VGA */ 344 if (!shftwrite((BYTE far *) dacbox, 256)) 345 goto oops;
346 #endif 347 } 348 else 349 { /* uh oh - better fake it */ 350 for (i = 0; i < 256; i += 16) 351 if (!shftwrite((BYTE far *)paletteEGA, 16)) 352 goto oops; 353 } 354 } 355 if (colors == 2) 356 { /* write out the B&W palette */ 357 if (!shftwrite((BYTE far *)paletteBW, colors)) 358 goto oops; 359 } 360 #ifndef XFRACT 361 if (colors == 4) 362 { /* write out the CGA palette */ 363 if (!shftwrite((BYTE far *)paletteCGA, colors)) 364 goto oops; 365 } 366 if (colors == 16) 367 { /* Either EGA or VGA */ 368 if (gotrealdac) 369 { 370 if (!shftwrite((BYTE *) dacbox, colors)) 371 goto oops; 372 } 373 else 374 { /* no DAC - must be an EGA */ 375 if (!shftwrite((BYTE far *)paletteEGA, colors)) 376 goto oops; 377 } 378 } 379 #endif 380 381 if (fwrite(",", 1, 1, g_outfile) != 1) 382 goto oops; /* Image Descriptor */ 383 i = 0; 384 if (write2(&i, 2, 1, g_outfile) != 1) 385 goto oops; 386 if (write2(&i, 2, 1, g_outfile) != 1) 387 goto oops; 388 if (write2(&width, 2, 1, g_outfile) != 1) 389 goto oops; 390 if (write2(&ydots, 2, 1, g_outfile) != 1) 391 goto oops; 392 if (write1(&i, 1, 1, g_outfile) != 1) 393 goto oops; 394 395 bitsperpixel = (BYTE) (startbits - 1); 396 397 if (write1(&bitsperpixel, 1, 1, g_outfile) != 1) 398 goto oops; 399 400 interrupted = compress(rowlimit); 401 402 if(ferror(g_outfile)) 403 goto oops; 404 405 if (fputc(0, g_outfile) != 0) 406 goto oops; 407 408 if (gif87a_flag == 0) 409 { /* store non-standard fractal info */ 410 /* loadfile.c has notes about extension block structure */ 411 if (interrupted) 412 save_info.calc_status = 0; /* partial save is not resumable */ 413 save_info.tot_extend_len = 0; 414 if (resume_info != 0 && save_info.calc_status == 2) 415 { 416 /* resume info block, 002 */ 417 save_info.tot_extend_len += extend_blk_len(resume_len); 418 MoveFromMemory((BYTE *)block,(U16)1,(long)resume_len,0,resume_info); 419 if (!put_extend_blk(2, resume_len, (char far *)block)) 420 goto oops; 421 } 422 /* save_info.fractal_type gets modified in setup_save_info() in float only 423 version, so we need to use fractype. JCO 06JAN01 */ 424 /* if (save_info.fractal_type == FORMULA || save_info.fractal_type == FFORMULA) */ 425 if (fractype == FORMULA || fractype == FFORMULA) 426 save_info.tot_extend_len += store_item_name(FormName); 427 /* if (save_info.fractal_type == LSYSTEM) */ 428 if (fractype == LSYSTEM) 429 save_info.tot_extend_len += store_item_name(LName); 430 /* if (save_info.fractal_type == IFS || save_info.fractal_type == IFS3D) */ 431 if (fractype == IFS || fractype == IFS3D) 432 save_info.tot_extend_len += store_item_name(IFSName); 433 if (display3d <= 0 && rangeslen) 434 { 435 /* ranges block, 004 */ 436 save_info.tot_extend_len += extend_blk_len(rangeslen * 2); 437 #ifdef XFRACT
438 fix_ranges(ranges, rangeslen, 0);
439 #endif 440 if (!put_extend_blk(4, rangeslen * 2, (char far *) ranges)) 441 goto oops; 442 443 } 444 /* Extended parameters block 005 */ 445 if (bf_math) 446 { 447 save_info.tot_extend_len += extend_blk_len(22 * (bflength + 2)); 448 /* note: this assumes variables allocated in order starting with 449 * bfxmin in init_bf2() in BIGNUM.C */ 450 if (!put_extend_blk(5, 22 * (bflength + 2), (char far *) bfxmin)) 451 goto oops; 452 } 453 454 /* Extended parameters block 006 */ 455 if (evolving&1) 456 { 457 struct evolution_info esave_info; 458 int i; 459 struct evolution_info resume_e_info; 460 GENEBASE gene[NUMGENES]; 461 MoveFromMemory((BYTE *)&gene, (U16)sizeof(gene), 1L, 0L, gene_handle); 462 if (evolve_handle == 0 || calc_status == 4) { 463 esave_info.paramrangex = paramrangex; 464 esave_info.paramrangey = paramrangey; 465 esave_info.opx = opx; 466 esave_info.opy = opy; 467 esave_info.odpx = (short)odpx; 468 esave_info.odpy = (short)odpy; 469 esave_info.px = (short)px; 470 esave_info.py = (short)py; 471 esave_info.sxoffs = (short)sxoffs; 472 esave_info.syoffs = (short)syoffs; 473 esave_info.xdots = (short)xdots; 474 esave_info.ydots = (short)ydots; 475 esave_info.gridsz = (short)gridsz; 476 esave_info.evolving = (short)evolving; 477 esave_info.this_gen_rseed = (unsigned short)this_gen_rseed; 478 esave_info.fiddlefactor = fiddlefactor; 479 esave_info.ecount = (short) (gridsz * gridsz); /* flag for done */ 480 } 481 else { /* we will need the resuming information */ 482 MoveFromMemory((BYTE *)&resume_e_info,(U16)sizeof(resume_e_info),1L,0L,evolve_handle); 483 esave_info.paramrangex = resume_e_info.paramrangex; 484 esave_info.paramrangey = resume_e_info.paramrangey; 485 esave_info.opx = resume_e_info.opx; 486 esave_info.opy = resume_e_info.opy; 487 esave_info.odpx = (short)resume_e_info.odpx; 488 esave_info.odpy = (short)resume_e_info.odpy; 489 esave_info.px = (short)resume_e_info.px; 490 esave_info.py = (short)resume_e_info.py; 491 esave_info.sxoffs = (short)resume_e_info.sxoffs; 492 esave_info.syoffs = (short)resume_e_info.syoffs; 493 esave_info.xdots = (short)resume_e_info.xdots; 494 esave_info.ydots = (short)resume_e_info.ydots; 495 esave_info.gridsz = (short)resume_e_info.gridsz; 496 esave_info.evolving = (short)resume_e_info.evolving; 497 esave_info.this_gen_rseed = (unsigned short)resume_e_info.this_gen_rseed; 498 esave_info.fiddlefactor = resume_e_info.fiddlefactor; 499 esave_info.ecount = resume_e_info.ecount; 500 } 501 for (i = 0; i < NUMGENES; i++) 502 esave_info.mutate[i] = (short)gene[i].mutate; 503 504 for (i = 0; i < sizeof(esave_info.future) / sizeof(short); i++) 505 esave_info.future[i] = 0; 506 507 /* some XFRACT logic for the doubles needed here */ 508 #ifdef XFRACT
509 decode_evolver_info(&esave_info, 0);
510 #endif 511 /* evolution info block, 006 */ 512 save_info.tot_extend_len += extend_blk_len(sizeof(esave_info)); 513 if (!put_extend_blk(6, sizeof(esave_info), (char far *) &esave_info)) 514 goto oops; 515 } 516 517 /* Extended parameters block 007 */ 518 if (stdcalcmode == 'o') 519 { 520 struct orbits_info osave_info; 521 int i; 522 osave_info.oxmin = oxmin; 523 osave_info.oxmax = oxmax; 524 osave_info.oymin = oymin; 525 osave_info.oymax = oymax; 526 osave_info.ox3rd = ox3rd; 527 osave_info.oy3rd = oy3rd; 528 osave_info.keep_scrn_coords= (short)keep_scrn_coords; 529 osave_info.drawmode = drawmode; 530 for (i = 0; i < sizeof(osave_info.future) / sizeof(short); i++) 531 osave_info.future[i] = 0; 532 533 /* some XFRACT logic for the doubles needed here */ 534 #ifdef XFRACT
535 decode_orbits_info(&osave_info, 0);
536 #endif 537 /* orbits info block, 007 */ 538 save_info.tot_extend_len += extend_blk_len(sizeof(osave_info)); 539 if (!put_extend_blk(7, sizeof(osave_info), (char far *) &osave_info)) 540 goto oops; 541 } 542 543 /* main and last block, 001 */ 544 save_info.tot_extend_len += extend_blk_len(FRACTAL_INFO_SIZE); 545 #ifdef XFRACT
546 decode_fractal_info(&save_info, 0);
547 #endif 548 if (!put_extend_blk(1, FRACTAL_INFO_SIZE, (char far *) &save_info)) 549 { 550 goto oops; 551 } 552 } 553 554 if (fwrite(";", 1, 1, g_outfile) != 1) 555 goto oops; /* GIF Terminator */ 556 557 return (interrupted); 558 559 oops: 560 { 561 static FCODE msg[] = {"Error Writing to disk (Disk full?)"}; 562 fflush(g_outfile); 563 stopmsg(0,msg); 564 return 1; 565 } 566 } 567 568 /* shift IBM colors to GIF */ 569 static int _fastcall shftwrite(BYTE far * color, int numcolors) 570 { 571 BYTE thiscolor; 572 int i, j; 573 for (i = 0; i < numcolors; i++) 574 for (j = 0; j < 3; j++) 575 { 576 thiscolor = color[3 * i + j]; 577 thiscolor = (BYTE) (thiscolor << 2); 578 thiscolor = (BYTE) (thiscolor + (BYTE) (thiscolor >> 6)); 579 if (fputc(thiscolor, g_outfile) != (int) thiscolor) 580 return (0); 581 } 582 return (1); 583 } 584 585 static int _fastcall extend_blk_len(int datalen) 586 { 587 return (datalen + (datalen + 254) / 255 + 15); 588 /* data + 1.per.block + 14 for id + 1 for null at end */ 589 } 590 591 static int _fastcall put_extend_blk(int block_id, int block_len, char far * block_data) 592 { 593 int i, j; 594 char header[15]; 595 strcpy(header, "!\377\013fractint"); 596 sprintf(&header[11], "%03u", block_id); 597 if (fwrite(header, 14, 1, g_outfile) != 1) 598 return (0); 599 i = (block_len + 254) / 255; 600 while (--i >= 0) 601 { 602 block_len -= (j = min(block_len, 255)); 603 if (fputc(j, g_outfile) != j) 604 return (0); 605 while (--j >= 0) 606 fputc(*(block_data++), g_outfile); 607 } 608 if (fputc(0, g_outfile) != 0) 609 return (0); 610 return (1); 611 } 612 613 static int _fastcall store_item_name(char *nameptr) 614 { 615 struct formula_info fsave_info; 616 int i; 617 for (i = 0; i < 40; i++) 618 fsave_info.form_name[i] = 0; /* initialize string */ 619 strcpy(fsave_info.form_name, nameptr); 620 if (fractype == FORMULA || fractype == FFORMULA) 621 { 622 fsave_info.uses_p1 = (short) uses_p1; 623 fsave_info.uses_p2 = (short) uses_p2; 624 fsave_info.uses_p3 = (short) uses_p3; 625 fsave_info.uses_ismand = (short) uses_ismand; 626 fsave_info.ismand = (short) ismand; 627 fsave_info.uses_p4 = (short) uses_p4; 628 fsave_info.uses_p5 = (short) uses_p5; 629 } 630 else 631 { 632 fsave_info.uses_p1 = 0; 633 fsave_info.uses_p2 = 0; 634 fsave_info.uses_p3 = 0; 635 fsave_info.uses_ismand = 0; 636 fsave_info.ismand = 0; 637 fsave_info.uses_p4 = 0; 638 fsave_info.uses_p5 = 0; 639 } 640 for (i = 0; i < sizeof(fsave_info.future) / sizeof(short); i++) 641 fsave_info.future[i] = 0; 642 /* formula/lsys/ifs info block, 003 */ 643 put_extend_blk(3, sizeof(fsave_info), (char far *) &fsave_info); 644 return (extend_blk_len(sizeof(fsave_info))); 645 } 646 647 static void _fastcall setup_save_info(struct fractal_info far * save_info) 648 { 649 int i; 650 if (fractype != FORMULA && fractype != FFORMULA) 651 maxfn = 0; 652 /* set save parameters in save structure */ 653 far_strcpy(save_info->info_id, INFO_ID); 654 save_info->version = VERSION; 655 656 if (maxit <= SHRT_MAX) 657 save_info->iterationsold = (short) maxit; 658 else 659 save_info->iterationsold = (short) SHRT_MAX; 660 661 save_info->fractal_type = (short) fractype; 662 save_info->xmin = xxmin; 663 save_info->xmax = xxmax; 664 save_info->ymin = yymin; 665 save_info->ymax = yymax; 666 save_info->creal = param[0]; 667 save_info->cimag = param[1]; 668 save_info->videomodeax = (short) videoentry.videomodeax; 669 save_info->videomodebx = (short) videoentry.videomodebx; 670 save_info->videomodecx = (short) videoentry.videomodecx; 671 save_info->videomodedx = (short) videoentry.videomodedx; 672 save_info->dotmode = (short) (videoentry.dotmode % 100); 673 save_info->xdots = (short) videoentry.xdots; 674 save_info->ydots = (short) videoentry.ydots; 675 save_info->colors = (short) videoentry.colors; 676 save_info->parm3 = 0; /* pre version==7 fields */ 677 save_info->parm4 = 0; 678 save_info->dparm3 = param[2]; 679 save_info->dparm4 = param[3]; 680 save_info->dparm5 = param[4]; 681 save_info->dparm6 = param[5]; 682 save_info->dparm7 = param[6]; 683 save_info->dparm8 = param[7]; 684 save_info->dparm9 = param[8]; 685 save_info->dparm10 = param[9]; 686 save_info->fillcolor = (short) fillcolor; 687 save_info->potential[0] = (float) potparam[0]; 688 save_info->potential[1] = (float) potparam[1]; 689 save_info->potential[2] = (float) potparam[2]; 690 save_info->rflag = (short) rflag; 691 save_info->rseed = (short) rseed; 692 save_info->inside = (short) inside; 693 if (LogFlag <= SHRT_MAX) 694 save_info->logmapold = (short) LogFlag; 695 else 696 save_info->logmapold = (short) SHRT_MAX; 697 save_info->invert[0] = (float) inversion[0]; 698 save_info->invert[1] = (float) inversion[1]; 699 save_info->invert[2] = (float) inversion[2]; 700 save_info->decomp[0] = (short) decomp[0]; 701 save_info->biomorph = (short) usr_biomorph; 702 save_info->symmetry = (short) forcesymmetry; 703 for (i = 0; i < 16; i++) 704 save_info->init3d[i] = (short) init3d[i]; 705 save_info->previewfactor = (short) previewfactor; 706 save_info->xtrans = (short) xtrans; 707 save_info->ytrans = (short) ytrans; 708 save_info->red_crop_left = (short) red_crop_left; 709 save_info->red_crop_right = (short) red_crop_right; 710 save_info->blue_crop_left = (short) blue_crop_left; 711 save_info->blue_crop_right = (short) blue_crop_right; 712 save_info->red_bright = (short) red_bright; 713 save_info->blue_bright = (short) blue_bright; 714 save_info->xadjust = (short) xadjust; 715 save_info->yadjust = (short) yadjust; 716 save_info->eyeseparation = (short) eyeseparation; 717 save_info->glassestype = (short) glassestype; 718 save_info->outside = (short) outside; 719 save_info->x3rd = xx3rd; 720 save_info->y3rd = yy3rd; 721 save_info->calc_status = (short) calc_status; 722 save_info->stdcalcmode = (char) ((three_pass && stdcalcmode == '3') ? 127 : stdcalcmode); 723 if (distest <= 32000) 724 save_info->distestold = (short) distest; 725 else 726 save_info->distestold = 32000; 727 save_info->floatflag = floatflag; 728 if (bailout >= 4 && bailout <= 32000) 729 save_info->bailoutold = (short) bailout; 730 else 731 save_info->bailoutold = 0; 732 733 save_info->calctime = calctime; 734 save_info->trigndx[0] = trigndx[0]; 735 save_info->trigndx[1] = trigndx[1]; 736 save_info->trigndx[2] = trigndx[2]; 737 save_info->trigndx[3] = trigndx[3]; 738 save_info->finattract = (short) finattract; 739 save_info->initorbit[0] = initorbit.x; 740 save_info->initorbit[1] = initorbit.y; 741 save_info->useinitorbit = useinitorbit; 742 save_info->periodicity = (short) periodicitycheck; 743 save_info->pot16bit = (short) disk16bit; 744 save_info->faspectratio = finalaspectratio; 745 save_info->system = (short) save_system; 746 747 if (check_back()) 748 save_info->release = (short) min(save_release, release); 749 else 750 save_info->release = (short) release; 751 752 save_info->flag3d = (short) display3d; 753 save_info->ambient = (short) Ambient; 754 save_info->randomize = (short) RANDOMIZE; 755 save_info->haze = (short) haze; 756 save_info->transparent[0] = (short) transparent[0]; 757 save_info->transparent[1] = (short) transparent[1]; 758 save_info->rotate_lo = (short) rotate_lo; 759 save_info->rotate_hi = (short) rotate_hi; 760 save_info->distestwidth = (short) distestwidth; 761 save_info->mxmaxfp = mxmaxfp; 762 save_info->mxminfp = mxminfp; 763 save_info->mymaxfp = mymaxfp; 764 save_info->myminfp = myminfp; 765 save_info->zdots = (short) zdots; 766 save_info->originfp = originfp; 767 save_info->depthfp = depthfp; 768 save_info->heightfp = heightfp; 769 save_info->widthfp = widthfp; 770 save_info->distfp = distfp; 771 save_info->eyesfp = eyesfp; 772 save_info->orbittype = (short) neworbittype; 773 save_info->juli3Dmode = (short) juli3Dmode; 774 save_info->maxfn = maxfn; 775 save_info->inversejulia = (short) ((major_method << 8) + minor_method); /* MVS */ 776 save_info->bailout = bailout; 777 save_info->bailoutest = (short) bailoutest; 778 save_info->iterations = maxit; 779 save_info->bflength = (short) bnlength; 780 save_info->bf_math = (short) bf_math; 781 save_info->old_demm_colors = (short) old_demm_colors; 782 save_info->logmap = LogFlag; 783 save_info->distest = distest; 784 save_info->dinvert[0] = inversion[0]; 785 save_info->dinvert[1] = inversion[1]; 786 save_info->dinvert[2] = inversion[2]; 787 save_info->logcalc = (short) Log_Fly_Calc; 788 save_info->stoppass = (short) stoppass; 789 save_info->quick_calc = (short) quick_calc; 790 save_info->closeprox = closeprox; 791 save_info->nobof = (short) nobof; 792 save_info->orbit_interval = orbit_interval; 793 save_info->orbit_delay = (short) orbit_delay; 794 save_info->math_tol[0] = math_tol[0]; 795 save_info->math_tol[1] = math_tol[1]; 796 for (i = 0; i < sizeof(save_info->future) / sizeof(short); i++) 797 save_info->future[i] = 0; 798 799 } 800 801 /*************************************************************************** 802 * 803 * GIFENCOD.C - GIF Image compression routines 804 * 805 * Lempel-Ziv compression based on 'compress'. GIF modifications by 806 * David Rowley (mgardi@watdcsu.waterloo.edu). 807 * Thoroughly massaged by the Stone Soup team for Fractint's purposes. 808 * 809 ***************************************************************************/ 810 811 #define BITSF 12 812 #define HSIZE 5003 /* 80% occupancy */ 813 814 /* 815 * 816 * GIF Image compression - modified 'compress' 817 * 818 * Based on: compress.c - File compression ala IEEE Computer, June 1984. 819 * 820 * By Authors: Spencer W. Thomas (decvax!harpo!utah-cs!utah-gr!thomas) 821 * Jim McKie (decvax!mcvax!jim) 822 * Steve Davies (decvax!vax135!petsd!peora!srd) 823 * Ken Turkowski (decvax!decwrl!turtlevax!ken) 824 * James A. Woods (decvax!ihnp4!ames!jaw) 825 * Joe Orost (decvax!vax135!petsd!joe) 826 * 827 */ 828 829 /* prototypes */ 830 831 static void _fastcall output(int code); 832 static void _fastcall char_out(int c); 833 static void _fastcall flush_char(void); 834 static void _fastcall cl_block(void); 835 836 static int n_bits; /* number of bits/code */ 837 static int maxbits = BITSF; /* user settable max # bits/code */ 838 static int maxcode; /* maximum code, given n_bits */ 839 static int maxmaxcode = (int)1 << BITSF; /* should NEVER generate this code */ 840 # define MAXCODE(n_bits) (((int) 1 << (n_bits)) - 1) 841 842 #ifdef XFRACT
843 unsigned int strlocn[10240]; 844 BYTE block[4096];
845 #endif 846 847 static long far *htab; 848 static unsigned short *codetab = (unsigned short *)strlocn; 849 850 /* 851 * To save much memory, we overlay the table used by compress() with those 852 * used by decompress(). The tab_prefix table is the same size and type 853 * as the codetab. The tab_suffix table needs 2**BITSF characters. We 854 * get this from the beginning of htab. The output stack uses the rest 855 * of htab, and contains characters. There is plenty of room for any 856 * possible stack (stack used to be 8000 characters). 857 */ 858 859 #define tab_prefixof(i) codetab[i] 860 #define tab_suffixof(i) ((char_type far *)(htab))[i] 861 #define de_stack ((char_type far *)&tab_suffixof((int)1<<BITSF)) 862 863 static int free_ent; /* first unused entry */ 864 865 /* 866 * block compression parameters -- after all codes are used up, 867 * and compression rate changes, start over. 868 */ 869 static int clear_flg = 0; 870 871 /* 872 * compress stdin to stdout 873 * 874 * Algorithm: use open addressing double hashing (no chaining) on the 875 * prefix code / next character combination. We do a variant of Knuth's 876 * algorithm D (vol. 3, sec. 6.4) along with G. Knott's relatively-prime 877 * secondary probe. Here, the modular division first probe is gives way 878 * to a faster exclusive-or manipulation. Also do block compression with 879 * an adaptive reset, whereby the code table is cleared when the compression 880 * ratio decreases, but after the table fills. The variable-length output 881 * codes are re-sized at this point, and a special CLEAR code is generated 882 * for the decompressor. Late addition: construct the table according to 883 * file size for noticeable speed improvement on small files. Please direct 884 * questions about this implementation to ames!jaw. 885 */ 886 887 static int ClearCode; 888 static int EOFCode; 889 static int a_count; /* Number of characters so far in this 'packet' */ 890 static unsigned long cur_accum = 0; 891 static int cur_bits = 0; 892 893 /* 894 * Define the storage for the packet accumulator 895 */ 896 static char *accum; /* 256 bytes */ 897 898 static int compress(int rowlimit) 899 { 900 int outcolor1, outcolor2; 901 long fcode; 902 int i = 0; 903 int ent; 904 int disp; 905 int hsize_reg; 906 int hshift; 907 int ydot, xdot, color; 908 int rownum; 909 int in_count = 0; 910 int interrupted = 0; 911 int tempkey; 912 char accum_stack[256]; 913 accum = accum_stack; 914 htab = (long far *)MK_FP(extraseg,0); 915 916 outcolor1 = 0; /* use these colors to show progress */ 917 outcolor2 = 1; /* (this has nothing to do with GIF) */ 918 919 if (colors > 2) 920 { 921 outcolor1 = 2; 922 outcolor2 = 3; 923 } 924 if (((++numsaves) & 1) == 0) 925 { /* reverse the colors on alt saves */ 926 i = outcolor1; 927 outcolor1 = outcolor2; 928 outcolor2 = i; 929 } 930 outcolor1s = outcolor1; 931 outcolor2s = outcolor2; 932 933 /* 934 * Set up the necessary values 935 */ 936 cur_accum = 0; 937 cur_bits = 0; 938 clear_flg = 0; 939 ydot = 0; 940 ent = 0; 941 maxcode = MAXCODE(n_bits = startbits); 942 943 ClearCode = (1 << (startbits - 1)); 944 EOFCode = ClearCode + 1; 945 free_ent = ClearCode + 2; 946 947 a_count = 0; 948 hshift = 0; 949 for (fcode = (long) HSIZE; fcode < 65536L; fcode *= 2L) 950 hshift++; 951 hshift = 8 - hshift; /* set hash code range bound */ 952 953 far_memset(htab,0xff,(unsigned)HSIZE*sizeof(long)); 954 hsize_reg = HSIZE; 955 956 output((int)ClearCode); 957 958 for (rownum = 0; rownum < ydots; rownum++) 959 { /* scan through the dots */ 960 for (ydot = rownum; ydot < rowlimit; ydot += ydots) 961 { 962 for (xdot = 0; xdot < xdots; xdot++) 963 { 964 if (save16bit == 0 || ydot < ydots) 965 color = getcolor(xdot, ydot); 966 else 967 color = readdisk(xdot + sxoffs, ydot + syoffs); 968 if(in_count == 0) 969 { 970 in_count = 1; 971 ent = color; 972 continue; 973 } 974 fcode = (long) (((long) color << maxbits) + ent); 975 i = (((int)color << hshift) ^ ent); /* xor hashing */ 976 977 if (htab[i] == fcode) 978 { 979 ent = codetab[i]; 980 continue; 981 } else if ((long)htab[i] < 0) /* empty slot */ 982 goto nomatch; 983 disp = hsize_reg - i; /* secondary hash (after G. Knott) */ 984 if (i == 0) 985 disp = 1; 986 probe: 987 if ((i -= disp) < 0) 988 i += hsize_reg; 989 990 if (htab[i] == fcode) 991 { 992 ent = codetab[i]; 993 continue; 994 } 995 if ((long)htab[i] > 0) 996 goto probe; 997 nomatch: 998 output ((int) ent); 999 ent = color; 1000 if (free_ent < maxmaxcode) 1001 { 1002 /* code -> hashtable */ 1003 codetab[i] = (unsigned short)free_ent++; 1004 htab[i] = fcode; 1005 } 1006 else 1007 cl_block(); 1008 } /* end for xdot */ 1009 if (dotmode != 11 /* supress this on disk-video */ 1010 && active_system == 0 /* and in Windows version */ 1011 && ydot == rownum) 1012 { 1013 if ((ydot & 4) == 0) 1014 { 1015 if (++outcolor1 >= colors) 1016 outcolor1 = 0; 1017 if (++outcolor2 >= colors) 1018 outcolor2 = 0; 1019 } 1020 for (i = 0; 250 * i < xdots; i++) 1021 { /* display vert status bars */ 1022 /* (this is NOT GIF-related) */ 1023 putcolor(i, ydot, getcolor(i, ydot) ^ outcolor1); 1024 putcolor(xdots - 1 - i, ydot, 1025 getcolor(xdots - 1 - i, ydot) ^ outcolor2); 1026 } 1027 last_colorbar = ydot; 1028 } /* end if dotmode != 11 */ 1029 tempkey = keypressed(); 1030 if (tempkey && (tempkey != (int)'s')) /* keyboard hit - bail out */ 1031 { 1032 interrupted = 1; 1033 rownum = ydots; 1034 break; 1035 } 1036 if (tempkey == (int)'s') 1037 getakey(); /* eat the keystroke */ 1038 } /* end for ydot */ 1039 } /* end for rownum */ 1040 1041 /* 1042 * Put out the final code. 1043 */ 1044 output((int)ent); 1045 output((int) EOFCode); 1046 return (interrupted); 1047 } 1048 1049 /***************************************************************** 1050 * TAG(output) 1051 * 1052 * Output the given code. 1053 * Inputs: 1054 * code: A n_bits-bit integer. If == -1, then EOF. This assumes 1055 * that n_bits =< (long)wordsize - 1. 1056 * Outputs: 1057 * Outputs code to the file. 1058 * Assumptions: 1059 * Chars are 8 bits long. 1060 * Algorithm: 1061 * Maintain a BITSF character long buffer (so that 8 codes will 1062 * fit in it exactly). Use the VAX insv instruction to insert each 1063 * code in turn. When the buffer fills up empty it and start over. 1064 */ 1065 1066 1067 static void _fastcall output(int code) 1068 { 1069 static ULFCODE masks[] = 1070 { 0x0000, 0x0001, 0x0003, 0x0007, 0x000F, 1071 0x001F, 0x003F, 0x007F, 0x00FF, 1072 0x01FF, 0x03FF, 0x07FF, 0x0FFF, 1073 0x1FFF, 0x3FFF, 0x7FFF, 0xFFFF }; 1074 1075 cur_accum &= masks[ cur_bits ]; 1076 1077 if(cur_bits > 0) 1078 cur_accum |= ((long)code << cur_bits); 1079 else 1080 cur_accum = code; 1081 1082 cur_bits += n_bits; 1083 1084 while(cur_bits >= 8) 1085 { 1086 char_out((unsigned int)(cur_accum & 0xff)); 1087 cur_accum >>= 8; 1088 cur_bits -= 8; 1089 } 1090 1091 /* 1092 * If the next entry is going to be too big for the code size, 1093 * then increase it, if possible. 1094 */ 1095 if (free_ent > maxcode || clear_flg) 1096 { 1097 if(clear_flg) 1098 { 1099 maxcode = MAXCODE (n_bits = startbits); 1100 clear_flg = 0; 1101 1102 } 1103 else 1104 { 1105 n_bits++; 1106 if (n_bits == maxbits) 1107 maxcode = maxmaxcode; 1108 else 1109 maxcode = MAXCODE(n_bits); 1110 } 1111 } 1112 1113 if(code == EOFCode) 1114 { 1115 /* 1116 * At EOF, write the rest of the buffer. 1117 */ 1118 while(cur_bits > 0) 1119 { 1120 char_out((unsigned int)(cur_accum & 0xff)); 1121 cur_accum >>= 8; 1122 cur_bits -= 8; 1123 } 1124 1125 flush_char(); 1126 1127 fflush(g_outfile); 1128 } 1129 } 1130 1131 /* 1132 * Clear out the hash table 1133 */ 1134 static void _fastcall cl_block(void) /* table clear for block compress */ 1135 { 1136 far_memset(htab,0xff,(unsigned)HSIZE*sizeof(long)); 1137 free_ent = ClearCode + 2; 1138 clear_flg = 1; 1139 output((int)ClearCode); 1140 } 1141 1142 /* 1143 * Add a character to the end of the current packet, and if it is 254 1144 * characters, flush the packet to disk. 1145 */ 1146 static void _fastcall char_out(int c) 1147 { 1148 accum[ a_count++ ] = (char)c; 1149 if(a_count >= 254) 1150 flush_char(); 1151 } 1152 1153 /* 1154 * Flush the packet to disk, and reset the accumulator 1155 */ 1156 static void _fastcall flush_char(void) 1157 { 1158 if(a_count > 0) { 1159 fputc(a_count, g_outfile); 1160 fwrite(accum, 1, a_count, g_outfile); 1161 a_count = 0; 1162 } 1163 } 1164