aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/enc/vp8l_enc.c17
-rw-r--r--src/utils/palette.c15
-rw-r--r--src/utils/palette.h2
-rw-r--r--tests/fuzzer/advanced_api_fuzzer.cc20
4 files changed, 44 insertions, 10 deletions
diff --git a/src/enc/vp8l_enc.c b/src/enc/vp8l_enc.c
index cd045e49..41a6d34e 100644
--- a/src/enc/vp8l_enc.c
+++ b/src/enc/vp8l_enc.c
@@ -1419,17 +1419,24 @@ static WebPEncodingError EncodePalette(VP8LBitWriter* const bw, int low_effort,
uint32_t tmp_palette[MAX_PALETTE_SIZE];
const int palette_size = enc->palette_size_;
const uint32_t* const palette = enc->palette_;
+ // If the last element is 0, do not store it and count on automatic palette
+ // 0-filling. This can only happen if there is no pixel packing, hence if
+ // there are strictly more than 16 colors (after 0 is removed).
+ const uint32_t encoded_palette_size =
+ (enc->palette_[palette_size - 1] == 0 && palette_size > 17)
+ ? palette_size - 1
+ : palette_size;
VP8LPutBits(bw, TRANSFORM_PRESENT, 1);
VP8LPutBits(bw, COLOR_INDEXING_TRANSFORM, 2);
assert(palette_size >= 1 && palette_size <= MAX_PALETTE_SIZE);
- VP8LPutBits(bw, palette_size - 1, 8);
- for (i = palette_size - 1; i >= 1; --i) {
+ VP8LPutBits(bw, encoded_palette_size - 1, 8);
+ for (i = encoded_palette_size - 1; i >= 1; --i) {
tmp_palette[i] = VP8LSubPixels(palette[i], palette[i - 1]);
}
tmp_palette[0] = palette[0];
- return EncodeImageNoHuffman(bw, tmp_palette, &enc->hash_chain_,
- &enc->refs_[0], palette_size, 1, /*quality=*/20,
- low_effort, enc->pic_, percent_range, percent);
+ return EncodeImageNoHuffman(
+ bw, tmp_palette, &enc->hash_chain_, &enc->refs_[0], encoded_palette_size,
+ 1, /*quality=*/20, low_effort, enc->pic_, percent_range, percent);
}
// -----------------------------------------------------------------------------
diff --git a/src/utils/palette.c b/src/utils/palette.c
index 515da210..8ae0a5cd 100644
--- a/src/utils/palette.c
+++ b/src/utils/palette.c
@@ -191,6 +191,12 @@ static void PaletteSortMinimizeDeltas(const uint32_t* const palette_sorted,
// Find greedily always the closest color of the predicted color to minimize
// deltas in the palette. This reduces storage needs since the
// palette is stored with delta encoding.
+ if (num_colors > 17) {
+ if (palette[0] == 0) {
+ --num_colors;
+ SwapColor(&palette[num_colors], &palette[0]);
+ }
+ }
for (i = 0; i < num_colors; ++i) {
int best_ix = i;
uint32_t best_score = ~0U;
@@ -384,8 +390,13 @@ int PaletteSort(PaletteSorting method, const struct WebPPicture* const pic,
uint32_t* const palette) {
switch (method) {
case kSortedDefault:
- // Nothing to do, we have already sorted the palette.
- memcpy(palette, palette_sorted, num_colors * sizeof(*palette));
+ if (palette_sorted[0] == 0 && num_colors > 17) {
+ memcpy(palette, palette_sorted + 1,
+ (num_colors - 1) * sizeof(*palette_sorted));
+ palette[num_colors - 1] = 0;
+ } else {
+ memcpy(palette, palette_sorted, num_colors * sizeof(*palette));
+ }
return 1;
case kMinimizeDelta:
PaletteSortMinimizeDeltas(palette_sorted, num_colors, palette);
diff --git a/src/utils/palette.h b/src/utils/palette.h
index 34479e46..417c61fa 100644
--- a/src/utils/palette.h
+++ b/src/utils/palette.h
@@ -53,6 +53,8 @@ int GetColorPalette(const struct WebPPicture* const pic,
// Sorts the palette according to the criterion defined by 'method'.
// 'palette_sorted' is the input palette sorted lexicographically, as done in
// PrepareMapToPalette. Returns 0 on memory allocation error.
+// For kSortedDefault and kMinimizeDelta methods, 0 (if present) is set as the
+// last element to optimize later storage.
int PaletteSort(PaletteSorting method, const struct WebPPicture* const pic,
const uint32_t* const palette_sorted, uint32_t num_colors,
uint32_t* const palette);
diff --git a/tests/fuzzer/advanced_api_fuzzer.cc b/tests/fuzzer/advanced_api_fuzzer.cc
index 5d24af81..a4f8045a 100644
--- a/tests/fuzzer/advanced_api_fuzzer.cc
+++ b/tests/fuzzer/advanced_api_fuzzer.cc
@@ -20,6 +20,7 @@
#include <string_view>
#include "./fuzz_utils.h"
+#include "src/dec/webpi_dec.h"
#include "src/utils/rescaler_utils.h"
#include "src/webp/decode.h"
@@ -80,11 +81,24 @@ void AdvancedApiTest(std::string_view blob, uint8_t factor_u8, bool flip,
// Skip easily avoidable out-of-memory fuzzing errors.
if (config.options.use_scaling) {
+ int input_width = config.input.width;
+ int input_height = config.input.height;
+ if (config.options.use_cropping) {
+ const int cw = config.options.crop_width;
+ const int ch = config.options.crop_height;
+ const int x = config.options.crop_left & ~1;
+ const int y = config.options.crop_top & ~1;
+ if (WebPCheckCropDimensions(input_width, input_height, x, y, cw,
+ ch)) {
+ input_width = cw;
+ input_height = ch;
+ }
+ }
+
int scaled_width = config.options.scaled_width;
int scaled_height = config.options.scaled_height;
- if (WebPRescalerGetScaledDimensions(config.input.width,
- config.input.height, &scaled_width,
- &scaled_height)) {
+ if (WebPRescalerGetScaledDimensions(input_width, input_height,
+ &scaled_width, &scaled_height)) {
size_t fuzz_px_limit = fuzz_utils::kFuzzPxLimit;
if (scaled_width != config.input.width ||
scaled_height != config.input.height) {