Path: blob/master/src/java.desktop/share/native/libsplashscreen/giflib/gifalloc.c
41153 views
/*1* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.2*3* This code is free software; you can redistribute it and/or modify it4* under the terms of the GNU General Public License version 2 only, as5* published by the Free Software Foundation. Oracle designates this6* particular file as subject to the "Classpath" exception as provided7* by Oracle in the LICENSE file that accompanied this code.8*9* This code is distributed in the hope that it will be useful, but WITHOUT10* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or11* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License12* version 2 for more details (a copy is included in the LICENSE file that13* accompanied this code).14*15* You should have received a copy of the GNU General Public License version16* 2 along with this work; if not, write to the Free Software Foundation,17* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.18*19* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA20* or visit www.oracle.com if you need additional information or have any21* questions.22*/2324/*****************************************************************************2526GIF construction tools2728SPDX-License-Identifier: MIT2930****************************************************************************/3132#include <stdlib.h>33#include <stdio.h>34#include <string.h>3536#include "gif_lib.h"37#include "gif_lib_private.h"3839#define MAX(x, y) (((x) > (y)) ? (x) : (y))4041/******************************************************************************42Miscellaneous utility functions43******************************************************************************/4445/* return smallest bitfield size n will fit in */46int47GifBitSize(int n)48{49register int i;5051for (i = 1; i <= 8; i++)52if ((1 << i) >= n)53break;54return (i);55}5657/******************************************************************************58Color map object functions59******************************************************************************/6061/*62* Allocate a color map of given size; initialize with contents of63* ColorMap if that pointer is non-NULL.64*/65ColorMapObject *66GifMakeMapObject(int ColorCount, const GifColorType *ColorMap)67{68ColorMapObject *Object;6970/*** FIXME: Our ColorCount has to be a power of two. Is it necessary to71* make the user know that or should we automatically round up instead? */72if (ColorCount != (1 << GifBitSize(ColorCount))) {73return ((ColorMapObject *) NULL);74}7576Object = (ColorMapObject *)malloc(sizeof(ColorMapObject));77if (Object == (ColorMapObject *) NULL) {78return ((ColorMapObject *) NULL);79}8081Object->Colors = (GifColorType *)calloc(ColorCount, sizeof(GifColorType));82if (Object->Colors == (GifColorType *) NULL) {83free(Object);84return ((ColorMapObject *) NULL);85}8687Object->ColorCount = ColorCount;88Object->BitsPerPixel = GifBitSize(ColorCount);89Object->SortFlag = false;9091if (ColorMap != NULL) {92memcpy((char *)Object->Colors,93(char *)ColorMap, ColorCount * sizeof(GifColorType));94}9596return (Object);97}9899/*******************************************************************************100Free a color map object101*******************************************************************************/102void103GifFreeMapObject(ColorMapObject *Object)104{105if (Object != NULL) {106(void)free(Object->Colors);107(void)free(Object);108}109}110111#ifdef DEBUG112void113DumpColorMap(ColorMapObject *Object,114FILE * fp)115{116if (Object != NULL) {117int i, j, Len = Object->ColorCount;118119for (i = 0; i < Len; i += 4) {120for (j = 0; j < 4 && j < Len; j++) {121(void)fprintf(fp, "%3d: %02x %02x %02x ", i + j,122Object->Colors[i + j].Red,123Object->Colors[i + j].Green,124Object->Colors[i + j].Blue);125}126(void)fprintf(fp, "\n");127}128}129}130#endif /* DEBUG */131132/*******************************************************************************133Compute the union of two given color maps and return it. If result can't134fit into 256 colors, NULL is returned, the allocated union otherwise.135ColorIn1 is copied as is to ColorUnion, while colors from ColorIn2 are136copied iff they didn't exist before. ColorTransIn2 maps the old137ColorIn2 into the ColorUnion color map table./138*******************************************************************************/139ColorMapObject *140GifUnionColorMap(const ColorMapObject *ColorIn1,141const ColorMapObject *ColorIn2,142GifPixelType ColorTransIn2[])143{144int i, j, CrntSlot, RoundUpTo, NewGifBitSize;145ColorMapObject *ColorUnion;146147/*148* We don't worry about duplicates within either color map; if149* the caller wants to resolve those, he can perform unions150* with an empty color map.151*/152153/* Allocate table which will hold the result for sure. */154ColorUnion = GifMakeMapObject(MAX(ColorIn1->ColorCount,155ColorIn2->ColorCount) * 2, NULL);156157if (ColorUnion == NULL)158return (NULL);159160/*161* Copy ColorIn1 to ColorUnion.162*/163for (i = 0; i < ColorIn1->ColorCount; i++)164ColorUnion->Colors[i] = ColorIn1->Colors[i];165CrntSlot = ColorIn1->ColorCount;166167/*168* Potentially obnoxious hack:169*170* Back CrntSlot down past all contiguous {0, 0, 0} slots at the end171* of table 1. This is very useful if your display is limited to172* 16 colors.173*/174while (ColorIn1->Colors[CrntSlot - 1].Red == 0175&& ColorIn1->Colors[CrntSlot - 1].Green == 0176&& ColorIn1->Colors[CrntSlot - 1].Blue == 0)177CrntSlot--;178179/* Copy ColorIn2 to ColorUnion (use old colors if they exist): */180for (i = 0; i < ColorIn2->ColorCount && CrntSlot <= 256; i++) {181/* Let's see if this color already exists: */182for (j = 0; j < ColorIn1->ColorCount; j++)183if (memcmp (&ColorIn1->Colors[j], &ColorIn2->Colors[i],184sizeof(GifColorType)) == 0)185break;186187if (j < ColorIn1->ColorCount)188ColorTransIn2[i] = j; /* color exists in Color1 */189else {190/* Color is new - copy it to a new slot: */191ColorUnion->Colors[CrntSlot] = ColorIn2->Colors[i];192ColorTransIn2[i] = CrntSlot++;193}194}195196if (CrntSlot > 256) {197GifFreeMapObject(ColorUnion);198return ((ColorMapObject *) NULL);199}200201NewGifBitSize = GifBitSize(CrntSlot);202RoundUpTo = (1 << NewGifBitSize);203204if (RoundUpTo != ColorUnion->ColorCount) {205register GifColorType *Map = ColorUnion->Colors;206207/*208* Zero out slots up to next power of 2.209* We know these slots exist because of the way ColorUnion's210* start dimension was computed.211*/212for (j = CrntSlot; j < RoundUpTo; j++)213Map[j].Red = Map[j].Green = Map[j].Blue = 0;214215/* perhaps we can shrink the map? */216if (RoundUpTo < ColorUnion->ColorCount) {217GifColorType *new_map = (GifColorType *)reallocarray(Map,218RoundUpTo, sizeof(GifColorType));219if( new_map == NULL ) {220GifFreeMapObject(ColorUnion);221return ((ColorMapObject *) NULL);222}223ColorUnion->Colors = new_map;224}225}226227ColorUnion->ColorCount = RoundUpTo;228ColorUnion->BitsPerPixel = NewGifBitSize;229230return (ColorUnion);231}232233/*******************************************************************************234Apply a given color translation to the raster bits of an image235*******************************************************************************/236void237GifApplyTranslation(SavedImage *Image, GifPixelType Translation[])238{239register int i;240register int RasterSize = Image->ImageDesc.Height * Image->ImageDesc.Width;241242for (i = 0; i < RasterSize; i++)243Image->RasterBits[i] = Translation[Image->RasterBits[i]];244}245246/******************************************************************************247Extension record functions248******************************************************************************/249int250GifAddExtensionBlock(int *ExtensionBlockCount,251ExtensionBlock **ExtensionBlocks,252int Function,253unsigned int Len,254unsigned char ExtData[])255{256ExtensionBlock *ep;257258if (*ExtensionBlocks == NULL)259*ExtensionBlocks=(ExtensionBlock *)malloc(sizeof(ExtensionBlock));260else {261ExtensionBlock* ep_new = (ExtensionBlock *)reallocarray262(*ExtensionBlocks, (*ExtensionBlockCount + 1),263sizeof(ExtensionBlock));264if( ep_new == NULL )265return (GIF_ERROR);266*ExtensionBlocks = ep_new;267}268269if (*ExtensionBlocks == NULL)270return (GIF_ERROR);271272ep = &(*ExtensionBlocks)[(*ExtensionBlockCount)++];273274ep->Function = Function;275ep->ByteCount=Len;276ep->Bytes = (GifByteType *)malloc(ep->ByteCount);277if (ep->Bytes == NULL)278return (GIF_ERROR);279280if (ExtData != NULL) {281memcpy(ep->Bytes, ExtData, Len);282}283284return (GIF_OK);285}286287void288GifFreeExtensions(int *ExtensionBlockCount,289ExtensionBlock **ExtensionBlocks)290{291ExtensionBlock *ep;292293if (*ExtensionBlocks == NULL)294return;295296for (ep = *ExtensionBlocks;297ep < (*ExtensionBlocks + *ExtensionBlockCount);298ep++)299(void)free((char *)ep->Bytes);300(void)free((char *)*ExtensionBlocks);301*ExtensionBlocks = NULL;302*ExtensionBlockCount = 0;303}304305/******************************************************************************306Image block allocation functions307******************************************************************************/308309/* Private Function:310* Frees the last image in the GifFile->SavedImages array311*/312void313FreeLastSavedImage(GifFileType *GifFile)314{315SavedImage *sp;316317if ((GifFile == NULL) || (GifFile->SavedImages == NULL))318return;319320/* Remove one SavedImage from the GifFile */321GifFile->ImageCount--;322sp = &GifFile->SavedImages[GifFile->ImageCount];323324/* Deallocate its Colormap */325if (sp->ImageDesc.ColorMap != NULL) {326GifFreeMapObject(sp->ImageDesc.ColorMap);327sp->ImageDesc.ColorMap = NULL;328}329330/* Deallocate the image data */331if (sp->RasterBits != NULL)332free((char *)sp->RasterBits);333334/* Deallocate any extensions */335GifFreeExtensions(&sp->ExtensionBlockCount, &sp->ExtensionBlocks);336337/*** FIXME: We could realloc the GifFile->SavedImages structure but is338* there a point to it? Saves some memory but we'd have to do it every339* time. If this is used in GifFreeSavedImages then it would be inefficient340* (The whole array is going to be deallocated.) If we just use it when341* we want to free the last Image it's convenient to do it here.342*/343}344345/*346* Append an image block to the SavedImages array347*/348SavedImage *349GifMakeSavedImage(GifFileType *GifFile, const SavedImage *CopyFrom)350{351if (GifFile->SavedImages == NULL)352GifFile->SavedImages = (SavedImage *)malloc(sizeof(SavedImage));353else {354SavedImage* newSavedImages = (SavedImage *)reallocarray(GifFile->SavedImages,355(GifFile->ImageCount + 1), sizeof(SavedImage));356if( newSavedImages == NULL)357return ((SavedImage *)NULL);358GifFile->SavedImages = newSavedImages;359}360if (GifFile->SavedImages == NULL)361return ((SavedImage *)NULL);362else {363SavedImage *sp = &GifFile->SavedImages[GifFile->ImageCount++];364365if (CopyFrom != NULL) {366memcpy((char *)sp, CopyFrom, sizeof(SavedImage));367368/*369* Make our own allocated copies of the heap fields in the370* copied record. This guards against potential aliasing371* problems.372*/373374/* first, the local color map */375if (CopyFrom->ImageDesc.ColorMap != NULL) {376sp->ImageDesc.ColorMap = GifMakeMapObject(377CopyFrom->ImageDesc.ColorMap->ColorCount,378CopyFrom->ImageDesc.ColorMap->Colors);379if (sp->ImageDesc.ColorMap == NULL) {380FreeLastSavedImage(GifFile);381return (SavedImage *)(NULL);382}383}384385/* next, the raster */386sp->RasterBits = (unsigned char *)reallocarray(NULL,387(CopyFrom->ImageDesc.Height *388CopyFrom->ImageDesc.Width),389sizeof(GifPixelType));390if (sp->RasterBits == NULL) {391FreeLastSavedImage(GifFile);392return (SavedImage *)(NULL);393}394memcpy(sp->RasterBits, CopyFrom->RasterBits,395sizeof(GifPixelType) * CopyFrom->ImageDesc.Height *396CopyFrom->ImageDesc.Width);397398/* finally, the extension blocks */399if (CopyFrom->ExtensionBlocks != NULL) {400sp->ExtensionBlocks = (ExtensionBlock *)reallocarray(NULL,401CopyFrom->ExtensionBlockCount,402sizeof(ExtensionBlock));403if (sp->ExtensionBlocks == NULL) {404FreeLastSavedImage(GifFile);405return (SavedImage *)(NULL);406}407memcpy(sp->ExtensionBlocks, CopyFrom->ExtensionBlocks,408sizeof(ExtensionBlock) * CopyFrom->ExtensionBlockCount);409}410}411else {412memset((char *)sp, '\0', sizeof(SavedImage));413}414415return (sp);416}417}418419void420GifFreeSavedImages(GifFileType *GifFile)421{422SavedImage *sp;423424if ((GifFile == NULL) || (GifFile->SavedImages == NULL)) {425return;426}427for (sp = GifFile->SavedImages;428sp < GifFile->SavedImages + GifFile->ImageCount; sp++) {429if (sp->ImageDesc.ColorMap != NULL) {430GifFreeMapObject(sp->ImageDesc.ColorMap);431sp->ImageDesc.ColorMap = NULL;432}433434if (sp->RasterBits != NULL)435free((char *)sp->RasterBits);436437GifFreeExtensions(&sp->ExtensionBlockCount, &sp->ExtensionBlocks);438}439free((char *)GifFile->SavedImages);440GifFile->SavedImages = NULL;441}442443/* end */444445446