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