Implement focus statistic in d3::scene::view_filter_focus().
[Ale.git] / d2 / render / incremental.h
blobe2b8bae79eb9267a1e67d339270174ef868a186d
1 // Copyright 2002, 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
21 #ifndef __incremental_h__
22 #define __incremental_h__
24 #include "invariant.h"
25 #include "../render.h"
26 #include "../transformation.h"
27 #include "../image.h"
28 #include "../point.h"
31 * Class for incremental renderers.
34 class incremental : public render {
35 protected:
36 image_weighted_avg *accum_image;
37 invariant *inv;
40 * Set extents of image and weight according to a new image to be
41 * merged. This function should remove only superfluous undefined
42 * areas.
45 void set_extents_by_map(unsigned int frame_num, transformation t) {
47 assert (accum_image != NULL);
49 ale_pos extend_offset_i = accum_image->offset()[0];
50 ale_pos extend_offset_j = accum_image->offset()[1];
52 int extend_top = 0;
53 int extend_bottom = 0;
54 int extend_left = 0;
55 int extend_right = 0;
57 double zero = 0;
58 double infinity = 1 / zero;
60 assert (!finite(infinity));
61 assert (!isnan(infinity));
62 assert (infinity > 0);
64 point min, max;
66 min[0] = min[1] = infinity;
67 max[0] = max[1] = -infinity;
69 for (unsigned int i = 0; i < t.unscaled_height(); i++)
70 for (unsigned int j = 0; j < t.unscaled_width(); j++) {
71 point p = t.transform_unscaled(point(i, j));
73 if (is_excluded(accum_image->offset(), p, frame_num))
74 continue;
76 if (p[0] < min[0]) {
77 min[0] = p[0];
79 if (p[0] > max[0]) {
80 max[0] = p[0];
82 if (p[1] < min[1]) {
83 min[1] = p[1];
85 if (p[1] > max[1]) {
86 max[1] = p[1];
90 if (!finite(max[0])
91 || !finite(max[1])
92 || !finite(min[0])
93 || !finite(min[1]))
94 return;
96 extend_top = (int) ceil(extend_offset_i - floor(min[0]));
97 extend_left = (int) ceil(extend_offset_j - floor(min[1]));
98 extend_bottom = (int) ceil(ceil(max[0]) - (accum_image->height() - 1 + extend_offset_i));
99 extend_right = (int) ceil(ceil(max[1]) - (accum_image->width() - 1 + extend_offset_j));
101 accum_image->extend(extend_top, extend_bottom,
102 extend_left, extend_right);
105 void increase_extents_by_map(unsigned int frame_num, transformation t) {
107 assert (accum_image != NULL);
109 ale_pos extend_offset_i = accum_image->offset()[0];
110 ale_pos extend_offset_j = accum_image->offset()[1];
112 int extend_top = 0;
113 int extend_bottom = 0;
114 int extend_left = 0;
115 int extend_right = 0;
117 double zero = 0;
118 double infinity = 1 / zero;
120 assert (!finite(infinity));
121 assert (!isnan(infinity));
122 assert (infinity > 0);
124 point min, max;
126 min[0] = min[1] = infinity;
127 max[0] = max[1] = -infinity;
129 for (unsigned int i = 0; i < t.unscaled_height(); i++)
130 for (unsigned int j = 0; j < t.unscaled_width(); j++) {
131 point p = t.transform_unscaled(point(i, j));
133 if (is_excluded(point(0, 0), p, frame_num))
134 continue;
136 if (p[0] < min[0]) {
137 min[0] = p[0];
139 if (p[0] > max[0]) {
140 max[0] = p[0];
142 if (p[1] < min[1]) {
143 min[1] = p[1];
145 if (p[1] > max[1]) {
146 max[1] = p[1];
150 if (!finite(max[0])
151 || !finite(max[1])
152 || !finite(min[0])
153 || !finite(min[1]))
154 return;
156 if (ceil(min[0]) < extend_offset_i)
157 extend_top = (int) ceil(extend_offset_i - floor(min[0]));
158 if (ceil(min[1]) < extend_offset_j)
159 extend_left = (int) ceil(extend_offset_j - floor(min[1]));
160 if (floor(max[0]) > accum_image->height() - 1 + extend_offset_i)
161 extend_bottom = (int) ceil(ceil(max[0]) - (accum_image->height() - 1 + extend_offset_i));
162 if (floor(max[1]) > accum_image->width() - 1 + extend_offset_j)
163 extend_right = (int) ceil(ceil(max[1]) - (accum_image->width() - 1 + extend_offset_j));
165 accum_image->extend(extend_top, extend_bottom,
166 extend_left, extend_right);
170 * Merge operation for a single pixel in the accumulated image.
172 void _merge_pixel(int frame, const image *delta, transformation t, int i, int j, const filter::ssfe *_ssfe) {
174 if (_ssfe->ex_is_honored() && is_excluded(i, j, frame))
175 return;
177 if (accum_image->accumulate_norender(i, j))
178 return;
181 * Pixel value to be merged, and the associated
182 * confidence
185 pixel value, confidence;
187 _ssfe->filtered(i, j, frame, &value, &confidence);
189 accum_image->accumulate(i, j, frame, value, confidence);
193 * Merge part of a delta frame with part of the accumulated image using
194 * the specified transformation.
196 void
197 _merge(int frame, const image *delta, transformation t) {
199 point offset = accum_image->offset();
201 assert (accum_image != NULL);
202 assert (delta != NULL);
204 const filter::ssfe *_ssfe = inv->ssfe();
206 _ssfe->set_parameters(t, delta, offset);
208 for (unsigned int i = 0; i < accum_image->height(); i++)
209 for (unsigned int j = 0; j < accum_image->width(); j++) {
211 #if 0
213 * This is untested, but it should work, and is less
214 * verbose than what follows.
217 _merge_pixel(frame, delta, t, i, j, _ssfe);
218 #else
220 if (_ssfe->ex_is_honored() && is_excluded(i, j, frame))
221 continue;
223 if (accum_image->accumulate_norender(i, j))
224 continue;
227 * Pixel value to be merged, and the associated
228 * confidence
231 pixel value, confidence;
233 _ssfe->filtered(i, j, frame, &value, &confidence);
235 accum_image->accumulate(i, j, frame, value, confidence);
236 #endif
240 public:
243 * Constructor
245 incremental(invariant *inv) {
246 this->inv = inv;
247 accum_image = NULL;
251 * Invariant
253 const invariant *get_invariant() const {
254 return inv;
258 * Result of rendering.
261 virtual const image *get_image() {
262 assert (accum_image != NULL);
263 return accum_image->get_colors();
267 * Definition map. Unit-depth image whose pixels are nonzero where
268 * the image is defined.
271 virtual const image *get_defined() {
272 assert (accum_image != NULL);
273 return accum_image->get_weights();
277 * Perform the current rendering step.
279 virtual void step() {
280 assert (get_step() >= -1);
281 if (get_step() == 0) {
282 transformation t = align::of(0);
284 const image *im = image_rw::open(0);
286 ui::get()->rendering();
288 if (inv->is_median())
289 accum_image = new image_weighted_median(1, 1, 3);
290 else
291 accum_image = new image_weighted_simple(1, 1, 3, inv);
293 set_extents_by_map(0, t);
295 _merge(0, im, t);
297 image_rw::close(0);
298 } else if (align::match(get_step())) {
299 transformation t = align::of(get_step());
300 ui::get()->rendering();
301 if (is_extend())
302 increase_extents_by_map(get_step(), t);
303 const image *im = image_rw::open(get_step());
304 _merge(get_step(), im, t);
305 image_rw::close(get_step());
310 virtual void init_point_renderer(unsigned int h, unsigned int w, unsigned int d) {
311 assert(accum_image == NULL);
313 if (inv->is_median())
314 accum_image = new image_weighted_median(h, w, d);
315 else
316 accum_image = new image_weighted_simple(h, w, d, inv);
318 assert(accum_image);
321 virtual void point_render(unsigned int i, unsigned int j, unsigned int f, transformation t) {
322 const image *im = d2::image_rw::get_open(f);
324 const filter::ssfe *_ssfe = inv->ssfe();
326 _ssfe->set_parameters(t, im, accum_image->offset());
327 _merge_pixel(f, im, t, i, j, _ssfe);
330 virtual void finish_point_rendering() {
331 return;
334 void free_memory() {
335 delete accum_image;
336 accum_image = NULL;
340 #endif