-
-/*
- * CINELERRA
- * Copyright (C) 2008 Adam Williams <broadcast at earthling dot net>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- *
- */
-
-#include "bcdisplayinfo.h"
-#include "clip.h"
-#include "bccmodels.h"
-#include "filexml.h"
-#include "aggregated.h"
-#include "language.h"
-#include "interpolate.h"
-
-#include <stdio.h>
-#include <string.h>
-
-
-REGISTER_PLUGIN(InterpolatePixelsMain)
-
-
-
-
-
-
-InterpolatePixelsOffset::InterpolatePixelsOffset(InterpolatePixelsWindow *window,
- int x,
- int y,
- int *output)
- : BC_ISlider(x,
- y,
- 0,
- 50,
- 50,
- 0,
- 1,
- *output,
- 0)
-{
- this->window = window;
- this->output = output;
-}
-
-InterpolatePixelsOffset::~InterpolatePixelsOffset()
-{
-}
-
-int InterpolatePixelsOffset::handle_event()
-{
- *output = get_value();
- window->client->send_configure_change();
- return 1;
-}
-
-
-
-
-
-
-InterpolatePixelsWindow::InterpolatePixelsWindow(InterpolatePixelsMain *client)
- : PluginClientWindow(client,
- 200,
- 100,
- 200,
- 100,
- 0)
-{
- this->client = client;
-}
-
-InterpolatePixelsWindow::~InterpolatePixelsWindow()
-{
-}
-
-void InterpolatePixelsWindow::create_objects()
-{
- int x = 10, y = 10;
-
- BC_Title *title;
- add_tool(title = new BC_Title(x, y, _("X Offset:")));
- add_tool(x_offset = new InterpolatePixelsOffset(this,
- x + title->get_w() + 5,
- y,
- &client->config.x));
- y += MAX(x_offset->get_h(), title->get_h()) + 5;
- add_tool(title = new BC_Title(x, y, _("Y Offset:")));
- add_tool(y_offset = new InterpolatePixelsOffset(this,
- x + title->get_w() + 5,
- y,
- &client->config.y));
- y += MAX(y_offset->get_h(), title->get_h()) + 5;
-
- show_window();
-}
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-InterpolatePixelsConfig::InterpolatePixelsConfig()
-{
- x = 0;
- y = 0;
-}
-
-int InterpolatePixelsConfig::equivalent(InterpolatePixelsConfig &that)
-{
- return x == that.x && y == that.y;
-}
-
-void InterpolatePixelsConfig::copy_from(InterpolatePixelsConfig &that)
-{
- x = that.x;
- y = that.y;
-}
-
-void InterpolatePixelsConfig::interpolate(InterpolatePixelsConfig &prev,
- InterpolatePixelsConfig &next,
- int64_t prev_position,
- int64_t next_position,
- int64_t current_position)
-{
- this->x = prev.x;
- this->y = prev.y;
-}
-
-
-
-
-
-
-InterpolatePixelsMain::InterpolatePixelsMain(PluginServer *server)
- : PluginVClient(server)
-{
- out_temp = out_frame = 0;
- engine = 0;
-}
-
-InterpolatePixelsMain::~InterpolatePixelsMain()
-{
- delete out_temp;
- delete engine;
-}
-
-const char* InterpolatePixelsMain::plugin_title() { return _("Interpolate Pixels"); }
-int InterpolatePixelsMain::is_realtime() { return 1; }
-
-
-NEW_WINDOW_MACRO(InterpolatePixelsMain, InterpolatePixelsWindow)
-
-
-void InterpolatePixelsMain::update_gui()
-{
- if(thread)
- {
- int changed = load_configuration();
- if(changed)
- {
- thread->window->lock_window("InterpolatePixelsMain::update_gui");
- ((InterpolatePixelsWindow*)thread->window)->x_offset->update(config.x);
- ((InterpolatePixelsWindow*)thread->window)->y_offset->update(config.y);
- thread->window->unlock_window();
- }
- }
-}
-
-
-LOAD_CONFIGURATION_MACRO(InterpolatePixelsMain, InterpolatePixelsConfig)
-
-
-void InterpolatePixelsMain::save_data(KeyFrame *keyframe)
-{
- FileXML output;
-
-// cause data to be stored directly in text
- output.set_shared_output(keyframe->get_data(), MESSAGESIZE);
- output.tag.set_title("INTERPOLATEPIXELS");
- output.tag.set_property("X", config.x);
- output.tag.set_property("Y", config.y);
- output.append_tag();
- output.tag.set_title("/INTERPOLATEPIXELS");
- output.append_tag();
- output.append_newline();
- output.terminate_string();
-}
-
-void InterpolatePixelsMain::read_data(KeyFrame *keyframe)
-{
- FileXML input;
-
- input.set_shared_input(keyframe->get_data(), strlen(keyframe->get_data()));
-
- int result = 0;
-
- while(!result)
- {
- result = input.read_tag();
-
- if(!result)
- {
- if(input.tag.title_is("INTERPOLATEPIXELS"))
- {
- config.x = input.tag.get_property("X", config.x);
- config.y = input.tag.get_property("Y", config.y);
- }
- }
- }
-}
-
-int InterpolatePixelsMain::process_buffer(VFrame *frame,
- int64_t start_position,
- double frame_rate)
-{
- load_configuration();
-
-// Set aggregation parameters
- frame->get_params()->update("INTERPOLATEPIXELS_X", config.x);
- frame->get_params()->update("INTERPOLATEPIXELS_Y", config.y);
-
- read_frame(frame,
- 0,
- start_position,
- frame_rate,
- get_use_opengl());
-//frame->dump_params();
-
- if(get_use_opengl())
- {
-// Aggregate with gamma
- if(next_effect_is(_("Gamma")) ||
- next_effect_is(_("Histogram")) ||
- next_effect_is(_("Color Balance")))
- return 0;
-
-
- return run_opengl();
- }
-
- int color_model = frame->get_color_model();
- int active_model = BC_CModels::has_alpha(color_model) ?
- BC_RGBA_FLOAT : BC_RGB_FLOAT;
- new_temp(frame->get_w(), frame->get_h(), active_model);
- get_temp()->transfer_from(frame);
-
- out_frame = get_output();
- color_model = out_frame->get_color_model();
- active_model = BC_CModels::has_alpha(color_model) ?
- BC_RGBA_FLOAT : BC_RGB_FLOAT;
- if( active_model != color_model ) {
- int w = out_frame->get_w(), h = out_frame->get_h();
- if( out_temp && ( out_temp->get_color_model() != active_model ||
- out_temp->get_w() != w || out_temp->get_w() != h ) ) {
- delete out_temp; out_temp = 0;
- }
- if( !out_temp )
- out_temp = new VFrame(0, -1, w, h, active_model, -1);
- out_frame = out_temp;
- }
-
- if(!engine)
- engine = new InterpolatePixelsEngine(this);
- engine->process_packages();
-
- if( out_frame != get_output() ) {
- if( BC_CModels::has_alpha(out_frame->get_color_model()) ) {
- unsigned char **out_rows = out_frame->get_rows();
- int w = out_frame->get_w(), h = out_frame->get_h();
- if( BC_CModels::has_alpha(get_temp()->get_color_model()) ) {
- unsigned char **in_rows = get_temp()->get_rows();
- for( int y=0; y<h; ++y ) {
- float *inp = (float *)in_rows[y];
- float *outp = (float *)out_rows[y];
- for( int x=0; x<w; ++x,inp+=4,outp+=4 ) outp[3] = inp[3];
- }
- }
- else {
- for( int y=0; y<h; ++y ) {
- float *outp = (float *)out_rows[y];
- for( int x=0; x<w; ++x,outp+=4 ) outp[3] = 1;
- }
- }
- }
- get_output()->transfer_from(out_frame);
- }
-
- return 0;
-}
-
-// The pattern is
-// G B
-// R G
-// And is offset to recreate the 4 possibilities.
-// The color values are interpolated in the most basic way.
-// No adaptive algorithm is used.
-
-int InterpolatePixelsMain::handle_opengl()
-{
-//printf("InterpolatePixelsMain::handle_opengl\n");
-#ifdef HAVE_GL
-
-
- get_output()->to_texture();
- get_output()->enable_opengl();
-
- const char *shader_stack[] = { 0, 0, 0 };
- int current_shader = 0;
- INTERPOLATE_COMPILE(shader_stack, current_shader)
- unsigned int frag = VFrame::make_shader(0,
- shader_stack[0],
- 0);
- if(frag > 0)
- {
- glUseProgram(frag);
- glUniform1i(glGetUniformLocation(frag, "tex"), 0);
- INTERPOLATE_UNIFORMS(frag)
- }
-
-
- get_output()->init_screen();
- get_output()->bind_texture(0);
- glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
- glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
-
-
- get_output()->draw_texture();
- glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
- glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
- glUseProgram(0);
- get_output()->set_opengl_state(VFrame::SCREEN);
-
-#endif
- return 0;
-}
-
-
-
-
-
-
-
-
-
-
-
-
-
-InterpolatePixelsPackage::InterpolatePixelsPackage()
- : LoadPackage()
-{
-
-}
-
-
-
-
-
-
-InterpolatePixelsUnit::InterpolatePixelsUnit(InterpolatePixelsEngine *server, InterpolatePixelsMain *plugin)
- : LoadClient(server)
-{
- this->plugin = plugin;
- this->server = server;
-}
-
-void InterpolatePixelsUnit::process_package(LoadPackage *package)
-{
- InterpolatePixelsPackage *pkg = (InterpolatePixelsPackage*)package;
- int h = plugin->get_temp()->get_h();
- int w = plugin->get_temp()->get_w();
- int pattern_offset_x = plugin->config.x;
- int pattern_offset_y = plugin->config.y;
- int y1 = pkg->y1;
- int y2 = pkg->y2;
- int components = BC_CModels::components(plugin->out_frame->get_color_model());
- float color_matrix[9];
- memcpy(color_matrix, server->color_matrix, sizeof(color_matrix));
-
- y1 = MAX(y1, 1);
- y2 = MIN(y2, h - 1);
-
-// Only supports float because it's useless in any other colormodel.
- for(int i = y1; i < y2; i++)
- {
- int pattern_coord_y = (i - pattern_offset_y) % 2;
- float *prev_row = (float*)plugin->get_temp()->get_rows()[i - 1];
- float *current_row = (float*)plugin->get_temp()->get_rows()[i];
- float *next_row = (float*)plugin->get_temp()->get_rows()[i + 1];
- float *out_row = (float*)plugin->out_frame->get_rows()[i];
-
- prev_row += components;
- current_row += components;
- next_row += components;
- out_row += components;
- float r;
- float g;
- float b;
-#undef RED
-#define RED 0
-#undef GREEN
-#define GREEN 1
-#undef BLUE
-#define BLUE 2
- if(pattern_coord_y == 0)
- {
- for(int j = 1; j < w - 1; j++)
- {
- int pattern_coord_x = (j - pattern_offset_x) % 2;
-// Top left pixel
- if(pattern_coord_x == 0)
- {
- r = (prev_row[RED] + next_row[RED]) / 2;
- g = current_row[GREEN];
- b = (current_row[-components + BLUE] + current_row[components + BLUE]) / 2;
- }
- else
-// Top right pixel
- {
- r = (prev_row[-components + RED] +
- prev_row[components + RED] +
- next_row[-components + RED] +
- next_row[components + RED]) / 4;
- g = (current_row[-components + GREEN] +
- prev_row[GREEN] +
- current_row[components + GREEN] +
- next_row[GREEN]) / 4;
- b = current_row[BLUE];
- }
-
- out_row[0] = r * color_matrix[0] + g * color_matrix[1] + b * color_matrix[2];
- out_row[1] = r * color_matrix[3] + g * color_matrix[4] + b * color_matrix[5];
- out_row[2] = r * color_matrix[6] + g * color_matrix[7] + b * color_matrix[8];
- prev_row += components;
- current_row += components;
- next_row += components;
- out_row += components;
- }
- }
- else
- {
- for(int j = 1; j < w - 1; j++)
- {
- int pattern_coord_x = (j - pattern_offset_x) % 2;
-// Bottom left pixel
- if(pattern_coord_x == 0)
- {
- r = current_row[RED];
- g = (current_row[-components + GREEN] +
- prev_row[GREEN] +
- current_row[components + GREEN] +
- next_row[GREEN]) / 4;
- b = (prev_row[-components + BLUE] +
- prev_row[components + BLUE] +
- next_row[-components + BLUE] +
- next_row[components + BLUE]) / 4;
- }
- else
-// Bottom right pixel
- {
- r = (current_row[-components + RED] + current_row[components + RED]) / 2;
- g = current_row[GREEN];
- b = (prev_row[BLUE] + next_row[BLUE]) / 2;
- }
-
- out_row[0] = r * color_matrix[0] + g * color_matrix[1] + b * color_matrix[2];
- out_row[1] = r * color_matrix[3] + g * color_matrix[4] + b * color_matrix[5];
- out_row[2] = r * color_matrix[6] + g * color_matrix[7] + b * color_matrix[8];
- prev_row += components;
- current_row += components;
- next_row += components;
- out_row += components;
- }
- }
- }
-}
-
-
-
-
-InterpolatePixelsEngine::InterpolatePixelsEngine(InterpolatePixelsMain *plugin)
- : LoadServer(plugin->get_project_smp() + 1, plugin->get_project_smp() + 1)
-{
- this->plugin = plugin;
-}
-
-void InterpolatePixelsEngine::init_packages()
-{
- for( int i=0; i<9; ++i ) color_matrix[i] = 0;
- for( int i=0; i<3; ++i ) color_matrix[i*3 + i] = 1;
- char string[BCTEXTLEN];
- string[0] = 0;
- plugin->get_output()->get_params()->get("DCRAW_MATRIX", string);
- sscanf(string,
- "%f %f %f %f %f %f %f %f %f",
- &color_matrix[0],
- &color_matrix[1],
- &color_matrix[2],
- &color_matrix[3],
- &color_matrix[4],
- &color_matrix[5],
- &color_matrix[6],
- &color_matrix[7],
- &color_matrix[8]);
- for(int i = 0; i < get_total_packages(); i++)
- {
- InterpolatePixelsPackage *package = (InterpolatePixelsPackage*)get_package(i);
- package->y1 = plugin->get_temp()->get_h() * i / get_total_packages();
- package->y2 = plugin->get_temp()->get_h() * (i + 1) / get_total_packages();
- }
-}
-
-
-LoadClient* InterpolatePixelsEngine::new_client()
-{
- return new InterpolatePixelsUnit(this, plugin);
-}
-
-
-LoadPackage* InterpolatePixelsEngine::new_package()
-{
- return new InterpolatePixelsPackage;
-}
-
-