r936: Sane default sample zoom...
[cinelerra_cv/mob.git] / plugins / interpolate / interpolate.C
blob3214d84f8a42ee6f11b2a8dfc9ecbf9bfd92093d
1 #include "bcdisplayinfo.h"
2 #include "clip.h"
3 #include "colormodels.h"
4 #include "filexml.h"
5 #include "aggregated.h"
6 #include "language.h"
7 #include "picon_png.h"
8 #include "interpolate.h"
10 #include <stdio.h>
11 #include <string.h>
14 REGISTER_PLUGIN(InterpolatePixelsMain)
18 PLUGIN_THREAD_OBJECT(InterpolatePixelsMain, 
19         InterpolatePixelsThread, 
20         InterpolatePixelsWindow)
24 InterpolatePixelsOffset::InterpolatePixelsOffset(InterpolatePixelsWindow *window, 
25         int x, 
26         int y, 
27         int *output)
28  : BC_ISlider(x,
29         y,
30         0,
31         50,
32         50,
33         0,
34         1,
35         *output,
36         0)
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();
50         return 1;
58 InterpolatePixelsWindow::InterpolatePixelsWindow(InterpolatePixelsMain *client, int x, int y)
59  : BC_Window(client->gui_string, 
60         x,
61         y,
62         200, 
63         100, 
64         200, 
65         100, 
66         0, 
67         0,
68         1)
69
70         this->client = client; 
73 InterpolatePixelsWindow::~InterpolatePixelsWindow()
77 int InterpolatePixelsWindow::create_objects()
79         int x = 10, y = 10;
80         
81         BC_Title *title;
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,
85                 y, 
86                 &client->config.x));
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,
91                 y, 
92                 &client->config.y));
93         y += MAX(y_offset->get_h(), title->get_h()) + 5;
95         show_window();
96         return 0;
100 WINDOW_CLOSE_EVENT(InterpolatePixelsWindow)
113 InterpolatePixelsConfig::InterpolatePixelsConfig()
115         x = 0;
116         y = 0;
119 int InterpolatePixelsConfig::equivalent(InterpolatePixelsConfig &that)
121         return x == that.x && y == that.y;
124 void InterpolatePixelsConfig::copy_from(InterpolatePixelsConfig &that)
126         x = that.x;
127         y = that.y;
130 void InterpolatePixelsConfig::interpolate(InterpolatePixelsConfig &prev,
131     InterpolatePixelsConfig &next,
132     int64_t prev_position,
133     int64_t next_position,
134     int64_t current_position)
136     this->x = prev.x;
137     this->y = prev.y;
145 InterpolatePixelsMain::InterpolatePixelsMain(PluginServer *server)
146  : PluginVClient(server)
148         PLUGIN_CONSTRUCTOR_MACRO
149         engine = 0;
152 InterpolatePixelsMain::~InterpolatePixelsMain()
154         PLUGIN_DESTRUCTOR_MACRO
155         delete engine;
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()
172         if(thread)
173         {
174                 int changed = load_configuration();
175                 if(changed)
176                 {
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();
181                 }
182         }
185 int InterpolatePixelsMain::load_defaults()
187         char directory[1024], string[1024];
188 // set the default directory
189         sprintf(directory, "%sinterpolatepixels.rc", BCASTDIR);
191 // load the defaults
192         defaults = new BC_Hash(directory);
193         defaults->load();
194         config.x = defaults->get("X", config.x);
195         config.y = defaults->get("Y", config.y);
197         return 0;
200 int InterpolatePixelsMain::save_defaults()
202         defaults->update("X", config.x);
203         defaults->update("Y", config.y);
204         defaults->save();
205         return 0;
208 LOAD_CONFIGURATION_MACRO(InterpolatePixelsMain, InterpolatePixelsConfig)
211 void InterpolatePixelsMain::save_data(KeyFrame *keyframe)
213         FileXML output;
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);
220         output.append_tag();
221         output.terminate_string();
224 void InterpolatePixelsMain::read_data(KeyFrame *keyframe)
226         FileXML input;
228         input.set_shared_string(keyframe->data, strlen(keyframe->data));
230         int result = 0;
231         float new_threshold;
233         while(!result)
234         {
235                 result = input.read_tag();
237                 if(!result)
238                 {
239                         if(input.tag.title_is("INTERPOLATEPIXELS"))
240                         {
241                                 config.x = input.tag.get_property("X", config.x);
242                                 config.y = input.tag.get_property("Y", config.y);
243                         }
244                 }
245         }
250 int InterpolatePixelsMain::process_buffer(VFrame *frame,
251         int64_t start_position,
252         double frame_rate)
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);
260         read_frame(frame, 
261                 0, 
262                 start_position, 
263                 frame_rate,
264                 get_use_opengl());
265 //frame->dump_params();
267         if(get_use_opengl())
268         {
269 // Aggregate with gamma
270                 if(next_effect_is("Gamma") ||
271                         next_effect_is("Histogram") ||
272                         next_effect_is("Color Balance"))
273                         return 0;
276                 return run_opengl();
277         }
280         if(get_output()->get_color_model() != BC_RGB_FLOAT &&
281                 get_output()->get_color_model() != BC_RGBA_FLOAT)
282         {
283                 printf("InterpolatePixelsMain::process_buffer: only supports float colormodels\n");
284                 return 1;
285         }
287         new_temp(frame->get_w(), frame->get_h(), frame->get_color_model());
288         get_temp()->copy_from(frame);
289         if(!engine)
290                 engine = new InterpolatePixelsEngine(this);
291         engine->process_packages();
293         return 0;
296 // The pattern is
297 //   G B
298 //   R G
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");
306 #ifdef HAVE_GL
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,
316                                         shader_stack[0],
317                                         0);
318         if(frag > 0)
319         {
320                 glUseProgram(frag);
321                 glUniform1i(glGetUniformLocation(frag, "tex"), 0);
322                 INTERPOLATE_UNIFORMS(frag)
323         }
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);
330         
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);
335         glUseProgram(0);
336         get_output()->set_opengl_state(VFrame::SCREEN);
338 #endif
339         return 0;
354 InterpolatePixelsPackage::InterpolatePixelsPackage()
355  : LoadPackage()
357         
365 InterpolatePixelsUnit::InterpolatePixelsUnit(InterpolatePixelsEngine *server, InterpolatePixelsMain *plugin)
366  : LoadClient(server)
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;
379         int y1 = pkg->y1;
380         int y2 = pkg->y2;
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));
385         y1 = MAX(y1, 1);
386         y2 = MIN(y2, h - 1);
388 // Only supports float because it's useless in any other colormodel.
389         for(int i = y1; i < y2; i++)
390         {
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;
401                 float r;
402                 float g;
403                 float b;
404 #undef RED
405 #define RED 0
406 #undef GREEN
407 #define GREEN 1
408 #undef BLUE
409 #define BLUE 2
410                 if(pattern_coord_y == 0)
411                 {
412                         for(int j = 1; j < w - 1; j++)
413                         {
414                                 int pattern_coord_x = (j - pattern_offset_x) % 2;
415 // Top left pixel
416                                 if(pattern_coord_x == 0)
417                                 {
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;
421                                 }
422                                 else
423 // Top right pixel
424                                 {
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] +
430                                                 prev_row[GREEN] +
431                                                 current_row[components + GREEN] +
432                                                 next_row[GREEN]) / 4;
433                                         b = current_row[BLUE];
434                                 }
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;
443                         }
444                 }
445                 else
446                 {
447                         for(int j = 1; j < w - 1; j++)
448                         {
449                                 int pattern_coord_x = (j - pattern_offset_x) % 2;
450 // Bottom left pixel
451                                 if(pattern_coord_x == 0)
452                                 {
453                                         r = current_row[RED];
454                                         g = (current_row[-components + GREEN] +
455                                                 prev_row[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;
462                                 }
463                                 else
464 // Bottom right pixel
465                                 {
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;
469                                 }
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;
478                         }
479                 }
480         }
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];
495         string[0] = 0;
496         plugin->get_output()->get_params()->get("DCRAW_MATRIX", string);
497         sscanf(string, 
498                 "%f %f %f %f %f %f %f %f %f", 
499                 &color_matrix[0],
500                 &color_matrix[1],
501                 &color_matrix[2],
502                 &color_matrix[3],
503                 &color_matrix[4],
504                 &color_matrix[5],
505                 &color_matrix[6],
506                 &color_matrix[7],
507                 &color_matrix[8]);
508         for(int i = 0; i < get_total_packages(); i++)
509         {
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();
513         }
517 LoadClient* InterpolatePixelsEngine::new_client()
519         return new InterpolatePixelsUnit(this, plugin);
523 LoadPackage* InterpolatePixelsEngine::new_package()
525         return new InterpolatePixelsPackage;