/**************************************************************************** * gif.c * * Gif-format file reader. * * NOTE: Portions of this module were written by Steve Bennett and are used * here with his permission. * * from Persistence of Vision Raytracer * Copyright 1993 Persistence of Vision Team *--------------------------------------------------------------------------- * NOTICE: This source code file is provided so that users may experiment * with enhancements to POV-Ray and to port the software to platforms other * than those supported by the POV-Ray Team. There are strict rules under * which you are permitted to use this file. The rules are in the file * named POVLEGAL.DOC which should be distributed with this file. If * POVLEGAL.DOC is not available or for more info please contact the POV-Ray * Team Coordinator by leaving a message in CompuServe's Graphics Developer's * Forum. The latest version of POV-Ray may be found there as well. * * This program is based on the popular DKB raytracer version 2.12. * DKBTrace was originally written by David K. Buck. * DKBTrace Ver 2.0-2.12 were written by David K. Buck & Aaron A. Collins. * *****************************************************************************/ /* The following routines were borrowed freely from FRACTINT, and represent a generalized GIF file decoder. This seems the best, most universal format for reading in Bitmapped images. GIF is a Copyright of Compuserve, Inc. Swiped and converted to entirely "C" coded routines by AAC for the most in future portability! */ #include "frame.h" #include "povproto.h" static IMAGE *Current_Image; static int Bitmap_Line; static FILE *Bit_File; unsigned char *decoderline /* [2049] */ ; /* write-line routines use this */ static IMAGE_COLOUR *gif_colour_map; static int colourmap_size; int out_line (pixels, linelen) unsigned char *pixels; int linelen; { register int x; register unsigned char *line; line = Current_Image->data.map_lines[Bitmap_Line++]; for (x = 0; x < linelen; x++) { if ((int)(*pixels) > Current_Image->Colour_Map_Size) { fprintf (stderr, "Error - GIF Image Map Colour out of range\n"); exit(1); } line[x] = *pixels; pixels++; } return (0); } #define READ_ERROR -1 int get_byte() /* get byte from file, return the next byte or an error */ { register int byte; if ((byte = getc(Bit_File)) != EOF) return (byte); else { fprintf (stderr, "Premature End Of File reading GIF image\n"); exit (1); } return (0); /* Keep the compiler happy */ } /* Main GIF file decoder. */ void Read_Gif_Image(Image, filename) IMAGE *Image; char *filename; { register int i, j, status; unsigned finished, planes; unsigned char buffer[16]; status = 0; Current_Image = Image; if ((Bit_File = Locate_File(filename, READ_FILE_STRING)) == NULL) { fprintf (stderr, "Cannot open GIF file %s\n", filename); exit(1); } /* zero out the full write-line */ if ((decoderline = (unsigned char *) malloc (2049)) == NULL) { fprintf (stderr, "Cannot allocate space for GIF decoder line\n"); fclose (Bit_File); exit (1); } for (i = 0; i < 2049; i++) decoderline[i] = (unsigned char) 0; /* Get the screen description */ for (i = 0; i < 13; i++) buffer[i] = (unsigned char)get_byte(); if (strncmp((char *) buffer,"GIF",3) || /* use updated GIF specs */ buffer[3] < '0' || buffer[3] > '9' || buffer[4] < '0' || buffer[4] > '9' || buffer[5] < 'A' || buffer[5] > 'z' ) { fprintf (stderr, "Invalid GIF file format: %s\n", filename); fclose(Bit_File); exit (1); } planes = ((unsigned)buffer[10] & 0x0F) + 1; colourmap_size = (int)(1 << planes); if ((gif_colour_map = (IMAGE_COLOUR *) malloc (colourmap_size * sizeof (IMAGE_COLOUR))) == NULL) { fprintf (stderr, "Cannot allocate GIF Colour Map\n"); fclose (Bit_File); exit (1); } if ((buffer[10] & 0x80) == 0) { /* color map (better be!) */ fprintf (stderr, "Invalid GIF file format: %s\n", filename); fclose(Bit_File); exit (1); } for (i = 0; i < colourmap_size ; i++) { gif_colour_map[i].Red = (unsigned char)get_byte(); gif_colour_map[i].Green = (unsigned char)get_byte(); gif_colour_map[i].Blue = (unsigned char)get_byte(); gif_colour_map[i].Filter = 0; } /* Now display one or more GIF objects */ finished = FALSE; while (!finished) { switch (get_byte()) { case ';': /* End of the GIF dataset */ finished = TRUE; status = 0; break; case '!': /* GIF Extension Block */ get_byte(); /* read (and ignore) the ID */ while ((i = get_byte()) > 0) /* get data len*/ for (j = 0; j < i; j++) get_byte(); /* flush data */ break; case ',': /* Start of image object. get description */ for (i = 0; i < 9; i++) { if ((j = get_byte()) < 0) { /* EOF test (?) */ status = -1; break; } buffer[i] = (unsigned char) j; } /* Check "interlaced" bit */ if (j & 0x40) Error ("Error! Can't deal with interlaced GIF files."); if (status < 0) { finished = TRUE; break; } Image->iwidth = buffer[4] | (buffer[5] << 8); Image->iheight = buffer[6] | (buffer[7] << 8); Image->width = (DBL) Image->iwidth; Image->height = (DBL) Image->iheight; Bitmap_Line = 0; Image->Colour_Map_Size = colourmap_size; Image->Colour_Map = gif_colour_map; if ((Image->data.map_lines = (unsigned char **) malloc(Image->iheight * sizeof (unsigned char *)))==NULL) { fprintf (stderr, "Cannot allocate memory for picture\n"); exit(1); } for (i = 0 ; i < Image->iheight ; i++) { if ((Image->data.map_lines[i] = (unsigned char *) malloc(Image->iwidth))==NULL) { fprintf (stderr, "Cannot allocate memory for picture\n"); exit(1); } } /* Setup the color palette for the image */ status = decoder ( Image->iwidth); /*put bytes in Buf*/ /* changed param to int */ finished = TRUE; break; default: status = -1; finished = TRUE; break; } } free (decoderline); fclose(Bit_File); }