Imported Debian version 1.0~trusty
[deb_vid.stab.git] / src / boxblur.c
CommitLineData
80f575fc
DM
1/*
2 * boxblur.c
3 *
4 * Copyright (C) Georg Martius - July 2010
5 * georg dot martius at web dot de
6 *
7 * This file is part of vid.stab video stabilization library
8 *
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.
13 *
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.
18 *
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.
22 *
23 */
24
25#include "boxblur.h"
26#include "vidstabdefines.h"
27
28
29void boxblur_hori_C(unsigned char* dest, const unsigned char* src,
30 int width, int height, int dest_strive, int src_strive, int size);
31void boxblur_vert_C(unsigned char* dest, const unsigned char* src,
32 int width, int height, int dest_strive, int src_strive, int size);
33
34/*
35 The algorithm:
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.
40
41 horizontal and vertical 1D boxfilters can be used
42
43 accumulator: acc = acc + new - old, pixel = acc/size
44*/
45
46void boxblurPlanar(VSFrame* dest, const VSFrame* src,
47 VSFrame* buffer, const VSFrameInfo* fi,
48 unsigned int size, BoxBlurColorMode colormode){
49 int localbuffer=0;
50 int size2;
51 if(size<2){
52 if(dest!=src)
53 vsFrameCopy(dest,src,fi);
54 return;
55 }
56 VSFrame buf;
57 if(buffer==0){
58 vsFrameAllocate(&buf,fi);
59 localbuffer=1;
60 }else{
61 buf = *buffer;
62 }
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);
66
67 // luminance
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);
72
73 size2 = size/2+1; // odd and larger than 0
74 int plane;
75 switch (colormode){
76 case BoxBlurColor:
77 // color
78 if(size2>1){
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);
88 }
89 }
90 break;
91 case BoxBlurKeepColor:
92 // copy both color channels
93 for(plane=1; plane<fi->planes; plane++){
94 vsFrameCopyPlane(dest, src, fi, plane);
95 }
96 case BoxBlurNoColor: // do nothing
97 default:
98 break;
99 }
100
101 if(localbuffer)
102 vsFrameFree(&buf);
103}
104
105/* /\* */
106/* The algorithm: */
107/* see boxblurPlanar but here we for Packed */
108
109/* we add the 3 bytes of one pixel as if they where one number */
110/* *\/ */
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; */
115/* if(buffer==0){ */
116/* buffer=(unsigned char*) vs_malloc(fi->framesize); */
117/* localbuffer=1; */
118/* } */
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))); */
122
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); */
126
127/* if(localbuffer) */
128/* vs_free(buffer); */
129/* } */
130
131
132void boxblur_hori_C(unsigned char* dest, const unsigned char* src,
133 int width, int height, int dest_strive, int src_strive, int size){
134
135 int i,j,k;
136 unsigned int acc;
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
148 acc+=(*end);
149 end++;
150 }
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;
157 current++;
158 }
159 }
160}
161
162void boxblur_vert_C(unsigned char* dest, const unsigned char* src,
163 int width, int height, int dest_strive, int src_strive, int size){
164
165 int i,j,k;
166 int acc;
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;
172 current = dest + 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
176 acc+=(*end);
177 end+=src_strive;
178 }
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;
184 *current = acc/size;
185 current+=dest_strive;
186 }
187 }
188}