r125: This commit was manufactured by cvs2svn to create tag 'r1_1_7-last'.
[cinelerra_cv/mob.git] / hvirtual / plugins / brightness / brightness.C
blob433edd71cbf73b7e896ec9c0c6a3fedd1eabab4f
1 #include "clip.h"
2 #include "filexml.h"
3 #include "brightness.h"
4 #include "defaults.h"
5 #include "picon_png.h"
7 #include <stdio.h>
8 #include <stdint.h>
9 #include <string.h>
11 #include <libintl.h>
12 #define _(String) gettext(String)
13 #define gettext_noop(String) String
14 #define N_(String) gettext_noop (String)
16 #define SQR(a) ((a) * (a))
18 REGISTER_PLUGIN(BrightnessMain)
22 BrightnessConfig::BrightnessConfig()
24         brightness = 0;
25         contrast = 0;
26         luma = 1;
29 int BrightnessConfig::equivalent(BrightnessConfig &that)
31         return (brightness == that.brightness && 
32                 contrast == that.contrast &&
33                 luma == that.luma);
36 void BrightnessConfig::copy_from(BrightnessConfig &that)
38         brightness = that.brightness;
39         contrast = that.contrast;
40         luma = that.luma;
43 void BrightnessConfig::interpolate(BrightnessConfig &prev, 
44         BrightnessConfig &next, 
45         int64_t prev_frame, 
46         int64_t next_frame, 
47         int64_t current_frame)
49         double next_scale = (double)(current_frame - prev_frame) / (next_frame - prev_frame);
50         double prev_scale = (double)(next_frame - current_frame) / (next_frame - prev_frame);
52         this->brightness = prev.brightness * prev_scale + next.brightness * next_scale;
53         this->contrast = prev.contrast * prev_scale + next.contrast * next_scale;
54         this->luma = (int)(prev.luma * prev_scale + next.luma * next_scale);
65 YUV BrightnessMain::yuv;
67 BrightnessMain::BrightnessMain(PluginServer *server)
68  : PluginVClient(server)
70     redo_buffers = 1;
71         engine = 0;
72         PLUGIN_CONSTRUCTOR_MACRO
75 BrightnessMain::~BrightnessMain()
77         PLUGIN_DESTRUCTOR_MACRO
78         if(engine) delete engine;
81 char* BrightnessMain::plugin_title() { return _("Brightness/Contrast"); }
82 int BrightnessMain::is_realtime() { return 1; }
84 NEW_PICON_MACRO(BrightnessMain) 
85 SHOW_GUI_MACRO(BrightnessMain, BrightnessThread)
86 RAISE_WINDOW_MACRO(BrightnessMain)
87 SET_STRING_MACRO(BrightnessMain)
88 LOAD_CONFIGURATION_MACRO(BrightnessMain, BrightnessConfig)
90 int BrightnessMain::process_realtime(VFrame *input_ptr, VFrame *output_ptr)
92         load_configuration();
93         if(!engine) engine = new BrightnessEngine(this, PluginClient::smp + 1);
95         this->input = input_ptr;
96         this->output = output_ptr;
98         if(!EQUIV(config.brightness, 0) || !EQUIV(config.contrast, 0))
99         {
100                 engine->process_packages();
101         }
102         else
103 // Data never processed so copy if necessary
104         if(input_ptr->get_rows()[0] != output_ptr->get_rows()[0])
105         {
106                 output_ptr->copy_from(input_ptr);
107         }
109         return 0;
114 void BrightnessMain::update_gui()
116         if(thread)
117         {
118                 load_configuration();
119                 thread->window->lock_window();
120                 thread->window->brightness->update(config.brightness);
121                 thread->window->contrast->update(config.contrast);
122                 thread->window->luma->update(config.luma);
123                 thread->window->unlock_window();
124         }
127 int BrightnessMain::load_defaults()
129         char directory[1024], string[1024];
130 // set the default directory
131         sprintf(directory, "%sbrightness.rc", BCASTDIR);
133 // load the defaults
134         defaults = new Defaults(directory);
135         defaults->load();
137         config.brightness = defaults->get("BRIGHTNESS", config.brightness);
138         config.contrast = defaults->get("CONTRAST", config.contrast);
139         config.luma = defaults->get("LUMA", config.luma);
140         return 0;
143 int BrightnessMain::save_defaults()
145         defaults->update("BRIGHTNESS", config.brightness);
146         defaults->update("CONTRAST", config.contrast);
147         defaults->update("LUMA", config.luma);
148         defaults->save();
149         return 0;
153 void BrightnessMain::save_data(KeyFrame *keyframe)
155         FileXML output;
157 // cause data to be stored directly in text
158         output.set_shared_string(keyframe->data, MESSAGESIZE);
159         output.tag.set_title("BRIGHTNESS");
160         output.tag.set_property("BRIGHTNESS", config.brightness);
161         output.tag.set_property("CONTRAST",  config.contrast);
162         output.tag.set_property("LUMA",  config.luma);
163 //printf("BrightnessMain::save_data %d\n", config.luma);
164         output.append_tag();
165         output.terminate_string();
168 void BrightnessMain::read_data(KeyFrame *keyframe)
170         FileXML input;
172         input.set_shared_string(keyframe->data, strlen(keyframe->data));
174         int result = 0;
176         while(!result)
177         {
178                 result = input.read_tag();
180                 if(!result)
181                 {
182                         if(input.tag.title_is("BRIGHTNESS"))
183                         {
184                                 config.brightness = input.tag.get_property("BRIGHTNESS", config.brightness);
185                                 config.contrast = input.tag.get_property("CONTRAST", config.contrast);
186                                 config.luma = input.tag.get_property("LUMA", config.luma);
187                         }
188                 }
189         }
204 BrightnessPackage::BrightnessPackage()
205  : LoadPackage()
212 BrightnessUnit::BrightnessUnit(BrightnessEngine *server, BrightnessMain *plugin)
213  : LoadClient(server)
215         this->plugin = plugin;
218 BrightnessUnit::~BrightnessUnit()
221         
222 void BrightnessUnit::process_package(LoadPackage *package)
224         BrightnessPackage *pkg = (BrightnessPackage*)package;
227         VFrame *output = plugin->output;
228         VFrame *input = plugin->input;
229         
234 #define DO_BRIGHTNESS(max, type, components, is_yuv) \
235 { \
236         type **input_rows = (type**)input->get_rows(); \
237         type **output_rows = (type**)output->get_rows(); \
238         int row1 = pkg->row1; \
239         int row2 = pkg->row2; \
240         int width = output->get_w(); \
241         int r, g, b; \
243         if(!EQUIV(plugin->config.brightness, 0)) \
244         { \
245                 int offset = (int)(plugin->config.brightness / 100 * max); \
246 /*printf("DO_BRIGHTNESS offset=%d\n", offset);*/ \
248                 for(int i = row1; i < row2; i++) \
249                 { \
250                         type *input_row = input_rows[i]; \
251                         type *output_row = output_rows[i]; \
253                         for(int j = 0; j < width; j++) \
254                         { \
255                                 r = input_row[j * components] + offset; \
257                                 if(!is_yuv) \
258                                 { \
259                                         g = input_row[j * components + 1] + offset; \
260                                         b = input_row[j * components + 2] + offset; \
261                                 } \
263                                 CLAMP(r, 0, max); \
264                                 if(!is_yuv) \
265                                 { \
266                                         CLAMP(g, 0, max); \
267                                         CLAMP(b, 0, max); \
268                                 } \
270                                 output_row[j * components] = r; \
272                                 if(!is_yuv) \
273                                 { \
274                                         output_row[j * components + 1] = g; \
275                                         output_row[j * components + 2] = b; \
276                                 } \
277                                 else \
278                                 { \
279                                         output_row[j * components + 1] = input_row[j * components + 1]; \
280                                         output_row[j * components + 2] = input_row[j * components + 2]; \
281                                 } \
283                                 if(components == 4)  \
284                                         output_row[j * components + 3] = input_row[j * components + 3]; \
285                         } \
286                 } \
288 /* Data to be processed is now in the output buffer */ \
289                 input_rows = output_rows; \
290         } \
292         if(!EQUIV(plugin->config.contrast, 0)) \
293         { \
294                 float contrast = (plugin->config.contrast < 0) ?  \
295                         (plugin->config.contrast + 100) / 100 :  \
296                         (plugin->config.contrast + 25) / 25; \
297 /*printf("DO_BRIGHTNESS contrast=%f\n", contrast);*/ \
299                 int scalar = (int)(contrast * 0x100); \
300                 int offset = (max << 8) / 2 - max * scalar / 2; \
301                 int y, u, v; \
303                 for(int i = row1; i < row2; i++) \
304                 { \
305                         type *input_row = input_rows[i]; \
306                         type *output_row = output_rows[i]; \
308                         if(plugin->config.luma) \
309                         { \
310                                 for(int j = 0; j < width; j++) \
311                                 { \
312                                         if(is_yuv) \
313                                         { \
314                                                 y = input_row[j * components]; \
315                                         } \
316                                         else \
317                                         { \
318                                                 r = input_row[j * components]; \
319                                                 g = input_row[j * components + 1]; \
320                                                 b = input_row[j * components + 2]; \
321                                                 if(max == 0xff) \
322                                                 { \
323                                                         BrightnessMain::yuv.rgb_to_yuv_8( \
324                                                                 r,  \
325                                                                 g,  \
326                                                                 b,  \
327                                                                 y,  \
328                                                                 u,  \
329                                                                 v); \
330                                                 } \
331                                                 else \
332                                                 { \
333                                                         BrightnessMain::yuv.rgb_to_yuv_16( \
334                                                                 r,  \
335                                                                 g,  \
336                                                                 b,  \
337                                                                 y,  \
338                                                                 u,  \
339                                                                 v); \
340                                                 } \
341          \
342                                         } \
343          \
344                                         y = (y * scalar + offset) >> 8; \
345                                         CLAMP(y, 0, max); \
346          \
347          \
348                                         if(is_yuv) \
349                                         { \
350                                                 output_row[j * components] = y; \
351                                                 output_row[j * components + 1] = input_row[j * components + 1]; \
352                                                 output_row[j * components + 2] = input_row[j * components + 2]; \
353                                         } \
354                                         else \
355                                         { \
356                                                 if(max == 0xff) \
357                                                 { \
358                                                         BrightnessMain::yuv.yuv_to_rgb_8( \
359                                                                 r,  \
360                                                                 g,  \
361                                                                 b,  \
362                                                                 y,  \
363                                                                 u,  \
364                                                                 v); \
365                                                 } \
366                                                 else \
367                                                 { \
368                                                         BrightnessMain::yuv.yuv_to_rgb_16( \
369                                                                 r,  \
370                                                                 g,  \
371                                                                 b,  \
372                                                                 y,  \
373                                                                 u,  \
374                                                                 v); \
375                                                 } \
376                                                 input_row[j * components] = r; \
377                                                 input_row[j * components + 1] = g; \
378                                                 input_row[j * components + 2] = b; \
379                                         } \
380          \
381                                         if(components == 4)  \
382                                                 output_row[j * components + 3] = input_row[j * components + 3]; \
383                                 } \
384                         } \
385                         else \
386                         { \
387                                 for(int j = 0; j < width; j++) \
388                                 { \
389                                         r = input_row[j * components]; \
390                                         g = input_row[j * components + 1]; \
391                                         b = input_row[j * components + 2]; \
393                                         r = (r * scalar + offset) >> 8; \
394                                         g = (g * scalar + offset) >> 8; \
395                                         b = (b * scalar + offset) >> 8; \
397                                         CLAMP(r, 0, max); \
398                                         CLAMP(g, 0, max); \
399                                         CLAMP(b, 0, max); \
401                                         output_row[j * components] = r; \
402                                         output_row[j * components + 1] = g; \
403                                         output_row[j * components + 2] = b; \
405                                         if(components == 4)  \
406                                                 output_row[j * components + 3] = input_row[j * components + 3]; \
407                                 } \
408                         } \
409                 } \
410         } \
414         switch(input->get_color_model())
415         {
416                 case BC_RGB888:
417                         DO_BRIGHTNESS(0xff, unsigned char, 3, 0)
418                         break;
420                 case BC_YUV888:
421                         DO_BRIGHTNESS(0xff, unsigned char, 3, 1)
422                         break;
424                 case BC_RGBA8888:
425                         DO_BRIGHTNESS(0xff, unsigned char, 4, 0)
426                         break;
428                 case BC_YUVA8888:
429                         DO_BRIGHTNESS(0xff, unsigned char, 4, 1)
430                         break;
432                 case BC_RGB161616:
433                         DO_BRIGHTNESS(0xffff, uint16_t, 3, 0)
434                         break;
436                 case BC_YUV161616:
437                         DO_BRIGHTNESS(0xffff, uint16_t, 3, 1)
438                         break;
440                 case BC_RGBA16161616:
441                         DO_BRIGHTNESS(0xffff, uint16_t, 4, 0)
442                         break;
444                 case BC_YUVA16161616:
445                         DO_BRIGHTNESS(0xffff, uint16_t, 4, 1)
446                         break;
447         }
464 BrightnessEngine::BrightnessEngine(BrightnessMain *plugin, int cpus)
465  : LoadServer(cpus, cpus)
467         this->plugin = plugin;
470 BrightnessEngine::~BrightnessEngine()
475 void BrightnessEngine::init_packages()
477         for(int i = 0; i < LoadServer::total_packages; i++)
478         {
479                 BrightnessPackage *package = (BrightnessPackage*)LoadServer::packages[i];
480                 package->row1 = (int)(plugin->input->get_h() / 
481                         LoadServer::total_packages * 
482                         i);
483                 package->row2 = package->row1 + 
484                         (int)(plugin->input->get_h() / 
485                         LoadServer::total_packages);
487                 if(i >= LoadServer::total_packages - 1)
488                         package->row2 = plugin->input->get_h();
489         }
492 LoadClient* BrightnessEngine::new_client()
494         return new BrightnessUnit(this, plugin);
497 LoadPackage* BrightnessEngine::new_package()
499         return new BrightnessPackage;