1 #include "bcdisplayinfo.h"
3 #include "colormodels.h"
5 #include "aggregated.h"
8 #include "interpolate.h"
14 REGISTER_PLUGIN(InterpolatePixelsMain)
18 PLUGIN_THREAD_OBJECT(InterpolatePixelsMain,
19 InterpolatePixelsThread,
20 InterpolatePixelsWindow)
24 InterpolatePixelsOffset::InterpolatePixelsOffset(InterpolatePixelsWindow *window,
38 this->window = window;
39 this->output = output;
42 InterpolatePixelsOffset::~InterpolatePixelsOffset()
46 int InterpolatePixelsOffset::handle_event()
48 *output = get_value();
49 window->client->send_configure_change();
58 InterpolatePixelsWindow::InterpolatePixelsWindow(InterpolatePixelsMain *client, int x, int y)
59 : BC_Window(client->gui_string,
70 this->client = client;
73 InterpolatePixelsWindow::~InterpolatePixelsWindow()
77 int InterpolatePixelsWindow::create_objects()
82 add_tool(title = new BC_Title(x, y, _("X Offset:")));
83 add_tool(x_offset = new InterpolatePixelsOffset(this,
84 x + title->get_w() + 5,
87 y += MAX(x_offset->get_h(), title->get_h()) + 5;
88 add_tool(title = new BC_Title(x, y, _("Y Offset:")));
89 add_tool(y_offset = new InterpolatePixelsOffset(this,
90 x + title->get_w() + 5,
93 y += MAX(y_offset->get_h(), title->get_h()) + 5;
100 WINDOW_CLOSE_EVENT(InterpolatePixelsWindow)
113 InterpolatePixelsConfig::InterpolatePixelsConfig()
119 int InterpolatePixelsConfig::equivalent(InterpolatePixelsConfig &that)
121 return x == that.x && y == that.y;
124 void InterpolatePixelsConfig::copy_from(InterpolatePixelsConfig &that)
130 void InterpolatePixelsConfig::interpolate(InterpolatePixelsConfig &prev,
131 InterpolatePixelsConfig &next,
132 int64_t prev_position,
133 int64_t next_position,
134 int64_t current_position)
145 InterpolatePixelsMain::InterpolatePixelsMain(PluginServer *server)
146 : PluginVClient(server)
148 PLUGIN_CONSTRUCTOR_MACRO
152 InterpolatePixelsMain::~InterpolatePixelsMain()
154 PLUGIN_DESTRUCTOR_MACRO
158 char* InterpolatePixelsMain::plugin_title() { return N_("Interpolate Pixels"); }
159 int InterpolatePixelsMain::is_realtime() { return 1; }
162 SHOW_GUI_MACRO(InterpolatePixelsMain, InterpolatePixelsThread)
164 SET_STRING_MACRO(InterpolatePixelsMain)
166 RAISE_WINDOW_MACRO(InterpolatePixelsMain)
168 NEW_PICON_MACRO(InterpolatePixelsMain)
170 void InterpolatePixelsMain::update_gui()
174 int changed = load_configuration();
177 thread->window->lock_window("InterpolatePixelsMain::update_gui");
178 thread->window->x_offset->update(config.x);
179 thread->window->y_offset->update(config.y);
180 thread->window->unlock_window();
185 int InterpolatePixelsMain::load_defaults()
187 char directory[1024], string[1024];
188 // set the default directory
189 sprintf(directory, "%sinterpolatepixels.rc", BCASTDIR);
192 defaults = new BC_Hash(directory);
194 config.x = defaults->get("X", config.x);
195 config.y = defaults->get("Y", config.y);
200 int InterpolatePixelsMain::save_defaults()
202 defaults->update("X", config.x);
203 defaults->update("Y", config.y);
208 LOAD_CONFIGURATION_MACRO(InterpolatePixelsMain, InterpolatePixelsConfig)
211 void InterpolatePixelsMain::save_data(KeyFrame *keyframe)
215 // cause data to be stored directly in text
216 output.set_shared_string(keyframe->data, MESSAGESIZE);
217 output.tag.set_title("INTERPOLATEPIXELS");
218 output.tag.set_property("X", config.x);
219 output.tag.set_property("Y", config.y);
221 output.terminate_string();
224 void InterpolatePixelsMain::read_data(KeyFrame *keyframe)
228 input.set_shared_string(keyframe->data, strlen(keyframe->data));
235 result = input.read_tag();
239 if(input.tag.title_is("INTERPOLATEPIXELS"))
241 config.x = input.tag.get_property("X", config.x);
242 config.y = input.tag.get_property("Y", config.y);
250 int InterpolatePixelsMain::process_buffer(VFrame *frame,
251 int64_t start_position,
254 load_configuration();
256 // Set aggregation parameters
257 frame->get_params()->update("INTERPOLATEPIXELS_X", config.x);
258 frame->get_params()->update("INTERPOLATEPIXELS_Y", config.y);
265 //frame->dump_params();
269 // Aggregate with gamma
270 if(next_effect_is("Gamma") ||
271 next_effect_is("Histogram") ||
272 next_effect_is("Color Balance"))
280 if(get_output()->get_color_model() != BC_RGB_FLOAT &&
281 get_output()->get_color_model() != BC_RGBA_FLOAT)
283 printf("InterpolatePixelsMain::process_buffer: only supports float colormodels\n");
287 new_temp(frame->get_w(), frame->get_h(), frame->get_color_model());
288 get_temp()->copy_from(frame);
290 engine = new InterpolatePixelsEngine(this);
291 engine->process_packages();
299 // And is offset to recreate the 4 possibilities.
300 // The color values are interpolated in the most basic way.
301 // No adaptive algorithm is used.
303 int InterpolatePixelsMain::handle_opengl()
305 printf("InterpolatePixelsMain::handle_opengl\n");
309 get_output()->to_texture();
310 get_output()->enable_opengl();
312 char *shader_stack[] = { 0, 0, 0 };
313 int current_shader = 0;
314 INTERPOLATE_COMPILE(shader_stack, current_shader)
315 unsigned int frag = VFrame::make_shader(0,
321 glUniform1i(glGetUniformLocation(frag, "tex"), 0);
322 INTERPOLATE_UNIFORMS(frag)
326 get_output()->init_screen();
327 get_output()->bind_texture(0);
328 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
329 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
332 get_output()->draw_texture();
333 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
334 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
336 get_output()->set_opengl_state(VFrame::SCREEN);
354 InterpolatePixelsPackage::InterpolatePixelsPackage()
365 InterpolatePixelsUnit::InterpolatePixelsUnit(InterpolatePixelsEngine *server, InterpolatePixelsMain *plugin)
368 this->plugin = plugin;
369 this->server = server;
372 void InterpolatePixelsUnit::process_package(LoadPackage *package)
374 InterpolatePixelsPackage *pkg = (InterpolatePixelsPackage*)package;
375 int h = plugin->get_temp()->get_h();
376 int w = plugin->get_temp()->get_w();
377 int pattern_offset_x = plugin->config.x;
378 int pattern_offset_y = plugin->config.y;
381 int components = cmodel_components(plugin->get_output()->get_color_model());
382 float color_matrix[9];
383 memcpy(color_matrix, server->color_matrix, sizeof(color_matrix));
388 // Only supports float because it's useless in any other colormodel.
389 for(int i = y1; i < y2; i++)
391 int pattern_coord_y = (i - pattern_offset_y) % 2;
392 float *prev_row = (float*)plugin->get_temp()->get_rows()[i - 1];
393 float *current_row = (float*)plugin->get_temp()->get_rows()[i];
394 float *next_row = (float*)plugin->get_temp()->get_rows()[i + 1];
395 float *out_row = (float*)plugin->get_output()->get_rows()[i];
397 prev_row += components;
398 current_row += components;
399 next_row += components;
400 out_row += components;
410 if(pattern_coord_y == 0)
412 for(int j = 1; j < w - 1; j++)
414 int pattern_coord_x = (j - pattern_offset_x) % 2;
416 if(pattern_coord_x == 0)
418 r = (prev_row[RED] + next_row[RED]) / 2;
419 g = current_row[GREEN];
420 b = (current_row[-components + BLUE] + current_row[components + BLUE]) / 2;
425 r = (prev_row[-components + RED] +
426 prev_row[components + RED] +
427 next_row[-components + RED] +
428 next_row[components + RED]) / 4;
429 g = (current_row[-components + GREEN] +
431 current_row[components + GREEN] +
432 next_row[GREEN]) / 4;
433 b = current_row[BLUE];
436 out_row[0] = r * color_matrix[0] + g * color_matrix[1] + b * color_matrix[2];
437 out_row[1] = r * color_matrix[3] + g * color_matrix[4] + b * color_matrix[5];
438 out_row[2] = r * color_matrix[6] + g * color_matrix[7] + b * color_matrix[8];
439 prev_row += components;
440 current_row += components;
441 next_row += components;
442 out_row += components;
447 for(int j = 1; j < w - 1; j++)
449 int pattern_coord_x = (j - pattern_offset_x) % 2;
451 if(pattern_coord_x == 0)
453 r = current_row[RED];
454 g = (current_row[-components + GREEN] +
456 current_row[components + GREEN] +
457 next_row[GREEN]) / 4;
458 b = (prev_row[-components + BLUE] +
459 prev_row[components + BLUE] +
460 next_row[-components + BLUE] +
461 next_row[components + BLUE]) / 4;
464 // Bottom right pixel
466 float r = (current_row[-components + RED] + current_row[components + RED]) / 2;
467 float g = current_row[GREEN];
468 float b = (prev_row[BLUE] + next_row[BLUE]) / 2;
471 out_row[0] = r * color_matrix[0] + g * color_matrix[1] + b * color_matrix[2];
472 out_row[1] = r * color_matrix[3] + g * color_matrix[4] + b * color_matrix[5];
473 out_row[2] = r * color_matrix[6] + g * color_matrix[7] + b * color_matrix[8];
474 prev_row += components;
475 current_row += components;
476 next_row += components;
477 out_row += components;
486 InterpolatePixelsEngine::InterpolatePixelsEngine(InterpolatePixelsMain *plugin)
487 : LoadServer(plugin->get_project_smp() + 1, plugin->get_project_smp() + 1)
489 this->plugin = plugin;
492 void InterpolatePixelsEngine::init_packages()
494 char string[BCTEXTLEN];
496 plugin->get_output()->get_params()->get("DCRAW_MATRIX", string);
498 "%f %f %f %f %f %f %f %f %f",
508 for(int i = 0; i < get_total_packages(); i++)
510 InterpolatePixelsPackage *package = (InterpolatePixelsPackage*)get_package(i);
511 package->y1 = plugin->get_temp()->get_h() * i / get_total_packages();
512 package->y2 = plugin->get_temp()->get_h() * (i + 1) / get_total_packages();
517 LoadClient* InterpolatePixelsEngine::new_client()
519 return new InterpolatePixelsUnit(this, plugin);
523 LoadPackage* InterpolatePixelsEngine::new_package()
525 return new InterpolatePixelsPackage;