Pass stride parameter to WebPDequantizeLevels()

and also pass 'VP8Io* io' extra param to VP8DecompressAlphaRows()

This is somehow in preparation for some memory optimizations in
the 'cropping' case. For now, only the easy crop_bottom case is
optimized.

Change-Id: Ib54531ba057bf62b98422dbb6c181dda626c72c2
This commit is contained in:
Pascal Massimino 2016-03-18 15:36:58 +01:00
parent e88c4ca013
commit 64eed38779
5 changed files with 23 additions and 14 deletions

View File

@ -120,16 +120,18 @@ static int ALPHDecode(VP8Decoder* const dec, int row, int num_rows) {
// Main entry point.
const uint8_t* VP8DecompressAlphaRows(VP8Decoder* const dec,
const VP8Io* const io,
int row, int num_rows) {
const int width = dec->pic_hdr_.width_;
const int height = dec->pic_hdr_.height_;
assert(dec != NULL && io != NULL);
if (row < 0 || num_rows <= 0 || row + num_rows > height) {
return NULL; // sanity check.
}
if (row == 0) {
// Initialize decoding.
if (dec->alph_dec_ == NULL) { // Initialize decoder.
assert(dec->alpha_plane_ != NULL);
dec->alph_dec_ = ALPHNew();
if (dec->alph_dec_ == NULL) return NULL;
@ -147,12 +149,17 @@ const uint8_t* VP8DecompressAlphaRows(VP8Decoder* const dec,
}
}
if (io->use_cropping) {
if (row + num_rows > io->crop_bottom) {
num_rows = io->crop_bottom - row;
}
}
if (!dec->is_alpha_decoded_) {
int ok = 0;
int ok = ALPHDecode(dec, row, num_rows);
assert(dec->alph_dec_ != NULL);
ok = ALPHDecode(dec, row, num_rows);
if (ok && dec->alpha_dithering_ > 0) {
ok = WebPDequantizeLevels(dec->alpha_plane_, width, height,
ok = WebPDequantizeLevels(dec->alpha_plane_, width, height, width,
dec->alpha_dithering_);
}
if (!ok || dec->is_alpha_decoded_) {
@ -161,7 +168,6 @@ const uint8_t* VP8DecompressAlphaRows(VP8Decoder* const dec,
}
if (!ok) return NULL; // Error.
}
// Return a pointer to the current decoded row.
return dec->alpha_plane_ + row * width;
}

View File

@ -462,7 +462,7 @@ static int FinishRow(VP8Decoder* const dec, VP8Io* const io) {
if (dec->alpha_data_ != NULL && y_start < y_end) {
// TODO(skal): testing presence of alpha with dec->alpha_data_ is not a
// good idea.
io->a = VP8DecompressAlphaRows(dec, y_start, y_end - y_start);
io->a = VP8DecompressAlphaRows(dec, io, y_start, y_end - y_start);
if (io->a == NULL) {
return VP8SetError(dec, VP8_STATUS_BITSTREAM_ERROR,
"Could not decode alpha data.");

View File

@ -306,6 +306,7 @@ int VP8DecodeMB(VP8Decoder* const dec, VP8BitReader* const token_br);
// in alpha.c
const uint8_t* VP8DecompressAlphaRows(VP8Decoder* const dec,
const VP8Io* const io,
int row, int num_rows);
//------------------------------------------------------------------------------

View File

@ -44,6 +44,7 @@ static const uint8_t kOrderedDither[DSIZE][DSIZE] = {
typedef struct {
int width_, height_; // dimension
int stride_; // stride in bytes
int row_; // current input row being processed
uint8_t* src_; // input pointer
uint8_t* dst_; // output pointer
@ -99,7 +100,7 @@ static void VFilter(SmoothParams* const p) {
// We replicate edges, as it's somewhat easier as a boundary condition.
// That's why we don't update the 'src' pointer on top/bottom area:
if (p->row_ >= 0 && p->row_ < p->height_ - 1) {
p->src_ += p->width_;
p->src_ += p->stride_;
}
}
@ -149,7 +150,7 @@ static void ApplyFilter(SmoothParams* const p) {
#endif
}
}
p->dst_ += w; // advance output pointer
p->dst_ += p->stride_; // advance output pointer
}
//------------------------------------------------------------------------------
@ -208,7 +209,7 @@ static void CountLevels(const uint8_t* const data, int size,
}
// Initialize all params.
static int InitParams(uint8_t* const data, int width, int height,
static int InitParams(uint8_t* const data, int width, int height, int stride,
int radius, SmoothParams* const p) {
const int R = 2 * radius + 1; // total size of the kernel
@ -233,6 +234,7 @@ static int InitParams(uint8_t* const data, int width, int height,
p->width_ = width;
p->height_ = height;
p->stride_ = stride;
p->src_ = data;
p->dst_ = data;
p->radius_ = radius;
@ -253,7 +255,7 @@ static void CleanupParams(SmoothParams* const p) {
WebPSafeFree(p->mem_);
}
int WebPDequantizeLevels(uint8_t* const data, int width, int height,
int WebPDequantizeLevels(uint8_t* const data, int width, int height, int stride,
int strength) {
const int radius = 4 * strength / 100;
if (strength < 0 || strength > 100) return 0;
@ -261,7 +263,7 @@ int WebPDequantizeLevels(uint8_t* const data, int width, int height,
if (radius > 0) {
SmoothParams p;
memset(&p, 0, sizeof(p));
if (!InitParams(data, width, height, radius, &p)) return 0;
if (!InitParams(data, width, height, stride, radius, &p)) return 0;
if (p.num_levels_ > 2) {
for (; p.row_ < p.height_; ++p.row_) {
VFilter(&p); // accumulate average of input

View File

@ -21,11 +21,11 @@ extern "C" {
#endif
// Apply post-processing to input 'data' of size 'width'x'height' assuming that
// the source was quantized to a reduced number of levels.
// the source was quantized to a reduced number of levels. 'stride' is in bytes.
// Strength is in [0..100] and controls the amount of dithering applied.
// Returns false in case of error (data is NULL, invalid parameters,
// malloc failure, ...).
int WebPDequantizeLevels(uint8_t* const data, int width, int height,
int WebPDequantizeLevels(uint8_t* const data, int width, int height, int stride,
int strength);
#ifdef __cplusplus