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
22 * usm.h: A render subclass that implements an unsharp mask
23 * postprocessing algorithm.
30 #include "../render.h"
33 class usm
: public render
{
39 const image
*input_image
;
40 const image
*input_defined
;
41 ale_real scale_factor
;
42 ale_real usm_multiplier
;
43 psf
*lresponse
, *nlresponse
;
47 * USM value for point (i, j).
49 pixel
_usm(int i
, int j
, const image
*im
) {
53 ale_real d
= scale_factor
/ 2;
58 * Convolve with the linear filter, iterating over pixels
59 * according to the filter support, and tracking contribution
60 * weights in the variable WEIGHT.
63 for (int ii
= (int) floor(i
- d
+ lresponse
->min_i());
64 ii
<= ceil(i
+ d
+ lresponse
->max_i()); ii
++)
65 for (int jj
= (int) floor(j
- d
+ lresponse
->min_j());
66 jj
<= ceil(j
+ d
+ lresponse
->max_j()); jj
++) {
68 ale_real top
= ii
- d
;
69 ale_real bot
= ii
+ d
;
70 ale_real lef
= jj
- d
;
71 ale_real rig
= jj
+ d
;
74 && ii
< (int) im
->height()
76 && jj
< (int) im
->width()
77 && input_defined
->get_pixel(ii
, jj
)[0]) {
79 class psf::psf_result r
= (*lresponse
)((top
- i
) / scale_factor
,
80 (bot
- i
) / scale_factor
,
81 (lef
- j
) / scale_factor
,
82 (rig
- j
) / scale_factor
);
87 * Convolve with the non-linear filter,
88 * iterating over pixels according to the
89 * filter support, and tracking contribution
90 * weights in the variable WWEIGHT.
92 * Note: This approach is efficient
93 * space-wise, but inefficient timewise. There
94 * is probably a better approach to this.
97 pixel
rresult(0, 0, 0), wweight(0, 0, 0);
99 for (int iii
= (int) floor(ii
- d
+ nlresponse
->min_i());
100 iii
<= ceil(ii
+ d
+ lresponse
->max_i()); iii
++)
101 for (int jjj
= (int) floor(jj
- d
+ nlresponse
->min_j());
102 jjj
<= ceil(jj
+ d
+ lresponse
->max_j()); jjj
++) {
104 ale_real top
= iii
- d
;
105 ale_real bot
= iii
+ d
;
106 ale_real lef
= jjj
- d
;
107 ale_real rig
= jjj
+ d
;
110 && iii
< (int) im
->height()
112 && jjj
< (int) im
->width()
113 && input_defined
->get_pixel(iii
, jjj
)[0]) {
115 class psf::psf_result r
= (*nlresponse
)((top
- ii
) / scale_factor
,
116 (bot
- ii
) / scale_factor
,
117 (lef
- jj
) / scale_factor
,
118 (rig
- jj
) / scale_factor
);
120 wweight
+= r
.weight();
121 rresult
+= r(exp
->unlinearize(im
->get_pixel(iii
, jjj
)));
125 result
+= r(exp
->linearize(rresult
/ wweight
));
127 result
+= r(im
->get_pixel(ii
, jj
));
130 weight
+= r
.weight();
136 result
= im
->get_pixel(i
, j
) - result
;
138 if (finite(result
[0])
140 && finite(result
[2]))
143 return pixel(0, 0, 0);
147 assert (done_image
->height() == input_image
->height());
148 assert (done_image
->width() == input_image
->width());
149 assert (done_image
->depth() == input_image
->depth());
151 for (unsigned int i
= 0; i
< done_image
->height(); i
++)
152 for (unsigned int j
= 0; j
< done_image
->width(); j
++) {
154 if (!input_defined
->get_pixel(i
, j
)[0])
157 done_image
->set_pixel(i
, j
,
158 input_image
->get_pixel(i
, j
)
160 * _usm(i
, j
, input_image
));
166 usm(render
*input
, ale_real scale_factor
, ale_real usm_multiplier
, int _inc
,
167 psf
*lresponse
, psf
*nlresponse
, exposure
*exp
) {
171 this->scale_factor
= scale_factor
;
172 this->usm_multiplier
= usm_multiplier
;
173 this->lresponse
= lresponse
;
174 this->nlresponse
= nlresponse
;
178 const image
*get_image() {
182 return input
->get_image();
185 const image
*get_defined() {
186 return input
->get_defined();
199 fprintf(stderr
, "Applying USM");
201 done_image
= input
->get_image()->clone("USM done_image");
202 input_image
= input
->get_image();
203 input_defined
= input
->get_defined();
207 image_rw::output(done_image
);
209 fprintf(stderr
, ".\n");