Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
PojavLauncherTeam
GitHub Repository: PojavLauncherTeam/mobile
Path: blob/master/src/java.desktop/share/native/libsplashscreen/giflib/gifalloc.c
41153 views
1
/*
2
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
3
*
4
* This code is free software; you can redistribute it and/or modify it
5
* under the terms of the GNU General Public License version 2 only, as
6
* published by the Free Software Foundation. Oracle designates this
7
* particular file as subject to the "Classpath" exception as provided
8
* by Oracle in the LICENSE file that accompanied this code.
9
*
10
* This code is distributed in the hope that it will be useful, but WITHOUT
11
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
12
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
13
* version 2 for more details (a copy is included in the LICENSE file that
14
* accompanied this code).
15
*
16
* You should have received a copy of the GNU General Public License version
17
* 2 along with this work; if not, write to the Free Software Foundation,
18
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
19
*
20
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
21
* or visit www.oracle.com if you need additional information or have any
22
* questions.
23
*/
24
25
/*****************************************************************************
26
27
GIF construction tools
28
29
SPDX-License-Identifier: MIT
30
31
****************************************************************************/
32
33
#include <stdlib.h>
34
#include <stdio.h>
35
#include <string.h>
36
37
#include "gif_lib.h"
38
#include "gif_lib_private.h"
39
40
#define MAX(x, y) (((x) > (y)) ? (x) : (y))
41
42
/******************************************************************************
43
Miscellaneous utility functions
44
******************************************************************************/
45
46
/* return smallest bitfield size n will fit in */
47
int
48
GifBitSize(int n)
49
{
50
register int i;
51
52
for (i = 1; i <= 8; i++)
53
if ((1 << i) >= n)
54
break;
55
return (i);
56
}
57
58
/******************************************************************************
59
Color map object functions
60
******************************************************************************/
61
62
/*
63
* Allocate a color map of given size; initialize with contents of
64
* ColorMap if that pointer is non-NULL.
65
*/
66
ColorMapObject *
67
GifMakeMapObject(int ColorCount, const GifColorType *ColorMap)
68
{
69
ColorMapObject *Object;
70
71
/*** FIXME: Our ColorCount has to be a power of two. Is it necessary to
72
* make the user know that or should we automatically round up instead? */
73
if (ColorCount != (1 << GifBitSize(ColorCount))) {
74
return ((ColorMapObject *) NULL);
75
}
76
77
Object = (ColorMapObject *)malloc(sizeof(ColorMapObject));
78
if (Object == (ColorMapObject *) NULL) {
79
return ((ColorMapObject *) NULL);
80
}
81
82
Object->Colors = (GifColorType *)calloc(ColorCount, sizeof(GifColorType));
83
if (Object->Colors == (GifColorType *) NULL) {
84
free(Object);
85
return ((ColorMapObject *) NULL);
86
}
87
88
Object->ColorCount = ColorCount;
89
Object->BitsPerPixel = GifBitSize(ColorCount);
90
Object->SortFlag = false;
91
92
if (ColorMap != NULL) {
93
memcpy((char *)Object->Colors,
94
(char *)ColorMap, ColorCount * sizeof(GifColorType));
95
}
96
97
return (Object);
98
}
99
100
/*******************************************************************************
101
Free a color map object
102
*******************************************************************************/
103
void
104
GifFreeMapObject(ColorMapObject *Object)
105
{
106
if (Object != NULL) {
107
(void)free(Object->Colors);
108
(void)free(Object);
109
}
110
}
111
112
#ifdef DEBUG
113
void
114
DumpColorMap(ColorMapObject *Object,
115
FILE * fp)
116
{
117
if (Object != NULL) {
118
int i, j, Len = Object->ColorCount;
119
120
for (i = 0; i < Len; i += 4) {
121
for (j = 0; j < 4 && j < Len; j++) {
122
(void)fprintf(fp, "%3d: %02x %02x %02x ", i + j,
123
Object->Colors[i + j].Red,
124
Object->Colors[i + j].Green,
125
Object->Colors[i + j].Blue);
126
}
127
(void)fprintf(fp, "\n");
128
}
129
}
130
}
131
#endif /* DEBUG */
132
133
/*******************************************************************************
134
Compute the union of two given color maps and return it. If result can't
135
fit into 256 colors, NULL is returned, the allocated union otherwise.
136
ColorIn1 is copied as is to ColorUnion, while colors from ColorIn2 are
137
copied iff they didn't exist before. ColorTransIn2 maps the old
138
ColorIn2 into the ColorUnion color map table./
139
*******************************************************************************/
140
ColorMapObject *
141
GifUnionColorMap(const ColorMapObject *ColorIn1,
142
const ColorMapObject *ColorIn2,
143
GifPixelType ColorTransIn2[])
144
{
145
int i, j, CrntSlot, RoundUpTo, NewGifBitSize;
146
ColorMapObject *ColorUnion;
147
148
/*
149
* We don't worry about duplicates within either color map; if
150
* the caller wants to resolve those, he can perform unions
151
* with an empty color map.
152
*/
153
154
/* Allocate table which will hold the result for sure. */
155
ColorUnion = GifMakeMapObject(MAX(ColorIn1->ColorCount,
156
ColorIn2->ColorCount) * 2, NULL);
157
158
if (ColorUnion == NULL)
159
return (NULL);
160
161
/*
162
* Copy ColorIn1 to ColorUnion.
163
*/
164
for (i = 0; i < ColorIn1->ColorCount; i++)
165
ColorUnion->Colors[i] = ColorIn1->Colors[i];
166
CrntSlot = ColorIn1->ColorCount;
167
168
/*
169
* Potentially obnoxious hack:
170
*
171
* Back CrntSlot down past all contiguous {0, 0, 0} slots at the end
172
* of table 1. This is very useful if your display is limited to
173
* 16 colors.
174
*/
175
while (ColorIn1->Colors[CrntSlot - 1].Red == 0
176
&& ColorIn1->Colors[CrntSlot - 1].Green == 0
177
&& ColorIn1->Colors[CrntSlot - 1].Blue == 0)
178
CrntSlot--;
179
180
/* Copy ColorIn2 to ColorUnion (use old colors if they exist): */
181
for (i = 0; i < ColorIn2->ColorCount && CrntSlot <= 256; i++) {
182
/* Let's see if this color already exists: */
183
for (j = 0; j < ColorIn1->ColorCount; j++)
184
if (memcmp (&ColorIn1->Colors[j], &ColorIn2->Colors[i],
185
sizeof(GifColorType)) == 0)
186
break;
187
188
if (j < ColorIn1->ColorCount)
189
ColorTransIn2[i] = j; /* color exists in Color1 */
190
else {
191
/* Color is new - copy it to a new slot: */
192
ColorUnion->Colors[CrntSlot] = ColorIn2->Colors[i];
193
ColorTransIn2[i] = CrntSlot++;
194
}
195
}
196
197
if (CrntSlot > 256) {
198
GifFreeMapObject(ColorUnion);
199
return ((ColorMapObject *) NULL);
200
}
201
202
NewGifBitSize = GifBitSize(CrntSlot);
203
RoundUpTo = (1 << NewGifBitSize);
204
205
if (RoundUpTo != ColorUnion->ColorCount) {
206
register GifColorType *Map = ColorUnion->Colors;
207
208
/*
209
* Zero out slots up to next power of 2.
210
* We know these slots exist because of the way ColorUnion's
211
* start dimension was computed.
212
*/
213
for (j = CrntSlot; j < RoundUpTo; j++)
214
Map[j].Red = Map[j].Green = Map[j].Blue = 0;
215
216
/* perhaps we can shrink the map? */
217
if (RoundUpTo < ColorUnion->ColorCount) {
218
GifColorType *new_map = (GifColorType *)reallocarray(Map,
219
RoundUpTo, sizeof(GifColorType));
220
if( new_map == NULL ) {
221
GifFreeMapObject(ColorUnion);
222
return ((ColorMapObject *) NULL);
223
}
224
ColorUnion->Colors = new_map;
225
}
226
}
227
228
ColorUnion->ColorCount = RoundUpTo;
229
ColorUnion->BitsPerPixel = NewGifBitSize;
230
231
return (ColorUnion);
232
}
233
234
/*******************************************************************************
235
Apply a given color translation to the raster bits of an image
236
*******************************************************************************/
237
void
238
GifApplyTranslation(SavedImage *Image, GifPixelType Translation[])
239
{
240
register int i;
241
register int RasterSize = Image->ImageDesc.Height * Image->ImageDesc.Width;
242
243
for (i = 0; i < RasterSize; i++)
244
Image->RasterBits[i] = Translation[Image->RasterBits[i]];
245
}
246
247
/******************************************************************************
248
Extension record functions
249
******************************************************************************/
250
int
251
GifAddExtensionBlock(int *ExtensionBlockCount,
252
ExtensionBlock **ExtensionBlocks,
253
int Function,
254
unsigned int Len,
255
unsigned char ExtData[])
256
{
257
ExtensionBlock *ep;
258
259
if (*ExtensionBlocks == NULL)
260
*ExtensionBlocks=(ExtensionBlock *)malloc(sizeof(ExtensionBlock));
261
else {
262
ExtensionBlock* ep_new = (ExtensionBlock *)reallocarray
263
(*ExtensionBlocks, (*ExtensionBlockCount + 1),
264
sizeof(ExtensionBlock));
265
if( ep_new == NULL )
266
return (GIF_ERROR);
267
*ExtensionBlocks = ep_new;
268
}
269
270
if (*ExtensionBlocks == NULL)
271
return (GIF_ERROR);
272
273
ep = &(*ExtensionBlocks)[(*ExtensionBlockCount)++];
274
275
ep->Function = Function;
276
ep->ByteCount=Len;
277
ep->Bytes = (GifByteType *)malloc(ep->ByteCount);
278
if (ep->Bytes == NULL)
279
return (GIF_ERROR);
280
281
if (ExtData != NULL) {
282
memcpy(ep->Bytes, ExtData, Len);
283
}
284
285
return (GIF_OK);
286
}
287
288
void
289
GifFreeExtensions(int *ExtensionBlockCount,
290
ExtensionBlock **ExtensionBlocks)
291
{
292
ExtensionBlock *ep;
293
294
if (*ExtensionBlocks == NULL)
295
return;
296
297
for (ep = *ExtensionBlocks;
298
ep < (*ExtensionBlocks + *ExtensionBlockCount);
299
ep++)
300
(void)free((char *)ep->Bytes);
301
(void)free((char *)*ExtensionBlocks);
302
*ExtensionBlocks = NULL;
303
*ExtensionBlockCount = 0;
304
}
305
306
/******************************************************************************
307
Image block allocation functions
308
******************************************************************************/
309
310
/* Private Function:
311
* Frees the last image in the GifFile->SavedImages array
312
*/
313
void
314
FreeLastSavedImage(GifFileType *GifFile)
315
{
316
SavedImage *sp;
317
318
if ((GifFile == NULL) || (GifFile->SavedImages == NULL))
319
return;
320
321
/* Remove one SavedImage from the GifFile */
322
GifFile->ImageCount--;
323
sp = &GifFile->SavedImages[GifFile->ImageCount];
324
325
/* Deallocate its Colormap */
326
if (sp->ImageDesc.ColorMap != NULL) {
327
GifFreeMapObject(sp->ImageDesc.ColorMap);
328
sp->ImageDesc.ColorMap = NULL;
329
}
330
331
/* Deallocate the image data */
332
if (sp->RasterBits != NULL)
333
free((char *)sp->RasterBits);
334
335
/* Deallocate any extensions */
336
GifFreeExtensions(&sp->ExtensionBlockCount, &sp->ExtensionBlocks);
337
338
/*** FIXME: We could realloc the GifFile->SavedImages structure but is
339
* there a point to it? Saves some memory but we'd have to do it every
340
* time. If this is used in GifFreeSavedImages then it would be inefficient
341
* (The whole array is going to be deallocated.) If we just use it when
342
* we want to free the last Image it's convenient to do it here.
343
*/
344
}
345
346
/*
347
* Append an image block to the SavedImages array
348
*/
349
SavedImage *
350
GifMakeSavedImage(GifFileType *GifFile, const SavedImage *CopyFrom)
351
{
352
if (GifFile->SavedImages == NULL)
353
GifFile->SavedImages = (SavedImage *)malloc(sizeof(SavedImage));
354
else {
355
SavedImage* newSavedImages = (SavedImage *)reallocarray(GifFile->SavedImages,
356
(GifFile->ImageCount + 1), sizeof(SavedImage));
357
if( newSavedImages == NULL)
358
return ((SavedImage *)NULL);
359
GifFile->SavedImages = newSavedImages;
360
}
361
if (GifFile->SavedImages == NULL)
362
return ((SavedImage *)NULL);
363
else {
364
SavedImage *sp = &GifFile->SavedImages[GifFile->ImageCount++];
365
366
if (CopyFrom != NULL) {
367
memcpy((char *)sp, CopyFrom, sizeof(SavedImage));
368
369
/*
370
* Make our own allocated copies of the heap fields in the
371
* copied record. This guards against potential aliasing
372
* problems.
373
*/
374
375
/* first, the local color map */
376
if (CopyFrom->ImageDesc.ColorMap != NULL) {
377
sp->ImageDesc.ColorMap = GifMakeMapObject(
378
CopyFrom->ImageDesc.ColorMap->ColorCount,
379
CopyFrom->ImageDesc.ColorMap->Colors);
380
if (sp->ImageDesc.ColorMap == NULL) {
381
FreeLastSavedImage(GifFile);
382
return (SavedImage *)(NULL);
383
}
384
}
385
386
/* next, the raster */
387
sp->RasterBits = (unsigned char *)reallocarray(NULL,
388
(CopyFrom->ImageDesc.Height *
389
CopyFrom->ImageDesc.Width),
390
sizeof(GifPixelType));
391
if (sp->RasterBits == NULL) {
392
FreeLastSavedImage(GifFile);
393
return (SavedImage *)(NULL);
394
}
395
memcpy(sp->RasterBits, CopyFrom->RasterBits,
396
sizeof(GifPixelType) * CopyFrom->ImageDesc.Height *
397
CopyFrom->ImageDesc.Width);
398
399
/* finally, the extension blocks */
400
if (CopyFrom->ExtensionBlocks != NULL) {
401
sp->ExtensionBlocks = (ExtensionBlock *)reallocarray(NULL,
402
CopyFrom->ExtensionBlockCount,
403
sizeof(ExtensionBlock));
404
if (sp->ExtensionBlocks == NULL) {
405
FreeLastSavedImage(GifFile);
406
return (SavedImage *)(NULL);
407
}
408
memcpy(sp->ExtensionBlocks, CopyFrom->ExtensionBlocks,
409
sizeof(ExtensionBlock) * CopyFrom->ExtensionBlockCount);
410
}
411
}
412
else {
413
memset((char *)sp, '\0', sizeof(SavedImage));
414
}
415
416
return (sp);
417
}
418
}
419
420
void
421
GifFreeSavedImages(GifFileType *GifFile)
422
{
423
SavedImage *sp;
424
425
if ((GifFile == NULL) || (GifFile->SavedImages == NULL)) {
426
return;
427
}
428
for (sp = GifFile->SavedImages;
429
sp < GifFile->SavedImages + GifFile->ImageCount; sp++) {
430
if (sp->ImageDesc.ColorMap != NULL) {
431
GifFreeMapObject(sp->ImageDesc.ColorMap);
432
sp->ImageDesc.ColorMap = NULL;
433
}
434
435
if (sp->RasterBits != NULL)
436
free((char *)sp->RasterBits);
437
438
GifFreeExtensions(&sp->ExtensionBlockCount, &sp->ExtensionBlocks);
439
}
440
free((char *)GifFile->SavedImages);
441
GifFile->SavedImages = NULL;
442
}
443
444
/* end */
445
446