summaryrefslogtreecommitdiff
path: root/thirdparty/libwebp/mux
diff options
context:
space:
mode:
Diffstat (limited to 'thirdparty/libwebp/mux')
-rw-r--r--thirdparty/libwebp/mux/anim_encode.c51
-rw-r--r--thirdparty/libwebp/mux/animi.h43
-rw-r--r--thirdparty/libwebp/mux/muxedit.c157
-rw-r--r--thirdparty/libwebp/mux/muxi.h16
-rw-r--r--thirdparty/libwebp/mux/muxinternal.c21
-rw-r--r--thirdparty/libwebp/mux/muxread.c48
6 files changed, 175 insertions, 161 deletions
diff --git a/thirdparty/libwebp/mux/anim_encode.c b/thirdparty/libwebp/mux/anim_encode.c
index 398ba8d850..6066388727 100644
--- a/thirdparty/libwebp/mux/anim_encode.c
+++ b/thirdparty/libwebp/mux/anim_encode.c
@@ -16,6 +16,7 @@
#include <stdio.h>
#include <stdlib.h> // for abs()
+#include "../mux/animi.h"
#include "../utils/utils.h"
#include "../webp/decode.h"
#include "../webp/encode.h"
@@ -128,14 +129,13 @@ static void SanitizeEncoderOptions(WebPAnimEncoderOptions* const enc_options) {
DisableKeyframes(enc_options);
}
- if (enc_options->kmin <= 0) {
- DisableKeyframes(enc_options);
- print_warning = 0;
- }
- if (enc_options->kmax <= 0) { // All frames will be key-frames.
+ if (enc_options->kmax == 1) { // All frames will be key-frames.
enc_options->kmin = 0;
enc_options->kmax = 0;
return;
+ } else if (enc_options->kmax <= 0) {
+ DisableKeyframes(enc_options);
+ print_warning = 0;
}
if (enc_options->kmin >= enc_options->kmax) {
@@ -378,10 +378,10 @@ static WEBP_INLINE int PixelsAreSimilar(uint32_t src, uint32_t dst,
const int dst_g = (dst >> 8) & 0xff;
const int dst_b = (dst >> 0) & 0xff;
- return (abs(src_r * src_a - dst_r * dst_a) <= (max_allowed_diff * 255)) &&
- (abs(src_g * src_a - dst_g * dst_a) <= (max_allowed_diff * 255)) &&
- (abs(src_b * src_a - dst_b * dst_a) <= (max_allowed_diff * 255)) &&
- (abs(src_a - dst_a) <= max_allowed_diff);
+ return (src_a == dst_a) &&
+ (abs(src_r - dst_r) * dst_a <= (max_allowed_diff * 255)) &&
+ (abs(src_g - dst_g) * dst_a <= (max_allowed_diff * 255)) &&
+ (abs(src_b - dst_b) * dst_a <= (max_allowed_diff * 255));
}
// Returns true if 'length' number of pixels in 'src' and 'dst' are within an
@@ -586,6 +586,39 @@ static int GetSubRects(const WebPPicture* const prev_canvas,
&params->rect_lossy_, &params->sub_frame_lossy_);
}
+static WEBP_INLINE int clip(int v, int min_v, int max_v) {
+ return (v < min_v) ? min_v : (v > max_v) ? max_v : v;
+}
+
+int WebPAnimEncoderRefineRect(
+ const WebPPicture* const prev_canvas, const WebPPicture* const curr_canvas,
+ int is_lossless, float quality, int* const x_offset, int* const y_offset,
+ int* const width, int* const height) {
+ FrameRect rect;
+ const int right = clip(*x_offset + *width, 0, curr_canvas->width);
+ const int left = clip(*x_offset, 0, curr_canvas->width - 1);
+ const int bottom = clip(*y_offset + *height, 0, curr_canvas->height);
+ const int top = clip(*y_offset, 0, curr_canvas->height - 1);
+ if (prev_canvas == NULL || curr_canvas == NULL ||
+ prev_canvas->width != curr_canvas->width ||
+ prev_canvas->height != curr_canvas->height ||
+ !prev_canvas->use_argb || !curr_canvas->use_argb) {
+ return 0;
+ }
+ rect.x_offset_ = left;
+ rect.y_offset_ = top;
+ rect.width_ = clip(right - left, 0, curr_canvas->width - rect.x_offset_);
+ rect.height_ = clip(bottom - top, 0, curr_canvas->height - rect.y_offset_);
+ MinimizeChangeRectangle(prev_canvas, curr_canvas, &rect, is_lossless,
+ quality);
+ SnapToEvenOffsets(&rect);
+ *x_offset = rect.x_offset_;
+ *y_offset = rect.y_offset_;
+ *width = rect.width_;
+ *height = rect.height_;
+ return 1;
+}
+
static void DisposeFrameRectangle(int dispose_method,
const FrameRect* const rect,
WebPPicture* const curr_canvas) {
diff --git a/thirdparty/libwebp/mux/animi.h b/thirdparty/libwebp/mux/animi.h
new file mode 100644
index 0000000000..cecaf1fee5
--- /dev/null
+++ b/thirdparty/libwebp/mux/animi.h
@@ -0,0 +1,43 @@
+// Copyright 2016 Google Inc. All Rights Reserved.
+//
+// Use of this source code is governed by a BSD-style license
+// that can be found in the COPYING file in the root of the source
+// tree. An additional intellectual property rights grant can be found
+// in the file PATENTS. All contributing project authors may
+// be found in the AUTHORS file in the root of the source tree.
+// -----------------------------------------------------------------------------
+//
+// Internal header for animation related functions.
+//
+// Author: Hui Su (huisu@google.com)
+
+#ifndef WEBP_MUX_ANIMI_H_
+#define WEBP_MUX_ANIMI_H_
+
+#include "../webp/mux.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+// Picks the optimal rectangle between two pictures, starting with initial
+// values of offsets and dimensions that are passed in. The initial
+// values will be clipped, if necessary, to make sure the rectangle is
+// within the canvas. "use_argb" must be true for both pictures.
+// Parameters:
+// prev_canvas, curr_canvas - (in) two input pictures to compare.
+// is_lossless, quality - (in) encoding settings.
+// x_offset, y_offset, width, height - (in/out) rectangle between the two
+// input pictures.
+// Returns true on success.
+int WebPAnimEncoderRefineRect(
+ const struct WebPPicture* const prev_canvas,
+ const struct WebPPicture* const curr_canvas,
+ int is_lossless, float quality, int* const x_offset, int* const y_offset,
+ int* const width, int* const height);
+
+#ifdef __cplusplus
+} // extern "C"
+#endif
+
+#endif /* WEBP_MUX_ANIMI_H_ */
diff --git a/thirdparty/libwebp/mux/muxedit.c b/thirdparty/libwebp/mux/muxedit.c
index 9bbed42b1a..d2c5305372 100644
--- a/thirdparty/libwebp/mux/muxedit.c
+++ b/thirdparty/libwebp/mux/muxedit.c
@@ -93,34 +93,32 @@ static WebPMuxError MuxSet(WebPMux* const mux, uint32_t tag, uint32_t nth,
}
#undef SWITCH_ID_LIST
-// Create data for frame/fragment given image data, offsets and duration.
-static WebPMuxError CreateFrameFragmentData(
- int width, int height, const WebPMuxFrameInfo* const info, int is_frame,
- WebPData* const frame_frgm) {
- uint8_t* frame_frgm_bytes;
- const size_t frame_frgm_size = kChunks[is_frame ? IDX_ANMF : IDX_FRGM].size;
+// Create data for frame given image data, offsets and duration.
+static WebPMuxError CreateFrameData(
+ int width, int height, const WebPMuxFrameInfo* const info,
+ WebPData* const frame) {
+ uint8_t* frame_bytes;
+ const size_t frame_size = kChunks[IDX_ANMF].size;
assert(width > 0 && height > 0 && info->duration >= 0);
assert(info->dispose_method == (info->dispose_method & 1));
// Note: assertion on upper bounds is done in PutLE24().
- frame_frgm_bytes = (uint8_t*)WebPSafeMalloc(1ULL, frame_frgm_size);
- if (frame_frgm_bytes == NULL) return WEBP_MUX_MEMORY_ERROR;
+ frame_bytes = (uint8_t*)WebPSafeMalloc(1ULL, frame_size);
+ if (frame_bytes == NULL) return WEBP_MUX_MEMORY_ERROR;
- PutLE24(frame_frgm_bytes + 0, info->x_offset / 2);
- PutLE24(frame_frgm_bytes + 3, info->y_offset / 2);
+ PutLE24(frame_bytes + 0, info->x_offset / 2);
+ PutLE24(frame_bytes + 3, info->y_offset / 2);
- if (is_frame) {
- PutLE24(frame_frgm_bytes + 6, width - 1);
- PutLE24(frame_frgm_bytes + 9, height - 1);
- PutLE24(frame_frgm_bytes + 12, info->duration);
- frame_frgm_bytes[15] =
- (info->blend_method == WEBP_MUX_NO_BLEND ? 2 : 0) |
- (info->dispose_method == WEBP_MUX_DISPOSE_BACKGROUND ? 1 : 0);
- }
+ PutLE24(frame_bytes + 6, width - 1);
+ PutLE24(frame_bytes + 9, height - 1);
+ PutLE24(frame_bytes + 12, info->duration);
+ frame_bytes[15] =
+ (info->blend_method == WEBP_MUX_NO_BLEND ? 2 : 0) |
+ (info->dispose_method == WEBP_MUX_DISPOSE_BACKGROUND ? 1 : 0);
- frame_frgm->bytes = frame_frgm_bytes;
- frame_frgm->size = frame_frgm_size;
+ frame->bytes = frame_bytes;
+ frame->size = frame_size;
return WEBP_MUX_OK;
}
@@ -264,23 +262,16 @@ WebPMuxError WebPMuxSetImage(WebPMux* mux, const WebPData* bitstream,
return err;
}
-WebPMuxError WebPMuxPushFrame(WebPMux* mux, const WebPMuxFrameInfo* frame,
+WebPMuxError WebPMuxPushFrame(WebPMux* mux, const WebPMuxFrameInfo* info,
int copy_data) {
WebPMuxImage wpi;
WebPMuxError err;
- int is_frame;
- const WebPData* const bitstream = &frame->bitstream;
+ const WebPData* const bitstream = &info->bitstream;
// Sanity checks.
- if (mux == NULL || frame == NULL) return WEBP_MUX_INVALID_ARGUMENT;
+ if (mux == NULL || info == NULL) return WEBP_MUX_INVALID_ARGUMENT;
- is_frame = (frame->id == WEBP_CHUNK_ANMF);
- if (!(is_frame || (frame->id == WEBP_CHUNK_FRGM))) {
- return WEBP_MUX_INVALID_ARGUMENT;
- }
- if (frame->id == WEBP_CHUNK_FRGM) { // Dead experiment.
- return WEBP_MUX_INVALID_ARGUMENT;
- }
+ if (info->id != WEBP_CHUNK_ANMF) return WEBP_MUX_INVALID_ARGUMENT;
if (bitstream->bytes == NULL || bitstream->size > MAX_CHUNK_PAYLOAD) {
return WEBP_MUX_INVALID_ARGUMENT;
@@ -290,7 +281,7 @@ WebPMuxError WebPMuxPushFrame(WebPMux* mux, const WebPMuxFrameInfo* frame,
const WebPMuxImage* const image = mux->images_;
const uint32_t image_id = (image->header_ != NULL) ?
ChunkGetIdFromTag(image->header_->tag_) : WEBP_CHUNK_IMAGE;
- if (image_id != frame->id) {
+ if (image_id != info->id) {
return WEBP_MUX_INVALID_ARGUMENT; // Conflicting frame types.
}
}
@@ -301,16 +292,11 @@ WebPMuxError WebPMuxPushFrame(WebPMux* mux, const WebPMuxFrameInfo* frame,
assert(wpi.img_ != NULL); // As SetAlphaAndImageChunks() was successful.
{
- WebPData frame_frgm;
- const uint32_t tag = kChunks[is_frame ? IDX_ANMF : IDX_FRGM].tag;
- WebPMuxFrameInfo tmp = *frame;
+ WebPData frame;
+ const uint32_t tag = kChunks[IDX_ANMF].tag;
+ WebPMuxFrameInfo tmp = *info;
tmp.x_offset &= ~1; // Snap offsets to even.
tmp.y_offset &= ~1;
- if (!is_frame) { // Reset unused values.
- tmp.duration = 1;
- tmp.dispose_method = WEBP_MUX_DISPOSE_NONE;
- tmp.blend_method = WEBP_MUX_BLEND;
- }
if (tmp.x_offset < 0 || tmp.x_offset >= MAX_POSITION_OFFSET ||
tmp.y_offset < 0 || tmp.y_offset >= MAX_POSITION_OFFSET ||
(tmp.duration < 0 || tmp.duration >= MAX_DURATION) ||
@@ -318,12 +304,11 @@ WebPMuxError WebPMuxPushFrame(WebPMux* mux, const WebPMuxFrameInfo* frame,
err = WEBP_MUX_INVALID_ARGUMENT;
goto Err;
}
- err = CreateFrameFragmentData(wpi.width_, wpi.height_, &tmp, is_frame,
- &frame_frgm);
+ err = CreateFrameData(wpi.width_, wpi.height_, &tmp, &frame);
if (err != WEBP_MUX_OK) goto Err;
- // Add frame/fragment chunk (with copy_data = 1).
- err = AddDataToChunkList(&frame_frgm, 1, tag, &wpi.header_);
- WebPDataClear(&frame_frgm); // frame_frgm owned by wpi.header_ now.
+ // Add frame chunk (with copy_data = 1).
+ err = AddDataToChunkList(&frame, 1, tag, &wpi.header_);
+ WebPDataClear(&frame); // frame owned by wpi.header_ now.
if (err != WEBP_MUX_OK) goto Err;
}
@@ -402,21 +387,18 @@ WebPMuxError WebPMuxDeleteFrame(WebPMux* mux, uint32_t nth) {
//------------------------------------------------------------------------------
// Assembly of the WebP RIFF file.
-static WebPMuxError GetFrameFragmentInfo(
- const WebPChunk* const frame_frgm_chunk,
+static WebPMuxError GetFrameInfo(
+ const WebPChunk* const frame_chunk,
int* const x_offset, int* const y_offset, int* const duration) {
- const uint32_t tag = frame_frgm_chunk->tag_;
- const int is_frame = (tag == kChunks[IDX_ANMF].tag);
- const WebPData* const data = &frame_frgm_chunk->data_;
- const size_t expected_data_size =
- is_frame ? ANMF_CHUNK_SIZE : FRGM_CHUNK_SIZE;
- assert(frame_frgm_chunk != NULL);
- assert(tag == kChunks[IDX_ANMF].tag || tag == kChunks[IDX_FRGM].tag);
+ const WebPData* const data = &frame_chunk->data_;
+ const size_t expected_data_size = ANMF_CHUNK_SIZE;
+ assert(frame_chunk->tag_ == kChunks[IDX_ANMF].tag);
+ assert(frame_chunk != NULL);
if (data->size != expected_data_size) return WEBP_MUX_INVALID_ARGUMENT;
*x_offset = 2 * GetLE24(data->bytes + 0);
*y_offset = 2 * GetLE24(data->bytes + 3);
- if (is_frame) *duration = GetLE24(data->bytes + 12);
+ *duration = GetLE24(data->bytes + 12);
return WEBP_MUX_OK;
}
@@ -424,13 +406,13 @@ static WebPMuxError GetImageInfo(const WebPMuxImage* const wpi,
int* const x_offset, int* const y_offset,
int* const duration,
int* const width, int* const height) {
- const WebPChunk* const frame_frgm_chunk = wpi->header_;
+ const WebPChunk* const frame_chunk = wpi->header_;
WebPMuxError err;
assert(wpi != NULL);
- assert(frame_frgm_chunk != NULL);
+ assert(frame_chunk != NULL);
- // Get offsets and duration from ANMF/FRGM chunk.
- err = GetFrameFragmentInfo(frame_frgm_chunk, x_offset, y_offset, duration);
+ // Get offsets and duration from ANMF chunk.
+ err = GetFrameInfo(frame_chunk, x_offset, y_offset, duration);
if (err != WEBP_MUX_OK) return err;
// Get width and height from VP8/VP8L chunk.
@@ -441,7 +423,6 @@ static WebPMuxError GetImageInfo(const WebPMuxImage* const wpi,
// Returns the tightest dimension for the canvas considering the image list.
static WebPMuxError GetAdjustedCanvasSize(const WebPMux* const mux,
- uint32_t flags,
int* const width, int* const height) {
WebPMuxImage* wpi = NULL;
assert(mux != NULL);
@@ -452,12 +433,10 @@ static WebPMuxError GetAdjustedCanvasSize(const WebPMux* const mux,
assert(wpi->img_ != NULL);
if (wpi->next_ != NULL) {
- int max_x = 0;
- int max_y = 0;
- int64_t image_area = 0;
+ int max_x = 0, max_y = 0;
// if we have a chain of wpi's, header_ is necessarily set
assert(wpi->header_ != NULL);
- // Aggregate the bounding box for animation frames & fragmented images.
+ // Aggregate the bounding box for animation frames.
for (; wpi != NULL; wpi = wpi->next_) {
int x_offset = 0, y_offset = 0, duration = 0, w = 0, h = 0;
const WebPMuxError err = GetImageInfo(wpi, &x_offset, &y_offset,
@@ -470,19 +449,9 @@ static WebPMuxError GetAdjustedCanvasSize(const WebPMux* const mux,
if (max_x_pos > max_x) max_x = max_x_pos;
if (max_y_pos > max_y) max_y = max_y_pos;
- image_area += w * h;
}
*width = max_x;
*height = max_y;
- // Crude check to validate that there are no image overlaps/holes for
- // fragmented images. Check that the aggregated image area for individual
- // fragments exactly matches the image area of the constructed canvas.
- // However, the area-match is necessary but not sufficient condition.
- if ((flags & FRAGMENTS_FLAG) && (image_area != (max_x * max_y))) {
- *width = 0;
- *height = 0;
- return WEBP_MUX_INVALID_ARGUMENT;
- }
} else {
// For a single image, canvas dimensions are same as image dimensions.
*width = wpi->width_;
@@ -528,10 +497,7 @@ static WebPMuxError CreateVP8XChunk(WebPMux* const mux) {
flags |= XMP_FLAG;
}
if (images->header_ != NULL) {
- if (images->header_->tag_ == kChunks[IDX_FRGM].tag) {
- // This is a fragmented image.
- flags |= FRAGMENTS_FLAG;
- } else if (images->header_->tag_ == kChunks[IDX_ANMF].tag) {
+ if (images->header_->tag_ == kChunks[IDX_ANMF].tag) {
// This is an image with animation.
flags |= ANIMATION_FLAG;
}
@@ -540,7 +506,7 @@ static WebPMuxError CreateVP8XChunk(WebPMux* const mux) {
flags |= ALPHA_FLAG; // Some images have an alpha channel.
}
- err = GetAdjustedCanvasSize(mux, flags, &width, &height);
+ err = GetAdjustedCanvasSize(mux, &width, &height);
if (err != WEBP_MUX_OK) return err;
if (width <= 0 || height <= 0) {
@@ -580,31 +546,26 @@ static WebPMuxError CreateVP8XChunk(WebPMux* const mux) {
// Cleans up 'mux' by removing any unnecessary chunks.
static WebPMuxError MuxCleanup(WebPMux* const mux) {
int num_frames;
- int num_fragments;
int num_anim_chunks;
- // If we have an image with a single fragment or frame, and its rectangle
- // covers the whole canvas, convert it to a non-animated non-fragmented image
- // (to avoid writing FRGM/ANMF chunk unnecessarily).
+ // If we have an image with a single frame, and its rectangle
+ // covers the whole canvas, convert it to a non-animated image
+ // (to avoid writing ANMF chunk unnecessarily).
WebPMuxError err = WebPMuxNumChunks(mux, kChunks[IDX_ANMF].id, &num_frames);
if (err != WEBP_MUX_OK) return err;
- err = WebPMuxNumChunks(mux, kChunks[IDX_FRGM].id, &num_fragments);
- if (err != WEBP_MUX_OK) return err;
- if (num_frames == 1 || num_fragments == 1) {
- WebPMuxImage* frame_frag;
- err = MuxImageGetNth((const WebPMuxImage**)&mux->images_, 1, &frame_frag);
- assert(err == WEBP_MUX_OK); // We know that one frame/fragment does exist.
- assert(frame_frag != NULL);
- if (frame_frag->header_ != NULL &&
+ if (num_frames == 1) {
+ WebPMuxImage* frame = NULL;
+ err = MuxImageGetNth((const WebPMuxImage**)&mux->images_, 1, &frame);
+ assert(err == WEBP_MUX_OK); // We know that one frame does exist.
+ assert(frame != NULL);
+ if (frame->header_ != NULL &&
((mux->canvas_width_ == 0 && mux->canvas_height_ == 0) ||
- (frame_frag->width_ == mux->canvas_width_ &&
- frame_frag->height_ == mux->canvas_height_))) {
- assert(frame_frag->header_->tag_ == kChunks[IDX_ANMF].tag ||
- frame_frag->header_->tag_ == kChunks[IDX_FRGM].tag);
- ChunkDelete(frame_frag->header_); // Removes ANMF/FRGM chunk.
- frame_frag->header_ = NULL;
+ (frame->width_ == mux->canvas_width_ &&
+ frame->height_ == mux->canvas_height_))) {
+ assert(frame->header_->tag_ == kChunks[IDX_ANMF].tag);
+ ChunkDelete(frame->header_); // Removes ANMF chunk.
+ frame->header_ = NULL;
num_frames = 0;
- num_fragments = 0;
}
}
// Remove ANIM chunk if this is a non-animated image.
diff --git a/thirdparty/libwebp/mux/muxi.h b/thirdparty/libwebp/mux/muxi.h
index b4865fe36f..e6606aa5d1 100644
--- a/thirdparty/libwebp/mux/muxi.h
+++ b/thirdparty/libwebp/mux/muxi.h
@@ -15,8 +15,8 @@
#define WEBP_MUX_MUXI_H_
#include <stdlib.h>
-#include "../dec/vp8i.h"
-#include "../dec/vp8li.h"
+#include "../dec/vp8i_dec.h"
+#include "../dec/vp8li_dec.h"
#include "../webp/mux.h"
#ifdef __cplusplus
@@ -27,8 +27,8 @@ extern "C" {
// Defines and constants.
#define MUX_MAJ_VERSION 0
-#define MUX_MIN_VERSION 3
-#define MUX_REV_VERSION 2
+#define MUX_MIN_VERSION 4
+#define MUX_REV_VERSION 0
// Chunk object.
typedef struct WebPChunk WebPChunk;
@@ -36,16 +36,16 @@ struct WebPChunk {
uint32_t tag_;
int owner_; // True if *data_ memory is owned internally.
// VP8X, ANIM, and other internally created chunks
- // like ANMF/FRGM are always owned.
+ // like ANMF are always owned.
WebPData data_;
WebPChunk* next_;
};
-// MuxImage object. Store a full WebP image (including ANMF/FRGM chunk, ALPH
+// MuxImage object. Store a full WebP image (including ANMF chunk, ALPH
// chunk and VP8/VP8L chunk),
typedef struct WebPMuxImage WebPMuxImage;
struct WebPMuxImage {
- WebPChunk* header_; // Corresponds to WEBP_CHUNK_ANMF/WEBP_CHUNK_FRGM.
+ WebPChunk* header_; // Corresponds to WEBP_CHUNK_ANMF.
WebPChunk* alpha_; // Corresponds to WEBP_CHUNK_ALPHA.
WebPChunk* img_; // Corresponds to WEBP_CHUNK_IMAGE.
WebPChunk* unknown_; // Corresponds to WEBP_CHUNK_UNKNOWN.
@@ -79,7 +79,6 @@ typedef enum {
IDX_ICCP,
IDX_ANIM,
IDX_ANMF,
- IDX_FRGM,
IDX_ALPHA,
IDX_VP8,
IDX_VP8L,
@@ -185,7 +184,6 @@ int MuxImageFinalize(WebPMuxImage* const wpi);
static WEBP_INLINE int IsWPI(WebPChunkId id) {
switch (id) {
case WEBP_CHUNK_ANMF:
- case WEBP_CHUNK_FRGM:
case WEBP_CHUNK_ALPHA:
case WEBP_CHUNK_IMAGE: return 1;
default: return 0;
diff --git a/thirdparty/libwebp/mux/muxinternal.c b/thirdparty/libwebp/mux/muxinternal.c
index 372c6a9674..387b57e8fe 100644
--- a/thirdparty/libwebp/mux/muxinternal.c
+++ b/thirdparty/libwebp/mux/muxinternal.c
@@ -23,7 +23,6 @@ const ChunkInfo kChunks[] = {
{ MKFOURCC('I', 'C', 'C', 'P'), WEBP_CHUNK_ICCP, UNDEFINED_CHUNK_SIZE },
{ MKFOURCC('A', 'N', 'I', 'M'), WEBP_CHUNK_ANIM, ANIM_CHUNK_SIZE },
{ MKFOURCC('A', 'N', 'M', 'F'), WEBP_CHUNK_ANMF, ANMF_CHUNK_SIZE },
- { MKFOURCC('F', 'R', 'G', 'M'), WEBP_CHUNK_FRGM, FRGM_CHUNK_SIZE },
{ MKFOURCC('A', 'L', 'P', 'H'), WEBP_CHUNK_ALPHA, UNDEFINED_CHUNK_SIZE },
{ MKFOURCC('V', 'P', '8', ' '), WEBP_CHUNK_IMAGE, UNDEFINED_CHUNK_SIZE },
{ MKFOURCC('V', 'P', '8', 'L'), WEBP_CHUNK_IMAGE, UNDEFINED_CHUNK_SIZE },
@@ -251,8 +250,7 @@ static WebPChunk** GetChunkListFromId(const WebPMuxImage* const wpi,
WebPChunkId id) {
assert(wpi != NULL);
switch (id) {
- case WEBP_CHUNK_ANMF:
- case WEBP_CHUNK_FRGM: return (WebPChunk**)&wpi->header_;
+ case WEBP_CHUNK_ANMF: return (WebPChunk**)&wpi->header_;
case WEBP_CHUNK_ALPHA: return (WebPChunk**)&wpi->alpha_;
case WEBP_CHUNK_IMAGE: return (WebPChunk**)&wpi->img_;
default: return NULL;
@@ -372,13 +370,12 @@ size_t MuxImageDiskSize(const WebPMuxImage* const wpi) {
return size;
}
-// Special case as ANMF/FRGM chunk encapsulates other image chunks.
+// Special case as ANMF chunk encapsulates other image chunks.
static uint8_t* ChunkEmitSpecial(const WebPChunk* const header,
size_t total_size, uint8_t* dst) {
const size_t header_size = header->data_.size;
const size_t offset_to_next = total_size - CHUNK_HEADER_SIZE;
- assert(header->tag_ == kChunks[IDX_ANMF].tag ||
- header->tag_ == kChunks[IDX_FRGM].tag);
+ assert(header->tag_ == kChunks[IDX_ANMF].tag);
PutLE32(dst + 0, header->tag_);
PutLE32(dst + TAG_SIZE, (uint32_t)offset_to_next);
assert(header_size == (uint32_t)header_size);
@@ -391,7 +388,7 @@ static uint8_t* ChunkEmitSpecial(const WebPChunk* const header,
uint8_t* MuxImageEmit(const WebPMuxImage* const wpi, uint8_t* dst) {
// Ordering of chunks to be emitted is strictly as follows:
- // 1. ANMF/FRGM chunk (if present).
+ // 1. ANMF chunk (if present).
// 2. ALPH chunk (if present).
// 3. VP8/VP8L chunk.
assert(wpi);
@@ -465,7 +462,6 @@ WebPMuxError MuxValidate(const WebPMux* const mux) {
int num_xmp;
int num_anim;
int num_frames;
- int num_fragments;
int num_vp8x;
int num_images;
int num_alpha;
@@ -510,10 +506,6 @@ WebPMuxError MuxValidate(const WebPMux* const mux) {
}
}
- // Fragmentation: FRAGMENTS_FLAG and FRGM chunk(s) are consistent.
- err = ValidateChunk(mux, IDX_FRGM, FRAGMENTS_FLAG, flags, -1, &num_fragments);
- if (err != WEBP_MUX_OK) return err;
-
// Verify either VP8X chunk is present OR there is only one elem in
// mux->images_.
err = ValidateChunk(mux, IDX_VP8X, NO_FLAG, flags, 1, &num_vp8x);
@@ -537,11 +529,6 @@ WebPMuxError MuxValidate(const WebPMux* const mux) {
if (flags & ALPHA_FLAG) return WEBP_MUX_INVALID_ARGUMENT;
}
- // num_fragments & num_images are consistent.
- if (num_fragments > 0 && num_images != num_fragments) {
- return WEBP_MUX_INVALID_ARGUMENT;
- }
-
return WEBP_MUX_OK;
}
diff --git a/thirdparty/libwebp/mux/muxread.c b/thirdparty/libwebp/mux/muxread.c
index 8957a1e46e..410acd9119 100644
--- a/thirdparty/libwebp/mux/muxread.c
+++ b/thirdparty/libwebp/mux/muxread.c
@@ -104,17 +104,15 @@ static int MuxImageParse(const WebPChunk* const chunk, int copy_data,
size_t subchunk_size;
ChunkInit(&subchunk);
- assert(chunk->tag_ == kChunks[IDX_ANMF].tag ||
- chunk->tag_ == kChunks[IDX_FRGM].tag);
+ assert(chunk->tag_ == kChunks[IDX_ANMF].tag);
assert(!wpi->is_partial_);
- // ANMF/FRGM.
+ // ANMF.
{
- const size_t hdr_size = (chunk->tag_ == kChunks[IDX_ANMF].tag) ?
- ANMF_CHUNK_SIZE : FRGM_CHUNK_SIZE;
+ const size_t hdr_size = ANMF_CHUNK_SIZE;
const WebPData temp = { bytes, hdr_size };
- // Each of ANMF and FRGM chunk contain a header at the beginning. So, its
- // size should at least be 'hdr_size'.
+ // Each of ANMF chunk contain a header at the beginning. So, its size should
+ // be at least 'hdr_size'.
if (size < hdr_size) goto Fail;
ChunkAssignData(&subchunk, &temp, copy_data, chunk->tag_);
}
@@ -292,16 +290,15 @@ WebPMux* WebPMuxCreateInternal(const WebPData* bitstream, int copy_data,
static WebPMuxError ValidateForSingleImage(const WebPMux* const mux) {
const int num_images = MuxImageCount(mux->images_, WEBP_CHUNK_IMAGE);
const int num_frames = MuxImageCount(mux->images_, WEBP_CHUNK_ANMF);
- const int num_fragments = MuxImageCount(mux->images_, WEBP_CHUNK_FRGM);
if (num_images == 0) {
// No images in mux.
return WEBP_MUX_NOT_FOUND;
- } else if (num_images == 1 && num_frames == 0 && num_fragments == 0) {
+ } else if (num_images == 1 && num_frames == 0) {
// Valid case (single image).
return WEBP_MUX_OK;
} else {
- // Frame/Fragment case OR an invalid mux.
+ // Frame case OR an invalid mux.
return WEBP_MUX_INVALID_ARGUMENT;
}
}
@@ -379,7 +376,7 @@ static WebPMuxError SynthesizeBitstream(const WebPMuxImage* const wpi,
const int need_vp8x = (wpi->alpha_ != NULL);
const size_t vp8x_size = need_vp8x ? CHUNK_HEADER_SIZE + VP8X_CHUNK_SIZE : 0;
const size_t alpha_size = need_vp8x ? ChunkDiskSize(wpi->alpha_) : 0;
- // Note: No need to output ANMF/FRGM chunk for a single image.
+ // Note: No need to output ANMF chunk for a single image.
const size_t size = RIFF_HEADER_SIZE + vp8x_size + alpha_size +
ChunkDiskSize(wpi->img_);
uint8_t* const data = (uint8_t*)WebPSafeMalloc(1ULL, size);
@@ -436,29 +433,24 @@ static WebPMuxError MuxGetImageInternal(const WebPMuxImage* const wpi,
return SynthesizeBitstream(wpi, &info->bitstream);
}
-static WebPMuxError MuxGetFrameFragmentInternal(const WebPMuxImage* const wpi,
- WebPMuxFrameInfo* const frame) {
+static WebPMuxError MuxGetFrameInternal(const WebPMuxImage* const wpi,
+ WebPMuxFrameInfo* const frame) {
const int is_frame = (wpi->header_->tag_ == kChunks[IDX_ANMF].tag);
- const CHUNK_INDEX idx = is_frame ? IDX_ANMF : IDX_FRGM;
- const WebPData* frame_frgm_data;
+ const WebPData* frame_data;
if (!is_frame) return WEBP_MUX_INVALID_ARGUMENT;
assert(wpi->header_ != NULL); // Already checked by WebPMuxGetFrame().
- // Get frame/fragment chunk.
- frame_frgm_data = &wpi->header_->data_;
- if (frame_frgm_data->size < kChunks[idx].size) return WEBP_MUX_BAD_DATA;
+ // Get frame chunk.
+ frame_data = &wpi->header_->data_;
+ if (frame_data->size < kChunks[IDX_ANMF].size) return WEBP_MUX_BAD_DATA;
// Extract info.
- frame->x_offset = 2 * GetLE24(frame_frgm_data->bytes + 0);
- frame->y_offset = 2 * GetLE24(frame_frgm_data->bytes + 3);
- if (is_frame) {
- const uint8_t bits = frame_frgm_data->bytes[15];
- frame->duration = GetLE24(frame_frgm_data->bytes + 12);
+ frame->x_offset = 2 * GetLE24(frame_data->bytes + 0);
+ frame->y_offset = 2 * GetLE24(frame_data->bytes + 3);
+ {
+ const uint8_t bits = frame_data->bytes[15];
+ frame->duration = GetLE24(frame_data->bytes + 12);
frame->dispose_method =
(bits & 1) ? WEBP_MUX_DISPOSE_BACKGROUND : WEBP_MUX_DISPOSE_NONE;
frame->blend_method = (bits & 2) ? WEBP_MUX_NO_BLEND : WEBP_MUX_BLEND;
- } else { // Defaults for unused values.
- frame->duration = 1;
- frame->dispose_method = WEBP_MUX_DISPOSE_NONE;
- frame->blend_method = WEBP_MUX_BLEND;
}
frame->id = ChunkGetIdFromTag(wpi->header_->tag_);
return SynthesizeBitstream(wpi, &frame->bitstream);
@@ -482,7 +474,7 @@ WebPMuxError WebPMuxGetFrame(
if (wpi->header_ == NULL) {
return MuxGetImageInternal(wpi, frame);
} else {
- return MuxGetFrameFragmentInternal(wpi, frame);
+ return MuxGetFrameInternal(wpi, frame);
}
}