mirror of
https://github.com/webmproject/libwebp.git
synced 2025-07-18 14:59:48 +02:00
lossy decoding: correct alpha-rescaling for YUVA format
The luminance needs to be pre- and post- multiplied by the alpha value in case of rescaling, for proper averaging. Also: - removed util/alpha_processing and moved it to dsp/ - removed WebPInitPremultiply() which was mostly useless and merged it with the new function WebPInitAlphaProcessing() Change-Id: If089cefd4ec53f6880a791c476fb1c7f7c5a8e60
This commit is contained in:
36
src/dec/io.c
36
src/dec/io.c
@ -280,7 +280,17 @@ static int Rescale(const uint8_t* src, int src_stride,
|
||||
static int EmitRescaledYUV(const VP8Io* const io, WebPDecParams* const p) {
|
||||
const int mb_h = io->mb_h;
|
||||
const int uv_mb_h = (mb_h + 1) >> 1;
|
||||
const int num_lines_out = Rescale(io->y, io->y_stride, mb_h, &p->scaler_y);
|
||||
WebPRescaler* const scaler = &p->scaler_y;
|
||||
int num_lines_out = 0;
|
||||
if (WebPIsAlphaMode(p->output->colorspace) && io->a != NULL) {
|
||||
// Before rescaling, we premultiply the luma directly into the io->y
|
||||
// internal buffer. This is OK since these samples are not used for
|
||||
// intra-prediction (the top samples are saved in cache_y_/u_/v_).
|
||||
// But we need to cast the const away, though.
|
||||
WebPMultRows((uint8_t*)io->y, io->y_stride,
|
||||
io->a, io->width, io->mb_w, mb_h, 0);
|
||||
}
|
||||
num_lines_out = Rescale(io->y, io->y_stride, mb_h, scaler);
|
||||
Rescale(io->u, io->uv_stride, uv_mb_h, &p->scaler_u);
|
||||
Rescale(io->v, io->uv_stride, uv_mb_h, &p->scaler_v);
|
||||
return num_lines_out;
|
||||
@ -288,7 +298,14 @@ static int EmitRescaledYUV(const VP8Io* const io, WebPDecParams* const p) {
|
||||
|
||||
static int EmitRescaledAlphaYUV(const VP8Io* const io, WebPDecParams* const p) {
|
||||
if (io->a != NULL) {
|
||||
Rescale(io->a, io->width, io->mb_h, &p->scaler_a);
|
||||
const WebPYUVABuffer* const buf = &p->output->u.YUVA;
|
||||
uint8_t* dst_y = buf->y + p->last_y * buf->y_stride;
|
||||
const uint8_t* src_a = buf->a + p->last_y * buf->a_stride;
|
||||
const int num_lines_out = Rescale(io->a, io->width, io->mb_h, &p->scaler_a);
|
||||
if (num_lines_out > 0) { // unmultiply the Y
|
||||
WebPMultRows(dst_y, buf->y_stride, src_a, buf->a_stride,
|
||||
p->scaler_a.dst_width, num_lines_out, 1);
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
@ -307,11 +324,11 @@ static int InitYUVRescaler(const VP8Io* const io, WebPDecParams* const p) {
|
||||
size_t tmp_size;
|
||||
int32_t* work;
|
||||
|
||||
tmp_size = work_size + 2 * uv_work_size;
|
||||
tmp_size = (work_size + 2 * uv_work_size) * sizeof(*work);
|
||||
if (has_alpha) {
|
||||
tmp_size += work_size;
|
||||
tmp_size += work_size * sizeof(*work);
|
||||
}
|
||||
p->memory = WebPSafeCalloc(1ULL, tmp_size * sizeof(*work));
|
||||
p->memory = WebPSafeCalloc(1ULL, tmp_size);
|
||||
if (p->memory == NULL) {
|
||||
return 0; // memory error
|
||||
}
|
||||
@ -338,6 +355,7 @@ static int InitYUVRescaler(const VP8Io* const io, WebPDecParams* const p) {
|
||||
io->mb_w, out_width, io->mb_h, out_height,
|
||||
work + work_size + 2 * uv_work_size);
|
||||
p->emit_alpha = EmitRescaledAlphaYUV;
|
||||
WebPInitAlphaProcessing();
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
@ -520,6 +538,7 @@ static int InitRGBRescaler(const VP8Io* const io, WebPDecParams* const p) {
|
||||
} else {
|
||||
p->emit_alpha_row = ExportAlpha;
|
||||
}
|
||||
WebPInitAlphaProcessing();
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
@ -540,7 +559,9 @@ static int CustomSetup(VP8Io* io) {
|
||||
if (!WebPIoInitFromOptions(p->options, io, is_alpha ? MODE_YUV : MODE_YUVA)) {
|
||||
return 0;
|
||||
}
|
||||
if (is_alpha && WebPIsPremultipliedMode(colorspace)) WebPInitPremultiply();
|
||||
if (is_alpha && WebPIsPremultipliedMode(colorspace)) {
|
||||
WebPInitUpsamplers();
|
||||
}
|
||||
if (io->use_scaling) {
|
||||
const int ok = is_rgb ? InitRGBRescaler(io, p) : InitYUVRescaler(io, p);
|
||||
if (!ok) {
|
||||
@ -574,6 +595,9 @@ static int CustomSetup(VP8Io* io) {
|
||||
EmitAlphaRGBA4444
|
||||
: is_rgb ? EmitAlphaRGB
|
||||
: EmitAlphaYUV;
|
||||
if (is_rgb) {
|
||||
WebPInitAlphaProcessing();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -16,9 +16,9 @@
|
||||
|
||||
#include "./alphai.h"
|
||||
#include "./vp8li.h"
|
||||
#include "../dsp/dsp.h"
|
||||
#include "../dsp/lossless.h"
|
||||
#include "../dsp/yuv.h"
|
||||
#include "../utils/alpha_processing.h"
|
||||
#include "../utils/huffman.h"
|
||||
#include "../utils/utils.h"
|
||||
|
||||
@ -412,6 +412,7 @@ static int AllocateAndInitRescaler(VP8LDecoder* const dec, VP8Io* const io) {
|
||||
WebPRescalerInit(dec->rescaler, in_width, in_height, (uint8_t*)scaled_data,
|
||||
out_width, out_height, 0, num_channels,
|
||||
in_width, out_width, in_height, out_height, work);
|
||||
WebPInitAlphaProcessing(); // needed for pre/post multiply with alpha
|
||||
return 1;
|
||||
}
|
||||
|
||||
@ -474,6 +475,7 @@ static int EmitRows(WEBP_CSP_MODE colorspace,
|
||||
//------------------------------------------------------------------------------
|
||||
// Export to YUVA
|
||||
|
||||
// TODO(skal): should be in yuv.c
|
||||
static void ConvertToYUVA(const uint32_t* const src, int width, int y_pos,
|
||||
const WebPDecBuffer* const output) {
|
||||
const WebPYUVABuffer* const buf = &output->u.YUVA;
|
||||
|
Reference in New Issue
Block a user