3 #include "brightness.h"
12 #define SQR(a) ((a) * (a))
14 REGISTER_PLUGIN(BrightnessMain)
18 BrightnessConfig::BrightnessConfig()
25 int BrightnessConfig::equivalent(BrightnessConfig &that)
27 return (brightness == that.brightness &&
28 contrast == that.contrast &&
32 void BrightnessConfig::copy_from(BrightnessConfig &that)
34 brightness = that.brightness;
35 contrast = that.contrast;
39 void BrightnessConfig::interpolate(BrightnessConfig &prev,
40 BrightnessConfig &next,
43 int64_t current_frame)
45 double next_scale = (double)(current_frame - prev_frame) / (next_frame - prev_frame);
46 double prev_scale = (double)(next_frame - current_frame) / (next_frame - prev_frame);
48 this->brightness = prev.brightness * prev_scale + next.brightness * next_scale;
49 this->contrast = prev.contrast * prev_scale + next.contrast * next_scale;
50 this->luma = (int)(prev.luma * prev_scale + next.luma * next_scale);
61 YUV BrightnessMain::yuv;
63 BrightnessMain::BrightnessMain(PluginServer *server)
64 : PluginVClient(server)
68 PLUGIN_CONSTRUCTOR_MACRO
71 BrightnessMain::~BrightnessMain()
73 PLUGIN_DESTRUCTOR_MACRO
74 if(engine) delete engine;
77 char* BrightnessMain::plugin_title() { return N_("Brightness/Contrast"); }
78 int BrightnessMain::is_realtime() { return 1; }
80 NEW_PICON_MACRO(BrightnessMain)
81 SHOW_GUI_MACRO(BrightnessMain, BrightnessThread)
82 RAISE_WINDOW_MACRO(BrightnessMain)
83 SET_STRING_MACRO(BrightnessMain)
84 LOAD_CONFIGURATION_MACRO(BrightnessMain, BrightnessConfig)
86 int BrightnessMain::process_realtime(VFrame *input_ptr, VFrame *output_ptr)
89 if(!engine) engine = new BrightnessEngine(this, PluginClient::smp + 1);
91 this->input = input_ptr;
92 this->output = output_ptr;
94 if(!EQUIV(config.brightness, 0) || !EQUIV(config.contrast, 0))
96 engine->process_packages();
99 // Data never processed so copy if necessary
100 if(input_ptr->get_rows()[0] != output_ptr->get_rows()[0])
102 output_ptr->copy_from(input_ptr);
110 void BrightnessMain::update_gui()
114 load_configuration();
115 thread->window->lock_window();
116 thread->window->brightness->update(config.brightness);
117 thread->window->contrast->update(config.contrast);
118 thread->window->luma->update(config.luma);
119 thread->window->unlock_window();
123 int BrightnessMain::load_defaults()
125 char directory[1024], string[1024];
126 // set the default directory
127 sprintf(directory, "%sbrightness.rc", BCASTDIR);
130 defaults = new Defaults(directory);
133 config.brightness = defaults->get("BRIGHTNESS", config.brightness);
134 config.contrast = defaults->get("CONTRAST", config.contrast);
135 config.luma = defaults->get("LUMA", config.luma);
139 int BrightnessMain::save_defaults()
141 defaults->update("BRIGHTNESS", config.brightness);
142 defaults->update("CONTRAST", config.contrast);
143 defaults->update("LUMA", config.luma);
149 void BrightnessMain::save_data(KeyFrame *keyframe)
153 // cause data to be stored directly in text
154 output.set_shared_string(keyframe->data, MESSAGESIZE);
155 output.tag.set_title("BRIGHTNESS");
156 output.tag.set_property("BRIGHTNESS", config.brightness);
157 output.tag.set_property("CONTRAST", config.contrast);
158 output.tag.set_property("LUMA", config.luma);
159 //printf("BrightnessMain::save_data %d\n", config.luma);
161 output.terminate_string();
164 void BrightnessMain::read_data(KeyFrame *keyframe)
168 input.set_shared_string(keyframe->data, strlen(keyframe->data));
174 result = input.read_tag();
178 if(input.tag.title_is("BRIGHTNESS"))
180 config.brightness = input.tag.get_property("BRIGHTNESS", config.brightness);
181 config.contrast = input.tag.get_property("CONTRAST", config.contrast);
182 config.luma = input.tag.get_property("LUMA", config.luma);
200 BrightnessPackage::BrightnessPackage()
208 BrightnessUnit::BrightnessUnit(BrightnessEngine *server, BrightnessMain *plugin)
211 this->plugin = plugin;
214 BrightnessUnit::~BrightnessUnit()
218 void BrightnessUnit::process_package(LoadPackage *package)
220 BrightnessPackage *pkg = (BrightnessPackage*)package;
223 VFrame *output = plugin->output;
224 VFrame *input = plugin->input;
230 #define DO_BRIGHTNESS(max, type, components, is_yuv) \
232 type **input_rows = (type**)input->get_rows(); \
233 type **output_rows = (type**)output->get_rows(); \
234 int row1 = pkg->row1; \
235 int row2 = pkg->row2; \
236 int width = output->get_w(); \
239 if(!EQUIV(plugin->config.brightness, 0)) \
241 int offset = (int)(plugin->config.brightness / 100 * max); \
242 /*printf("DO_BRIGHTNESS offset=%d\n", offset);*/ \
244 for(int i = row1; i < row2; i++) \
246 type *input_row = input_rows[i]; \
247 type *output_row = output_rows[i]; \
249 for(int j = 0; j < width; j++) \
251 r = input_row[j * components] + offset; \
255 g = input_row[j * components + 1] + offset; \
256 b = input_row[j * components + 2] + offset; \
266 output_row[j * components] = r; \
270 output_row[j * components + 1] = g; \
271 output_row[j * components + 2] = b; \
275 output_row[j * components + 1] = input_row[j * components + 1]; \
276 output_row[j * components + 2] = input_row[j * components + 2]; \
279 if(components == 4) \
280 output_row[j * components + 3] = input_row[j * components + 3]; \
284 /* Data to be processed is now in the output buffer */ \
285 input_rows = output_rows; \
288 if(!EQUIV(plugin->config.contrast, 0)) \
290 float contrast = (plugin->config.contrast < 0) ? \
291 (plugin->config.contrast + 100) / 100 : \
292 (plugin->config.contrast + 25) / 25; \
293 /*printf("DO_BRIGHTNESS contrast=%f\n", contrast);*/ \
295 int scalar = (int)(contrast * 0x100); \
296 int offset = (max << 8) / 2 - max * scalar / 2; \
299 for(int i = row1; i < row2; i++) \
301 type *input_row = input_rows[i]; \
302 type *output_row = output_rows[i]; \
304 if(plugin->config.luma) \
306 for(int j = 0; j < width; j++) \
310 y = input_row[j * components]; \
314 r = input_row[j * components]; \
315 g = input_row[j * components + 1]; \
316 b = input_row[j * components + 2]; \
319 BrightnessMain::yuv.rgb_to_yuv_8( \
329 BrightnessMain::yuv.rgb_to_yuv_16( \
340 y = (y * scalar + offset) >> 8; \
346 output_row[j * components] = y; \
347 output_row[j * components + 1] = input_row[j * components + 1]; \
348 output_row[j * components + 2] = input_row[j * components + 2]; \
354 BrightnessMain::yuv.yuv_to_rgb_8( \
364 BrightnessMain::yuv.yuv_to_rgb_16( \
372 input_row[j * components] = r; \
373 input_row[j * components + 1] = g; \
374 input_row[j * components + 2] = b; \
377 if(components == 4) \
378 output_row[j * components + 3] = input_row[j * components + 3]; \
383 for(int j = 0; j < width; j++) \
385 r = input_row[j * components]; \
386 g = input_row[j * components + 1]; \
387 b = input_row[j * components + 2]; \
389 r = (r * scalar + offset) >> 8; \
390 g = (g * scalar + offset) >> 8; \
391 b = (b * scalar + offset) >> 8; \
397 output_row[j * components] = r; \
398 output_row[j * components + 1] = g; \
399 output_row[j * components + 2] = b; \
401 if(components == 4) \
402 output_row[j * components + 3] = input_row[j * components + 3]; \
411 #define DO_BRIGHTNESS_F(components) \
413 float **input_rows = (float**)input->get_rows(); \
414 float **output_rows = (float**)output->get_rows(); \
415 int row1 = pkg->row1; \
416 int row2 = pkg->row2; \
417 int width = output->get_w(); \
420 if(!EQUIV(plugin->config.brightness, 0)) \
422 float offset = plugin->config.brightness / 100; \
424 for(int i = row1; i < row2; i++) \
426 float *input_row = input_rows[i]; \
427 float *output_row = output_rows[i]; \
429 for(int j = 0; j < width; j++) \
431 r = input_row[j * components] + offset; \
432 g = input_row[j * components + 1] + offset; \
433 b = input_row[j * components + 2] + offset; \
435 output_row[j * components] = r; \
436 output_row[j * components + 1] = g; \
437 output_row[j * components + 2] = b; \
438 if(components == 4) \
439 output_row[j * components + 3] = input_row[j * components + 3]; \
443 /* Data to be processed is now in the output buffer */ \
444 input_rows = output_rows; \
447 if(!EQUIV(plugin->config.contrast, 0)) \
449 float contrast = (plugin->config.contrast < 0) ? \
450 (plugin->config.contrast + 100) / 100 : \
451 (plugin->config.contrast + 25) / 25; \
453 /* Shift black level down so shadows get darker instead of lighter */ \
454 float offset = 0.5 - contrast / 2; \
457 for(int i = row1; i < row2; i++) \
459 float *input_row = input_rows[i]; \
460 float *output_row = output_rows[i]; \
462 if(plugin->config.luma) \
464 for(int j = 0; j < width; j++) \
466 r = input_row[j * components]; \
467 g = input_row[j * components + 1]; \
468 b = input_row[j * components + 2]; \
477 y = y * contrast + offset; \
487 input_row[j * components] = r; \
488 input_row[j * components + 1] = g; \
489 input_row[j * components + 2] = b; \
491 if(components == 4) \
492 output_row[j * components + 3] = input_row[j * components + 3]; \
497 for(int j = 0; j < width; j++) \
499 r = input_row[j * components]; \
500 g = input_row[j * components + 1]; \
501 b = input_row[j * components + 2]; \
503 r = r * contrast + offset; \
504 g = g * contrast + offset; \
505 b = b * contrast + offset; \
507 output_row[j * components] = r; \
508 output_row[j * components + 1] = g; \
509 output_row[j * components + 2] = b; \
511 if(components == 4) \
512 output_row[j * components + 3] = input_row[j * components + 3]; \
520 switch(input->get_color_model())
523 DO_BRIGHTNESS(0xff, unsigned char, 3, 0)
531 DO_BRIGHTNESS(0xff, unsigned char, 3, 1)
535 DO_BRIGHTNESS(0xff, unsigned char, 4, 0)
543 DO_BRIGHTNESS(0xff, unsigned char, 4, 1)
547 DO_BRIGHTNESS(0xffff, uint16_t, 3, 0)
551 DO_BRIGHTNESS(0xffff, uint16_t, 3, 1)
554 case BC_RGBA16161616:
555 DO_BRIGHTNESS(0xffff, uint16_t, 4, 0)
558 case BC_YUVA16161616:
559 DO_BRIGHTNESS(0xffff, uint16_t, 4, 1)
578 BrightnessEngine::BrightnessEngine(BrightnessMain *plugin, int cpus)
579 : LoadServer(cpus, cpus)
581 this->plugin = plugin;
584 BrightnessEngine::~BrightnessEngine()
589 void BrightnessEngine::init_packages()
591 for(int i = 0; i < LoadServer::total_packages; i++)
593 BrightnessPackage *package = (BrightnessPackage*)LoadServer::packages[i];
594 package->row1 = plugin->input->get_h() * i / LoadServer::total_packages;
595 package->row2 = plugin->input->get_h() * (i + 1) / LoadServer::total_packages;
599 LoadClient* BrightnessEngine::new_client()
601 return new BrightnessUnit(this, plugin);
604 LoadPackage* BrightnessEngine::new_package()
606 return new BrightnessPackage;