- add sources.
[platform/framework/web/crosswalk.git] / src / skia / ext / recursive_gaussian_convolution.cc
1 // Copyright (c) 2013 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #include <algorithm>
6 #include <cmath>
7 #include <vector>
8
9 #include "base/logging.h"
10 #include "skia/ext/recursive_gaussian_convolution.h"
11
12 namespace skia {
13
14 namespace {
15
16 // Takes the value produced by accumulating element-wise product of image with
17 // a kernel and brings it back into range.
18 // All of the filter scaling factors are in fixed point with kShiftBits bits of
19 // fractional part.
20 template<bool take_absolute>
21 inline unsigned char FloatTo8(float f) {
22   int a = static_cast<int>(f + 0.5f);
23   if (take_absolute)
24     a = std::abs(a);
25   else if (a < 0)
26     return 0;
27   if (a < 256)
28     return a;
29   return 255;
30 }
31
32 template<RecursiveFilter::Order order>
33 inline float ForwardFilter(float in_n_1,
34                            float in_n,
35                            float in_n1,
36                            const std::vector<float>& w,
37                            int n,
38                            const float* b) {
39   switch (order) {
40     case RecursiveFilter::FUNCTION:
41       return b[0] * in_n + b[1] * w[n-1] + b[2] * w[n-2] + b[3] * w[n-3];
42     case RecursiveFilter::FIRST_DERIVATIVE:
43       return b[0] * 0.5f * (in_n1 - in_n_1) +
44           b[1] * w[n-1] + b[2] * w[n-2] + b[3] * w[n-3];
45     case RecursiveFilter::SECOND_DERIVATIVE:
46       return b[0] * (in_n - in_n_1)  +
47           b[1] * w[n-1] + b[2] * w[n-2] + b[3] * w[n-3];
48   }
49
50   NOTREACHED();
51   return 0.0f;
52 }
53
54 template<RecursiveFilter::Order order>
55 inline float BackwardFilter(const std::vector<float>& out,
56                             int n,
57                             float w_n,
58                             float w_n1,
59                             const float* b) {
60   switch (order) {
61     case RecursiveFilter::FUNCTION:
62     case RecursiveFilter::FIRST_DERIVATIVE:
63       return b[0] * w_n +
64           b[1] * out[n + 1] + b[2] * out[n + 2] + b[3] * out[n + 3];
65     case RecursiveFilter::SECOND_DERIVATIVE:
66       return b[0] * (w_n1 - w_n)  +
67           b[1] * out[n + 1] + b[2] * out[n + 2] + b[3] * out[n + 3];
68   }
69   NOTREACHED();
70   return 0.0f;
71 }
72
73 template<RecursiveFilter::Order order, bool absolute_values>
74 unsigned char SingleChannelRecursiveFilter(
75     const unsigned char* const source_data,
76     int source_pixel_stride,
77     int source_row_stride,
78     int row_width,
79     int row_count,
80     unsigned char* const output,
81     int output_pixel_stride,
82     int output_row_stride,
83     const float* b) {
84   const int intermediate_buffer_size = row_width + 6;
85   std::vector<float> w(intermediate_buffer_size);
86   const unsigned char* in = source_data;
87   unsigned char* out = output;
88   unsigned char max_output = 0;
89   for (int r = 0; r < row_count;
90        ++r, in += source_row_stride, out += output_row_stride) {
91     // Compute forward filter.
92     // First initialize start of the w (temporary) vector.
93     if (order == RecursiveFilter::FUNCTION)
94       w[0] = w[1] = w[2] = in[0];
95     else
96       w[0] = w[1] = w[2] = 0.0f;
97     // Note that special-casing of w[3] is needed because of derivatives.
98     w[3] = ForwardFilter<order>(
99         in[0], in[0], in[source_pixel_stride], w, 3, b);
100     int n = 4;
101     int c = 1;
102     int byte_index = source_pixel_stride;
103     for (; c < row_width - 1; ++c, ++n, byte_index += source_pixel_stride) {
104       w[n] = ForwardFilter<order>(in[byte_index - source_pixel_stride],
105                                   in[byte_index],
106                                   in[byte_index + source_pixel_stride],
107                                   w, n, b);
108     }
109
110     // The value of w corresponding to the last image pixel needs to be computed
111     // separately, again because of derivatives.
112     w[n] = ForwardFilter<order>(in[byte_index - source_pixel_stride],
113                                 in[byte_index],
114                                 in[byte_index],
115                                 w, n, b);
116     // Now three trailing bytes set to the same value as current w[n].
117     w[n + 1] = w[n];
118     w[n + 2] = w[n];
119     w[n + 3] = w[n];
120
121     // Now apply the back filter.
122     float w_n1 = w[n + 1];
123     int output_index = (row_width - 1) * output_pixel_stride;
124     for (; c >= 0; output_index -= output_pixel_stride, --c, --n) {
125       float w_n = BackwardFilter<order>(w, n, w[n], w_n1, b);
126       w_n1 = w[n];
127       w[n] = w_n;
128       out[output_index] = FloatTo8<absolute_values>(w_n);
129       max_output = std::max(max_output, out[output_index]);
130     }
131   }
132   return max_output;
133 }
134
135 unsigned char SingleChannelRecursiveFilter(
136     const unsigned char* const source_data,
137     int source_pixel_stride,
138     int source_row_stride,
139     int row_width,
140     int row_count,
141     unsigned char* const output,
142     int output_pixel_stride,
143     int output_row_stride,
144     const float* b,
145     RecursiveFilter::Order order,
146     bool absolute_values) {
147   if (absolute_values) {
148    switch (order) {
149      case RecursiveFilter::FUNCTION:
150        return SingleChannelRecursiveFilter<RecursiveFilter::FUNCTION, true>(
151            source_data, source_pixel_stride, source_row_stride,
152            row_width, row_count,
153            output, output_pixel_stride, output_row_stride, b);
154      case RecursiveFilter::FIRST_DERIVATIVE:
155        return SingleChannelRecursiveFilter<
156          RecursiveFilter::FIRST_DERIVATIVE, true>(
157              source_data, source_pixel_stride, source_row_stride,
158              row_width, row_count,
159              output, output_pixel_stride, output_row_stride, b);
160      case RecursiveFilter::SECOND_DERIVATIVE:
161        return SingleChannelRecursiveFilter<
162          RecursiveFilter::SECOND_DERIVATIVE, true>(
163              source_data, source_pixel_stride, source_row_stride,
164              row_width, row_count,
165              output, output_pixel_stride, output_row_stride, b);
166    }
167   } else {
168     switch (order) {
169      case RecursiveFilter::FUNCTION:
170        return SingleChannelRecursiveFilter<RecursiveFilter::FUNCTION, false>(
171            source_data, source_pixel_stride, source_row_stride,
172            row_width, row_count,
173            output, output_pixel_stride, output_row_stride, b);
174      case RecursiveFilter::FIRST_DERIVATIVE:
175        return SingleChannelRecursiveFilter<
176          RecursiveFilter::FIRST_DERIVATIVE, false>(
177              source_data, source_pixel_stride, source_row_stride,
178              row_width, row_count,
179              output, output_pixel_stride, output_row_stride, b);
180      case RecursiveFilter::SECOND_DERIVATIVE:
181        return SingleChannelRecursiveFilter<
182          RecursiveFilter::SECOND_DERIVATIVE, false>(
183              source_data, source_pixel_stride, source_row_stride,
184              row_width, row_count,
185              output, output_pixel_stride, output_row_stride, b);
186    }
187   }
188
189   NOTREACHED();
190   return 0;
191 }
192
193 }
194
195 float RecursiveFilter::qFromSigma(float sigma) {
196   DCHECK_GE(sigma, 0.5f);
197   if (sigma <= 2.5f)
198     return 3.97156f - 4.14554f * std::sqrt(1.0f - 0.26891f * sigma);
199   return 0.98711f * sigma - 0.96330f;
200 }
201
202 void RecursiveFilter::computeCoefficients(float q, float b[4]) {
203   b[0] = 1.57825f + 2.44413f * q + 1.4281f * q * q + 0.422205f * q * q * q;
204   b[1] = 2.4413f * q + 2.85619f * q * q + 1.26661f * q * q * q;
205   b[2] = - 1.4281f * q * q - 1.26661f * q * q * q;
206   b[3] = 0.422205f * q * q * q;
207
208   // The above is exactly like in the paper. To cut down on computations,
209   // we can fix up these numbers a bit now.
210   float b_norm = 1.0f - (b[1] + b[2] + b[3]) / b[0];
211   b[1] /= b[0];
212   b[2] /= b[0];
213   b[3] /= b[0];
214   b[0] = b_norm;
215 }
216
217 RecursiveFilter::RecursiveFilter(float sigma, Order order)
218     : order_(order), q_(qFromSigma(sigma)) {
219   computeCoefficients(q_, b_);
220 }
221
222 unsigned char SingleChannelRecursiveGaussianX(const unsigned char* source_data,
223                                               int source_byte_row_stride,
224                                               int input_channel_index,
225                                               int input_channel_count,
226                                               const RecursiveFilter& filter,
227                                               const SkISize& image_size,
228                                               unsigned char* output,
229                                               int output_byte_row_stride,
230                                               int output_channel_index,
231                                               int output_channel_count,
232                                               bool absolute_values) {
233   return SingleChannelRecursiveFilter(source_data + input_channel_index,
234                                       input_channel_count,
235                                       source_byte_row_stride,
236                                       image_size.width(),
237                                       image_size.height(),
238                                       output + output_channel_index,
239                                       output_channel_count,
240                                       output_byte_row_stride,
241                                       filter.b(),
242                                       filter.order(),
243                                       absolute_values);
244 }
245
246 unsigned char  SingleChannelRecursiveGaussianY(const unsigned char* source_data,
247                                                int source_byte_row_stride,
248                                                int input_channel_index,
249                                                int input_channel_count,
250                                                const RecursiveFilter& filter,
251                                                const SkISize& image_size,
252                                                unsigned char* output,
253                                                int output_byte_row_stride,
254                                                int output_channel_index,
255                                                int output_channel_count,
256                                                bool absolute_values) {
257   return SingleChannelRecursiveFilter(source_data + input_channel_index,
258                                       source_byte_row_stride,
259                                       input_channel_count,
260                                       image_size.height(),
261                                       image_size.width(),
262                                       output + output_channel_index,
263                                       output_byte_row_stride,
264                                       output_channel_count,
265                                       filter.b(),
266                                       filter.order(),
267                                       absolute_values);
268 }
269
270 }  // namespace skia