0N/A/*
553N/A * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
0N/A *
0N/A * This code is free software; you can redistribute it and/or modify it
0N/A * under the terms of the GNU General Public License version 2 only, as
0N/A * published by the Free Software Foundation. Oracle designates this
0N/A * particular file as subject to the "Classpath" exception as provided
0N/A * by Oracle in the LICENSE file that accompanied this code.
0N/A *
0N/A * This code is distributed in the hope that it will be useful, but WITHOUT
0N/A * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
0N/A * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
0N/A * version 2 for more details (a copy is included in the LICENSE file that
0N/A * accompanied this code).
0N/A *
0N/A * You should have received a copy of the GNU General Public License version
0N/A * 2 along with this work; if not, write to the Free Software Foundation,
0N/A * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
553N/A *
553N/A * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
553N/A * or visit www.oracle.com if you need additional information or have any
0N/A * questions.
0N/A */
0N/A
0N/A/*****************************************************************************
0N/A * "Gif-Lib" - Yet another gif library.
0N/A *
0N/A * Written by: Gershon Elber Ver 0.1, Jun. 1989
0N/A * Extensively hacked by: Eric S. Raymond Ver 1.?, Sep 1992
0N/A *****************************************************************************
0N/A * GIF construction tools
0N/A *****************************************************************************
0N/A * History:
0N/A * 15 Sep 92 - Version 1.0 by Eric Raymond.
0N/A ****************************************************************************/
0N/A
0N/A#ifdef HAVE_CONFIG_H
0N/A#include <config.h>
0N/A#endif
0N/A
0N/A#include <stdlib.h>
0N/A#include <stdio.h>
0N/A#include <string.h>
0N/A#include "gif_lib.h"
0N/A
0N/A#define MAX(x, y) (((x) > (y)) ? (x) : (y))
0N/A
0N/A/******************************************************************************
0N/A * Miscellaneous utility functions
0N/A *****************************************************************************/
0N/A
0N/A/* return smallest bitfield size n will fit in */
0N/Aint
0N/ABitSize(int n) {
0N/A
0N/A register int i;
0N/A
0N/A for (i = 1; i <= 8; i++)
0N/A if ((1 << i) >= n)
0N/A break;
0N/A return (i);
0N/A}
0N/A
0N/A/******************************************************************************
0N/A * Color map object functions
0N/A *****************************************************************************/
0N/A
0N/A/*
0N/A * Allocate a color map of given size; initialize with contents of
0N/A * ColorMap if that pointer is non-NULL.
0N/A */
0N/AColorMapObject *
0N/AMakeMapObject(int ColorCount,
0N/A const GifColorType * ColorMap) {
0N/A
0N/A ColorMapObject *Object;
0N/A
0N/A /*** FIXME: Our ColorCount has to be a power of two. Is it necessary to
0N/A * make the user know that or should we automatically round up instead? */
0N/A if (ColorCount != (1 << BitSize(ColorCount))) {
0N/A return ((ColorMapObject *) NULL);
0N/A }
0N/A
0N/A Object = (ColorMapObject *)malloc(sizeof(ColorMapObject));
0N/A if (Object == (ColorMapObject *) NULL) {
0N/A return ((ColorMapObject *) NULL);
0N/A }
0N/A
0N/A Object->Colors = (GifColorType *)calloc(ColorCount, sizeof(GifColorType));
0N/A if (Object->Colors == (GifColorType *) NULL) {
0N/A free(Object);
0N/A return ((ColorMapObject *) NULL);
0N/A }
0N/A
0N/A Object->ColorCount = ColorCount;
0N/A Object->BitsPerPixel = BitSize(ColorCount);
0N/A
0N/A if (ColorMap) {
0N/A memcpy((char *)Object->Colors,
0N/A (char *)ColorMap, ColorCount * sizeof(GifColorType));
0N/A }
0N/A
0N/A return (Object);
0N/A}
0N/A
0N/A/*
0N/A * Free a color map object
0N/A */
0N/Avoid
0N/AFreeMapObject(ColorMapObject * Object) {
0N/A
0N/A if (Object != NULL) {
0N/A free(Object->Colors);
0N/A free(Object);
0N/A Object = NULL;
0N/A }
0N/A}
0N/A
0N/A#ifdef DEBUG
0N/Avoid
0N/ADumpColorMap(ColorMapObject * Object,
0N/A FILE * fp) {
0N/A
0N/A if (Object) {
0N/A int i, j, Len = Object->ColorCount;
0N/A
0N/A for (i = 0; i < Len; i += 4) {
0N/A for (j = 0; j < 4 && j < Len; j++) {
0N/A fprintf(fp, "%3d: %02x %02x %02x ", i + j,
0N/A Object->Colors[i + j].Red,
0N/A Object->Colors[i + j].Green,
0N/A Object->Colors[i + j].Blue);
0N/A }
0N/A fprintf(fp, "\n");
0N/A }
0N/A }
0N/A}
0N/A#endif /* DEBUG */
0N/A
0N/A/******************************************************************************
0N/A * Extension record functions
0N/A *****************************************************************************/
0N/A
0N/Avoid
0N/AMakeExtension(SavedImage * New,
0N/A int Function) {
0N/A
0N/A New->Function = Function;
0N/A /*** FIXME:
0N/A * Someday we might have to deal with multiple extensions.
0N/A * ??? Was this a note from Gershon or from me? Does the multiple
0N/A * extension blocks solve this or do we need multiple Functions? Or is
0N/A * this an obsolete function? (People should use AddExtensionBlock
0N/A * instead?)
0N/A * Looks like AddExtensionBlock needs to take the int Function argument
0N/A * then it can take the place of this function. Right now people have to
0N/A * use both. Fix AddExtensionBlock and add this to the deprecation list.
0N/A */
0N/A}
0N/A
0N/Aint
0N/AAddExtensionBlock(SavedImage * New,
0N/A int Len,
0N/A unsigned char ExtData[]) {
0N/A
0N/A ExtensionBlock *ep;
0N/A
0N/A if (New->ExtensionBlocks == NULL)
0N/A New->ExtensionBlocks=(ExtensionBlock *)malloc(sizeof(ExtensionBlock));
0N/A else
0N/A New->ExtensionBlocks = (ExtensionBlock *)realloc(New->ExtensionBlocks,
0N/A sizeof(ExtensionBlock) *
0N/A (New->ExtensionBlockCount + 1));
0N/A
0N/A if (New->ExtensionBlocks == NULL)
0N/A return (GIF_ERROR);
0N/A
0N/A ep = &New->ExtensionBlocks[New->ExtensionBlockCount++];
0N/A
0N/A ep->ByteCount=Len;
0N/A ep->Bytes = (char *)malloc(ep->ByteCount);
0N/A if (ep->Bytes == NULL)
0N/A return (GIF_ERROR);
0N/A
0N/A if (ExtData) {
0N/A memcpy(ep->Bytes, ExtData, Len);
0N/A ep->Function = New->Function;
0N/A }
0N/A
0N/A return (GIF_OK);
0N/A}
0N/A
0N/Avoid
0N/AFreeExtension(SavedImage * Image)
0N/A{
0N/A ExtensionBlock *ep;
0N/A
0N/A if ((Image == NULL) || (Image->ExtensionBlocks == NULL)) {
0N/A return;
0N/A }
0N/A for (ep = Image->ExtensionBlocks;
0N/A ep < (Image->ExtensionBlocks + Image->ExtensionBlockCount); ep++)
0N/A (void)free((char *)ep->Bytes);
0N/A free((char *)Image->ExtensionBlocks);
0N/A Image->ExtensionBlocks = NULL;
0N/A}
0N/A
0N/A/******************************************************************************
0N/A * Image block allocation functions
0N/A******************************************************************************/
0N/A
0N/A/* Private Function:
0N/A * Frees the last image in the GifFile->SavedImages array
0N/A */
0N/Avoid
0N/AFreeLastSavedImage(GifFileType *GifFile) {
0N/A
0N/A SavedImage *sp;
0N/A
0N/A if ((GifFile == NULL) || (GifFile->SavedImages == NULL))
0N/A return;
0N/A
0N/A /* Remove one SavedImage from the GifFile */
0N/A GifFile->ImageCount--;
0N/A sp = &GifFile->SavedImages[GifFile->ImageCount];
0N/A
0N/A /* Deallocate its Colormap */
0N/A if (sp->ImageDesc.ColorMap)
0N/A FreeMapObject(sp->ImageDesc.ColorMap);
0N/A
0N/A /* Deallocate the image data */
0N/A 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);
}
}
void
FreeSavedImages(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);
if (sp->RasterBits)
free((char *)sp->RasterBits);
if (sp->ExtensionBlocks)
FreeExtension(sp);
}
free((char *)GifFile->SavedImages);
GifFile->SavedImages=NULL;
}