gifalloc.c

Go to the documentation of this file.
00001 /*****************************************************************************
00002 *   "Gif-Lib" - Yet another gif library.                                     *
00003 *                                                                            *
00004 * Written by:  Gershon Elber                            Ver 0.1, Jun. 1989   *
00005 * Extensively hacked by: Eric S. Raymond                Ver 1.?, Sep 1992    *
00006 ******************************************************************************
00007 * GIF construction tools                                                      *
00008 ******************************************************************************
00009 * History:                                                                   *
00010 * 15 Sep 92 - Version 1.0 by Eric Raymond.                                   *
00011 *****************************************************************************/
00012 
00013 #ifdef HAVE_CONFIG_H
00014 #include <config.h>
00015 #endif
00016 
00017 #include <stdlib.h>
00018 #include <stdio.h>
00019 #include <string.h>
00020 #include "gif_lib.h"
00021 
00022 #define MAX(x, y)       (((x) > (y)) ? (x) : (y))
00023 
00024 /******************************************************************************
00025 * Miscellaneous utility functions                                             *
00026 ******************************************************************************/
00027 
00028 int BitSize(int n)
00029 /* return smallest bitfield size n will fit in */
00030 {
00031     register  int i;
00032 
00033     for (i = 1; i <= 8; i++)
00034         if ((1 << i) >= n)
00035             break;
00036     return(i);
00037 }
00038 
00039 
00040 /******************************************************************************
00041 * Color map object functions                                                  *
00042 ******************************************************************************/
00043 
00044 ColorMapObject *MakeMapObject(int ColorCount, const GifColorType *ColorMap)
00045 /*
00046  * Allocate a color map of given size; initialize with contents of
00047  * ColorMap if that pointer is non-NULL.
00048  */
00049 {
00050     ColorMapObject *Object;
00051 
00052     if (ColorCount != (1 << BitSize(ColorCount)))
00053         return((ColorMapObject *)NULL);
00054 
00055     Object = (ColorMapObject *)malloc(sizeof(ColorMapObject));
00056     if (Object == (ColorMapObject *)NULL)
00057         return((ColorMapObject *)NULL);
00058 
00059     Object->Colors = (GifColorType *)calloc(ColorCount, sizeof(GifColorType));
00060     if (Object->Colors == (GifColorType *)NULL)
00061         return((ColorMapObject *)NULL);
00062 
00063     Object->ColorCount = ColorCount;
00064     Object->BitsPerPixel = BitSize(ColorCount);
00065 
00066     if (ColorMap)
00067         memcpy((char *)Object->Colors,
00068                (char *)ColorMap, ColorCount * sizeof(GifColorType));
00069 
00070     return(Object);
00071 }
00072 
00073 void FreeMapObject(ColorMapObject *Object)
00074 /*
00075  * Free a color map object
00076  */
00077 {
00078     free(Object->Colors);
00079     free(Object);
00080 }
00081 
00082 #ifdef DEBUG
00083 void DumpColorMap(ColorMapObject *Object, FILE *fp)
00084 {
00085     if (Object)
00086     {
00087         int i, j, Len = Object->ColorCount;
00088 
00089         for (i = 0; i < Len; i+=4) {
00090             for (j = 0; j < 4 && j < Len; j++) {
00091                 fprintf(fp,
00092                         "%3d: %02x %02x %02x   ", i + j,
00093                        Object->Colors[i + j].Red,
00094                        Object->Colors[i + j].Green,
00095                        Object->Colors[i + j].Blue);
00096             }
00097             fprintf(fp, "\n");
00098         }
00099     }
00100 }
00101 #endif /* DEBUG */
00102 
00103 ColorMapObject *UnionColorMap(
00104                          const ColorMapObject *ColorIn1,
00105                          const ColorMapObject *ColorIn2,
00106                          GifPixelType ColorTransIn2[])
00107 /*
00108  * Compute the union of two given color maps and return it.  If result can't 
00109  * fit into 256 colors, NULL is returned, the allocated union otherwise.
00110  * ColorIn1 is copied as is to ColorUnion, while colors from ColorIn2 are
00111  * copied iff they didn't exist before.  ColorTransIn2 maps the old
00112  * ColorIn2 into ColorUnion color map table.
00113  */
00114 {
00115     int i, j, CrntSlot, RoundUpTo, NewBitSize;
00116     ColorMapObject *ColorUnion;
00117 
00118     /*
00119      * Allocate table which will hold the result for sure.
00120      */
00121     ColorUnion
00122         = MakeMapObject(MAX(ColorIn1->ColorCount,ColorIn2->ColorCount)*2,NULL);
00123 
00124     if (ColorUnion == NULL)
00125         return(NULL);
00126 
00127     /* Copy ColorIn1 to ColorUnionSize; */
00128     for (i = 0; i < ColorIn1->ColorCount; i++)
00129         ColorUnion->Colors[i] = ColorIn1->Colors[i];
00130     CrntSlot = ColorIn1->ColorCount;
00131 
00132     /*
00133      * Potentially obnoxious hack:
00134      *
00135      * Back CrntSlot down past all contiguous {0, 0, 0} slots at the end
00136      * of table 1.  This is very useful if your display is limited to
00137      * 16 colors.
00138      */
00139     while (ColorIn1->Colors[CrntSlot-1].Red == 0
00140            && ColorIn1->Colors[CrntSlot-1].Green == 0
00141            && ColorIn1->Colors[CrntSlot-1].Red == 0)
00142         CrntSlot--;
00143 
00144     /* Copy ColorIn2 to ColorUnionSize (use old colors if they exist): */
00145     for (i = 0; i < ColorIn2->ColorCount && CrntSlot<=256; i++)
00146     {
00147         /* Let's see if this color already exists: */
00148         for (j = 0; j < ColorIn1->ColorCount; j++)
00149             if (memcmp(&ColorIn1->Colors[j], &ColorIn2->Colors[i], sizeof(GifColorType)) == 0)
00150                 break;
00151 
00152         if (j < ColorIn1->ColorCount)
00153             ColorTransIn2[i] = j;       /* color exists in Color1 */
00154         else
00155         {
00156             /* Color is new - copy it to a new slot: */
00157             ColorUnion->Colors[CrntSlot] = ColorIn2->Colors[i];
00158             ColorTransIn2[i] = CrntSlot++;
00159         }
00160     }
00161 
00162     if (CrntSlot > 256)
00163     {
00164         FreeMapObject(ColorUnion);
00165         return((ColorMapObject *)NULL);
00166     }
00167 
00168     NewBitSize = BitSize(CrntSlot);
00169     RoundUpTo = (1 << NewBitSize);
00170 
00171     if (RoundUpTo != ColorUnion->ColorCount)
00172     {
00173         register GifColorType   *Map = ColorUnion->Colors;
00174 
00175         /*
00176          * Zero out slots up to next power of 2.
00177          * We know these slots exist because of the way ColorUnion's
00178          * start dimension was computed.
00179          */
00180         for (j = CrntSlot; j < RoundUpTo; j++)
00181             Map[j].Red = Map[j].Green = Map[j].Blue = 0;
00182 
00183         /* perhaps we can shrink the map? */
00184         if (RoundUpTo < ColorUnion->ColorCount)
00185             ColorUnion->Colors 
00186                 = (GifColorType *)realloc(Map, sizeof(GifColorType)*RoundUpTo);
00187     }
00188 
00189     ColorUnion->ColorCount = RoundUpTo;
00190     ColorUnion->BitsPerPixel = NewBitSize;
00191 
00192     return(ColorUnion);
00193 }
00194 
00195 void ApplyTranslation(SavedImage *Image, GifPixelType Translation[])
00196 /*
00197  * Apply a given color translation to the raster bits of an image
00198  */
00199 {
00200     register int i;
00201     register int RasterSize = Image->ImageDesc.Height * Image->ImageDesc.Width;
00202 
00203     for (i = 0; i < RasterSize; i++)
00204         Image->RasterBits[i] = Translation[(int)(Image->RasterBits[i])];
00205 }
00206 
00207 /******************************************************************************
00208 * Extension record functions                                                  *
00209 ******************************************************************************/
00210 
00211 void MakeExtension(SavedImage *New, int Function)
00212 {
00213     New->Function = Function;
00214     /*
00215      * Someday we might have to deal with multiple extensions.
00216      */
00217 }
00218 
00219 int AddExtensionBlock(SavedImage *New, int Len, char ExtData[])
00220 {
00221     ExtensionBlock      *ep;
00222 
00223     if (New->ExtensionBlocks == NULL)
00224         New->ExtensionBlocks = (ExtensionBlock *)malloc(sizeof(ExtensionBlock));
00225     else
00226         New->ExtensionBlocks =
00227             (ExtensionBlock *)realloc(New->ExtensionBlocks,
00228                       sizeof(ExtensionBlock) * (New->ExtensionBlockCount + 1));
00229 
00230     if (New->ExtensionBlocks == NULL)
00231         return(GIF_ERROR);
00232 
00233     ep = &New->ExtensionBlocks[New->ExtensionBlockCount++];
00234 
00235     if ((ep->Bytes = (char *)malloc(ep->ByteCount = Len)) == NULL)
00236         return(GIF_ERROR);
00237 
00238     if (ExtData) {
00239             memcpy(ep->Bytes, ExtData, Len);
00240         ep->Function = New->Function;
00241     }
00242 
00243     return(GIF_OK);
00244 }
00245 
00246 void FreeExtension(SavedImage *Image)
00247 {
00248     ExtensionBlock      *ep;
00249 
00250     for (ep = Image->ExtensionBlocks;
00251          ep < Image->ExtensionBlocks + Image->ExtensionBlockCount;
00252          ep++)
00253         (void) free((char *)ep->Bytes);
00254     free((char *)Image->ExtensionBlocks);
00255     Image->ExtensionBlocks = NULL;
00256 }
00257 
00258 /******************************************************************************
00259 * Image block allocation functions                                            *
00260 ******************************************************************************/
00261 SavedImage *MakeSavedImage(GifFileType *GifFile, const SavedImage *CopyFrom)
00262 /*
00263  * Append an image block to the SavedImages array  
00264  */
00265 {
00266     SavedImage  *sp;
00267 
00268     if (GifFile->SavedImages == NULL)
00269         GifFile->SavedImages = (SavedImage *)malloc(sizeof(SavedImage));
00270     else
00271         GifFile->SavedImages = (SavedImage *)realloc(GifFile->SavedImages,
00272                                 sizeof(SavedImage) * (GifFile->ImageCount+1));
00273 
00274     if (GifFile->SavedImages == NULL)
00275         return((SavedImage *)NULL);
00276     else
00277     {
00278         sp = &GifFile->SavedImages[GifFile->ImageCount++];
00279         memset((char *)sp, '\0', sizeof(SavedImage));
00280 
00281         if (CopyFrom)
00282         {
00283             memcpy((char *)sp, CopyFrom, sizeof(SavedImage));
00284 
00285             /*
00286              * Make our own allocated copies of the heap fields in the
00287              * copied record.  This guards against potential aliasing
00288              * problems.
00289              */
00290 
00291             /* first, the local color map */
00292             if (sp->ImageDesc.ColorMap)
00293                 sp->ImageDesc.ColorMap =
00294                     MakeMapObject(CopyFrom->ImageDesc.ColorMap->ColorCount,
00295                                   CopyFrom->ImageDesc.ColorMap->Colors);
00296 
00297             /* next, the raster */
00298             sp->RasterBits = (char *)malloc(sizeof(GifPixelType)
00299                                 * CopyFrom->ImageDesc.Height
00300                                 * CopyFrom->ImageDesc.Width);
00301             memcpy(sp->RasterBits,
00302                    CopyFrom->RasterBits,
00303                    sizeof(GifPixelType)
00304                         * CopyFrom->ImageDesc.Height
00305                         * CopyFrom->ImageDesc.Width);
00306 
00307             /* finally, the extension blocks */
00308             if (sp->ExtensionBlocks)
00309             {
00310                 sp->ExtensionBlocks
00311                     = (ExtensionBlock*)malloc(sizeof(ExtensionBlock)
00312                                               * CopyFrom->ExtensionBlockCount);
00313                 memcpy(sp->ExtensionBlocks,
00314                    CopyFrom->ExtensionBlocks,
00315                    sizeof(ExtensionBlock)
00316                         * CopyFrom->ExtensionBlockCount);
00317 
00318                 /*
00319                  * For the moment, the actual blocks can take their
00320                  * chances with free().  We'll fix this later. 
00321                  */
00322             }
00323         }
00324 
00325         return(sp);
00326     }
00327 }
00328 
00329 void FreeSavedImages(GifFileType *GifFile)
00330 {
00331     SavedImage  *sp;
00332 
00333     for (sp = GifFile->SavedImages;
00334          sp < GifFile->SavedImages + GifFile->ImageCount;
00335          sp++)
00336     {
00337         if (sp->ImageDesc.ColorMap)
00338             FreeMapObject(sp->ImageDesc.ColorMap);
00339 
00340         if (sp->RasterBits)
00341             free((char *)sp->RasterBits);
00342 
00343         if (sp->ExtensionBlocks)
00344             FreeExtension(sp);
00345     }
00346     free((char *) GifFile->SavedImages);
00347 }
00348 
00349 
00350 

Generated on Tue Jul 5 14:13:32 2011 for ROOT_528-00b_version by  doxygen 1.5.1