4 #include "histogramengine.h"
6 #include "plugincolors.h"
8 #include "thresholdwindow.h"
14 ThresholdConfig::ThresholdConfig()
19 int ThresholdConfig::equivalent(ThresholdConfig &that)
21 return EQUIV(min, that.min) &&
22 EQUIV(max, that.max) &&
26 void ThresholdConfig::copy_from(ThresholdConfig &that)
33 void ThresholdConfig::interpolate(ThresholdConfig &prev,
34 ThresholdConfig &next,
37 int64_t current_frame)
39 double next_scale = (double)(current_frame - prev_frame) /
40 (next_frame - prev_frame);
41 double prev_scale = (double)(next_frame - current_frame) /
42 (next_frame - prev_frame);
44 min = prev.min * prev_scale + next.min * next_scale;
45 max = prev.max * prev_scale + next.max * next_scale;
49 void ThresholdConfig::reset()
56 void ThresholdConfig::boundaries()
58 CLAMP(min, HISTOGRAM_MIN, max);
59 CLAMP(max, min, HISTOGRAM_MAX);
69 REGISTER_PLUGIN(ThresholdMain)
71 ThresholdMain::ThresholdMain(PluginServer *server)
72 : PluginVClient(server)
74 PLUGIN_CONSTRUCTOR_MACRO
79 ThresholdMain::~ThresholdMain()
81 PLUGIN_DESTRUCTOR_MACRO
83 delete threshold_engine;
86 int ThresholdMain::is_realtime()
91 char* ThresholdMain::plugin_title()
93 return N_("Threshold");
97 #include "picon_png.h"
98 NEW_PICON_MACRO(ThresholdMain)
100 SHOW_GUI_MACRO(ThresholdMain, ThresholdThread)
102 SET_STRING_MACRO(ThresholdMain)
104 RAISE_WINDOW_MACRO(ThresholdMain)
106 LOAD_CONFIGURATION_MACRO(ThresholdMain, ThresholdConfig)
114 int ThresholdMain::process_buffer(VFrame *frame,
115 int64_t start_position,
118 load_configuration();
120 int use_opengl = get_use_opengl() &&
121 (!config.plot || !gui_open());
125 get_source_position(),
129 if(use_opengl) return run_opengl();
131 send_render_gui(frame);
133 if(!threshold_engine)
134 threshold_engine = new ThresholdEngine(this);
135 threshold_engine->process_packages(frame);
140 int ThresholdMain::load_defaults()
142 char directory[BCTEXTLEN], string[BCTEXTLEN];
143 sprintf(directory, "%sthreshold.rc", BCASTDIR);
144 defaults = new BC_Hash(directory);
146 config.min = defaults->get("MIN", config.min);
147 config.max = defaults->get("MAX", config.max);
148 config.plot = defaults->get("PLOT", config.plot);
153 int ThresholdMain::save_defaults()
155 defaults->update("MIN", config.min);
156 defaults->update("MAX", config.max);
157 defaults->update("PLOT", config.plot);
161 void ThresholdMain::save_data(KeyFrame *keyframe)
164 file.set_shared_string(keyframe->data, MESSAGESIZE);
165 file.tag.set_title("THRESHOLD");
166 file.tag.set_property("MIN", config.min);
167 file.tag.set_property("MAX", config.max);
168 file.tag.set_property("PLOT", config.plot);
170 file.terminate_string();
173 void ThresholdMain::read_data(KeyFrame *keyframe)
176 file.set_shared_string(keyframe->data, strlen(keyframe->data));
180 result = file.read_tag();
183 config.min = file.tag.get_property("MIN", config.min);
184 config.max = file.tag.get_property("MAX", config.max);
185 config.plot = file.tag.get_property("PLOT", config.plot);
191 void ThresholdMain::update_gui()
195 thread->window->lock_window("ThresholdMain::update_gui");
196 if(load_configuration())
198 thread->window->min->update(config.min);
199 thread->window->max->update(config.max);
200 thread->window->plot->update(config.plot);
202 thread->window->unlock_window();
206 void ThresholdMain::render_gui(void *data)
210 calculate_histogram((VFrame*)data);
211 thread->window->lock_window("ThresholdMain::render_gui");
212 thread->window->canvas->draw();
213 thread->window->unlock_window();
217 void ThresholdMain::calculate_histogram(VFrame *frame)
219 if(!engine) engine = new HistogramEngine(get_project_smp() + 1,
220 get_project_smp() + 1);
221 engine->process_packages(frame);
224 int ThresholdMain::handle_opengl()
227 static char *rgb_shader =
228 "uniform sampler2D tex;\n"
229 "uniform float min;\n"
230 "uniform float max;\n"
233 " vec4 pixel = texture2D(tex, gl_TexCoord[0].st);\n"
234 " float v = dot(pixel.rgb, vec3(0.299, 0.587, 0.114));\n"
235 " if(v >= min && v < max)\n"
236 " pixel.rgb = vec3(1.0, 1.0, 1.0);\n"
238 " pixel.rgb = vec3(0.0, 0.0, 0.0);\n"
239 " gl_FragColor = pixel;\n"
242 static char *yuv_shader =
243 "uniform sampler2D tex;\n"
244 "uniform float min;\n"
245 "uniform float max;\n"
248 " vec4 pixel = texture2D(tex, gl_TexCoord[0].st);\n"
249 " if(pixel.r >= min && pixel.r < max)\n"
250 " pixel.rgb = vec3(1.0, 0.5, 0.5);\n"
252 " pixel.rgb = vec3(0.0, 0.5, 0.5);\n"
253 " gl_FragColor = pixel;\n"
256 get_output()->to_texture();
257 get_output()->enable_opengl();
259 unsigned int shader = 0;
260 if(cmodel_is_yuv(get_output()->get_color_model()))
261 shader = VFrame::make_shader(0, yuv_shader, 0);
263 shader = VFrame::make_shader(0, rgb_shader, 0);
267 glUseProgram(shader);
268 glUniform1i(glGetUniformLocation(shader, "tex"), 0);
269 glUniform1f(glGetUniformLocation(shader, "min"), config.min);
270 glUniform1f(glGetUniformLocation(shader, "max"), config.max);
273 get_output()->init_screen();
274 get_output()->bind_texture(0);
275 get_output()->draw_texture();
277 get_output()->set_opengl_state(VFrame::SCREEN);
303 ThresholdPackage::ThresholdPackage()
319 ThresholdUnit::ThresholdUnit(ThresholdEngine *server)
322 this->server = server;
325 void ThresholdUnit::process_package(LoadPackage *package)
327 ThresholdPackage *pkg = (ThresholdPackage*)package;
328 VFrame *data = server->data;
329 int min = (int)(server->plugin->config.min * 0xffff);
330 int max = (int)(server->plugin->config.max * 0xffff);
331 int r, g, b, a, y, u, v;
332 int w = server->data->get_w();
333 int h = server->data->get_h();
335 #define THRESHOLD_HEAD(type) \
337 for(int i = pkg->start; i < pkg->end; i++) \
339 type *in_row = (type*)data->get_rows()[i]; \
340 type *out_row = in_row; \
341 for(int j = 0; j < w; j++) \
344 #define THRESHOLD_TAIL(components, r_on, g_on, b_on, a_on, r_off, g_off, b_off, a_off) \
345 v = (r * 76 + g * 150 + b * 29) >> 8; \
346 if(v >= min && v < max) \
351 if(components == 4) *out_row++ = a_on; \
355 *out_row++ = r_off; \
356 *out_row++ = g_off; \
357 *out_row++ = b_off; \
358 if(components == 4) *out_row++ = a_off; \
360 in_row += components; \
366 switch(data->get_color_model())
369 THRESHOLD_HEAD(unsigned char)
370 r = (in_row[0] << 8) | in_row[0];
371 g = (in_row[1] << 8) | in_row[1];
372 b = (in_row[2] << 8) | in_row[2];
373 THRESHOLD_TAIL(3, 0xff, 0xff, 0xff, 0xff, 0x0, 0x0, 0x0, 0x0);
376 THRESHOLD_HEAD(float)
377 r = (int)(in_row[0] * 0xffff);
378 g = (int)(in_row[1] * 0xffff);
379 b = (int)(in_row[2] * 0xffff);
380 THRESHOLD_TAIL(3, 1.0, 1.0, 1.0, 1.0, 0.0, 0.0, 0.0, 0.0);
383 THRESHOLD_HEAD(unsigned char)
384 r = (in_row[0] << 8) | in_row[0];
385 g = (in_row[1] << 8) | in_row[1];
386 b = (in_row[2] << 8) | in_row[2];
387 THRESHOLD_TAIL(4, 0xff, 0xff, 0xff, 0xff, 0x0, 0x0, 0x0, 0x0);
390 THRESHOLD_HEAD(float)
391 r = (int)(in_row[0] * 0xffff);
392 g = (int)(in_row[1] * 0xffff);
393 b = (int)(in_row[2] * 0xffff);
394 THRESHOLD_TAIL(4, 1.0, 1.0, 1.0, 1.0, 0, 0, 0, 0);
397 THRESHOLD_HEAD(unsigned char)
398 y = (in_row[0] << 8) | in_row[0];
399 u = (in_row[1] << 8) | in_row[1];
400 v = (in_row[2] << 8) | in_row[2];
401 server->yuv->yuv_to_rgb_16(r, g, b, y, u, v);
402 THRESHOLD_TAIL(3, 0xff, 0x80, 0x80, 0xff, 0x0, 0x80, 0x80, 0x0)
405 THRESHOLD_HEAD(unsigned char)
406 y = (in_row[0] << 8) | in_row[0];
407 u = (in_row[1] << 8) | in_row[1];
408 v = (in_row[2] << 8) | in_row[2];
409 server->yuv->yuv_to_rgb_16(r, g, b, y, u, v);
410 THRESHOLD_TAIL(4, 0xff, 0x80, 0x80, 0xff, 0x0, 0x80, 0x80, 0x0)
413 THRESHOLD_HEAD(uint16_t)
417 server->yuv->yuv_to_rgb_16(r, g, b, y, u, v);
418 THRESHOLD_TAIL(3, 0xffff, 0x8000, 0x8000, 0xffff, 0x0, 0x8000, 0x8000, 0x0)
420 case BC_YUVA16161616:
421 THRESHOLD_HEAD(uint16_t)
425 server->yuv->yuv_to_rgb_16(r, g, b, y, u, v);
426 THRESHOLD_TAIL(4, 0xffff, 0x8000, 0x8000, 0xffff, 0x0, 0x8000, 0x8000, 0x0)
441 ThresholdEngine::ThresholdEngine(ThresholdMain *plugin)
442 : LoadServer(plugin->get_project_smp() + 1,
443 plugin->get_project_smp() + 1)
445 this->plugin = plugin;
449 ThresholdEngine::~ThresholdEngine()
454 void ThresholdEngine::process_packages(VFrame *data)
457 LoadServer::process_packages();
460 void ThresholdEngine::init_packages()
462 for(int i = 0; i < get_total_packages(); i++)
464 ThresholdPackage *package = (ThresholdPackage*)get_package(i);
465 package->start = data->get_h() * i / get_total_packages();
466 package->end = data->get_h() * (i + 1) / get_total_packages();
470 LoadClient* ThresholdEngine::new_client()
472 return (LoadClient*)new ThresholdUnit(this);
475 LoadPackage* ThresholdEngine::new_package()
477 return (LoadPackage*)new HistogramPackage;