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); 63e189ac98c1d4e339fd0327aae046f908e22fa1bcMatt Sarett Object->SortFlag = false; 64c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project 659aef3ea079a57c98a9207f8c3b95a5dc08ee74b5Chris Craik if (ColorMap != NULL) { 66c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project memcpy((char *)Object->Colors, 67c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project (char *)ColorMap, ColorCount * sizeof(GifColorType)); 68c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project } 69c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project 70c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project return (Object); 71c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project} 72c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project 739aef3ea079a57c98a9207f8c3b95a5dc08ee74b5Chris Craik/******************************************************************************* 749aef3ea079a57c98a9207f8c3b95a5dc08ee74b5Chris CraikFree a color map object 759aef3ea079a57c98a9207f8c3b95a5dc08ee74b5Chris Craik*******************************************************************************/ 76c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Projectvoid 779aef3ea079a57c98a9207f8c3b95a5dc08ee74b5Chris CraikGifFreeMapObject(ColorMapObject *Object) 789aef3ea079a57c98a9207f8c3b95a5dc08ee74b5Chris Craik{ 79c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project if (Object != NULL) { 809aef3ea079a57c98a9207f8c3b95a5dc08ee74b5Chris Craik (void)free(Object->Colors); 819aef3ea079a57c98a9207f8c3b95a5dc08ee74b5Chris Craik (void)free(Object); 82c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project } 83c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project} 84c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project 85c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project#ifdef DEBUG 86c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Projectvoid 879aef3ea079a57c98a9207f8c3b95a5dc08ee74b5Chris CraikDumpColorMap(ColorMapObject *Object, 889aef3ea079a57c98a9207f8c3b95a5dc08ee74b5Chris Craik FILE * fp) 899aef3ea079a57c98a9207f8c3b95a5dc08ee74b5Chris Craik{ 909aef3ea079a57c98a9207f8c3b95a5dc08ee74b5Chris Craik if (Object != NULL) { 91c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project int i, j, Len = Object->ColorCount; 92c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project 93c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project for (i = 0; i < Len; i += 4) { 94c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project for (j = 0; j < 4 && j < Len; j++) { 959aef3ea079a57c98a9207f8c3b95a5dc08ee74b5Chris Craik (void)fprintf(fp, "%3d: %02x %02x %02x ", i + j, 969aef3ea079a57c98a9207f8c3b95a5dc08ee74b5Chris Craik Object->Colors[i + j].Red, 979aef3ea079a57c98a9207f8c3b95a5dc08ee74b5Chris Craik Object->Colors[i + j].Green, 989aef3ea079a57c98a9207f8c3b95a5dc08ee74b5Chris Craik Object->Colors[i + j].Blue); 99c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project } 1009aef3ea079a57c98a9207f8c3b95a5dc08ee74b5Chris Craik (void)fprintf(fp, "\n"); 101c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project } 102c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project } 103c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project} 104c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project#endif /* DEBUG */ 105c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project 1069aef3ea079a57c98a9207f8c3b95a5dc08ee74b5Chris Craik/******************************************************************************* 1079aef3ea079a57c98a9207f8c3b95a5dc08ee74b5Chris Craik Compute the union of two given color maps and return it. If result can't 1089aef3ea079a57c98a9207f8c3b95a5dc08ee74b5Chris Craik fit into 256 colors, NULL is returned, the allocated union otherwise. 1099aef3ea079a57c98a9207f8c3b95a5dc08ee74b5Chris Craik ColorIn1 is copied as is to ColorUnion, while colors from ColorIn2 are 1109aef3ea079a57c98a9207f8c3b95a5dc08ee74b5Chris Craik copied iff they didn't exist before. ColorTransIn2 maps the old 1119aef3ea079a57c98a9207f8c3b95a5dc08ee74b5Chris Craik ColorIn2 into the ColorUnion color map table./ 1129aef3ea079a57c98a9207f8c3b95a5dc08ee74b5Chris Craik*******************************************************************************/ 113c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source ProjectColorMapObject * 1149aef3ea079a57c98a9207f8c3b95a5dc08ee74b5Chris CraikGifUnionColorMap(const ColorMapObject *ColorIn1, 1159aef3ea079a57c98a9207f8c3b95a5dc08ee74b5Chris Craik const ColorMapObject *ColorIn2, 1169aef3ea079a57c98a9207f8c3b95a5dc08ee74b5Chris Craik GifPixelType ColorTransIn2[]) 1179aef3ea079a57c98a9207f8c3b95a5dc08ee74b5Chris Craik{ 1189aef3ea079a57c98a9207f8c3b95a5dc08ee74b5Chris Craik int i, j, CrntSlot, RoundUpTo, NewGifBitSize; 119c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project ColorMapObject *ColorUnion; 120c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project 1219aef3ea079a57c98a9207f8c3b95a5dc08ee74b5Chris Craik /* 1229aef3ea079a57c98a9207f8c3b95a5dc08ee74b5Chris Craik * We don't worry about duplicates within either color map; if 1239aef3ea079a57c98a9207f8c3b95a5dc08ee74b5Chris Craik * the caller wants to resolve those, he can perform unions 1249aef3ea079a57c98a9207f8c3b95a5dc08ee74b5Chris Craik * with an empty color map. 125c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project */ 1269aef3ea079a57c98a9207f8c3b95a5dc08ee74b5Chris Craik 1279aef3ea079a57c98a9207f8c3b95a5dc08ee74b5Chris Craik /* Allocate table which will hold the result for sure. */ 1289aef3ea079a57c98a9207f8c3b95a5dc08ee74b5Chris Craik ColorUnion = GifMakeMapObject(MAX(ColorIn1->ColorCount, 129c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project ColorIn2->ColorCount) * 2, NULL); 130c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project 131c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project if (ColorUnion == NULL) 132c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project return (NULL); 133c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project 1349aef3ea079a57c98a9207f8c3b95a5dc08ee74b5Chris Craik /* 1359aef3ea079a57c98a9207f8c3b95a5dc08ee74b5Chris Craik * Copy ColorIn1 to ColorUnion. 1369aef3ea079a57c98a9207f8c3b95a5dc08ee74b5Chris Craik */ 137c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project for (i = 0; i < ColorIn1->ColorCount; i++) 138c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project ColorUnion->Colors[i] = ColorIn1->Colors[i]; 139c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project CrntSlot = ColorIn1->ColorCount; 140c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project 141c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project /* 142c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project * Potentially obnoxious hack: 143c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project * 144c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project * Back CrntSlot down past all contiguous {0, 0, 0} slots at the end 145c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project * of table 1. This is very useful if your display is limited to 146c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project * 16 colors. 147c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project */ 148c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project while (ColorIn1->Colors[CrntSlot - 1].Red == 0 149c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project && ColorIn1->Colors[CrntSlot - 1].Green == 0 150c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project && ColorIn1->Colors[CrntSlot - 1].Blue == 0) 151c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project CrntSlot--; 152c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project 1539aef3ea079a57c98a9207f8c3b95a5dc08ee74b5Chris Craik /* Copy ColorIn2 to ColorUnion (use old colors if they exist): */ 154c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project for (i = 0; i < ColorIn2->ColorCount && CrntSlot <= 256; i++) { 155c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project /* Let's see if this color already exists: */ 156c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project for (j = 0; j < ColorIn1->ColorCount; j++) 157c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project if (memcmp (&ColorIn1->Colors[j], &ColorIn2->Colors[i], 158c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project sizeof(GifColorType)) == 0) 159c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project break; 160c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project 161c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project if (j < ColorIn1->ColorCount) 162c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project ColorTransIn2[i] = j; /* color exists in Color1 */ 163c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project else { 164c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project /* Color is new - copy it to a new slot: */ 165c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project ColorUnion->Colors[CrntSlot] = ColorIn2->Colors[i]; 166c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project ColorTransIn2[i] = CrntSlot++; 167c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project } 168c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project } 169c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project 170c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project if (CrntSlot > 256) { 1719aef3ea079a57c98a9207f8c3b95a5dc08ee74b5Chris Craik GifFreeMapObject(ColorUnion); 172c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project return ((ColorMapObject *) NULL); 173c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project } 174c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project 1759aef3ea079a57c98a9207f8c3b95a5dc08ee74b5Chris Craik NewGifBitSize = GifBitSize(CrntSlot); 1769aef3ea079a57c98a9207f8c3b95a5dc08ee74b5Chris Craik RoundUpTo = (1 << NewGifBitSize); 177c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project 178c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project if (RoundUpTo != ColorUnion->ColorCount) { 179c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project register GifColorType *Map = ColorUnion->Colors; 180c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project 181c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project /* 182c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project * Zero out slots up to next power of 2. 183c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project * We know these slots exist because of the way ColorUnion's 184c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project * start dimension was computed. 185c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project */ 186c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project for (j = CrntSlot; j < RoundUpTo; j++) 187c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project Map[j].Red = Map[j].Green = Map[j].Blue = 0; 188c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project 189c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project /* perhaps we can shrink the map? */ 190e189ac98c1d4e339fd0327aae046f908e22fa1bcMatt Sarett if (RoundUpTo < ColorUnion->ColorCount) { 19135418eae036ff745837b1098ab8d4c606ea577d5Leon Scroggins III GifColorType *new_map = (GifColorType *)reallocarray(Map, 19235418eae036ff745837b1098ab8d4c606ea577d5Leon Scroggins III RoundUpTo, sizeof(GifColorType)); 193e189ac98c1d4e339fd0327aae046f908e22fa1bcMatt Sarett if( new_map == NULL ) { 194e189ac98c1d4e339fd0327aae046f908e22fa1bcMatt Sarett GifFreeMapObject(ColorUnion); 195e189ac98c1d4e339fd0327aae046f908e22fa1bcMatt Sarett return ((ColorMapObject *) NULL); 196e189ac98c1d4e339fd0327aae046f908e22fa1bcMatt Sarett } 197e189ac98c1d4e339fd0327aae046f908e22fa1bcMatt Sarett ColorUnion->Colors = new_map; 198e189ac98c1d4e339fd0327aae046f908e22fa1bcMatt Sarett } 199c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project } 200c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project 201c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project ColorUnion->ColorCount = RoundUpTo; 2029aef3ea079a57c98a9207f8c3b95a5dc08ee74b5Chris Craik ColorUnion->BitsPerPixel = NewGifBitSize; 203c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project 204c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project return (ColorUnion); 205c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project} 206c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project 2079aef3ea079a57c98a9207f8c3b95a5dc08ee74b5Chris Craik/******************************************************************************* 2089aef3ea079a57c98a9207f8c3b95a5dc08ee74b5Chris Craik Apply a given color translation to the raster bits of an image 2099aef3ea079a57c98a9207f8c3b95a5dc08ee74b5Chris Craik*******************************************************************************/ 210c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Projectvoid 2119aef3ea079a57c98a9207f8c3b95a5dc08ee74b5Chris CraikGifApplyTranslation(SavedImage *Image, GifPixelType Translation[]) 2129aef3ea079a57c98a9207f8c3b95a5dc08ee74b5Chris Craik{ 213c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project register int i; 214c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project register int RasterSize = Image->ImageDesc.Height * Image->ImageDesc.Width; 215c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project 216c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project for (i = 0; i < RasterSize; i++) 217c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project Image->RasterBits[i] = Translation[Image->RasterBits[i]]; 218c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project} 219c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project 220c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project/****************************************************************************** 2219aef3ea079a57c98a9207f8c3b95a5dc08ee74b5Chris Craik Extension record functions 2229aef3ea079a57c98a9207f8c3b95a5dc08ee74b5Chris Craik******************************************************************************/ 223c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Projectint 2249aef3ea079a57c98a9207f8c3b95a5dc08ee74b5Chris CraikGifAddExtensionBlock(int *ExtensionBlockCount, 2259aef3ea079a57c98a9207f8c3b95a5dc08ee74b5Chris Craik ExtensionBlock **ExtensionBlocks, 2269aef3ea079a57c98a9207f8c3b95a5dc08ee74b5Chris Craik int Function, 2279aef3ea079a57c98a9207f8c3b95a5dc08ee74b5Chris Craik unsigned int Len, 2289aef3ea079a57c98a9207f8c3b95a5dc08ee74b5Chris Craik unsigned char ExtData[]) 2299aef3ea079a57c98a9207f8c3b95a5dc08ee74b5Chris Craik{ 230c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project ExtensionBlock *ep; 231c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project 2329aef3ea079a57c98a9207f8c3b95a5dc08ee74b5Chris Craik if (*ExtensionBlocks == NULL) 2339aef3ea079a57c98a9207f8c3b95a5dc08ee74b5Chris Craik *ExtensionBlocks=(ExtensionBlock *)malloc(sizeof(ExtensionBlock)); 234e189ac98c1d4e339fd0327aae046f908e22fa1bcMatt Sarett else { 23535418eae036ff745837b1098ab8d4c606ea577d5Leon Scroggins III ExtensionBlock* ep_new = (ExtensionBlock *)reallocarray 23635418eae036ff745837b1098ab8d4c606ea577d5Leon Scroggins III (*ExtensionBlocks, (*ExtensionBlockCount + 1), 23735418eae036ff745837b1098ab8d4c606ea577d5Leon Scroggins III sizeof(ExtensionBlock)); 238e189ac98c1d4e339fd0327aae046f908e22fa1bcMatt Sarett if( ep_new == NULL ) 239e189ac98c1d4e339fd0327aae046f908e22fa1bcMatt Sarett return (GIF_ERROR); 240e189ac98c1d4e339fd0327aae046f908e22fa1bcMatt Sarett *ExtensionBlocks = ep_new; 241e189ac98c1d4e339fd0327aae046f908e22fa1bcMatt Sarett } 242c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project 2439aef3ea079a57c98a9207f8c3b95a5dc08ee74b5Chris Craik if (*ExtensionBlocks == NULL) 244c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project return (GIF_ERROR); 245c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project 2469aef3ea079a57c98a9207f8c3b95a5dc08ee74b5Chris Craik ep = &(*ExtensionBlocks)[(*ExtensionBlockCount)++]; 247c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project 2489aef3ea079a57c98a9207f8c3b95a5dc08ee74b5Chris Craik ep->Function = Function; 249c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project ep->ByteCount=Len; 2509aef3ea079a57c98a9207f8c3b95a5dc08ee74b5Chris Craik ep->Bytes = (GifByteType *)malloc(ep->ByteCount); 251c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project if (ep->Bytes == NULL) 252c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project return (GIF_ERROR); 253c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project 2549aef3ea079a57c98a9207f8c3b95a5dc08ee74b5Chris Craik if (ExtData != NULL) { 255c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project memcpy(ep->Bytes, ExtData, Len); 256c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project } 257c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project 258c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project return (GIF_OK); 259c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project} 260c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project 261c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Projectvoid 2629aef3ea079a57c98a9207f8c3b95a5dc08ee74b5Chris CraikGifFreeExtensions(int *ExtensionBlockCount, 2639aef3ea079a57c98a9207f8c3b95a5dc08ee74b5Chris Craik ExtensionBlock **ExtensionBlocks) 264c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project{ 265c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project ExtensionBlock *ep; 266c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project 2679aef3ea079a57c98a9207f8c3b95a5dc08ee74b5Chris Craik if (*ExtensionBlocks == NULL) 268c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project return; 2699aef3ea079a57c98a9207f8c3b95a5dc08ee74b5Chris Craik 2709aef3ea079a57c98a9207f8c3b95a5dc08ee74b5Chris Craik for (ep = *ExtensionBlocks; 2719aef3ea079a57c98a9207f8c3b95a5dc08ee74b5Chris Craik ep < (*ExtensionBlocks + *ExtensionBlockCount); 2729aef3ea079a57c98a9207f8c3b95a5dc08ee74b5Chris Craik ep++) 273c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project (void)free((char *)ep->Bytes); 2749aef3ea079a57c98a9207f8c3b95a5dc08ee74b5Chris Craik (void)free((char *)*ExtensionBlocks); 2759aef3ea079a57c98a9207f8c3b95a5dc08ee74b5Chris Craik *ExtensionBlocks = NULL; 2769aef3ea079a57c98a9207f8c3b95a5dc08ee74b5Chris Craik *ExtensionBlockCount = 0; 277c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project} 278c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project 279c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project/****************************************************************************** 2809aef3ea079a57c98a9207f8c3b95a5dc08ee74b5Chris Craik Image block allocation functions 281c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project******************************************************************************/ 282c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project 283c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project/* Private Function: 284c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project * Frees the last image in the GifFile->SavedImages array 285c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project */ 286c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Projectvoid 2879aef3ea079a57c98a9207f8c3b95a5dc08ee74b5Chris CraikFreeLastSavedImage(GifFileType *GifFile) 2889aef3ea079a57c98a9207f8c3b95a5dc08ee74b5Chris Craik{ 289c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project SavedImage *sp; 290c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project 291c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project if ((GifFile == NULL) || (GifFile->SavedImages == NULL)) 292c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project return; 293c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project 294c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project /* Remove one SavedImage from the GifFile */ 295c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project GifFile->ImageCount--; 296c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project sp = &GifFile->SavedImages[GifFile->ImageCount]; 297c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project 298c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project /* Deallocate its Colormap */ 2999aef3ea079a57c98a9207f8c3b95a5dc08ee74b5Chris Craik if (sp->ImageDesc.ColorMap != NULL) { 3009aef3ea079a57c98a9207f8c3b95a5dc08ee74b5Chris Craik GifFreeMapObject(sp->ImageDesc.ColorMap); 301c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project sp->ImageDesc.ColorMap = NULL; 302c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project } 303c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project 304c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project /* Deallocate the image data */ 3059aef3ea079a57c98a9207f8c3b95a5dc08ee74b5Chris Craik if (sp->RasterBits != NULL) 306c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project free((char *)sp->RasterBits); 307c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project 308c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project /* Deallocate any extensions */ 3099aef3ea079a57c98a9207f8c3b95a5dc08ee74b5Chris Craik GifFreeExtensions(&sp->ExtensionBlockCount, &sp->ExtensionBlocks); 310c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project 311c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project /*** FIXME: We could realloc the GifFile->SavedImages structure but is 312c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project * there a point to it? Saves some memory but we'd have to do it every 3139aef3ea079a57c98a9207f8c3b95a5dc08ee74b5Chris Craik * time. If this is used in GifFreeSavedImages then it would be inefficient 314c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project * (The whole array is going to be deallocated.) If we just use it when 315c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project * we want to free the last Image it's convenient to do it here. 316c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project */ 317c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project} 318c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project 319c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project/* 320c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project * Append an image block to the SavedImages array 321c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project */ 322c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source ProjectSavedImage * 3239aef3ea079a57c98a9207f8c3b95a5dc08ee74b5Chris CraikGifMakeSavedImage(GifFileType *GifFile, const SavedImage *CopyFrom) 3249aef3ea079a57c98a9207f8c3b95a5dc08ee74b5Chris Craik{ 325c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project if (GifFile->SavedImages == NULL) 326c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project GifFile->SavedImages = (SavedImage *)malloc(sizeof(SavedImage)); 327c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project else 32835418eae036ff745837b1098ab8d4c606ea577d5Leon Scroggins III GifFile->SavedImages = (SavedImage *)reallocarray(GifFile->SavedImages, 32935418eae036ff745837b1098ab8d4c606ea577d5Leon Scroggins III (GifFile->ImageCount + 1), sizeof(SavedImage)); 330c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project 331c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project if (GifFile->SavedImages == NULL) 332c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project return ((SavedImage *)NULL); 333c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project else { 334e189ac98c1d4e339fd0327aae046f908e22fa1bcMatt Sarett SavedImage *sp = &GifFile->SavedImages[GifFile->ImageCount++]; 335c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project memset((char *)sp, '\0', sizeof(SavedImage)); 336c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project 3379aef3ea079a57c98a9207f8c3b95a5dc08ee74b5Chris Craik if (CopyFrom != NULL) { 338c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project memcpy((char *)sp, CopyFrom, sizeof(SavedImage)); 339c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project 340c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project /* 341c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project * Make our own allocated copies of the heap fields in the 342c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project * copied record. This guards against potential aliasing 343c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project * problems. 344c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project */ 345c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project 346c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project /* first, the local color map */ 3479aef3ea079a57c98a9207f8c3b95a5dc08ee74b5Chris Craik if (sp->ImageDesc.ColorMap != NULL) { 3489aef3ea079a57c98a9207f8c3b95a5dc08ee74b5Chris Craik sp->ImageDesc.ColorMap = GifMakeMapObject( 349c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project CopyFrom->ImageDesc.ColorMap->ColorCount, 350c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project CopyFrom->ImageDesc.ColorMap->Colors); 351c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project if (sp->ImageDesc.ColorMap == NULL) { 352c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project FreeLastSavedImage(GifFile); 353c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project return (SavedImage *)(NULL); 354c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project } 355c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project } 356c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project 357c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project /* next, the raster */ 35835418eae036ff745837b1098ab8d4c606ea577d5Leon Scroggins III sp->RasterBits = (unsigned char *)reallocarray(NULL, 35935418eae036ff745837b1098ab8d4c606ea577d5Leon Scroggins III (CopyFrom->ImageDesc.Height * 36035418eae036ff745837b1098ab8d4c606ea577d5Leon Scroggins III CopyFrom->ImageDesc.Width), 36135418eae036ff745837b1098ab8d4c606ea577d5Leon Scroggins III sizeof(GifPixelType)); 362c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project if (sp->RasterBits == NULL) { 363c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project FreeLastSavedImage(GifFile); 364c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project return (SavedImage *)(NULL); 365c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project } 366c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project memcpy(sp->RasterBits, CopyFrom->RasterBits, 367c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project sizeof(GifPixelType) * CopyFrom->ImageDesc.Height * 368c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project CopyFrom->ImageDesc.Width); 369c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project 370c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project /* finally, the extension blocks */ 3719aef3ea079a57c98a9207f8c3b95a5dc08ee74b5Chris Craik if (sp->ExtensionBlocks != NULL) { 37235418eae036ff745837b1098ab8d4c606ea577d5Leon Scroggins III sp->ExtensionBlocks = (ExtensionBlock *)reallocarray(NULL, 37335418eae036ff745837b1098ab8d4c606ea577d5Leon Scroggins III CopyFrom->ExtensionBlockCount, 37435418eae036ff745837b1098ab8d4c606ea577d5Leon Scroggins III sizeof(ExtensionBlock)); 375c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project if (sp->ExtensionBlocks == NULL) { 376c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project FreeLastSavedImage(GifFile); 377c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project return (SavedImage *)(NULL); 378c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project } 379c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project memcpy(sp->ExtensionBlocks, CopyFrom->ExtensionBlocks, 380c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project sizeof(ExtensionBlock) * CopyFrom->ExtensionBlockCount); 381c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project } 382c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project } 383c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project 384c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project return (sp); 385c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project } 386c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project} 387c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project 388c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Projectvoid 3899aef3ea079a57c98a9207f8c3b95a5dc08ee74b5Chris CraikGifFreeSavedImages(GifFileType *GifFile) 3909aef3ea079a57c98a9207f8c3b95a5dc08ee74b5Chris Craik{ 391c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project SavedImage *sp; 392c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project 393c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project if ((GifFile == NULL) || (GifFile->SavedImages == NULL)) { 394c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project return; 395c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project } 396c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project for (sp = GifFile->SavedImages; 397c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project sp < GifFile->SavedImages + GifFile->ImageCount; sp++) { 3989aef3ea079a57c98a9207f8c3b95a5dc08ee74b5Chris Craik if (sp->ImageDesc.ColorMap != NULL) { 3999aef3ea079a57c98a9207f8c3b95a5dc08ee74b5Chris Craik GifFreeMapObject(sp->ImageDesc.ColorMap); 400c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project sp->ImageDesc.ColorMap = NULL; 401c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project } 402c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project 4039aef3ea079a57c98a9207f8c3b95a5dc08ee74b5Chris Craik if (sp->RasterBits != NULL) 404c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project free((char *)sp->RasterBits); 4059aef3ea079a57c98a9207f8c3b95a5dc08ee74b5Chris Craik 4069aef3ea079a57c98a9207f8c3b95a5dc08ee74b5Chris Craik GifFreeExtensions(&sp->ExtensionBlockCount, &sp->ExtensionBlocks); 407c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project } 408c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project free((char *)GifFile->SavedImages); 4099aef3ea079a57c98a9207f8c3b95a5dc08ee74b5Chris Craik GifFile->SavedImages = NULL; 410c2eacaec90baee57fdbbdbad935d161638894ee7The Android Open Source Project} 4119aef3ea079a57c98a9207f8c3b95a5dc08ee74b5Chris Craik 4129aef3ea079a57c98a9207f8c3b95a5dc08ee74b5Chris Craik/* end */ 413