7 #include "../colors/plugincolors.h"
8 #include "workarounds.h"
13 #define SQR(a) ((a) * (a))
15 REGISTER_PLUGIN(LinearizeMain)
19 LinearizeConfig::LinearizeConfig()
26 int LinearizeConfig::equivalent(LinearizeConfig &that)
28 return (EQUIV(max, that.max) &&
29 EQUIV(gamma, that.gamma) &&
30 automatic == that.automatic);
33 void LinearizeConfig::copy_from(LinearizeConfig &that)
37 automatic = that.automatic;
40 void LinearizeConfig::interpolate(LinearizeConfig &prev,
41 LinearizeConfig &next,
44 int64_t current_frame)
46 double next_scale = (double)(current_frame - prev_frame) / (next_frame - prev_frame);
47 double prev_scale = (double)(next_frame - current_frame) / (next_frame - prev_frame);
49 this->max = prev.max * prev_scale + next.max * next_scale;
50 this->gamma = prev.gamma * prev_scale + next.gamma * next_scale;
51 this->automatic = prev.automatic;
61 LinearizePackage::LinearizePackage()
76 LinearizeUnit::LinearizeUnit(LinearizeMain *plugin)
78 this->plugin = plugin;
81 void LinearizeUnit::process_package(LoadPackage *package)
83 LinearizePackage *pkg = (LinearizePackage*)package;
84 LinearizeEngine *engine = (LinearizeEngine*)get_server();
85 VFrame *data = engine->data;
86 int w = data->get_w();
87 float r, g, b, y, u, v;
89 // The same algorithm used by dcraw
90 if(engine->operation == LinearizeEngine::HISTOGRAM)
92 #define HISTOGRAM_HEAD(type) \
93 for(int i = pkg->start; i < pkg->end; i++) \
95 type *row = (type*)data->get_rows()[i]; \
96 for(int j = 0; j < w; j++) \
99 #define HISTOGRAM_TAIL(components) \
101 slot = (int)(r * HISTOGRAM_SIZE); \
102 accum[CLIP(slot, 0, HISTOGRAM_SIZE - 1)]++; \
103 slot = (int)(g * HISTOGRAM_SIZE); \
104 accum[CLIP(slot, 0, HISTOGRAM_SIZE - 1)]++; \
105 slot = (int)(b * HISTOGRAM_SIZE); \
106 accum[CLIP(slot, 0, HISTOGRAM_SIZE - 1)]++; \
112 switch(data->get_color_model())
115 HISTOGRAM_HEAD(unsigned char)
116 r = (float)row[0] / 0xff;
117 g = (float)row[1] / 0xff;
118 b = (float)row[2] / 0xff;
122 HISTOGRAM_HEAD(unsigned char)
123 r = (float)row[0] / 0xff;
124 g = (float)row[1] / 0xff;
125 b = (float)row[2] / 0xff;
129 HISTOGRAM_HEAD(float)
136 HISTOGRAM_HEAD(float)
143 HISTOGRAM_HEAD(unsigned char)
148 u = (float)((u - 0x80) / 0xff);
149 v = (float)((v - 0x80) / 0xff);
150 YUV::yuv_to_rgb_f(r, g, b, y, u, v);
154 HISTOGRAM_HEAD(unsigned char)
155 y = (float)row[0] / 0xff;
156 u = (float)row[1] / 0xff;
157 v = (float)row[2] / 0xff;
158 YUV::yuv_to_rgb_f(r, g, b, y, u, v);
165 float max = plugin->config.max;
166 float scale = 1.0 / max;
167 float gamma = plugin->config.gamma - 1.0;
169 #define LINEARIZE_HEAD(type) \
170 for(int i = pkg->start; i < pkg->end; i++) \
172 type *row = (type*)data->get_rows()[i]; \
173 for(int j = 0; j < w; j++) \
176 #define LINEARIZE_MID \
177 r = r * scale * powf(r * 2 / max, gamma); \
178 g = g * scale * powf(g * 2 / max, gamma); \
179 b = b * scale * powf(b * 2 / max, gamma); \
181 #define LINEARIZE_TAIL(components) \
187 switch(data->get_color_model())
190 LINEARIZE_HEAD(unsigned char)
191 r = (float)row[0] / 0xff;
192 g = (float)row[1] / 0xff;
193 b = (float)row[2] / 0xff;
195 row[0] = (int)CLIP(r * 0xff, 0, 0xff);
196 row[1] = (int)CLIP(g * 0xff, 0, 0xff);
197 row[2] = (int)CLIP(b * 0xff, 0, 0xff);
201 LINEARIZE_HEAD(unsigned char)
202 r = (float)row[0] / 0xff;
203 g = (float)row[1] / 0xff;
204 b = (float)row[2] / 0xff;
206 row[0] = (int)CLIP(r * 0xff, 0, 0xff);
207 row[1] = (int)CLIP(g * 0xff, 0, 0xff);
208 row[2] = (int)CLIP(b * 0xff, 0, 0xff);
212 LINEARIZE_HEAD(float)
223 LINEARIZE_HEAD(float)
234 LINEARIZE_HEAD(unsigned char)
239 u = (float)((u - 0x80) / 0xff);
240 v = (float)((v - 0x80) / 0xff);
241 YUV::yuv_to_rgb_f(r, g, b, y, u, v);
243 YUV::rgb_to_yuv_f(r, g, b, y, u, v);
247 row[0] = (int)CLIP(y, 0, 0xff);
248 row[1] = (int)CLIP(u, 0, 0xff);
249 row[2] = (int)CLIP(v, 0, 0xff);
253 LINEARIZE_HEAD(unsigned char)
258 u = (float)((u - 0x80) / 0xff);
259 v = (float)((v - 0x80) / 0xff);
260 YUV::yuv_to_rgb_f(r, g, b, y, u, v);
262 YUV::rgb_to_yuv_f(r, g, b, y, u, v);
266 row[0] = (int)CLIP(y, 0, 0xff);
267 row[1] = (int)CLIP(u, 0, 0xff);
268 row[2] = (int)CLIP(v, 0, 0xff);
285 LinearizeEngine::LinearizeEngine(LinearizeMain *plugin)
286 : LoadServer(plugin->get_project_smp() + 1,
287 plugin->get_project_smp() + 1)
289 this->plugin = plugin;
292 void LinearizeEngine::init_packages()
294 for(int i = 0; i < get_total_packages(); i++)
296 LinearizePackage *package = (LinearizePackage*)get_package(i);
297 package->start = data->get_h() * i / get_total_packages();
298 package->end = data->get_h() * (i + 1) / get_total_packages();
301 // Initialize clients here in case some don't get run.
302 for(int i = 0; i < get_total_clients(); i++)
304 LinearizeUnit *unit = (LinearizeUnit*)get_client(i);
305 bzero(unit->accum, sizeof(int) * HISTOGRAM_SIZE);
307 bzero(accum, sizeof(int) * HISTOGRAM_SIZE);
310 LoadClient* LinearizeEngine::new_client()
312 return new LinearizeUnit(plugin);
315 LoadPackage* LinearizeEngine::new_package()
317 return new LinearizePackage;
320 void LinearizeEngine::process_packages(int operation, VFrame *data)
323 this->operation = operation;
324 LoadServer::process_packages();
325 for(int i = 0; i < get_total_clients(); i++)
327 LinearizeUnit *unit = (LinearizeUnit*)get_client(i);
328 for(int j = 0; j < HISTOGRAM_SIZE; j++)
330 accum[j] += unit->accum[j];
350 LinearizeMain::LinearizeMain(PluginServer *server)
351 : PluginVClient(server)
354 PLUGIN_CONSTRUCTOR_MACRO
357 LinearizeMain::~LinearizeMain()
359 PLUGIN_DESTRUCTOR_MACRO
364 char* LinearizeMain::plugin_title() { return N_("Linearize"); }
365 int LinearizeMain::is_realtime() { return 1; }
371 NEW_PICON_MACRO(LinearizeMain)
372 LOAD_CONFIGURATION_MACRO(LinearizeMain, LinearizeConfig)
373 SHOW_GUI_MACRO(LinearizeMain, LinearizeThread)
374 RAISE_WINDOW_MACRO(LinearizeMain)
375 SET_STRING_MACRO(LinearizeMain)
381 int LinearizeMain::process_realtime(VFrame *input_ptr, VFrame *output_ptr)
383 this->frame = input_ptr;
384 load_configuration();
389 calculate_max(input_ptr);
390 send_render_gui(this);
393 send_render_gui(this);
395 if(!engine) engine = new LinearizeEngine(this);
396 engine->process_packages(LinearizeEngine::APPLY, input_ptr);
400 void LinearizeMain::calculate_max(VFrame *frame)
402 if(!engine) engine = new LinearizeEngine(this);
403 engine->process_packages(LinearizeEngine::HISTOGRAM, frame);
404 int total_pixels = frame->get_w() * frame->get_h() * 3;
405 int max_fraction = (int)((int64_t)total_pixels * 99 / 100);
408 for(int i = 0; i < HISTOGRAM_SIZE; i++)
410 current += engine->accum[i];
411 if(current > max_fraction)
413 config.max = (float)i / HISTOGRAM_SIZE;
420 void LinearizeMain::update_gui()
424 if(load_configuration())
426 thread->window->lock_window("LinearizeMain::update_gui");
427 thread->window->update();
428 thread->window->unlock_window();
433 void LinearizeMain::render_gui(void *data)
435 LinearizeMain *ptr = (LinearizeMain*)data;
436 config.max = ptr->config.max;
438 if(!engine) engine = new LinearizeEngine(this);
439 if(ptr->engine && ptr->config.automatic)
441 memcpy(engine->accum,
443 sizeof(int) * HISTOGRAM_SIZE);
444 thread->window->lock_window("LinearizeMain::render_gui");
445 thread->window->update();
446 thread->window->unlock_window();
450 engine->process_packages(LinearizeEngine::HISTOGRAM,
452 thread->window->lock_window("LinearizeMain::render_gui");
453 thread->window->update_histogram();
454 thread->window->unlock_window();
460 int LinearizeMain::load_defaults()
462 char directory[1024], string[1024];
463 // set the default directory
464 sprintf(directory, "%slinearize.rc", BCASTDIR);
467 defaults = new BC_Hash(directory);
470 config.max = defaults->get("MAX", config.max);
471 config.gamma = defaults->get("GAMMA", config.gamma);
472 config.automatic = defaults->get("AUTOMATIC", config.automatic);
476 int LinearizeMain::save_defaults()
478 defaults->update("MAX", config.max);
479 defaults->update("GAMMA", config.gamma);
480 defaults->update("AUTOMATIC", config.automatic);
485 void LinearizeMain::save_data(KeyFrame *keyframe)
489 // cause data to be stored directly in text
490 output.set_shared_string(keyframe->data, MESSAGESIZE);
491 output.tag.set_title("LINEARIZE");
492 output.tag.set_property("MAX", config.max);
493 output.tag.set_property("GAMMA", config.gamma);
494 output.tag.set_property("AUTOMATIC", config.automatic);
496 output.terminate_string();
499 void LinearizeMain::read_data(KeyFrame *keyframe)
503 input.set_shared_string(keyframe->data, strlen(keyframe->data));
509 result = input.read_tag();
513 if(input.tag.title_is("LINEARIZE"))
515 config.max = input.tag.get_property("MAX", config.max);
516 config.gamma = input.tag.get_property("GAMMA", config.gamma);
517 config.automatic = input.tag.get_property("AUTOMATIC", config.automatic);