4 * Copyright (C) 2008 Adam Williams <broadcast at earthling dot net>
6 * This program 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 * This program 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 this program; if not, write to the Free Software
18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
23 #include "bistogramconfig.h"
29 HistogramPoint::HistogramPoint()
30 : ListItem<HistogramPoint>()
39 HistogramPoint::~HistogramPoint()
43 int HistogramPoint::equivalent(HistogramPoint *src)
45 return EQUIV(x, src->x) && EQUIV(y, src->y) &&
46 EQUIV(xoffset_left, src->xoffset_left) &&
47 EQUIV(xoffset_right, src->xoffset_right) &&
48 EQUIV(gradient, src->gradient);
51 void HistogramPoint::copy_from(HistogramPoint *that)
53 x = that->x; y = that->y;
54 xoffset_left = that->xoffset_left;
55 xoffset_right = that->xoffset_right;
56 gradient = that->gradient;
61 HistogramPoints::HistogramPoints()
62 : List<HistogramPoint>()
67 HistogramPoints::~HistogramPoints()
71 void HistogramPoints::clear()
73 while( last ) delete last;
75 first->gradient = 1.0;
76 first->xoffset_left = 0.0;
77 first->xoffset_right = 0.05;
80 last->xoffset_left = -0.05;
81 last->xoffset_right = 0.0;
84 HistogramPoint* HistogramPoints::insert(float x, float y)
86 HistogramPoint *current = first;
88 // Get existing point after new point
90 if( current->x > x ) break;
94 // Insert new point before current point
95 HistogramPoint *new_point = new HistogramPoint;
97 insert_before(current, new_point);
106 void HistogramPoints::boundaries()
108 HistogramPoint *current = first;
110 CLAMP(current->x, 0.0, 1.0);
111 CLAMP(current->y, 0.0, 1.0);
116 int HistogramPoints::equivalent(HistogramPoints *src)
118 HistogramPoint *current_this = first;
119 HistogramPoint *current_src = src->first;
120 while( current_this && current_src ) {
121 if(!current_this->equivalent(current_src)) return 0;
122 current_this = current_this->next;
123 current_src = current_src->next;
126 return current_this || current_src ? 0 : 1;
129 void HistogramPoints::copy_from(HistogramPoints *src)
133 HistogramPoint *current = src->first;
135 HistogramPoint *new_point = new HistogramPoint;
136 new_point->copy_from(current);
142 int HistogramPoints::cmprx(HistogramPoint *ap, HistogramPoint *bp)
144 return ap->x < bp->x ? -1 : ap->x == bp->x ? 0 : 1;
147 void HistogramPoints::interpolate(HistogramPoints *prev, HistogramPoints *next,
148 double prev_scale, double next_scale)
150 HistogramPoint *current_prev = prev->first;
151 HistogramPoint *current_next = next->first;
153 HistogramPoint *current = first;
154 while( current_prev || current_next ) {
156 current = new HistogramPoint;
159 if( !current_next ) {
160 current->copy_from(current_prev);
161 current_prev = current_prev->next;
163 else if( !current_prev ) {
164 current->copy_from(current_next);
165 current_next = current_next->next;
168 current->x = current_prev->x * prev_scale +
169 current_next->x * next_scale;
170 current->y = current_prev->y * prev_scale +
171 current_next->y * next_scale;
172 current->gradient = current_prev->gradient * prev_scale +
173 current_next->gradient * next_scale;
174 current->xoffset_left = current_prev->xoffset_left * prev_scale +
175 current_next->xoffset_left * next_scale;
176 current->xoffset_right = current_prev->xoffset_right * prev_scale +
177 current_next->xoffset_right * next_scale;
178 current_prev = current_prev->next;
179 current_next = current_next->next;
181 current = current->next;
185 HistogramPoint *next_point = current->next;
186 delete current; current = next_point;
192 HistogramConfig::HistogramConfig()
197 void HistogramConfig::reset(int do_mode)
200 for( int i = 0; i < HISTOGRAM_MODES; i++ ) {
213 void HistogramConfig::reset_points()
215 for( int i=0; i<HISTOGRAM_MODES; ++i )
220 void HistogramConfig::boundaries()
222 for( int i=0; i<HISTOGRAM_MODES; ++i ) {
223 points[i].boundaries();
224 CLAMP(output_min[i], HIST_MIN_INPUT, HIST_MAX_INPUT);
225 CLAMP(output_max[i], HIST_MIN_INPUT, HIST_MAX_INPUT);
226 output_min[i] = Units::quantize(output_min[i], PRECISION);
227 output_max[i] = Units::quantize(output_max[i], PRECISION);
229 CLAMP(threshold, 0, 1);
232 int HistogramConfig::equivalent(HistogramConfig &that)
234 for( int i=0; i<HISTOGRAM_MODES; ++i ) {
235 if( !points[i].equivalent(&that.points[i]) ||
236 !EQUIV(output_min[i], that.output_min[i]) ||
237 !EQUIV(output_max[i], that.output_max[i]) ) return 0;
240 if( automatic != that.automatic ||
241 split != that.split ||
242 smoothMode != that.smoothMode ||
243 !EQUIV(threshold, that.threshold) ) return 0;
248 void HistogramConfig::copy_from(HistogramConfig &that)
250 for( int i=0; i<HISTOGRAM_MODES; ++i ) {
251 points[i].copy_from(&that.points[i]);
252 output_min[i] = that.output_min[i];
253 output_max[i] = that.output_max[i];
256 automatic = that.automatic;
257 threshold = that.threshold;
259 smoothMode = that.smoothMode;
262 void HistogramConfig::interpolate(HistogramConfig &prev, HistogramConfig &next,
263 int64_t prev_frame, int64_t next_frame, int64_t current_frame)
265 double next_scale = (double)(current_frame - prev_frame) / (next_frame - prev_frame);
266 double prev_scale = 1.0 - next_scale;
268 for( int i=0; i<HISTOGRAM_MODES; ++i ) {
269 points[i].interpolate(&prev.points[i], &next.points[i], prev_scale, next_scale);
270 output_min[i] = prev.output_min[i] * prev_scale + next.output_min[i] * next_scale;
271 output_max[i] = prev.output_max[i] * prev_scale + next.output_max[i] * next_scale;
274 threshold = prev.threshold * prev_scale + next.threshold * next_scale;
275 automatic = prev.automatic;
277 smoothMode = prev.smoothMode;
281 void HistogramConfig::dump()
283 printf("HistogramConfig::dump: automatic=%d, threshold=%f, split=%d, smoothMode=%d\n",
284 automatic, threshold, split, smoothMode);
285 static const char *mode_name[] = { "red","grn","blu","val" };
286 for( int j=0; j<HISTOGRAM_MODES; ++j ) {
287 printf("mode[%s]:\n", mode_name[j]);
288 HistogramPoints *points = &this->points[j];
289 HistogramPoint *current = points->first;
291 printf("%f,%f (@%f l%f,r%f)\n", current->x, current->y,
292 current->gradient, current->xoffset_left, current->xoffset_right);