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_buffer(VFrame *frame,
87 int64_t start_position,
106 if(!engine) engine = new BrightnessEngine(this, PluginClient::smp + 1);
109 this->output = frame;
111 if(!EQUIV(config.brightness, 0) || !EQUIV(config.contrast, 0))
113 engine->process_packages();
121 void BrightnessMain::update_gui()
125 if(load_configuration())
127 thread->window->lock_window("BrightnessMain::update_gui");
128 thread->window->brightness->update(config.brightness);
129 thread->window->contrast->update(config.contrast);
130 thread->window->luma->update(config.luma);
131 thread->window->unlock_window();
136 int BrightnessMain::load_defaults()
138 char directory[BCTEXTLEN], string[BCTEXTLEN];
139 // set the default directory
140 sprintf(directory, "%sbrightness.rc", BCASTDIR);
143 defaults = new BC_Hash(directory);
146 config.brightness = defaults->get("BRIGHTNESS", config.brightness);
147 config.contrast = defaults->get("CONTRAST", config.contrast);
148 config.luma = defaults->get("LUMA", config.luma);
152 int BrightnessMain::save_defaults()
154 defaults->update("BRIGHTNESS", config.brightness);
155 defaults->update("CONTRAST", config.contrast);
156 defaults->update("LUMA", config.luma);
162 void BrightnessMain::save_data(KeyFrame *keyframe)
166 // cause data to be stored directly in text
167 output.set_shared_string(keyframe->data, MESSAGESIZE);
168 output.tag.set_title("BRIGHTNESS");
169 output.tag.set_property("BRIGHTNESS", config.brightness);
170 output.tag.set_property("CONTRAST", config.contrast);
171 output.tag.set_property("LUMA", config.luma);
172 //printf("BrightnessMain::save_data %d\n", config.luma);
174 output.terminate_string();
177 void BrightnessMain::read_data(KeyFrame *keyframe)
181 input.set_shared_string(keyframe->data, strlen(keyframe->data));
187 result = input.read_tag();
191 if(input.tag.title_is("BRIGHTNESS"))
193 config.brightness = input.tag.get_property("BRIGHTNESS", config.brightness);
194 config.contrast = input.tag.get_property("CONTRAST", config.contrast);
195 config.luma = input.tag.get_property("LUMA", config.luma);
213 BrightnessPackage::BrightnessPackage()
221 BrightnessUnit::BrightnessUnit(BrightnessEngine *server, BrightnessMain *plugin)
224 this->plugin = plugin;
227 BrightnessUnit::~BrightnessUnit()
231 void BrightnessUnit::process_package(LoadPackage *package)
233 BrightnessPackage *pkg = (BrightnessPackage*)package;
236 VFrame *output = plugin->output;
237 VFrame *input = plugin->input;
243 #define DO_BRIGHTNESS(max, type, components, is_yuv) \
245 type **input_rows = (type**)input->get_rows(); \
246 type **output_rows = (type**)output->get_rows(); \
247 int row1 = pkg->row1; \
248 int row2 = pkg->row2; \
249 int width = output->get_w(); \
252 if(!EQUIV(plugin->config.brightness, 0)) \
254 int offset = (int)(plugin->config.brightness / 100 * max); \
255 /*printf("DO_BRIGHTNESS offset=%d\n", offset);*/ \
257 for(int i = row1; i < row2; i++) \
259 type *input_row = input_rows[i]; \
260 type *output_row = output_rows[i]; \
262 for(int j = 0; j < width; j++) \
264 r = input_row[j * components] + offset; \
268 g = input_row[j * components + 1] + offset; \
269 b = input_row[j * components + 2] + offset; \
279 output_row[j * components] = r; \
283 output_row[j * components + 1] = g; \
284 output_row[j * components + 2] = b; \
288 output_row[j * components + 1] = input_row[j * components + 1]; \
289 output_row[j * components + 2] = input_row[j * components + 2]; \
292 if(components == 4) \
293 output_row[j * components + 3] = input_row[j * components + 3]; \
297 /* Data to be processed is now in the output buffer */ \
298 input_rows = output_rows; \
301 if(!EQUIV(plugin->config.contrast, 0)) \
303 float contrast = (plugin->config.contrast < 0) ? \
304 (plugin->config.contrast + 100) / 100 : \
305 (plugin->config.contrast + 25) / 25; \
306 /*printf("DO_BRIGHTNESS contrast=%f\n", contrast);*/ \
308 int scalar = (int)(contrast * 0x100); \
309 int offset = (max << 8) / 2 - max * scalar / 2; \
312 for(int i = row1; i < row2; i++) \
314 type *input_row = input_rows[i]; \
315 type *output_row = output_rows[i]; \
317 if(plugin->config.luma) \
319 for(int j = 0; j < width; j++) \
323 y = input_row[j * components]; \
327 r = input_row[j * components]; \
328 g = input_row[j * components + 1]; \
329 b = input_row[j * components + 2]; \
332 BrightnessMain::yuv.rgb_to_yuv_8( \
342 BrightnessMain::yuv.rgb_to_yuv_16( \
353 y = (y * scalar + offset) >> 8; \
359 output_row[j * components] = y; \
360 output_row[j * components + 1] = input_row[j * components + 1]; \
361 output_row[j * components + 2] = input_row[j * components + 2]; \
367 BrightnessMain::yuv.yuv_to_rgb_8( \
377 BrightnessMain::yuv.yuv_to_rgb_16( \
385 input_row[j * components] = r; \
386 input_row[j * components + 1] = g; \
387 input_row[j * components + 2] = b; \
390 if(components == 4) \
391 output_row[j * components + 3] = input_row[j * components + 3]; \
396 for(int j = 0; j < width; j++) \
398 r = input_row[j * components]; \
399 g = input_row[j * components + 1]; \
400 b = input_row[j * components + 2]; \
402 r = (r * scalar + offset) >> 8; \
403 g = (g * scalar + offset) >> 8; \
404 b = (b * scalar + offset) >> 8; \
410 output_row[j * components] = r; \
411 output_row[j * components + 1] = g; \
412 output_row[j * components + 2] = b; \
414 if(components == 4) \
415 output_row[j * components + 3] = input_row[j * components + 3]; \
424 #define DO_BRIGHTNESS_F(components) \
426 float **input_rows = (float**)input->get_rows(); \
427 float **output_rows = (float**)output->get_rows(); \
428 int row1 = pkg->row1; \
429 int row2 = pkg->row2; \
430 int width = output->get_w(); \
433 if(!EQUIV(plugin->config.brightness, 0)) \
435 float offset = plugin->config.brightness / 100; \
437 for(int i = row1; i < row2; i++) \
439 float *input_row = input_rows[i]; \
440 float *output_row = output_rows[i]; \
442 for(int j = 0; j < width; j++) \
444 r = input_row[j * components] + offset; \
445 g = input_row[j * components + 1] + offset; \
446 b = input_row[j * components + 2] + offset; \
448 output_row[j * components] = r; \
449 output_row[j * components + 1] = g; \
450 output_row[j * components + 2] = b; \
451 if(components == 4) \
452 output_row[j * components + 3] = input_row[j * components + 3]; \
456 /* Data to be processed is now in the output buffer */ \
457 input_rows = output_rows; \
460 if(!EQUIV(plugin->config.contrast, 0)) \
462 float contrast = (plugin->config.contrast < 0) ? \
463 (plugin->config.contrast + 100) / 100 : \
464 (plugin->config.contrast + 25) / 25; \
466 /* Shift black level down so shadows get darker instead of lighter */ \
467 float offset = 0.5 - contrast / 2; \
470 for(int i = row1; i < row2; i++) \
472 float *input_row = input_rows[i]; \
473 float *output_row = output_rows[i]; \
475 if(plugin->config.luma) \
477 for(int j = 0; j < width; j++) \
479 r = input_row[j * components]; \
480 g = input_row[j * components + 1]; \
481 b = input_row[j * components + 2]; \
490 y = y * contrast + offset; \
500 input_row[j * components] = r; \
501 input_row[j * components + 1] = g; \
502 input_row[j * components + 2] = b; \
504 if(components == 4) \
505 output_row[j * components + 3] = input_row[j * components + 3]; \
510 for(int j = 0; j < width; j++) \
512 r = input_row[j * components]; \
513 g = input_row[j * components + 1]; \
514 b = input_row[j * components + 2]; \
516 r = r * contrast + offset; \
517 g = g * contrast + offset; \
518 b = b * contrast + offset; \
520 output_row[j * components] = r; \
521 output_row[j * components + 1] = g; \
522 output_row[j * components + 2] = b; \
524 if(components == 4) \
525 output_row[j * components + 3] = input_row[j * components + 3]; \
533 switch(input->get_color_model())
536 DO_BRIGHTNESS(0xff, unsigned char, 3, 0)
544 DO_BRIGHTNESS(0xff, unsigned char, 3, 1)
548 DO_BRIGHTNESS(0xff, unsigned char, 4, 0)
556 DO_BRIGHTNESS(0xff, unsigned char, 4, 1)
560 DO_BRIGHTNESS(0xffff, uint16_t, 3, 0)
564 DO_BRIGHTNESS(0xffff, uint16_t, 3, 1)
567 case BC_RGBA16161616:
568 DO_BRIGHTNESS(0xffff, uint16_t, 4, 0)
571 case BC_YUVA16161616:
572 DO_BRIGHTNESS(0xffff, uint16_t, 4, 1)
591 BrightnessEngine::BrightnessEngine(BrightnessMain *plugin, int cpus)
592 : LoadServer(cpus, cpus)
594 this->plugin = plugin;
597 BrightnessEngine::~BrightnessEngine()
602 void BrightnessEngine::init_packages()
604 for(int i = 0; i < LoadServer::get_total_packages(); i++)
606 BrightnessPackage *package = (BrightnessPackage*)LoadServer::get_package(i);
607 package->row1 = plugin->input->get_h() * i / LoadServer::get_total_packages();
608 package->row2 = plugin->input->get_h() * (i + 1) / LoadServer::get_total_packages();
612 LoadClient* BrightnessEngine::new_client()
614 return new BrightnessUnit(this, plugin);
617 LoadPackage* BrightnessEngine::new_package()
619 return new BrightnessPackage;