1*b2055c35SXin Li // Copyright 2012 Google Inc. All Rights Reserved.
2*b2055c35SXin Li //
3*b2055c35SXin Li // Use of this source code is governed by a BSD-style license
4*b2055c35SXin Li // that can be found in the COPYING file in the root of the source
5*b2055c35SXin Li // tree. An additional intellectual property rights grant can be found
6*b2055c35SXin Li // in the file PATENTS. All contributing project authors may
7*b2055c35SXin Li // be found in the AUTHORS file in the root of the source tree.
8*b2055c35SXin Li // -----------------------------------------------------------------------------
9*b2055c35SXin Li //
10*b2055c35SXin Li // GIF decode.
11*b2055c35SXin Li
12*b2055c35SXin Li #include "./gifdec.h"
13*b2055c35SXin Li
14*b2055c35SXin Li #include <stdio.h>
15*b2055c35SXin Li
16*b2055c35SXin Li #ifdef WEBP_HAVE_GIF
17*b2055c35SXin Li #include <assert.h>
18*b2055c35SXin Li #include <stdlib.h>
19*b2055c35SXin Li #include <string.h>
20*b2055c35SXin Li
21*b2055c35SXin Li #include "webp/encode.h"
22*b2055c35SXin Li #include "webp/mux_types.h"
23*b2055c35SXin Li
24*b2055c35SXin Li #define GIF_TRANSPARENT_COLOR 0x00000000u
25*b2055c35SXin Li #define GIF_WHITE_COLOR 0xffffffffu
26*b2055c35SXin Li #define GIF_TRANSPARENT_MASK 0x01
27*b2055c35SXin Li #define GIF_DISPOSE_MASK 0x07
28*b2055c35SXin Li #define GIF_DISPOSE_SHIFT 2
29*b2055c35SXin Li
30*b2055c35SXin Li // from utils/utils.h
31*b2055c35SXin Li #ifdef __cplusplus
32*b2055c35SXin Li extern "C" {
33*b2055c35SXin Li #endif
34*b2055c35SXin Li extern void WebPCopyPlane(const uint8_t* src, int src_stride,
35*b2055c35SXin Li uint8_t* dst, int dst_stride,
36*b2055c35SXin Li int width, int height);
37*b2055c35SXin Li extern void WebPCopyPixels(const WebPPicture* const src,
38*b2055c35SXin Li WebPPicture* const dst);
39*b2055c35SXin Li #ifdef __cplusplus
40*b2055c35SXin Li }
41*b2055c35SXin Li #endif
42*b2055c35SXin Li
GIFGetBackgroundColor(const ColorMapObject * const color_map,int bgcolor_index,int transparent_index,uint32_t * const bgcolor)43*b2055c35SXin Li void GIFGetBackgroundColor(const ColorMapObject* const color_map,
44*b2055c35SXin Li int bgcolor_index, int transparent_index,
45*b2055c35SXin Li uint32_t* const bgcolor) {
46*b2055c35SXin Li if (transparent_index != GIF_INDEX_INVALID &&
47*b2055c35SXin Li bgcolor_index == transparent_index) {
48*b2055c35SXin Li *bgcolor = GIF_TRANSPARENT_COLOR; // Special case.
49*b2055c35SXin Li } else if (color_map == NULL || color_map->Colors == NULL
50*b2055c35SXin Li || bgcolor_index >= color_map->ColorCount) {
51*b2055c35SXin Li *bgcolor = GIF_WHITE_COLOR;
52*b2055c35SXin Li fprintf(stderr,
53*b2055c35SXin Li "GIF decode warning: invalid background color index. Assuming "
54*b2055c35SXin Li "white background.\n");
55*b2055c35SXin Li } else {
56*b2055c35SXin Li const GifColorType color = color_map->Colors[bgcolor_index];
57*b2055c35SXin Li *bgcolor = (0xffu << 24)
58*b2055c35SXin Li | (color.Red << 16)
59*b2055c35SXin Li | (color.Green << 8)
60*b2055c35SXin Li | (color.Blue << 0);
61*b2055c35SXin Li }
62*b2055c35SXin Li }
63*b2055c35SXin Li
GIFReadGraphicsExtension(const GifByteType * const buf,int * const duration,GIFDisposeMethod * const dispose,int * const transparent_index)64*b2055c35SXin Li int GIFReadGraphicsExtension(const GifByteType* const buf, int* const duration,
65*b2055c35SXin Li GIFDisposeMethod* const dispose,
66*b2055c35SXin Li int* const transparent_index) {
67*b2055c35SXin Li const int flags = buf[1];
68*b2055c35SXin Li const int dispose_raw = (flags >> GIF_DISPOSE_SHIFT) & GIF_DISPOSE_MASK;
69*b2055c35SXin Li const int duration_raw = buf[2] | (buf[3] << 8); // In 10 ms units.
70*b2055c35SXin Li if (buf[0] != 4) return 0;
71*b2055c35SXin Li *duration = duration_raw * 10; // Duration is in 1 ms units.
72*b2055c35SXin Li switch (dispose_raw) {
73*b2055c35SXin Li case 3:
74*b2055c35SXin Li *dispose = GIF_DISPOSE_RESTORE_PREVIOUS;
75*b2055c35SXin Li break;
76*b2055c35SXin Li case 2:
77*b2055c35SXin Li *dispose = GIF_DISPOSE_BACKGROUND;
78*b2055c35SXin Li break;
79*b2055c35SXin Li case 1:
80*b2055c35SXin Li case 0:
81*b2055c35SXin Li default:
82*b2055c35SXin Li *dispose = GIF_DISPOSE_NONE;
83*b2055c35SXin Li break;
84*b2055c35SXin Li }
85*b2055c35SXin Li *transparent_index =
86*b2055c35SXin Li (flags & GIF_TRANSPARENT_MASK) ? buf[4] : GIF_INDEX_INVALID;
87*b2055c35SXin Li return 1;
88*b2055c35SXin Li }
89*b2055c35SXin Li
Remap(const GifFileType * const gif,const uint8_t * const src,int len,int transparent_index,uint32_t * dst)90*b2055c35SXin Li static int Remap(const GifFileType* const gif, const uint8_t* const src,
91*b2055c35SXin Li int len, int transparent_index, uint32_t* dst) {
92*b2055c35SXin Li int i;
93*b2055c35SXin Li const GifColorType* colors;
94*b2055c35SXin Li const ColorMapObject* const cmap =
95*b2055c35SXin Li gif->Image.ColorMap ? gif->Image.ColorMap : gif->SColorMap;
96*b2055c35SXin Li if (cmap == NULL) return 1;
97*b2055c35SXin Li if (cmap->Colors == NULL || cmap->ColorCount <= 0) return 0;
98*b2055c35SXin Li colors = cmap->Colors;
99*b2055c35SXin Li
100*b2055c35SXin Li for (i = 0; i < len; ++i) {
101*b2055c35SXin Li if (src[i] == transparent_index) {
102*b2055c35SXin Li dst[i] = GIF_TRANSPARENT_COLOR;
103*b2055c35SXin Li } else if (src[i] < cmap->ColorCount) {
104*b2055c35SXin Li const GifColorType c = colors[src[i]];
105*b2055c35SXin Li dst[i] = c.Blue | (c.Green << 8) | (c.Red << 16) | (0xffu << 24);
106*b2055c35SXin Li } else {
107*b2055c35SXin Li return 0;
108*b2055c35SXin Li }
109*b2055c35SXin Li }
110*b2055c35SXin Li return 1;
111*b2055c35SXin Li }
112*b2055c35SXin Li
GIFReadFrame(GifFileType * const gif,int transparent_index,GIFFrameRect * const gif_rect,WebPPicture * const picture)113*b2055c35SXin Li int GIFReadFrame(GifFileType* const gif, int transparent_index,
114*b2055c35SXin Li GIFFrameRect* const gif_rect, WebPPicture* const picture) {
115*b2055c35SXin Li WebPPicture sub_image;
116*b2055c35SXin Li const GifImageDesc* const image_desc = &gif->Image;
117*b2055c35SXin Li uint32_t* dst = NULL;
118*b2055c35SXin Li uint8_t* tmp = NULL;
119*b2055c35SXin Li const GIFFrameRect rect = {
120*b2055c35SXin Li image_desc->Left, image_desc->Top, image_desc->Width, image_desc->Height
121*b2055c35SXin Li };
122*b2055c35SXin Li const uint64_t memory_needed = 4 * rect.width * (uint64_t)rect.height;
123*b2055c35SXin Li int ok = 0;
124*b2055c35SXin Li *gif_rect = rect;
125*b2055c35SXin Li
126*b2055c35SXin Li if (memory_needed != (size_t)memory_needed || memory_needed > (4ULL << 32)) {
127*b2055c35SXin Li fprintf(stderr, "Image is too large (%d x %d).", rect.width, rect.height);
128*b2055c35SXin Li return 0;
129*b2055c35SXin Li }
130*b2055c35SXin Li
131*b2055c35SXin Li // Use a view for the sub-picture:
132*b2055c35SXin Li if (!WebPPictureView(picture, rect.x_offset, rect.y_offset,
133*b2055c35SXin Li rect.width, rect.height, &sub_image)) {
134*b2055c35SXin Li fprintf(stderr, "Sub-image %dx%d at position %d,%d is invalid!\n",
135*b2055c35SXin Li rect.width, rect.height, rect.x_offset, rect.y_offset);
136*b2055c35SXin Li return 0;
137*b2055c35SXin Li }
138*b2055c35SXin Li dst = sub_image.argb;
139*b2055c35SXin Li
140*b2055c35SXin Li tmp = (uint8_t*)WebPMalloc(rect.width * sizeof(*tmp));
141*b2055c35SXin Li if (tmp == NULL) goto End;
142*b2055c35SXin Li
143*b2055c35SXin Li if (image_desc->Interlace) { // Interlaced image.
144*b2055c35SXin Li // We need 4 passes, with the following offsets and jumps.
145*b2055c35SXin Li const int interlace_offsets[] = { 0, 4, 2, 1 };
146*b2055c35SXin Li const int interlace_jumps[] = { 8, 8, 4, 2 };
147*b2055c35SXin Li int pass;
148*b2055c35SXin Li for (pass = 0; pass < 4; ++pass) {
149*b2055c35SXin Li const size_t stride = (size_t)sub_image.argb_stride;
150*b2055c35SXin Li int y = interlace_offsets[pass];
151*b2055c35SXin Li uint32_t* row = dst + y * stride;
152*b2055c35SXin Li const size_t jump = interlace_jumps[pass] * stride;
153*b2055c35SXin Li for (; y < rect.height; y += interlace_jumps[pass], row += jump) {
154*b2055c35SXin Li if (DGifGetLine(gif, tmp, rect.width) == GIF_ERROR) goto End;
155*b2055c35SXin Li if (!Remap(gif, tmp, rect.width, transparent_index, row)) goto End;
156*b2055c35SXin Li }
157*b2055c35SXin Li }
158*b2055c35SXin Li } else { // Non-interlaced image.
159*b2055c35SXin Li int y;
160*b2055c35SXin Li uint32_t* ptr = dst;
161*b2055c35SXin Li for (y = 0; y < rect.height; ++y, ptr += sub_image.argb_stride) {
162*b2055c35SXin Li if (DGifGetLine(gif, tmp, rect.width) == GIF_ERROR) goto End;
163*b2055c35SXin Li if (!Remap(gif, tmp, rect.width, transparent_index, ptr)) goto End;
164*b2055c35SXin Li }
165*b2055c35SXin Li }
166*b2055c35SXin Li ok = 1;
167*b2055c35SXin Li
168*b2055c35SXin Li End:
169*b2055c35SXin Li if (!ok) picture->error_code = sub_image.error_code;
170*b2055c35SXin Li WebPPictureFree(&sub_image);
171*b2055c35SXin Li WebPFree(tmp);
172*b2055c35SXin Li return ok;
173*b2055c35SXin Li }
174*b2055c35SXin Li
GIFReadLoopCount(GifFileType * const gif,GifByteType ** const buf,int * const loop_count)175*b2055c35SXin Li int GIFReadLoopCount(GifFileType* const gif, GifByteType** const buf,
176*b2055c35SXin Li int* const loop_count) {
177*b2055c35SXin Li assert(!memcmp(*buf + 1, "NETSCAPE2.0", 11) ||
178*b2055c35SXin Li !memcmp(*buf + 1, "ANIMEXTS1.0", 11));
179*b2055c35SXin Li if (DGifGetExtensionNext(gif, buf) == GIF_ERROR) {
180*b2055c35SXin Li return 0;
181*b2055c35SXin Li }
182*b2055c35SXin Li if (*buf == NULL) {
183*b2055c35SXin Li return 0; // Loop count sub-block missing.
184*b2055c35SXin Li }
185*b2055c35SXin Li if ((*buf)[0] < 3 || (*buf)[1] != 1) {
186*b2055c35SXin Li return 0; // wrong size/marker
187*b2055c35SXin Li }
188*b2055c35SXin Li *loop_count = (*buf)[2] | ((*buf)[3] << 8);
189*b2055c35SXin Li return 1;
190*b2055c35SXin Li }
191*b2055c35SXin Li
GIFReadMetadata(GifFileType * const gif,GifByteType ** const buf,WebPData * const metadata)192*b2055c35SXin Li int GIFReadMetadata(GifFileType* const gif, GifByteType** const buf,
193*b2055c35SXin Li WebPData* const metadata) {
194*b2055c35SXin Li const int is_xmp = !memcmp(*buf + 1, "XMP DataXMP", 11);
195*b2055c35SXin Li const int is_icc = !memcmp(*buf + 1, "ICCRGBG1012", 11);
196*b2055c35SXin Li assert(is_xmp || is_icc);
197*b2055c35SXin Li (void)is_icc; // silence unused warning.
198*b2055c35SXin Li // Construct metadata from sub-blocks.
199*b2055c35SXin Li // Usual case (including ICC profile): In each sub-block, the
200*b2055c35SXin Li // first byte specifies its size in bytes (0 to 255) and the
201*b2055c35SXin Li // rest of the bytes contain the data.
202*b2055c35SXin Li // Special case for XMP data: In each sub-block, the first byte
203*b2055c35SXin Li // is also part of the XMP payload. XMP in GIF also has a 257
204*b2055c35SXin Li // byte padding data. See the XMP specification for details.
205*b2055c35SXin Li while (1) {
206*b2055c35SXin Li WebPData subblock;
207*b2055c35SXin Li const uint8_t* tmp;
208*b2055c35SXin Li if (DGifGetExtensionNext(gif, buf) == GIF_ERROR) {
209*b2055c35SXin Li return 0;
210*b2055c35SXin Li }
211*b2055c35SXin Li if (*buf == NULL) break; // Finished.
212*b2055c35SXin Li subblock.size = is_xmp ? (*buf)[0] + 1 : (*buf)[0];
213*b2055c35SXin Li assert(subblock.size > 0);
214*b2055c35SXin Li subblock.bytes = is_xmp ? *buf : *buf + 1;
215*b2055c35SXin Li // Note: We store returned value in 'tmp' first, to avoid
216*b2055c35SXin Li // leaking old memory in metadata->bytes on error.
217*b2055c35SXin Li tmp = (uint8_t*)realloc((void*)metadata->bytes,
218*b2055c35SXin Li metadata->size + subblock.size);
219*b2055c35SXin Li if (tmp == NULL) {
220*b2055c35SXin Li return 0;
221*b2055c35SXin Li }
222*b2055c35SXin Li memcpy((void*)(tmp + metadata->size),
223*b2055c35SXin Li subblock.bytes, subblock.size);
224*b2055c35SXin Li metadata->bytes = tmp;
225*b2055c35SXin Li metadata->size += subblock.size;
226*b2055c35SXin Li }
227*b2055c35SXin Li if (is_xmp) {
228*b2055c35SXin Li // XMP padding data is 0x01, 0xff, 0xfe ... 0x01, 0x00.
229*b2055c35SXin Li const size_t xmp_pading_size = 257;
230*b2055c35SXin Li if (metadata->size > xmp_pading_size) {
231*b2055c35SXin Li metadata->size -= xmp_pading_size;
232*b2055c35SXin Li }
233*b2055c35SXin Li }
234*b2055c35SXin Li return 1;
235*b2055c35SXin Li }
236*b2055c35SXin Li
ClearRectangle(WebPPicture * const picture,int left,int top,int width,int height)237*b2055c35SXin Li static void ClearRectangle(WebPPicture* const picture,
238*b2055c35SXin Li int left, int top, int width, int height) {
239*b2055c35SXin Li int i, j;
240*b2055c35SXin Li const size_t stride = picture->argb_stride;
241*b2055c35SXin Li uint32_t* dst = picture->argb + top * stride + left;
242*b2055c35SXin Li for (j = 0; j < height; ++j, dst += stride) {
243*b2055c35SXin Li for (i = 0; i < width; ++i) dst[i] = GIF_TRANSPARENT_COLOR;
244*b2055c35SXin Li }
245*b2055c35SXin Li }
246*b2055c35SXin Li
GIFClearPic(WebPPicture * const pic,const GIFFrameRect * const rect)247*b2055c35SXin Li void GIFClearPic(WebPPicture* const pic, const GIFFrameRect* const rect) {
248*b2055c35SXin Li if (rect != NULL) {
249*b2055c35SXin Li ClearRectangle(pic, rect->x_offset, rect->y_offset,
250*b2055c35SXin Li rect->width, rect->height);
251*b2055c35SXin Li } else {
252*b2055c35SXin Li ClearRectangle(pic, 0, 0, pic->width, pic->height);
253*b2055c35SXin Li }
254*b2055c35SXin Li }
255*b2055c35SXin Li
GIFCopyPixels(const WebPPicture * const src,WebPPicture * const dst)256*b2055c35SXin Li void GIFCopyPixels(const WebPPicture* const src, WebPPicture* const dst) {
257*b2055c35SXin Li WebPCopyPixels(src, dst);
258*b2055c35SXin Li }
259*b2055c35SXin Li
GIFDisposeFrame(GIFDisposeMethod dispose,const GIFFrameRect * const rect,const WebPPicture * const prev_canvas,WebPPicture * const curr_canvas)260*b2055c35SXin Li void GIFDisposeFrame(GIFDisposeMethod dispose, const GIFFrameRect* const rect,
261*b2055c35SXin Li const WebPPicture* const prev_canvas,
262*b2055c35SXin Li WebPPicture* const curr_canvas) {
263*b2055c35SXin Li assert(rect != NULL);
264*b2055c35SXin Li if (dispose == GIF_DISPOSE_BACKGROUND) {
265*b2055c35SXin Li GIFClearPic(curr_canvas, rect);
266*b2055c35SXin Li } else if (dispose == GIF_DISPOSE_RESTORE_PREVIOUS) {
267*b2055c35SXin Li const size_t src_stride = prev_canvas->argb_stride;
268*b2055c35SXin Li const uint32_t* const src = prev_canvas->argb + rect->x_offset
269*b2055c35SXin Li + rect->y_offset * src_stride;
270*b2055c35SXin Li const size_t dst_stride = curr_canvas->argb_stride;
271*b2055c35SXin Li uint32_t* const dst = curr_canvas->argb + rect->x_offset
272*b2055c35SXin Li + rect->y_offset * dst_stride;
273*b2055c35SXin Li assert(prev_canvas != NULL);
274*b2055c35SXin Li WebPCopyPlane((uint8_t*)src, (int)(4 * src_stride),
275*b2055c35SXin Li (uint8_t*)dst, (int)(4 * dst_stride),
276*b2055c35SXin Li 4 * rect->width, rect->height);
277*b2055c35SXin Li }
278*b2055c35SXin Li }
279*b2055c35SXin Li
GIFBlendFrames(const WebPPicture * const src,const GIFFrameRect * const rect,WebPPicture * const dst)280*b2055c35SXin Li void GIFBlendFrames(const WebPPicture* const src,
281*b2055c35SXin Li const GIFFrameRect* const rect, WebPPicture* const dst) {
282*b2055c35SXin Li int i, j;
283*b2055c35SXin Li const size_t src_stride = src->argb_stride;
284*b2055c35SXin Li const size_t dst_stride = dst->argb_stride;
285*b2055c35SXin Li assert(src->width == dst->width && src->height == dst->height);
286*b2055c35SXin Li for (j = rect->y_offset; j < rect->y_offset + rect->height; ++j) {
287*b2055c35SXin Li for (i = rect->x_offset; i < rect->x_offset + rect->width; ++i) {
288*b2055c35SXin Li const uint32_t src_pixel = src->argb[j * src_stride + i];
289*b2055c35SXin Li const int src_alpha = src_pixel >> 24;
290*b2055c35SXin Li if (src_alpha != 0) {
291*b2055c35SXin Li dst->argb[j * dst_stride + i] = src_pixel;
292*b2055c35SXin Li }
293*b2055c35SXin Li }
294*b2055c35SXin Li }
295*b2055c35SXin Li }
296*b2055c35SXin Li
GIFDisplayError(const GifFileType * const gif,int gif_error)297*b2055c35SXin Li void GIFDisplayError(const GifFileType* const gif, int gif_error) {
298*b2055c35SXin Li // libgif 4.2.0 has retired PrintGifError() and added GifErrorString().
299*b2055c35SXin Li #if LOCAL_GIF_PREREQ(4,2)
300*b2055c35SXin Li #if LOCAL_GIF_PREREQ(5,0)
301*b2055c35SXin Li // Static string actually, hence the const char* cast.
302*b2055c35SXin Li const char* error_str = (const char*)GifErrorString(
303*b2055c35SXin Li (gif == NULL) ? gif_error : gif->Error);
304*b2055c35SXin Li #else
305*b2055c35SXin Li const char* error_str = (const char*)GifErrorString();
306*b2055c35SXin Li (void)gif;
307*b2055c35SXin Li #endif
308*b2055c35SXin Li if (error_str == NULL) error_str = "Unknown error";
309*b2055c35SXin Li fprintf(stderr, "GIFLib Error %d: %s\n", gif_error, error_str);
310*b2055c35SXin Li #else
311*b2055c35SXin Li (void)gif;
312*b2055c35SXin Li fprintf(stderr, "GIFLib Error %d: ", gif_error);
313*b2055c35SXin Li PrintGifError();
314*b2055c35SXin Li fprintf(stderr, "\n");
315*b2055c35SXin Li #endif
316*b2055c35SXin Li }
317*b2055c35SXin Li
318*b2055c35SXin Li #else // !WEBP_HAVE_GIF
319*b2055c35SXin Li
ErrorGIFNotAvailable(void)320*b2055c35SXin Li static void ErrorGIFNotAvailable(void) {
321*b2055c35SXin Li fprintf(stderr, "GIF support not compiled. Please install the libgif-dev "
322*b2055c35SXin Li "package before building.\n");
323*b2055c35SXin Li }
324*b2055c35SXin Li
GIFGetBackgroundColor(const struct ColorMapObject * const color_map,int bgcolor_index,int transparent_index,uint32_t * const bgcolor)325*b2055c35SXin Li void GIFGetBackgroundColor(const struct ColorMapObject* const color_map,
326*b2055c35SXin Li int bgcolor_index, int transparent_index,
327*b2055c35SXin Li uint32_t* const bgcolor) {
328*b2055c35SXin Li (void)color_map;
329*b2055c35SXin Li (void)bgcolor_index;
330*b2055c35SXin Li (void)transparent_index;
331*b2055c35SXin Li (void)bgcolor;
332*b2055c35SXin Li ErrorGIFNotAvailable();
333*b2055c35SXin Li }
334*b2055c35SXin Li
GIFReadGraphicsExtension(const GifByteType * const data,int * const duration,GIFDisposeMethod * const dispose,int * const transparent_index)335*b2055c35SXin Li int GIFReadGraphicsExtension(const GifByteType* const data, int* const duration,
336*b2055c35SXin Li GIFDisposeMethod* const dispose,
337*b2055c35SXin Li int* const transparent_index) {
338*b2055c35SXin Li (void)data;
339*b2055c35SXin Li (void)duration;
340*b2055c35SXin Li (void)dispose;
341*b2055c35SXin Li (void)transparent_index;
342*b2055c35SXin Li ErrorGIFNotAvailable();
343*b2055c35SXin Li return 0;
344*b2055c35SXin Li }
345*b2055c35SXin Li
GIFReadFrame(struct GifFileType * const gif,int transparent_index,GIFFrameRect * const gif_rect,struct WebPPicture * const picture)346*b2055c35SXin Li int GIFReadFrame(struct GifFileType* const gif, int transparent_index,
347*b2055c35SXin Li GIFFrameRect* const gif_rect,
348*b2055c35SXin Li struct WebPPicture* const picture) {
349*b2055c35SXin Li (void)gif;
350*b2055c35SXin Li (void)transparent_index;
351*b2055c35SXin Li (void)gif_rect;
352*b2055c35SXin Li (void)picture;
353*b2055c35SXin Li ErrorGIFNotAvailable();
354*b2055c35SXin Li return 0;
355*b2055c35SXin Li }
356*b2055c35SXin Li
GIFReadLoopCount(struct GifFileType * const gif,GifByteType ** const buf,int * const loop_count)357*b2055c35SXin Li int GIFReadLoopCount(struct GifFileType* const gif, GifByteType** const buf,
358*b2055c35SXin Li int* const loop_count) {
359*b2055c35SXin Li (void)gif;
360*b2055c35SXin Li (void)buf;
361*b2055c35SXin Li (void)loop_count;
362*b2055c35SXin Li ErrorGIFNotAvailable();
363*b2055c35SXin Li return 0;
364*b2055c35SXin Li }
365*b2055c35SXin Li
GIFReadMetadata(struct GifFileType * const gif,GifByteType ** const buf,struct WebPData * const metadata)366*b2055c35SXin Li int GIFReadMetadata(struct GifFileType* const gif, GifByteType** const buf,
367*b2055c35SXin Li struct WebPData* const metadata) {
368*b2055c35SXin Li (void)gif;
369*b2055c35SXin Li (void)buf;
370*b2055c35SXin Li (void)metadata;
371*b2055c35SXin Li ErrorGIFNotAvailable();
372*b2055c35SXin Li return 0;
373*b2055c35SXin Li }
374*b2055c35SXin Li
GIFDisposeFrame(GIFDisposeMethod dispose,const GIFFrameRect * const rect,const struct WebPPicture * const prev_canvas,struct WebPPicture * const curr_canvas)375*b2055c35SXin Li void GIFDisposeFrame(GIFDisposeMethod dispose, const GIFFrameRect* const rect,
376*b2055c35SXin Li const struct WebPPicture* const prev_canvas,
377*b2055c35SXin Li struct WebPPicture* const curr_canvas) {
378*b2055c35SXin Li (void)dispose;
379*b2055c35SXin Li (void)rect;
380*b2055c35SXin Li (void)prev_canvas;
381*b2055c35SXin Li (void)curr_canvas;
382*b2055c35SXin Li ErrorGIFNotAvailable();
383*b2055c35SXin Li }
384*b2055c35SXin Li
GIFBlendFrames(const struct WebPPicture * const src,const GIFFrameRect * const rect,struct WebPPicture * const dst)385*b2055c35SXin Li void GIFBlendFrames(const struct WebPPicture* const src,
386*b2055c35SXin Li const GIFFrameRect* const rect,
387*b2055c35SXin Li struct WebPPicture* const dst) {
388*b2055c35SXin Li (void)src;
389*b2055c35SXin Li (void)rect;
390*b2055c35SXin Li (void)dst;
391*b2055c35SXin Li ErrorGIFNotAvailable();
392*b2055c35SXin Li }
393*b2055c35SXin Li
GIFDisplayError(const struct GifFileType * const gif,int gif_error)394*b2055c35SXin Li void GIFDisplayError(const struct GifFileType* const gif, int gif_error) {
395*b2055c35SXin Li (void)gif;
396*b2055c35SXin Li (void)gif_error;
397*b2055c35SXin Li ErrorGIFNotAvailable();
398*b2055c35SXin Li }
399*b2055c35SXin Li
GIFClearPic(struct WebPPicture * const pic,const GIFFrameRect * const rect)400*b2055c35SXin Li void GIFClearPic(struct WebPPicture* const pic,
401*b2055c35SXin Li const GIFFrameRect* const rect) {
402*b2055c35SXin Li (void)pic;
403*b2055c35SXin Li (void)rect;
404*b2055c35SXin Li ErrorGIFNotAvailable();
405*b2055c35SXin Li }
406*b2055c35SXin Li
GIFCopyPixels(const struct WebPPicture * const src,struct WebPPicture * const dst)407*b2055c35SXin Li void GIFCopyPixels(const struct WebPPicture* const src,
408*b2055c35SXin Li struct WebPPicture* const dst) {
409*b2055c35SXin Li (void)src;
410*b2055c35SXin Li (void)dst;
411*b2055c35SXin Li ErrorGIFNotAvailable();
412*b2055c35SXin Li }
413*b2055c35SXin Li
414*b2055c35SXin Li #endif // WEBP_HAVE_GIF
415*b2055c35SXin Li
416*b2055c35SXin Li // -----------------------------------------------------------------------------
417