Project Ne10
An open, optimized software library for the ARM architecture.
NE10_boxfilter.c
Go to the documentation of this file.
1 /*
2  * Copyright 2013-16 ARM Limited and Contributors.
3  * All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions are met:
7  * * Redistributions of source code must retain the above copyright
8  * notice, this list of conditions and the following disclaimer.
9  * * Redistributions in binary form must reproduce the above copyright
10  * notice, this list of conditions and the following disclaimer in the
11  * documentation and/or other materials provided with the distribution.
12  * * Neither the name of ARM Limited nor the
13  * names of its contributors may be used to endorse or promote products
14  * derived from this software without specific prior written permission.
15  *
16  * THIS SOFTWARE IS PROVIDED BY ARM LIMITED AND CONTRIBUTORS "AS IS" AND
17  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
19  * DISCLAIMED. IN NO EVENT SHALL ARM LIMITED AND CONTRIBUTORS BE LIABLE FOR ANY
20  * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
21  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
22  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
23  * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
25  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26  */
27 /* license of OpenCV */
28 /*M///////////////////////////////////////////////////////////////////////////////////////
29 //
30 // IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING.
31 //
32 // By downloading, copying, installing or using the software you agree to this license.
33 // If you do not agree to this license, do not download, install,
34 // copy or use the software.
35 //
36 //
37 // License Agreement
38 // For Open Source Computer Vision Library
39 //
40 // Copyright (C) 2000-2008, Intel Corporation, all rights reserved.
41 // Copyright (C) 2009, Willow Garage Inc., all rights reserved.
42 // Third party copyrights are property of their respective owners.
43 //
44 // Redistribution and use in source and binary forms, with or without modification,
45 // are permitted provided that the following conditions are met:
46 //
47 // * Redistribution's of source code must retain the above copyright notice,
48 // this list of conditions and the following disclaimer.
49 //
50 // * Redistribution's in binary form must reproduce the above copyright notice,
51 // this list of conditions and the following disclaimer in the documentation
52 // and/or other materials provided with the distribution.
53 //
54 // * The name of the copyright holders may not be used to endorse or promote products
55 // derived from this software without specific prior written permission.
56 //
57 // This software is provided by the copyright holders and contributors "as is" and
58 // any express or implied warranties, including, but not limited to, the implied
59 // warranties of merchantability and fitness for a particular purpose are disclaimed.
60 // In no event shall the Intel Corporation or contributors be liable for any direct,
61 // indirect, incidental, special, exemplary, or consequential damages
62 // (including, but not limited to, procurement of substitute goods or services;
63 // loss of use, data, or profits; or business interruption) however caused
64 // and on any theory of liability, whether in contract, strict liability,
65 // or tort (including negligence or otherwise) arising in any way out of
66 // the use of this software, even if advised of the possibility of such damage.
67 //
68 //M*/
69 
70 /*
71  * NE10 Library : imgproc/NE10_boxfilter.c
72  */
73 
74 #include "NE10.h"
75 #include <stdlib.h>
76 
77 /* RGBA CHANNEL number is 4 */
78 #define RGBA_CH 4
79 
80 /*
81  * compute destination image's row border.
82  */
84  ne10_uint8_t* dst,
85  ne10_size_t src_sz,
86  ne10_int32_t src_stride,
87  ne10_int32_t dst_stride,
88  ne10_size_t kernel,
89  ne10_point_t anchor,
90  ne10_int32_t *border_l_p,
91  ne10_int32_t *border_r_p)
92 {
93  assert (kernel.x <= src_sz.x);
94  assert (src != dst);
95 
96  *border_l_p = anchor.x;
97  *border_r_p = kernel.x - (anchor.x + 1);
98 
99  ne10_int32_t x, y, k;
100 
101  const ne10_uint8_t *src_row;
102  ne10_uint8_t *dst_row;
103 
104  for (y = 0; y < src_sz.y; y++)
105  {
106  src_row = src + y * src_stride;
107  dst_row = dst + y * dst_stride;
108  ne10_float32_t sum[RGBA_CH];
109 
110  /* compute left border */
111  ne10_int32_t offset = kernel.x - *border_l_p - 1;
112  for (k = 0; k < RGBA_CH; k++)
113  {
114  sum[k] = 0;
115  for (x = 0; x < offset; x++)
116  {
117  sum[k] += * (src_row + x * RGBA_CH + k);
118  }
119  }
120 
121  for (k = 0; k < RGBA_CH; k++)
122  {
123  for (x = 0; x < *border_l_p; x++)
124  {
125  sum[k] += * (src_row + (offset + x) *
126  RGBA_CH + k);
127  * (dst_row + x * RGBA_CH + k) = sum[k] /
128  kernel.x;
129  }
130  }
131 
132  /* compute right border */
133  for (k = 0; k < RGBA_CH; k++)
134  {
135  sum[k] = 0;
136  for (x = 0; x < kernel.x; x++)
137  {
138  sum[k] += * (src_row + (src_sz.x - kernel.x + x) *
139  RGBA_CH + k);
140  }
141  }
142 
143  for (k = 0; k < RGBA_CH; k++)
144  {
145  for (x = 0; x < *border_r_p; x++)
146  {
147  sum[k] -= * (src_row + (src_sz.x - kernel.x + x) *
148  RGBA_CH + k);
149  * (dst_row + (src_sz.x - *border_r_p + x) *
150  RGBA_CH + k) = sum[k] / kernel.x;
151  }
152  }
153  }
154 }
155 
157  ne10_uint8_t *dst,
158  ne10_size_t src_sz,
159  ne10_int32_t src_stride,
160  ne10_int32_t dst_stride,
161  ne10_size_t kernel,
162  ne10_point_t anchor,
163  ne10_int32_t border_l,
164  ne10_int32_t border_r)
165 {
166  assert (src != dst);
167  assert ( (kernel.x > 0) && (kernel.x < (1 << 16)));
168  assert (kernel.x <= src_sz.x);
169 
170  ne10_int32_t x, y, k;
171 
172  for (y = 0; y < src_sz.y; y++)
173  {
174  const ne10_uint8_t *src_row = src + y * src_stride;
175  ne10_uint8_t *dst_row = dst + y * dst_stride;
176  ne10_float32_t sum[RGBA_CH];
177 
178  for (k = 0; k < RGBA_CH; k++)
179  {
180  sum[k] = 0;
181 
182  for (x = 0; x < kernel.x; x++)
183  {
184  sum[k] += * (src_row + x * RGBA_CH + k);
185  }
186 
187  * (dst_row + border_l * RGBA_CH + k) = sum[k] /
188  kernel.x;
189  }
190 
191  ne10_uint32_t prev = (anchor.x + 1) * RGBA_CH;
192  ne10_uint32_t next = (kernel.x - anchor.x - 1) * RGBA_CH;
193  const ne10_uint8_t *src_pixel = src_row + (1 + border_l) * RGBA_CH;
194  const ne10_uint8_t *src_pixel_end = src_row + (src_sz.x - border_r) *
195  RGBA_CH;
196  ne10_uint8_t *dst_pixel = dst_row + (1 + border_l) * RGBA_CH;
197 
198  for (k = 0; src_pixel < src_pixel_end; src_pixel++, dst_pixel++)
199  {
200  sum[k] += src_pixel[next] - * (src_pixel - prev);
201  *dst_pixel = sum[k] / kernel.x;
202  k++;
203  k &= 3;
204  }
205  }
206 }
207 
209  ne10_uint8_t *dst,
210  ne10_size_t src_sz,
211  ne10_int32_t src_stride,
212  ne10_int32_t dst_stride,
213  ne10_size_t kernel,
214  ne10_point_t anchor,
215  ne10_int32_t *border_t_p,
216  ne10_int32_t *border_b_p)
217 {
218  assert (kernel.y <= src_sz.y);
219  assert (src != dst);
220 
221  *border_t_p = anchor.y;
222  *border_b_p = kernel.y - (anchor.y + 1);
223 
224  ne10_int32_t x, y, k;
225  const ne10_uint8_t *src_col;
226  ne10_uint8_t *dst_col;
227 
228  for (x = 0; x < src_sz.x; x++)
229  {
230  src_col = src + x * RGBA_CH;
231  dst_col = dst + x * RGBA_CH;
232  ne10_float32_t sum[RGBA_CH];
233 
234  /* compute top border */
235  ne10_int32_t offset = kernel.y - *border_t_p - 1;
236  for (k = 0; k < RGBA_CH; k++)
237  {
238  sum[k] = 0;
239 
240  for (y = 0; y < offset; y++)
241  {
242  sum[k] += * (src_col + y * src_stride + k);
243  }
244  }
245 
246  for (k = 0; k < RGBA_CH; k++)
247  {
248  for (y = 0; y < *border_t_p; y++)
249  {
250  sum[k] += * (src_col + (offset + y) *
251  src_stride + k);
252  * (dst_col + y * dst_stride + k) = sum[k] /
253  kernel.y;
254  }
255  }
256 
257  /* compute the bottom border */
258  for (k = 0; k < RGBA_CH; k++)
259  {
260  sum[k] = 0;
261  for (y = 0; y < kernel.y; y++)
262  {
263  sum[k] += * (src_col + (src_sz.y - kernel.y + y) *
264  src_stride + k);
265  }
266  }
267 
268  for (k = 0; k < RGBA_CH; k++)
269  {
270  for (y = 0; y < *border_b_p; y++)
271  {
272  sum[k] -= * (src_col + (src_sz.y - kernel.y + y) *
273  src_stride + k);
274  * (dst_col + (src_sz.y - *border_b_p + y) * dst_stride + k) =
275  sum[k] / kernel.y;
276  }
277  }
278  }
279 }
280 
282  ne10_uint8_t *dst,
283  ne10_size_t src_sz,
284  ne10_int32_t src_stride,
285  ne10_int32_t dst_stride,
286  ne10_size_t kernel,
287  ne10_point_t anchor,
288  ne10_int32_t border_t,
289  ne10_int32_t border_b)
290 {
291  assert (src != dst);
292  assert ( (kernel.y > 0) && (kernel.y < (1 << 16)));
293  assert (kernel.y <= src_sz.y);
294 
295  ne10_int32_t x, y, k;
296 
297  for (x = 0; x < src_sz.x; x++)
298  {
299  const ne10_uint8_t *src_col = src + x * RGBA_CH;
300  ne10_uint8_t *dst_col = dst + x * RGBA_CH;
301  ne10_float32_t sum[RGBA_CH];
302 
303  for (k = 0; k < RGBA_CH; k++)
304  {
305  sum[k] = 0;
306 
307  for (y = 0; y < kernel.y; y++)
308  {
309  sum[k] += * (src_col + y * src_stride + k);
310  }
311 
312  * (dst_col + border_t * dst_stride + k) = sum[k] / kernel.y;
313  }
314 
315  ne10_uint32_t prev = (anchor.y + 1) * src_stride;
316  ne10_uint32_t next = (kernel.y - anchor.y - 1) * src_stride;
317  const ne10_uint8_t *src_pixel = src_col + (1 + border_t) * src_stride;
318  const ne10_uint8_t *src_end = src_col + (src_sz.y - border_b) *
319  src_stride;
320  ne10_uint8_t *dst_pixel = dst_col + (1 + border_t) * dst_stride;
321 
322  while (src_pixel < src_end)
323  {
324  for (k = 0; k < RGBA_CH; k++)
325  {
326  sum[k] += src_pixel[next + k] - * (src_pixel - prev + k);
327  * (dst_pixel + k) = sum[k] / kernel.y;
328  }
329  dst_pixel += dst_stride;
330  src_pixel += src_stride;
331  }
332  }
333 }
334 
345  ne10_uint8_t *dst,
346  ne10_size_t src_sz,
347  ne10_int32_t src_stride,
348  ne10_int32_t dst_stride,
349  ne10_size_t kernel)
350 {
351  ne10_int32_t border_l, border_r, border_t, border_b;
352  ne10_point_t anchor;
353 
354  assert (src != 0 && dst != 0);
355  assert (src_sz.x > 0 && src_sz.y > 0);
356  assert (src_stride > 0 && dst_stride > 0);
357  assert (kernel.x > 0 && kernel.x <= src_sz.x
358  && kernel.y > 0 && kernel.y <= src_sz.y);
359 
360  anchor.x = kernel.x / 2;
361  anchor.y = kernel.y / 2;
362 
363  ne10_uint8_t *dst_buf = (ne10_uint8_t *) malloc (sizeof (ne10_uint8_t) *
364  src_sz.x *
365  src_sz.y *
366  RGBA_CH);
367 
368  if (!dst_buf)
369  {
370  fprintf (stderr,
371  "ERROR: buffer allocation fails!\nallocation size: %d\n",
372  sizeof (ne10_uint8_t) *
373  src_sz.x *
374  src_sz.y *
375  RGBA_CH);
376  return;
377  }
378 
379  ne10_int32_t dst_buf_stride = src_sz.x * RGBA_CH;
380 
381  /* compute the row border of dst image */
383  dst_buf,
384  src_sz,
385  src_stride,
386  dst_buf_stride,
387  kernel,
388  anchor,
389  &border_l,
390  &border_r);
391  /* boxfilter is separable filter, and then can be apply row filter and
392  * column filter sequentially. here apply boxfilter's row part to image
393  */
395  dst_buf,
396  src_sz,
397  src_stride,
398  dst_buf_stride,
399  kernel,
400  anchor,
401  border_l,
402  border_r);
403 
404  /* compute the column border of dst image,
405  * which is based on previous row filter result.
406  */
408  dst,
409  src_sz,
410  dst_buf_stride,
411  dst_stride,
412  kernel,
413  anchor,
414  &border_t,
415  &border_b);
416 
417  /* apply boxfilter column filter to image */
418  ne10_img_boxfilter_col_c (dst_buf,
419  dst,
420  src_sz,
421  dst_buf_stride,
422  dst_stride,
423  kernel,
424  anchor,
425  border_t,
426  border_b);
427 
428  free (dst_buf);
429 }
uint8_t ne10_uint8_t
Definition: NE10_types.h:73
ne10_uint32_t y
Definition: NE10_types.h:440
int32_t ne10_int32_t
Definition: NE10_types.h:76
void ne10_img_boxfilter_col_border(const ne10_uint8_t *src, ne10_uint8_t *dst, ne10_size_t src_sz, ne10_int32_t src_stride, ne10_int32_t dst_stride, ne10_size_t kernel, ne10_point_t anchor, ne10_int32_t *border_t_p, ne10_int32_t *border_b_p)
float ne10_float32_t
Definition: NE10_types.h:80
ne10_uint32_t x
Definition: NE10_types.h:439
uint32_t ne10_uint32_t
Definition: NE10_types.h:77
void ne10_img_boxfilter_rgba8888_c(const ne10_uint8_t *src, ne10_uint8_t *dst, ne10_size_t src_sz, ne10_int32_t src_stride, ne10_int32_t dst_stride, ne10_size_t kernel)
Specific implementation of ne10_img_boxfilter_rgba8888 using plain C.
void ne10_img_boxfilter_row_c(const ne10_uint8_t *src, ne10_uint8_t *dst, ne10_size_t src_sz, ne10_int32_t src_stride, ne10_int32_t dst_stride, ne10_size_t kernel, ne10_point_t anchor, ne10_int32_t border_l, ne10_int32_t border_r)
ne10_uint32_t y
Definition: NE10_types.h:434
#define RGBA_CH
void ne10_img_boxfilter_col_c(const ne10_uint8_t *src, ne10_uint8_t *dst, ne10_size_t src_sz, ne10_int32_t src_stride, ne10_int32_t dst_stride, ne10_size_t kernel, ne10_point_t anchor, ne10_int32_t border_t, ne10_int32_t border_b)
void ne10_img_boxfilter_row_border(const ne10_uint8_t *src, ne10_uint8_t *dst, ne10_size_t src_sz, ne10_int32_t src_stride, ne10_int32_t dst_stride, ne10_size_t kernel, ne10_point_t anchor, ne10_int32_t *border_l_p, ne10_int32_t *border_r_p)
Structure for point in image.
Definition: NE10_types.h:431
ne10_uint32_t x
Definition: NE10_types.h:433