colorpick rework, color popup for titler, color convert fixes
[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 & 0xff0000) >> 16) / 255.;
204         float g = ((thread->output & 0xff00) >> 8) / 255.;
205         float b = ((thread->output & 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         {
300                 button_down = 1;
301                 cursor_motion_event();
302                 return 1;
303         }
304         return 0;
305 }
306
307 int PaletteWheel::cursor_motion_event()
308 {
309         int x1, y1, distance;
310         if(button_down && is_event_win())
311         {
312                 window->hsv.h = get_angle(get_w() / 2,
313                         get_h() / 2,
314                         get_cursor_x(),
315                         get_cursor_y());
316                 x1 = get_w() / 2 - get_cursor_x();
317                 y1 = get_h() / 2 - get_cursor_y();
318                 distance = (int)sqrt(x1 * x1 + y1 * y1);
319                 if(distance > get_w() / 2) distance = get_w() / 2;
320                 window->hsv.s = (float)distance / (get_w() / 2);
321                 window->update_hsv();
322                 window->update_display();
323                 window->handle_event();
324                 return 1;
325         }
326         return 0;
327 }
328
329 int PaletteWheel::button_release_event()
330 {
331         if(button_down)
332         {
333                 button_down = 0;
334                 return 1;
335         }
336         return 0;
337 }
338
339 void PaletteWheel::create_objects()
340 {
341 // Upper right
342 //printf("PaletteWheel::create_objects 1\n");
343         float h;
344         float s;
345         float v = 1;
346         float r, g, b;
347         float x1, y1, x2, y2;
348         float distance;
349         int default_r, default_g, default_b;
350         VFrame frame(0, -1, get_w(), get_h(), BC_RGBA8888, -1);
351         x1 = get_w() / 2;
352         y1 = get_h() / 2;
353         default_r = (get_resources()->get_bg_color() & 0xff0000) >> 16;
354         default_g = (get_resources()->get_bg_color() & 0xff00) >> 8;
355         default_b = (get_resources()->get_bg_color() & 0xff);
356 //printf("PaletteWheel::create_objects 1\n");
357
358         int highlight_r = (get_resources()->button_light & 0xff0000) >> 16;
359         int highlight_g = (get_resources()->button_light & 0xff00) >> 8;
360         int highlight_b = (get_resources()->button_light & 0xff);
361
362         for(y2 = 0; y2 < get_h(); y2++)
363         {
364                 unsigned char *row = (unsigned char*)frame.get_rows()[(int)y2];
365                 for(x2 = 0; x2 < get_w(); x2++)
366                 {
367                         distance = sqrt((x2 - x1) * (x2 - x1) + (y2 - y1) * (y2 - y1));
368                         if(distance > x1)
369                         {
370                                 row[(int)x2 * 4] = default_r;
371                                 row[(int)x2 * 4 + 1] = default_g;
372                                 row[(int)x2 * 4 + 2] = default_b;
373                                 row[(int)x2 * 4 + 3] = 0;
374                         }
375                         else
376                         if(distance > x1 - 1)
377                         {
378                                 int r_i, g_i, b_i;
379                                 if(get_h() - y2 < x2)
380                                 {
381                                         r_i = highlight_r;
382                                         g_i = highlight_g;
383                                         b_i = highlight_b;
384                                 }
385                                 else
386                                 {
387                                         r_i = 0;
388                                         g_i = 0;
389                                         b_i = 0;
390                                 }
391
392                                 row[(int)x2 * 4] = r_i;
393                                 row[(int)x2 * 4 + 1] = g_i;
394                                 row[(int)x2 * 4 + 2] = b_i;
395                                 row[(int)x2 * 4 + 3] = 255;
396                         }
397                         else
398                         {
399                                 h = get_angle(x1, y1, x2, y2);
400                                 s = distance / x1;
401                                 HSV::hsv_to_rgb(r, g, b, h, s, v);
402                                 row[(int)x2 * 4] = (int)(r * 255);
403                                 row[(int)x2 * 4 + 1] = (int)(g * 255);
404                                 row[(int)x2 * 4 + 2] = (int)(b * 255);
405                                 row[(int)x2 * 4 + 3] = 255;
406                         }
407                 }
408         }
409 //printf("PaletteWheel::create_objects 1\n");
410
411         draw_vframe(&frame,
412                 0,
413                 0,
414                 get_w(),
415                 get_h(),
416                 0,
417                 0,
418                 get_w(),
419                 get_h(),
420                 0);
421 //printf("PaletteWheel::create_objects 1\n");
422
423         oldhue = window->hsv.h;
424         oldsaturation = window->hsv.s;
425 //printf("PaletteWheel::create_objects 1\n");
426         draw(oldhue, oldsaturation);
427 //printf("PaletteWheel::create_objects 1\n");
428         flash();
429 //printf("PaletteWheel::create_objects 2\n");
430 }
431
432 float PaletteWheel::torads(float angle)
433 {
434         return (float)angle / 360 * 2 * M_PI;
435 }
436
437
438 int PaletteWheel::draw(float hue, float saturation)
439 {
440         int x, y, w, h;
441         x = w = get_w() / 2;
442         y = h = get_h() / 2;
443
444         if(hue > 0 && hue < 90)
445         {
446                 x = (int)(w - w * cos(torads(90 - hue)) * saturation);
447                 y = (int)(h - h * sin(torads(90 - hue)) * saturation);
448         }
449         else
450         if(hue > 90 && hue < 180)
451         {
452                 x = (int)(w - w * cos(torads(hue - 90)) * saturation);
453                 y = (int)(h + h * sin(torads(hue - 90)) * saturation);
454         }
455         else
456         if(hue > 180 && hue < 270)
457         {
458                 x = (int)(w + w * cos(torads(270 - hue)) * saturation);
459                 y = (int)(h + h * sin(torads(270 - hue)) * saturation);
460         }
461         else
462         if(hue > 270 && hue < 360)
463         {
464                 x = (int)(w + w * cos(torads(hue - 270)) * saturation);
465                 y = (int)(h - w * sin(torads(hue - 270)) * saturation);
466         }
467         else
468         if(hue == 0)
469         {
470                 x = w;
471                 y = (int)(h - h * saturation);
472         }
473         else
474         if(hue == 90)
475         {
476                 x = (int)(w - w * saturation);
477                 y = h;
478         }
479         else
480         if(hue == 180)
481         {
482                 x = w;
483                 y = (int)(h + h * saturation);
484         }
485         else
486         if(hue == 270)
487         {
488                 x = (int)(w + w * saturation);
489                 y = h;
490         }
491
492         set_inverse();
493         set_color(WHITE);
494         draw_circle(x - 5, y - 5, 10, 10);
495         set_opaque();
496         return 0;
497 }
498
499 int PaletteWheel::get_angle(float x1, float y1, float x2, float y2)
500 {
501         float result = -atan2(x2 - x1, y1 - y2) * (360 / M_PI / 2);
502         if (result < 0)
503                 result += 360;
504         return (int)result;
505 }
506
507 PaletteWheelValue::PaletteWheelValue(ColorWindow *window, int x, int y)
508  : BC_SubWindow(x, y, 40, 170, BLACK)
509 {
510         this->window = window;
511         button_down = 0;
512 }
513 PaletteWheelValue::~PaletteWheelValue()
514 {
515         delete frame;
516 }
517
518 void PaletteWheelValue::create_objects()
519 {
520         frame = new VFrame(0, -1, get_w(), get_h(), BC_RGB888, -1);
521         draw(window->hsv.h, window->hsv.s, window->hsv.v);
522         flash();
523 }
524
525 int PaletteWheelValue::button_press_event()
526 {
527 //printf("PaletteWheelValue::button_press 1 %d\n", is_event_win());
528         if(get_cursor_x() >= 0 && get_cursor_x() < get_w() &&
529                 get_cursor_y() >= 0 && get_cursor_y() < get_h() &&
530                 is_event_win())
531         {
532 //printf("PaletteWheelValue::button_press 2\n");
533                 button_down = 1;
534                 cursor_motion_event();
535                 return 1;
536         }
537         return 0;
538 }
539
540 int PaletteWheelValue::cursor_motion_event()
541 {
542         if(button_down && is_event_win())
543         {
544 //printf("PaletteWheelValue::cursor_motion 1\n");
545                 window->hsv.v = 1.0 - (float)(get_cursor_y() - 2) / (get_h() - 4);
546                 window->update_hsv();
547                 window->update_display();
548                 window->handle_event();
549                 return 1;
550         }
551         return 0;
552 }
553
554 int PaletteWheelValue::button_release_event()
555 {
556         if(button_down)
557         {
558 //printf("PaletteWheelValue::button_release 1\n");
559                 button_down = 0;
560                 return 1;
561         }
562         return 0;
563 }
564
565 int PaletteWheelValue::draw(float hue, float saturation, float value)
566 {
567         float r_f, g_f, b_f;
568         int i, j, r, g, b;
569
570         for(i = get_h() - 3; i >= 2; i--)
571         {
572                 unsigned char *row = (unsigned char*)frame->get_rows()[i];
573                 HSV::hsv_to_rgb(r_f, g_f, b_f, hue, saturation,
574                         1.0 - (float)(i - 2) / (get_h() - 4));
575                 r = (int)(r_f * 255);
576                 g = (int)(g_f * 255);
577                 b = (int)(b_f * 255);
578                 for(j = 0; j < get_w(); j++)
579                 {
580                         row[j * 3] = r;
581                         row[j * 3 + 1] = g;
582                         row[j * 3 + 2] = b;
583                 }
584         }
585
586         draw_3d_border(0, 0, get_w(), get_h(), 1);
587         draw_vframe(frame, 2, 2, get_w() - 4, get_h() - 4,
588                 2, 2, get_w() - 4, get_h() - 4, 0);
589         set_color(BLACK);
590         draw_line(2, get_h() - 3 - (int)(value * (get_h() - 5)),
591                   get_w() - 3, get_h() - 3 - (int)(value * (get_h() - 5)));
592 //printf("PaletteWheelValue::draw %d %f\n", __LINE__, value);
593
594         return 0;
595 }
596
597 PaletteOutput::PaletteOutput(ColorWindow *window, int x, int y)
598  : BC_SubWindow(x, y, 180, 30, BLACK)
599 {
600         this->window = window;
601 }
602 PaletteOutput::~PaletteOutput()
603 {
604 }
605
606
607 void PaletteOutput::create_objects()
608 {
609         draw();
610         flash();
611 }
612
613 int PaletteOutput::handle_event()
614 {
615         return 1;
616 }
617
618 int PaletteOutput::draw()
619 {
620         int r = 255*window->rgb.r + 0.5f;
621         int g = 255*window->rgb.g + 0.5f;
622         int b = 255*window->rgb.b + 0.5f;
623         set_color((r << 16) | (g << 8) | (b << 0));
624         draw_box(2, 2, get_w() - 4, get_h() - 4);
625         draw_3d_border(0, 0, get_w(), get_h(), 1);
626         return 0;
627 }
628
629 PaletteHue::PaletteHue(ColorWindow *window, int x, int y)
630  : BC_ISlider(x, y, 0, 150, 200, 0, 359, (int)(window->hsv.h), 0)
631 {
632         this->window = window;
633 }
634 PaletteHue::~PaletteHue()
635 {
636 }
637
638 int PaletteHue::handle_event()
639 {
640         window->hsv.h = get_value();
641         window->update_hsv();
642         window->handle_event();
643         return 1;
644 }
645
646 PaletteSat::PaletteSat(ColorWindow *window, int x, int y)
647  : BC_FSlider(x, y, 0, 150, 200, 0, 1.0, window->hsv.s, 0)
648 {
649         this->window = window;
650         set_precision(0.01);
651 }
652 PaletteSat::~PaletteSat()
653 {
654 }
655
656 int PaletteSat::handle_event()
657 {
658         window->hsv.s = get_value();
659         window->update_hsv();
660         window->handle_event();
661         return 1;
662 }
663
664
665 PaletteVal::PaletteVal(ColorWindow *window, int x, int y)
666  : BC_FSlider(x, y, 0, 150, 200, 0, 1.0, window->hsv.v, 0)
667 {
668         this->window = window;
669         set_precision(0.01);
670 }
671 PaletteVal::~PaletteVal()
672 {
673 }
674
675 int PaletteVal::handle_event()
676 {
677         window->hsv.v = get_value();
678         window->update_hsv();
679         window->handle_event();
680         return 1;
681 }
682
683
684 PaletteRed::PaletteRed(ColorWindow *window, int x, int y)
685  : BC_FSlider(x, y, 0, 150, 200, 0, 1, window->rgb.r, 0)
686 {
687         this->window = window;
688         set_precision(0.01);
689 }
690 PaletteRed::~PaletteRed()
691 {
692 }
693
694 int PaletteRed::handle_event()
695 {
696         window->rgb.r = get_value();
697         window->update_rgb();
698         window->handle_event();
699         return 1;
700 }
701
702 PaletteGrn::PaletteGrn(ColorWindow *window, int x, int y)
703  : BC_FSlider(x, y, 0, 150, 200, 0, 1, window->rgb.g, 0)
704 {
705         this->window = window;
706         set_precision(0.01);
707 }
708 PaletteGrn::~PaletteGrn()
709 {
710 }
711
712 int PaletteGrn::handle_event()
713 {
714         window->rgb.g = get_value();
715         window->update_rgb();
716         window->handle_event();
717         return 1;
718 }
719
720 PaletteBlu::PaletteBlu(ColorWindow *window, int x, int y)
721  : BC_FSlider(x, y, 0, 150, 200, 0, 1, window->rgb.b, 0)
722 {
723         this->window = window;
724         set_precision(0.01);
725 }
726 PaletteBlu::~PaletteBlu()
727 {
728 }
729
730 int PaletteBlu::handle_event()
731 {
732         window->rgb.b = get_value();
733         window->update_rgb();
734         window->handle_event();
735         return 1;
736 }
737
738 PaletteAlpha::PaletteAlpha(ColorWindow *window, int x, int y)
739  : BC_FSlider(x, y, 0, 150, 200, 0, 1, window->aph, 0)
740 {
741         this->window = window;
742         set_precision(0.01);
743 }
744 PaletteAlpha::~PaletteAlpha()
745 {
746 }
747
748 int PaletteAlpha::handle_event()
749 {
750         window->aph = get_value();
751         window->handle_event();
752         return 1;
753 }
754
755 PaletteLum::PaletteLum(ColorWindow *window, int x, int y)
756  : BC_FSlider(x, y, 0, 150, 200, 0, 1, window->yuv.y, 0)
757 {
758         this->window = window;
759         set_precision(0.01);
760 }
761 PaletteLum::~PaletteLum()
762 {
763 }
764
765 int PaletteLum::handle_event()
766 {
767         window->yuv.y = get_value();
768         window->update_yuv();
769         window->handle_event();
770         return 1;
771 }
772
773 PaletteCr::PaletteCr(ColorWindow *window, int x, int y)
774  : BC_FSlider(x, y, 0, 150, 200, 0, 1, window->yuv.u, 0)
775 {
776         this->window = window;
777         set_precision(0.01);
778 }
779 PaletteCr::~PaletteCr()
780 {
781 }
782
783 int PaletteCr::handle_event()
784 {
785         window->yuv.u = get_value();
786         window->update_yuv();
787         window->handle_event();
788         return 1;
789 }
790
791 PaletteCb::PaletteCb(ColorWindow *window, int x, int y)
792  : BC_FSlider(x, y, 0, 150, 200, 0, 1, window->yuv.v, 0)
793 {
794         this->window = window;
795         set_precision(0.01);
796 }
797 PaletteCb::~PaletteCb()
798 {
799 }
800
801 int PaletteCb::handle_event()
802 {
803         window->yuv.v = get_value();
804         window->update_yuv();
805         window->handle_event();
806         return 1;
807 }
808
809 void ColorWindow::update_rgb(float r, float g, float b)
810 {
811         { float y, u, v;
812         YUV::rgb_to_yuv_f(r, g, b, y, u, v);
813         u += 0.5f;  v += 0.5f;
814         bclamp(y, 0, 1);    yuv.y = y;
815         bclamp(u, 0, 1);    yuv.u = u;
816         bclamp(v, 0, 1);    yuv.v = v; }
817         { float h, s, v;
818         HSV::rgb_to_hsv(r,g,b, h,s,v);
819         bclamp(h, 0, 360);  hsv.h = h;
820         bclamp(s, 0, 1);    hsv.s = s;
821         bclamp(v, 0, 1);    hsv.v = v; }
822 }
823
824 void ColorWindow::update_yuv(float y, float u, float v)
825 {
826         u -= 0.5f;  v -= 0.5f;
827         { float r, g, b;
828         YUV::yuv_to_rgb_f(r, g, b, y, u, v);
829         bclamp(r, 0, 1);   rgb.r = r;
830         bclamp(g, 0, 1);   rgb.g = g;
831         bclamp(b, 0, 1);   rgb.b = b;
832         float h, s, v;
833         HSV::rgb_to_hsv(r,g,b, h, s, v);
834         bclamp(h, 0, 360); hsv.h = h;
835         bclamp(s, 0, 1);   hsv.s = s;
836         bclamp(v, 0, 1);   hsv.v = v; }
837 }
838
839 void ColorWindow::update_hsv(float h, float s, float v)
840 {
841         { float r, g, b;
842         HSV::hsv_to_rgb(r,g,b, h,s,v);
843         bclamp(r, 0, 1);   rgb.r = r;
844         bclamp(g, 0, 1);   rgb.g = g;
845         bclamp(b, 0, 1);   rgb.b = b;
846         float y, u, v;
847         YUV::rgb_to_yuv_f(r, g, b, y, u, v);
848         u += 0.5f;  v += 0.5f;
849         bclamp(y, 0, 1);   yuv.y = y;
850         bclamp(u, 0, 1);   yuv.u = u;
851         bclamp(v, 0, 1);   yuv.v = v; }
852 }
853
854 PalletteNum::PalletteNum(ColorWindow *window, int x, int y,
855         float &output, float min, float max)
856  : BC_TumbleTextBox(window, output, min, max, x, y, 64)
857 {
858         this->window = window;
859         this->output = &output;
860         set_increment(0.01);
861 }
862
863 PalletteNum::~PalletteNum()
864 {
865 }
866
867
868 int PalletteHSV::handle_event()
869 {
870         update_output();
871         window->update_hsv();
872         window->update_display();
873         window->handle_event();
874         return 1;
875 }
876
877 int PalletteRGB::handle_event()
878 {
879         update_output();
880         window->update_rgb();
881         window->update_display();
882         window->handle_event();
883         return 1;
884 }
885
886 int PalletteYUV::handle_event()
887 {
888         update_output();
889         window->update_yuv();
890         window->update_display();
891         window->handle_event();
892         return 1;
893 }
894
895 int PalletteAPH::handle_event()
896 {
897         update_output();
898         window->update_display();
899         window->handle_event();
900         return 1;
901 }
902