4 * Copyright (C) Georg Martius - July 2010
5 * georg dot martius at web dot de
7 * This file is part of vid.stab video stabilization library
9 * vid.stab is free software; you can redistribute it and/or modify
10 * it under the terms of the GNU General Public License,
11 * as published by the Free Software Foundation; either version 2, or
12 * (at your option) any later version.
14 * vid.stab is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 * GNU General Public License for more details.
19 * You should have received a copy of the GNU General Public License
20 * along with GNU Make; see the file COPYING. If not, write to
21 * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
26 #include "vidstabdefines.h"
29 void boxblur_hori_C(unsigned char* dest
, const unsigned char* src
,
30 int width
, int height
, int dest_strive
, int src_strive
, int size
);
31 void boxblur_vert_C(unsigned char* dest
, const unsigned char* src
,
32 int width
, int height
, int dest_strive
, int src_strive
, int size
);
36 box filter: kernel has only 1's
37 a good blur is obtained for multiple runs of boxblur
38 - 2 runs: tent kernel, infinity -> gaussian
39 but for our purposes is the tent kernel enough.
41 horizontal and vertical 1D boxfilters can be used
43 accumulator: acc = acc + new - old, pixel = acc/size
46 void boxblurPlanar(VSFrame
* dest
, const VSFrame
* src
,
47 VSFrame
* buffer
, const VSFrameInfo
* fi
,
48 unsigned int size
, BoxBlurColorMode colormode
){
53 vsFrameCopy(dest
,src
,fi
);
58 vsFrameAllocate(&buf
,fi
);
63 // odd and larger than 2 and maximally half of smaller image dimension
64 size
= VS_CLAMP((size
/2)*2+1,3,VS_MIN(fi
->height
/2,fi
->width
/2));
65 //printf("%i\n",size);
68 boxblur_hori_C(buf
.data
[0], src
->data
[0],
69 fi
->width
, fi
->height
, buf
.linesize
[0],src
->linesize
[0], size
);
70 boxblur_vert_C(dest
->data
[0], buf
.data
[0],
71 fi
->width
, fi
->height
, dest
->linesize
[0], buf
.linesize
[0], size
);
73 size2
= size
/2+1; // odd and larger than 0
79 for(plane
=1; plane
<fi
->planes
; plane
++){
80 boxblur_hori_C(buf
.data
[plane
], src
->data
[plane
],
81 fi
->width
>> vsGetPlaneWidthSubS(fi
,plane
),
82 fi
->height
>> vsGetPlaneHeightSubS(fi
,plane
),
83 buf
.linesize
[plane
], src
->linesize
[plane
], size2
);
84 boxblur_vert_C(dest
->data
[plane
], buf
.data
[plane
],
85 fi
->width
>> vsGetPlaneWidthSubS(fi
,plane
),
86 fi
->height
>> vsGetPlaneHeightSubS(fi
,plane
),
87 dest
->linesize
[plane
], buf
.linesize
[plane
], size2
);
91 case BoxBlurKeepColor
:
92 // copy both color channels
93 for(plane
=1; plane
<fi
->planes
; plane
++){
94 vsFrameCopyPlane(dest
, src
, fi
, plane
);
96 case BoxBlurNoColor
: // do nothing
107 /* see boxblurPlanar but here we for Packed */
109 /* we add the 3 bytes of one pixel as if they where one number */
111 /* void boxblurPacked(const unsigned char* src, unsigned char* dest, */
112 /* unsigned char* buffer, const VSFrameInfo* fi, */
113 /* unsigned int size){ */
114 /* int localbuffer=0; */
116 /* buffer=(unsigned char*) vs_malloc(fi->framesize); */
119 /* // odd and larger than 2 and maximal half of smaller image dimension */
120 /* // (and not larger than 256, because otherwise we can get an overflow) */
121 /* size = VS_CLAMP((size/2)*2+1,3,VS_MIN(256,VS_MIN(fi->height/2,fi->width/2))); */
123 /* // we need a different version of these functions for Packed */
124 /* boxblur_hori_C(src, buffer, fi->width, fi->height, fi->strive, size); */
125 /* boxblur_vert_C(buffer, dest, fi->width, fi->height, fi->strive, size); */
127 /* if(localbuffer) */
128 /* vs_free(buffer); */
132 void boxblur_hori_C(unsigned char* dest
, const unsigned char* src
,
133 int width
, int height
, int dest_strive
, int src_strive
, int size
){
137 const unsigned char *start
, *end
; // start and end of kernel
138 unsigned char *current
; // current destination pixel
139 int size2
= size
/2; // size of one side of the kernel without center
140 // #pragma omp parallel for private(acc),schedule(guided,2) (no speedup)
141 for(j
=0; j
< height
; j
++){
142 // for(j=100; j< 101; j++){
143 start
= end
= src
+ j
*src_strive
;
144 current
= dest
+ j
*dest_strive
;
145 // initialize accumulator
146 acc
= (*start
)*(size2
+1); // left half of kernel with first pixel
147 for(k
=0; k
<size2
; k
++){ // right half of kernel
151 // go through the image
152 for(i
=0; i
< width
; i
++){
153 acc
= acc
+ (*end
) - (*start
);
154 if(i
> size2
) start
++;
155 if(i
< width
- size2
- 1) end
++;
156 (*current
) = acc
/size
;
162 void boxblur_vert_C(unsigned char* dest
, const unsigned char* src
,
163 int width
, int height
, int dest_strive
, int src_strive
, int size
){
167 const unsigned char *start
, *end
; // start and end of kernel
168 unsigned char *current
; // current destination pixel
169 int size2
= size
/2; // size of one side of the kernel without center
170 for(i
=0; i
< width
; i
++){
171 start
= end
= src
+ i
;
173 // initialize accumulator
174 acc
= (*start
)*(size2
+1); // left half of kernel with first pixel
175 for(k
=0; k
<size2
; k
++){ // right half of kernel
179 // go through the image
180 for(j
=0; j
< height
; j
++){
181 acc
= acc
- (*start
) + (*end
);
182 if(j
> size2
) start
+=src_strive
;
183 if(j
< height
- size2
- 1) end
+=src_strive
;
185 current
+=dest_strive
;