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 |