TODO: add entries for centralizing licensing and authorship information and incorpora...
[Ale.git] / d2 / vise / ma.h
blobe421cd21e71afbe5305d1d08dc9088455718ebbd
1 // Copyright 2004 David Hilvert <dhilvert@auricle.dyndns.org>,
2 // <dhilvert@ugcs.caltech.edu>
4 /* This file is part of the Anti-Lamenessing Engine.
6 The Anti-Lamenessing Engine is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 2 of the License, or
9 (at your option) any later version.
11 The Anti-Lamenessing Engine is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
16 You should have received a copy of the GNU General Public License
17 along with the Anti-Lamenessing Engine; if not, write to the Free Software
18 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
22 * ma.h: A video stabilizer that uses moving averages to calculate
23 * transformations.
26 #ifndef __ma_h__
27 #define __ma_h__
29 #include "../vise.h"
30 #include "../image.h"
31 #include "../point.h"
34 * Stabilize using moving averages.
36 * For a given frame x, the moving averages are calculated over frames
37 * ranging from x - r to x + r, where r is the specified RANGE size.
40 class ma : public vise {
41 unsigned int range;
42 public:
43 ma(render *r, unsigned int range, const char *prefix, const char *suffix,
44 ale_real scale_factor) : vise(r, prefix, suffix, scale_factor) {
45 r->extend_queue(range);
46 this->range = range;
50 * Accept an image for rendering.
53 void render_frame(unsigned int frame_number) {
55 const image *im = r->get_image(frame_number);
56 int replace = 0;
57 int replace_ex = 0;
58 const filter::scaled_filter *scf = NULL;
59 unsigned int rx_count = render::get_rx_count();
60 const exclusion *rx_parameters = render::get_rx_parameters();
61 int rx_show = render::is_rx_show();
64 * Determine, for single-invariant chains, whether replacement
65 * is occurring, and, if so, determine whether we are honoring
66 * exclusion regions.
68 if (typeid(*r) == typeid(incremental)
69 && ((incremental *)r)->get_invariant()->is_last()) {
70 scf = ((incremental *)r)->get_invariant()->ssfe()->get_scaled_filter();
71 if (scf->is_coarse() && scf->get_filter()->support() >= 1) {
72 replace = 1;
73 replace_ex = ((incremental *)r)->get_invariant()->ssfe()->ex_is_honored();
78 * Calculate the parameters for the desired
79 * transformation.
82 point p[4] = {
83 point(0, 0),
84 point(0, 0),
85 point(0, 0),
86 point(0, 0)
89 ale_pos bd[BARREL_DEGREE] = {0, /* ... */};
90 unsigned int bd_count = BARREL_DEGREE;
91 int frame_count = 0;
93 for (int f = frame_number - range; f <= (int) (frame_number + range); f++) {
94 if (f < 0
95 || f >= (int) image_rw::count())
96 continue;
98 frame_count++;
100 transformation t = align::of(f);
102 for (unsigned int i = 0; i < 4; i++)
103 p[i] = p[i] + t.transform_scaled(point((i == 1 || i == 2) ? t.scaled_height() : 0,
104 (i > 1) ? t.scaled_width() : 0));
106 if (t.bd_count() < bd_count)
107 bd_count = t.bd_count();
109 for (unsigned int i = 0; i < bd_count; i++)
110 bd[i] += t.bd_get(i);
113 for (unsigned int i = 0; i < 4; i++)
114 p[i] = p[i] / (ale_real) frame_count;
116 for (unsigned int i = 0; i < bd_count; i++)
117 bd[i] /= frame_count;
120 * Generate the desired transformation.
122 transformation t = align::of(frame_number);
123 transformation s = t;
124 unsigned int new_height = (unsigned int)
125 floor(s.unscaled_height() * scale_factor);
126 unsigned int new_width = (unsigned int)
127 floor(s.unscaled_width() * scale_factor);
128 s.set_domain(new_height, new_width);
129 s.gpt_set(p);
130 s.bd_set(bd_count, bd);
132 image *rendered = new image_ale_real(new_height, new_width, 3);
134 if (replace) {
135 const image *replace_image = NULL;
136 replace_image = image_rw::open(frame_number);
137 scf->set_parameters(t, s, replace_image);
140 for (unsigned int i = 0; i < rendered->height(); i++)
141 for (unsigned int j = 0; j < rendered->width(); j++) {
142 point unoffset_p = s.transform_scaled(point(i, j));
143 point p = unoffset_p - im->offset();
144 // point p_replace = t.inverse_transform(s(point(i, j)));
145 double shading = 1;
148 if (rx_show || (replace && replace_ex))
149 for (unsigned int param = 0; param < rx_count; param++) {
150 if (rx_parameters[param].type == exclusion::RENDER
151 && unoffset_p[0] >= rx_parameters[param].x[0]
152 && unoffset_p[0] <= rx_parameters[param].x[1]
153 && unoffset_p[1] >= rx_parameters[param].x[2]
154 && unoffset_p[1] <= rx_parameters[param].x[3]
155 && frame_number >= (unsigned) rx_parameters[param].x[4]
156 && frame_number <= (unsigned) rx_parameters[param].x[5])
157 shading *= 0.5;
159 if (rx_parameters[param].type == exclusion::FRAME
160 && i >= rx_parameters[param].x[0] * scale_factor
161 && i <= rx_parameters[param].x[1] * scale_factor
162 && j >= rx_parameters[param].x[2] * scale_factor
163 && j <= rx_parameters[param].x[3] * scale_factor
164 && frame_number >= (unsigned) rx_parameters[param].x[4]
165 && frame_number <= (unsigned) rx_parameters[param].x[5])
166 shading *= 0.5;
169 if (shading < 1 && !rx_show && replace && replace_ex)
170 continue;
172 if (replace) {
173 pixel value, weight;
175 scf->filtered(i, j, &value, &weight, replace_ex, frame_number);
177 if (weight.min_norm() > 0) {
178 rendered->set_pixel(i, j, shading * value);
179 continue;
184 if (p[0] >= 0
185 && p[0] <= im->height() - 1
186 && p[1] >= 0
187 && p[1] <= im->width() - 1)
188 rendered->set_pixel(i, j, shading * im->get_bl(p));
189 else
190 rendered->set_pixel(i, j, pixel(0, 0, 0));
193 if (replace)
194 image_rw::close(frame_number);
196 write_frame(rendered, frame_number);
198 delete rendered;
202 * Report the frame lag for this stabilizer.
205 unsigned int lag() {
206 return range;
210 #endif