4 * Copyright (C) Georg Martius - June 2007
6 * This file is part of transcode, a video stream processing tool
8 * transcode is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation; either version 2, or (at your option)
13 * transcode is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
18 * You should have received a copy of the GNU General Public License
19 * along with GNU Make; see the file COPYING. If not, write to
20 * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
30 #include "transform.h"
32 /***********************************************************************
33 * helper functions to create and operate with transforms.
34 * all functions are non-destructive
37 /* create an initialized transform*/
38 Transform new_transform(double x, double y, double alpha,
39 double zoom, int extra)
50 /* create a zero initialized transform*/
51 Transform null_transform(void)
53 return new_transform(0, 0, 0, 0, 0);
56 /* adds two transforms */
57 Transform add_transforms(const Transform* t1, const Transform* t2)
62 t.alpha = t1->alpha + t2->alpha;
63 t.zoom = t1->zoom + t2->zoom;
68 /* like add_transform but with non-pointer signature */
69 Transform add_transforms_(const Transform t1, const Transform t2)
71 return add_transforms(&t1, &t2);
74 /* subtracts two transforms */
75 Transform sub_transforms(const Transform* t1, const Transform* t2)
80 t.alpha = t1->alpha - t2->alpha;
81 t.zoom = t1->zoom - t2->zoom;
86 /* multiplies a transforms with a scalar */
87 Transform mult_transform(const Transform* t1, double f)
92 t.alpha = t1->alpha * f;
93 t.zoom = t1->zoom * f;
98 /* like mult_transform but with non-pointer signature */
99 Transform mult_transform_(const Transform t1, double f)
101 return mult_transform(&t1,f);
104 /* compares a transform with respect to x (for sort function) */
105 int cmp_trans_x(const void *t1, const void* t2)
107 double a = ((Transform*)t1)->x;
108 double b = ((Transform*)t2)->x;
109 return a < b ? -1 : ( a > b ? 1 : 0 );
112 /* compares a transform with respect to y (for sort function) */
113 int cmp_trans_y(const void *t1, const void* t2)
115 double a = ((Transform*)t1)->y;
116 double b = ((Transform*)t2)->y;
117 return a < b ? -1 : ( a > b ? 1: 0 );
120 /* static int cmp_trans_alpha(const void *t1, const void* t2){ */
121 /* double a = ((Transform*)t1)->alpha; */
122 /* double b = ((Transform*)t2)->alpha; */
123 /* return a < b ? -1 : ( a > b ? 1 : 0 ); */
127 /* compares two double values (for sort function)*/
128 int cmp_double(const void *t1, const void* t2)
130 double a = *((double*)t1);
131 double b = *((double*)t2);
132 return a < b ? -1 : ( a > b ? 1 : 0 );
136 * median_xy_transform: calulcates the median of an array
137 * of transforms, considering only x and y
140 * transforms: array of transforms.
141 * len: length of array
143 * A new transform with x and y beeing the median of
144 * all transforms. alpha and other fields are 0.
150 Transform median_xy_transform(const Transform* transforms, int len)
152 Transform* ts = malloc(sizeof(Transform) * len);
154 memcpy(ts,transforms, sizeof(Transform)*len );
156 qsort(ts, len, sizeof(Transform), cmp_trans_x);
157 t.x = len % 2 == 0 ? ts[half].x : (ts[half].x + ts[half+1].x)/2;
158 qsort(ts, len, sizeof(Transform), cmp_trans_y);
159 t.y = len % 2 == 0 ? ts[half].y : (ts[half].y + ts[half+1].y)/2;
168 * cleanmean_xy_transform: calulcates the cleaned mean of an array
169 * of transforms, considering only x and y
172 * transforms: array of transforms.
173 * len: length of array
175 * A new transform with x and y beeing the cleaned mean
176 * (meaning upper and lower pentile are removed) of
177 * all transforms. alpha and other fields are 0.
183 Transform cleanmean_xy_transform(const Transform* transforms, int len)
185 Transform* ts = malloc(sizeof(Transform) * len);
186 Transform t = null_transform();
187 int i, cut = len / 5;
188 memcpy(ts, transforms, sizeof(Transform) * len);
189 qsort(ts,len, sizeof(Transform), cmp_trans_x);
190 for (i = cut; i < len - cut; i++){ // all but cutted
193 qsort(ts, len, sizeof(Transform), cmp_trans_y);
194 for (i = cut; i < len - cut; i++){ // all but cutted
198 return mult_transform(&t, 1.0 / (len - (2.0 * cut)));
203 * calulcates the cleaned maximum and minimum of an array of transforms,
204 * considerung only x and y
205 * It cuts off the upper and lower x-th percentil
208 * transforms: array of transforms.
209 * len: length of array
210 * percentil: the x-th percentil to cut off
211 * min: pointer to min (return value)
212 * max: pointer to max (return value)
214 * call by reference in min and max
216 * len>0, 0<=percentil<50
218 * only on min and max
220 void cleanmaxmin_xy_transform(const Transform* transforms, int len,
222 Transform* min, Transform* max){
223 Transform* ts = malloc(sizeof(Transform) * len);
224 int cut = len * percentil / 100;
225 memcpy(ts, transforms, sizeof(Transform) * len);
226 qsort(ts,len, sizeof(Transform), cmp_trans_x);
228 max->x = ts[len-cut-1].x;
229 qsort(ts, len, sizeof(Transform), cmp_trans_y);
231 max->y = ts[len-cut-1].y;
237 * media: median of a double array
240 * ds: array of values
241 * len: length of array
243 * the median value of the array
244 * Preconditions: len>0
245 * Side effects: ds will be sorted!
247 double median(double* ds, int len)
250 qsort(ds,len, sizeof(double), cmp_double);
251 return len % 2 == 0 ? ds[half] : (ds[half] + ds[half+1])/2;
255 * mean: mean of a double array
258 * ds: array of values
259 * len: length of array
260 * Return value: the mean value of the array
261 * Preconditions: len>0
264 double mean(const double* ds, int len)
268 for (i = 0; i < len; i++)
274 * cleanmean: mean with cutted upper and lower pentile
277 * ds: array of values
278 * len: length of array
279 * len: length of array
280 * minimum: minimal value (after cleaning) if not NULL
281 * maximum: maximal value (after cleaning) if not NULL
283 * the mean value of the array without the upper
284 * and lower pentile (20% each)
285 * and lower pentile (20% each)
286 * and minimum and maximum without the pentiles
287 * Preconditions: len>0
288 * Side effects: ds will be sorted!
290 double cleanmean(double* ds, int len, double* minimum, double* maximum)
295 qsort(ds, len, sizeof(double), cmp_double);
296 for (i = cut; i < len - cut; i++) { // all but first and last
302 *maximum = ds[len-cut-1];
303 return sum / (len - (2.0 * cut));
309 * c-file-style: "stroustrup"
310 * c-file-offsets: ((case-label . *) (statement-case-intro . *))
311 * indent-tabs-mode: nil
314 * vim: expandtab shiftwidth=4: