|
Packit |
9c6abc |
// Copyright 2012 Google Inc. All Rights Reserved.
|
|
Packit |
9c6abc |
//
|
|
Packit |
9c6abc |
// Use of this source code is governed by a BSD-style license
|
|
Packit |
9c6abc |
// that can be found in the COPYING file in the root of the source
|
|
Packit |
9c6abc |
// tree. An additional intellectual property rights grant can be found
|
|
Packit |
9c6abc |
// in the file PATENTS. All contributing project authors may
|
|
Packit |
9c6abc |
// be found in the AUTHORS file in the root of the source tree.
|
|
Packit |
9c6abc |
// -----------------------------------------------------------------------------
|
|
Packit |
9c6abc |
//
|
|
Packit |
9c6abc |
// GIF decode.
|
|
Packit |
9c6abc |
|
|
Packit |
9c6abc |
#include "./gifdec.h"
|
|
Packit |
9c6abc |
|
|
Packit |
9c6abc |
#include <stdio.h>
|
|
Packit |
9c6abc |
|
|
Packit |
9c6abc |
#ifdef WEBP_HAVE_GIF
|
|
Packit |
9c6abc |
#include <assert.h>
|
|
Packit |
9c6abc |
#include <stdlib.h>
|
|
Packit |
9c6abc |
#include <string.h>
|
|
Packit |
9c6abc |
|
|
Packit |
9c6abc |
#include "webp/encode.h"
|
|
Packit |
9c6abc |
#include "webp/mux_types.h"
|
|
Packit |
9c6abc |
|
|
Packit |
9c6abc |
#define GIF_TRANSPARENT_COLOR 0x00000000u
|
|
Packit |
9c6abc |
#define GIF_WHITE_COLOR 0xffffffffu
|
|
Packit |
9c6abc |
#define GIF_TRANSPARENT_MASK 0x01
|
|
Packit |
9c6abc |
#define GIF_DISPOSE_MASK 0x07
|
|
Packit |
9c6abc |
#define GIF_DISPOSE_SHIFT 2
|
|
Packit |
9c6abc |
|
|
Packit |
9c6abc |
// from utils/utils.h
|
|
Packit |
9c6abc |
#ifdef __cplusplus
|
|
Packit |
9c6abc |
extern "C" {
|
|
Packit |
9c6abc |
#endif
|
|
Packit |
9c6abc |
extern void WebPCopyPlane(const uint8_t* src, int src_stride,
|
|
Packit |
9c6abc |
uint8_t* dst, int dst_stride,
|
|
Packit |
9c6abc |
int width, int height);
|
|
Packit |
9c6abc |
extern void WebPCopyPixels(const WebPPicture* const src,
|
|
Packit |
9c6abc |
WebPPicture* const dst);
|
|
Packit |
9c6abc |
#ifdef __cplusplus
|
|
Packit |
9c6abc |
}
|
|
Packit |
9c6abc |
#endif
|
|
Packit |
9c6abc |
|
|
Packit |
9c6abc |
void GIFGetBackgroundColor(const ColorMapObject* const color_map,
|
|
Packit |
9c6abc |
int bgcolor_index, int transparent_index,
|
|
Packit |
9c6abc |
uint32_t* const bgcolor) {
|
|
Packit |
9c6abc |
if (transparent_index != GIF_INDEX_INVALID &&
|
|
Packit |
9c6abc |
bgcolor_index == transparent_index) {
|
|
Packit |
9c6abc |
*bgcolor = GIF_TRANSPARENT_COLOR; // Special case.
|
|
Packit |
9c6abc |
} else if (color_map == NULL || color_map->Colors == NULL
|
|
Packit |
9c6abc |
|| bgcolor_index >= color_map->ColorCount) {
|
|
Packit |
9c6abc |
*bgcolor = GIF_WHITE_COLOR;
|
|
Packit |
9c6abc |
fprintf(stderr,
|
|
Packit |
9c6abc |
"GIF decode warning: invalid background color index. Assuming "
|
|
Packit |
9c6abc |
"white background.\n");
|
|
Packit |
9c6abc |
} else {
|
|
Packit |
9c6abc |
const GifColorType color = color_map->Colors[bgcolor_index];
|
|
Packit |
9c6abc |
*bgcolor = (0xffu << 24)
|
|
Packit |
9c6abc |
| (color.Red << 16)
|
|
Packit |
9c6abc |
| (color.Green << 8)
|
|
Packit |
9c6abc |
| (color.Blue << 0);
|
|
Packit |
9c6abc |
}
|
|
Packit |
9c6abc |
}
|
|
Packit |
9c6abc |
|
|
Packit |
9c6abc |
int GIFReadGraphicsExtension(const GifByteType* const buf, int* const duration,
|
|
Packit |
9c6abc |
GIFDisposeMethod* const dispose,
|
|
Packit |
9c6abc |
int* const transparent_index) {
|
|
Packit |
9c6abc |
const int flags = buf[1];
|
|
Packit |
9c6abc |
const int dispose_raw = (flags >> GIF_DISPOSE_SHIFT) & GIF_DISPOSE_MASK;
|
|
Packit |
9c6abc |
const int duration_raw = buf[2] | (buf[3] << 8); // In 10 ms units.
|
|
Packit |
9c6abc |
if (buf[0] != 4) return 0;
|
|
Packit |
9c6abc |
*duration = duration_raw * 10; // Duration is in 1 ms units.
|
|
Packit |
9c6abc |
switch (dispose_raw) {
|
|
Packit |
9c6abc |
case 3:
|
|
Packit |
9c6abc |
*dispose = GIF_DISPOSE_RESTORE_PREVIOUS;
|
|
Packit |
9c6abc |
break;
|
|
Packit |
9c6abc |
case 2:
|
|
Packit |
9c6abc |
*dispose = GIF_DISPOSE_BACKGROUND;
|
|
Packit |
9c6abc |
break;
|
|
Packit |
9c6abc |
case 1:
|
|
Packit |
9c6abc |
case 0:
|
|
Packit |
9c6abc |
default:
|
|
Packit |
9c6abc |
*dispose = GIF_DISPOSE_NONE;
|
|
Packit |
9c6abc |
break;
|
|
Packit |
9c6abc |
}
|
|
Packit |
9c6abc |
*transparent_index =
|
|
Packit |
9c6abc |
(flags & GIF_TRANSPARENT_MASK) ? buf[4] : GIF_INDEX_INVALID;
|
|
Packit |
9c6abc |
return 1;
|
|
Packit |
9c6abc |
}
|
|
Packit |
9c6abc |
|
|
Packit |
9c6abc |
static int Remap(const GifFileType* const gif, const uint8_t* const src,
|
|
Packit |
9c6abc |
int len, int transparent_index, uint32_t* dst) {
|
|
Packit |
9c6abc |
int i;
|
|
Packit |
9c6abc |
const GifColorType* colors;
|
|
Packit |
9c6abc |
const ColorMapObject* const cmap =
|
|
Packit |
9c6abc |
gif->Image.ColorMap ? gif->Image.ColorMap : gif->SColorMap;
|
|
Packit |
9c6abc |
if (cmap == NULL) return 1;
|
|
Packit |
9c6abc |
if (cmap->Colors == NULL || cmap->ColorCount <= 0) return 0;
|
|
Packit |
9c6abc |
colors = cmap->Colors;
|
|
Packit |
9c6abc |
|
|
Packit |
9c6abc |
for (i = 0; i < len; ++i) {
|
|
Packit |
9c6abc |
if (src[i] == transparent_index) {
|
|
Packit |
9c6abc |
dst[i] = GIF_TRANSPARENT_COLOR;
|
|
Packit |
9c6abc |
} else if (src[i] < cmap->ColorCount) {
|
|
Packit |
9c6abc |
const GifColorType c = colors[src[i]];
|
|
Packit |
9c6abc |
dst[i] = c.Blue | (c.Green << 8) | (c.Red << 16) | (0xffu << 24);
|
|
Packit |
9c6abc |
} else {
|
|
Packit |
9c6abc |
return 0;
|
|
Packit |
9c6abc |
}
|
|
Packit |
9c6abc |
}
|
|
Packit |
9c6abc |
return 1;
|
|
Packit |
9c6abc |
}
|
|
Packit |
9c6abc |
|
|
Packit |
9c6abc |
int GIFReadFrame(GifFileType* const gif, int transparent_index,
|
|
Packit |
9c6abc |
GIFFrameRect* const gif_rect, WebPPicture* const picture) {
|
|
Packit |
9c6abc |
WebPPicture sub_image;
|
|
Packit |
9c6abc |
const GifImageDesc* const image_desc = &gif->Image;
|
|
Packit |
9c6abc |
uint32_t* dst = NULL;
|
|
Packit |
9c6abc |
uint8_t* tmp = NULL;
|
|
Packit |
9c6abc |
const GIFFrameRect rect = {
|
|
Packit |
9c6abc |
image_desc->Left, image_desc->Top, image_desc->Width, image_desc->Height
|
|
Packit |
9c6abc |
};
|
|
Packit |
9c6abc |
const uint64_t memory_needed = 4 * rect.width * (uint64_t)rect.height;
|
|
Packit |
9c6abc |
int ok = 0;
|
|
Packit |
9c6abc |
*gif_rect = rect;
|
|
Packit |
9c6abc |
|
|
Packit |
9c6abc |
if (memory_needed != (size_t)memory_needed || memory_needed > (4ULL << 32)) {
|
|
Packit |
9c6abc |
fprintf(stderr, "Image is too large (%d x %d).", rect.width, rect.height);
|
|
Packit |
9c6abc |
return 0;
|
|
Packit |
9c6abc |
}
|
|
Packit |
9c6abc |
|
|
Packit |
9c6abc |
// Use a view for the sub-picture:
|
|
Packit |
9c6abc |
if (!WebPPictureView(picture, rect.x_offset, rect.y_offset,
|
|
Packit |
9c6abc |
rect.width, rect.height, &sub_image)) {
|
|
Packit |
9c6abc |
fprintf(stderr, "Sub-image %dx%d at position %d,%d is invalid!\n",
|
|
Packit |
9c6abc |
rect.width, rect.height, rect.x_offset, rect.y_offset);
|
|
Packit |
9c6abc |
return 0;
|
|
Packit |
9c6abc |
}
|
|
Packit |
9c6abc |
dst = sub_image.argb;
|
|
Packit |
9c6abc |
|
|
Packit |
9c6abc |
tmp = (uint8_t*)malloc(rect.width * sizeof(*tmp));
|
|
Packit |
9c6abc |
if (tmp == NULL) goto End;
|
|
Packit |
9c6abc |
|
|
Packit |
9c6abc |
if (image_desc->Interlace) { // Interlaced image.
|
|
Packit |
9c6abc |
// We need 4 passes, with the following offsets and jumps.
|
|
Packit |
9c6abc |
const int interlace_offsets[] = { 0, 4, 2, 1 };
|
|
Packit |
9c6abc |
const int interlace_jumps[] = { 8, 8, 4, 2 };
|
|
Packit |
9c6abc |
int pass;
|
|
Packit |
9c6abc |
for (pass = 0; pass < 4; ++pass) {
|
|
Packit |
9c6abc |
const size_t stride = (size_t)sub_image.argb_stride;
|
|
Packit |
9c6abc |
int y = interlace_offsets[pass];
|
|
Packit |
9c6abc |
uint32_t* row = dst + y * stride;
|
|
Packit |
9c6abc |
const size_t jump = interlace_jumps[pass] * stride;
|
|
Packit |
9c6abc |
for (; y < rect.height; y += interlace_jumps[pass], row += jump) {
|
|
Packit |
9c6abc |
if (DGifGetLine(gif, tmp, rect.width) == GIF_ERROR) goto End;
|
|
Packit |
9c6abc |
if (!Remap(gif, tmp, rect.width, transparent_index, row)) goto End;
|
|
Packit |
9c6abc |
}
|
|
Packit |
9c6abc |
}
|
|
Packit |
9c6abc |
} else { // Non-interlaced image.
|
|
Packit |
9c6abc |
int y;
|
|
Packit |
9c6abc |
uint32_t* ptr = dst;
|
|
Packit |
9c6abc |
for (y = 0; y < rect.height; ++y, ptr += sub_image.argb_stride) {
|
|
Packit |
9c6abc |
if (DGifGetLine(gif, tmp, rect.width) == GIF_ERROR) goto End;
|
|
Packit |
9c6abc |
if (!Remap(gif, tmp, rect.width, transparent_index, ptr)) goto End;
|
|
Packit |
9c6abc |
}
|
|
Packit |
9c6abc |
}
|
|
Packit |
9c6abc |
ok = 1;
|
|
Packit |
9c6abc |
|
|
Packit |
9c6abc |
End:
|
|
Packit |
9c6abc |
if (!ok) picture->error_code = sub_image.error_code;
|
|
Packit |
9c6abc |
WebPPictureFree(&sub_image);
|
|
Packit |
9c6abc |
free(tmp);
|
|
Packit |
9c6abc |
return ok;
|
|
Packit |
9c6abc |
}
|
|
Packit |
9c6abc |
|
|
Packit |
9c6abc |
int GIFReadLoopCount(GifFileType* const gif, GifByteType** const buf,
|
|
Packit |
9c6abc |
int* const loop_count) {
|
|
Packit |
9c6abc |
assert(!memcmp(*buf + 1, "NETSCAPE2.0", 11) ||
|
|
Packit |
9c6abc |
!memcmp(*buf + 1, "ANIMEXTS1.0", 11));
|
|
Packit |
9c6abc |
if (DGifGetExtensionNext(gif, buf) == GIF_ERROR) {
|
|
Packit |
9c6abc |
return 0;
|
|
Packit |
9c6abc |
}
|
|
Packit |
9c6abc |
if (*buf == NULL) {
|
|
Packit |
9c6abc |
return 0; // Loop count sub-block missing.
|
|
Packit |
9c6abc |
}
|
|
Packit |
9c6abc |
if ((*buf)[0] < 3 || (*buf)[1] != 1) {
|
|
Packit |
9c6abc |
return 0; // wrong size/marker
|
|
Packit |
9c6abc |
}
|
|
Packit |
9c6abc |
*loop_count = (*buf)[2] | ((*buf)[3] << 8);
|
|
Packit |
9c6abc |
return 1;
|
|
Packit |
9c6abc |
}
|
|
Packit |
9c6abc |
|
|
Packit |
9c6abc |
int GIFReadMetadata(GifFileType* const gif, GifByteType** const buf,
|
|
Packit |
9c6abc |
WebPData* const metadata) {
|
|
Packit |
9c6abc |
const int is_xmp = !memcmp(*buf + 1, "XMP DataXMP", 11);
|
|
Packit |
9c6abc |
const int is_icc = !memcmp(*buf + 1, "ICCRGBG1012", 11);
|
|
Packit |
9c6abc |
assert(is_xmp || is_icc);
|
|
Packit |
9c6abc |
(void)is_icc; // silence unused warning.
|
|
Packit |
9c6abc |
// Construct metadata from sub-blocks.
|
|
Packit |
9c6abc |
// Usual case (including ICC profile): In each sub-block, the
|
|
Packit |
9c6abc |
// first byte specifies its size in bytes (0 to 255) and the
|
|
Packit |
9c6abc |
// rest of the bytes contain the data.
|
|
Packit |
9c6abc |
// Special case for XMP data: In each sub-block, the first byte
|
|
Packit |
9c6abc |
// is also part of the XMP payload. XMP in GIF also has a 257
|
|
Packit |
9c6abc |
// byte padding data. See the XMP specification for details.
|
|
Packit |
9c6abc |
while (1) {
|
|
Packit |
9c6abc |
WebPData subblock;
|
|
Packit |
9c6abc |
const uint8_t* tmp;
|
|
Packit |
9c6abc |
if (DGifGetExtensionNext(gif, buf) == GIF_ERROR) {
|
|
Packit |
9c6abc |
return 0;
|
|
Packit |
9c6abc |
}
|
|
Packit |
9c6abc |
if (*buf == NULL) break; // Finished.
|
|
Packit |
9c6abc |
subblock.size = is_xmp ? (*buf)[0] + 1 : (*buf)[0];
|
|
Packit |
9c6abc |
assert(subblock.size > 0);
|
|
Packit |
9c6abc |
subblock.bytes = is_xmp ? *buf : *buf + 1;
|
|
Packit |
9c6abc |
// Note: We store returned value in 'tmp' first, to avoid
|
|
Packit |
9c6abc |
// leaking old memory in metadata->bytes on error.
|
|
Packit |
9c6abc |
tmp = (uint8_t*)realloc((void*)metadata->bytes,
|
|
Packit |
9c6abc |
metadata->size + subblock.size);
|
|
Packit |
9c6abc |
if (tmp == NULL) {
|
|
Packit |
9c6abc |
return 0;
|
|
Packit |
9c6abc |
}
|
|
Packit |
9c6abc |
memcpy((void*)(tmp + metadata->size),
|
|
Packit |
9c6abc |
subblock.bytes, subblock.size);
|
|
Packit |
9c6abc |
metadata->bytes = tmp;
|
|
Packit |
9c6abc |
metadata->size += subblock.size;
|
|
Packit |
9c6abc |
}
|
|
Packit |
9c6abc |
if (is_xmp) {
|
|
Packit |
9c6abc |
// XMP padding data is 0x01, 0xff, 0xfe ... 0x01, 0x00.
|
|
Packit |
9c6abc |
const size_t xmp_pading_size = 257;
|
|
Packit |
9c6abc |
if (metadata->size > xmp_pading_size) {
|
|
Packit |
9c6abc |
metadata->size -= xmp_pading_size;
|
|
Packit |
9c6abc |
}
|
|
Packit |
9c6abc |
}
|
|
Packit |
9c6abc |
return 1;
|
|
Packit |
9c6abc |
}
|
|
Packit |
9c6abc |
|
|
Packit |
9c6abc |
static void ClearRectangle(WebPPicture* const picture,
|
|
Packit |
9c6abc |
int left, int top, int width, int height) {
|
|
Packit |
9c6abc |
int i, j;
|
|
Packit |
9c6abc |
const size_t stride = picture->argb_stride;
|
|
Packit |
9c6abc |
uint32_t* dst = picture->argb + top * stride + left;
|
|
Packit |
9c6abc |
for (j = 0; j < height; ++j, dst += stride) {
|
|
Packit |
9c6abc |
for (i = 0; i < width; ++i) dst[i] = GIF_TRANSPARENT_COLOR;
|
|
Packit |
9c6abc |
}
|
|
Packit |
9c6abc |
}
|
|
Packit |
9c6abc |
|
|
Packit |
9c6abc |
void GIFClearPic(WebPPicture* const pic, const GIFFrameRect* const rect) {
|
|
Packit |
9c6abc |
if (rect != NULL) {
|
|
Packit |
9c6abc |
ClearRectangle(pic, rect->x_offset, rect->y_offset,
|
|
Packit |
9c6abc |
rect->width, rect->height);
|
|
Packit |
9c6abc |
} else {
|
|
Packit |
9c6abc |
ClearRectangle(pic, 0, 0, pic->width, pic->height);
|
|
Packit |
9c6abc |
}
|
|
Packit |
9c6abc |
}
|
|
Packit |
9c6abc |
|
|
Packit |
9c6abc |
void GIFCopyPixels(const WebPPicture* const src, WebPPicture* const dst) {
|
|
Packit |
9c6abc |
WebPCopyPixels(src, dst);
|
|
Packit |
9c6abc |
}
|
|
Packit |
9c6abc |
|
|
Packit |
9c6abc |
void GIFDisposeFrame(GIFDisposeMethod dispose, const GIFFrameRect* const rect,
|
|
Packit |
9c6abc |
const WebPPicture* const prev_canvas,
|
|
Packit |
9c6abc |
WebPPicture* const curr_canvas) {
|
|
Packit |
9c6abc |
assert(rect != NULL);
|
|
Packit |
9c6abc |
if (dispose == GIF_DISPOSE_BACKGROUND) {
|
|
Packit |
9c6abc |
GIFClearPic(curr_canvas, rect);
|
|
Packit |
9c6abc |
} else if (dispose == GIF_DISPOSE_RESTORE_PREVIOUS) {
|
|
Packit |
9c6abc |
const size_t src_stride = prev_canvas->argb_stride;
|
|
Packit |
9c6abc |
const uint32_t* const src = prev_canvas->argb + rect->x_offset
|
|
Packit |
9c6abc |
+ rect->y_offset * src_stride;
|
|
Packit |
9c6abc |
const size_t dst_stride = curr_canvas->argb_stride;
|
|
Packit |
9c6abc |
uint32_t* const dst = curr_canvas->argb + rect->x_offset
|
|
Packit |
9c6abc |
+ rect->y_offset * dst_stride;
|
|
Packit |
9c6abc |
assert(prev_canvas != NULL);
|
|
Packit |
9c6abc |
WebPCopyPlane((uint8_t*)src, (int)(4 * src_stride),
|
|
Packit |
9c6abc |
(uint8_t*)dst, (int)(4 * dst_stride),
|
|
Packit |
9c6abc |
4 * rect->width, rect->height);
|
|
Packit |
9c6abc |
}
|
|
Packit |
9c6abc |
}
|
|
Packit |
9c6abc |
|
|
Packit |
9c6abc |
void GIFBlendFrames(const WebPPicture* const src,
|
|
Packit |
9c6abc |
const GIFFrameRect* const rect, WebPPicture* const dst) {
|
|
Packit |
9c6abc |
int i, j;
|
|
Packit |
9c6abc |
const size_t src_stride = src->argb_stride;
|
|
Packit |
9c6abc |
const size_t dst_stride = dst->argb_stride;
|
|
Packit |
9c6abc |
assert(src->width == dst->width && src->height == dst->height);
|
|
Packit |
9c6abc |
for (j = rect->y_offset; j < rect->y_offset + rect->height; ++j) {
|
|
Packit |
9c6abc |
for (i = rect->x_offset; i < rect->x_offset + rect->width; ++i) {
|
|
Packit |
9c6abc |
const uint32_t src_pixel = src->argb[j * src_stride + i];
|
|
Packit |
9c6abc |
const int src_alpha = src_pixel >> 24;
|
|
Packit |
9c6abc |
if (src_alpha != 0) {
|
|
Packit |
9c6abc |
dst->argb[j * dst_stride + i] = src_pixel;
|
|
Packit |
9c6abc |
}
|
|
Packit |
9c6abc |
}
|
|
Packit |
9c6abc |
}
|
|
Packit |
9c6abc |
}
|
|
Packit |
9c6abc |
|
|
Packit |
9c6abc |
void GIFDisplayError(const GifFileType* const gif, int gif_error) {
|
|
Packit |
9c6abc |
// libgif 4.2.0 has retired PrintGifError() and added GifErrorString().
|
|
Packit |
9c6abc |
#if LOCAL_GIF_PREREQ(4,2)
|
|
Packit |
9c6abc |
#if LOCAL_GIF_PREREQ(5,0)
|
|
Packit |
9c6abc |
// Static string actually, hence the const char* cast.
|
|
Packit |
9c6abc |
const char* error_str = (const char*)GifErrorString(
|
|
Packit |
9c6abc |
(gif == NULL) ? gif_error : gif->Error);
|
|
Packit |
9c6abc |
#else
|
|
Packit |
9c6abc |
const char* error_str = (const char*)GifErrorString();
|
|
Packit |
9c6abc |
(void)gif;
|
|
Packit |
9c6abc |
#endif
|
|
Packit |
9c6abc |
if (error_str == NULL) error_str = "Unknown error";
|
|
Packit |
9c6abc |
fprintf(stderr, "GIFLib Error %d: %s\n", gif_error, error_str);
|
|
Packit |
9c6abc |
#else
|
|
Packit |
9c6abc |
(void)gif;
|
|
Packit |
9c6abc |
fprintf(stderr, "GIFLib Error %d: ", gif_error);
|
|
Packit |
9c6abc |
PrintGifError();
|
|
Packit |
9c6abc |
fprintf(stderr, "\n");
|
|
Packit |
9c6abc |
#endif
|
|
Packit |
9c6abc |
}
|
|
Packit |
9c6abc |
|
|
Packit |
9c6abc |
#else // !WEBP_HAVE_GIF
|
|
Packit |
9c6abc |
|
|
Packit |
9c6abc |
static void ErrorGIFNotAvailable() {
|
|
Packit |
9c6abc |
fprintf(stderr, "GIF support not compiled. Please install the libgif-dev "
|
|
Packit |
9c6abc |
"package before building.\n");
|
|
Packit |
9c6abc |
}
|
|
Packit |
9c6abc |
|
|
Packit |
9c6abc |
void GIFGetBackgroundColor(const struct ColorMapObject* const color_map,
|
|
Packit |
9c6abc |
int bgcolor_index, int transparent_index,
|
|
Packit |
9c6abc |
uint32_t* const bgcolor) {
|
|
Packit |
9c6abc |
(void)color_map;
|
|
Packit |
9c6abc |
(void)bgcolor_index;
|
|
Packit |
9c6abc |
(void)transparent_index;
|
|
Packit |
9c6abc |
(void)bgcolor;
|
|
Packit |
9c6abc |
ErrorGIFNotAvailable();
|
|
Packit |
9c6abc |
}
|
|
Packit |
9c6abc |
|
|
Packit |
9c6abc |
int GIFReadGraphicsExtension(const GifByteType* const data, int* const duration,
|
|
Packit |
9c6abc |
GIFDisposeMethod* const dispose,
|
|
Packit |
9c6abc |
int* const transparent_index) {
|
|
Packit |
9c6abc |
(void)data;
|
|
Packit |
9c6abc |
(void)duration;
|
|
Packit |
9c6abc |
(void)dispose;
|
|
Packit |
9c6abc |
(void)transparent_index;
|
|
Packit |
9c6abc |
ErrorGIFNotAvailable();
|
|
Packit |
9c6abc |
return 0;
|
|
Packit |
9c6abc |
}
|
|
Packit |
9c6abc |
|
|
Packit |
9c6abc |
int GIFReadFrame(struct GifFileType* const gif, int transparent_index,
|
|
Packit |
9c6abc |
GIFFrameRect* const gif_rect,
|
|
Packit |
9c6abc |
struct WebPPicture* const picture) {
|
|
Packit |
9c6abc |
(void)gif;
|
|
Packit |
9c6abc |
(void)transparent_index;
|
|
Packit |
9c6abc |
(void)gif_rect;
|
|
Packit |
9c6abc |
(void)picture;
|
|
Packit |
9c6abc |
ErrorGIFNotAvailable();
|
|
Packit |
9c6abc |
return 0;
|
|
Packit |
9c6abc |
}
|
|
Packit |
9c6abc |
|
|
Packit |
9c6abc |
int GIFReadLoopCount(struct GifFileType* const gif, GifByteType** const buf,
|
|
Packit |
9c6abc |
int* const loop_count) {
|
|
Packit |
9c6abc |
(void)gif;
|
|
Packit |
9c6abc |
(void)buf;
|
|
Packit |
9c6abc |
(void)loop_count;
|
|
Packit |
9c6abc |
ErrorGIFNotAvailable();
|
|
Packit |
9c6abc |
return 0;
|
|
Packit |
9c6abc |
}
|
|
Packit |
9c6abc |
|
|
Packit |
9c6abc |
int GIFReadMetadata(struct GifFileType* const gif, GifByteType** const buf,
|
|
Packit |
9c6abc |
struct WebPData* const metadata) {
|
|
Packit |
9c6abc |
(void)gif;
|
|
Packit |
9c6abc |
(void)buf;
|
|
Packit |
9c6abc |
(void)metadata;
|
|
Packit |
9c6abc |
ErrorGIFNotAvailable();
|
|
Packit |
9c6abc |
return 0;
|
|
Packit |
9c6abc |
}
|
|
Packit |
9c6abc |
|
|
Packit |
9c6abc |
void GIFDisposeFrame(GIFDisposeMethod dispose, const GIFFrameRect* const rect,
|
|
Packit |
9c6abc |
const struct WebPPicture* const prev_canvas,
|
|
Packit |
9c6abc |
struct WebPPicture* const curr_canvas) {
|
|
Packit |
9c6abc |
(void)dispose;
|
|
Packit |
9c6abc |
(void)rect;
|
|
Packit |
9c6abc |
(void)prev_canvas;
|
|
Packit |
9c6abc |
(void)curr_canvas;
|
|
Packit |
9c6abc |
ErrorGIFNotAvailable();
|
|
Packit |
9c6abc |
}
|
|
Packit |
9c6abc |
|
|
Packit |
9c6abc |
void GIFBlendFrames(const struct WebPPicture* const src,
|
|
Packit |
9c6abc |
const GIFFrameRect* const rect,
|
|
Packit |
9c6abc |
struct WebPPicture* const dst) {
|
|
Packit |
9c6abc |
(void)src;
|
|
Packit |
9c6abc |
(void)rect;
|
|
Packit |
9c6abc |
(void)dst;
|
|
Packit |
9c6abc |
ErrorGIFNotAvailable();
|
|
Packit |
9c6abc |
}
|
|
Packit |
9c6abc |
|
|
Packit |
9c6abc |
void GIFDisplayError(const struct GifFileType* const gif, int gif_error) {
|
|
Packit |
9c6abc |
(void)gif;
|
|
Packit |
9c6abc |
(void)gif_error;
|
|
Packit |
9c6abc |
ErrorGIFNotAvailable();
|
|
Packit |
9c6abc |
}
|
|
Packit |
9c6abc |
|
|
Packit |
9c6abc |
void GIFClearPic(struct WebPPicture* const pic,
|
|
Packit |
9c6abc |
const GIFFrameRect* const rect) {
|
|
Packit |
9c6abc |
(void)pic;
|
|
Packit |
9c6abc |
(void)rect;
|
|
Packit |
9c6abc |
ErrorGIFNotAvailable();
|
|
Packit |
9c6abc |
}
|
|
Packit |
9c6abc |
|
|
Packit |
9c6abc |
void GIFCopyPixels(const struct WebPPicture* const src,
|
|
Packit |
9c6abc |
struct WebPPicture* const dst) {
|
|
Packit |
9c6abc |
(void)src;
|
|
Packit |
9c6abc |
(void)dst;
|
|
Packit |
9c6abc |
ErrorGIFNotAvailable();
|
|
Packit |
9c6abc |
}
|
|
Packit |
9c6abc |
|
|
Packit |
9c6abc |
#endif // WEBP_HAVE_GIF
|
|
Packit |
9c6abc |
|
|
Packit |
9c6abc |
// -----------------------------------------------------------------------------
|