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"
31 * Class for incremental renderers.
34 class incremental
: public render
{
36 image_weighted_avg
*accum_image
;
40 * Set extents of image and weight according to a new image to be
41 * merged. This function should remove only superfluous undefined
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];
53 int extend_bottom
= 0;
58 double infinity
= 1 / zero
;
60 assert (!finite(infinity
));
61 assert (!isnan(infinity
));
62 assert (infinity
> 0);
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
))
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];
113 int extend_bottom
= 0;
115 int extend_right
= 0;
118 double infinity
= 1 / zero
;
120 assert (!finite(infinity
));
121 assert (!isnan(infinity
));
122 assert (infinity
> 0);
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
))
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
))
177 if (accum_image
->accumulate_norender(i
, j
))
181 * Pixel value to be merged, and the associated
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.
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
++) {
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
);
220 if (_ssfe
->ex_is_honored() && is_excluded(i
, j
, frame
))
223 if (accum_image
->accumulate_norender(i
, j
))
227 * Pixel value to be merged, and the associated
231 pixel value
, confidence
;
233 _ssfe
->filtered(i
, j
, frame
, &value
, &confidence
);
235 accum_image
->accumulate(i
, j
, frame
, value
, confidence
);
245 incremental(invariant
*inv
) {
253 const invariant
*get_invariant() const {
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);
291 accum_image
= new image_weighted_simple(1, 1, 3, inv
);
293 set_extents_by_map(0, t
);
298 } else if (align::match(get_step())) {
299 transformation t
= align::of(get_step());
300 ui::get()->rendering();
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
);
316 accum_image
= new image_weighted_simple(h
, w
, d
, inv
);
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() {