home *** CD-ROM | disk | FTP | other *** search
/ Media Share 9 / MEDIASHARE_09.ISO / progmisc / frasrc18.zip / GIFVIEW.C < prev    next >
C/C++ Source or Header  |  1993-01-12  |  9KB  |  363 lines

  1. /*
  2.  *
  3.  * This GIF decoder is designed for use with the FRACTINT program.
  4.  * This decoder code lacks full generality in the following respects:
  5.  * supports non-interlaced GIF files only, and calmly ignores any
  6.  * local color maps and non-Fractint-specific extension blocks.
  7.  *
  8.  * GIF and 'Graphics Interchange Format' are trademarks (tm) of
  9.  * Compuserve, Incorporated, an H&R Block Company.
  10.  *
  11.  *                                            Tim Wegner
  12.  */
  13.  
  14. #include <stdio.h>
  15. #include <string.h>
  16. #ifndef XFRACT
  17. #include <dos.h>
  18. #endif
  19. #include "fractint.h"
  20. #include "prototyp.h"
  21.  
  22. static void close_file(void);
  23.  
  24. #define MAXCOLORS    256
  25.  
  26. extern int rowcount;        /* row counter for screen */
  27. extern char readname[];     /* file name          */
  28. static FILE *fpin = NULL;    /* FILE pointer       */
  29. unsigned int height;
  30. extern    char busy;
  31. unsigned numcolors;
  32.  
  33. extern char MAP_name[];
  34. extern int mapset;
  35. extern int colorstate;        /* comments in cmdfiles */
  36.  
  37. extern int colors;
  38. extern int glassestype;
  39. extern int display3d;
  40. extern int dotmode;        /* so we can detect disk-video */
  41. extern int calc_status;
  42. extern long calctime;
  43. extern long timer_interval;
  44. extern int pot16bit;        /* 16 bit values for continuous potential */
  45. extern int dither_flag;
  46.  
  47. extern int (*outln)();
  48. static int out_line_dither(BYTE *, int);
  49. static int out_line_migs(BYTE *, int);
  50.  
  51. int bad_code_count = 0;     /* needed by decoder module */
  52.  
  53. extern short skipxdots; /* 0 to get every dot, 1 for every 2nd, 2 every 3rd, ... */
  54. extern short skipydots; /* ditto for rows */
  55. unsigned int far gifview_image_top;    /* (for migs) */
  56. unsigned int far gifview_image_left;    /* (for migs) */
  57. unsigned int far gifview_image_twidth;    /* (for migs) */
  58.  
  59. int get_byte()
  60. {
  61.    return (getc(fpin)); /* EOF is -1, as desired */
  62. }
  63.  
  64. int get_bytes(BYTE *where,int how_many)
  65. {
  66.    return (fread((char *)where,1,how_many,fpin)); /* EOF is -1, as desired */
  67. }
  68.  
  69. extern BYTE dacbox[256][3];    /* Video-DAC (filled in by SETVIDEO) */
  70. #ifndef XFRACT
  71. extern BYTE decoderline[MAXPIXELS+1]; /* write-line routines use this */
  72. #else
  73. BYTE decoderline[MAXPIXELS+1]; /* write-line routines use this */
  74. #endif
  75.  
  76. static int ditherlen = -1;
  77. static char far *ditherbuf = NULL;
  78.  
  79. /* Main entry decoder */
  80.  
  81. void decoder_overlay() { }    /* for restore_active_ovly */
  82.  
  83. int gifview1()
  84. {
  85.    BYTE buffer[16];
  86.    unsigned top, left, width, finished;
  87.    char temp1[81];
  88.  
  89.    int status;
  90.    int i, j, k, planes;
  91.  
  92.    ENTER_OVLY(OVLY_DECODER);
  93.  
  94.    status = 0;
  95.  
  96.    /* initialize the row count for write-lines */
  97.    rowcount = 0;
  98.  
  99.    /* zero out the full write-line */
  100.    for (width = 0; width < MAXPIXELS+1; width++) decoderline[width] = 0;
  101.  
  102.    /* Open the file */
  103.    strcpy(temp1,readname);
  104.    if (strchr(temp1,'.') == NULL) {
  105.       strcat(temp1,DEFAULTFRACTALTYPE);
  106.       if ((fpin = fopen(temp1,"rb")) != NULL) {
  107.      fclose(fpin);
  108.      }
  109.       else {
  110.      strcpy(temp1,readname);
  111.      strcat(temp1,ALTERNATEFRACTALTYPE);
  112.      }
  113.       }
  114.    if ((fpin = fopen(temp1, "rb")) == NULL) {
  115.       EXIT_OVLY;
  116.       return (-1);
  117.       }
  118.  
  119.    /* Get the screen description */
  120.    for (i = 0; i < 13; i++)
  121.    {
  122.       int tmp;
  123.  
  124.       buffer[i] = tmp = get_byte();
  125.       if (tmp < 0)
  126.       {
  127.      close_file();
  128.          EXIT_OVLY;
  129.      return(-1);
  130.       }
  131.    }
  132.  
  133.    if(strncmp(buffer,"GIF87a",3) ||             /* use updated GIF specs */
  134.       buffer[3] < '0' || buffer[3] > '9' ||
  135.       buffer[4] < '0' || buffer[4] > '9' ||
  136.       buffer[5] < 'A' || buffer[5] > 'z' )
  137.    {
  138.       close_file();
  139.       EXIT_OVLY;
  140.       return(-1);
  141.    }
  142.  
  143.    width  = buffer[6] | (buffer[7] << 8);
  144.    height = buffer[8] | (buffer[9] << 8);
  145.    planes = (buffer[10] & 0x0F) + 1;
  146.    gifview_image_twidth = width;
  147.  
  148.    if((buffer[10] & 0x80)==0)     /* color map (better be!) */
  149.    {
  150.       close_file();
  151.       EXIT_OVLY;
  152.       return(-1);
  153.    }
  154.    numcolors = 1 << planes;
  155.  
  156.    if (dither_flag && numcolors>2 && colors==2 && outln==out_line) {
  157.      outln = out_line_dither;
  158.    }
  159.  
  160.  
  161.    for (i = 0; i < numcolors; i++)
  162.    {
  163.       for (j = 0; j < 3; j++) {
  164.      if ((k = get_byte()) < 0)
  165.      {
  166.         close_file();
  167.             EXIT_OVLY;
  168.         return(-1);
  169.      }
  170.      if(!display3d || (glassestype != 1 && glassestype != 2))
  171.         dacbox[i][j] = k >> 2;
  172.       }
  173.    }
  174.    colorstate = 1; /* colors aren't default and not a known .map file */
  175.  
  176.    /* don't read if glasses */
  177.    if (display3d && mapset && glassestype!=1 && glassestype != 2)
  178.    {
  179.        ValidateLuts(MAP_name);    /* read the palette file */
  180.        spindac(0,1); /* load it, but don't spin */
  181.    }
  182.    if (dacbox[0][0] != 255)
  183.       spindac(0,1);      /* update the DAC */
  184.  
  185.    if (dotmode == 11) /* disk-video */
  186.        dvid_status(1,"...restoring...");
  187.  
  188.    /* Now display one or more GIF objects */
  189.    finished = 0;
  190.    while (!finished)
  191.    {
  192.       switch (get_byte())
  193.       {
  194.       case ';':
  195.      /* End of the GIF dataset */
  196.  
  197.      finished = 1;
  198.      status = 0;
  199.      break;
  200.  
  201.       case '!':                               /* GIF Extension Block */
  202.      get_byte();             /* read (and ignore) the ID */
  203.      while ((i = get_byte()) > 0)     /* get the data length */
  204.         for (j = 0; j < i; j++)
  205.            get_byte();     /* flush the data */
  206.      break;
  207.       case ',':
  208.      /*
  209.       * Start of an image object. Read the image description.
  210.       */
  211.  
  212.      for (i = 0; i < 9; i++)
  213.      {
  214.             int tmp;
  215.  
  216.             buffer[i] = tmp = get_byte();
  217.         if (tmp < 0)
  218.         {
  219.            status = -1;
  220.            break;
  221.         }
  222.      }
  223.      if(status < 0)
  224.      {
  225.         finished = 1;
  226.         break;
  227.      }
  228.  
  229.      left    = buffer[0] | (buffer[1] << 8);
  230.      top    = buffer[2] | (buffer[3] << 8);
  231.      width    = buffer[4] | (buffer[5] << 8);
  232.      if (pot16bit) width >>= 1;
  233.      height = buffer[6] | (buffer[7] << 8);
  234.  
  235.          /* adjustments for handling MIGs */
  236.          gifview_image_top  = top;
  237.          if (skipxdots > 0)
  238.              gifview_image_top /= (skipydots+1);
  239.          gifview_image_left = left;
  240.          if (skipydots > 0)
  241.              gifview_image_left /= (skipxdots+1);
  242.          if (outln==out_line &&
  243.              (width != gifview_image_twidth || top != 0)) {
  244.               /* we're using normal decoding and we have a MIG */
  245.          outln = out_line_migs;
  246.              }
  247.  
  248.          /* Skip local color palette */
  249.          if((buffer[8] & 0x80)==0x80) {      /* local map? */
  250.              int numcolors;    /* make this local */
  251.              planes = (buffer[8] & 0x0F) + 1;
  252.              numcolors = 1 << planes;
  253.              /* skip local map */
  254.              for (i = 0; i < numcolors; i++) {
  255.                 for (j = 0; j < 3; j++) {
  256.                    if ((k = get_byte()) < 0) {
  257.                       close_file();
  258.                       return(-1);
  259.                       }
  260.                    }
  261.                 }
  262.              }
  263.  
  264.          /* initialize the row count for write-lines */
  265.          rowcount = 0;
  266.  
  267.          /* zero out the full write-line */
  268.          {
  269.          int i;
  270.          for (i = 0; i < MAXPIXELS+1; i++) decoderline[i] = 0;
  271.          }
  272.  
  273.      if (calc_status == 1) /* should never be so, but make sure */
  274.         calc_status = 0;
  275.      busy = 1;    /* for slideshow CALCWAIT */
  276.      status = timer(1,NULL,width); /* call decoder(width) via timer */
  277.      busy = 0;    /* for slideshow CALCWAIT */
  278.      if (calc_status == 1) /* e.g., set by line3d */
  279.      {
  280.         calctime = timer_interval; /* note how long it took */
  281.         if (keypressed() != 0) {
  282.            calc_status = 3; /* interrupted, not resumable */
  283.                finished = 1;
  284.            }
  285.         else
  286.            calc_status = 4; /* complete */
  287.      }
  288.          /* Hey! the decoder doesn't read the last (0-length) block!! */
  289.          if (get_byte() != 0) {
  290.              status = -1;
  291.              finished = 1;
  292.              }
  293.      break;
  294.       default:
  295.      status = -1;
  296.      finished = 1;
  297.      break;
  298.       }
  299.    }
  300.    close_file();
  301.    if (dotmode == 11) { /* disk-video */
  302.       dvid_status(0,"Restore completed");
  303.       dvid_status(1,"");
  304.       }
  305.       
  306.     if (ditherbuf != NULL) { /* we're done, free dither memory */
  307.         farmemfree(ditherbuf);
  308.         ditherbuf = NULL;
  309.     }
  310.  
  311.    EXIT_OVLY;
  312.    return(status);
  313. }
  314.  
  315. static void close_file()
  316. {
  317.    fclose(fpin);
  318.    fpin = NULL;
  319. }
  320.  
  321. /* routine for MIGS that generates partial output lines */
  322.  
  323. static out_line_migs(BYTE *pixels, int linelen)
  324. {
  325. int row, startcol, stopcol;
  326.  
  327. row = gifview_image_top + rowcount;
  328. startcol = gifview_image_left;
  329. stopcol = startcol+linelen-1;
  330. put_line(row, startcol, stopcol, pixels);
  331. rowcount++;
  332.  
  333. }
  334.  
  335.  
  336. static int out_line_dither(pixels, linelen)
  337. BYTE *pixels;
  338. int linelen;
  339. {
  340.     int i,nexterr,brt,err;
  341.     if(ditherbuf == NULL)
  342.         ditherbuf = (char far *)farmemalloc(linelen+1);
  343.     far_memset( ditherbuf, 0, linelen+1); 
  344.  
  345.     nexterr = (rand15()&0x1f)-16;
  346.     for (i=0;i<linelen;i++) {
  347.     brt = (dacbox[pixels[i]][0]*5+dacbox[pixels[i]][1]*9 +
  348.         dacbox[pixels[i]][2]*2)>>4; /* brightness from 0 to 63 */
  349.     brt += nexterr;
  350.     if (brt>32) {
  351.         pixels[i] = 1;
  352.         err = brt-63;
  353.     } else {
  354.         pixels[i] = 0;
  355.         err = brt;
  356.     }
  357.     nexterr = ditherbuf[i+1]+err/3;
  358.     ditherbuf[i] = err/3;
  359.     ditherbuf[i+1] = err/3;
  360.     }
  361.     return out_line(pixels, linelen);
  362. }
  363.