mirror of
https://github.com/webmproject/libwebp.git
synced 2024-12-27 06:08:21 +01:00
WebPAnimEncoder: FlattenSimilarPixels(): look for similar
not exactly same. Based on lossy WebP quality setting, ignore minor differences when flattening similar blocks. For 6k set, at default quality with '-min_size' option, improves compression by 0.3% Change-Id: Ifcb64219f941e869eb2643e231220b278aad4cd4
This commit is contained in:
parent
238cdcdbe1
commit
31f2b8d8e1
@ -596,7 +596,7 @@ static uint32_t RectArea(const FrameRect* const rect) {
|
|||||||
return (uint32_t)rect->width_ * rect->height_;
|
return (uint32_t)rect->width_ * rect->height_;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int IsBlendingPossible(const WebPPicture* const src,
|
static int IsLosslessBlendingPossible(const WebPPicture* const src,
|
||||||
const WebPPicture* const dst,
|
const WebPPicture* const dst,
|
||||||
const FrameRect* const rect) {
|
const FrameRect* const rect) {
|
||||||
int i, j;
|
int i, j;
|
||||||
@ -618,6 +618,31 @@ static int IsBlendingPossible(const WebPPicture* const src,
|
|||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int IsLossyBlendingPossible(const WebPPicture* const src,
|
||||||
|
const WebPPicture* const dst,
|
||||||
|
const FrameRect* const rect,
|
||||||
|
float quality) {
|
||||||
|
const int max_allowed_diff_lossy = QualityToMaxDiff(quality);
|
||||||
|
int i, j;
|
||||||
|
assert(src->width == dst->width && src->height == dst->height);
|
||||||
|
assert(rect->x_offset_ + rect->width_ <= dst->width);
|
||||||
|
assert(rect->y_offset_ + rect->height_ <= dst->height);
|
||||||
|
for (j = rect->y_offset_; j < rect->y_offset_ + rect->height_; ++j) {
|
||||||
|
for (i = rect->x_offset_; i < rect->x_offset_ + rect->width_; ++i) {
|
||||||
|
const uint32_t src_pixel = src->argb[j * src->argb_stride + i];
|
||||||
|
const uint32_t dst_pixel = dst->argb[j * dst->argb_stride + i];
|
||||||
|
const uint32_t dst_alpha = dst_pixel >> 24;
|
||||||
|
if (dst_alpha != 0xff &&
|
||||||
|
!PixelsAreSimilar(src_pixel, dst_pixel, max_allowed_diff_lossy)) {
|
||||||
|
// In this case, if we use blending, we can't attain the desired
|
||||||
|
// 'dst_pixel' value for this pixel. So, blending is not possible.
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
#define MIN_COLORS_LOSSY 31 // Don't try lossy below this threshold.
|
#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_COLORS_LOSSLESS 194 // Don't try lossless above this threshold.
|
||||||
#define MAX_COLOR_COUNT 256 // Power of 2 greater than MAX_COLORS_LOSSLESS.
|
#define MAX_COLOR_COUNT 256 // Power of 2 greater than MAX_COLORS_LOSSLESS.
|
||||||
@ -696,9 +721,12 @@ static void IncreaseTransparency(const WebPPicture* const src,
|
|||||||
|
|
||||||
// Replace similar blocks of pixels by a 'see-through' transparent block
|
// Replace similar blocks of pixels by a 'see-through' transparent block
|
||||||
// with uniform average color.
|
// with uniform average color.
|
||||||
|
// Assumes lossy compression is being used.
|
||||||
static void FlattenSimilarBlocks(const WebPPicture* const src,
|
static void FlattenSimilarBlocks(const WebPPicture* const src,
|
||||||
const FrameRect* const rect,
|
const FrameRect* const rect,
|
||||||
WebPPicture* const dst) {
|
WebPPicture* const dst,
|
||||||
|
float quality) {
|
||||||
|
const int max_allowed_diff_lossy = QualityToMaxDiff(quality);
|
||||||
int i, j;
|
int i, j;
|
||||||
const int block_size = 8;
|
const int block_size = 8;
|
||||||
const int y_start = (rect->y_offset_ + block_size) & ~(block_size - 1);
|
const int y_start = (rect->y_offset_ + block_size) & ~(block_size - 1);
|
||||||
@ -721,7 +749,8 @@ static void FlattenSimilarBlocks(const WebPPicture* const src,
|
|||||||
const uint32_t src_pixel = psrc[x + y * src->argb_stride];
|
const uint32_t src_pixel = psrc[x + y * src->argb_stride];
|
||||||
const int alpha = src_pixel >> 24;
|
const int alpha = src_pixel >> 24;
|
||||||
if (alpha == 0xff &&
|
if (alpha == 0xff &&
|
||||||
src_pixel == pdst[x + y * dst->argb_stride]) {
|
PixelsAreSimilar(src_pixel, pdst[x + y * dst->argb_stride],
|
||||||
|
max_allowed_diff_lossy)) {
|
||||||
++cnt;
|
++cnt;
|
||||||
avg_r += (src_pixel >> 16) & 0xff;
|
avg_r += (src_pixel >> 16) & 0xff;
|
||||||
avg_g += (src_pixel >> 8) & 0xff;
|
avg_g += (src_pixel >> 8) & 0xff;
|
||||||
@ -844,10 +873,11 @@ static WebPEncodingError GenerateCandidates(
|
|||||||
is_dispose_none ? &enc->prev_canvas_ : &enc->prev_canvas_disposed_;
|
is_dispose_none ? &enc->prev_canvas_ : &enc->prev_canvas_disposed_;
|
||||||
const int use_blending_ll =
|
const int use_blending_ll =
|
||||||
!is_key_frame &&
|
!is_key_frame &&
|
||||||
IsBlendingPossible(prev_canvas, curr_canvas, ¶ms->rect_ll_);
|
IsLosslessBlendingPossible(prev_canvas, curr_canvas, ¶ms->rect_ll_);
|
||||||
const int use_blending_lossy =
|
const int use_blending_lossy =
|
||||||
!is_key_frame &&
|
!is_key_frame &&
|
||||||
IsBlendingPossible(prev_canvas, curr_canvas, ¶ms->rect_lossy_);
|
IsLossyBlendingPossible(prev_canvas, curr_canvas, ¶ms->rect_lossy_,
|
||||||
|
config_lossy->quality);
|
||||||
|
|
||||||
// Pick candidates to be tried.
|
// Pick candidates to be tried.
|
||||||
if (!enc->options_.allow_mixed) {
|
if (!enc->options_.allow_mixed) {
|
||||||
@ -873,7 +903,8 @@ static WebPEncodingError GenerateCandidates(
|
|||||||
if (candidate_lossy->evaluate_) {
|
if (candidate_lossy->evaluate_) {
|
||||||
CopyCurrentCanvas(enc);
|
CopyCurrentCanvas(enc);
|
||||||
if (use_blending_lossy) {
|
if (use_blending_lossy) {
|
||||||
FlattenSimilarBlocks(prev_canvas, ¶ms->rect_lossy_, curr_canvas);
|
FlattenSimilarBlocks(prev_canvas, ¶ms->rect_lossy_, curr_canvas,
|
||||||
|
config_lossy->quality);
|
||||||
enc->curr_canvas_copy_modified_ = 1;
|
enc->curr_canvas_copy_modified_ = 1;
|
||||||
}
|
}
|
||||||
error_code =
|
error_code =
|
||||||
|
Loading…
Reference in New Issue
Block a user