| Index: third_party/libwebp/utils/quant_levels_dec.c
|
| diff --git a/third_party/libwebp/utils/quant_levels_dec.c b/third_party/libwebp/utils/quant_levels_dec.c
|
| index 5b8b8b49e6bf732a86c110c344e1fbca7287c96b..ee0a3fe127d26e3fe1d41fc96949516b73a8c5e8 100644
|
| --- a/third_party/libwebp/utils/quant_levels_dec.c
|
| +++ b/third_party/libwebp/utils/quant_levels_dec.c
|
| @@ -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
|
| }
|
|
|
| //------------------------------------------------------------------------------
|
| @@ -178,17 +179,20 @@ static void InitCorrectionLUT(int16_t* const lut, int min_dist) {
|
| lut[0] = 0;
|
| }
|
|
|
| -static void CountLevels(const uint8_t* const data, int size,
|
| - SmoothParams* const p) {
|
| - int i, last_level;
|
| +static void CountLevels(SmoothParams* const p) {
|
| + int i, j, last_level;
|
| uint8_t used_levels[256] = { 0 };
|
| + const uint8_t* data = p->src_;
|
| p->min_ = 255;
|
| p->max_ = 0;
|
| - for (i = 0; i < size; ++i) {
|
| - const int v = data[i];
|
| - if (v < p->min_) p->min_ = v;
|
| - if (v > p->max_) p->max_ = v;
|
| - used_levels[v] = 1;
|
| + for (j = 0; j < p->height_; ++j) {
|
| + for (i = 0; i < p->width_; ++i) {
|
| + const int v = data[i];
|
| + if (v < p->min_) p->min_ = v;
|
| + if (v > p->max_) p->max_ = v;
|
| + used_levels[v] = 1;
|
| + }
|
| + data += p->stride_;
|
| }
|
| // Compute the mininum distance between two non-zero levels.
|
| p->min_level_dist_ = p->max_ - p->min_;
|
| @@ -208,7 +212,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 +237,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;
|
| @@ -240,7 +245,7 @@ static int InitParams(uint8_t* const data, int width, int height,
|
| p->row_ = -radius;
|
|
|
| // analyze the input distribution so we can best-fit the threshold
|
| - CountLevels(data, width * height, p);
|
| + CountLevels(p);
|
|
|
| // correction table
|
| p->correction_ = ((int16_t*)mem) + LUT_SIZE;
|
| @@ -253,7 +258,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 +266,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
|
|
|