mirror of
https://github.com/webmproject/libwebp.git
synced 2024-12-26 13:48:21 +01:00
Merge changes Idfa8ce83,I19adc9c4
* changes: WebPAnimEncoder: Restore original canvas between multiple encodes. Refactor GetColorPalette method.
This commit is contained in:
commit
0a27aca3f8
@ -126,54 +126,8 @@ static int AnalyzeAndCreatePalette(const WebPPicture* const pic,
|
|||||||
int low_effort,
|
int low_effort,
|
||||||
uint32_t palette[MAX_PALETTE_SIZE],
|
uint32_t palette[MAX_PALETTE_SIZE],
|
||||||
int* const palette_size) {
|
int* const palette_size) {
|
||||||
int i, x, y, key;
|
const int num_colors = WebPGetColorPalette(pic, palette);
|
||||||
int num_colors = 0;
|
if (num_colors > MAX_PALETTE_SIZE) return 0;
|
||||||
uint8_t in_use[MAX_PALETTE_SIZE * 4] = { 0 };
|
|
||||||
uint32_t colors[MAX_PALETTE_SIZE * 4];
|
|
||||||
static const uint32_t kHashMul = 0x1e35a7bd;
|
|
||||||
const uint32_t* argb = pic->argb;
|
|
||||||
const int width = pic->width;
|
|
||||||
const int height = pic->height;
|
|
||||||
uint32_t last_pix = ~argb[0]; // so we're sure that last_pix != argb[0]
|
|
||||||
|
|
||||||
for (y = 0; y < height; ++y) {
|
|
||||||
for (x = 0; x < width; ++x) {
|
|
||||||
if (argb[x] == last_pix) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
last_pix = argb[x];
|
|
||||||
key = (kHashMul * last_pix) >> PALETTE_KEY_RIGHT_SHIFT;
|
|
||||||
while (1) {
|
|
||||||
if (!in_use[key]) {
|
|
||||||
colors[key] = last_pix;
|
|
||||||
in_use[key] = 1;
|
|
||||||
++num_colors;
|
|
||||||
if (num_colors > MAX_PALETTE_SIZE) {
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
} else if (colors[key] == last_pix) {
|
|
||||||
// The color is already there.
|
|
||||||
break;
|
|
||||||
} else {
|
|
||||||
// Some other color sits there.
|
|
||||||
// Do linear conflict resolution.
|
|
||||||
++key;
|
|
||||||
key &= (MAX_PALETTE_SIZE * 4 - 1); // key mask for 1K buffer.
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
argb += pic->argb_stride;
|
|
||||||
}
|
|
||||||
|
|
||||||
// TODO(skal): could we reuse in_use[] to speed up EncodePalette()?
|
|
||||||
num_colors = 0;
|
|
||||||
for (i = 0; i < (int)(sizeof(in_use) / sizeof(in_use[0])); ++i) {
|
|
||||||
if (in_use[i]) {
|
|
||||||
palette[num_colors] = colors[i];
|
|
||||||
++num_colors;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
*palette_size = num_colors;
|
*palette_size = num_colors;
|
||||||
qsort(palette, num_colors, sizeof(*palette), PaletteCompareColorsForQsort);
|
qsort(palette, num_colors, sizeof(*palette), PaletteCompareColorsForQsort);
|
||||||
if (!low_effort && PaletteHasNonMonotonousDeltas(palette, num_colors)) {
|
if (!low_effort && PaletteHasNonMonotonousDeltas(palette, num_colors)) {
|
||||||
|
@ -190,7 +190,8 @@ int WebPAnimEncoderOptionsInitInternal(WebPAnimEncoderOptions* enc_options,
|
|||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
#define TRANSPARENT_COLOR 0x00ffffff
|
// This starting value is more fit to WebPCleanupTransparentAreaLossless().
|
||||||
|
#define TRANSPARENT_COLOR 0x00000000
|
||||||
|
|
||||||
static void ClearRectangle(WebPPicture* const picture,
|
static void ClearRectangle(WebPPicture* const picture,
|
||||||
int left, int top, int width, int height) {
|
int left, int top, int width, int height) {
|
||||||
@ -645,61 +646,6 @@ static int IsLossyBlendingPossible(const WebPPicture* const src,
|
|||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
#define MIN_COLORS_LOSSY 31 // Don't try lossy below this threshold.
|
|
||||||
#define MAX_COLORS_LOSSLESS 194 // Don't try lossless above this threshold.
|
|
||||||
#define MAX_COLOR_COUNT 256 // Power of 2 greater than MAX_COLORS_LOSSLESS.
|
|
||||||
#define HASH_SIZE (MAX_COLOR_COUNT * 4)
|
|
||||||
#define HASH_RIGHT_SHIFT 22 // 32 - log2(HASH_SIZE).
|
|
||||||
|
|
||||||
// TODO(urvang): Also used in enc/vp8l.c. Move to utils.
|
|
||||||
// If the number of colors in the 'pic' is at least MAX_COLOR_COUNT, return
|
|
||||||
// MAX_COLOR_COUNT. Otherwise, return the exact number of colors in the 'pic'.
|
|
||||||
static int GetColorCount(const WebPPicture* const pic) {
|
|
||||||
int x, y;
|
|
||||||
int num_colors = 0;
|
|
||||||
uint8_t in_use[HASH_SIZE] = { 0 };
|
|
||||||
uint32_t colors[HASH_SIZE];
|
|
||||||
static const uint32_t kHashMul = 0x1e35a7bd;
|
|
||||||
const uint32_t* argb = pic->argb;
|
|
||||||
const int width = pic->width;
|
|
||||||
const int height = pic->height;
|
|
||||||
uint32_t last_pix = ~argb[0]; // so we're sure that last_pix != argb[0]
|
|
||||||
|
|
||||||
for (y = 0; y < height; ++y) {
|
|
||||||
for (x = 0; x < width; ++x) {
|
|
||||||
int key;
|
|
||||||
if (argb[x] == last_pix) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
last_pix = argb[x];
|
|
||||||
key = (kHashMul * last_pix) >> HASH_RIGHT_SHIFT;
|
|
||||||
while (1) {
|
|
||||||
if (!in_use[key]) {
|
|
||||||
colors[key] = last_pix;
|
|
||||||
in_use[key] = 1;
|
|
||||||
++num_colors;
|
|
||||||
if (num_colors >= MAX_COLOR_COUNT) {
|
|
||||||
return MAX_COLOR_COUNT; // Exact count not needed.
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
} else if (colors[key] == last_pix) {
|
|
||||||
break; // The color is already there.
|
|
||||||
} else {
|
|
||||||
// Some other color sits here, so do linear conflict resolution.
|
|
||||||
++key;
|
|
||||||
key &= (HASH_SIZE - 1); // Key mask.
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
argb += pic->argb_stride;
|
|
||||||
}
|
|
||||||
return num_colors;
|
|
||||||
}
|
|
||||||
|
|
||||||
#undef MAX_COLOR_COUNT
|
|
||||||
#undef HASH_SIZE
|
|
||||||
#undef HASH_RIGHT_SHIFT
|
|
||||||
|
|
||||||
// For pixels in 'rect', replace those pixels in 'dst' that are same as 'src' by
|
// For pixels in 'rect', replace those pixels in 'dst' that are same as 'src' by
|
||||||
// transparent pixels.
|
// transparent pixels.
|
||||||
static void IncreaseTransparency(const WebPPicture* const src,
|
static void IncreaseTransparency(const WebPPicture* const src,
|
||||||
@ -856,6 +802,9 @@ enum {
|
|||||||
CANDIDATE_COUNT
|
CANDIDATE_COUNT
|
||||||
};
|
};
|
||||||
|
|
||||||
|
#define MIN_COLORS_LOSSY 31 // Don't try lossy below this threshold.
|
||||||
|
#define MAX_COLORS_LOSSLESS 194 // Don't try lossless above this threshold.
|
||||||
|
|
||||||
// Generates candidates for a given dispose method given pre-filled sub-frame
|
// Generates candidates for a given dispose method given pre-filled sub-frame
|
||||||
// 'params'.
|
// 'params'.
|
||||||
static WebPEncodingError GenerateCandidates(
|
static WebPEncodingError GenerateCandidates(
|
||||||
@ -890,7 +839,7 @@ static WebPEncodingError GenerateCandidates(
|
|||||||
candidate_ll->evaluate_ = is_lossless;
|
candidate_ll->evaluate_ = is_lossless;
|
||||||
candidate_lossy->evaluate_ = !is_lossless;
|
candidate_lossy->evaluate_ = !is_lossless;
|
||||||
} else { // Use a heuristic for trying lossless and/or lossy compression.
|
} else { // Use a heuristic for trying lossless and/or lossy compression.
|
||||||
const int num_colors = GetColorCount(¶ms->sub_frame_ll_);
|
const int num_colors = WebPGetColorPalette(¶ms->sub_frame_ll_, NULL);
|
||||||
candidate_ll->evaluate_ = (num_colors < MAX_COLORS_LOSSLESS);
|
candidate_ll->evaluate_ = (num_colors < MAX_COLORS_LOSSLESS);
|
||||||
candidate_lossy->evaluate_ = (num_colors >= MIN_COLORS_LOSSY);
|
candidate_lossy->evaluate_ = (num_colors >= MIN_COLORS_LOSSY);
|
||||||
}
|
}
|
||||||
@ -917,6 +866,7 @@ static WebPEncodingError GenerateCandidates(
|
|||||||
EncodeCandidate(¶ms->sub_frame_lossy_, ¶ms->rect_lossy_,
|
EncodeCandidate(¶ms->sub_frame_lossy_, ¶ms->rect_lossy_,
|
||||||
config_lossy, use_blending_lossy, candidate_lossy);
|
config_lossy, use_blending_lossy, candidate_lossy);
|
||||||
if (error_code != VP8_ENC_OK) return error_code;
|
if (error_code != VP8_ENC_OK) return error_code;
|
||||||
|
enc->curr_canvas_copy_modified_ = 1;
|
||||||
}
|
}
|
||||||
return error_code;
|
return error_code;
|
||||||
}
|
}
|
||||||
|
@ -15,6 +15,7 @@
|
|||||||
#include <string.h> // for memcpy()
|
#include <string.h> // for memcpy()
|
||||||
#include "../webp/decode.h"
|
#include "../webp/decode.h"
|
||||||
#include "../webp/encode.h"
|
#include "../webp/encode.h"
|
||||||
|
#include "../webp/format_constants.h" // for MAX_PALETTE_SIZE
|
||||||
#include "./utils.h"
|
#include "./utils.h"
|
||||||
|
|
||||||
// If PRINT_MEM_INFO is defined, extra info (like total memory used, number of
|
// If PRINT_MEM_INFO is defined, extra info (like total memory used, number of
|
||||||
@ -237,3 +238,68 @@ void WebPCopyPixels(const WebPPicture* const src, WebPPicture* const dst) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
//------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
#define MAX_COLOR_COUNT MAX_PALETTE_SIZE
|
||||||
|
#define COLOR_HASH_SIZE (MAX_COLOR_COUNT * 4)
|
||||||
|
#define COLOR_HASH_RIGHT_SHIFT 22 // 32 - log2(COLOR_HASH_SIZE).
|
||||||
|
|
||||||
|
int WebPGetColorPalette(const WebPPicture* const pic, uint32_t* const palette) {
|
||||||
|
int i;
|
||||||
|
int x, y;
|
||||||
|
int num_colors = 0;
|
||||||
|
uint8_t in_use[COLOR_HASH_SIZE] = { 0 };
|
||||||
|
uint32_t colors[COLOR_HASH_SIZE];
|
||||||
|
static const uint32_t kHashMul = 0x1e35a7bdU;
|
||||||
|
const uint32_t* argb = pic->argb;
|
||||||
|
const int width = pic->width;
|
||||||
|
const int height = pic->height;
|
||||||
|
uint32_t last_pix = ~argb[0]; // so we're sure that last_pix != argb[0]
|
||||||
|
assert(pic != NULL);
|
||||||
|
assert(pic->use_argb);
|
||||||
|
|
||||||
|
for (y = 0; y < height; ++y) {
|
||||||
|
for (x = 0; x < width; ++x) {
|
||||||
|
int key;
|
||||||
|
if (argb[x] == last_pix) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
last_pix = argb[x];
|
||||||
|
key = (kHashMul * last_pix) >> COLOR_HASH_RIGHT_SHIFT;
|
||||||
|
while (1) {
|
||||||
|
if (!in_use[key]) {
|
||||||
|
colors[key] = last_pix;
|
||||||
|
in_use[key] = 1;
|
||||||
|
++num_colors;
|
||||||
|
if (num_colors > MAX_COLOR_COUNT) {
|
||||||
|
return MAX_COLOR_COUNT + 1; // Exact count not needed.
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
} else if (colors[key] == last_pix) {
|
||||||
|
break; // The color is already there.
|
||||||
|
} else {
|
||||||
|
// Some other color sits here, so do linear conflict resolution.
|
||||||
|
++key;
|
||||||
|
key &= (COLOR_HASH_SIZE - 1); // Key mask.
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
argb += pic->argb_stride;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (palette != NULL) { // Fill the colors into palette.
|
||||||
|
num_colors = 0;
|
||||||
|
for (i = 0; i < COLOR_HASH_SIZE; ++i) {
|
||||||
|
if (in_use[i]) {
|
||||||
|
palette[num_colors] = colors[i];
|
||||||
|
++num_colors;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return num_colors;
|
||||||
|
}
|
||||||
|
|
||||||
|
#undef MAX_COLOR_COUNT
|
||||||
|
#undef COLOR_HASH_SIZE
|
||||||
|
#undef COLOR_HASH_RIGHT_SHIFT
|
||||||
|
|
||||||
|
//------------------------------------------------------------------------------
|
||||||
|
@ -160,6 +160,19 @@ WEBP_EXTERN(void) WebPCopyPlane(const uint8_t* src, int src_stride,
|
|||||||
WEBP_EXTERN(void) WebPCopyPixels(const struct WebPPicture* const src,
|
WEBP_EXTERN(void) WebPCopyPixels(const struct WebPPicture* const src,
|
||||||
struct WebPPicture* const dst);
|
struct WebPPicture* const dst);
|
||||||
|
|
||||||
|
//------------------------------------------------------------------------------
|
||||||
|
// Unique colors.
|
||||||
|
|
||||||
|
// Returns count of unique colors in 'pic', assuming pic->use_argb is true.
|
||||||
|
// If the unique color count is more than MAX_COLOR_COUNT, returns
|
||||||
|
// MAX_COLOR_COUNT+1.
|
||||||
|
// If 'palette' is not NULL and number of unique colors is less than or equal to
|
||||||
|
// MAX_COLOR_COUNT, also outputs the actual unique colors into 'palette'.
|
||||||
|
// Note: 'palette' is assumed to be an array already allocated with at least
|
||||||
|
// MAX_COLOR_COUNT elements.
|
||||||
|
WEBP_EXTERN(int) WebPGetColorPalette(const struct WebPPicture* const pic,
|
||||||
|
uint32_t* const palette);
|
||||||
|
|
||||||
//------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
|
Loading…
Reference in New Issue
Block a user