⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 gifalloc.c

📁 giflib-4.1.6.tar.gz,最新的GIF 解码库
💻 C
字号:
/***************************************************************************** *   "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.                      ****************************************************************************/#ifdef HAVE_CONFIG_H#include <config.h>#endif#include <stdlib.h>#include <stdio.h>#include <string.h>#include "gif_lib.h"#define MAX(x, y)    (((x) > (y)) ? (x) : (y))/****************************************************************************** * Miscellaneous utility functions                           *****************************************************************************//* return smallest bitfield size n will fit in */intBitSize(int n) {        register int i;    for (i = 1; i <= 8; i++)        if ((1 << i) >= n)            break;    return (i);}/****************************************************************************** * Color map object functions                               *****************************************************************************//* * Allocate a color map of given size; initialize with contents of * ColorMap if that pointer is non-NULL. */ColorMapObject *MakeMapObject(int ColorCount,              const GifColorType * ColorMap) {        ColorMapObject *Object;    /*** FIXME: Our ColorCount has to be a power of two.  Is it necessary to     * make the user know that or should we automatically round up instead? */    if (ColorCount != (1 << BitSize(ColorCount))) {        return ((ColorMapObject *) NULL);    }        Object = (ColorMapObject *)malloc(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);}/* * Free a color map object */voidFreeMapObject(ColorMapObject * Object) {    if (Object != NULL) {        free(Object->Colors);        free(Object);        /*** FIXME:         * When we are willing to break API we need to make this function         * FreeMapObject(ColorMapObject **Object)         * and do this assignment to NULL here:         * *Object = NULL;         */    }}#ifdef DEBUGvoidDumpColorMap(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 *//* * 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 is to ColorUnion, while colors from ColorIn2 are * copied iff they didn't exist before.  ColorTransIn2 maps the old * ColorIn2 into ColorUnion color map table. */ColorMapObject *UnionColorMap(const ColorMapObject * ColorIn1,              const ColorMapObject * ColorIn2,              GifPixelType ColorTransIn2[]) {    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; */    /*** FIXME: What if there are duplicate entries into the colormap to begin     * with? */    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].Blue == 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: */        /*** FIXME: Will it ever occur that ColorIn2 will contain duplicate         * entries?  So we should search from 0 to CrntSlot rather than         * ColorIn1->ColorCount?         */        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 *)realloc(Map,                                 sizeof(GifColorType) * RoundUpTo);    }    ColorUnion->ColorCount = RoundUpTo;    ColorUnion->BitsPerPixel = NewBitSize;    return (ColorUnion);}/* * Apply a given color translation to the raster bits of an image */voidApplyTranslation(SavedImage * Image,                 GifPixelType Translation[]) {    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                               *****************************************************************************/voidMakeExtension(SavedImage * New,              int Function) {    New->Function = Function;    /*** FIXME:     * Someday we might have to deal with multiple extensions.     * ??? Was this a note from Gershon or from me?  Does the multiple     * extension blocks solve this or do we need multiple Functions?  Or is     * this an obsolete function?  (People should use AddExtensionBlock     * instead?)     * Looks like AddExtensionBlock needs to take the int Function argument     * then it can take the place of this function.  Right now people have to     * use both.  Fix AddExtensionBlock and add this to the deprecation list.     */}intAddExtensionBlock(SavedImage * New,                  int Len,                  unsigned char ExtData[]) {    ExtensionBlock *ep;    if (New->ExtensionBlocks == NULL)        New->ExtensionBlocks=(ExtensionBlock *)malloc(sizeof(ExtensionBlock));    else        New->ExtensionBlocks = (ExtensionBlock *)realloc(New->ExtensionBlocks,                                      sizeof(ExtensionBlock) *                                      (New->ExtensionBlockCount + 1));    if (New->ExtensionBlocks == NULL)        return (GIF_ERROR);    ep = &New->ExtensionBlocks[New->ExtensionBlockCount++];    ep->ByteCount=Len;    ep->Bytes = (char *)malloc(ep->ByteCount);    if (ep->Bytes == NULL)        return (GIF_ERROR);    if (ExtData) {        memcpy(ep->Bytes, ExtData, Len);        ep->Function = New->Function;    }    return (GIF_OK);}voidFreeExtension(SavedImage * Image){    ExtensionBlock *ep;    if ((Image == NULL) || (Image->ExtensionBlocks == NULL)) {        return;    }    for (ep = Image->ExtensionBlocks;         ep < (Image->ExtensionBlocks + Image->ExtensionBlockCount); ep++)        (void)free((char *)ep->Bytes);    free((char *)Image->ExtensionBlocks);    Image->ExtensionBlocks = NULL;}/****************************************************************************** * Image block allocation functions                          ******************************************************************************//* Private Function: * Frees the last image in the GifFile->SavedImages array */voidFreeLastSavedImage(GifFileType *GifFile) {    SavedImage *sp;        if ((GifFile == NULL) || (GifFile->SavedImages == NULL))        return;    /* Remove one SavedImage from the GifFile */    GifFile->ImageCount--;    sp = &GifFile->SavedImages[GifFile->ImageCount];    /* Deallocate its Colormap */    if (sp->ImageDesc.ColorMap) {        FreeMapObject(sp->ImageDesc.ColorMap);        sp->ImageDesc.ColorMap = NULL;    }    /* Deallocate the image data */    if (sp->RasterBits)        free((char *)sp->RasterBits);    /* Deallocate any extensions */    if (sp->ExtensionBlocks)        FreeExtension(sp);    /*** FIXME: We could realloc the GifFile->SavedImages structure but is     * there a point to it? Saves some memory but we'd have to do it every     * time.  If this is used in FreeSavedImages then it would be inefficient     * (The whole array is going to be deallocated.)  If we just use it when     * we want to free the last Image it's convenient to do it here.     */}/* * Append an image block to the SavedImages array   */SavedImage *MakeSavedImage(GifFileType * GifFile,               const SavedImage * CopyFrom) {    SavedImage *sp;    if (GifFile->SavedImages == NULL)        GifFile->SavedImages = (SavedImage *)malloc(sizeof(SavedImage));    else        GifFile->SavedImages = (SavedImage *)realloc(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);                if (sp->ImageDesc.ColorMap == NULL) {                    FreeLastSavedImage(GifFile);                    return (SavedImage *)(NULL);                }            }            /* next, the raster */            sp->RasterBits = (unsigned char *)malloc(sizeof(GifPixelType) *                                                   CopyFrom->ImageDesc.Height *                                                   CopyFrom->ImageDesc.Width);            if (sp->RasterBits == NULL) {                FreeLastSavedImage(GifFile);                return (SavedImage *)(NULL);            }            memcpy(sp->RasterBits, CopyFrom->RasterBits,                   sizeof(GifPixelType) * CopyFrom->ImageDesc.Height *                   CopyFrom->ImageDesc.Width);            /* finally, the extension blocks */            if (sp->ExtensionBlocks) {                sp->ExtensionBlocks = (ExtensionBlock *)malloc(                                      sizeof(ExtensionBlock) *                                      CopyFrom->ExtensionBlockCount);                if (sp->ExtensionBlocks == NULL) {                    FreeLastSavedImage(GifFile);                    return (SavedImage *)(NULL);                }                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.                  *** FIXME: [Better check this out... Toshio]                 * 2004 May 27: Looks like this was an ESR note.                 * It means the blocks are shallow copied from InFile to                 * OutFile.  However, I don't see that in this code....                 * Did ESR fix it but never remove this note (And other notes                 * in gifspnge?)                 */            }        }        return (sp);    }}voidFreeSavedImages(GifFileType * GifFile) {    SavedImage *sp;    if ((GifFile == NULL) || (GifFile->SavedImages == NULL)) {        return;    }    for (sp = GifFile->SavedImages;         sp < GifFile->SavedImages + GifFile->ImageCount; sp++) {        if (sp->ImageDesc.ColorMap) {            FreeMapObject(sp->ImageDesc.ColorMap);            sp->ImageDesc.ColorMap = NULL;        }        if (sp->RasterBits)            free((char *)sp->RasterBits);        if (sp->ExtensionBlocks)            FreeExtension(sp);    }    free((char *)GifFile->SavedImages);    GifFile->SavedImages=NULL;}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -