Back to index

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