mirror of
				https://github.com/webmproject/libwebp.git
				synced 2025-10-31 02:15:42 +01:00 
			
		
		
		
	Alpha unfilter for given set of rows
Support reconstruction of small number of rows at a time. Change-Id: Ief1bc78c7ad011ec6df856551f3beb5f907fd8e0
This commit is contained in:
		| @@ -23,12 +23,14 @@ extern "C" { | ||||
| //------------------------------------------------------------------------------ | ||||
| // Helpful macro. | ||||
|  | ||||
| # define SANITY_CHECK(in, out)                              \ | ||||
|   assert(in != NULL);                                       \ | ||||
|   assert(out != NULL);                                      \ | ||||
|   assert(width > 0);                                        \ | ||||
|   assert(height > 0);                                       \ | ||||
|   assert(stride >= width); | ||||
| # 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. | ||||
|  | ||||
| static WEBP_INLINE void PredictLine(const uint8_t* src, const uint8_t* pred, | ||||
|                                     uint8_t* dst, int length, int inverse) { | ||||
| @@ -45,20 +47,32 @@ static WEBP_INLINE void PredictLine(const uint8_t* src, const uint8_t* pred, | ||||
|  | ||||
| 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) { | ||||
|   int h; | ||||
|   const uint8_t* preds = (inverse ? out : in); | ||||
|   const uint8_t* preds; | ||||
|   const size_t start_offset = row * stride; | ||||
|   const int last_row = row + num_rows; | ||||
|   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. | ||||
|   for (h = 0; h < height; ++h) { | ||||
|     // Leftmost pixel is predicted from above (except for topmost scanline). | ||||
|     if (h == 0) { | ||||
|       out[0] = in[0]; | ||||
|     } else { | ||||
|       PredictLine(in, preds - stride, out, 1, inverse); | ||||
|     } | ||||
|   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; | ||||
|     preds += stride; | ||||
|     in += stride; | ||||
|     out += stride; | ||||
| @@ -67,12 +81,12 @@ 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, filtered_data); | ||||
|   DoHorizontalFilter(data, width, height, stride, 0, height, 0, filtered_data); | ||||
| } | ||||
|  | ||||
| static void HorizontalUnfilter(int width, int height, int stride, | ||||
|                                uint8_t* data) { | ||||
|   DoHorizontalFilter(data, width, height, stride, 1, 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); | ||||
| } | ||||
|  | ||||
| //------------------------------------------------------------------------------ | ||||
| @@ -80,32 +94,44 @@ static void HorizontalUnfilter(int width, int height, int stride, | ||||
|  | ||||
| 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) { | ||||
|   int h; | ||||
|   const uint8_t* preds = (inverse ? out : in); | ||||
|   const uint8_t* preds; | ||||
|   const size_t start_offset = row * stride; | ||||
|   const int last_row = row + num_rows; | ||||
|   SANITY_CHECK(in, out); | ||||
|   in += start_offset; | ||||
|   out += start_offset; | ||||
|   preds = inverse ? out : in; | ||||
|  | ||||
|   // 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); | ||||
|  | ||||
|   // Filter line-by-line. | ||||
|   for (h = 1; h < height; ++h) { | ||||
|   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; | ||||
|   } | ||||
|  | ||||
|   // Filter line-by-line. | ||||
|   while (row < last_row) { | ||||
|     PredictLine(in, preds, out, width, inverse); | ||||
|     ++row; | ||||
|     preds += stride; | ||||
|     in += stride; | ||||
|     out += stride; | ||||
|   } | ||||
| } | ||||
|  | ||||
| static void VerticalFilter(const uint8_t* data, int width, int height, | ||||
|                            int stride, uint8_t* filtered_data) { | ||||
|   DoVerticalFilter(data, width, height, stride, 0, filtered_data); | ||||
|   DoVerticalFilter(data, width, height, stride, 0, height, 0, filtered_data); | ||||
| } | ||||
|  | ||||
| static void VerticalUnfilter(int width, int height, int stride, uint8_t* data) { | ||||
|   DoVerticalFilter(data, width, height, stride, 1, 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); | ||||
| } | ||||
|  | ||||
| //------------------------------------------------------------------------------ | ||||
| @@ -116,23 +142,31 @@ static WEBP_INLINE int GradientPredictor(uint8_t a, uint8_t b, uint8_t c) { | ||||
|   return ((g & ~0xff) == 0) ? g : (g < 0) ? 0 : 255;  // clip to 8bit | ||||
| } | ||||
|  | ||||
| static WEBP_INLINE | ||||
| void DoGradientFilter(const uint8_t* in, int width, int height, | ||||
|                       int stride, int inverse, uint8_t* out) { | ||||
|   const uint8_t* preds = (inverse ? out : in); | ||||
|   int h; | ||||
| 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; | ||||
|   SANITY_CHECK(in, out); | ||||
|   in += start_offset; | ||||
|   out += start_offset; | ||||
|   preds = inverse ? out : in; | ||||
|  | ||||
|   // left prediction for top scan-line | ||||
|   out[0] = in[0]; | ||||
|   PredictLine(in + 1, preds, out + 1, width - 1, inverse); | ||||
|  | ||||
|   // Filter line-by-line. | ||||
|   for (h = 1; h < height; ++h) { | ||||
|     int w; | ||||
|   if (row == 0) { | ||||
|     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) { | ||||
|     int w; | ||||
|     // leftmost pixel: predict from above. | ||||
|     PredictLine(in, preds - stride, out, 1, inverse); | ||||
|     for (w = 1; w < width; ++w) { | ||||
| @@ -141,16 +175,21 @@ void DoGradientFilter(const uint8_t* in, int width, int height, | ||||
|                                          preds[w - stride - 1]); | ||||
|       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, filtered_data); | ||||
|   DoGradientFilter(data, width, height, stride, 0, height, 0, filtered_data); | ||||
| } | ||||
|  | ||||
| static void GradientUnfilter(int width, int height, int stride, uint8_t* data) { | ||||
|   DoGradientFilter(data, width, height, stride, 1, 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); | ||||
| } | ||||
|  | ||||
| #undef SANITY_CHECK | ||||
|   | ||||
| @@ -34,7 +34,7 @@ typedef enum { | ||||
| typedef void (*WebPFilterFunc)(const uint8_t* in, int width, int height, | ||||
|                                int stride, uint8_t* out); | ||||
| typedef void (*WebPUnfilterFunc)(int width, int height, int stride, | ||||
|                                  uint8_t* data); | ||||
|                                  int row, int num_rows, uint8_t* data); | ||||
|  | ||||
| // Filter the given data using the given predictor. | ||||
| // 'in' corresponds to a 2-dimensional pixel array of size (stride * height) | ||||
| @@ -44,6 +44,8 @@ typedef void (*WebPUnfilterFunc)(int width, int height, int stride, | ||||
| extern const WebPFilterFunc WebPFilters[WEBP_FILTER_LAST]; | ||||
|  | ||||
| // In-place reconstruct the original data from the given filtered data. | ||||
| // The reconstruction will be done for 'num_rows' rows starting from 'row' | ||||
| // (assuming rows upto 'row - 1' are already reconstructed). | ||||
| extern const WebPUnfilterFunc WebPUnfilters[WEBP_FILTER_LAST]; | ||||
|  | ||||
| // Fast estimate of a potentially good filter. | ||||
|   | ||||
		Reference in New Issue
	
	Block a user