update internationalization data
[goodguy/history.git] / cinelerra-5.0 / plugins / histogram / histogram.C
1
2 /*
3  * CINELERRA
4  * Copyright (C) 2008-2012 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 <math.h>
23 #include <stdint.h>
24 #include <string.h>
25 #include <unistd.h>
26
27 #include "bcdisplayinfo.h"
28 #include "bcsignals.h"
29 #include "clip.h"
30 #include "bchash.h"
31 #include "filexml.h"
32 #include "histogram.h"
33 #include "histogramconfig.h"
34 #include "histogramwindow.h"
35 #include "keyframe.h"
36 #include "language.h"
37 #include "loadbalance.h"
38 #include "playback3d.h"
39 #include "cicolors.h"
40 #include "vframe.h"
41 #include "workarounds.h"
42
43 #include "aggregated.h"
44 #include "../colorbalance/aggregated.h"
45 #include "../interpolate/aggregated.h"
46 #include "../gamma/aggregated.h"
47
48 class HistogramMain;
49 class HistogramEngine;
50 class HistogramWindow;
51
52
53
54
55
56 REGISTER_PLUGIN(HistogramMain)
57
58
59
60
61
62
63
64
65
66 HistogramMain::HistogramMain(PluginServer *server)
67  : PluginVClient(server)
68 {
69         
70         engine = 0;
71         for(int i = 0; i < HISTOGRAM_MODES; i++)
72         {
73                 lookup[i] = 0;
74                 accum[i] = 0;
75                 preview_lookup[i] = 0;
76         }
77         current_point = -1;
78         mode = HISTOGRAM_VALUE;
79         dragging_point = 0;
80         input = 0;
81         output = 0;
82         w = 440;
83         h = 500;
84         parade = 0;
85 }
86
87 HistogramMain::~HistogramMain()
88 {
89         
90         for(int i = 0; i < HISTOGRAM_MODES;i++)
91         {
92                 delete [] lookup[i];
93                 delete [] accum[i];
94                 delete [] preview_lookup[i];
95         }
96         delete engine;
97 }
98
99 const char* HistogramMain::plugin_title() { return _("Histogram"); }
100 int HistogramMain::is_realtime() { return 1; }
101
102
103
104 NEW_WINDOW_MACRO(HistogramMain, HistogramWindow)
105
106 LOAD_CONFIGURATION_MACRO(HistogramMain, HistogramConfig)
107
108 void HistogramMain::render_gui(void *data)
109 {
110         if(thread)
111         {
112 // Process just the RGB values to determine the automatic points or
113 // all the points if manual
114                 if(!config.automatic)
115                 {
116 // Generate curves for value histogram
117 // Lock out changes to curves
118                         ((HistogramWindow*)thread->window)->lock_window("HistogramMain::render_gui 1");
119                         tabulate_curve(HISTOGRAM_RED, 0);
120                         tabulate_curve(HISTOGRAM_GREEN, 0);
121                         tabulate_curve(HISTOGRAM_BLUE, 0);
122                         ((HistogramWindow*)thread->window)->unlock_window();
123                 }
124
125                 calculate_histogram((VFrame*)data, !config.automatic);
126
127
128                 if(config.automatic)
129                 {
130                         calculate_automatic((VFrame*)data);
131
132 // Generate curves for value histogram
133 // Lock out changes to curves
134                         ((HistogramWindow*)thread->window)->lock_window("HistogramMain::render_gui 1");
135                         tabulate_curve(HISTOGRAM_RED, 0);
136                         tabulate_curve(HISTOGRAM_GREEN, 0);
137                         tabulate_curve(HISTOGRAM_BLUE, 0);
138                         ((HistogramWindow*)thread->window)->unlock_window();
139
140
141 // Need a second pass to get the luminance values.
142                         calculate_histogram((VFrame*)data, 1);
143                 }
144
145                 ((HistogramWindow*)thread->window)->lock_window("HistogramMain::render_gui 2");
146 // Always draw the histogram but don't update widgets if automatic
147                 ((HistogramWindow*)thread->window)->update(1,
148                         config.automatic && mode != HISTOGRAM_VALUE,
149                         config.automatic && mode != HISTOGRAM_VALUE,
150                         0);
151
152                 ((HistogramWindow*)thread->window)->unlock_window();
153         }
154 }
155
156 void HistogramMain::update_gui()
157 {
158         if(thread)
159         {
160                 ((HistogramWindow*)thread->window)->lock_window("HistogramMain::update_gui");
161                 int reconfigure = load_configuration();
162                 if(reconfigure) 
163                 {
164                         ((HistogramWindow*)thread->window)->update(1,
165                                 1,
166                                 1,
167                                 1);
168                 }
169                 ((HistogramWindow*)thread->window)->unlock_window();
170         }
171 }
172
173
174
175
176 void HistogramMain::save_data(KeyFrame *keyframe)
177 {
178         FileXML output;
179
180 // cause data to be stored directly in text
181         output.set_shared_output(keyframe->get_data(), MESSAGESIZE);
182         output.tag.set_title("HISTOGRAM");
183
184         char string[BCTEXTLEN];
185
186         output.tag.set_property("AUTOMATIC", config.automatic);
187         output.tag.set_property("THRESHOLD", config.threshold);
188         output.tag.set_property("PLOT", config.plot);
189         output.tag.set_property("SPLIT", config.split);
190         output.tag.set_property("W", w);
191         output.tag.set_property("H", h);
192         output.tag.set_property("PARADE", parade);
193         output.tag.set_property("MODE", mode);
194
195         for(int i = 0; i < HISTOGRAM_MODES; i++)
196         {
197                 sprintf(string, "LOW_OUTPUT_%d", i);
198                 output.tag.set_property(string, config.low_output[i]);
199                 sprintf(string, "HIGH_OUTPUT_%d", i);
200                 output.tag.set_property(string, config.high_output[i]);
201                 sprintf(string, "LOW_INPUT_%d", i);
202                 output.tag.set_property(string, config.low_input[i]);
203                 sprintf(string, "HIGH_INPUT_%d", i);
204                 output.tag.set_property(string, config.high_input[i]);
205                 sprintf(string, "GAMMA_%d", i);
206                 output.tag.set_property(string, config.gamma[i]);
207 //printf("HistogramMain::save_data %d %f %d\n", config.input_min[i], config.input_mid[i], config.input_max[i]);
208         }
209
210         output.append_tag();
211         output.append_newline();
212
213
214
215
216
217
218         output.terminate_string();
219 }
220
221 void HistogramMain::read_data(KeyFrame *keyframe)
222 {
223         FileXML input;
224
225         input.set_shared_input(keyframe->get_data(), strlen(keyframe->get_data()));
226
227         int result = 0;
228
229
230         while(!result)
231         {
232                 result = input.read_tag();
233
234                 if(!result)
235                 {
236                         if(input.tag.title_is("HISTOGRAM"))
237                         {
238                                 config.automatic = input.tag.get_property("AUTOMATIC", config.automatic);
239                                 config.threshold = input.tag.get_property("THRESHOLD", config.threshold);
240                                 config.plot = input.tag.get_property("PLOT", config.plot);
241                                 config.split = input.tag.get_property("SPLIT", config.split);
242
243                                 if(is_defaults())
244                                 {
245                                         w = input.tag.get_property("W", w);
246                                         h = input.tag.get_property("H", h);
247                                         parade = input.tag.get_property("PARADE", parade);
248                                         mode = input.tag.get_property("MODE", mode);
249                                 }
250
251                                 char string[BCTEXTLEN];
252                                 for(int i = 0; i < HISTOGRAM_MODES; i++)
253                                 {
254                                         sprintf(string, "LOW_OUTPUT_%d", i);
255                                         config.low_output[i] = input.tag.get_property(string, config.low_output[i]);
256                                         sprintf(string, "HIGH_OUTPUT_%d", i);
257                                         config.high_output[i] = input.tag.get_property(string, config.high_output[i]);
258                                         sprintf(string, "GAMMA_%d", i);
259                                         config.gamma[i] = input.tag.get_property(string, config.gamma[i]);
260
261                                         if(i == HISTOGRAM_VALUE || !config.automatic)
262                                         {
263                                                 sprintf(string, "LOW_INPUT_%d", i);
264                                                 config.low_input[i] = input.tag.get_property(string, config.low_input[i]);
265                                                 sprintf(string, "HIGH_INPUT_%d", i);
266                                                 config.high_input[i] = input.tag.get_property(string, config.high_input[i]);
267                                         }
268 //printf("HistogramMain::read_data %d %f %d\n", config.input_min[i], config.input_mid[i], config.input_max[i]);
269                                 }
270                         }
271                 }
272         }
273
274         config.boundaries();
275
276 }
277
278 float HistogramMain::calculate_level(float input, 
279         int mode,
280         int use_value)
281 {
282         float output = 0.0;
283
284 // Scale to input range
285         if(!EQUIV(config.high_input[mode], config.low_input[mode]))
286         {
287                 output = (input - config.low_input[mode]) /
288                         (config.high_input[mode] - config.low_input[mode]);
289         }
290         else
291         {
292                 output = input;
293         }
294         
295
296
297         if(!EQUIV(config.gamma[mode], 0))
298         {
299                 output = pow(output, 1.0 / config.gamma[mode]);
300                 CLAMP(output, 0, 1.0);
301         }
302
303 // Apply value curve
304         if(use_value && mode != HISTOGRAM_VALUE)
305         {
306                 output = calculate_level(output, HISTOGRAM_VALUE, 0);
307         }
308
309
310
311
312 // scale to output range
313         if(!EQUIV(config.low_output[mode], config.high_output[mode]))
314         {
315                 output = output * (config.high_output[mode] - config.low_output[mode]) +
316                         config.low_output[mode];
317         }
318
319         CLAMP(output, 0, 1.0);
320
321         return output;
322 }
323
324
325
326 void HistogramMain::calculate_histogram(VFrame *data, int do_value)
327 {
328
329         if(!engine) engine = new HistogramEngine(this,
330                 get_project_smp() + 1,
331                 get_project_smp() + 1);
332
333         if(!accum[0])
334         {
335                 for(int i = 0; i < HISTOGRAM_MODES; i++)
336                         accum[i] = new int[HISTOGRAM_SLOTS];
337         }
338
339         engine->process_packages(HistogramEngine::HISTOGRAM, data, do_value);
340
341         for(int i = 0; i < engine->get_total_clients(); i++)
342         {
343                 HistogramUnit *unit = (HistogramUnit*)engine->get_client(i);
344
345                 if(i == 0)
346                 {
347                         for(int j = 0; j < HISTOGRAM_MODES; j++)
348                         {
349                                 memcpy(accum[j], unit->accum[j], sizeof(int) * HISTOGRAM_SLOTS);
350                         }
351                 }
352                 else
353                 {
354                         for(int j = 0; j < HISTOGRAM_MODES; j++)
355                         {
356                                 int *out = accum[j];
357                                 int *in = unit->accum[j];
358                                 for(int k = 0; k < HISTOGRAM_SLOTS; k++)
359                                         out[k] += in[k];
360                         }
361                 }
362         }
363
364 // Remove top and bottom from calculations.  Doesn't work in high
365 // precision colormodels.
366         for(int i = 0; i < HISTOGRAM_MODES; i++)
367         {
368                 accum[i][0] = 0;
369                 accum[i][HISTOGRAM_SLOTS - 1] = 0;
370         }
371 }
372
373
374 void HistogramMain::calculate_automatic(VFrame *data)
375 {
376         calculate_histogram(data, 0);
377         config.reset_points(1);
378
379 // Do each channel
380         for(int i = 0; i < 3; i++)
381         {
382                 int *accum = this->accum[i];
383                 int pixels = data->get_w() * data->get_h();
384                 float white_fraction = 1.0 - (1.0 - config.threshold) / 2;
385                 int threshold = (int)(white_fraction * pixels);
386                 int total = 0;
387                 float max_level = 1.0;
388                 float min_level = 0.0;
389
390 // Get histogram slot above threshold of pixels
391                 for(int j = 0; j < HISTOGRAM_SLOTS; j++)
392                 {
393                         total += accum[j];
394                         if(total >= threshold)
395                         {
396                                 max_level = (float)j / HISTOGRAM_SLOTS * FLOAT_RANGE + HIST_MIN_INPUT;
397                                 break;
398                         }
399                 }
400
401 // Get slot below 99% of pixels
402                 total = 0;
403                 for(int j = HISTOGRAM_SLOTS - 1; j >= 0; j--)
404                 {
405                         total += accum[j];
406                         if(total >= threshold)
407                         {
408                                 min_level = (float)j / HISTOGRAM_SLOTS * FLOAT_RANGE + HIST_MIN_INPUT;
409                                 break;
410                         }
411                 }
412
413
414                 config.low_input[i] = min_level;
415                 config.high_input[i] = max_level;
416         }
417 }
418
419
420
421
422
423 int HistogramMain::calculate_use_opengl()
424 {
425 // glHistogram doesn't work.
426         int result = get_use_opengl() &&
427                 !config.automatic && 
428                 (!config.plot || !gui_open());
429         return result;
430 }
431
432
433 int HistogramMain::process_buffer(VFrame *frame,
434         int64_t start_position,
435         double frame_rate)
436 {
437         int need_reconfigure = load_configuration();
438
439
440
441         int use_opengl = calculate_use_opengl();
442
443 //printf("%d\n", use_opengl);
444         read_frame(frame, 
445                 0, 
446                 start_position, 
447                 frame_rate,
448                 use_opengl);
449
450 // Apply histogram in hardware
451         if(use_opengl) return run_opengl();
452
453         if(!engine) engine = new HistogramEngine(this,
454                 get_project_smp() + 1,
455                 get_project_smp() + 1);
456         this->input = frame;
457         this->output = frame;
458 // Always plot to set the curves if automatic
459         if(config.plot || config.automatic) send_render_gui(frame);
460
461 // Generate tables here.  The same table is used by many packages to render
462 // each horizontal stripe.  Need to cover the entire output range in  each
463 // table to avoid green borders
464
465
466         if(need_reconfigure || 
467                 !lookup[0] || 
468                 config.automatic)
469         {
470 // Calculate new curves
471                 if(config.automatic)
472                 {
473                         calculate_automatic(input);
474                 }
475
476
477 // Generate transfer tables with value function for integer colormodels.
478                 for(int i = 0; i < 3; i++)
479                         tabulate_curve(i, 1);
480         }
481
482 // printf("HistogramMain::process_buffer %d %f %f %f  %f %f %f  %f %f %f\n", 
483 // __LINE__, 
484 // config.low_input[HISTOGRAM_RED],
485 // config.gamma[HISTOGRAM_RED],
486 // config.high_input[HISTOGRAM_RED],
487 // config.low_input[HISTOGRAM_GREEN],
488 // config.gamma[HISTOGRAM_GREEN],
489 // config.high_input[HISTOGRAM_GREEN],
490 // config.low_input[HISTOGRAM_BLUE],
491 // config.gamma[HISTOGRAM_BLUE],
492 // config.high_input[HISTOGRAM_BLUE]);
493
494
495
496 // Apply histogram
497         engine->process_packages(HistogramEngine::APPLY, input, 0);
498
499
500         return 0;
501 }
502
503 void HistogramMain::tabulate_curve(int subscript, int use_value)
504 {
505         int i;
506         if(!lookup[subscript])
507                 lookup[subscript] = new int[HISTOGRAM_SLOTS];
508         if(!preview_lookup[subscript])
509                 preview_lookup[subscript] = new int[HISTOGRAM_SLOTS];
510
511 //printf("HistogramMain::tabulate_curve %d input=%p\n", __LINE__, input);
512
513
514 // Generate lookup tables for integer colormodels
515         if(input)
516         {
517                 switch(input->get_color_model())
518                 {
519                         case BC_RGB888:
520                         case BC_RGBA8888:
521                                 for(i = 0; i < 0x100; i++)
522                                 {
523                                         lookup[subscript][i] = 
524                                                 (int)(calculate_level((float)i / 0xff, subscript, use_value) * 
525                                                 0xff);
526                                         CLAMP(lookup[subscript][i], 0, 0xff);
527                                 }
528                                 break;
529 // All other integer colormodels are converted to 16 bit RGB
530                         default:
531                                 for(i = 0; i < 0x10000; i++)
532                                 {
533                                         lookup[subscript][i] = 
534                                                 (int)(calculate_level((float)i / 0xffff, subscript, use_value) * 
535                                                 0xffff);
536                                         CLAMP(lookup[subscript][i], 0, 0xffff);
537                                 }
538 // for(i = 0; i < 0x100; i++)
539 // {
540 // if(subscript == HISTOGRAM_BLUE) printf("%d ", lookup[subscript][i * 0x100]);
541 // }
542 // if(subscript == HISTOGRAM_BLUE) printf("\n");
543
544                                 break;
545                 }
546         }
547
548 // Lookup table for preview only used for GUI
549         if(!use_value)
550         {
551                 for(i = 0; i < 0x10000; i++)
552                 {
553                         preview_lookup[subscript][i] = 
554                                 (int)(calculate_level((float)i / 0xffff, subscript, use_value) * 
555                                 0xffff);
556                         CLAMP(preview_lookup[subscript][i], 0, 0xffff);
557                 }
558         }
559 }
560
561 int HistogramMain::handle_opengl()
562 {
563 #ifdef HAVE_GL
564 // Functions to get pixel from either previous effect or texture
565         static const char *histogram_get_pixel1 =
566                 "vec4 histogram_get_pixel()\n"
567                 "{\n"
568                 "       return gl_FragColor;\n"
569                 "}\n";
570
571         static const char *histogram_get_pixel2 =
572                 "uniform sampler2D tex;\n"
573                 "vec4 histogram_get_pixel()\n"
574                 "{\n"
575                 "       return texture2D(tex, gl_TexCoord[0].st);\n"
576                 "}\n";
577
578         static const char *head_frag = 
579                 "uniform vec4 low_input;\n"
580                 "uniform vec4 high_input;\n"
581                 "uniform vec4 gamma;\n"
582                 "uniform vec4 low_output;\n"
583                 "uniform vec4 output_scale;\n"
584                 "void main()\n"
585                 "{\n"
586                 "       float temp = 0.0;\n";
587
588         static const char *get_rgb_frag =
589                 "       vec4 pixel = histogram_get_pixel();\n";
590
591         static const char *get_yuv_frag =
592                 "       vec4 pixel = histogram_get_pixel();\n"
593                         YUV_TO_RGB_FRAG("pixel");
594
595 #define APPLY_INPUT_CURVE(PIXEL, LOW_INPUT, HIGH_INPUT, GAMMA) \
596                 "// apply input curve\n" \
597                 "       temp = (" PIXEL " - " LOW_INPUT ") / \n" \
598                 "               (" HIGH_INPUT " - " LOW_INPUT ");\n" \
599                 "       temp = max(temp, 0.0);\n" \
600                 "       " PIXEL " = pow(temp, 1.0 / " GAMMA ");\n"
601
602
603
604         static const char *apply_histogram_frag = 
605                 APPLY_INPUT_CURVE("pixel.r", "low_input.r", "high_input.r", "gamma.r")
606                 APPLY_INPUT_CURVE("pixel.g", "low_input.g", "high_input.g", "gamma.g")
607                 APPLY_INPUT_CURVE("pixel.b", "low_input.b", "high_input.b", "gamma.b")
608                 "// apply output curve\n"
609                 "       pixel.rgb *= output_scale.rgb;\n"
610                 "       pixel.rgb += low_output.rgb;\n"
611                 APPLY_INPUT_CURVE("pixel.r", "low_input.a", "high_input.a", "gamma.a")
612                 APPLY_INPUT_CURVE("pixel.g", "low_input.a", "high_input.a", "gamma.a")
613                 APPLY_INPUT_CURVE("pixel.b", "low_input.a", "high_input.a", "gamma.a")
614                 "// apply output curve\n"
615                 "       pixel.rgb *= vec3(output_scale.a, output_scale.a, output_scale.a);\n"
616                 "       pixel.rgb += vec3(low_output.a, low_output.a, low_output.a);\n";
617
618         static const char *put_rgb_frag =
619                 "       gl_FragColor = pixel;\n"
620                 "}\n";
621
622         static const char *put_yuv_frag =
623                         RGB_TO_YUV_FRAG("pixel")
624                 "       gl_FragColor = pixel;\n"
625                 "}\n";
626
627
628
629         get_output()->to_texture();
630         get_output()->enable_opengl();
631
632         const char *shader_stack[] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
633         int current_shader = 0;
634         int aggregate_interpolation = 0;
635         int aggregate_gamma = 0;
636         int aggregate_colorbalance = 0;
637 // All aggregation possibilities must be accounted for because unsupported
638 // effects can get in between the aggregation members.
639         if(!strcmp(get_output()->get_prev_effect(2), _("Interpolate Pixels")) &&
640                 !strcmp(get_output()->get_prev_effect(1), _("Gamma")) &&
641                 !strcmp(get_output()->get_prev_effect(0), _("Color Balance")))
642         {
643                 aggregate_interpolation = 1;
644                 aggregate_gamma = 1;
645                 aggregate_colorbalance = 1;
646         }
647         else
648         if(!strcmp(get_output()->get_prev_effect(1), _("Gamma")) &&
649                 !strcmp(get_output()->get_prev_effect(0), _("Color Balance")))
650         {
651                 aggregate_gamma = 1;
652                 aggregate_colorbalance = 1;
653         }
654         else
655         if(!strcmp(get_output()->get_prev_effect(1), _("Interpolate Pixels")) &&
656                 !strcmp(get_output()->get_prev_effect(0), _("Gamma")))
657         {
658                 aggregate_interpolation = 1;
659                 aggregate_gamma = 1;
660         }
661         else
662         if(!strcmp(get_output()->get_prev_effect(1), _("Interpolate Pixels")) &&
663                 !strcmp(get_output()->get_prev_effect(0), _("Color Balance")))
664         {
665                 aggregate_interpolation = 1;
666                 aggregate_colorbalance = 1;
667         }
668         else
669         if(!strcmp(get_output()->get_prev_effect(0), _("Interpolate Pixels")))
670                 aggregate_interpolation = 1;
671         else
672         if(!strcmp(get_output()->get_prev_effect(0), _("Gamma")))
673                 aggregate_gamma = 1;
674         else
675         if(!strcmp(get_output()->get_prev_effect(0), _("Color Balance")))
676                 aggregate_colorbalance = 1;
677
678
679 // The order of processing is fixed by this sequence
680         if(aggregate_interpolation)
681                 INTERPOLATE_COMPILE(shader_stack, 
682                         current_shader)
683
684         if(aggregate_gamma)
685                 GAMMA_COMPILE(shader_stack, 
686                         current_shader, 
687                         aggregate_interpolation)
688
689         if(aggregate_colorbalance)
690                 COLORBALANCE_COMPILE(shader_stack, 
691                         current_shader, 
692                         aggregate_interpolation || aggregate_gamma)
693
694
695         if(aggregate_interpolation || aggregate_gamma || aggregate_colorbalance)
696                 shader_stack[current_shader++] = histogram_get_pixel1;
697         else
698                 shader_stack[current_shader++] = histogram_get_pixel2;
699
700         unsigned int shader = 0;
701         switch(get_output()->get_color_model())
702         {
703                 case BC_YUV888:
704                 case BC_YUVA8888:
705                         shader_stack[current_shader++] = head_frag;
706                         shader_stack[current_shader++] = get_yuv_frag;
707                         shader_stack[current_shader++] = apply_histogram_frag;
708                         shader_stack[current_shader++] = put_yuv_frag;
709                         break;
710                 default:
711                         shader_stack[current_shader++] = head_frag;
712                         shader_stack[current_shader++] = get_rgb_frag;
713                         shader_stack[current_shader++] = apply_histogram_frag;
714                         shader_stack[current_shader++] = put_rgb_frag;
715                         break;
716         }
717
718         shader = VFrame::make_shader(0,
719                 shader_stack[0],
720                 shader_stack[1],
721                 shader_stack[2],
722                 shader_stack[3],
723                 shader_stack[4],
724                 shader_stack[5],
725                 shader_stack[6],
726                 shader_stack[7],
727                 shader_stack[8],
728                 shader_stack[9],
729                 shader_stack[10],
730                 shader_stack[11],
731                 shader_stack[12],
732                 shader_stack[13],
733                 shader_stack[14],
734                 shader_stack[15],
735                 0);
736
737 // printf("HistogramMain::handle_opengl %d %d %d %d shader=%d\n", 
738 // aggregate_interpolation, 
739 // aggregate_gamma,
740 // aggregate_colorbalance,
741 // current_shader,
742 // shader);
743
744         float low_input[4];
745         float high_input[4];
746         float gamma[4];
747         float low_output[4];
748         float output_scale[4];
749
750
751 // printf("min x    min y    max x    max y\n");
752 // printf("%f %f %f %f\n", input_min_r[0], input_min_r[1], input_max_r[0], input_max_r[1]);
753 // printf("%f %f %f %f\n", input_min_g[0], input_min_g[1], input_max_g[0], input_max_g[1]);
754 // printf("%f %f %f %f\n", input_min_b[0], input_min_b[1], input_max_b[0], input_max_b[1]);
755 // printf("%f %f %f %f\n", input_min_v[0], input_min_v[1], input_max_v[0], input_max_v[1]);
756
757         for(int i = 0; i < HISTOGRAM_MODES; i++)
758         {
759                 low_input[i] = config.low_input[i];
760                 high_input[i] = config.high_input[i];
761                 gamma[i] = config.gamma[i];
762                 low_output[i] = config.low_output[i];
763                 output_scale[i] = config.high_output[i] - config.low_output[i];
764         }
765
766         if(shader > 0)
767         {
768                 glUseProgram(shader);
769                 glUniform1i(glGetUniformLocation(shader, "tex"), 0);
770                 if(aggregate_gamma) GAMMA_UNIFORMS(shader)
771                 if(aggregate_interpolation) INTERPOLATE_UNIFORMS(shader)
772                 if(aggregate_colorbalance) COLORBALANCE_UNIFORMS(shader)
773                 glUniform4fv(glGetUniformLocation(shader, "low_input"), 1, low_input);
774                 glUniform4fv(glGetUniformLocation(shader, "high_input"), 1, high_input);
775                 glUniform4fv(glGetUniformLocation(shader, "gamma"), 1, gamma);
776                 glUniform4fv(glGetUniformLocation(shader, "low_output"), 1, low_output);
777                 glUniform4fv(glGetUniformLocation(shader, "output_scale"), 1, output_scale);
778         }
779
780         get_output()->init_screen();
781         get_output()->bind_texture(0);
782
783         glDisable(GL_BLEND);
784
785 // Draw the affected half
786         if(config.split)
787         {
788                 glBegin(GL_TRIANGLES);
789                 glNormal3f(0, 0, 1.0);
790
791                 glTexCoord2f(0.0 / get_output()->get_texture_w(), 
792                         0.0 / get_output()->get_texture_h());
793                 glVertex3f(0.0, -(float)get_output()->get_h(), 0);
794
795
796                 glTexCoord2f((float)get_output()->get_w() / get_output()->get_texture_w(), 
797                         (float)get_output()->get_h() / get_output()->get_texture_h());
798                 glVertex3f((float)get_output()->get_w(), -0.0, 0);
799
800                 glTexCoord2f(0.0 / get_output()->get_texture_w(), 
801                         (float)get_output()->get_h() / get_output()->get_texture_h());
802                 glVertex3f(0.0, -0.0, 0);
803
804
805                 glEnd();
806         }
807         else
808         {
809                 get_output()->draw_texture();
810         }
811
812         glUseProgram(0);
813
814 // Draw the unaffected half
815         if(config.split)
816         {
817                 glBegin(GL_TRIANGLES);
818                 glNormal3f(0, 0, 1.0);
819
820
821                 glTexCoord2f(0.0 / get_output()->get_texture_w(), 
822                         0.0 / get_output()->get_texture_h());
823                 glVertex3f(0.0, -(float)get_output()->get_h(), 0);
824
825                 glTexCoord2f((float)get_output()->get_w() / get_output()->get_texture_w(), 
826                         0.0 / get_output()->get_texture_h());
827                 glVertex3f((float)get_output()->get_w(), 
828                         -(float)get_output()->get_h(), 0);
829
830                 glTexCoord2f((float)get_output()->get_w() / get_output()->get_texture_w(), 
831                         (float)get_output()->get_h() / get_output()->get_texture_h());
832                 glVertex3f((float)get_output()->get_w(), -0.0, 0);
833
834
835                 glEnd();
836         }
837
838         get_output()->set_opengl_state(VFrame::SCREEN);
839 #endif
840         return 0;
841 }
842
843
844
845
846
847
848
849
850
851
852
853
854 HistogramPackage::HistogramPackage()
855  : LoadPackage()
856 {
857 }
858
859
860
861
862 HistogramUnit::HistogramUnit(HistogramEngine *server, 
863         HistogramMain *plugin)
864  : LoadClient(server)
865 {
866         this->plugin = plugin;
867         this->server = server;
868         for(int i = 0; i < HISTOGRAM_MODES; i++)
869                 accum[i] = new int[HISTOGRAM_SLOTS];
870 }
871
872 HistogramUnit::~HistogramUnit()
873 {
874         for(int i = 0; i < HISTOGRAM_MODES; i++)
875                 delete [] accum[i];
876 }
877
878 void HistogramUnit::process_package(LoadPackage *package)
879 {
880         HistogramPackage *pkg = (HistogramPackage*)package;
881
882         if(server->operation == HistogramEngine::HISTOGRAM)
883         {
884                 int do_value = server->do_value;
885
886
887 #define HISTOGRAM_HEAD(type) \
888 { \
889         for(int i = pkg->start; i < pkg->end; i++) \
890         { \
891                 type *row = (type*)data->get_rows()[i]; \
892                 for(int j = 0; j < w; j++) \
893                 {
894
895 #define HISTOGRAM_TAIL(components) \
896 /* Value takes the maximum of the output RGB values */ \
897                         if(do_value) \
898                         { \
899                                 CLAMP(r, 0, HISTOGRAM_SLOTS - 1); \
900                                 CLAMP(g, 0, HISTOGRAM_SLOTS - 1); \
901                                 CLAMP(b, 0, HISTOGRAM_SLOTS - 1); \
902                                 r_out = lookup_r[r]; \
903                                 g_out = lookup_g[g]; \
904                                 b_out = lookup_b[b]; \
905 /*                              v = (r * 76 + g * 150 + b * 29) >> 8; */ \
906                                 v = MAX(r_out, g_out); \
907                                 v = MAX(v, b_out); \
908                                 v += -HISTOGRAM_MIN * 0xffff / 100; \
909                                 CLAMP(v, 0, HISTOGRAM_SLOTS - 1); \
910                                 accum_v[v]++; \
911                         } \
912  \
913                         r += -HISTOGRAM_MIN * 0xffff / 100; \
914                         g += -HISTOGRAM_MIN * 0xffff / 100; \
915                         b += -HISTOGRAM_MIN * 0xffff / 100; \
916                         CLAMP(r, 0, HISTOGRAM_SLOTS - 1); \
917                         CLAMP(g, 0, HISTOGRAM_SLOTS - 1); \
918                         CLAMP(b, 0, HISTOGRAM_SLOTS - 1); \
919                         accum_r[r]++; \
920                         accum_g[g]++; \
921                         accum_b[b]++; \
922                         row += components; \
923                 } \
924         } \
925 }
926
927
928
929
930                 VFrame *data = server->data;
931                 int w = data->get_w();
932                 //int h = data->get_h();
933                 int *accum_r = accum[HISTOGRAM_RED];
934                 int *accum_g = accum[HISTOGRAM_GREEN];
935                 int *accum_b = accum[HISTOGRAM_BLUE];
936                 int *accum_v = accum[HISTOGRAM_VALUE];
937                 int32_t r, g, b, y, u, v;
938                 int r_out, g_out, b_out;
939                 int *lookup_r = plugin->preview_lookup[HISTOGRAM_RED];
940                 int *lookup_g = plugin->preview_lookup[HISTOGRAM_GREEN];
941                 int *lookup_b = plugin->preview_lookup[HISTOGRAM_BLUE];
942
943                 switch(data->get_color_model())
944                 {
945                         case BC_RGB888:
946                                 HISTOGRAM_HEAD(unsigned char)
947                                 r = (row[0] << 8) | row[0];
948                                 g = (row[1] << 8) | row[1];
949                                 b = (row[2] << 8) | row[2];
950                                 HISTOGRAM_TAIL(3)
951                                 break;
952                         case BC_RGB_FLOAT:
953                                 HISTOGRAM_HEAD(float)
954                                 r = (int)(row[0] * 0xffff);
955                                 g = (int)(row[1] * 0xffff);
956                                 b = (int)(row[2] * 0xffff);
957                                 HISTOGRAM_TAIL(3)
958                                 break;
959                         case BC_YUV888:
960                                 HISTOGRAM_HEAD(unsigned char)
961                                 y = (row[0] << 8) | row[0];
962                                 u = (row[1] << 8) | row[1];
963                                 v = (row[2] << 8) | row[2];
964                                 plugin->yuv.yuv_to_rgb_16(r, g, b, y, u, v);
965                                 HISTOGRAM_TAIL(3)
966                                 break;
967                         case BC_RGBA8888:
968                                 HISTOGRAM_HEAD(unsigned char)
969                                 r = (row[0] << 8) | row[0];
970                                 g = (row[1] << 8) | row[1];
971                                 b = (row[2] << 8) | row[2];
972                                 HISTOGRAM_TAIL(4)
973                                 break;
974                         case BC_RGBA_FLOAT:
975                                 HISTOGRAM_HEAD(float)
976                                 r = (int)(row[0] * 0xffff);
977                                 g = (int)(row[1] * 0xffff);
978                                 b = (int)(row[2] * 0xffff);
979                                 HISTOGRAM_TAIL(4)
980                                 break;
981                         case BC_YUVA8888:
982                                 HISTOGRAM_HEAD(unsigned char)
983                                 y = (row[0] << 8) | row[0];
984                                 u = (row[1] << 8) | row[1];
985                                 v = (row[2] << 8) | row[2];
986                                 plugin->yuv.yuv_to_rgb_16(r, g, b, y, u, v);
987                                 HISTOGRAM_TAIL(4)
988                                 break;
989                         case BC_RGB161616:
990                                 HISTOGRAM_HEAD(uint16_t)
991                                 r = row[0];
992                                 g = row[1];
993                                 b = row[2];
994                                 HISTOGRAM_TAIL(3)
995                                 break;
996                         case BC_YUV161616:
997                                 HISTOGRAM_HEAD(uint16_t)
998                                 y = row[0];
999                                 u = row[1];
1000                                 v = row[2];
1001                                 plugin->yuv.yuv_to_rgb_16(r, g, b, y, u, v);
1002                                 HISTOGRAM_TAIL(3)
1003                                 break;
1004                         case BC_RGBA16161616:
1005                                 HISTOGRAM_HEAD(uint16_t)
1006                                 r = row[0];
1007                                 g = row[1];
1008                                 b = row[2];
1009                                 HISTOGRAM_TAIL(3)
1010                                 break;
1011                         case BC_YUVA16161616:
1012                                 HISTOGRAM_HEAD(uint16_t)
1013                                 y = row[0];
1014                                 u = row[1];
1015                                 v = row[2];
1016                                 plugin->yuv.yuv_to_rgb_16(r, g, b, y, u, v);
1017                                 HISTOGRAM_TAIL(4)
1018                                 break;
1019                 }
1020         }
1021         else
1022         if(server->operation == HistogramEngine::APPLY)
1023         {
1024
1025
1026
1027 #define PROCESS(type, components) \
1028 { \
1029         for(int i = pkg->start; i < pkg->end; i++) \
1030         { \
1031                 type *row = (type*)input->get_rows()[i]; \
1032                 for(int j = 0; j < w; j++) \
1033                 { \
1034                         if ( plugin->config.split && ((j + i * w / h) < w) ) \
1035                         continue; \
1036                         row[0] = lookup_r[row[0]]; \
1037                         row[1] = lookup_g[row[1]]; \
1038                         row[2] = lookup_b[row[2]]; \
1039                         row += components; \
1040                 } \
1041         } \
1042 }
1043
1044 #define PROCESS_YUV(type, components, max) \
1045 { \
1046         for(int i = pkg->start; i < pkg->end; i++) \
1047         { \
1048                 type *row = (type*)input->get_rows()[i]; \
1049                 for(int j = 0; j < w; j++) \
1050                 { \
1051                         if ( plugin->config.split && ((j + i * w / h) < w) ) \
1052                         continue; \
1053 /* Convert to 16 bit RGB */ \
1054                         if(max == 0xff) \
1055                         { \
1056                                 y = (row[0] << 8) | row[0]; \
1057                                 u = (row[1] << 8) | row[1]; \
1058                                 v = (row[2] << 8) | row[2]; \
1059                         } \
1060                         else \
1061                         { \
1062                                 y = row[0]; \
1063                                 u = row[1]; \
1064                                 v = row[2]; \
1065                         } \
1066  \
1067                         plugin->yuv.yuv_to_rgb_16(r, g, b, y, u, v); \
1068  \
1069 /* Look up in RGB domain */ \
1070                         r = lookup_r[r]; \
1071                         g = lookup_g[g]; \
1072                         b = lookup_b[b]; \
1073  \
1074 /* Convert to 16 bit YUV */ \
1075                         plugin->yuv.rgb_to_yuv_16(r, g, b, y, u, v); \
1076  \
1077                         if(max == 0xff) \
1078                         { \
1079                                 row[0] = y >> 8; \
1080                                 row[1] = u >> 8; \
1081                                 row[2] = v >> 8; \
1082                         } \
1083                         else \
1084                         { \
1085                                 row[0] = y; \
1086                                 row[1] = u; \
1087                                 row[2] = v; \
1088                         } \
1089                         row += components; \
1090                 } \
1091         } \
1092 }
1093
1094 #define PROCESS_FLOAT(components) \
1095 { \
1096         for(int i = pkg->start; i < pkg->end; i++) \
1097         { \
1098                 float *row = (float*)input->get_rows()[i]; \
1099                 for(int j = 0; j < w; j++) \
1100                 { \
1101                         if ( plugin->config.split && ((j + i * w / h) < w) ) \
1102                         continue; \
1103                         float r = row[0]; \
1104                         float g = row[1]; \
1105                         float b = row[2]; \
1106  \
1107                         r = plugin->calculate_level(r, HISTOGRAM_RED, 1); \
1108                         g = plugin->calculate_level(g, HISTOGRAM_GREEN, 1); \
1109                         b = plugin->calculate_level(b, HISTOGRAM_BLUE, 1); \
1110  \
1111                         row[0] = r; \
1112                         row[1] = g; \
1113                         row[2] = b; \
1114  \
1115                         row += components; \
1116                 } \
1117         } \
1118 }
1119
1120
1121                 VFrame *input = plugin->input;
1122                 //VFrame *output = plugin->output;
1123                 int w = input->get_w();
1124                 int h = input->get_h();
1125                 int *lookup_r = plugin->lookup[0];
1126                 int *lookup_g = plugin->lookup[1];
1127                 int *lookup_b = plugin->lookup[2];
1128                 int r, g, b, y, u, v;
1129                 switch(input->get_color_model())
1130                 {
1131                         case BC_RGB888:
1132                                 PROCESS(unsigned char, 3)
1133                                 break;
1134                         case BC_RGB_FLOAT:
1135                                 PROCESS_FLOAT(3);
1136                                 break;
1137                         case BC_RGBA8888:
1138                                 PROCESS(unsigned char, 4)
1139                                 break;
1140                         case BC_RGBA_FLOAT:
1141                                 PROCESS_FLOAT(4);
1142                                 break;
1143                         case BC_RGB161616:
1144                                 PROCESS(uint16_t, 3)
1145                                 break;
1146                         case BC_RGBA16161616:
1147                                 PROCESS(uint16_t, 4)
1148                                 break;
1149                         case BC_YUV888:
1150                                 PROCESS_YUV(unsigned char, 3, 0xff)
1151                                 break;
1152                         case BC_YUVA8888:
1153                                 PROCESS_YUV(unsigned char, 4, 0xff)
1154                                 break;
1155                         case BC_YUV161616:
1156                                 PROCESS_YUV(uint16_t, 3, 0xffff)
1157                                 break;
1158                         case BC_YUVA16161616:
1159                                 PROCESS_YUV(uint16_t, 4, 0xffff)
1160                                 break;
1161                 }
1162         }
1163 }
1164
1165
1166
1167
1168
1169
1170 HistogramEngine::HistogramEngine(HistogramMain *plugin, 
1171         int total_clients, 
1172         int total_packages)
1173  : LoadServer(total_clients, total_packages)
1174 {
1175         this->plugin = plugin;
1176 }
1177
1178 void HistogramEngine::init_packages()
1179 {
1180         switch(operation)
1181         {
1182                 case HISTOGRAM:
1183                         total_size = data->get_h();
1184                         break;
1185                 case APPLY:
1186                         total_size = data->get_h();
1187                         break;
1188         }
1189
1190
1191         //int package_size = (int)((float)total_size / get_total_packages() + 1);
1192         //int start = 0;
1193
1194         for(int i = 0; i < get_total_packages(); i++)
1195         {
1196                 HistogramPackage *package = (HistogramPackage*)get_package(i);
1197                 package->start = total_size * i / get_total_packages();
1198                 package->end = total_size * (i + 1) / get_total_packages();
1199         }
1200
1201 // Initialize clients here in case some don't get run.
1202         for(int i = 0; i < get_total_clients(); i++)
1203         {
1204                 HistogramUnit *unit = (HistogramUnit*)get_client(i);
1205                 for(int i = 0; i < HISTOGRAM_MODES; i++)
1206                         bzero(unit->accum[i], sizeof(int) * HISTOGRAM_SLOTS);
1207         }
1208
1209 }
1210
1211 LoadClient* HistogramEngine::new_client()
1212 {
1213         return new HistogramUnit(this, plugin);
1214 }
1215
1216 LoadPackage* HistogramEngine::new_package()
1217 {
1218         return new HistogramPackage;
1219 }
1220
1221 void HistogramEngine::process_packages(int operation, VFrame *data, int do_value)
1222 {
1223         this->data = data;
1224         this->operation = operation;
1225         this->do_value = do_value;
1226         LoadServer::process_packages();
1227 }
1228
1229