xref: /aosp_15_r20/external/webp/examples/gifdec.c (revision b2055c353e87c8814eb2b6b1b11112a1562253bd)
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