diff options
Diffstat (limited to 'drivers/webp/utils/filters.c')
-rw-r--r-- | drivers/webp/utils/filters.c | 187 |
1 files changed, 75 insertions, 112 deletions
diff --git a/drivers/webp/utils/filters.c b/drivers/webp/utils/filters.c index 2d15bd0e4a..08f52a3d20 100644 --- a/drivers/webp/utils/filters.c +++ b/drivers/webp/utils/filters.c @@ -1,10 +1,8 @@ // Copyright 2011 Google Inc. All Rights Reserved. // -// Use of this source code is governed by a BSD-style license -// that can be found in the COPYING file in the root of the source -// tree. An additional intellectual property rights grant can be found -// in the file PATENTS. All contributing project authors may -// be found in the AUTHORS file in the root of the source tree. +// This code is licensed under the same terms as WebM: +// Software License Agreement: http://www.webmproject.org/license/software/ +// Additional IP Rights Grant: http://www.webmproject.org/license/additional/ // ----------------------------------------------------------------------------- // // Spatial prediction using various filters @@ -16,17 +14,20 @@ #include <stdlib.h> #include <string.h> +#if defined(__cplusplus) || defined(c_plusplus) +extern "C" { +#endif + //------------------------------------------------------------------------------ // Helpful macro. -# define SANITY_CHECK(in, out) \ - assert(in != NULL); \ - assert(out != NULL); \ - assert(width > 0); \ - assert(height > 0); \ - assert(stride >= width); \ - assert(row >= 0 && num_rows > 0 && row + num_rows <= height); \ - (void)height; // Silence unused warning. +# define SANITY_CHECK(in, out) \ + assert(in != NULL); \ + assert(out != NULL); \ + assert(width > 0); \ + assert(height > 0); \ + assert(bpp > 0); \ + assert(stride >= width * bpp); static WEBP_INLINE void PredictLine(const uint8_t* src, const uint8_t* pred, uint8_t* dst, int length, int inverse) { @@ -42,33 +43,20 @@ static WEBP_INLINE void PredictLine(const uint8_t* src, const uint8_t* pred, // Horizontal filter. static WEBP_INLINE void DoHorizontalFilter(const uint8_t* in, - int width, int height, int stride, - int row, int num_rows, - int inverse, uint8_t* out) { - const uint8_t* preds; - const size_t start_offset = row * stride; - const int last_row = row + num_rows; + int width, int height, int bpp, int stride, int inverse, uint8_t* out) { + int h; + const uint8_t* preds = (inverse ? out : in); SANITY_CHECK(in, out); - in += start_offset; - out += start_offset; - preds = inverse ? out : in; - - if (row == 0) { - // Leftmost pixel is the same as input for topmost scanline. - out[0] = in[0]; - PredictLine(in + 1, preds, out + 1, width - 1, inverse); - row = 1; - preds += stride; - in += stride; - out += stride; - } // Filter line-by-line. - while (row < last_row) { - // Leftmost pixel is predicted from above. - PredictLine(in, preds - stride, out, 1, inverse); - PredictLine(in + 1, preds, out + 1, width - 1, inverse); - ++row; + for (h = 0; h < height; ++h) { + // Leftmost pixel is predicted from above (except for topmost scanline). + if (h == 0) { + memcpy((void*)out, (const void*)in, bpp); + } else { + PredictLine(in, preds - stride, out, bpp, inverse); + } + PredictLine(in + bpp, preds, out + bpp, bpp * (width - 1), inverse); preds += stride; in += stride; out += stride; @@ -76,61 +64,46 @@ static WEBP_INLINE void DoHorizontalFilter(const uint8_t* in, } static void HorizontalFilter(const uint8_t* data, int width, int height, - int stride, uint8_t* filtered_data) { - DoHorizontalFilter(data, width, height, stride, 0, height, 0, filtered_data); + int bpp, int stride, uint8_t* filtered_data) { + DoHorizontalFilter(data, width, height, bpp, stride, 0, filtered_data); } -static void HorizontalUnfilter(int width, int height, int stride, int row, - int num_rows, uint8_t* data) { - DoHorizontalFilter(data, width, height, stride, row, num_rows, 1, data); +static void HorizontalUnfilter(const uint8_t* data, int width, int height, + int bpp, int stride, uint8_t* recon_data) { + DoHorizontalFilter(data, width, height, bpp, stride, 1, recon_data); } //------------------------------------------------------------------------------ // Vertical filter. static WEBP_INLINE void DoVerticalFilter(const uint8_t* in, - int width, int height, int stride, - int row, int num_rows, - int inverse, uint8_t* out) { - const uint8_t* preds; - const size_t start_offset = row * stride; - const int last_row = row + num_rows; + int width, int height, int bpp, int stride, int inverse, uint8_t* out) { + int h; + const uint8_t* preds = (inverse ? out : in); SANITY_CHECK(in, out); - in += start_offset; - out += start_offset; - preds = inverse ? out : in; - - if (row == 0) { - // Very first top-left pixel is copied. - out[0] = in[0]; - // Rest of top scan-line is left-predicted. - PredictLine(in + 1, preds, out + 1, width - 1, inverse); - row = 1; - in += stride; - out += stride; - } else { - // We are starting from in-between. Make sure 'preds' points to prev row. - preds -= stride; - } + + // Very first top-left pixel is copied. + memcpy((void*)out, (const void*)in, bpp); + // Rest of top scan-line is left-predicted. + PredictLine(in + bpp, preds, out + bpp, bpp * (width - 1), inverse); // Filter line-by-line. - while (row < last_row) { - PredictLine(in, preds, out, width, inverse); - ++row; - preds += stride; + for (h = 1; h < height; ++h) { in += stride; out += stride; + PredictLine(in, preds, out, bpp * width, inverse); + preds += stride; } } static void VerticalFilter(const uint8_t* data, int width, int height, - int stride, uint8_t* filtered_data) { - DoVerticalFilter(data, width, height, stride, 0, height, 0, filtered_data); + int bpp, int stride, uint8_t* filtered_data) { + DoVerticalFilter(data, width, height, bpp, stride, 0, filtered_data); } -static void VerticalUnfilter(int width, int height, int stride, int row, - int num_rows, uint8_t* data) { - DoVerticalFilter(data, width, height, stride, row, num_rows, 1, data); +static void VerticalUnfilter(const uint8_t* data, int width, int height, + int bpp, int stride, uint8_t* recon_data) { + DoVerticalFilter(data, width, height, bpp, stride, 1, recon_data); } //------------------------------------------------------------------------------ @@ -138,63 +111,52 @@ static void VerticalUnfilter(int width, int height, int stride, int row, static WEBP_INLINE int GradientPredictor(uint8_t a, uint8_t b, uint8_t c) { const int g = a + b - c; - return ((g & ~0xff) == 0) ? g : (g < 0) ? 0 : 255; // clip to 8bit + return (g < 0) ? 0 : (g > 255) ? 255 : g; } -static WEBP_INLINE void DoGradientFilter(const uint8_t* in, - int width, int height, int stride, - int row, int num_rows, - int inverse, uint8_t* out) { - const uint8_t* preds; - const size_t start_offset = row * stride; - const int last_row = row + num_rows; +static WEBP_INLINE +void DoGradientFilter(const uint8_t* in, int width, int height, + int bpp, int stride, int inverse, uint8_t* out) { + const uint8_t* preds = (inverse ? out : in); + int h; SANITY_CHECK(in, out); - in += start_offset; - out += start_offset; - preds = inverse ? out : in; // left prediction for top scan-line - if (row == 0) { - out[0] = in[0]; - PredictLine(in + 1, preds, out + 1, width - 1, inverse); - row = 1; - preds += stride; - in += stride; - out += stride; - } + memcpy((void*)out, (const void*)in, bpp); + PredictLine(in + bpp, preds, out + bpp, bpp * (width - 1), inverse); // Filter line-by-line. - while (row < last_row) { + for (h = 1; h < height; ++h) { int w; + preds += stride; + in += stride; + out += stride; // leftmost pixel: predict from above. - PredictLine(in, preds - stride, out, 1, inverse); - for (w = 1; w < width; ++w) { - const int pred = GradientPredictor(preds[w - 1], + PredictLine(in, preds - stride, out, bpp, inverse); + for (w = bpp; w < width * bpp; ++w) { + const int pred = GradientPredictor(preds[w - bpp], preds[w - stride], - preds[w - stride - 1]); + preds[w - stride - bpp]); out[w] = in[w] + (inverse ? pred : -pred); } - ++row; - preds += stride; - in += stride; - out += stride; } } static void GradientFilter(const uint8_t* data, int width, int height, - int stride, uint8_t* filtered_data) { - DoGradientFilter(data, width, height, stride, 0, height, 0, filtered_data); + int bpp, int stride, uint8_t* filtered_data) { + DoGradientFilter(data, width, height, bpp, stride, 0, filtered_data); } -static void GradientUnfilter(int width, int height, int stride, int row, - int num_rows, uint8_t* data) { - DoGradientFilter(data, width, height, stride, row, num_rows, 1, data); +static void GradientUnfilter(const uint8_t* data, int width, int height, + int bpp, int stride, uint8_t* recon_data) { + DoGradientFilter(data, width, height, bpp, stride, 1, recon_data); } #undef SANITY_CHECK // ----------------------------------------------------------------------------- -// Quick estimate of a potentially interesting filter mode to try. +// Quick estimate of a potentially interesting filter mode to try, in addition +// to the default NONE. #define SMAX 16 #define SDIFF(a, b) (abs((a) - (b)) >> 4) // Scoring diff, in [0..SMAX) @@ -204,7 +166,6 @@ WEBP_FILTER_TYPE EstimateBestFilter(const uint8_t* data, int i, j; int bins[WEBP_FILTER_LAST][SMAX]; memset(bins, 0, sizeof(bins)); - // We only sample every other pixels. That's enough. for (j = 2; j < height - 1; j += 2) { const uint8_t* const p = data + j * stride; @@ -224,8 +185,7 @@ WEBP_FILTER_TYPE EstimateBestFilter(const uint8_t* data, } } { - int filter; - WEBP_FILTER_TYPE best_filter = WEBP_FILTER_NONE; + WEBP_FILTER_TYPE filter, best_filter = WEBP_FILTER_NONE; int best_score = 0x7fffffff; for (filter = WEBP_FILTER_NONE; filter < WEBP_FILTER_LAST; ++filter) { int score = 0; @@ -236,7 +196,7 @@ WEBP_FILTER_TYPE EstimateBestFilter(const uint8_t* data, } if (score < best_score) { best_score = score; - best_filter = (WEBP_FILTER_TYPE)filter; + best_filter = filter; } } return best_filter; @@ -255,7 +215,7 @@ const WebPFilterFunc WebPFilters[WEBP_FILTER_LAST] = { GradientFilter // WEBP_FILTER_GRADIENT }; -const WebPUnfilterFunc WebPUnfilters[WEBP_FILTER_LAST] = { +const WebPFilterFunc WebPUnfilters[WEBP_FILTER_LAST] = { NULL, // WEBP_FILTER_NONE HorizontalUnfilter, // WEBP_FILTER_HORIZONTAL VerticalUnfilter, // WEBP_FILTER_VERTICAL @@ -264,3 +224,6 @@ const WebPUnfilterFunc WebPUnfilters[WEBP_FILTER_LAST] = { //------------------------------------------------------------------------------ +#if defined(__cplusplus) || defined(c_plusplus) +} // extern "C" +#endif |