home *** CD-ROM | disk | FTP | other *** search
/ Source Code 1992 March / Source_Code_CD-ROM_Walnut_Creek_March_1992.iso / usenet / altsrcs / 2 / 2313 / evdisp.c next >
C/C++ Source or Header  |  1990-12-28  |  14KB  |  574 lines

  1. /*
  2.  *      Load a GIF image file into an Environ V window
  3.  * evgif.c  -  derived almost entirely from :-
  4.  *
  5.  * gif2ras.c - Converts from a Compuserve GIF (tm) image to a Sun Raster image.
  6.  *
  7.  * Copyright (c) 1988, 1989 by Patrick J. Naughton
  8.  *
  9.  * Author: Patrick J. Naughton
  10.  * naughton@wind.sun.com
  11.  *
  12.  * Permission to use, copy, modify, and distribute this software and its
  13.  * documentation for any purpose and without fee is hereby granted,
  14.  * provided that the above copyright notice appear in all copies and that
  15.  * both that copyright notice and this permission notice appear in
  16.  * supporting documentation.
  17.  *
  18.  * This file is provided AS IS with no warranties of any kind.  The author
  19.  * shall have no liability with respect to the infringement of copyrights,
  20.  * trade secrets or any patents by this file or any part thereof.  In no
  21.  * event will the author be liable for any lost revenue or profits or
  22.  * other special, indirect and consequential damages.
  23.  *
  24.  */
  25.  
  26. #include "evgif.h"
  27.  
  28. #define BOOLEAN int
  29.  
  30. #define NEXTBYTE (*ptr++)
  31. #define IMAGESEP 0x2c
  32. #define INTERLACEMASK 0x40
  33. #define COLORMAPMASK 0x80
  34.  
  35. FILE *fp;
  36.  
  37. int BitOffset = 0,        /* Bit Offset of next code */
  38.     XC = 0, YC = 0,        /* Output X and Y coords of current pixel */
  39.     Pass = 0,            /* Used by output routine if interlaced pic */
  40.     OutCount = 0,        /* Decompressor output 'stack count' */
  41.     RWidth, RHeight,        /* screen dimensions */
  42.     Width, Height,        /* image dimensions */
  43.     LeftOfs, TopOfs,        /* image offset */
  44.     BitsPerPixel,        /* Bits per pixel, read from GIF header */
  45.     BytesPerScanline,        /* bytes per scanline in output raster */
  46.     ColorMapSize,        /* number of colors */
  47.     Background,            /* background color */
  48.     CodeSize,            /* Code size, read from GIF header */
  49.     InitCodeSize,        /* Starting code size, used during Clear */
  50.     Code,            /* Value returned by ReadCode */
  51.     MaxCode,            /* limiting value for current code size */
  52.     ClearCode,            /* GIF clear code */
  53.     EOFCode,            /* GIF end-of-information code */
  54.     CurCode, OldCode, InCode,    /* Decompressor variables */
  55.     FirstFree,            /* First free code, generated per GIF spec */
  56.     FreeCode,            /* Decompressor, next free slot in hash table */
  57.     FinChar,            /* Decompressor variable */
  58.     BitMask,            /* AND mask for data size */
  59.     ReadMask;            /* Code AND mask for current code size */
  60.  
  61. BOOLEAN Interlace, HasColormap;
  62. BOOLEAN Verbose = TRUE;
  63.  
  64. byte *RawGIF;            /* The heap array to hold it, raw */
  65. byte *Raster;            /* The raster data stream, unblocked */
  66.  
  67.     /* The hash table used by the decompressor */
  68. int Prefix[4096];
  69. int Suffix[4096];
  70. int bright;
  71.  
  72.     /* An output array used by the decompressor */
  73. int OutCode[1025];
  74.  
  75.     /* The color map, read from the GIF header */
  76. byte Red[256], Green[256], Blue[256], used[256];
  77. struct vlt_slot vlt[256];
  78. int  numused;
  79.  
  80. char *id = "GIF87a";
  81.  
  82. void get_color_map()
  83. {
  84.     /* we've got the picture loaded, we know what colors are needed. get 'em */
  85.  
  86.     register int   i,j;
  87.     byte           lmask, *ptr;
  88.     float       brightness;
  89.  
  90.  
  91.     if (!HasColormap)
  92.     return;
  93.  
  94.     brightness=(float)bright/100.0;
  95.  
  96.     for (i=0;i<256;i++)
  97.     {
  98.         int red,green,blue;
  99.         red = (Red[i]<<8)*brightness;
  100.         green = (Green[i]<<8)*brightness;
  101.         blue = (Blue[i]<<8)*brightness;
  102.                 vlt[i].v_red   = (red > 65535)? 65535:red;
  103.                 vlt[i].v_green = (green  > 65535)? 65535:green;
  104.                 vlt[i].v_blue  = (blue  > 65535)? 65535:blue;
  105.                 vlt[i].v_slot = i;
  106.     }
  107.   
  108.     Loadvlt(vsno,vlt,256);
  109.  
  110. }
  111.  
  112. int find_slot(red,green,blue)
  113.     byte red,green,blue;
  114. {
  115.     int slot=0;
  116.  
  117.     while (slot < 512 )
  118.         if ((vlt[slot].v_red == (int)red) &&
  119.             (vlt[slot].v_green == (int)green) &&
  120.             (vlt[slot].v_blue == (int)blue))
  121.         {
  122.             fprintf(stderr,"vlt values = %d %d %d\n",vlt[slot].v_red,vlt[slot].v_green,vlt[slot].v_blue);
  123.             fprintf(stderr,"gif values = %d %d %d\n",red,green,blue);
  124.             return vlt[slot].v_slot;
  125.         }
  126.         else
  127.             slot++;
  128.     return -1;
  129. }
  130.  
  131.  
  132. /*****************************/
  133. LoadGIF(fname)
  134.   char *fname;
  135. /*****************************/
  136. {
  137.     int            filesize;
  138.     register byte  ch, ch1;
  139.     register byte *ptr, *ptr1;
  140.     register int   i;
  141.  
  142.     if (strcmp(fname,"-")==0) { fp = stdin;  fname = "<stdin>"; }
  143.                          else fp = fopen(fname,"r");
  144.  
  145.     if (!fp) FatalError("file not found");
  146.  
  147.     /* find the size of the file */
  148.     fseek(fp, 0L, 2);
  149.     filesize = ftell(fp);
  150.     fseek(fp, 0L, 0);
  151.  
  152.     if (!(ptr = RawGIF = (byte *) malloc(filesize)))
  153.     FatalError("not enough memory to read gif file");
  154.  
  155.     if (!(Raster = (byte *) malloc(filesize)))
  156.     FatalError("not enough memory to read gif file");
  157.  
  158.     if (fread(ptr, filesize, 1, fp) != 1)
  159.     FatalError("GIF data read failed");
  160.  
  161.     if (strncmp(ptr, id, 6))
  162.     FatalError("not a GIF file");
  163.  
  164.     ptr += 6;
  165.  
  166. /* Get variables from the GIF screen descriptor */
  167.  
  168.     ch = NEXTBYTE;
  169.     RWidth = ch + 0x100 * NEXTBYTE;    /* screen dimensions... not used. */
  170.     ch = NEXTBYTE;
  171.     RHeight = ch + 0x100 * NEXTBYTE;
  172.  
  173.     if (Verbose)
  174.     fprintf(stderr, "screen dims: %dx%d.\n", RWidth, RHeight);
  175.  
  176.     ch = NEXTBYTE;
  177.     HasColormap = ((ch & COLORMAPMASK) ? TRUE : FALSE);
  178.  
  179.     BitsPerPixel = (ch & 7) + 1;
  180.     numcols = ColorMapSize = 1 << BitsPerPixel;
  181.     BitMask = ColorMapSize - 1;
  182.  
  183.     Background = NEXTBYTE;        /* background color... not used. */
  184.  
  185.     if (NEXTBYTE)        /* supposed to be NULL */
  186.     FatalError("corrupt GIF file (bad screen descriptor)");
  187.  
  188.  
  189. /* Read in global colormap. */
  190.  
  191.     if (HasColormap) {
  192.     if (Verbose)
  193.         fprintf(stderr, "%s is %dx%d, %d bits per pixel, (%d colors).\n",
  194.         fname, Width,Height,BitsPerPixel, ColorMapSize);
  195.     for (i = 0; i < ColorMapSize; i++) {
  196.         Red[i] = NEXTBYTE;
  197.         Green[i] = NEXTBYTE;
  198.         Blue[i] = NEXTBYTE;
  199.             used[i] = 0;
  200.         }
  201.         numused = 0;
  202.  
  203.         }
  204.  
  205.     else {  /* no colormap in GIF file */
  206.         fprintf(stderr,"%s:  warning!  no colortable in this file.  Winging it.\n",cmd);
  207.         if (!numcols) numcols=256;
  208.         for (i=0; i<numcols; i++) cols[i] = (unsigned long) i;
  209.         }
  210.  
  211. /* Check for image seperator */
  212.  
  213.     if (NEXTBYTE != IMAGESEP)
  214.     FatalError("corrupt GIF file (no image separator)");
  215.  
  216. /* Now read in values from the image descriptor */
  217.  
  218.     ch = NEXTBYTE;
  219.     LeftOfs = ch + 0x100 * NEXTBYTE;
  220.     ch = NEXTBYTE;
  221.     TopOfs = ch + 0x100 * NEXTBYTE;
  222.     ch = NEXTBYTE;
  223.     Width = ch + 0x100 * NEXTBYTE;
  224.     ch = NEXTBYTE;
  225.     Height = ch + 0x100 * NEXTBYTE;
  226.     Interlace = ((NEXTBYTE & INTERLACEMASK) ? TRUE : FALSE);
  227.  
  228.     if (Verbose)
  229.     fprintf(stderr, "Reading a %d by %d %sinterlaced image...",
  230.         Width, Height, (Interlace) ? "" : "non-");
  231.  
  232.     else 
  233.         fprintf(stderr, "%s:  %s is %dx%d, %d colors  ",
  234.        cmd, fname, Width,Height,ColorMapSize);
  235.     
  236.  
  237. /* Note that I ignore the possible existence of a local color map.
  238.  * I'm told there aren't many files around that use them, and the spec
  239.  * says it's defined for future use.  This could lead to an error
  240.  * reading some files. 
  241.  */
  242.  
  243. /* Start reading the raster data. First we get the intial code size
  244.  * and compute decompressor constant values, based on this code size.
  245.  */
  246.  
  247.     CodeSize = NEXTBYTE;
  248.     ClearCode = (1 << CodeSize);
  249.     EOFCode = ClearCode + 1;
  250.     FreeCode = FirstFree = ClearCode + 2;
  251.  
  252. /* The GIF spec has it that the code size is the code size used to
  253.  * compute the above values is the code size given in the file, but the
  254.  * code size used in compression/decompression is the code size given in
  255.  * the file plus one. (thus the ++).
  256.  */
  257.  
  258.     CodeSize++;
  259.     InitCodeSize = CodeSize;
  260.     MaxCode = (1 << CodeSize);
  261.     ReadMask = MaxCode - 1;
  262.  
  263. /* Read the raster data.  Here we just transpose it from the GIF array
  264.  * to the Raster array, turning it from a series of blocks into one long
  265.  * data stream, which makes life much easier for ReadCode().
  266.  */
  267.  
  268.     ptr1 = Raster;
  269.     do {
  270.     ch = ch1 = NEXTBYTE;
  271.     while (ch--) *ptr1++ = NEXTBYTE;
  272.     if ((Raster - ptr1) > filesize)
  273.         FatalError("corrupt GIF file (unblock)");
  274.     } while(ch1);
  275.  
  276.     free(RawGIF);        /* We're done with the raw data now... */
  277.  
  278.     if (Verbose) {
  279.     fprintf(stderr, "done.\n");
  280.     fprintf(stderr, "Decompressing...");
  281.     }
  282.  
  283.  
  284. /* Allocate the memory for the display */
  285.     Image = (byte *) malloc(Width*Height);
  286.     fprintf(stderr,"%d,%d\n",Width,Height);
  287.     if (!Image) FatalError("not enough memory for Image %d bytes",Width*Height);
  288.  
  289.  
  290.     BytesPerScanline = Width;
  291.  
  292.  
  293. /* Decompress the file, continuing until you see the GIF EOF code.
  294.  * One obvious enhancement is to add checking for corrupt files here.
  295.  */
  296.  
  297.     Code = ReadCode();
  298.     while (Code != EOFCode) {
  299.  
  300. /* Clear code sets everything back to its initial value, then reads the
  301.  * immediately subsequent code as uncompressed data.
  302.  */
  303.  
  304.     if (Code == ClearCode) {
  305.         CodeSize = InitCodeSize;
  306.         MaxCode = (1 << CodeSize);
  307.         ReadMask = MaxCode - 1;
  308.         FreeCode = FirstFree;
  309.         CurCode = OldCode = Code = ReadCode();
  310.         FinChar = CurCode & BitMask;
  311.         AddToPixel(FinChar);
  312.     }
  313.     else {
  314.  
  315. /* If not a clear code, then must be data: save same as CurCode and InCode */
  316.  
  317.         CurCode = InCode = Code;
  318.  
  319. /* If greater or equal to FreeCode, not in the hash table yet;
  320.  * repeat the last character decoded
  321.  */
  322.  
  323.         if (CurCode >= FreeCode) {
  324.         CurCode = OldCode;
  325.         OutCode[OutCount++] = FinChar;
  326.         }
  327.  
  328. /* Unless this code is raw data, pursue the chain pointed to by CurCode
  329.  * through the hash table to its end; each code in the chain puts its
  330.  * associated output code on the output queue.
  331.  */
  332.  
  333.         while (CurCode > BitMask) {
  334.         if (OutCount > 1024) {
  335.             fprintf(stderr,"\nCorrupt GIF file (OutCount)!\n");
  336.                     _exit(-1);  /* calling 'exit(-1)' dumps core, so I don't */
  337.                     }
  338.         OutCode[OutCount++] = Suffix[CurCode];
  339.         CurCode = Prefix[CurCode];
  340.         }
  341.  
  342. /* The last code in the chain is treated as raw data. */
  343.  
  344.         FinChar = CurCode & BitMask;
  345.         OutCode[OutCount++] = FinChar;
  346.  
  347. /* Now we put the data out to the Output routine.
  348.  * It's been stacked LIFO, so deal with it that way...
  349.  */
  350.  
  351.         for (i = OutCount - 1; i >= 0; i--)
  352.         AddToPixel(OutCode[i]);
  353.         OutCount = 0;
  354.  
  355. /* Build the hash table on-the-fly. No table is stored in the file. */
  356.  
  357.         Prefix[FreeCode] = OldCode;
  358.         Suffix[FreeCode] = FinChar;
  359.         OldCode = InCode;
  360.  
  361. /* Point to the next slot in the table.  If we exceed the current
  362.  * MaxCode value, increment the code size unless it's already 12.  If it
  363.  * is, do nothing: the next code decompressed better be CLEAR
  364.  */
  365.  
  366.         FreeCode++;
  367.         if (FreeCode >= MaxCode) {
  368.         if (CodeSize < 12) {
  369.             CodeSize++;
  370.             MaxCode *= 2;
  371.             ReadMask = (1 << CodeSize) - 1;
  372.         }
  373.         }
  374.     }
  375.     Code = ReadCode();
  376.     }
  377.  
  378.     free(Raster);
  379.  
  380.     if (Verbose)
  381.     fprintf(stderr, "done.\n");
  382.     else
  383.         fprintf(stderr,"(of which %d are used)\n",numused);
  384.  
  385.     if (fp != stdin)
  386.     fclose(fp);
  387.  
  388.     get_color_map();
  389. }
  390.  
  391.  
  392. /* Fetch the next code from the raster data stream.  The codes can be
  393.  * any length from 3 to 12 bits, packed into 8-bit bytes, so we have to
  394.  * maintain our location in the Raster array as a BIT Offset.  We compute
  395.  * the byte Offset into the raster array by dividing this by 8, pick up
  396.  * three bytes, compute the bit Offset into our 24-bit chunk, shift to
  397.  * bring the desired code to the bottom, then mask it off and return it. 
  398.  */
  399. ReadCode()
  400. {
  401. int RawCode, ByteOffset;
  402.  
  403.     ByteOffset = BitOffset / 8;
  404.     RawCode = Raster[ByteOffset] + (0x100 * Raster[ByteOffset + 1]);
  405.     if (CodeSize >= 8)
  406.     RawCode += (0x10000 * Raster[ByteOffset + 2]);
  407.     RawCode >>= (BitOffset % 8);
  408.     BitOffset += CodeSize;
  409.     return(RawCode & ReadMask);
  410. }
  411.  
  412.  
  413. AddToPixel(Index)
  414. byte Index;
  415. {
  416.     if (YC<Height)
  417.         *(Image + YC * BytesPerScanline + XC) = Index;
  418.  
  419.     if (!used[Index]) { used[Index]=1;  numused++; }
  420.  
  421. /* Update the X-coordinate, and if it overflows, update the Y-coordinate */
  422.  
  423.     if (++XC == Width) {
  424.  
  425. /* If a non-interlaced picture, just increment YC to the next scan line. 
  426.  * If it's interlaced, deal with the interlace as described in the GIF
  427.  * spec.  Put the decoded scan line out to the screen if we haven't gone
  428.  * past the bottom of it
  429.  */
  430.  
  431.     XC = 0;
  432.     if (!Interlace) YC++;
  433.     else {
  434.         switch (Pass) {
  435.         case 0:
  436.             YC += 8;
  437.             if (YC >= Height) {
  438.             Pass++;
  439.             YC = 4;
  440.             }
  441.         break;
  442.         case 1:
  443.             YC += 8;
  444.             if (YC >= Height) {
  445.             Pass++;
  446.             YC = 2;
  447.             }
  448.         break;
  449.         case 2:
  450.             YC += 4;
  451.             if (YC >= Height) {
  452.             Pass++;
  453.             YC = 1;
  454.             }
  455.         break;
  456.         case 3:
  457.             YC += 2;
  458.         break;
  459.         default:
  460.         break;
  461.         }
  462.     }
  463.     }
  464. }
  465.  
  466.  
  467.  
  468. /*************************/
  469.  
  470. main(argc, argv)
  471.     int   argc;
  472.     char *argv[];
  473. {
  474.     char *fname;
  475.     int i,name,wno;
  476.  
  477.     expand = 1;  strip = 0;  nostrip = 0; 
  478.     pausetime = 0;
  479.  
  480.  
  481.     name = FALSE;
  482.     bright=100;
  483.  
  484.     for (i=1;i<argc;i++)
  485.     {
  486.         fprintf(stderr,"%s\n",argv[i]);
  487.         if (strcmp(argv[i],"-b") == 0)
  488.             bright=atoi(argv[++i]);
  489.         else
  490.         {
  491.             if (name==TRUE)
  492.                 Syntax(cmd);
  493.             else
  494.             {
  495.                 fname=argv[i];
  496.                 name=TRUE;
  497.             }
  498.         }
  499.     }
  500.     fprintf(stderr,"image = %s\n",fname);
  501.     fprintf(stderr,"brightness = %d\n",bright);
  502.  
  503.         Enter_tools();
  504.         Inq_displayed_vs(&vsno);
  505.   
  506.     LoadGIF(fname);
  507.     iWIDE = Width;  iHIGH = Height;
  508.     fprintf(stderr,"width= %d,height = %d\n",iWIDE,iHIGH);
  509.     fprintf(stderr,"colour slots used = %d\n",numused);
  510.     Create_win_no_cstrip(vsno,100,100,100+Width,100+Height,&wno);
  511.     Display_win(wno);
  512.  
  513.  
  514.     DrawWindow (wno,Image,Width,Height);
  515.     sleep(10);
  516. }
  517.  
  518.  
  519.  
  520.  
  521. /***********************************/
  522. Syntax()
  523. {
  524.     printf("Usage: evgif [-b brightness] filename \n");
  525.     exit(1);
  526. }
  527.  
  528.  
  529. /***********************************/
  530. FatalError (identifier)
  531.        char *identifier;
  532. {
  533.     fprintf(stderr, "%s: %s\n",cmd, identifier);
  534.     exit(-1);
  535. }
  536.  
  537.  
  538. /***********************************/
  539. Quit()
  540. {
  541.     exit(0);
  542. }
  543.  
  544.  
  545. /***********************************/
  546. DrawWindow(wno,Image,width,height)
  547.     int wno;
  548.     byte *Image;
  549.     int width,height;
  550. {
  551.     byte *ptr=Image;
  552.     int x,y;
  553.     short *newimage,*new_ptr;
  554.  
  555.     newimage = (short *)malloc(width*height);
  556.  
  557.     new_ptr=newimage;
  558.     for (x=0;x<width*height;x++)
  559.         *new_ptr++ = *ptr++;
  560.  
  561.     new_ptr=newimage;
  562.     hidecursor(wno);
  563.     putpixelblock16(wno,0xffffffff,0,0,width-1,height-1,new_ptr);
  564.     showcursor(wno);
  565. }
  566.  
  567.     
  568.  
  569.  
  570. CheckDepth()
  571. {
  572. }
  573.  
  574.