Merge CV, ver=5.1; ops/methods from HV, and interface from CV where possible
[goodguy/history.git] / cinelerra-5.1 / plugins / histogram_bezier / bistogramconfig.C
1
2 /*
3  * CINELERRA
4  * Copyright (C) 2008 Adam Williams <broadcast at earthling dot net>
5  * 
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.
10  * 
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.
15  * 
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
19  * 
20  */
21
22 #include "clip.h"
23 #include "bistogramconfig.h"
24 #include "units.h"
25
26 #include <math.h>
27
28
29
30
31 HistogramPoint::HistogramPoint()
32  : ListItem<HistogramPoint>()
33 {
34 }
35
36 HistogramPoint::~HistogramPoint()
37 {
38 }
39
40 int HistogramPoint::equivalent(HistogramPoint *src)
41 {
42         return EQUIV(x, src->x) && EQUIV(y, src->y) && EQUIV(gradient, src->gradient);
43 }
44
45
46
47
48 HistogramPoints::HistogramPoints()
49  : List<HistogramPoint>()
50 {
51         insert(0.0,0.0);
52         first->gradient = 1.0;
53         first->xoffset_left = 0.0;
54         first->xoffset_right = 0.05;
55         insert(1.0,1.0);
56         last->gradient = 1.0;  
57         last->xoffset_left = -0.05;
58         last->xoffset_right = 0.0;
59         
60 }
61
62 HistogramPoints::~HistogramPoints()
63 {
64 }
65
66 HistogramPoint* HistogramPoints::insert(float x, float y)
67 {
68         HistogramPoint *current = first;
69
70 // Get existing point after new point
71         while(current)
72         {
73                 if(current->x > x)
74                         break;
75                 else
76                         current = NEXT;
77         }
78
79 // Insert new point before current point
80         HistogramPoint *new_point = new HistogramPoint;
81         if(current)
82         {
83                 insert_before(current, new_point);
84         }
85         else
86 // Append new point to list
87         {
88                 append(new_point);
89         }
90
91         new_point->x = x;
92         new_point->y = y;
93         new_point->xoffset_left = -0.05;
94         new_point->xoffset_right = 0.05;
95
96
97         return new_point;
98 }
99
100 void HistogramPoints::boundaries()
101 {
102         HistogramPoint *current = first;
103         while(current)
104         {
105                 CLAMP(current->x, 0.0, 1.0);
106                 CLAMP(current->y, 0.0, 1.0);
107                 current = NEXT;
108         }
109 }
110
111 int HistogramPoints::equivalent(HistogramPoints *src)
112 {
113         HistogramPoint *current_this = first;
114         HistogramPoint *current_src = src->first;
115         while(current_this && current_src)
116         {
117                 if(!current_this->equivalent(current_src)) return 0;
118                 current_this = current_this->next;
119                 current_src = current_src->next;
120         }
121
122         return !current_this ^ !current_src ? 0 : 1;
123 }
124
125 void HistogramPoints::copy_from(HistogramPoints *src)
126 {
127         while(last)
128                 delete last;
129         HistogramPoint *current = src->first;
130         while(current)
131         {
132                 HistogramPoint *new_point = new HistogramPoint;
133                 new_point->x = current->x;
134                 new_point->y = current->y;
135                 append(new_point);
136                 current = NEXT;
137         }
138 }
139
140 void HistogramPoints::interpolate(HistogramPoints *prev, 
141         HistogramPoints *next,
142         double prev_scale,
143         double next_scale)
144 {
145         HistogramPoint *current = first;
146         HistogramPoint *current_prev = prev->first;
147         HistogramPoint *current_next = next->first;
148
149         while(current && current_prev && current_next)
150         {
151                 current->x = current_prev->x * prev_scale +
152                         current_next->x * next_scale;
153                 current->y = current_prev->y * prev_scale +
154                         current_next->y * next_scale;
155                 current = NEXT;
156                 current_prev = current_prev->next;
157                 current_next = current_next->next;
158         }
159 }
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174 HistogramConfig::HistogramConfig()
175 {
176         reset(1);
177 }
178
179 void HistogramConfig::reset(int do_mode)
180 {
181         reset_points();
182
183         
184         for(int i = 0; i < HISTOGRAM_MODES; i++)
185         {
186                 output_min[i] = 0.0;
187                 output_max[i] = 1.0;
188         }
189
190         if(do_mode) 
191         {
192                 automatic = 0;
193                 threshold = 0.1;
194                 split = 0;
195                 smoothMode = 0;
196         }
197 }
198
199 void HistogramConfig::reset_points()
200 {
201         for(int i = 0; i < HISTOGRAM_MODES; i++)
202         {
203                 while(points[i].last) delete points[i].last;
204                 points[i].insert(0.0,0.0);
205                 points[i].last->gradient = 1.0;
206                 points[i].insert(1.0,1.0);
207                 points[i].last->gradient = 1.0;
208         }
209 }
210
211
212 void HistogramConfig::boundaries()
213 {
214         for(int i = 0; i < HISTOGRAM_MODES; i++)
215         {
216                 points[i].boundaries();
217                 CLAMP(output_min[i], HIST_MIN_INPUT, HIST_MAX_INPUT);
218                 CLAMP(output_max[i], HIST_MIN_INPUT, HIST_MAX_INPUT);
219                 output_min[i] = Units::quantize(output_min[i], PRECISION);
220                 output_max[i] = Units::quantize(output_max[i], PRECISION);
221         }
222         CLAMP(threshold, 0, 1);
223 }
224
225 int HistogramConfig::equivalent(HistogramConfig &that)
226 {
227         for(int i = 0; i < HISTOGRAM_MODES; i++)
228         {
229                 if(!points[i].equivalent(&that.points[i]) ||
230                         !EQUIV(output_min[i], that.output_min[i]) ||
231                         !EQUIV(output_max[i], that.output_max[i])) return 0;
232         }
233
234         if(automatic != that.automatic ||
235                 !EQUIV(threshold, that.threshold)) return 0;
236
237         return 1;
238 }
239
240 void HistogramConfig::copy_from(HistogramConfig &that)
241 {
242         for(int i = 0; i < HISTOGRAM_MODES; i++)
243         {
244                 points[i].copy_from(&that.points[i]);
245                 output_min[i] = that.output_min[i];
246                 output_max[i] = that.output_max[i];
247         }
248
249         automatic = that.automatic;
250         threshold = that.threshold;
251         split = that.split;
252         smoothMode = that.smoothMode;
253 }
254
255 void HistogramConfig::interpolate(HistogramConfig &prev, 
256         HistogramConfig &next, 
257         int64_t prev_frame, 
258         int64_t next_frame, 
259         int64_t current_frame)
260 {
261         double next_scale = (double)(current_frame - prev_frame) / (next_frame - prev_frame);
262         double prev_scale = 1.0 - next_scale;
263
264         for(int i = 0; i < HISTOGRAM_MODES; i++)
265         {
266                 points[i].interpolate(&prev.points[i], &next.points[i], next_scale, prev_scale);
267                 output_min[i] = prev.output_min[i] * prev_scale + next.output_min[i] * next_scale;
268                 output_max[i] = prev.output_max[i] * prev_scale + next.output_max[i] * next_scale;
269         }
270
271         threshold = prev.threshold * prev_scale + next.threshold * next_scale;
272         automatic = prev.automatic;
273         split = prev.split;
274         smoothMode = prev.smoothMode;
275 }
276
277
278 void HistogramConfig::dump()
279 {
280         for(int j = 0; j < HISTOGRAM_MODES; j++)
281         {
282                 printf("HistogramConfig::dump mode=%d\n", j);
283                 HistogramPoints *points = &this->points[j];
284                 HistogramPoint *current = points->first;
285                 while(current)
286                 {
287                         printf("%f,%f ", current->x, current->y);
288                         fflush(stdout);
289                         current = NEXT;
290                 }
291                 printf("\n");
292         }
293 }
294
295
296