b3befe77f387bdc50fa4dc0d8b7a570fb6af5c52
[goodguy/history.git] / cinelerra-5.1 / cinelerra / colorpicker.C
1
2 /*
3  * CINELERRA
4  * Copyright (C) 1997-2011 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 "bcdisplayinfo.h"
23 #include "colorpicker.h"
24 #include "condition.h"
25 #include "language.h"
26 #include "mutex.h"
27 #include "mwindow.inc"
28 #include "cicolors.h"
29 #include "vframe.h"
30
31 #include <string.h>
32 #include <unistd.h>
33
34
35 ColorThread::ColorThread(int do_alpha, const char *title)
36  : BC_DialogThread()
37 {
38         this->title = title;
39         this->do_alpha = do_alpha;
40         this->do_okcancel = 0;
41         this->output = BLACK;
42         this->alpha = 255;
43 }
44
45 ColorThread::~ColorThread()
46 {
47         close_window();
48 }
49
50 void ColorThread::start_window(int output, int alpha, int do_okcancel)
51 {
52         if( running() ) {
53                 ColorWindow *gui = (ColorWindow *)get_gui();
54                 if( gui ) {
55                         gui->lock_window("ColorThread::start_window");
56                         gui->raise_window(1);
57                         gui->unlock_window();
58                 }
59                 return;
60         }
61         this->output = output;
62         this->alpha = alpha;
63         this->do_okcancel = do_okcancel;
64         start();
65 }
66
67 BC_Window* ColorThread::new_gui()
68 {
69         char window_title[BCTEXTLEN];
70         strcpy(window_title, _(PROGRAM_NAME ": "));
71         strcat(window_title, title ? title : _("Color Picker"));
72         BC_DisplayInfo display_info;
73         int x = display_info.get_abs_cursor_x() + 25;
74         int y = display_info.get_abs_cursor_y() - 100;
75         int w = 540, h = 290;
76         if( do_alpha )
77                 h += 40 + PalletteAPH::calculate_h();
78         if( do_okcancel )
79                 h += bmax(BC_OKButton::calculate_h(),BC_CancelButton::calculate_h());
80         int root_w = display_info.get_root_w(), root_h = display_info.get_root_h();
81         if( x+w > root_w ) x = root_w - w;
82         if( y+h > root_h ) y = root_h - h;
83         if( x < 0 ) x = 0;
84         if( y < 0 ) y = 0;
85         ColorWindow *gui = new ColorWindow(this, x, y, w, h, window_title);
86         gui->create_objects();
87         return gui;
88 }
89
90 void ColorThread::update_gui(int output, int alpha)
91 {
92         ColorWindow *gui = (ColorWindow *)get_gui();
93         if( !gui ) return;
94         gui->lock_window();
95         this->output = output;
96         this->alpha = alpha;
97         gui->change_values();
98         gui->update_display();
99         gui->unlock_window();
100 }
101
102 int ColorThread::handle_new_color(int output, int alpha)
103 {
104         printf("ColorThread::handle_new_color undefined.\n");
105         return 0;
106 }
107
108
109 ColorWindow::ColorWindow(ColorThread *thread, int x, int y, int w, int h, const char *title)
110  : BC_Window(title, x, y, w, h, w, h, 0, 0, 1)
111 {
112         this->thread = thread;
113         wheel = 0;
114         wheel_value = 0;
115         output = 0;
116
117         hue = 0; sat = 0; val = 0;
118         red = 0; grn = 0; blu = 0;
119         lum = 0; c_r = 0; c_b = 0;
120         alpha = 0;
121
122         hsv_h = 0;  hsv_s = 0;  hsv_v = 0;
123         rgb_r = 0;  rgb_g = 0;  rgb_b = 0;
124         yuv_y = 0;  yuv_u = 0;  yuv_v = 0;
125         aph_a = 0;
126 }
127 ColorWindow::~ColorWindow()
128 {
129         delete hsv_h;  delete hsv_s;  delete hsv_v;
130         delete rgb_r;  delete rgb_g;  delete rgb_b;
131         delete yuv_y;  delete yuv_u;  delete yuv_v;
132         delete aph_a;
133 }
134
135 void ColorWindow::create_objects()
136 {
137         int x0 = 10, y0 = 10;
138         lock_window("ColorWindow::create_objects");
139         change_values();
140
141         int x = x0, y = y0;
142         add_tool(wheel = new PaletteWheel(this, x, y));
143         wheel->create_objects();
144
145         x += 180;  add_tool(wheel_value = new PaletteWheelValue(this, x, y));
146         wheel_value->create_objects();
147         x = x0;
148         y += 180;  add_tool(output = new PaletteOutput(this, x, y));
149         output->create_objects();
150         y += output->get_h() + 20;
151
152         x += 240;
153         add_tool(new BC_Title(x, y =y0, _("H:"), SMALLFONT));
154         add_tool(new BC_Title(x, y+=25, _("S:"), SMALLFONT));
155         add_tool(new BC_Title(x, y+=25, _("V:"), SMALLFONT));
156         add_tool(new BC_Title(x, y+=40, _("R:"), SMALLFONT));
157         add_tool(new BC_Title(x, y+=25, _("G:"), SMALLFONT));
158         add_tool(new BC_Title(x, y+=25, _("B:"), SMALLFONT));
159         add_tool(new BC_Title(x, y+=40, _("Y:"), SMALLFONT));
160         add_tool(new BC_Title(x, y+=25, _("U:"), SMALLFONT));
161         add_tool(new BC_Title(x, y+=25, _("V:"), SMALLFONT));
162         if( thread->do_alpha )
163                 add_tool(new BC_Title(x, y+=40, _("A:"), SMALLFONT));
164         x += 24;
165         add_tool(hue = new PaletteHue(this, x, y= y0));
166         add_tool(sat = new PaletteSat(this, x, y+=25));
167         add_tool(val = new PaletteVal(this, x, y+=25));
168         add_tool(red = new PaletteRed(this, x, y+=40));
169         add_tool(grn = new PaletteGrn(this, x, y+=25));
170         add_tool(blu = new PaletteBlu(this, x, y+=25));
171         add_tool(lum = new PaletteLum(this, x, y+=40));
172         add_tool(c_r = new PaletteCr (this, x, y+=25));
173         add_tool(c_b = new PaletteCb (this, x, y+=25));
174         if( thread->do_alpha )
175                 add_tool(alpha = new PaletteAlpha(this, x, y+=40));
176
177         x += hue->get_w() + 10;
178         hsv_h = new PalletteHSV(this, x,y= y0, hsv.h, 0, 360);  hsv_h->create_objects();
179         hsv_s = new PalletteHSV(this, x,y+=25, hsv.s, 0, 1);    hsv_s->create_objects();
180         hsv_v = new PalletteHSV(this, x,y+=25, hsv.v, 0, 1);    hsv_v->create_objects();
181         rgb_r = new PalletteRGB(this, x,y+=40, rgb.r, 0, 1);    rgb_r->create_objects();
182         rgb_g = new PalletteRGB(this, x,y+=25, rgb.g, 0, 1);    rgb_g->create_objects();
183         rgb_b = new PalletteRGB(this, x,y+=25, rgb.b, 0, 1);    rgb_b->create_objects();
184         yuv_y = new PalletteYUV(this, x,y+=40, yuv.y, 0, 1);    yuv_y->create_objects();
185         yuv_u = new PalletteYUV(this, x,y+=25, yuv.u, 0, 1);    yuv_u->create_objects();
186         yuv_v = new PalletteYUV(this, x,y+=25, yuv.v, 0, 1);    yuv_v->create_objects();
187         if( thread->do_alpha ) {
188                 aph_a = new PalletteAPH(this, x,y+=40, aph, 0, 1); aph_a->create_objects();
189         }
190         if( thread->do_okcancel ) {
191                 add_tool(new BC_OKButton(this));
192                 add_tool(new BC_CancelButton(this));
193         }
194
195         update_display();
196         show_window(1);
197         unlock_window();
198 }
199
200
201 void ColorWindow::change_values()
202 {
203         float r = ((thread->output>>16) & 0xff) / 255.;
204         float g = ((thread->output>>8)  & 0xff) / 255.;
205         float b = ((thread->output>>0)  & 0xff) / 255.;
206         rgb.r = r;  rgb.g = g;  rgb.b = b;
207         aph = (float)thread->alpha / 255;
208         update_rgb(rgb.r, rgb.g, rgb.b);
209 }
210
211
212 int ColorWindow::close_event()
213 {
214         set_done(thread->do_okcancel ? 1 : 0);
215         return 1;
216 }
217
218
219 void ColorWindow::update_rgb()
220 {
221         update_rgb(rgb.r, rgb.g, rgb.b);
222         update_display();
223 }
224 void ColorWindow::update_hsv()
225 {
226         update_hsv(hsv.h, hsv.s, hsv.v);
227         update_display();
228 }
229 void ColorWindow::update_yuv()
230 {
231         update_yuv(yuv.y, yuv.u, yuv.v);
232         update_display();
233 }
234
235 void ColorWindow::update_display()
236 {
237         wheel->draw(wheel->oldhue, wheel->oldsaturation);
238         wheel->oldhue = hsv.h;
239         wheel->oldsaturation = hsv.s;
240         wheel->draw(hsv.h, hsv.s);
241         wheel->flash();
242         wheel_value->draw(hsv.h, hsv.s, hsv.v);
243         wheel_value->flash();
244         output->draw();
245         output->flash();
246
247         hue->update((int)hsv.h);
248         sat->update(hsv.s);
249         val->update(hsv.v);
250
251         red->update(rgb.r);
252         grn->update(rgb.g);
253         blu->update(rgb.b);
254
255         lum->update(yuv.y);
256         c_r->update(yuv.u);
257         c_b->update(yuv.v);
258
259         hsv_h->update(hsv.h);
260         hsv_s->update(hsv.s);
261         hsv_v->update(hsv.v);
262         rgb_r->update(rgb.r);
263         rgb_g->update(rgb.g);
264         rgb_b->update(rgb.b);
265         yuv_y->update(yuv.y);
266         yuv_u->update(yuv.u);
267         yuv_v->update(yuv.v);
268         if( thread->do_alpha )
269                 aph_a->update(aph);
270 }
271
272 int ColorWindow::handle_event()
273 {
274         int r = 255*rgb.r + 0.5, g = 255*rgb.g + 0.5, b = 255*rgb.b + 0.5;
275         int result = (r << 16) | (g << 8) | (b << 0);
276         thread->handle_new_color(result, (int)(255*aph + 0.5));
277         return 1;
278 }
279
280
281 PaletteWheel::PaletteWheel(ColorWindow *window, int x, int y)
282  : BC_SubWindow(x, y, 170, 170)
283 {
284         this->window = window;
285         oldhue = 0;
286         oldsaturation = 0;
287         button_down = 0;
288 }
289
290 PaletteWheel::~PaletteWheel()
291 {
292 }
293
294 int PaletteWheel::button_press_event()
295 {
296         if( get_cursor_x() >= 0 && get_cursor_x() < get_w() &&
297                 get_cursor_y() >= 0 && get_cursor_y() < get_h() &&
298                 is_event_win() ) {
299                 button_down = 1;
300                 cursor_motion_event();
301                 return 1;
302         }
303         return 0;
304 }
305
306 int PaletteWheel::cursor_motion_event()
307 {
308         int x1, y1, distance;
309         if( button_down && is_event_win() ) {
310                 float h = get_angle(get_w()/2, get_h()/2, get_cursor_x(), get_cursor_y());
311                 bclamp(h, 0, 359.999);  window->hsv.h = h;
312                 x1 = get_w() / 2 - get_cursor_x();
313                 y1 = get_h() / 2 - get_cursor_y();
314                 distance = (int)sqrt(x1 * x1 + y1 * y1);
315                 float s = (float)distance / (get_w() / 2);
316                 bclamp(s, 0, 1);  window->hsv.s = s;
317                 window->update_hsv();
318                 window->update_display();
319                 window->handle_event();
320                 return 1;
321         }
322         return 0;
323 }
324
325 int PaletteWheel::button_release_event()
326 {
327         if( button_down ) {
328                 button_down = 0;
329                 return 1;
330         }
331         return 0;
332 }
333
334 void PaletteWheel::create_objects()
335 {
336 // Upper right
337 //printf("PaletteWheel::create_objects 1\n");
338         float h, s, v = 1;
339         float r, g, b;
340         float x1, y1, x2, y2;
341         float distance;
342         int default_r, default_g, default_b;
343         VFrame frame(0, -1, get_w(), get_h(), BC_RGBA8888, -1);
344         x1 = get_w() / 2;
345         y1 = get_h() / 2;
346         default_r = (get_resources()->get_bg_color() & 0xff0000) >> 16;
347         default_g = (get_resources()->get_bg_color() & 0xff00) >> 8;
348         default_b = (get_resources()->get_bg_color() & 0xff);
349 //printf("PaletteWheel::create_objects 1\n");
350
351         int highlight_r = (get_resources()->button_light & 0xff0000) >> 16;
352         int highlight_g = (get_resources()->button_light & 0xff00) >> 8;
353         int highlight_b = (get_resources()->button_light & 0xff);
354
355         for( y2 = 0; y2 < get_h(); y2++ ) {
356                 unsigned char *row = (unsigned char*)frame.get_rows()[(int)y2];
357                 for( x2 = 0; x2 < get_w(); x2++ ) {
358                         distance = sqrt((x2 - x1) * (x2 - x1) + (y2 - y1) * (y2 - y1));
359                         if( distance > x1 ) {
360                                 row[(int)x2 * 4] = default_r;
361                                 row[(int)x2 * 4 + 1] = default_g;
362                                 row[(int)x2 * 4 + 2] = default_b;
363                                 row[(int)x2 * 4 + 3] = 0;
364                         }
365                         else
366                         if( distance > x1 - 1 ) {
367                                 int r_i, g_i, b_i;
368                                 if( get_h() - y2 < x2 ) {
369                                         r_i = highlight_r;
370                                         g_i = highlight_g;
371                                         b_i = highlight_b;
372                                 }
373                                 else {
374                                         r_i = 0;
375                                         g_i = 0;
376                                         b_i = 0;
377                                 }
378
379                                 row[(int)x2 * 4] = r_i;
380                                 row[(int)x2 * 4 + 1] = g_i;
381                                 row[(int)x2 * 4 + 2] = b_i;
382                                 row[(int)x2 * 4 + 3] = 255;
383                         }
384                         else {
385                                 h = get_angle(x1, y1, x2, y2);
386                                 s = distance / x1;
387                                 HSV::hsv_to_rgb(r, g, b, h, s, v);
388                                 row[(int)x2 * 4] = (int)(r * 255);
389                                 row[(int)x2 * 4 + 1] = (int)(g * 255);
390                                 row[(int)x2 * 4 + 2] = (int)(b * 255);
391                                 row[(int)x2 * 4 + 3] = 255;
392                         }
393                 }
394         }
395 //printf("PaletteWheel::create_objects 1\n");
396
397         draw_vframe(&frame,
398                 0,
399                 0,
400                 get_w(),
401                 get_h(),
402                 0,
403                 0,
404                 get_w(),
405                 get_h(),
406                 0);
407 //printf("PaletteWheel::create_objects 1\n");
408
409         oldhue = window->hsv.h;
410         oldsaturation = window->hsv.s;
411 //printf("PaletteWheel::create_objects 1\n");
412         draw(oldhue, oldsaturation);
413 //printf("PaletteWheel::create_objects 1\n");
414         flash();
415 //printf("PaletteWheel::create_objects 2\n");
416 }
417
418 float PaletteWheel::torads(float angle)
419 {
420         return (float)angle / 360 * 2 * M_PI;
421 }
422
423
424 int PaletteWheel::draw(float hue, float saturation)
425 {
426         int x, y, w, h;
427         x = w = get_w() / 2;
428         y = h = get_h() / 2;
429
430         if( hue > 0 && hue < 90 ) {
431                 x = (int)(w - w * cos(torads(90 - hue)) * saturation);
432                 y = (int)(h - h * sin(torads(90 - hue)) * saturation);
433         }
434         else if( hue > 90 && hue < 180 ) {
435                 x = (int)(w - w * cos(torads(hue - 90)) * saturation);
436                 y = (int)(h + h * sin(torads(hue - 90)) * saturation);
437         }
438         else if( hue > 180 && hue < 270 ) {
439                 x = (int)(w + w * cos(torads(270 - hue)) * saturation);
440                 y = (int)(h + h * sin(torads(270 - hue)) * saturation);
441         }
442         else if( hue > 270 && hue < 360 ) {
443                 x = (int)(w + w * cos(torads(hue - 270)) * saturation);
444                 y = (int)(h - w * sin(torads(hue - 270)) * saturation);
445         }
446         else if( hue == 0 ) {
447                 x = w;
448                 y = (int)(h - h * saturation);
449         }
450         else if( hue == 90 ) {
451                 x = (int)(w - w * saturation);
452                 y = h;
453         }
454         else if( hue == 180 ) {
455                 x = w;
456                 y = (int)(h + h * saturation);
457         }
458         else if( hue == 270 ) {
459                 x = (int)(w + w * saturation);
460                 y = h;
461         }
462
463         set_inverse();
464         set_color(WHITE);
465         draw_circle(x - 5, y - 5, 10, 10);
466         set_opaque();
467         return 0;
468 }
469
470 int PaletteWheel::get_angle(float x1, float y1, float x2, float y2)
471 {
472         float result = -atan2(x2 - x1, y1 - y2) * (360 / M_PI / 2);
473         if( result < 0 )
474                 result += 360;
475         return (int)result;
476 }
477
478 PaletteWheelValue::PaletteWheelValue(ColorWindow *window, int x, int y)
479  : BC_SubWindow(x, y, 40, 170, BLACK)
480 {
481         this->window = window;
482         button_down = 0;
483 }
484 PaletteWheelValue::~PaletteWheelValue()
485 {
486         delete frame;
487 }
488
489 void PaletteWheelValue::create_objects()
490 {
491         frame = new VFrame(0, -1, get_w(), get_h(), BC_RGB888, -1);
492         draw(window->hsv.h, window->hsv.s, window->hsv.v);
493         flash();
494 }
495
496 int PaletteWheelValue::button_press_event()
497 {
498 //printf("PaletteWheelValue::button_press 1 %d\n", is_event_win());
499         if( get_cursor_x() >= 0 && get_cursor_x() < get_w() &&
500                 get_cursor_y() >= 0 && get_cursor_y() < get_h() &&
501                 is_event_win() ) {
502 //printf("PaletteWheelValue::button_press 2\n");
503                 button_down = 1;
504                 cursor_motion_event();
505                 return 1;
506         }
507         return 0;
508 }
509
510 int PaletteWheelValue::cursor_motion_event()
511 {
512         if( button_down && is_event_win() ) {
513 //printf("PaletteWheelValue::cursor_motion 1\n");
514                 float v = 1.0 - (float)(get_cursor_y() - 2) / (get_h() - 4);
515                 bclamp(v, 0, 1);  window->hsv.v = v;
516                 window->update_hsv();
517                 window->update_display();
518                 window->handle_event();
519                 return 1;
520         }
521         return 0;
522 }
523
524 int PaletteWheelValue::button_release_event()
525 {
526         if( button_down ) {
527 //printf("PaletteWheelValue::button_release 1\n");
528                 button_down = 0;
529                 return 1;
530         }
531         return 0;
532 }
533
534 int PaletteWheelValue::draw(float hue, float saturation, float value)
535 {
536         float r_f, g_f, b_f;
537         int i, j, r, g, b;
538
539         for( i = get_h() - 3; i >= 2; i-- ) {
540                 unsigned char *row = (unsigned char*)frame->get_rows()[i];
541                 HSV::hsv_to_rgb(r_f, g_f, b_f, hue, saturation,
542                         1.0 - (float)(i - 2) / (get_h() - 4));
543                 r = (int)(r_f * 255);
544                 g = (int)(g_f * 255);
545                 b = (int)(b_f * 255);
546                 for( j = 0; j < get_w(); j++ ) {
547                         row[j * 3] = r;
548                         row[j * 3 + 1] = g;
549                         row[j * 3 + 2] = b;
550                 }
551         }
552
553         draw_3d_border(0, 0, get_w(), get_h(), 1);
554         draw_vframe(frame, 2, 2, get_w() - 4, get_h() - 4,
555                 2, 2, get_w() - 4, get_h() - 4, 0);
556         set_color(BLACK);
557         draw_line(2, get_h() - 3 - (int)(value * (get_h() - 5)),
558                   get_w() - 3, get_h() - 3 - (int)(value * (get_h() - 5)));
559 //printf("PaletteWheelValue::draw %d %f\n", __LINE__, value);
560
561         return 0;
562 }
563
564 PaletteOutput::PaletteOutput(ColorWindow *window, int x, int y)
565  : BC_SubWindow(x, y, 180, 30, BLACK)
566 {
567         this->window = window;
568 }
569 PaletteOutput::~PaletteOutput()
570 {
571 }
572
573
574 void PaletteOutput::create_objects()
575 {
576         draw();
577         flash();
578 }
579
580 int PaletteOutput::handle_event()
581 {
582         return 1;
583 }
584
585 int PaletteOutput::draw()
586 {
587         int r = 255*window->rgb.r + 0.5f;
588         int g = 255*window->rgb.g + 0.5f;
589         int b = 255*window->rgb.b + 0.5f;
590         set_color((r << 16) | (g << 8) | (b << 0));
591         draw_box(2, 2, get_w() - 4, get_h() - 4);
592         draw_3d_border(0, 0, get_w(), get_h(), 1);
593         return 0;
594 }
595
596 PaletteHue::PaletteHue(ColorWindow *window, int x, int y)
597  : BC_ISlider(x, y, 0, 150, 200, 0, 359, (int)(window->hsv.h), 0)
598 {
599         this->window = window;
600 }
601 PaletteHue::~PaletteHue()
602 {
603 }
604
605 int PaletteHue::handle_event()
606 {
607         window->hsv.h = get_value();
608         window->update_hsv();
609         window->handle_event();
610         return 1;
611 }
612
613 PaletteSat::PaletteSat(ColorWindow *window, int x, int y)
614  : BC_FSlider(x, y, 0, 150, 200, 0, 1.0, window->hsv.s, 0)
615 {
616         this->window = window;
617         set_precision(0.01);
618 }
619 PaletteSat::~PaletteSat()
620 {
621 }
622
623 int PaletteSat::handle_event()
624 {
625         window->hsv.s = get_value();
626         window->update_hsv();
627         window->handle_event();
628         return 1;
629 }
630
631
632 PaletteVal::PaletteVal(ColorWindow *window, int x, int y)
633  : BC_FSlider(x, y, 0, 150, 200, 0, 1.0, window->hsv.v, 0)
634 {
635         this->window = window;
636         set_precision(0.01);
637 }
638 PaletteVal::~PaletteVal()
639 {
640 }
641
642 int PaletteVal::handle_event()
643 {
644         window->hsv.v = get_value();
645         window->update_hsv();
646         window->handle_event();
647         return 1;
648 }
649
650
651 PaletteRed::PaletteRed(ColorWindow *window, int x, int y)
652  : BC_FSlider(x, y, 0, 150, 200, 0, 1, window->rgb.r, 0)
653 {
654         this->window = window;
655         set_precision(0.01);
656 }
657 PaletteRed::~PaletteRed()
658 {
659 }
660
661 int PaletteRed::handle_event()
662 {
663         window->rgb.r = get_value();
664         window->update_rgb();
665         window->handle_event();
666         return 1;
667 }
668
669 PaletteGrn::PaletteGrn(ColorWindow *window, int x, int y)
670  : BC_FSlider(x, y, 0, 150, 200, 0, 1, window->rgb.g, 0)
671 {
672         this->window = window;
673         set_precision(0.01);
674 }
675 PaletteGrn::~PaletteGrn()
676 {
677 }
678
679 int PaletteGrn::handle_event()
680 {
681         window->rgb.g = get_value();
682         window->update_rgb();
683         window->handle_event();
684         return 1;
685 }
686
687 PaletteBlu::PaletteBlu(ColorWindow *window, int x, int y)
688  : BC_FSlider(x, y, 0, 150, 200, 0, 1, window->rgb.b, 0)
689 {
690         this->window = window;
691         set_precision(0.01);
692 }
693 PaletteBlu::~PaletteBlu()
694 {
695 }
696
697 int PaletteBlu::handle_event()
698 {
699         window->rgb.b = get_value();
700         window->update_rgb();
701         window->handle_event();
702         return 1;
703 }
704
705 PaletteAlpha::PaletteAlpha(ColorWindow *window, int x, int y)
706  : BC_FSlider(x, y, 0, 150, 200, 0, 1, window->aph, 0)
707 {
708         this->window = window;
709         set_precision(0.01);
710 }
711 PaletteAlpha::~PaletteAlpha()
712 {
713 }
714
715 int PaletteAlpha::handle_event()
716 {
717         window->aph = get_value();
718         window->handle_event();
719         return 1;
720 }
721
722 PaletteLum::PaletteLum(ColorWindow *window, int x, int y)
723  : BC_FSlider(x, y, 0, 150, 200, 0, 1, window->yuv.y, 0)
724 {
725         this->window = window;
726         set_precision(0.01);
727 }
728 PaletteLum::~PaletteLum()
729 {
730 }
731
732 int PaletteLum::handle_event()
733 {
734         window->yuv.y = get_value();
735         window->update_yuv();
736         window->handle_event();
737         return 1;
738 }
739
740 PaletteCr::PaletteCr(ColorWindow *window, int x, int y)
741  : BC_FSlider(x, y, 0, 150, 200, 0, 1, window->yuv.u, 0)
742 {
743         this->window = window;
744         set_precision(0.01);
745 }
746 PaletteCr::~PaletteCr()
747 {
748 }
749
750 int PaletteCr::handle_event()
751 {
752         window->yuv.u = get_value();
753         window->update_yuv();
754         window->handle_event();
755         return 1;
756 }
757
758 PaletteCb::PaletteCb(ColorWindow *window, int x, int y)
759  : BC_FSlider(x, y, 0, 150, 200, 0, 1, window->yuv.v, 0)
760 {
761         this->window = window;
762         set_precision(0.01);
763 }
764 PaletteCb::~PaletteCb()
765 {
766 }
767
768 int PaletteCb::handle_event()
769 {
770         window->yuv.v = get_value();
771         window->update_yuv();
772         window->handle_event();
773         return 1;
774 }
775
776 void ColorWindow::update_rgb(float r, float g, float b)
777 {
778         { float y, u, v;
779         YUV::rgb_to_yuv_f(r, g, b, y, u, v);
780         u += 0.5f;  v += 0.5f;
781         bclamp(y, 0, 1);    yuv.y = y;
782         bclamp(u, 0, 1);    yuv.u = u;
783         bclamp(v, 0, 1);    yuv.v = v; }
784         { float h, s, v;
785         HSV::rgb_to_hsv(r,g,b, h,s,v);
786         bclamp(h, 0, 360);  hsv.h = h;
787         bclamp(s, 0, 1);    hsv.s = s;
788         bclamp(v, 0, 1);    hsv.v = v; }
789 }
790
791 void ColorWindow::update_yuv(float y, float u, float v)
792 {
793         u -= 0.5f;  v -= 0.5f;
794         { float r, g, b;
795         YUV::yuv_to_rgb_f(r, g, b, y, u, v);
796         bclamp(r, 0, 1);   rgb.r = r;
797         bclamp(g, 0, 1);   rgb.g = g;
798         bclamp(b, 0, 1);   rgb.b = b;
799         float h, s, v;
800         HSV::rgb_to_hsv(r,g,b, h, s, v);
801         bclamp(h, 0, 360); hsv.h = h;
802         bclamp(s, 0, 1);   hsv.s = s;
803         bclamp(v, 0, 1);   hsv.v = v; }
804 }
805
806 void ColorWindow::update_hsv(float h, float s, float v)
807 {
808         { float r, g, b;
809         HSV::hsv_to_rgb(r,g,b, h,s,v);
810         bclamp(r, 0, 1);   rgb.r = r;
811         bclamp(g, 0, 1);   rgb.g = g;
812         bclamp(b, 0, 1);   rgb.b = b;
813         float y, u, v;
814         YUV::rgb_to_yuv_f(r, g, b, y, u, v);
815         u += 0.5f;  v += 0.5f;
816         bclamp(y, 0, 1);   yuv.y = y;
817         bclamp(u, 0, 1);   yuv.u = u;
818         bclamp(v, 0, 1);   yuv.v = v; }
819 }
820
821 PalletteNum::PalletteNum(ColorWindow *window, int x, int y,
822         float &output, float min, float max)
823  : BC_TumbleTextBox(window, output, min, max, x, y, 64)
824 {
825         this->window = window;
826         this->output = &output;
827         set_increment(0.01);
828         set_precision(2);
829 }
830
831 PalletteNum::~PalletteNum()
832 {
833 }
834
835
836 int PalletteHSV::handle_event()
837 {
838         update_output();
839         window->update_hsv();
840         window->update_display();
841         window->handle_event();
842         return 1;
843 }
844
845 int PalletteRGB::handle_event()
846 {
847         update_output();
848         window->update_rgb();
849         window->update_display();
850         window->handle_event();
851         return 1;
852 }
853
854 int PalletteYUV::handle_event()
855 {
856         update_output();
857         window->update_yuv();
858         window->update_display();
859         window->handle_event();
860         return 1;
861 }
862
863 int PalletteAPH::handle_event()
864 {
865         update_output();
866         window->update_display();
867         window->handle_event();
868         return 1;
869 }
870