source: trunk/src/testing/app/bitplay/libimg/gifdisp.c @ 4

Revision 4, 14.9 KB checked in by ajaworski, 13 years ago (diff)

Added modified SAGE sources

  • Property svn:executable set to *
Line 
1/******************************************************************************
2 * SAGE - Scalable Adaptive Graphics Environment
3 *
4 * Copyright (C) 2004 Electronic Visualization Laboratory,
5 * University of Illinois at Chicago
6 *
7 * All rights reserved.
8 *
9 * Redistribution and use in source and binary forms, with or without
10 * modification, are permitted provided that the following conditions are met:
11 *
12 *  * Redistributions of source code must retain the above copyright
13 *    notice, this list of conditions and the following disclaimer.
14 *  * Redistributions in binary form must reproduce the above
15 *    copyright notice, this list of conditions and the following disclaimer
16 *    in the documentation and/or other materials provided with the distribution.
17 *  * Neither the name of the University of Illinois at Chicago nor
18 *    the names of its contributors may be used to endorse or promote
19 *    products derived from this software without specific prior written permission.
20 *
21 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
22 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
23 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
24 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
25 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
26 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
27 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
28 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
29 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
30 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
31 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
32 *
33 * Direct questions, comments etc about SAGE to http://www.evl.uic.edu/cavern/forum/
34 *
35 *****************************************************************************/
36
37/*-
38 * gif2ras.c - Converts from a Compuserve GIF (tm) image to a Sun Raster image.
39 *
40 * Copyright (c) 1988 by Patrick J. Naughton
41 *
42 * Author: Patrick J. Naughton
43 * naughton@wind.sun.com
44 *
45 * Permission to use, copy, modify, and distribute this software and its
46 * documentation for any purpose and without fee is hereby granted,
47 * provided that the above copyright notice appear in all copies and that
48 * both that copyright notice and this permission notice appear in
49 * supporting documentation.
50 *
51 * This file is provided AS IS with no warranties of any kind.  The author
52 * shall have no liability with respect to the infringement of copyrights,
53 * trade secrets or any patents by this file or any part thereof.  In no
54 * event will the author be liable for any lost revenue or profits or
55 * other special, indirect and consequential damages.
56 *
57 * Comments and additions should be sent to the author:
58 *
59 *                     Patrick J. Naughton
60 *                     Sun Microsystems, Inc.
61 *                     2550 Garcia Ave, MS 14-40
62 *                     Mountain View, CA 94043
63 *                     (415) 336-1080
64 *
65 * Revision History:
66 * 27-Jul-88: Updated to use libpixrect to fix 386i byteswapping problems.
67 * 11-Apr-88: Converted to C and changed to write Sun rasterfiles.
68 * 19-Jan-88: GIFSLOW.PAS posted to comp.graphics by Jim Briebel,
69 *            a Turbo Pascal 4.0 program to painfully slowly display
70 *            GIF images on an EGA equipped IBM-PC.
71 * 13-Jul-90: changed to gif2raw for use by the Geometry Supercomputer Project
72 *            by Cary Sandvig
73 *
74 * Description:
75 *   This program takes a Compuserve "Graphics Interchange Format" or "GIF"
76 * file as input and writes a file known as a Sun rasterfile.  This datafile
77 * can be loaded by the NeWS "readcanvas" operator and is of the same format
78 * as the files in /usr/NeWS/smi/...  Under X11R2 there is a program called
79 * xraster to display these files.
80 *
81 * Portability:
82 *   To make this program convert to some image format other than Sun's
83 * Rasterfile format simply seach for the tag "SS:" in the source and
84 * replace these simple mechanisms with the appropriate ones for the
85 * other output format.  I have marked all (six) Sun Specific pieces
86 * of code with this comment.
87 *
88 * SS: compile with "cc -o gif2raw -O gif2raw.c"
89 */
90
91#include <fcntl.h>
92#include <stdio.h>
93#include <stdlib.h>
94#include <string.h>
95#include "softpic.h"
96#include "imginfo.h"
97
98typedef int boolean;
99#define True (1)
100#define False (0)
101
102#define NEXTSHORT (ptr += 2, ptr[-2] + 0x100 * ptr[-1])
103#define NEXTBYTE (*ptr++)
104#define IMAGESEP 0x2c
105#define EXTENSION '!'
106#define TRANSPARENCY 0xF9       /* transparency extension-code */
107#define INTERLACEMASK 0x40
108#define COLORMAPMASK 0x80
109
110static int BitOffset = 0,               /* Bit Offset of next code */
111    XC = 0, YC = 0,             /* Output X and Y coords of current pixel */
112    Pass = 0,                   /* Used by output routine if interlaced pic */
113    OutCount = 0,               /* Decompressor output 'stack count' */
114    RWidth, RHeight,            /* screen dimensions */
115    Width, Height,              /* image dimensions */
116    LeftOfs, TopOfs,            /* image offset */
117    BitsPerPixel,               /* Bits per pixel, read from GIF header */
118    ColorMapSize,               /* number of colors */
119    CodeSize,                   /* Code size, read from GIF header */
120    InitCodeSize,               /* Starting code size, used during Clear */
121    Code,                       /* Value returned by ReadCode */
122    MaxCode,                    /* limiting value for current code size */
123    ClearCode,                  /* GIF clear code */
124    EOFCode,                    /* GIF end-of-information code */
125    CurCode, OldCode, InCode,   /* Decompressor variables */
126    FirstFree,                  /* First free code, generated per GIF spec */
127    FreeCode,                   /* Decompressor, next free slot in hash table */
128    FinChar,                    /* Decompressor variable */
129    BitMask,                    /* AND mask for data size */
130    ReadMask;                   /* Code AND mask for current code size */
131
132static boolean Interlace, HasColormap;
133
134static unsigned char *Image;                    /* The result array */
135static unsigned char *RawGIF;                   /* The heap array to hold it, raw */
136static unsigned char *Raster;                   /* The raster data stream, unblocked */
137
138    /* The hash table used by the decompressor */
139static int Prefix[4096];
140static int Suffix[4096];
141
142    /* An output array used by the decompressor */
143static int OutCode[1025];
144
145    /* The color map, read from the GIF header */
146static unsigned char Red[256], Green[256], Blue[256];
147static long abgr[256];
148
149static char *id, *id2;
150
151static char *pname;                     /* program name (used for error messages) */
152
153static int  ReadCode();
154static void AddToPixel(char Index);
155
156static void error( char *s1, char *s2 )
157{
158    fprintf(stderr, s1, pname, s2);
159    exit(1);
160}
161
162
163static void gif_init()
164{
165   BitOffset = 0;
166   XC = 0;
167   YC = 0;
168   Pass = 0;
169   OutCount = 0;
170   id = "GIF87a";
171   id2 = "GIF89a";
172}
173
174IMG *gifmakedisp( char *inname )
175{
176    FILE *fpin;
177    int filesize;
178    register unsigned char ch, ch1;
179    register unsigned char *ptr, *ptr1;
180    IMG *out;
181    int transindex = -1;
182    int i, j;
183
184    gif_init();
185    setbuf(stderr, NULL);
186
187    fpin = fopen(inname, "rb");
188    /* find the size of the file */
189
190    fseek(fpin, 0L, 2);
191    filesize = ftell(fpin);
192    fseek(fpin, 0L, 0);
193
194    if (!(ptr = RawGIF = (unsigned char *) malloc(filesize)))
195        error("%s: not enough memory to read gif file.\n", NULL);
196
197    if (!(Raster = (unsigned char *) malloc(filesize)))
198        error("%s: not enough memory to read gif file.\n", NULL);
199
200    fread(ptr, filesize, 1, fpin);
201
202    if (memcmp(ptr, id, 6) && memcmp(ptr, id2, 6))
203        error("%s: %s is not a GIF file.\n", inname);
204    ptr += 6;
205
206/* Get variables from the GIF screen descriptor */
207
208    RWidth = NEXTSHORT;         /* screen dimensions... not used. */
209    RHeight = NEXTSHORT;
210
211    ch = NEXTBYTE;
212    HasColormap = ((ch & COLORMAPMASK) ? True : False);
213
214    BitsPerPixel = (ch & 7) + 1;
215    ColorMapSize = 1 << BitsPerPixel;
216    BitMask = ColorMapSize - 1;
217
218    ch = NEXTBYTE;              /* background color... not used. */
219
220    (void) NEXTBYTE;            /* what's this? */
221
222/* Read in global colormap. */
223
224    if (HasColormap) {
225/*
226        fprintf(stderr, "%s is %d bits per pixel, (%d colors).\n",
227                inname, BitsPerPixel, ColorMapSize);
228*/
229        for (i = 0; i < ColorMapSize; i++) {
230            Red[i] = NEXTBYTE;
231            Green[i] = NEXTBYTE;
232            Blue[i] = NEXTBYTE;
233            abgr[i] = 0xFF000000 | (Blue[i]<<16) | (Green[i]<<8) | Red[i];
234        }
235
236    }
237    else error("gifdisp: %s does not have a colormap.\n", inname);
238
239
240    /* Skip any GIF89 extensions */
241    while((i = NEXTBYTE) == EXTENSION) {
242        int extno = NEXTBYTE & 0xFF;
243        int len;
244        unsigned char block[256];
245
246        /* Skip <lengthbyte><data> segments until we see lengthbyte==0. */
247        while((len = NEXTBYTE) != 0) {
248            for(i = 0; i < len; i++)
249                block[i] = NEXTBYTE;
250        }
251        switch(extno) {
252        case 0xF9:              /* Transparency */
253            if(block[0] & 0x01) {
254                transindex = block[3];
255                if(transindex >= 0 && transindex < ColorMapSize)
256                    abgr[transindex] &= ~0xFF000000;
257            }
258            break;
259        }
260    }
261
262    /* Check for image separator */
263    if (i != IMAGESEP)
264        fprintf(stderr, "gifdisp: %s is a corrupt GIF file.\n", inname);
265
266/* Now read in values from the image descriptor */
267
268    LeftOfs = NEXTSHORT;
269    TopOfs = NEXTSHORT;
270    Width = NEXTSHORT;
271    Height = NEXTSHORT;
272    Interlace = ((NEXTBYTE & INTERLACEMASK) ? True : False);
273
274/*
275    fprintf(stderr, "Reading a %d by %d %sinterlaced image...",
276        Width, Height, (Interlace) ? "" : "non-");
277*/
278
279
280/* Note that I ignore the possible existence of a local color map.
281 * I'm told there aren't many files around that use them, and the spec
282 * says it's defined for future use.  This could lead to an error
283 * reading some files.
284 */
285
286/* Start reading the raster data. First we get the intial code size
287 * and compute decompressor constant values, based on this code size.
288 */
289
290    CodeSize = NEXTBYTE;
291    ClearCode = (1 << CodeSize);
292    EOFCode = ClearCode + 1;
293    FreeCode = FirstFree = ClearCode + 2;
294
295/* The GIF spec has it that the code size is the code size used to
296 * compute the above values is the code size given in the file, but the
297 * code size used in compression/decompression is the code size given in
298 * the file plus one. (thus the ++).
299 */
300
301    CodeSize++;
302    InitCodeSize = CodeSize;
303    MaxCode = (1 << CodeSize);
304    ReadMask = MaxCode - 1;
305
306/* Read the raster data.  Here we just transpose it from the GIF array
307 * to the Raster array, turning it from a series of blocks into one long
308 * data stream, which makes life much easier for ReadCode().
309 */
310
311    ptr1 = Raster;
312    do {
313        ch = ch1 = NEXTBYTE;
314        while (ch--) *ptr1++ = NEXTBYTE;
315    } while(ch1);
316
317    free(RawGIF);               /* We're done with the raw data now... */
318
319/*
320    fprintf(stderr, "done.\n");
321    fprintf(stderr, "Decompressing...");
322*/
323
324    Image = (unsigned char *)calloc((Width*Height), sizeof(char));
325
326
327/* Decompress the file, continuing until you see the GIF EOF code.
328 * One obvious enhancement is to add checking for corrupt files here.
329 */
330
331    Code = ReadCode();
332    while (Code != EOFCode) {
333
334/* Clear code sets everything back to its initial value, then reads the
335 * immediately subsequent code as uncompressed data.
336 */
337
338        if (Code == ClearCode) {
339            CodeSize = InitCodeSize;
340            MaxCode = (1 << CodeSize);
341            ReadMask = MaxCode - 1;
342            FreeCode = FirstFree;
343            CurCode = OldCode = Code = ReadCode();
344            FinChar = CurCode & BitMask;
345            AddToPixel(FinChar);
346        }
347        else {
348
349/* If not a clear code, then must be data: save same as CurCode and InCode */
350
351            CurCode = InCode = Code;
352
353/* If greater or equal to FreeCode, not in the hash table yet;
354 * repeat the last character decoded
355 */
356
357            if (CurCode >= FreeCode) {
358                CurCode = OldCode;
359                OutCode[OutCount++] = FinChar;
360            }
361
362/* Unless this code is raw data, pursue the chain pointed to by CurCode
363 * through the hash table to its end; each code in the chain puts its
364 * associated output code on the output queue.
365 */
366
367            while (CurCode > BitMask) {
368                OutCode[OutCount++] = Suffix[CurCode];
369                CurCode = Prefix[CurCode];
370            }
371
372/* The last code in the chain is treated as raw data. */
373
374            FinChar = CurCode & BitMask;
375            OutCode[OutCount++] = FinChar;
376
377/* Now we put the data out to the Output routine.
378 * It's been stacked LIFO, so deal with it that way...
379 */
380
381            for (i = OutCount - 1; i >= 0; i--)
382                AddToPixel(OutCode[i]);
383            OutCount = 0;
384
385/* Build the hash table on-the-fly. No table is stored in the file. */
386
387            Prefix[FreeCode] = OldCode;
388            Suffix[FreeCode] = FinChar;
389            OldCode = InCode;
390
391/* Point to the next slot in the table.  If we exceed the current
392 * MaxCode value, increment the code size unless it's already 12.  If it
393 * is, do nothing: the next code decompressed better be CLEAR
394 */
395
396            FreeCode++;
397            if (FreeCode >= MaxCode) {
398                if (CodeSize < 12) {
399                    CodeSize++;
400                    MaxCode *= 2;
401                    ReadMask = (1 << CodeSize) - 1;
402                }
403            }
404        }
405        Code = ReadCode();
406    }
407
408    free(Raster);
409
410/*
411    fprintf(stderr, "done.\n");
412
413    fprintf(stderr, "outputting image.\n");
414*/
415
416    out = (IMG *)malloc(sizeof(IMG));
417    out->type = IT_LONG;
418    out->rowbytes = Width * sizeof(long);
419    out->xsize = Width;
420    out->ysize = Height;
421    out->data = (unsigned char *)malloc(4*(Width*Height)*sizeof(char));
422
423    for(j = 0; j<Height; j++)
424       for (i=0; i<Width; i++) {
425          *(long *)&out->data[4*(((Height - j - 1)*Width)+i)] =
426                abgr[Image[j*Width + i]];
427        }
428
429     free(Image);
430     fclose(fpin);
431     return (out);
432
433/*
434    fprintf(stderr, "done.\n");
435*/
436}
437
438
439/* Fetch the next code from the raster data stream.  The codes can be
440 * any length from 3 to 12 bits, packed into 8-bit bytes, so we have to
441 * maintain our location in the Raster array as a BIT Offset.  We compute
442 * the byte Offset into the raster array by dividing this by 8, pick up
443 * three bytes, compute the bit Offset into our 24-bit chunk, shift to
444 * bring the desired code to the bottom, then mask it off and return it.
445 */
446static int ReadCode()
447{
448    int RawCode, ByteOffset;
449
450    ByteOffset = BitOffset / 8;
451    RawCode = Raster[ByteOffset] + (0x100 * Raster[ByteOffset + 1]);
452    if (CodeSize >= 8)
453        RawCode += (0x10000 * Raster[ByteOffset + 2]);
454    RawCode >>= (BitOffset % 8);
455    BitOffset += CodeSize;
456    return(RawCode & ReadMask);
457}
458
459static void AddToPixel(char Index)
460{
461    if((unsigned int)XC >= Width || (unsigned int)YC >= Height) {
462        fprintf(stderr, "[BP] ");
463    } else {
464        *(Image + YC * Width + XC) = Index;
465    }
466
467/* Update the X-coordinate, and if it overflows, update the Y-coordinate */
468
469    if (++XC == Width) {
470
471/* If a non-interlaced picture, just increment YC to the next scan line.
472 * If it's interlaced, deal with the interlace as described in the GIF
473 * spec.  Put the decoded scan line out to the screen if we haven't gone
474 * past the bottom of it
475 */
476
477        XC = 0;
478        if (!Interlace) YC++;
479        else {
480            switch (Pass) {
481                case 0:
482                    YC += 8;
483                    if (YC >= Height) {
484                        Pass++;
485                        YC = 4;
486                    }
487                break;
488                case 1:
489                    YC += 8;
490                    if (YC >= Height) {
491                        Pass++;
492                        YC = 2;
493                    }
494                break;
495                case 2:
496                    YC += 4;
497                    if (YC >= Height) {
498                        Pass++;
499                        YC = 1;
500                    }
501                break;
502                case 3:
503                    YC += 2;
504                    if(YC >= Height) {
505                        fprintf(stderr, "[BG] ");
506                        YC = Height-1;  /* eh?? */
507                    }
508                break;
509                default:
510                break;
511            }
512        }
513    }
514}
Note: See TracBrowser for help on using the repository browser.