mirror of
https://github.com/webmproject/libwebp.git
synced 2024-12-27 22:28:22 +01:00
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:
parent
e88c4ca013
commit
64eed38779
@ -120,16 +120,18 @@ static int ALPHDecode(VP8Decoder* const dec, int row, int num_rows) {
|
|||||||
// Main entry point.
|
// Main entry point.
|
||||||
|
|
||||||
const uint8_t* VP8DecompressAlphaRows(VP8Decoder* const dec,
|
const uint8_t* VP8DecompressAlphaRows(VP8Decoder* const dec,
|
||||||
|
const VP8Io* const io,
|
||||||
int row, int num_rows) {
|
int row, int num_rows) {
|
||||||
const int width = dec->pic_hdr_.width_;
|
const int width = dec->pic_hdr_.width_;
|
||||||
const int height = dec->pic_hdr_.height_;
|
const int height = dec->pic_hdr_.height_;
|
||||||
|
|
||||||
|
assert(dec != NULL && io != NULL);
|
||||||
|
|
||||||
if (row < 0 || num_rows <= 0 || row + num_rows > height) {
|
if (row < 0 || num_rows <= 0 || row + num_rows > height) {
|
||||||
return NULL; // sanity check.
|
return NULL; // sanity check.
|
||||||
}
|
}
|
||||||
|
|
||||||
if (row == 0) {
|
if (dec->alph_dec_ == NULL) { // Initialize decoder.
|
||||||
// Initialize decoding.
|
|
||||||
assert(dec->alpha_plane_ != NULL);
|
assert(dec->alpha_plane_ != NULL);
|
||||||
dec->alph_dec_ = ALPHNew();
|
dec->alph_dec_ = ALPHNew();
|
||||||
if (dec->alph_dec_ == NULL) return NULL;
|
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_) {
|
if (!dec->is_alpha_decoded_) {
|
||||||
int ok = 0;
|
int ok = ALPHDecode(dec, row, num_rows);
|
||||||
assert(dec->alph_dec_ != NULL);
|
assert(dec->alph_dec_ != NULL);
|
||||||
ok = ALPHDecode(dec, row, num_rows);
|
|
||||||
if (ok && dec->alpha_dithering_ > 0) {
|
if (ok && dec->alpha_dithering_ > 0) {
|
||||||
ok = WebPDequantizeLevels(dec->alpha_plane_, width, height,
|
ok = WebPDequantizeLevels(dec->alpha_plane_, width, height, width,
|
||||||
dec->alpha_dithering_);
|
dec->alpha_dithering_);
|
||||||
}
|
}
|
||||||
if (!ok || dec->is_alpha_decoded_) {
|
if (!ok || dec->is_alpha_decoded_) {
|
||||||
@ -161,7 +168,6 @@ const uint8_t* VP8DecompressAlphaRows(VP8Decoder* const dec,
|
|||||||
}
|
}
|
||||||
if (!ok) return NULL; // Error.
|
if (!ok) return NULL; // Error.
|
||||||
}
|
}
|
||||||
|
|
||||||
// Return a pointer to the current decoded row.
|
// Return a pointer to the current decoded row.
|
||||||
return dec->alpha_plane_ + row * width;
|
return dec->alpha_plane_ + row * width;
|
||||||
}
|
}
|
||||||
|
@ -462,7 +462,7 @@ static int FinishRow(VP8Decoder* const dec, VP8Io* const io) {
|
|||||||
if (dec->alpha_data_ != NULL && y_start < y_end) {
|
if (dec->alpha_data_ != NULL && y_start < y_end) {
|
||||||
// TODO(skal): testing presence of alpha with dec->alpha_data_ is not a
|
// TODO(skal): testing presence of alpha with dec->alpha_data_ is not a
|
||||||
// good idea.
|
// 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) {
|
if (io->a == NULL) {
|
||||||
return VP8SetError(dec, VP8_STATUS_BITSTREAM_ERROR,
|
return VP8SetError(dec, VP8_STATUS_BITSTREAM_ERROR,
|
||||||
"Could not decode alpha data.");
|
"Could not decode alpha data.");
|
||||||
|
@ -306,6 +306,7 @@ int VP8DecodeMB(VP8Decoder* const dec, VP8BitReader* const token_br);
|
|||||||
|
|
||||||
// in alpha.c
|
// in alpha.c
|
||||||
const uint8_t* VP8DecompressAlphaRows(VP8Decoder* const dec,
|
const uint8_t* VP8DecompressAlphaRows(VP8Decoder* const dec,
|
||||||
|
const VP8Io* const io,
|
||||||
int row, int num_rows);
|
int row, int num_rows);
|
||||||
|
|
||||||
//------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------
|
||||||
|
@ -44,6 +44,7 @@ static const uint8_t kOrderedDither[DSIZE][DSIZE] = {
|
|||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
int width_, height_; // dimension
|
int width_, height_; // dimension
|
||||||
|
int stride_; // stride in bytes
|
||||||
int row_; // current input row being processed
|
int row_; // current input row being processed
|
||||||
uint8_t* src_; // input pointer
|
uint8_t* src_; // input pointer
|
||||||
uint8_t* dst_; // output 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.
|
// 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:
|
// That's why we don't update the 'src' pointer on top/bottom area:
|
||||||
if (p->row_ >= 0 && p->row_ < p->height_ - 1) {
|
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
|
#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.
|
// 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) {
|
int radius, SmoothParams* const p) {
|
||||||
const int R = 2 * radius + 1; // total size of the kernel
|
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->width_ = width;
|
||||||
p->height_ = height;
|
p->height_ = height;
|
||||||
|
p->stride_ = stride;
|
||||||
p->src_ = data;
|
p->src_ = data;
|
||||||
p->dst_ = data;
|
p->dst_ = data;
|
||||||
p->radius_ = radius;
|
p->radius_ = radius;
|
||||||
@ -253,7 +255,7 @@ static void CleanupParams(SmoothParams* const p) {
|
|||||||
WebPSafeFree(p->mem_);
|
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) {
|
int strength) {
|
||||||
const int radius = 4 * strength / 100;
|
const int radius = 4 * strength / 100;
|
||||||
if (strength < 0 || strength > 100) return 0;
|
if (strength < 0 || strength > 100) return 0;
|
||||||
@ -261,7 +263,7 @@ int WebPDequantizeLevels(uint8_t* const data, int width, int height,
|
|||||||
if (radius > 0) {
|
if (radius > 0) {
|
||||||
SmoothParams p;
|
SmoothParams p;
|
||||||
memset(&p, 0, sizeof(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) {
|
if (p.num_levels_ > 2) {
|
||||||
for (; p.row_ < p.height_; ++p.row_) {
|
for (; p.row_ < p.height_; ++p.row_) {
|
||||||
VFilter(&p); // accumulate average of input
|
VFilter(&p); // accumulate average of input
|
||||||
|
@ -21,11 +21,11 @@ extern "C" {
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
// Apply post-processing to input 'data' of size 'width'x'height' assuming that
|
// 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.
|
// Strength is in [0..100] and controls the amount of dithering applied.
|
||||||
// Returns false in case of error (data is NULL, invalid parameters,
|
// Returns false in case of error (data is NULL, invalid parameters,
|
||||||
// malloc failure, ...).
|
// 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);
|
int strength);
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
|
Loading…
Reference in New Issue
Block a user