Mercurial > hg > xemacs-beta
diff src/gifalloc.c @ 0:376386a54a3c r19-14
Import from CVS: tag r19-14
author | cvs |
---|---|
date | Mon, 13 Aug 2007 08:45:50 +0200 |
parents | |
children | 43dd3413c7c7 |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/gifalloc.c Mon Aug 13 08:45:50 2007 +0200 @@ -0,0 +1,370 @@ +/* Synched up with: Not in FSF. */ + +/***************************************************************************** +* "Gif-Lib" - Yet another gif library. * +* * +* Written by: Gershon Elber Ver 0.1, Jun. 1989 * +* Extensively hacked by: Eric S. Raymond Ver 1.?, Sep 1992 * +****************************************************************************** +* GIF construction tools * +****************************************************************************** +* History: * +* 15 Sep 92 - Version 1.0 by Eric Raymond. * +*****************************************************************************/ +#include <stdio.h> +#include <string.h> +#include <stdlib.h> + +#ifdef emacs +#include <config.h> + +void *xmalloc (unsigned int size); +void *xrealloc (void *ptr, unsigned int size); +#ifdef ERROR_CHECK_MALLOC +void *xfree_1 (void *); +#define xfree xfree_1 +#else +void *xfree (void *); +#endif +#endif + +#include "gif_lib.h" + +#ifndef MAX +#define MAX(x, y) (((x) > (y)) ? (x) : (y)) +#endif + +/****************************************************************************** +* Miscellaneous utility functions * +******************************************************************************/ + +int BitSize(int n) +/* return smallest bitfield size n will fit in */ +{ + register i; + + for (i = 1; i <= 8; i++) + if ((1 << i) >= n) + break; + return(i); +} + + +/****************************************************************************** +* Color map object functions * +******************************************************************************/ + +ColorMapObject *MakeMapObject(int ColorCount, GifColorType *ColorMap) +/* + * Allocate a color map of given size; initialize with contents of + * ColorMap if that pointer is non-NULL. + */ +{ + ColorMapObject *Object; + + if (ColorCount != (1 << BitSize(ColorCount))) + return((ColorMapObject *)NULL); + + Object = (ColorMapObject *)xmalloc(sizeof(ColorMapObject)); + if (Object == (ColorMapObject *)NULL) + return((ColorMapObject *)NULL); + + Object->Colors = (GifColorType *)calloc(ColorCount, sizeof(GifColorType)); + if (Object->Colors == (GifColorType *)NULL) + return((ColorMapObject *)NULL); + + Object->ColorCount = ColorCount; + Object->BitsPerPixel = BitSize(ColorCount); + + if (ColorMap) + memcpy((char *)Object->Colors, + (char *)ColorMap, ColorCount * sizeof(GifColorType)); + + return(Object); +} + +void FreeMapObject(ColorMapObject *Object) +/* + * Free a color map object + */ +{ + xfree(Object->Colors); + xfree(Object); +} + +#ifdef DEBUG +void DumpColorMap(ColorMapObject *Object, FILE *fp) +{ + if (Object) + { + int i, j, Len = Object->ColorCount; + + for (i = 0; i < Len; i+=4) { + for (j = 0; j < 4 && j < Len; j++) { + fprintf(fp, + "%3d: %02x %02x %02x ", i + j, + Object->Colors[i + j].Red, + Object->Colors[i + j].Green, + Object->Colors[i + j].Blue); + } + fprintf(fp, "\n"); + } + } +} +#endif /* DEBUG */ + +ColorMapObject *UnionColorMap( + ColorMapObject *ColorIn1, + ColorMapObject *ColorIn2, + GifPixelType ColorTransIn2[]) +/* + * Compute the union of two given color maps and return it. If result can't + * fit into 256 colors, NULL is returned, the allocated union otherwise. + * ColorIn1 is copied as it to ColorUnion, while colors from ColorIn2 are + * copied iff they didn't exist before. ColorTransIn2 maps the old + * ColorIn2 into ColorUnion color map table. + */ +{ + int i, j, CrntSlot, RoundUpTo, NewBitSize; + ColorMapObject *ColorUnion; + + /* + * Allocate table which will hold the result for sure. + */ + ColorUnion + = MakeMapObject(MAX(ColorIn1->ColorCount,ColorIn2->ColorCount)*2,NULL); + + if (ColorUnion == NULL) + return(NULL); + + /* Copy ColorIn1 to ColorUnionSize; */ + for (i = 0; i < ColorIn1->ColorCount; i++) + ColorUnion->Colors[i] = ColorIn1->Colors[i]; + CrntSlot = ColorIn1->ColorCount; + + /* + * Potentially obnoxious hack: + * + * Back CrntSlot down past all contiguous {0, 0, 0} slots at the end + * of table 1. This is very useful if your display is limited to + * 16 colors. + */ + while (ColorIn1->Colors[CrntSlot-1].Red == 0 + && ColorIn1->Colors[CrntSlot-1].Green == 0 + && ColorIn1->Colors[CrntSlot-1].Red == 0) + CrntSlot--; + + /* Copy ColorIn2 to ColorUnionSize (use old colors if they exist): */ + for (i = 0; i < ColorIn2->ColorCount && CrntSlot<=256; i++) + { + /* Let's see if this color already exists: */ + for (j = 0; j < ColorIn1->ColorCount; j++) + if (memcmp(&ColorIn1->Colors[j], &ColorIn2->Colors[i], sizeof(GifColorType)) == 0) + break; + + if (j < ColorIn1->ColorCount) + ColorTransIn2[i] = j; /* color exists in Color1 */ + else + { + /* Color is new - copy it to a new slot: */ + ColorUnion->Colors[CrntSlot] = ColorIn2->Colors[i]; + ColorTransIn2[i] = CrntSlot++; + } + } + + if (CrntSlot > 256) + { + FreeMapObject(ColorUnion); + return((ColorMapObject *)NULL); + } + + NewBitSize = BitSize(CrntSlot); + RoundUpTo = (1 << NewBitSize); + + if (RoundUpTo != ColorUnion->ColorCount) + { + register GifColorType *Map = ColorUnion->Colors; + + /* + * Zero out slots up to next power of 2. + * We know these slots exist because of the way ColorUnion's + * start dimension was computed. + */ + for (j = CrntSlot; j < RoundUpTo; j++) + Map[j].Red = Map[j].Green = Map[j].Blue = 0; + + /* perhaps we can shrink the map? */ + if (RoundUpTo < ColorUnion->ColorCount) + ColorUnion->Colors + = (GifColorType *)xrealloc(Map, sizeof(GifColorType)*RoundUpTo); + } + + ColorUnion->ColorCount = RoundUpTo; + ColorUnion->BitsPerPixel = NewBitSize; + + return(ColorUnion); +} + +void ApplyTranslation(SavedImage *Image, GifPixelType Translation[]) +/* + * Apply a given color translation to the raster bits of an image + */ +{ + register int i; + register int RasterSize = Image->ImageDesc.Height * Image->ImageDesc.Width; + + for (i = 0; i < RasterSize; i++) + Image->RasterBits[i] = Translation[Image->RasterBits[i]]; +} + +/****************************************************************************** +* Extension record functions * +******************************************************************************/ + +void MakeExtension(SavedImage *New, int Function) +{ + New->Function = Function; + /* + * Someday we might have to deal with multiple extensions. + */ +} + +int AddExtensionBlock(SavedImage *New, int Len, char ExtData[]) +{ + ExtensionBlock *ep; + + if (New->ExtensionBlocks == NULL) + New->ExtensionBlocks = (ExtensionBlock *)xmalloc(sizeof(ExtensionBlock)); + else + New->ExtensionBlocks = + (ExtensionBlock *)xrealloc(New->ExtensionBlocks, + sizeof(ExtensionBlock) * (New->ExtensionBlockCount + 1)); + + if (New->ExtensionBlocks == NULL) + return(GIF_ERROR); + + ep = &New->ExtensionBlocks[New->ExtensionBlockCount++]; + + if ((ep->Bytes = (GifByteType *)xmalloc(ep->ByteCount = Len)) == NULL) + return(GIF_ERROR); + + if (ExtData) + memcpy(ep->Bytes, ExtData, Len); + + return(GIF_OK); +} + +void FreeExtension(SavedImage *Image) +{ + ExtensionBlock *ep; + + for (ep = Image->ExtensionBlocks; + ep < Image->ExtensionBlocks + Image->ExtensionBlockCount; + ep++) + (void) xfree((char *)ep->Bytes); + xfree((char *)Image->ExtensionBlocks); + Image->ExtensionBlocks = NULL; +} + +/****************************************************************************** +* Image block allocation functions * +******************************************************************************/ +SavedImage *MakeSavedImage(GifFileType *GifFile, SavedImage *CopyFrom) +/* + * Append an image block to the SavedImages array + */ +{ + SavedImage *sp; + + if (GifFile->SavedImages == NULL) + GifFile->SavedImages = (SavedImage *)xmalloc(sizeof(SavedImage)); + else + GifFile->SavedImages = (SavedImage *)xrealloc(GifFile->SavedImages, + sizeof(SavedImage) * (GifFile->ImageCount+1)); + + if (GifFile->SavedImages == NULL) + return((SavedImage *)NULL); + else + { + sp = &GifFile->SavedImages[GifFile->ImageCount++]; + memset((char *)sp, '\0', sizeof(SavedImage)); + + if (CopyFrom) + { + memcpy((char *)sp, CopyFrom, sizeof(SavedImage)); + + /* + * Make our own allocated copies of the heap fields in the + * copied record. This guards against potential aliasing + * problems. + */ + + /* first, the local color map */ + if (sp->ImageDesc.ColorMap) + sp->ImageDesc.ColorMap = + MakeMapObject(CopyFrom->ImageDesc.ColorMap->ColorCount, + CopyFrom->ImageDesc.ColorMap->Colors); + + /* next, the raster */ + sp->RasterBits = (GifPixelType *)xmalloc(sizeof(GifPixelType) + * CopyFrom->ImageDesc.Height + * CopyFrom->ImageDesc.Width); + memcpy(sp->RasterBits, + CopyFrom->RasterBits, + sizeof(GifPixelType) + * CopyFrom->ImageDesc.Height + * CopyFrom->ImageDesc.Width); + + /* finally, the extension blocks */ + if (sp->ExtensionBlocks) + { + sp->ExtensionBlocks + = (ExtensionBlock*)xmalloc(sizeof(ExtensionBlock) + * CopyFrom->ExtensionBlockCount); + memcpy(sp->ExtensionBlocks, + CopyFrom->ExtensionBlocks, + sizeof(ExtensionBlock) + * CopyFrom->ExtensionBlockCount); + + /* + * For the moment, the actual blocks can take their + * chances with free(). We'll fix this later. + */ + } + } + + return(sp); + } +} + +void FreeSavedImages(GifFileType *GifFile) +{ + SavedImage *sp; + + for (sp = GifFile->SavedImages; + sp < GifFile->SavedImages + GifFile->ImageCount; + sp++) + { + if (sp->ImageDesc.ColorMap) + { + FreeMapObject(sp->ImageDesc.ColorMap); + sp->ImageDesc.ColorMap = 0; + } + + if (sp->RasterBits) + { + xfree((char *)sp->RasterBits); + sp->RasterBits = 0; + } + + if (sp->ExtensionBlocks) + { + FreeExtension(sp); + sp->ExtensionBlocks = 0; + } + } + xfree((char *) GifFile->SavedImages); +} + + +