mirror of
https://github.com/webmproject/libwebp.git
synced 2024-11-19 20:08:28 +01:00
add support for ARGB -> YUVA conversion for lossless decoder
This was returning an (hard-to-explain) error before. (through WebPDecodeYUV() for instance). + rationalize the incremental API: -> add WebPINewYUVA -> deprecated WebPINewYUV -> add WebPIDecGetYUVA -> deprecated WebPIDecGetYUV + some NULL cosmetics Change-Id: I39a6bd6018a34294d898b29f6c40e2cf76f1037e
This commit is contained in:
parent
33705ca093
commit
43b0d6107a
4
README
4
README
@ -405,12 +405,12 @@ The 'idec' object must always be released (even upon an error condition) by
|
||||
calling: WebPDelete(idec).
|
||||
|
||||
To retrieve partially decoded picture samples, one must use the corresponding
|
||||
method: WebPIDecGetRGB or WebPIDecGetYUV.
|
||||
method: WebPIDecGetRGB or WebPIDecGetYUVA.
|
||||
It will return the last displayable pixel row.
|
||||
|
||||
Lastly, note that decoding can also be performed into a pre-allocated pixel
|
||||
buffer. This buffer must be passed when creating a WebPIDecoder, calling
|
||||
WebPINewRGB() or WebPINewYUV().
|
||||
WebPINewRGB() or WebPINewYUVA().
|
||||
|
||||
Please have a look at the src/webp/decode.h header for further details.
|
||||
|
||||
|
@ -567,7 +567,7 @@ WebPIDecoder* WebPIDecode(const uint8_t* data, size_t data_size,
|
||||
}
|
||||
// Create an instance of the incremental decoder
|
||||
idec = WebPINewDecoder(config ? &config->output : NULL);
|
||||
if (!idec) {
|
||||
if (idec == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
// Finish initialization
|
||||
@ -599,7 +599,7 @@ WebPIDecoder* WebPINewRGB(WEBP_CSP_MODE mode, uint8_t* output_buffer,
|
||||
WebPIDecoder* idec;
|
||||
if (mode >= MODE_YUV) return NULL;
|
||||
idec = WebPINewDecoder(NULL);
|
||||
if (!idec) return NULL;
|
||||
if (idec == NULL) return NULL;
|
||||
idec->output_.colorspace = mode;
|
||||
idec->output_.is_external_memory = 1;
|
||||
idec->output_.u.RGBA.rgba = output_buffer;
|
||||
@ -608,12 +608,13 @@ WebPIDecoder* WebPINewRGB(WEBP_CSP_MODE mode, uint8_t* output_buffer,
|
||||
return idec;
|
||||
}
|
||||
|
||||
WebPIDecoder* WebPINewYUV(uint8_t* luma, size_t luma_size, int luma_stride,
|
||||
uint8_t* u, size_t u_size, int u_stride,
|
||||
uint8_t* v, size_t v_size, int v_stride) {
|
||||
WebPIDecoder* WebPINewYUVA(uint8_t* luma, size_t luma_size, int luma_stride,
|
||||
uint8_t* u, size_t u_size, int u_stride,
|
||||
uint8_t* v, size_t v_size, int v_stride,
|
||||
uint8_t* a, size_t a_size, int a_stride) {
|
||||
WebPIDecoder* const idec = WebPINewDecoder(NULL);
|
||||
if (!idec) return NULL;
|
||||
idec->output_.colorspace = MODE_YUV;
|
||||
if (idec == NULL) return NULL;
|
||||
idec->output_.colorspace = (a == NULL) ? MODE_YUV : MODE_YUVA;
|
||||
idec->output_.is_external_memory = 1;
|
||||
idec->output_.u.YUVA.y = luma;
|
||||
idec->output_.u.YUVA.y_stride = luma_stride;
|
||||
@ -624,9 +625,21 @@ WebPIDecoder* WebPINewYUV(uint8_t* luma, size_t luma_size, int luma_stride,
|
||||
idec->output_.u.YUVA.v = v;
|
||||
idec->output_.u.YUVA.v_stride = v_stride;
|
||||
idec->output_.u.YUVA.v_size = v_size;
|
||||
idec->output_.u.YUVA.a = a;
|
||||
idec->output_.u.YUVA.a_stride = a_stride;
|
||||
idec->output_.u.YUVA.a_size = a_size;
|
||||
return idec;
|
||||
}
|
||||
|
||||
WebPIDecoder* WebPINewYUV(uint8_t* luma, size_t luma_size, int luma_stride,
|
||||
uint8_t* u, size_t u_size, int u_stride,
|
||||
uint8_t* v, size_t v_size, int v_stride) {
|
||||
return WebPINewYUVA(luma, luma_size, luma_stride,
|
||||
u, u_size, u_stride,
|
||||
v, v_size, v_stride,
|
||||
NULL, 0, 0);
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
static VP8StatusCode IDecCheckStatus(const WebPIDecoder* const idec) {
|
||||
@ -698,15 +711,15 @@ const WebPDecBuffer* WebPIDecodedArea(const WebPIDecoder* idec,
|
||||
int* left, int* top,
|
||||
int* width, int* height) {
|
||||
const WebPDecBuffer* const src = GetOutputBuffer(idec);
|
||||
if (left) *left = 0;
|
||||
if (top) *top = 0;
|
||||
if (left != NULL) *left = 0;
|
||||
if (top != NULL) *top = 0;
|
||||
// TODO(skal): later include handling of rotations.
|
||||
if (src) {
|
||||
if (width) *width = src->width;
|
||||
if (height) *height = idec->params_.last_y;
|
||||
if (width != NULL) *width = src->width;
|
||||
if (height != NULL) *height = idec->params_.last_y;
|
||||
} else {
|
||||
if (width) *width = 0;
|
||||
if (height) *height = 0;
|
||||
if (width != NULL) *width = 0;
|
||||
if (height != NULL) *height = 0;
|
||||
}
|
||||
return src;
|
||||
}
|
||||
@ -714,35 +727,38 @@ const WebPDecBuffer* WebPIDecodedArea(const WebPIDecoder* idec,
|
||||
uint8_t* WebPIDecGetRGB(const WebPIDecoder* idec, int* last_y,
|
||||
int* width, int* height, int* stride) {
|
||||
const WebPDecBuffer* const src = GetOutputBuffer(idec);
|
||||
if (!src) return NULL;
|
||||
if (src == NULL) return NULL;
|
||||
if (src->colorspace >= MODE_YUV) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (last_y) *last_y = idec->params_.last_y;
|
||||
if (width) *width = src->width;
|
||||
if (height) *height = src->height;
|
||||
if (stride) *stride = src->u.RGBA.stride;
|
||||
if (last_y != NULL) *last_y = idec->params_.last_y;
|
||||
if (width != NULL) *width = src->width;
|
||||
if (height != NULL) *height = src->height;
|
||||
if (stride != NULL) *stride = src->u.RGBA.stride;
|
||||
|
||||
return src->u.RGBA.rgba;
|
||||
}
|
||||
|
||||
uint8_t* WebPIDecGetYUV(const WebPIDecoder* idec, int* last_y,
|
||||
uint8_t** u, uint8_t** v,
|
||||
int* width, int* height, int *stride, int* uv_stride) {
|
||||
uint8_t* WebPIDecGetYUVA(const WebPIDecoder* idec, int* last_y,
|
||||
uint8_t** u, uint8_t** v, uint8_t** a,
|
||||
int* width, int* height,
|
||||
int* stride, int* uv_stride, int* a_stride) {
|
||||
const WebPDecBuffer* const src = GetOutputBuffer(idec);
|
||||
if (!src) return NULL;
|
||||
if (src == NULL) return NULL;
|
||||
if (src->colorspace < MODE_YUV) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (last_y) *last_y = idec->params_.last_y;
|
||||
if (u) *u = src->u.YUVA.u;
|
||||
if (v) *v = src->u.YUVA.v;
|
||||
if (width) *width = src->width;
|
||||
if (height) *height = src->height;
|
||||
if (stride) *stride = src->u.YUVA.y_stride;
|
||||
if (uv_stride) *uv_stride = src->u.YUVA.u_stride;
|
||||
if (last_y != NULL) *last_y = idec->params_.last_y;
|
||||
if (u != NULL) *u = src->u.YUVA.u;
|
||||
if (v != NULL) *v = src->u.YUVA.v;
|
||||
if (a != NULL) *a = src->u.YUVA.a;
|
||||
if (width != NULL) *width = src->width;
|
||||
if (height != NULL) *height = src->height;
|
||||
if (stride != NULL) *stride = src->u.YUVA.y_stride;
|
||||
if (uv_stride != NULL) *uv_stride = src->u.YUVA.u_stride;
|
||||
if (a_stride != NULL) *a_stride = src->u.YUVA.a_stride;
|
||||
|
||||
return src->u.YUVA.y;
|
||||
}
|
||||
|
163
src/dec/vp8l.c
163
src/dec/vp8l.c
@ -14,6 +14,7 @@
|
||||
#include <stdlib.h>
|
||||
#include "./vp8li.h"
|
||||
#include "../dsp/lossless.h"
|
||||
#include "../dsp/yuv.h"
|
||||
#include "../utils/huffman.h"
|
||||
#include "../utils/utils.h"
|
||||
|
||||
@ -404,10 +405,12 @@ static int AllocateAndInitRescaler(VP8LDecoder* const dec, VP8Io* const io) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// Export to ARGB
|
||||
|
||||
// We have special "export" function since we need to convert from BGRA
|
||||
static int Export(VP8LDecoder* const dec, WEBP_CSP_MODE colorspace,
|
||||
static int Export(WebPRescaler* const rescaler, WEBP_CSP_MODE colorspace,
|
||||
int rgba_stride, uint8_t* const rgba) {
|
||||
WebPRescaler* const rescaler = dec->rescaler;
|
||||
const uint32_t* const src = (const uint32_t*)rescaler->dst;
|
||||
const int dst_width = rescaler->dst_width;
|
||||
int num_lines_out = 0;
|
||||
@ -421,18 +424,19 @@ static int Export(VP8LDecoder* const dec, WEBP_CSP_MODE colorspace,
|
||||
}
|
||||
|
||||
// Emit scaled rows.
|
||||
static int EmitRescaledRows(VP8LDecoder* const dec, WEBP_CSP_MODE colorspace,
|
||||
static int EmitRescaledRows(const VP8LDecoder* const dec,
|
||||
const uint32_t* const data, int in_stride, int mb_h,
|
||||
uint8_t* const out, int out_stride) {
|
||||
const WEBP_CSP_MODE colorspace = dec->output_->colorspace;
|
||||
const uint8_t* const in = (const uint8_t*)data;
|
||||
int num_lines_in = 0;
|
||||
int num_lines_out = 0;
|
||||
while (num_lines_in < mb_h) {
|
||||
const uint8_t* row_in = in + num_lines_in * in_stride;
|
||||
const uint8_t* const row_in = in + num_lines_in * in_stride;
|
||||
uint8_t* const row_out = out + num_lines_out * out_stride;
|
||||
num_lines_in += WebPRescalerImport(dec->rescaler, mb_h - num_lines_in,
|
||||
row_in, in_stride);
|
||||
num_lines_out += Export(dec, colorspace, out_stride, row_out);
|
||||
num_lines_out += Export(dec->rescaler, colorspace, out_stride, row_out);
|
||||
}
|
||||
return num_lines_out;
|
||||
}
|
||||
@ -453,6 +457,113 @@ static int EmitRows(WEBP_CSP_MODE colorspace,
|
||||
return mb_h; // Num rows out == num rows in.
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// Export to YUVA
|
||||
|
||||
static void ConvertToYUVA(const uint32_t* const src, int width, int y_pos,
|
||||
const WebPDecBuffer* const output) {
|
||||
const WebPYUVABuffer* const buf = &output->u.YUVA;
|
||||
// first, the luma plane
|
||||
{
|
||||
int i;
|
||||
uint8_t* const y = buf->y + y_pos * buf->y_stride;
|
||||
for (i = 0; i < width; ++i) {
|
||||
const uint32_t p = src[i];
|
||||
y[i] = VP8RGBToY((p >> 16) & 0xff, (p >> 8) & 0xff, (p >> 0) & 0xff);
|
||||
}
|
||||
}
|
||||
|
||||
// then U/V planes
|
||||
{
|
||||
uint8_t* const u = buf->u + (y_pos >> 1) * buf->u_stride;
|
||||
uint8_t* const v = buf->v + (y_pos >> 1) * buf->v_stride;
|
||||
const int uv_width = width >> 1;
|
||||
int i;
|
||||
for (i = 0; i < uv_width; ++i) {
|
||||
const uint32_t v0 = src[2 * i + 0];
|
||||
const uint32_t v1 = src[2 * i + 1];
|
||||
// VP8RGBToU/V expects four accumulated pixels. Hence we need to
|
||||
// scale r/g/b value by a factor 2. We just shift v0/v1 one bit less.
|
||||
const int r = ((v0 >> 15) & 0x1fe) + ((v1 >> 15) & 0x1fe);
|
||||
const int g = ((v0 >> 7) & 0x1fe) + ((v1 >> 7) & 0x1fe);
|
||||
const int b = ((v0 << 1) & 0x1fe) + ((v1 << 1) & 0x1fe);
|
||||
if (!(y_pos & 1)) { // even lines: store values
|
||||
u[i] = VP8RGBToU(r, g, b);
|
||||
v[i] = VP8RGBToV(r, g, b);
|
||||
} else { // odd lines: average with previous values
|
||||
const int tmp_u = VP8RGBToU(r, g, b);
|
||||
const int tmp_v = VP8RGBToV(r, g, b);
|
||||
// Approximated average-of-four. But it's an acceptable diff.
|
||||
u[i] = (u[i] + tmp_u + 1) >> 1;
|
||||
v[i] = (v[i] + tmp_v + 1) >> 1;
|
||||
}
|
||||
}
|
||||
if (width & 1) { // last pixel
|
||||
const uint32_t v0 = src[2 * i + 0];
|
||||
const int r = (v0 >> 14) & 0x3fc;
|
||||
const int g = (v0 >> 6) & 0x3fc;
|
||||
const int b = (v0 << 2) & 0x3fc;
|
||||
if (!(y_pos & 1)) { // even lines
|
||||
u[i] = VP8RGBToU(r, g, b);
|
||||
v[i] = VP8RGBToV(r, g, b);
|
||||
} else { // odd lines (note: we could just skip this)
|
||||
const int tmp_u = VP8RGBToU(r, g, b);
|
||||
const int tmp_v = VP8RGBToV(r, g, b);
|
||||
u[i] = (u[i] + tmp_u + 1) >> 1;
|
||||
v[i] = (v[i] + tmp_v + 1) >> 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
// Lastly, store alpha if needed.
|
||||
if (buf->a != NULL) {
|
||||
int i;
|
||||
uint8_t* const a = buf->a + y_pos * buf->a_stride;
|
||||
for (i = 0; i < width; ++i) a[i] = (src[i] >> 24);
|
||||
}
|
||||
}
|
||||
|
||||
static int ExportYUVA(const VP8LDecoder* const dec, int y_pos) {
|
||||
WebPRescaler* const rescaler = dec->rescaler;
|
||||
const uint32_t* const src = (const uint32_t*)rescaler->dst;
|
||||
const int dst_width = rescaler->dst_width;
|
||||
int num_lines_out = 0;
|
||||
while (WebPRescalerHasPendingOutput(rescaler)) {
|
||||
WebPRescalerExportRow(rescaler);
|
||||
ConvertToYUVA(src, dst_width, y_pos, dec->output_);
|
||||
++y_pos;
|
||||
++num_lines_out;
|
||||
}
|
||||
return num_lines_out;
|
||||
}
|
||||
|
||||
static int EmitRescaledRowsYUVA(const VP8LDecoder* const dec,
|
||||
const uint32_t* const data,
|
||||
int in_stride, int mb_h) {
|
||||
const uint8_t* const in = (const uint8_t*)data;
|
||||
int num_lines_in = 0;
|
||||
int y_pos = dec->last_out_row_;
|
||||
while (num_lines_in < mb_h) {
|
||||
const uint8_t* const row_in = in + num_lines_in * in_stride;
|
||||
num_lines_in += WebPRescalerImport(dec->rescaler, mb_h - num_lines_in,
|
||||
row_in, in_stride);
|
||||
y_pos += ExportYUVA(dec, y_pos);
|
||||
}
|
||||
return y_pos;
|
||||
}
|
||||
|
||||
static int EmitRowsYUVA(const VP8LDecoder* const dec,
|
||||
const uint32_t* const data, int in_stride,
|
||||
int mb_w, int num_rows) {
|
||||
int y_pos = dec->last_out_row_;
|
||||
const uint8_t* row_in = (const uint8_t*)data;
|
||||
while (num_rows-- > 0) {
|
||||
ConvertToYUVA((const uint32_t*)row_in, mb_w, y_pos, dec->output_);
|
||||
row_in += in_stride;
|
||||
++y_pos;
|
||||
}
|
||||
return y_pos;
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// Cropping.
|
||||
|
||||
@ -537,19 +648,23 @@ static void ProcessRows(VP8LDecoder* const dec, int row) {
|
||||
if (!SetCropWindow(io, dec->last_row_, row, &rows_data, io->width)) {
|
||||
// Nothing to output (this time).
|
||||
} else {
|
||||
WebPDecParams* const params = (WebPDecParams*)io->opaque;
|
||||
const WebPDecBuffer* const output = params->output;
|
||||
const WebPRGBABuffer* const buf = &output->u.RGBA;
|
||||
uint8_t* const rgba = buf->rgba + dec->last_out_row_ * buf->stride;
|
||||
const WebPDecBuffer* const output = dec->output_;
|
||||
const int in_stride = io->width * sizeof(*rows_data);
|
||||
const WEBP_CSP_MODE colorspace = output->colorspace;
|
||||
const int num_rows_out = io->use_scaling ?
|
||||
EmitRescaledRows(dec, colorspace, rows_data, in_stride, io->mb_h,
|
||||
rgba, buf->stride) :
|
||||
EmitRows(colorspace, rows_data, in_stride, io->mb_w, io->mb_h,
|
||||
rgba, buf->stride);
|
||||
// Update 'last_out_row_'.
|
||||
dec->last_out_row_ += num_rows_out;
|
||||
if (output->colorspace < MODE_YUV) { // convert to RGBA
|
||||
const WebPRGBABuffer* const buf = &output->u.RGBA;
|
||||
uint8_t* const rgba = buf->rgba + dec->last_out_row_ * buf->stride;
|
||||
const int num_rows_out = io->use_scaling ?
|
||||
EmitRescaledRows(dec, rows_data, in_stride, io->mb_h,
|
||||
rgba, buf->stride) :
|
||||
EmitRows(output->colorspace, rows_data, in_stride,
|
||||
io->mb_w, io->mb_h, rgba, buf->stride);
|
||||
// Update 'last_out_row_'.
|
||||
dec->last_out_row_ += num_rows_out;
|
||||
} else { // convert to YUVA
|
||||
dec->last_out_row_ = io->use_scaling ?
|
||||
EmitRescaledRowsYUVA(dec, rows_data, in_stride, io->mb_h) :
|
||||
EmitRowsYUVA(dec, rows_data, in_stride, io->mb_w, io->mb_h);
|
||||
}
|
||||
assert(dec->last_out_row_ <= output->height);
|
||||
}
|
||||
}
|
||||
@ -818,6 +933,8 @@ void VP8LClear(VP8LDecoder* const dec) {
|
||||
|
||||
free(dec->rescaler_memory);
|
||||
dec->rescaler_memory = NULL;
|
||||
|
||||
dec->output_ = NULL; // leave no trace behind
|
||||
}
|
||||
|
||||
void VP8LDelete(VP8LDecoder* const dec) {
|
||||
@ -950,7 +1067,7 @@ static int AllocateARGBBuffers(VP8LDecoder* const dec, int final_width) {
|
||||
assert(dec->width_ <= final_width);
|
||||
dec->argb_ = (uint32_t*)WebPSafeMalloc(total_num_pixels, sizeof(*dec->argb_));
|
||||
if (dec->argb_ == NULL) {
|
||||
dec->argb_cache_ = NULL;
|
||||
dec->argb_cache_ = NULL; // for sanity check
|
||||
dec->status_ = VP8_STATUS_OUT_OF_MEMORY;
|
||||
return 0;
|
||||
}
|
||||
@ -1052,20 +1169,16 @@ int VP8LDecodeHeader(VP8LDecoder* const dec, VP8Io* const io) {
|
||||
int VP8LDecodeImage(VP8LDecoder* const dec) {
|
||||
VP8Io* io = NULL;
|
||||
WebPDecParams* params = NULL;
|
||||
WebPDecBuffer* output = NULL;
|
||||
|
||||
// Sanity checks.
|
||||
if (dec == NULL) return 0;
|
||||
|
||||
io = dec->io_;
|
||||
assert(io != NULL);
|
||||
params = (WebPDecParams*)io->opaque;
|
||||
assert(params != NULL);
|
||||
output = params->output;
|
||||
// YUV modes are invalid.
|
||||
if (output->colorspace >= MODE_YUV) {
|
||||
dec->status_ = VP8_STATUS_INVALID_PARAM;
|
||||
goto Err;
|
||||
}
|
||||
dec->output_ = params->output;
|
||||
assert(dec->output_ != NULL);
|
||||
|
||||
// Initialization.
|
||||
if (!WebPIoInitFromOptions(params->options, io, MODE_BGRA)) {
|
||||
|
@ -61,6 +61,8 @@ typedef struct {
|
||||
VP8LDecodeState state_;
|
||||
VP8Io *io_;
|
||||
|
||||
const WebPDecBuffer *output_; // shortcut to io->opaque->output
|
||||
|
||||
uint32_t *argb_; // Internal data: always in BGRA color mode.
|
||||
uint32_t *argb_cache_; // Scratch buffer for temporary BGRA storage.
|
||||
|
||||
|
@ -233,7 +233,7 @@ typedef enum {
|
||||
//
|
||||
// // The above call decodes the current available buffer.
|
||||
// // Part of the image can now be refreshed by calling to
|
||||
// // WebPIDecGetRGB()/WebPIDecGetYUV() etc.
|
||||
// // WebPIDecGetRGB()/WebPIDecGetYUVA() etc.
|
||||
// }
|
||||
// WebPIDelete(idec);
|
||||
|
||||
@ -260,9 +260,18 @@ WEBP_EXTERN(WebPIDecoder*) WebPINewRGB(
|
||||
// will output the raw luma/chroma samples into a preallocated planes. The luma
|
||||
// plane is specified by its pointer 'luma', its size 'luma_size' and its stride
|
||||
// 'luma_stride'. Similarly, the chroma-u plane is specified by the 'u',
|
||||
// 'u_size' and 'u_stride' parameters, and the chroma-v plane by 'v', 'v_size'
|
||||
// and 'v_size'.
|
||||
// 'u_size' and 'u_stride' parameters, and the chroma-v plane by 'v'
|
||||
// and 'v_size'. And same for the alpha-plane. The 'a' pointer can be pass
|
||||
// NULL in case one is not interested in the transparency plane.
|
||||
// Returns NULL if the allocation failed.
|
||||
WEBP_EXTERN(WebPIDecoder*) WebPINewYUVA(
|
||||
uint8_t* luma, size_t luma_size, int luma_stride,
|
||||
uint8_t* u, size_t u_size, int u_stride,
|
||||
uint8_t* v, size_t v_size, int v_stride,
|
||||
uint8_t* a, size_t a_size, int a_stride);
|
||||
|
||||
// Deprecated version of the above, without the alpha plane.
|
||||
// Kept for backward compatibility.
|
||||
WEBP_EXTERN(WebPIDecoder*) WebPINewYUV(
|
||||
uint8_t* luma, size_t luma_size, int luma_stride,
|
||||
uint8_t* u, size_t u_size, int u_stride,
|
||||
@ -296,12 +305,22 @@ WEBP_EXTERN(uint8_t*) WebPIDecGetRGB(
|
||||
const WebPIDecoder* idec, int* last_y,
|
||||
int* width, int* height, int* stride);
|
||||
|
||||
// Same as above function to get YUV image. Returns pointer to the luma plane
|
||||
// or NULL in case of error.
|
||||
WEBP_EXTERN(uint8_t*) WebPIDecGetYUV(
|
||||
// Same as above function to get a YUVA image. Returns pointer to the luma
|
||||
// plane or NULL in case of error. If there is no alpha information
|
||||
// the alpha pointer '*a' will be returned NULL.
|
||||
WEBP_EXTERN(uint8_t*) WebPIDecGetYUVA(
|
||||
const WebPIDecoder* idec, int* last_y,
|
||||
uint8_t** u, uint8_t** v,
|
||||
int* width, int* height, int* stride, int* uv_stride);
|
||||
uint8_t** u, uint8_t** v, uint8_t** a,
|
||||
int* width, int* height, int* stride, int* uv_stride, int* a_stride);
|
||||
|
||||
// Deprecated alpha-less version of WebPIDecGetYUVA(): it will ignore the
|
||||
// alpha information (if present). Kept for backward compatibility.
|
||||
static WEBP_INLINE uint8_t* WebPIDecGetYUV(
|
||||
const WebPIDecoder* idec, int* last_y, uint8_t** u, uint8_t** v,
|
||||
int* width, int* height, int* stride, int* uv_stride) {
|
||||
return WebPIDecGetYUVA(idec, last_y, u, v, NULL, width, height,
|
||||
stride, uv_stride, NULL);
|
||||
}
|
||||
|
||||
// Generic call to retrieve information about the displayable area.
|
||||
// If non NULL, the left/right/width/height pointers are filled with the visible
|
||||
|
Loading…
Reference in New Issue
Block a user