1c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project/***************************************************************************** 29aef3ea079a57c98a9207f8c3b95a5dc08ee74b5Chris Craik 39aef3ea079a57c98a9207f8c3b95a5dc08ee74b5Chris Craik GIF construction tools 49aef3ea079a57c98a9207f8c3b95a5dc08ee74b5Chris Craik 59aef3ea079a57c98a9207f8c3b95a5dc08ee74b5Chris Craik****************************************************************************/ 6c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project 7c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project#include <stdlib.h> 8c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project#include <stdio.h> 9c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project#include <string.h> 109aef3ea079a57c98a9207f8c3b95a5dc08ee74b5Chris Craik 11c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project#include "gif_lib.h" 12c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project 13c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project#define MAX(x, y) (((x) > (y)) ? (x) : (y)) 14c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project 15c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project/****************************************************************************** 169aef3ea079a57c98a9207f8c3b95a5dc08ee74b5Chris Craik Miscellaneous utility functions 179aef3ea079a57c98a9207f8c3b95a5dc08ee74b5Chris Craik******************************************************************************/ 18c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project 19c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project/* return smallest bitfield size n will fit in */ 20c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Projectint 219aef3ea079a57c98a9207f8c3b95a5dc08ee74b5Chris CraikGifBitSize(int n) 229aef3ea079a57c98a9207f8c3b95a5dc08ee74b5Chris Craik{ 23c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project register int i; 24c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project 25c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project for (i = 1; i <= 8; i++) 26c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project if ((1 << i) >= n) 27c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project break; 28c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project return (i); 29c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project} 30c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project 31c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project/****************************************************************************** 329aef3ea079a57c98a9207f8c3b95a5dc08ee74b5Chris Craik Color map object functions 339aef3ea079a57c98a9207f8c3b95a5dc08ee74b5Chris Craik******************************************************************************/ 34c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project 35c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project/* 36c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project * Allocate a color map of given size; initialize with contents of 37c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project * ColorMap if that pointer is non-NULL. 38c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project */ 39c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source ProjectColorMapObject * 409aef3ea079a57c98a9207f8c3b95a5dc08ee74b5Chris CraikGifMakeMapObject(int ColorCount, const GifColorType *ColorMap) 419aef3ea079a57c98a9207f8c3b95a5dc08ee74b5Chris Craik{ 42c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project ColorMapObject *Object; 43c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project 44c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project /*** FIXME: Our ColorCount has to be a power of two. Is it necessary to 45c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project * make the user know that or should we automatically round up instead? */ 469aef3ea079a57c98a9207f8c3b95a5dc08ee74b5Chris Craik if (ColorCount != (1 << GifBitSize(ColorCount))) { 47c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project return ((ColorMapObject *) NULL); 48c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project } 49c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project 50c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project Object = (ColorMapObject *)malloc(sizeof(ColorMapObject)); 51c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project if (Object == (ColorMapObject *) NULL) { 52c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project return ((ColorMapObject *) NULL); 53c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project } 54c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project 55c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project Object->Colors = (GifColorType *)calloc(ColorCount, sizeof(GifColorType)); 56c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project if (Object->Colors == (GifColorType *) NULL) { 579aef3ea079a57c98a9207f8c3b95a5dc08ee74b5Chris Craik free(Object); 58c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project return ((ColorMapObject *) NULL); 59c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project } 60c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project 61c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project Object->ColorCount = ColorCount; 629aef3ea079a57c98a9207f8c3b95a5dc08ee74b5Chris Craik Object->BitsPerPixel = GifBitSize(ColorCount); 63c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project 649aef3ea079a57c98a9207f8c3b95a5dc08ee74b5Chris Craik if (ColorMap != NULL) { 65c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project memcpy((char *)Object->Colors, 66c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project (char *)ColorMap, ColorCount * sizeof(GifColorType)); 67c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project } 68c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project 69c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project return (Object); 70c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project} 71c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project 729aef3ea079a57c98a9207f8c3b95a5dc08ee74b5Chris Craik/******************************************************************************* 739aef3ea079a57c98a9207f8c3b95a5dc08ee74b5Chris CraikFree a color map object 749aef3ea079a57c98a9207f8c3b95a5dc08ee74b5Chris Craik*******************************************************************************/ 75c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Projectvoid 769aef3ea079a57c98a9207f8c3b95a5dc08ee74b5Chris CraikGifFreeMapObject(ColorMapObject *Object) 779aef3ea079a57c98a9207f8c3b95a5dc08ee74b5Chris Craik{ 78c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project if (Object != NULL) { 799aef3ea079a57c98a9207f8c3b95a5dc08ee74b5Chris Craik (void)free(Object->Colors); 809aef3ea079a57c98a9207f8c3b95a5dc08ee74b5Chris Craik (void)free(Object); 81c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project } 82c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project} 83c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project 84c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project#ifdef DEBUG 85c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Projectvoid 869aef3ea079a57c98a9207f8c3b95a5dc08ee74b5Chris CraikDumpColorMap(ColorMapObject *Object, 879aef3ea079a57c98a9207f8c3b95a5dc08ee74b5Chris Craik FILE * fp) 889aef3ea079a57c98a9207f8c3b95a5dc08ee74b5Chris Craik{ 899aef3ea079a57c98a9207f8c3b95a5dc08ee74b5Chris Craik if (Object != NULL) { 90c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project int i, j, Len = Object->ColorCount; 91c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project 92c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project for (i = 0; i < Len; i += 4) { 93c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project for (j = 0; j < 4 && j < Len; j++) { 949aef3ea079a57c98a9207f8c3b95a5dc08ee74b5Chris Craik (void)fprintf(fp, "%3d: %02x %02x %02x ", i + j, 959aef3ea079a57c98a9207f8c3b95a5dc08ee74b5Chris Craik Object->Colors[i + j].Red, 969aef3ea079a57c98a9207f8c3b95a5dc08ee74b5Chris Craik Object->Colors[i + j].Green, 979aef3ea079a57c98a9207f8c3b95a5dc08ee74b5Chris Craik Object->Colors[i + j].Blue); 98c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project } 999aef3ea079a57c98a9207f8c3b95a5dc08ee74b5Chris Craik (void)fprintf(fp, "\n"); 100c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project } 101c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project } 102c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project} 103c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project#endif /* DEBUG */ 104c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project 1059aef3ea079a57c98a9207f8c3b95a5dc08ee74b5Chris Craik/******************************************************************************* 1069aef3ea079a57c98a9207f8c3b95a5dc08ee74b5Chris Craik Compute the union of two given color maps and return it. If result can't 1079aef3ea079a57c98a9207f8c3b95a5dc08ee74b5Chris Craik fit into 256 colors, NULL is returned, the allocated union otherwise. 1089aef3ea079a57c98a9207f8c3b95a5dc08ee74b5Chris Craik ColorIn1 is copied as is to ColorUnion, while colors from ColorIn2 are 1099aef3ea079a57c98a9207f8c3b95a5dc08ee74b5Chris Craik copied iff they didn't exist before. ColorTransIn2 maps the old 1109aef3ea079a57c98a9207f8c3b95a5dc08ee74b5Chris Craik ColorIn2 into the ColorUnion color map table./ 1119aef3ea079a57c98a9207f8c3b95a5dc08ee74b5Chris Craik*******************************************************************************/ 112c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source ProjectColorMapObject * 1139aef3ea079a57c98a9207f8c3b95a5dc08ee74b5Chris CraikGifUnionColorMap(const ColorMapObject *ColorIn1, 1149aef3ea079a57c98a9207f8c3b95a5dc08ee74b5Chris Craik const ColorMapObject *ColorIn2, 1159aef3ea079a57c98a9207f8c3b95a5dc08ee74b5Chris Craik GifPixelType ColorTransIn2[]) 1169aef3ea079a57c98a9207f8c3b95a5dc08ee74b5Chris Craik{ 1179aef3ea079a57c98a9207f8c3b95a5dc08ee74b5Chris Craik int i, j, CrntSlot, RoundUpTo, NewGifBitSize; 118c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project ColorMapObject *ColorUnion; 119c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project 1209aef3ea079a57c98a9207f8c3b95a5dc08ee74b5Chris Craik /* 1219aef3ea079a57c98a9207f8c3b95a5dc08ee74b5Chris Craik * We don't worry about duplicates within either color map; if 1229aef3ea079a57c98a9207f8c3b95a5dc08ee74b5Chris Craik * the caller wants to resolve those, he can perform unions 1239aef3ea079a57c98a9207f8c3b95a5dc08ee74b5Chris Craik * with an empty color map. 124c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project */ 1259aef3ea079a57c98a9207f8c3b95a5dc08ee74b5Chris Craik 1269aef3ea079a57c98a9207f8c3b95a5dc08ee74b5Chris Craik /* Allocate table which will hold the result for sure. */ 1279aef3ea079a57c98a9207f8c3b95a5dc08ee74b5Chris Craik ColorUnion = GifMakeMapObject(MAX(ColorIn1->ColorCount, 128c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project ColorIn2->ColorCount) * 2, NULL); 129c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project 130c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project if (ColorUnion == NULL) 131c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project return (NULL); 132c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project 1339aef3ea079a57c98a9207f8c3b95a5dc08ee74b5Chris Craik /* 1349aef3ea079a57c98a9207f8c3b95a5dc08ee74b5Chris Craik * Copy ColorIn1 to ColorUnion. 1359aef3ea079a57c98a9207f8c3b95a5dc08ee74b5Chris Craik */ 136c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project for (i = 0; i < ColorIn1->ColorCount; i++) 137c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project ColorUnion->Colors[i] = ColorIn1->Colors[i]; 138c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project CrntSlot = ColorIn1->ColorCount; 139c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project 140c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project /* 141c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project * Potentially obnoxious hack: 142c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project * 143c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project * Back CrntSlot down past all contiguous {0, 0, 0} slots at the end 144c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project * of table 1. This is very useful if your display is limited to 145c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project * 16 colors. 146c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project */ 147c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project while (ColorIn1->Colors[CrntSlot - 1].Red == 0 148c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project && ColorIn1->Colors[CrntSlot - 1].Green == 0 149c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project && ColorIn1->Colors[CrntSlot - 1].Blue == 0) 150c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project CrntSlot--; 151c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project 1529aef3ea079a57c98a9207f8c3b95a5dc08ee74b5Chris Craik /* Copy ColorIn2 to ColorUnion (use old colors if they exist): */ 153c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project for (i = 0; i < ColorIn2->ColorCount && CrntSlot <= 256; i++) { 154c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project /* Let's see if this color already exists: */ 155c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project for (j = 0; j < ColorIn1->ColorCount; j++) 156c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project if (memcmp (&ColorIn1->Colors[j], &ColorIn2->Colors[i], 157c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project sizeof(GifColorType)) == 0) 158c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project break; 159c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project 160c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project if (j < ColorIn1->ColorCount) 161c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project ColorTransIn2[i] = j; /* color exists in Color1 */ 162c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project else { 163c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project /* Color is new - copy it to a new slot: */ 164c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project ColorUnion->Colors[CrntSlot] = ColorIn2->Colors[i]; 165c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project ColorTransIn2[i] = CrntSlot++; 166c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project } 167c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project } 168c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project 169c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project if (CrntSlot > 256) { 1709aef3ea079a57c98a9207f8c3b95a5dc08ee74b5Chris Craik GifFreeMapObject(ColorUnion); 171c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project return ((ColorMapObject *) NULL); 172c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project } 173c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project 1749aef3ea079a57c98a9207f8c3b95a5dc08ee74b5Chris Craik NewGifBitSize = GifBitSize(CrntSlot); 1759aef3ea079a57c98a9207f8c3b95a5dc08ee74b5Chris Craik RoundUpTo = (1 << NewGifBitSize); 176c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project 177c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project if (RoundUpTo != ColorUnion->ColorCount) { 178c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project register GifColorType *Map = ColorUnion->Colors; 179c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project 180c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project /* 181c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project * Zero out slots up to next power of 2. 182c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project * We know these slots exist because of the way ColorUnion's 183c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project * start dimension was computed. 184c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project */ 185c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project for (j = CrntSlot; j < RoundUpTo; j++) 186c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project Map[j].Red = Map[j].Green = Map[j].Blue = 0; 187c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project 188c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project /* perhaps we can shrink the map? */ 189c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project if (RoundUpTo < ColorUnion->ColorCount) 190c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project ColorUnion->Colors = (GifColorType *)realloc(Map, 191c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project sizeof(GifColorType) * RoundUpTo); 192c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project } 193c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project 194c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project ColorUnion->ColorCount = RoundUpTo; 1959aef3ea079a57c98a9207f8c3b95a5dc08ee74b5Chris Craik ColorUnion->BitsPerPixel = NewGifBitSize; 196c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project 197c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project return (ColorUnion); 198c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project} 199c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project 2009aef3ea079a57c98a9207f8c3b95a5dc08ee74b5Chris Craik/******************************************************************************* 2019aef3ea079a57c98a9207f8c3b95a5dc08ee74b5Chris Craik Apply a given color translation to the raster bits of an image 2029aef3ea079a57c98a9207f8c3b95a5dc08ee74b5Chris Craik*******************************************************************************/ 203c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Projectvoid 2049aef3ea079a57c98a9207f8c3b95a5dc08ee74b5Chris CraikGifApplyTranslation(SavedImage *Image, GifPixelType Translation[]) 2059aef3ea079a57c98a9207f8c3b95a5dc08ee74b5Chris Craik{ 206c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project register int i; 207c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project register int RasterSize = Image->ImageDesc.Height * Image->ImageDesc.Width; 208c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project 209c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project for (i = 0; i < RasterSize; i++) 210c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project Image->RasterBits[i] = Translation[Image->RasterBits[i]]; 211c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project} 212c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project 213c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project/****************************************************************************** 2149aef3ea079a57c98a9207f8c3b95a5dc08ee74b5Chris Craik Extension record functions 2159aef3ea079a57c98a9207f8c3b95a5dc08ee74b5Chris Craik******************************************************************************/ 216c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Projectint 2179aef3ea079a57c98a9207f8c3b95a5dc08ee74b5Chris CraikGifAddExtensionBlock(int *ExtensionBlockCount, 2189aef3ea079a57c98a9207f8c3b95a5dc08ee74b5Chris Craik ExtensionBlock **ExtensionBlocks, 2199aef3ea079a57c98a9207f8c3b95a5dc08ee74b5Chris Craik int Function, 2209aef3ea079a57c98a9207f8c3b95a5dc08ee74b5Chris Craik unsigned int Len, 2219aef3ea079a57c98a9207f8c3b95a5dc08ee74b5Chris Craik unsigned char ExtData[]) 2229aef3ea079a57c98a9207f8c3b95a5dc08ee74b5Chris Craik{ 223c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project ExtensionBlock *ep; 224c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project 2259aef3ea079a57c98a9207f8c3b95a5dc08ee74b5Chris Craik if (*ExtensionBlocks == NULL) 2269aef3ea079a57c98a9207f8c3b95a5dc08ee74b5Chris Craik *ExtensionBlocks=(ExtensionBlock *)malloc(sizeof(ExtensionBlock)); 227c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project else 2289aef3ea079a57c98a9207f8c3b95a5dc08ee74b5Chris Craik *ExtensionBlocks = (ExtensionBlock *)realloc(*ExtensionBlocks, 229c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project sizeof(ExtensionBlock) * 2309aef3ea079a57c98a9207f8c3b95a5dc08ee74b5Chris Craik (*ExtensionBlockCount + 1)); 231c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project 2329aef3ea079a57c98a9207f8c3b95a5dc08ee74b5Chris Craik if (*ExtensionBlocks == NULL) 233c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project return (GIF_ERROR); 234c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project 2359aef3ea079a57c98a9207f8c3b95a5dc08ee74b5Chris Craik ep = &(*ExtensionBlocks)[(*ExtensionBlockCount)++]; 236c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project 2379aef3ea079a57c98a9207f8c3b95a5dc08ee74b5Chris Craik ep->Function = Function; 238c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project ep->ByteCount=Len; 2399aef3ea079a57c98a9207f8c3b95a5dc08ee74b5Chris Craik ep->Bytes = (GifByteType *)malloc(ep->ByteCount); 240c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project if (ep->Bytes == NULL) 241c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project return (GIF_ERROR); 242c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project 2439aef3ea079a57c98a9207f8c3b95a5dc08ee74b5Chris Craik if (ExtData != NULL) { 244c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project memcpy(ep->Bytes, ExtData, Len); 245c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project } 246c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project 247c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project return (GIF_OK); 248c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project} 249c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project 250c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Projectvoid 2519aef3ea079a57c98a9207f8c3b95a5dc08ee74b5Chris CraikGifFreeExtensions(int *ExtensionBlockCount, 2529aef3ea079a57c98a9207f8c3b95a5dc08ee74b5Chris Craik ExtensionBlock **ExtensionBlocks) 253c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project{ 254c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project ExtensionBlock *ep; 255c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project 2569aef3ea079a57c98a9207f8c3b95a5dc08ee74b5Chris Craik if (*ExtensionBlocks == NULL) 257c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project return; 2589aef3ea079a57c98a9207f8c3b95a5dc08ee74b5Chris Craik 2599aef3ea079a57c98a9207f8c3b95a5dc08ee74b5Chris Craik for (ep = *ExtensionBlocks; 2609aef3ea079a57c98a9207f8c3b95a5dc08ee74b5Chris Craik ep < (*ExtensionBlocks + *ExtensionBlockCount); 2619aef3ea079a57c98a9207f8c3b95a5dc08ee74b5Chris Craik ep++) 262c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project (void)free((char *)ep->Bytes); 2639aef3ea079a57c98a9207f8c3b95a5dc08ee74b5Chris Craik (void)free((char *)*ExtensionBlocks); 2649aef3ea079a57c98a9207f8c3b95a5dc08ee74b5Chris Craik *ExtensionBlocks = NULL; 2659aef3ea079a57c98a9207f8c3b95a5dc08ee74b5Chris Craik *ExtensionBlockCount = 0; 266c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project} 267c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project 268c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project/****************************************************************************** 2699aef3ea079a57c98a9207f8c3b95a5dc08ee74b5Chris Craik Image block allocation functions 270c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project******************************************************************************/ 271c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project 272c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project/* Private Function: 273c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project * Frees the last image in the GifFile->SavedImages array 274c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project */ 275c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Projectvoid 2769aef3ea079a57c98a9207f8c3b95a5dc08ee74b5Chris CraikFreeLastSavedImage(GifFileType *GifFile) 2779aef3ea079a57c98a9207f8c3b95a5dc08ee74b5Chris Craik{ 278c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project SavedImage *sp; 279c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project 280c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project if ((GifFile == NULL) || (GifFile->SavedImages == NULL)) 281c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project return; 282c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project 283c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project /* Remove one SavedImage from the GifFile */ 284c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project GifFile->ImageCount--; 285c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project sp = &GifFile->SavedImages[GifFile->ImageCount]; 286c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project 287c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project /* Deallocate its Colormap */ 2889aef3ea079a57c98a9207f8c3b95a5dc08ee74b5Chris Craik if (sp->ImageDesc.ColorMap != NULL) { 2899aef3ea079a57c98a9207f8c3b95a5dc08ee74b5Chris Craik GifFreeMapObject(sp->ImageDesc.ColorMap); 290c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project sp->ImageDesc.ColorMap = NULL; 291c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project } 292c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project 293c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project /* Deallocate the image data */ 2949aef3ea079a57c98a9207f8c3b95a5dc08ee74b5Chris Craik if (sp->RasterBits != NULL) 295c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project free((char *)sp->RasterBits); 296c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project 297c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project /* Deallocate any extensions */ 2989aef3ea079a57c98a9207f8c3b95a5dc08ee74b5Chris Craik GifFreeExtensions(&sp->ExtensionBlockCount, &sp->ExtensionBlocks); 299c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project 300c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project /*** FIXME: We could realloc the GifFile->SavedImages structure but is 301c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project * there a point to it? Saves some memory but we'd have to do it every 3029aef3ea079a57c98a9207f8c3b95a5dc08ee74b5Chris Craik * time. If this is used in GifFreeSavedImages then it would be inefficient 303c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project * (The whole array is going to be deallocated.) If we just use it when 304c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project * we want to free the last Image it's convenient to do it here. 305c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project */ 306c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project} 307c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project 308c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project/* 309c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project * Append an image block to the SavedImages array 310c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project */ 311c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source ProjectSavedImage * 3129aef3ea079a57c98a9207f8c3b95a5dc08ee74b5Chris CraikGifMakeSavedImage(GifFileType *GifFile, const SavedImage *CopyFrom) 3139aef3ea079a57c98a9207f8c3b95a5dc08ee74b5Chris Craik{ 314c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project SavedImage *sp; 315c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project 316c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project if (GifFile->SavedImages == NULL) 317c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project GifFile->SavedImages = (SavedImage *)malloc(sizeof(SavedImage)); 318c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project else 319c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project GifFile->SavedImages = (SavedImage *)realloc(GifFile->SavedImages, 320c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project sizeof(SavedImage) * (GifFile->ImageCount + 1)); 321c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project 322c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project if (GifFile->SavedImages == NULL) 323c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project return ((SavedImage *)NULL); 324c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project else { 325c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project sp = &GifFile->SavedImages[GifFile->ImageCount++]; 326c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project memset((char *)sp, '\0', sizeof(SavedImage)); 327c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project 3289aef3ea079a57c98a9207f8c3b95a5dc08ee74b5Chris Craik if (CopyFrom != NULL) { 329c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project memcpy((char *)sp, CopyFrom, sizeof(SavedImage)); 330c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project 331c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project /* 332c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project * Make our own allocated copies of the heap fields in the 333c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project * copied record. This guards against potential aliasing 334c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project * problems. 335c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project */ 336c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project 337c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project /* first, the local color map */ 3389aef3ea079a57c98a9207f8c3b95a5dc08ee74b5Chris Craik if (sp->ImageDesc.ColorMap != NULL) { 3399aef3ea079a57c98a9207f8c3b95a5dc08ee74b5Chris Craik sp->ImageDesc.ColorMap = GifMakeMapObject( 340c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project CopyFrom->ImageDesc.ColorMap->ColorCount, 341c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project CopyFrom->ImageDesc.ColorMap->Colors); 342c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project if (sp->ImageDesc.ColorMap == NULL) { 343c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project FreeLastSavedImage(GifFile); 344c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project return (SavedImage *)(NULL); 345c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project } 346c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project } 347c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project 348c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project /* next, the raster */ 349c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project sp->RasterBits = (unsigned char *)malloc(sizeof(GifPixelType) * 350c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project CopyFrom->ImageDesc.Height * 351c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project CopyFrom->ImageDesc.Width); 352c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project if (sp->RasterBits == NULL) { 353c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project FreeLastSavedImage(GifFile); 354c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project return (SavedImage *)(NULL); 355c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project } 356c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project memcpy(sp->RasterBits, CopyFrom->RasterBits, 357c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project sizeof(GifPixelType) * CopyFrom->ImageDesc.Height * 358c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project CopyFrom->ImageDesc.Width); 359c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project 360c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project /* finally, the extension blocks */ 3619aef3ea079a57c98a9207f8c3b95a5dc08ee74b5Chris Craik if (sp->ExtensionBlocks != NULL) { 362c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project sp->ExtensionBlocks = (ExtensionBlock *)malloc( 363c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project sizeof(ExtensionBlock) * 364c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project CopyFrom->ExtensionBlockCount); 365c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project if (sp->ExtensionBlocks == NULL) { 366c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project FreeLastSavedImage(GifFile); 367c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project return (SavedImage *)(NULL); 368c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project } 369c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project memcpy(sp->ExtensionBlocks, CopyFrom->ExtensionBlocks, 370c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project sizeof(ExtensionBlock) * CopyFrom->ExtensionBlockCount); 371c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project } 372c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project } 373c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project 374c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project return (sp); 375c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project } 376c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project} 377c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project 378c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Projectvoid 3799aef3ea079a57c98a9207f8c3b95a5dc08ee74b5Chris CraikGifFreeSavedImages(GifFileType *GifFile) 3809aef3ea079a57c98a9207f8c3b95a5dc08ee74b5Chris Craik{ 381c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project SavedImage *sp; 382c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project 383c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project if ((GifFile == NULL) || (GifFile->SavedImages == NULL)) { 384c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project return; 385c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project } 386c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project for (sp = GifFile->SavedImages; 387c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project sp < GifFile->SavedImages + GifFile->ImageCount; sp++) { 3889aef3ea079a57c98a9207f8c3b95a5dc08ee74b5Chris Craik if (sp->ImageDesc.ColorMap != NULL) { 3899aef3ea079a57c98a9207f8c3b95a5dc08ee74b5Chris Craik GifFreeMapObject(sp->ImageDesc.ColorMap); 390c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project sp->ImageDesc.ColorMap = NULL; 391c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project } 392c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project 3939aef3ea079a57c98a9207f8c3b95a5dc08ee74b5Chris Craik if (sp->RasterBits != NULL) 394c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project free((char *)sp->RasterBits); 3959aef3ea079a57c98a9207f8c3b95a5dc08ee74b5Chris Craik 3969aef3ea079a57c98a9207f8c3b95a5dc08ee74b5Chris Craik GifFreeExtensions(&sp->ExtensionBlockCount, &sp->ExtensionBlocks); 397c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project } 398c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project free((char *)GifFile->SavedImages); 3999aef3ea079a57c98a9207f8c3b95a5dc08ee74b5Chris Craik GifFile->SavedImages = NULL; 400c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project} 4019aef3ea079a57c98a9207f8c3b95a5dc08ee74b5Chris Craik 4029aef3ea079a57c98a9207f8c3b95a5dc08ee74b5Chris Craik/* end */ 403