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