/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * Copyright by The HDF Group. * * Copyright by the Board of Trustees of the University of Illinois. * * All rights reserved. * * * * This file is part of HDF5. The full HDF5 copyright notice, including * * terms governing use, modification, and redistribution, is contained in * * the files COPYING and Copyright.html. COPYING can be found at the root * * of the source code distribution tree; Copyright.html can be found at the * * root level of an installed copy of the electronic HDF5 document set and * * is linked from the top-level documents page. It can also be found at * * http://hdfgroup.org/HDF5/doc/Copyright.html. If you do not have * * access to either file, you may request a copy from help@hdfgroup.org. * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ #include #include #include "gif.h" int EndianOrder; static BYTE *ReadDataSubBlocks(BYTE **MemGif2, WORD *DSize); WORD GetWord(BYTE *MemGif) { WORD w; if (EndianOrder == 1) { /* LittleEndian */ w = (WORD) (*MemGif++ & 0xFF); w |= (WORD) ((*MemGif++ & 0xFF) << 0x08); } else { w = (WORD) (*MemGif++ & 0xFF); w = ((WORD) (*MemGif++ & 0xFF)) | (w << 0x08); } return w; } BYTE GetByte(BYTE *MemGif) { return *MemGif; } /* * Read a GIF image BYTE Header. * * This function reads the Header, Logical Screen Descriptor, and * Global Color Table (if any) from a GIF image file. The information * is stored in a GIFHEAD structure. * * Returns: -1 if a FILE stream error occured during the read, * otherwise 0 if no error occured. */ int ReadGifHeader(GIFHEAD *GifHead, /* Pointer to GIF header structure */ BYTE **MemGif2) /* GIF image file input FILE stream */ { WORD i; /* Loop counter */ WORD tableSize; /* Number of entires in the Global Color Table */ GifHead->TableSize = 0; for (i = 0 ; i < 6 ; i++) { GifHead->HeaderDump[i] = *(*MemGif2)++; } if (strncmp((const char *)GifHead->HeaderDump , "GIF" , (size_t)3)) { printf("The file does not appear to be a valid GIF file.\n"); exit(-1); } for (i = 0 ; i < 7 ; i++) { GifHead->LSDDump[i] = *(*MemGif2)++; } GifHead->PackedField = GifHead->LSDDump[4]; /* Check if a Global Color Table is present */ if (GifHead->PackedField & 0x80) { /* Read number of color table entries */ tableSize = (WORD) (1L << ((GifHead->PackedField & 0x07) + 1)); GifHead->TableSize = tableSize; /* Read the Global Color Table */ /* * There are some changes made here apart from just reading in the * global color table as would seem intuitively obvious. The colors * are stored in the bottom part of the palette as opposed to the top */ for (i = 0; i < tableSize; i++) { GifHead->HDFPalette[i][0] = *(*MemGif2)++; GifHead->HDFPalette[i][1] = *(*MemGif2)++; GifHead->HDFPalette[i][2] = *(*MemGif2)++; } } /* Check for a FILE stream error */ #if 0 if (ferror(FpGif)) return -1; #endif /* 0 */ return 0; /* No FILE stream error occured */ } /* ** Read a GIF Local Image Descriptor. ** ** This function reads the Local Image Descriptor, and Local Color ** Table (if any) from a GIF image file. The information is stored ** in a GIFIMAGEDESC structure. ** ** Note that the ImageSeparator field value in the GIFIMAGEDESC ** structure is assigned by the function calling ReadGifImageDesc(). ** ** Returns: -1 if a FILE stream error occured during the read, ** otherwise 0 if no error occured. */ int ReadGifImageDesc( GIFIMAGEDESC *GifImageDesc, /* Pointer to GIF image descriptor structure */ BYTE **MemGif2 /* GIF image file input FILE stream */ ) { WORD i; /* Loop counter */ WORD tableSize; /* Number of entries in the Local Color Table */ /* BYTE Interlace; */ /* PackedField & 0x20 gives information on interlacing */ BYTE *TempPtr; int ch , ch1; GifImageDesc->TableSize = 0; for (i = 0 ; i < 9 ; i++) { GifImageDesc->GIDDump[i] = *(*MemGif2)++; } /* ** Get the relevant fields. I need ImageWidth and Height actively hence I have ** taken information from those fields. I intend to keep the GifImageDesc data ** structure as it is so that anyone needing the rest of the fields can do so ** quickly. */ if (EndianOrder == 1) /* LittleEndian */ { GifImageDesc->ImageWidth = (WORD) (GifImageDesc->GIDDump[4] & 0xFF); GifImageDesc->ImageWidth |= (WORD) ((GifImageDesc->GIDDump[5] & 0xFF) << 0x08); GifImageDesc->ImageHeight = (WORD) (GifImageDesc->GIDDump[6] & 0xFF); GifImageDesc->ImageHeight |= (WORD) ((GifImageDesc->GIDDump[7] & 0xFF) << 0x08); } else { GifImageDesc->ImageWidth = (WORD) (GifImageDesc->GIDDump[4] & 0xFF); GifImageDesc->ImageWidth = ((WORD) (GifImageDesc->GIDDump[5] & 0xFF)) | (GifImageDesc->ImageWidth << 0x08); GifImageDesc->ImageHeight = (WORD) (GifImageDesc->GIDDump[6] & 0xFF); GifImageDesc->ImageHeight = ((WORD) (GifImageDesc->GIDDump[7] & 0xFF)) | (GifImageDesc->ImageWidth << 0x08); } GifImageDesc->PackedField = GifImageDesc->GIDDump[8]; /* Interlace = GifImageDesc->PackedField & 0x20; */ /* Check if a Local Color Table is present */ if (GifImageDesc->PackedField & 0x80) { /* Read number of color table entries */ tableSize = (WORD) (1L << ((GifImageDesc->PackedField & 0x07) + 1)); GifImageDesc->TableSize = tableSize; /* Read the Local Color Table */ for (i = 0; i < tableSize; i++) { GifImageDesc->HDFPalette[i][0] = *(*MemGif2)++; GifImageDesc->HDFPalette[i][1] = *(*MemGif2)++; GifImageDesc->HDFPalette[i][2] = *(*MemGif2)++; } } /* ** Get LZW minimum Code Size */ GifImageDesc->CodeSize = (WORD)*(*MemGif2)++; /*GifImageDesc->GIFImage = ReadDataSubBlocks(FpGif);*/ if (!(GifImageDesc->GIFImage = (BYTE *)malloc((GifImageDesc->ImageWidth) * (GifImageDesc->ImageHeight)))) { printf("Out of memory"); exit(-1); } TempPtr = GifImageDesc->GIFImage; do { ch = ch1 = (int)*(*MemGif2)++; while (ch--) *TempPtr++ = *(*MemGif2)++; } while (ch1); return(0); /* No FILE stream error occured */ } /* ** Read a GIF Graphic Control Extension block. ** ** Note that the Introducer and Label field values in the GIFGRAPHICCONTROL ** structure are assigned by the function calling ReadGifGraphicControl(). ** ** Returns: -1 if a FILE stream error occured during the read, ** otherwise 0 if no error occured. */ int ReadGifGraphicControl( GIFGRAPHICCONTROL *GifGraphicControl, /* Pointer to GC Extension structure */ BYTE **MemGif2 /* GIF image file input FILE stream */ ) { int i; for (i = 0 ; i < 5 ; i++) { GifGraphicControl->GCEDump[i] = *(*MemGif2)++; } return(0); /* No FILE stream error occured */ } /* ** Read a GIF Plain Text Extension block. ** ** Note that the Introducer and Label field values in the GIFLPLAINTEXT ** structure are assigned by the function calling ReadGifPlainText(). ** ** Returns: -1 if a FILE stream error occured during the read, ** otherwise 0 if no error occured. */ int ReadGifPlainText( GIFPLAINTEXT *GifPlainText, /* Pointer to Plain Text Extension structure */ BYTE **MemGif2 /* GIF image file input FILE stream */ ) { int i; for (i = 0 ; i < 13 ; i++) { GifPlainText->PTEDump[i] = *(*MemGif2)++; } /* Read in the Plain Text data sub-blocks */ if (!(GifPlainText->PlainTextData = ReadDataSubBlocks(MemGif2 , &(GifPlainText->DataSize)))) return(1); /* GifPlainText->Terminator = 0; */ /* Check for a FILE stream error */ /* if (ferror(FpGif)) return(-1); */ return(0); /* No FILE stream error occured */ } /* ** Read a GIF Application Extension block. ** ** Note that the Introducer and Label field values in the GIFAPPLICATION ** structure are assigned by the function calling ReadGifApplication(). ** ** Returns: -1 if a FILE stream error occured during the read, ** otherwise 0 if no error occured. */ int ReadGifApplication( GIFAPPLICATION *GifApplication, /* Pointer to Application Extension structure */ BYTE **MemGif2 /* GIF image file input FILE stream */ ) { int i; for (i = 0 ; i < 12 ; i++) { GifApplication->AEDump[i] = *(*MemGif2)++; } /* Read in the Plain Text data sub-blocks */ if (!(GifApplication->ApplicationData = ReadDataSubBlocks(MemGif2 , &(GifApplication->DataSize)))) return(1); /* GifApplication->Terminator = 0; */ /* Check for a FILE stream error */ /* if (ferror(FpGif)) return(-1); */ return(0); /* No FILE stream error occured */ } /* ** Read a GIF Comment Extension block. ** ** Note that the Introducer and Label field values in the GIFCOMMENT ** structure are assigned by the function calling ReadGifComment(). ** ** Returns: -1 if a FILE stream error occured during the read, ** otherwise 0 if no error occured. */ int ReadGifComment( GIFCOMMENT *GifComment, /* Pointer to GIF Comment Extension structure */ BYTE **MemGif2 /* GIF image file input FILE stream */ ) { /* Read in the Plain Text data sub-blocks */ if (!(GifComment->CommentData = ReadDataSubBlocks(MemGif2 , &(GifComment->DataSize)))) return(1); GifComment->Terminator = 0; return(0); /* No FILE stream error occured */ } /* ** Read one or more GIF data sub-blocks and write the information ** to a buffer. ** ** A GIF "sub-block" is a single count byte followed by 1 to 255 ** additional data bytes. ** ** Returns: A NULL pointer if a memory allocation error occured, ** otherwise a valid pointer if no error occured. */ static BYTE * ReadDataSubBlocks(BYTE **MemGif2, /* GIF image file input FILE stream */ WORD *DSize) { BYTE *ptr1; /* Pointer used to "walk the heap" */ BYTE *ptr2; /* Pointer used to mark the top of the heap */ BYTE dataSize; /* Size of the current data sub-block being read */ WORD bufSize; /* Total size of the Plain Text data buffer */ int tempcount = 0; bufSize = 0; /* The output buffer is empty */ dataSize = *(*MemGif2)++; /* Get the size of the first sub-block */ /* Allocate initial data buffer */ if (!(ptr1 = ptr2 = (BYTE *) malloc((size_t)dataSize + 1))) { printf("Out of memory. Allocation of memory for data sub-blocks for\neither Comment, Plain Text or Application Extensions failed"); return((BYTE *) NULL); } for (;;) { tempcount++; bufSize += (dataSize); /* Running total of the buffer size */ *DSize = bufSize; #ifdef COMMENTED_OUT *ptr1++ = dataSize; /* Write the data count */ #endif /* COMMENTED_OUT */ while (dataSize--) /* Read/write the Plain Text data */ *ptr1++ = *(*MemGif2)++; /* Check if there is another data sub-block */ if ((dataSize = *(*MemGif2)++) == 0) break; /* Block Terminator encountered */ /* Increase the buffer size to accomodate the next sub-block */ if (!(ptr1 = ptr2 = (BYTE *) realloc(ptr2, bufSize + dataSize + 1))) return((BYTE *) NULL); ptr1 += bufSize; /* Move pointer to the end of the data */ } *ptr1++ = '\0'; return(ptr2); /* Return a pointer to the sub-block data */ }