ale/d2/image_weighted_simple.h
2022-07-30 14:46:04 -03:00

206 lines
5.1 KiB
C++

// Copyright 2002, 2003, 2004 David Hilvert <dhilvert@auricle.dyndns.org>,
// <dhilvert@ugcs.caltech.edu>
/* This file is part of the Anti-Lamenessing Engine.
The Anti-Lamenessing Engine is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 3 of the License, or
(at your option) any later version.
The Anti-Lamenessing Engine is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with the Anti-Lamenessing Engine; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
/*
* image_weighted_simple.h: Image representing a weighted average of inputs.
* Covers simple cases that require space constant with frame count.
*/
#ifndef __image_weighted_simple_h__
#define __image_weighted_simple_h__
#include "image_weighted_avg.h"
#include "render/invariant.h"
class image_weighted_simple : public image_weighted_avg {
private:
invariant *inv;
image *colors;
image *weights;
public:
image_weighted_simple (unsigned int dimy, unsigned int dimx, unsigned int
depth, invariant *inv, const char *name = "anonymous")
: image_weighted_avg(dimy, dimx, depth, name) {
colors = new_image_ale_real(dimy, dimx, depth);
weights = new_image_ale_real(dimy, dimx, depth);
this->inv = inv;
}
virtual ~image_weighted_simple() {
delete colors;
delete weights;
}
/*
* Extend the image area to the top, bottom, left, and right,
* initializing the new image areas with black pixels. Negative values
* shrink the image.
*/
image *_extend(int top, int bottom, int left, int right) {
extend(&colors, top, bottom, left, right);
extend(&weights, top, bottom, left, right);
_dimx = colors->width();
_dimy = colors->height();
_offset = colors->offset();
return NULL;
}
/*
* Pre-transformation check for whether an area should be skipped.
* Takes image weights as an argument.
*/
int accumulate_norender(int i, int j) {
/*
* Initial value
*/
if (inv->is_first() && weights->get_chan(i, j, 0) != 0)
return 1;
/*
* Weight limit satisfied
*/
if (inv->is_avgf()
&& weights->get_chan(i, j, 0) > inv->get_param()
&& weights->get_chan(i, j, 1) > inv->get_param()
&& weights->get_chan(i, j, 2) > inv->get_param())
return 1;
return 0;
}
/*
* Accumulate pixels
*/
void accumulate(int i, int j, int f, pixel new_value, pixel new_weight) {
/*
* Perform operations separately for each channel
*/
for (unsigned int k = 0; k < 3; k++) {
/*
* Cases independent of the old pixel value and weight
* for which the update can be ignored.
*/
if (!inv->is_avgx()
&& new_weight[k] < render::get_wt())
continue;
/*
* Cases independent of the old pixel value and weight for which
* previous pixel values can be ignored.
*/
if (inv->is_last() && new_weight[k] >= render::get_wt()) {
colors->set_chan(i, j, k, new_value[k]);
weights->set_chan(i, j, k, new_weight[k]);
continue;
}
/*
* Obtain the old pixel weight.
*/
ale_real old_weight = weights->get_chan(i, j, k);
/*
* Cases independent of the old pixel value for which the
* update can be ignored.
*/
if (old_weight >= render::get_wt()
&& inv->is_first())
continue;
if (inv->is_avgf()
&& old_weight >= inv->get_param())
continue;
/*
* Cases independent of the old pixel value for which previous
* pixel values can be ignored.
*/
if (old_weight == 0
|| (old_weight < render::get_wt()
&& !inv->is_avgx())) {
weights->set_chan(i, j, k, new_weight[k]);
colors ->set_chan(i, j, k, new_value[k]);
continue;
}
if (inv->is_max()) {
/*
* Cases in which the old pixel value can be ignored
*/
if (new_value[k] * (ale_real) weights->get_chan(i, j, k)
> (ale_real) colors->get_chan(i, j, k) * new_weight[k]) {
weights->set_chan(i, j, k, new_weight[k]);
colors-> set_chan(i, j, k, new_value[k]);
}
continue;
} else if (inv->is_min()) {
/*
* Cases in which the old pixel value can be ignored
*/
if (new_value[k] * (ale_real) weights->get_chan(i, j, k)
< (ale_real) colors->get_chan(i, j, k) * new_weight[k]) {
weights->set_chan(i, j, k, new_weight[k]);
colors-> set_chan(i, j, k, new_value[k]);
}
continue;
}
/*
* Update weight and color values.
*/
weights->set_chan(i, j, k, weights->get_chan(i, j, k) + new_weight[k]);
colors->set_chan(i, j, k, colors->get_chan(i, j, k) + new_value[k]);
}
}
spixel get_pixel(unsigned int y, unsigned int x) const {
return (pixel) colors->get_pixel(y, x) / (pixel) weights->get_pixel(y, x);
}
image *get_weights() {
return weights;
}
image *get_colors() {
assert(0);
return colors;
}
};
#endif