/* gif.c: * * adapted from code by kirk johnson (tuna@athena.mit.edu). most of this * code is unchanged. -- jim frost 12.31.89 * * gifin.c * kirk johnson * november 1989 * * routines for reading GIF files * * Copyright 1989 Kirk L. Johnson (see the included file * "kljcpyrght.h" for complete copyright information) */ #ifdef USE_GIF #include "image.h" #include static void tellAboutImage(name, gifp) char *name; GifFileType *gifp; { fprintf(stderr, "%s is a %dx%d GIF image\n", name, gifp->SWidth, gifp->SHeight); } /* The way Interlaced image should. */ static int InterlacedOffset[] = { 0, 4, 2, 1 }; /* be read - offsets and jumps... */ static int InterlacedJumps[] = { 8, 8, 4, 2 }; Image * gifLoad(fullname, name, verbose) char *fullname, *name; unsigned int verbose; { byte *pixline; unsigned char *Buffer, *BufferP; Image *image; int Size, Row, Col, Width, Height, Count, ExtCode; int i, j, x, y, trans = 0; GifRecordType RecordType; GifByteType *Extension; GifRowType *ScreenBuffer; GifRowType GifRow; GifFileType *GifFile; ColorMapObject *ColorMap; GifColorType *ColorMapEntry; GifFile = DGifOpenFileName(fullname); if (GifFile == NULL) return NULL; if ((ScreenBuffer = (GifRowType *) malloc(GifFile->SHeight * sizeof(GifRowType *))) == NULL) { fprintf(stderr, "malloc failed\n"); exit(1); } /* Size in bytes one row.*/ Size = GifFile->SWidth * sizeof(GifPixelType); /* First row. */ if ((ScreenBuffer[0] = (GifRowType) malloc(Size)) == NULL) { fprintf(stderr, "malloc failed\n"); exit(1); } /* Set its color to BackGround. */ for (i = 0; i < GifFile->SWidth; i++) ScreenBuffer[0][i] = GifFile->SBackGroundColor; for (i = 1; i < GifFile->SHeight; i++) { /* * Allocate the other rows, and set their color to background * too: */ if ((ScreenBuffer[i] = (GifRowType) malloc(Size)) == NULL) { fprintf(stderr, "malloc failed\n"); exit(1); } memcpy(ScreenBuffer[i], ScreenBuffer[0], Size); } /* Scan the content of the GIF file and load the image(s) in: */ do { if (DGifGetRecordType(GifFile, &RecordType) == GIF_ERROR) { PrintGifError(); exit(-1); } switch (RecordType) { case IMAGE_DESC_RECORD_TYPE: if (DGifGetImageDesc(GifFile) == GIF_ERROR) { PrintGifError(); exit(-1); } Row = GifFile->Image.Top; /* Image Position relative to Screen. */ Col = GifFile->Image.Left; Width = GifFile->Image.Width; Height = GifFile->Image.Height; if (GifFile->Image.Left + GifFile->Image.Width > GifFile->SWidth || GifFile->Image.Top + GifFile->Image.Height > GifFile->SHeight) { fprintf(stderr, "Image %d is not confined to screen dimension, aborted.\n"); exit(-2); } if (GifFile->Image.Interlace) { /* Need to perform 4 passes on the images: */ for (Count = i = 0; i < 4; i++) for (j = Row + InterlacedOffset[i]; j < Row + Height; j += InterlacedJumps[i]) { if (DGifGetLine(GifFile, &ScreenBuffer[j][Col], Width) == GIF_ERROR) { PrintGifError(); exit(-1); } } } else { for (i = 0; i < Height; i++) { if (DGifGetLine(GifFile, &ScreenBuffer[Row++][Col], Width) == GIF_ERROR) { PrintGifError(); exit(-1); } } } break; case EXTENSION_RECORD_TYPE: /* Skip any extension blocks in file: */ if (DGifGetExtension(GifFile, &ExtCode, &Extension) == GIF_ERROR) { PrintGifError(); exit(-1); } /* very adhoc transparency support */ if (ExtCode == GRAPHICS_EXT_FUNC_CODE){ if (*((char *)Extension +1) & 1) trans = 1; } while (Extension != NULL) { if (DGifGetExtensionNext(GifFile, &Extension) == GIF_ERROR) { PrintGifError(); exit(-1); } } break; case TERMINATE_RECORD_TYPE: break; default: /* Should be traps by DGifGetRecordType. */ break; } } while (RecordType != TERMINATE_RECORD_TYPE); /* Lets dump it - set the global variables required and do it: */ ColorMap = (GifFile->Image.ColorMap ? GifFile->Image.ColorMap : GifFile->SColorMap); image = newRGBImage(GifFile->SWidth, GifFile->SHeight, 8); if (trans) image->trans = GifFile->SBackGroundColor; else image->trans = -1; image->rgb.used = ColorMap->ColorCount; for (i = 0; i < ColorMap->ColorCount; i++) { ColorMapEntry = &ColorMap->Colors[i]; image->rgb.red[i]= ColorMapEntry->Red << 8; image->rgb.green[i]= ColorMapEntry->Green << 8; image->rgb.blue[i]= ColorMapEntry->Blue << 8; } for (y = 0; y < GifFile->SHeight; y++) { GifRow = ScreenBuffer[y]; pixline = image->data + (y * image->width * image->pixlen); for (x = 0; x < GifFile->SWidth; x++) pixline[x] = GifRow[x]; } if (DGifCloseFile(GifFile) == GIF_ERROR) { PrintGifError(); exit(-1); } image->title = dupString(name); return image; } int gifIdent(fullname, name) char *fullname, *name; { GifFileType *gifp; int ret; gifp = DGifOpenFileName(fullname); if (gifp == NULL) ret = 0; else { DGifCloseFile(gifp); tellAboutImage(name); ret = 1; } return ret; } #endif /*USE_GIF*/