From: Good Guy Date: Mon, 29 Feb 2016 17:47:42 +0000 (-0700) Subject: add histogram_bezier plugin X-Git-Url: https://git.cinelerra-gg.org/?a=commitdiff_plain;h=bc872c7cea032325f9a7b5c1c6ad78ba0b6c32f9;p=goodguy%2Fhistory.git add histogram_bezier plugin --- diff --git a/cinelerra-5.0/plugin_defs b/cinelerra-5.0/plugin_defs index 41c39b5f..b07ef216 100644 --- a/cinelerra-5.0/plugin_defs +++ b/cinelerra-5.0/plugin_defs @@ -16,7 +16,7 @@ transforms := 1080to480 1080to540 720to480 lens perspective photoscale \ plugin_dirs += colors colors := brightness bluebanana C41 color3way colorbalance huesaturation \ - gamma gradient histogram threshold + gamma gradient histogram histogram_bezier threshold plugin_dirs += exotic exotic := aging burn dot holo oil edge diff --git a/cinelerra-5.0/plugins/Makefile b/cinelerra-5.0/plugins/Makefile index e45c30b5..ffbff611 100644 --- a/cinelerra-5.0/plugins/Makefile +++ b/cinelerra-5.0/plugins/Makefile @@ -56,6 +56,7 @@ DIRS = \ graphic \ greycstoration \ histogram \ + histogram_bezier \ holo \ huesaturation \ interpolate \ diff --git a/cinelerra-5.0/plugins/histogram_bezier/Makefile b/cinelerra-5.0/plugins/histogram_bezier/Makefile index e4fa47ea..a0f852e9 100644 --- a/cinelerra-5.0/plugins/histogram_bezier/Makefile +++ b/cinelerra-5.0/plugins/histogram_bezier/Makefile @@ -1,14 +1,14 @@ include ../../global_config OBJS = \ - $(OBJDIR)/histogram.o \ - $(OBJDIR)/histogramconfig.o \ - $(OBJDIR)/histogramwindow.o + $(OBJDIR)/bistogram.o \ + $(OBJDIR)/bistogramconfig.o \ + $(OBJDIR)/bistogramwindow.o -PLUGIN = histogram +PLUGIN = histogram_bezier include ../../plugin_config -$(OBJDIR)/histogram.o: histogram.C -$(OBJDIR)/histogramconfig.o: histogramconfig.C -$(OBJDIR)/histogramwindow.o: histogramwindow.C +$(OBJDIR)/bistogram.o: bistogram.C +$(OBJDIR)/bistogramconfig.o: bistogramconfig.C +$(OBJDIR)/bistogramwindow.o: bistogramwindow.C diff --git a/cinelerra-5.0/plugins/histogram_bezier/bistogram.C b/cinelerra-5.0/plugins/histogram_bezier/bistogram.C new file mode 100644 index 00000000..6799e316 --- /dev/null +++ b/cinelerra-5.0/plugins/histogram_bezier/bistogram.C @@ -0,0 +1,914 @@ + +/* + * CINELERRA + * Copyright (C) 2008 Adam Williams + * + * 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 +#include +#include +#include + +#include "bcdisplayinfo.h" +#include "bcsignals.h" +#include "clip.h" +#include "bchash.h" +#include "filexml.h" +#include "bistogram.h" +#include "bistogramconfig.h" +#include "bistogramwindow.h" +#include "keyframe.h" +#include "language.h" +#include "loadbalance.h" +#include "cicolors.h" +#include "vframe.h" + + + +class HistogramMain; +class HistogramEngine; +class HistogramWindow; + +REGISTER_PLUGIN(HistogramMain) + +HistogramMain::HistogramMain(PluginServer *server) + : PluginVClient(server) +{ + + engine = 0; + for(int i = 0; i < HISTOGRAM_MODES; i++) + { + lookup[i] = 0; + smoothed[i] = 0; + linear[i] = 0; + accum[i] = 0; + } + current_point = -1; + mode = HISTOGRAM_VALUE; + dragging_point = 0; + input = 0; + output = 0; +} + +HistogramMain::~HistogramMain() +{ + + for(int i = 0; i < HISTOGRAM_MODES;i++) + { + delete [] lookup[i]; + delete [] smoothed[i]; + delete [] linear[i]; + delete [] accum[i]; + } + delete engine; +} + +const char* HistogramMain::plugin_title() { return _("Histogram Bezier"); } +int HistogramMain::is_realtime() { return 1; } + + +NEW_WINDOW_MACRO(HistogramMain, HistogramWindow) +LOAD_CONFIGURATION_MACRO(HistogramMain, HistogramConfig) + +void HistogramMain::render_gui(void *data) +{ + if(thread) + { + calculate_histogram((VFrame*)data); + + if(config.automatic) + { + calculate_automatic((VFrame*)data); + } + + HistogramWindow *window = (HistogramWindow *)thread->window; + window->lock_window("HistogramMain::render_gui"); + window->update_canvas(); + if(config.automatic) + { + window->update_input(); + } + window->unlock_window(); + } +} + +void HistogramMain::update_gui() +{ + if(thread) + { + thread->window->lock_window("HistogramMain::update_gui"); + int reconfigure = load_configuration(); + if(reconfigure) + { + HistogramWindow *window = (HistogramWindow *)thread->window; + window->update(0); + if(!config.automatic) + { + window->update_input(); + } + } + thread->window->unlock_window(); + } +} + + +void HistogramMain::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("HISTOGRAM"); + + char string[BCTEXTLEN]; + + + for(int i = 0; i < HISTOGRAM_MODES; i++) + { + sprintf(string, "OUTPUT_MIN_%d", i); + output.tag.set_property(string, config.output_min[i]); + sprintf(string, "OUTPUT_MAX_%d", i); + output.tag.set_property(string, config.output_max[i]); +//printf("HistogramMain::save_data %d %f %d\n", config.input_min[i], config.input_mid[i], config.input_max[i]); + } + + output.tag.set_property("AUTOMATIC", config.automatic); + output.tag.set_property("THRESHOLD", config.threshold); + output.tag.set_property("SPLIT", config.split); + output.tag.set_property("INTERPOLATION", config.smoothMode); + output.append_tag(); + output.tag.set_title("/HISTOGRAM"); + output.append_tag(); + output.append_newline(); + + + + + + for(int j = 0; j < HISTOGRAM_MODES; j++) + { + output.tag.set_title("POINTS"); + output.append_tag(); + output.append_newline(); + + + HistogramPoint *current = config.points[j].first; + while(current) + { + output.tag.set_title("POINT"); + output.tag.set_property("X", current->x); + output.tag.set_property("Y", current->y); + output.tag.set_property("GRADIENT", current->gradient); + output.tag.set_property("XOFFSET_LEFT", current->xoffset_left); + output.tag.set_property("XOFFSET_RIGHT", current->xoffset_right); + output.append_tag(); + output.tag.set_title("/POINT"); + output.append_tag(); + output.append_newline(); + current = NEXT; + } + + + output.tag.set_title("/POINTS"); + output.append_tag(); + output.append_newline(); + } + + + + + + + output.terminate_string(); +} + +void HistogramMain::read_data(KeyFrame *keyframe) +{ + FileXML input; + + input.set_shared_input(keyframe->get_data(), strlen(keyframe->get_data())); + + int result = 0; + int current_input_mode = 0; + + + while(!result) + { + result = input.read_tag(); + + if(!result) + { + if(input.tag.title_is("HISTOGRAM")) + { + char string[BCTEXTLEN]; + for(int i = 0; i < HISTOGRAM_MODES; i++) + { + sprintf(string, "OUTPUT_MIN_%d", i); + config.output_min[i] = input.tag.get_property(string, config.output_min[i]); + sprintf(string, "OUTPUT_MAX_%d", i); + config.output_max[i] = input.tag.get_property(string, config.output_max[i]); +//printf("HistogramMain::read_data %d %f %d\n", config.input_min[i], config.input_mid[i], config.input_max[i]); + } + config.automatic = input.tag.get_property("AUTOMATIC", config.automatic); + config.threshold = input.tag.get_property("THRESHOLD", config.threshold); + config.split = input.tag.get_property("SPLIT", config.split); + config.smoothMode = input.tag.get_property("INTERPOLATION", config.smoothMode); + } + else + if(input.tag.title_is("POINTS")) + { + if(current_input_mode < HISTOGRAM_MODES) + { + HistogramPoints *points = &config.points[current_input_mode]; + while(points->last) + delete points->last; + while(!result) + { + result = input.read_tag(); + if(!result) + { + if(input.tag.title_is("/POINTS")) + { + break; + } + else + if(input.tag.title_is("POINT")) + { + points->insert( + input.tag.get_property("X", 0.0), + input.tag.get_property("Y", 0.0)); + points->last->gradient = + input.tag.get_property("GRADIENT", 1.0); + points->last->xoffset_left = + input.tag.get_property("XOFFSET_LEFT", -0.02); + points->last->xoffset_right = + input.tag.get_property("XOFFSET_RIGHT", 0.02); + } + } + } + + } + current_input_mode++; + } + } + } + + config.boundaries(); + +} + +float HistogramMain::calculate_linear(float input, + int subscript, + int use_value) +{ + int done = 0; + float output; + + if(input < 0) { + output = 0; + done = 1; + } + + if(input > 1) { + output = 1; + done = 1; + } + + if(!done) { + + float x1 = 0, y1 = 0; + float grad1 = 1.0; + float x1right = 0; + float x2 = 1, y2 = 1; + float grad2 = 1.0; + float x2left = 0; + +// Get 2 points surrounding current position + HistogramPoints *points = &config.points[subscript]; + HistogramPoint *current = points->first; + int done = 0; + while(current && !done) { + if(current->x > input) { + x2 = current->x; + y2 = current->y; + grad2 = current->gradient; + x2left = current->xoffset_left; + done = 1; + } + else + current = NEXT; + } + + current = points->last; + done = 0; + while(current && !done) { + if(current->x <= input) { + x1 = current->x; + y1 = current->y; + grad1 = current->gradient; + done = 1; + x1right = current->xoffset_right; + } + else + current = PREVIOUS; + } + + + + + if(!EQUIV(x2 - x1, 0)) + { + if (config.smoothMode == HISTOGRAM_LINEAR) + output = (input - x1) * (y2 - y1) / (x2 - x1) + y1; + else if (config.smoothMode == HISTOGRAM_POLYNOMINAL) + { + /* Construct third grade polynom between every two points */ + float dx = x2 - x1; + float dy = y2 - y1; + float delx = input - x1; + output = (grad2 * dx + grad1 * dx - 2*dy) / (dx * dx * dx) * delx * delx * delx + + (dx * dx) * (3*dy - 2* grad1*dx - grad2*dx) / (dx * dx) * delx * delx + grad1*delx + y1; + } + else if (config.smoothMode == HISTOGRAM_BEZIER) + { + /* Using standart DeCasteljau algorithm */ + float y1right = y1 + grad1 * x1right; + float y2left = y2 + grad2 * x2left; + + float t = (input - x1) / (x2 - x1); + + float pointAy = y1 + (y1right - y1) * t; + float pointBy = y1right + (y2left - y1right) * t; + float pointCy = y2left + (y2 - y2left) * t; + float pointABy = pointAy + (pointBy - pointAy) * t; + float pointBCy = pointBy + (pointCy - pointBy) * t; + output = pointABy + (pointBCy - pointABy) * t; + } + } + else +// Linear + output = input * y2; + } + +// Apply value curve + if(use_value) { + output = calculate_linear(output, HISTOGRAM_VALUE, 0); + } + + + float output_min = config.output_min[subscript]; + float output_max = config.output_max[subscript]; + +// Compress output for value followed by channel + output = output_min + output * (output_max - output_min); + return output; +} + +float HistogramMain::calculate_smooth(float input, int subscript) +{ + float x_f = (input - HIST_MIN_INPUT) * HISTOGRAM_SLOTS / FLOAT_RANGE; + int x_i1 = (int)x_f; + int x_i2 = x_i1 + 1; + CLAMP(x_i1, 0, HISTOGRAM_SLOTS-1); + CLAMP(x_i2, 0, HISTOGRAM_SLOTS-1); + CLAMP(x_f, 0, HISTOGRAM_SLOTS-1); + + float smooth1 = smoothed[subscript][x_i1]; + float smooth2 = smoothed[subscript][x_i2]; + float result = smooth1 + (smooth2 - smooth1) * (x_f - x_i1); + CLAMP(result, 0, 1.0); + return result; +} + + +void HistogramMain::calculate_histogram(VFrame *data) +{ + + if(!engine) engine = new HistogramEngine(this, + get_project_smp() + 1, + get_project_smp() + 1); + + if(!accum[0]) + { + for(int i = 0; i < HISTOGRAM_MODES; i++) + accum[i] = new int[HISTOGRAM_SLOTS]; + } + engine->process_packages(HistogramEngine::HISTOGRAM, data); + + for(int i = 0; i < engine->get_total_clients(); i++) { + HistogramUnit *unit = (HistogramUnit*)engine->get_client(i); + if(i == 0) { + for(int j = 0; j < HISTOGRAM_MODES; j++) + memcpy(accum[j], unit->accum[j], sizeof(int) * HISTOGRAM_SLOTS); + } + else { + for(int j = 0; j < HISTOGRAM_MODES; j++) { + int *out = accum[j]; + int *in = unit->accum[j]; + for(int k = 0; k < HISTOGRAM_SLOTS; k++) + out[k] += in[k]; + } + } + } + +// Remove top and bottom from calculations. Doesn't work in high +// precision colormodels. + for(int i = 0; i < HISTOGRAM_MODES; i++) { + accum[i][0] = 0; + accum[i][HISTOGRAM_SLOTS - 1] = 0; + } +} + + +void HistogramMain::calculate_automatic(VFrame *data) +{ + calculate_histogram(data); + config.reset_points(); + +// Do each channel + for(int i = 0; i < 3; i++) { + int *accum = this->accum[i]; + int pixels = data->get_w() * data->get_h(); + float white_fraction = 1.0 - (1.0 - config.threshold) / 2; + int threshold = (int)(white_fraction * pixels); + int total = 0; + float max_level = 1.0; + float min_level = 0.0; + +// Get histogram slot above threshold of pixels + for(int j = 0; j < HISTOGRAM_SLOTS; j++) { + total += accum[j]; + if(total >= threshold) { + max_level = (float)j / HISTOGRAM_SLOTS * FLOAT_RANGE + HIST_MIN_INPUT; + break; + } + } + +// Get slot below 99% of pixels + total = 0; + for(int j = HISTOGRAM_SLOTS - 1; j >= 0; j--) { + total += accum[j]; + if(total >= threshold) { + min_level = (float)j / HISTOGRAM_SLOTS * FLOAT_RANGE + HIST_MIN_INPUT; + break; + } + } + config.points[i].insert(max_level, 1.0); + config.points[i].insert(min_level, 0.0); + } +} + +int HistogramMain::process_realtime(VFrame *input_ptr, VFrame *output_ptr) +{ +SET_TRACE + int need_reconfigure = load_configuration(); +SET_TRACE + + if(!engine) engine = new HistogramEngine(this, + get_project_smp() + 1, + get_project_smp() + 1); + this->input = input_ptr; + this->output = output_ptr; + + send_render_gui(input_ptr); + + if(input_ptr->get_rows()[0] != output_ptr->get_rows()[0]) + { + output_ptr->copy_from(input_ptr); + } + +SET_TRACE +// Generate tables here. The same table is used by many packages to render +// each horizontal stripe. Need to cover the entire output range in each +// table to avoid green borders + if( !lookup[0] || !smoothed[0] || !linear[0] || config.automatic) + need_reconfigure = 1; + if( need_reconfigure ) { +SET_TRACE +// Calculate new curves + if(config.automatic) { + calculate_automatic(input); + } +SET_TRACE + +// Generate transfer tables for integer colormodels. + for(int i = 0; i < 3; i++) + tabulate_curve(i, 1); +SET_TRACE + } + +// Apply histogram + engine->process_packages(HistogramEngine::APPLY, input); + +SET_TRACE + return 0; +} + +void HistogramMain::tabulate_curve(int subscript, int use_value) +{ + int i; + if(!lookup[subscript]) + lookup[subscript] = new int[HISTOGRAM_SLOTS]; + if(!smoothed[subscript]) + smoothed[subscript] = new float[HISTOGRAM_SLOTS]; + if(!linear[subscript]) + linear[subscript] = new float[HISTOGRAM_SLOTS]; + + float *current_smooth = smoothed[subscript]; + float *current_linear = linear[subscript]; + +// Make linear curve + for(i = 0; i < HISTOGRAM_SLOTS; i++) { + float input = (float)i / HISTOGRAM_SLOTS * FLOAT_RANGE + HIST_MIN_INPUT; + current_linear[i] = calculate_linear(input, subscript, use_value); + } +// Make smooth curve + //float prev = 0.0; + for(i = 0; i < HISTOGRAM_SLOTS; i++) + { +// current_smooth[i] = current_linear[i] * 0.001 + +// prev * 0.999; + current_smooth[i] = current_linear[i]; +// prev = current_smooth[i]; + } +// Generate lookup tables for integer colormodels + if(input) + { + switch(input->get_color_model()) + { + case BC_RGB888: + case BC_RGBA8888: + for(i = 0; i < 0x100; i++) + lookup[subscript][i] = + (int)(calculate_smooth((float)i / 0xff, subscript) * 0xff); + break; +// All other integer colormodels are converted to 16 bit RGB + default: + for(i = 0; i < 0x10000; i++) + lookup[subscript][i] = + (int)(calculate_smooth((float)i / 0xffff, subscript) * 0xffff); + break; + } + } +} + +HistogramPackage::HistogramPackage() + : LoadPackage() +{ +} + +HistogramUnit::HistogramUnit(HistogramEngine *server, + HistogramMain *plugin) + : LoadClient(server) +{ + this->plugin = plugin; + this->server = server; + for(int i = 0; i < HISTOGRAM_MODES; i++) + accum[i] = new int[HISTOGRAM_SLOTS]; +} + +HistogramUnit::~HistogramUnit() +{ + for(int i = 0; i < HISTOGRAM_MODES; i++) + delete [] accum[i]; +} + +void HistogramUnit::process_package(LoadPackage *package) +{ + HistogramPackage *pkg = (HistogramPackage*)package; + + if(server->operation == HistogramEngine::HISTOGRAM) + { + +#define HISTOGRAM_HEAD(type) \ +{ \ + for(int i = pkg->start; i < pkg->end; i++) \ + { \ + type *row = (type*)data->get_rows()[i]; \ + for(int j = 0; j < w; j++) \ + { + +#define HISTOGRAM_TAIL(components) \ +/* v = (r * 76 + g * 150 + b * 29) >> 8; */ \ + v = MAX(r, g); \ + v = MAX(v, b); \ + r += -HISTOGRAM_MIN * 0xffff / 100; \ + g += -HISTOGRAM_MIN * 0xffff / 100; \ + b += -HISTOGRAM_MIN * 0xffff / 100; \ + v += -HISTOGRAM_MIN * 0xffff / 100; \ + CLAMP(r, 0, HISTOGRAM_SLOTS-1); \ + CLAMP(g, 0, HISTOGRAM_SLOTS-1); \ + CLAMP(b, 0, HISTOGRAM_SLOTS-1); \ + CLAMP(v, 0, HISTOGRAM_SLOTS-1); \ + accum_r[r]++; \ + accum_g[g]++; \ + accum_b[b]++; \ + accum_v[v]++; \ + row += components; \ + } \ + } \ +} + + VFrame *data = server->data; + int w = data->get_w(); +// int h = data->get_h(); + int *accum_r = accum[HISTOGRAM_RED]; + int *accum_g = accum[HISTOGRAM_GREEN]; + int *accum_b = accum[HISTOGRAM_BLUE]; + int *accum_v = accum[HISTOGRAM_VALUE]; + int r, g, b, y, u, v; + + switch(data->get_color_model()) + { + case BC_RGB888: + HISTOGRAM_HEAD(unsigned char) + r = (row[0] << 8) | row[0]; + g = (row[1] << 8) | row[1]; + b = (row[2] << 8) | row[2]; + HISTOGRAM_TAIL(3) + break; + case BC_RGB_FLOAT: + HISTOGRAM_HEAD(float) + r = (int)(row[0] * 0xffff); + g = (int)(row[1] * 0xffff); + b = (int)(row[2] * 0xffff); + HISTOGRAM_TAIL(3) + break; + case BC_YUV888: + HISTOGRAM_HEAD(unsigned char) + y = (row[0] << 8) | row[0]; + u = (row[1] << 8) | row[1]; + v = (row[2] << 8) | row[2]; + plugin->yuv.yuv_to_rgb_16(r, g, b, y, u, v); + HISTOGRAM_TAIL(3) + break; + case BC_RGBA8888: + HISTOGRAM_HEAD(unsigned char) + r = (row[0] << 8) | row[0]; + g = (row[1] << 8) | row[1]; + b = (row[2] << 8) | row[2]; + HISTOGRAM_TAIL(4) + break; + case BC_RGBA_FLOAT: + HISTOGRAM_HEAD(float) + r = (int)(row[0] * 0xffff); + g = (int)(row[1] * 0xffff); + b = (int)(row[2] * 0xffff); + HISTOGRAM_TAIL(4) + break; + case BC_YUVA8888: + HISTOGRAM_HEAD(unsigned char) + y = (row[0] << 8) | row[0]; + u = (row[1] << 8) | row[1]; + v = (row[2] << 8) | row[2]; + plugin->yuv.yuv_to_rgb_16(r, g, b, y, u, v); + HISTOGRAM_TAIL(4) + break; + case BC_RGB161616: + HISTOGRAM_HEAD(uint16_t) + r = row[0]; + g = row[1]; + b = row[2]; + HISTOGRAM_TAIL(3) + break; + case BC_YUV161616: + HISTOGRAM_HEAD(uint16_t) + y = row[0]; + u = row[1]; + v = row[2]; + plugin->yuv.yuv_to_rgb_16(r, g, b, y, u, v); + HISTOGRAM_TAIL(3) + break; + case BC_RGBA16161616: + HISTOGRAM_HEAD(uint16_t) + r = row[0]; + g = row[1]; + b = row[2]; + HISTOGRAM_TAIL(3) + break; + case BC_YUVA16161616: + HISTOGRAM_HEAD(uint16_t) + y = row[0]; + u = row[1]; + v = row[2]; + plugin->yuv.yuv_to_rgb_16(r, g, b, y, u, v); + HISTOGRAM_TAIL(4) + break; + } + } + else + if(server->operation == HistogramEngine::APPLY) + { + + + +#define PROCESS(type, components) \ +{ \ + for(int i = pkg->start; i < pkg->end; i++) \ + { \ + type *row = (type*)input->get_rows()[i]; \ + for(int j = 0; j < w; j++) \ + { \ + if ( plugin->config.split && ((j + i * w / h) < w) ) \ + continue; \ + row[0] = lookup_r[row[0]]; \ + row[1] = lookup_g[row[1]]; \ + row[2] = lookup_b[row[2]]; \ + row += components; \ + } \ + } \ +} + +#define PROCESS_YUV(type, components, max) \ +{ \ + for(int i = pkg->start; i < pkg->end; i++) \ + { \ + type *row = (type*)input->get_rows()[i]; \ + for(int j = 0; j < w; j++) \ + { \ + if ( plugin->config.split && ((j + i * w / h) < w) ) \ + continue; \ +/* Convert to 16 bit RGB */ \ + if(max == 0xff) \ + { \ + y = (row[0] << 8) | row[0]; \ + u = (row[1] << 8) | row[1]; \ + v = (row[2] << 8) | row[2]; \ + } \ + else \ + { \ + y = row[0]; \ + u = row[1]; \ + v = row[2]; \ + } \ + \ + plugin->yuv.yuv_to_rgb_16(r, g, b, y, u, v); \ + \ +/* Look up in RGB domain */ \ + r = lookup_r[r]; \ + g = lookup_g[g]; \ + b = lookup_b[b]; \ + \ +/* Convert to 16 bit YUV */ \ + plugin->yuv.rgb_to_yuv_16(r, g, b, y, u, v); \ + \ + if(max == 0xff) \ + { \ + row[0] = y >> 8; \ + row[1] = u >> 8; \ + row[2] = v >> 8; \ + } \ + else \ + { \ + row[0] = y; \ + row[1] = u; \ + row[2] = v; \ + } \ + row += components; \ + } \ + } \ +} + +#define PROCESS_FLOAT(components) \ +{ \ + for(int i = pkg->start; i < pkg->end; i++) \ + { \ + float *row = (float*)input->get_rows()[i]; \ + for(int j = 0; j < w; j++) \ + { \ + if ( plugin->config.split && ((j + i * w / h) < w) ) \ + continue; \ + float r = row[0]; \ + float g = row[1]; \ + float b = row[2]; \ + \ + r = plugin->calculate_smooth(r, HISTOGRAM_RED); \ + g = plugin->calculate_smooth(g, HISTOGRAM_GREEN); \ + b = plugin->calculate_smooth(b, HISTOGRAM_BLUE); \ + \ + row[0] = r; \ + row[1] = g; \ + row[2] = b; \ + \ + row += components; \ + } \ + } \ +} + + + VFrame *input = plugin->input; +// VFrame *output = plugin->output; + int w = input->get_w(), h = input->get_h(); + int *lookup_r = plugin->lookup[0]; + int *lookup_g = plugin->lookup[1]; + int *lookup_b = plugin->lookup[2]; + int r, g, b, y, u, v; + switch(input->get_color_model()) + { + case BC_RGB888: + PROCESS(unsigned char, 3) + break; + case BC_RGB_FLOAT: + PROCESS_FLOAT(3); + break; + case BC_RGBA8888: + PROCESS(unsigned char, 4) + break; + case BC_RGBA_FLOAT: + PROCESS_FLOAT(4); + break; + case BC_RGB161616: + PROCESS(uint16_t, 3) + break; + case BC_RGBA16161616: + PROCESS(uint16_t, 4) + break; + case BC_YUV888: + PROCESS_YUV(unsigned char, 3, 0xff) + break; + case BC_YUVA8888: + PROCESS_YUV(unsigned char, 4, 0xff) + break; + case BC_YUV161616: + PROCESS_YUV(uint16_t, 3, 0xffff) + break; + case BC_YUVA16161616: + PROCESS_YUV(uint16_t, 4, 0xffff) + break; + } + } +} + + + + + + +HistogramEngine::HistogramEngine(HistogramMain *plugin, + int total_clients, + int total_packages) + : LoadServer(total_clients, total_packages) +{ + this->plugin = plugin; +} + +void HistogramEngine::init_packages() +{ + switch(operation) { + case HISTOGRAM: + total_size = data->get_h(); + break; + case APPLY: + total_size = data->get_h(); + break; + } + + for(int i = 0; i < get_total_packages(); i++) { + HistogramPackage *package = (HistogramPackage*)get_package(i); + package->start = total_size * i / get_total_packages(); + package->end = total_size * (i + 1) / get_total_packages(); + } + +// Initialize clients here in case some don't get run. + for(int i = 0; i < get_total_clients(); i++) { + HistogramUnit *unit = (HistogramUnit*)get_client(i); + for(int i = 0; i < HISTOGRAM_MODES; i++) + bzero(unit->accum[i], sizeof(int) * HISTOGRAM_SLOTS); + } + +} + +LoadClient* HistogramEngine::new_client() +{ + return new HistogramUnit(this, plugin); +} + +LoadPackage* HistogramEngine::new_package() +{ + return new HistogramPackage; +} + +void HistogramEngine::process_packages(int operation, VFrame *data) +{ + this->data = data; + this->operation = operation; + LoadServer::process_packages(); +} + + + diff --git a/cinelerra-5.0/plugins/histogram_bezier/bistogram.h b/cinelerra-5.0/plugins/histogram_bezier/bistogram.h new file mode 100644 index 00000000..659b71dc --- /dev/null +++ b/cinelerra-5.0/plugins/histogram_bezier/bistogram.h @@ -0,0 +1,138 @@ + +/* + * CINELERRA + * Copyright (C) 2008 Adam Williams + * + * 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 + * + */ + +#ifndef HISTOGRAM_H +#define HISTOGRAM_H + + +#include "bistogram.inc" +#include "bistogramconfig.h" +#include "bistogramwindow.inc" +#include "loadbalance.h" +#include "cicolors.h" +#include "pluginvclient.h" + + +enum +{ + HISTOGRAM_LINEAR, + HISTOGRAM_POLYNOMINAL, + HISTOGRAM_BEZIER, +}; + + +class HistogramMain : public PluginVClient +{ +public: + HistogramMain(PluginServer *server); + ~HistogramMain(); + + int process_realtime(VFrame *input_ptr, VFrame *output_ptr); + int is_realtime(); + void save_data(KeyFrame *keyframe); + void read_data(KeyFrame *keyframe); + void update_gui(); + void render_gui(void *data); + + PLUGIN_CLASS_MEMBERS(HistogramConfig) + +// Convert input to linear output + float calculate_linear(float input, int mode, int do_value); + float calculate_smooth(float input, int subscript); +// Convert input to smoothed output by looking up in smooth table. + float calculate_curve(float input); +// Calculate automatic settings + void calculate_automatic(VFrame *data); +// Calculate histogram + void calculate_histogram(VFrame *data); +// Calculate the linear, smoothed, lookup curves + void tabulate_curve(int subscript, int use_value); + + + + YUV yuv; + VFrame *input, *output; + HistogramEngine *engine; + int *lookup[HISTOGRAM_MODES]; + float *smoothed[HISTOGRAM_MODES]; + float *linear[HISTOGRAM_MODES]; + int *accum[HISTOGRAM_MODES]; +// Input point being dragged or edited + int current_point; +// Current channel being viewed + int mode; + int dragging_point; + int point_x_offset; + int point_y_offset; +}; + +class HistogramPackage : public LoadPackage +{ +public: + HistogramPackage(); + int start, end; +}; + +class HistogramUnit : public LoadClient +{ +public: + HistogramUnit(HistogramEngine *server, HistogramMain *plugin); + ~HistogramUnit(); + void process_package(LoadPackage *package); + HistogramEngine *server; + HistogramMain *plugin; + int *accum[5]; +}; + +class HistogramEngine : public LoadServer +{ +public: + HistogramEngine(HistogramMain *plugin, + int total_clients, + int total_packages); + void process_packages(int operation, VFrame *data); + void init_packages(); + LoadClient* new_client(); + LoadPackage* new_package(); + HistogramMain *plugin; + int total_size; + + + int operation; + enum + { + HISTOGRAM, + APPLY + }; + VFrame *data; +}; + + + + + + + + + + + +#endif diff --git a/cinelerra-5.0/plugins/histogram_bezier/bistogram.inc b/cinelerra-5.0/plugins/histogram_bezier/bistogram.inc new file mode 100644 index 00000000..bfbd7e3d --- /dev/null +++ b/cinelerra-5.0/plugins/histogram_bezier/bistogram.inc @@ -0,0 +1,58 @@ + +/* + * CINELERRA + * Copyright (C) 2008 Adam Williams + * + * 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 + * + */ + +#ifndef HISTOGRAM_INC +#define HISTOGRAM_INC + + + + + +// modes +#define HISTOGRAM_MODES 4 +#define HISTOGRAM_RED 0 +#define HISTOGRAM_GREEN 1 +#define HISTOGRAM_BLUE 2 +#define HISTOGRAM_VALUE 3 + +// Number of divisions in histogram. +// 65536 + min and max range to speed up the tabulation +#define HISTOGRAM_SLOTS 0x13333 +#define FLOAT_RANGE 1.2 +// Minimum value in percentage +#define HISTOGRAM_MIN -10 +#define HIST_MIN_INPUT -0.1 +// Maximum value in percentage +#define HISTOGRAM_MAX 110 +#define HIST_MAX_INPUT 1.1 + +#define PRECISION 0.001 +#define DIGITS 3 +#define THRESHOLD_SCALE 1000 + +#define BOX_SIZE 10 + + +class HistogramEngine; +class HistogramMain; + + +#endif diff --git a/cinelerra-5.0/plugins/histogram_bezier/bistogramconfig.C b/cinelerra-5.0/plugins/histogram_bezier/bistogramconfig.C new file mode 100644 index 00000000..d84550f8 --- /dev/null +++ b/cinelerra-5.0/plugins/histogram_bezier/bistogramconfig.C @@ -0,0 +1,296 @@ + +/* + * CINELERRA + * Copyright (C) 2008 Adam Williams + * + * 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 "clip.h" +#include "bistogramconfig.h" +#include "units.h" + +#include + + + + +HistogramPoint::HistogramPoint() + : ListItem() +{ +} + +HistogramPoint::~HistogramPoint() +{ +} + +int HistogramPoint::equivalent(HistogramPoint *src) +{ + return EQUIV(x, src->x) && EQUIV(y, src->y) && EQUIV(gradient, src->gradient); +} + + + + +HistogramPoints::HistogramPoints() + : List() +{ + insert(0.0,0.0); + first->gradient = 1.0; + first->xoffset_left = 0.0; + first->xoffset_right = 0.05; + insert(1.0,1.0); + last->gradient = 1.0; + last->xoffset_left = -0.05; + last->xoffset_right = 0.0; + +} + +HistogramPoints::~HistogramPoints() +{ +} + +HistogramPoint* HistogramPoints::insert(float x, float y) +{ + HistogramPoint *current = first; + +// Get existing point after new point + while(current) + { + if(current->x > x) + break; + else + current = NEXT; + } + +// Insert new point before current point + HistogramPoint *new_point = new HistogramPoint; + if(current) + { + insert_before(current, new_point); + } + else +// Append new point to list + { + append(new_point); + } + + new_point->x = x; + new_point->y = y; + new_point->xoffset_left = -0.05; + new_point->xoffset_right = 0.05; + + + return new_point; +} + +void HistogramPoints::boundaries() +{ + HistogramPoint *current = first; + while(current) + { + CLAMP(current->x, 0.0, 1.0); + CLAMP(current->y, 0.0, 1.0); + current = NEXT; + } +} + +int HistogramPoints::equivalent(HistogramPoints *src) +{ + HistogramPoint *current_this = first; + HistogramPoint *current_src = src->first; + while(current_this && current_src) + { + if(!current_this->equivalent(current_src)) return 0; + current_this = current_this->next; + current_src = current_src->next; + } + + return !current_this ^ !current_src ? 0 : 1; +} + +void HistogramPoints::copy_from(HistogramPoints *src) +{ + while(last) + delete last; + HistogramPoint *current = src->first; + while(current) + { + HistogramPoint *new_point = new HistogramPoint; + new_point->x = current->x; + new_point->y = current->y; + append(new_point); + current = NEXT; + } +} + +void HistogramPoints::interpolate(HistogramPoints *prev, + HistogramPoints *next, + double prev_scale, + double next_scale) +{ + HistogramPoint *current = first; + HistogramPoint *current_prev = prev->first; + HistogramPoint *current_next = next->first; + + while(current && current_prev && current_next) + { + current->x = current_prev->x * prev_scale + + current_next->x * next_scale; + current->y = current_prev->y * prev_scale + + current_next->y * next_scale; + current = NEXT; + current_prev = current_prev->next; + current_next = current_next->next; + } +} + + + + + + + + + + + + + + +HistogramConfig::HistogramConfig() +{ + reset(1); +} + +void HistogramConfig::reset(int do_mode) +{ + reset_points(); + + + for(int i = 0; i < HISTOGRAM_MODES; i++) + { + output_min[i] = 0.0; + output_max[i] = 1.0; + } + + if(do_mode) + { + automatic = 0; + threshold = 0.1; + split = 0; + smoothMode = 0; + } +} + +void HistogramConfig::reset_points() +{ + for(int i = 0; i < HISTOGRAM_MODES; i++) + { + while(points[i].last) delete points[i].last; + points[i].insert(0.0,0.0); + points[i].last->gradient = 1.0; + points[i].insert(1.0,1.0); + points[i].last->gradient = 1.0; + } +} + + +void HistogramConfig::boundaries() +{ + for(int i = 0; i < HISTOGRAM_MODES; i++) + { + points[i].boundaries(); + CLAMP(output_min[i], HIST_MIN_INPUT, HIST_MAX_INPUT); + CLAMP(output_max[i], HIST_MIN_INPUT, HIST_MAX_INPUT); + output_min[i] = Units::quantize(output_min[i], PRECISION); + output_max[i] = Units::quantize(output_max[i], PRECISION); + } + CLAMP(threshold, 0, 1); +} + +int HistogramConfig::equivalent(HistogramConfig &that) +{ + for(int i = 0; i < HISTOGRAM_MODES; i++) + { + if(!points[i].equivalent(&that.points[i]) || + !EQUIV(output_min[i], that.output_min[i]) || + !EQUIV(output_max[i], that.output_max[i])) return 0; + } + + if(automatic != that.automatic || + !EQUIV(threshold, that.threshold)) return 0; + + return 1; +} + +void HistogramConfig::copy_from(HistogramConfig &that) +{ + for(int i = 0; i < HISTOGRAM_MODES; i++) + { + points[i].copy_from(&that.points[i]); + output_min[i] = that.output_min[i]; + output_max[i] = that.output_max[i]; + } + + automatic = that.automatic; + threshold = that.threshold; + split = that.split; + smoothMode = that.smoothMode; +} + +void HistogramConfig::interpolate(HistogramConfig &prev, + HistogramConfig &next, + int64_t prev_frame, + int64_t next_frame, + int64_t current_frame) +{ + double next_scale = (double)(current_frame - prev_frame) / (next_frame - prev_frame); + double prev_scale = 1.0 - next_scale; + + for(int i = 0; i < HISTOGRAM_MODES; i++) + { + points[i].interpolate(&prev.points[i], &next.points[i], next_scale, prev_scale); + output_min[i] = prev.output_min[i] * prev_scale + next.output_min[i] * next_scale; + output_max[i] = prev.output_max[i] * prev_scale + next.output_max[i] * next_scale; + } + + threshold = prev.threshold * prev_scale + next.threshold * next_scale; + automatic = prev.automatic; + split = prev.split; + smoothMode = prev.smoothMode; +} + + +void HistogramConfig::dump() +{ + for(int j = 0; j < HISTOGRAM_MODES; j++) + { + printf("HistogramConfig::dump mode=%d\n", j); + HistogramPoints *points = &this->points[j]; + HistogramPoint *current = points->first; + while(current) + { + printf("%f,%f ", current->x, current->y); + fflush(stdout); + current = NEXT; + } + printf("\n"); + } +} + + + diff --git a/cinelerra-5.0/plugins/histogram_bezier/bistogramconfig.h b/cinelerra-5.0/plugins/histogram_bezier/bistogramconfig.h new file mode 100644 index 00000000..ce4d490d --- /dev/null +++ b/cinelerra-5.0/plugins/histogram_bezier/bistogramconfig.h @@ -0,0 +1,96 @@ + +/* + * CINELERRA + * Copyright (C) 2008 Adam Williams + * + * 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 + * + */ + +#ifndef HISTOGRAMCONFIG_H +#define HISTOGRAMCONFIG_H + + +#include "bistogram.inc" +#include "bistogramconfig.inc" +#include "linklist.h" +#include + +class HistogramPoint : public ListItem +{ +public: + HistogramPoint(); + ~HistogramPoint(); + + int equivalent(HistogramPoint *src); + float x, y; + float gradient; + float xoffset_left; + float xoffset_right; +}; + + +class HistogramPoints : public List +{ +public: + HistogramPoints(); + ~HistogramPoints(); + +// Insert new point + HistogramPoint* insert(float x, float y); + int equivalent(HistogramPoints *src); + void boundaries(); + void copy_from(HistogramPoints *src); + void interpolate(HistogramPoints *prev, + HistogramPoints *next, + double prev_scale, + double next_scale); +}; + +class HistogramConfig +{ +public: + HistogramConfig(); + + int equivalent(HistogramConfig &that); + void copy_from(HistogramConfig &that); + void interpolate(HistogramConfig &prev, + HistogramConfig &next, + int64_t prev_frame, + int64_t next_frame, + int64_t current_frame); +// Used by constructor and reset button + void reset(int do_mode); + void reset_points(); + void boundaries(); + void dump(); + +// Range 0 - 1.0 +// Input points + HistogramPoints points[HISTOGRAM_MODES]; +// Output points + float output_min[HISTOGRAM_MODES]; + float output_max[HISTOGRAM_MODES]; + int automatic; + float threshold; + int split; + int smoothMode; +}; + + +#endif + + + diff --git a/cinelerra-5.0/plugins/histogram_bezier/bistogramconfig.inc b/cinelerra-5.0/plugins/histogram_bezier/bistogramconfig.inc new file mode 100644 index 00000000..de386501 --- /dev/null +++ b/cinelerra-5.0/plugins/histogram_bezier/bistogramconfig.inc @@ -0,0 +1,31 @@ + +/* + * CINELERRA + * Copyright (C) 2008 Adam Williams + * + * 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 + * + */ + +#ifndef HISTOGRAMCONFIG_INC +#define HISTOGRAMCONFIG_INC + + +class HistogramPoint; +class HistogramPoints; +class HistogramConfig; + + +#endif diff --git a/cinelerra-5.0/plugins/histogram_bezier/bistogramwindow.C b/cinelerra-5.0/plugins/histogram_bezier/bistogramwindow.C new file mode 100644 index 00000000..55046ece --- /dev/null +++ b/cinelerra-5.0/plugins/histogram_bezier/bistogramwindow.C @@ -0,0 +1,1056 @@ + +/* + * CINELERRA + * Copyright (C) 2008 Adam Williams + * + * 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 "bcsignals.h" +#include "bistogram.h" +#include "bistogramconfig.h" +#include "bistogramwindow.h" +#include "keys.h" +#include "language.h" + + +#include +#include + +HistogramWindow::HistogramWindow(HistogramMain *plugin) + : PluginClientWindow(plugin, 440, 480, 440, 480, 0) +{ + this->plugin = plugin; +} + +HistogramWindow::~HistogramWindow() +{ +} + +#include "min_picon_png.h" +#include "mid_picon_png.h" +#include "max_picon_png.h" +static VFramePng max_picon_image(max_picon_png); +static VFramePng mid_picon_image(mid_picon_png); +static VFramePng min_picon_image(min_picon_png); + +void HistogramWindow::create_objects() +{ + int x = 10, y = 10, x1 = 10; + BC_Title *title = 0; + + max_picon = create_pixmap(&max_picon_image); + mid_picon = create_pixmap(&mid_picon_image); + min_picon = create_pixmap(&min_picon_image); + add_subwindow(mode_v = new HistogramMode(plugin, + x, + y, + HISTOGRAM_VALUE, + _("Value"))); + x += 70; + add_subwindow(mode_r = new HistogramMode(plugin, + x, + y, + HISTOGRAM_RED, + _("Red"))); + x += 70; + add_subwindow(mode_g = new HistogramMode(plugin, + x, + y, + HISTOGRAM_GREEN, + _("Green"))); + x += 70; + add_subwindow(mode_b = new HistogramMode(plugin, + x, + y, + HISTOGRAM_BLUE, + _("Blue"))); +// x += 70; +// add_subwindow(mode_a = new HistogramMode(plugin, +// x, +// y, +// HISTOGRAM_ALPHA, +// _("Alpha"))); + + x = x1; + y += 30; + add_subwindow(title = new BC_Title(x, y, _("Input X:"))); + x += title->get_w() + 10; + input_x = new HistogramInputText(plugin, + this, + x, + y, + 1); + input_x->create_objects(); + + x += input_x->get_w() + 10; + add_subwindow(title = new BC_Title(x, y, _("Input Y:"))); + x += title->get_w() + 10; + input_y = new HistogramInputText(plugin, + this, + x, + y, + 0); + input_y->create_objects(); + + y += 30; + x = x1; + + canvas_w = get_w() - x - x; + canvas_h = get_h() - y - 170; + title1_x = x; + title2_x = x + (int)(canvas_w * -HIST_MIN_INPUT / FLOAT_RANGE); + title3_x = x + (int)(canvas_w * (1.0 - HIST_MIN_INPUT) / FLOAT_RANGE); + title4_x = x + (int)(canvas_w); + add_subwindow(canvas = new HistogramCanvas(plugin, + this, + x, + y, + canvas_w, + canvas_h)); + draw_canvas_overlay(); + canvas->flash(); + + y += canvas->get_h() + 1; + add_subwindow(new BC_Title(title1_x, + y, + "-10%")); + add_subwindow(new BC_Title(title2_x, + y, + "0%")); + add_subwindow(new BC_Title(title3_x - get_text_width(MEDIUMFONT, "100"), + y, + "100%")); + add_subwindow(new BC_Title(title4_x - get_text_width(MEDIUMFONT, "110"), + y, + "110%")); + + y += 20; + add_subwindow(title = new BC_Title(x, y, _("Output min:"))); + x += title->get_w() + 10; + output_min = new HistogramOutputText(plugin, + this, + x, + y, + &plugin->config.output_min[plugin->mode]); + output_min->create_objects(); + x += output_min->get_w() + 10; + add_subwindow(new BC_Title(x, y, _("Output Max:"))); + x += title->get_w() + 10; + output_max = new HistogramOutputText(plugin, + this, + x, + y, + &plugin->config.output_max[plugin->mode]); + output_max->create_objects(); + + x = x1; + y += 30; + + add_subwindow(output = new HistogramSlider(plugin, + this, + x, + y, + get_w() - 20, + 30, + 0)); + output->update(); + y += 40; + + + add_subwindow(automatic = new HistogramAuto(plugin, + x, + y)); + + x += 120; + add_subwindow(new HistogramReset(plugin, + x, + y)); + x += 100; + add_subwindow(new BC_Title(x, y, _("Threshold:"))); + x += 100; + threshold = new HistogramOutputText(plugin, + this, + x, + y, + &plugin->config.threshold); + threshold->create_objects(); + x = x1; + y += 40; + add_subwindow(split = new HistogramSplit(plugin, x, y)); + y += 6; + x += 150; + add_subwindow(new BC_Title(x,y, _("Interpolation:"))); + x += 120; + add_subwindow(smoothModeChoser = new HistogramSmoothMode(plugin, this, x, y)); + smoothModeChoser->create_objects(); + + show_window(); +} + +int HistogramWindow::keypress_event() +{ + int result = 0; + if(get_keypress() == BACKSPACE || + get_keypress() == DELETE) + { + if(plugin->current_point >= 0) + { + HistogramPoint *current = + plugin->config.points[plugin->mode].get_item_number(plugin->current_point); + delete current; + plugin->current_point = -1; + update_input(); + update_canvas(); + plugin->send_configure_change(); + result = 1; + } + } + return result; +} + +void HistogramWindow::update(int do_input) +{ + automatic->update(plugin->config.automatic); + threshold->update(plugin->config.threshold); + update_mode(); + + if(do_input) update_input(); + update_output(); +} + +void HistogramWindow::update_input() +{ + input_x->update(); + input_y->update(); +} + +void HistogramWindow::update_output() +{ + output->update(); + output_min->update(plugin->config.output_min[plugin->mode]); + output_max->update(plugin->config.output_max[plugin->mode]); +} + +void HistogramWindow::update_mode() +{ + mode_v->update(plugin->mode == HISTOGRAM_VALUE ? 1 : 0); + mode_r->update(plugin->mode == HISTOGRAM_RED ? 1 : 0); + mode_g->update(plugin->mode == HISTOGRAM_GREEN ? 1 : 0); + mode_b->update(plugin->mode == HISTOGRAM_BLUE ? 1 : 0); + output_min->output = &plugin->config.output_min[plugin->mode]; + output_max->output = &plugin->config.output_max[plugin->mode]; +} + +void HistogramWindow::draw_canvas_overlay() +{ + canvas->set_color(0x00ff00); + int y1; + +// Calculate output curve + plugin->tabulate_curve(plugin->mode, 0); + +// Draw output line + for(int i = 0; i < canvas_w; i++) + { + float input = (float)i / + canvas_w * + FLOAT_RANGE + + HIST_MIN_INPUT; + float output = plugin->calculate_smooth(input, plugin->mode); + + int y2 = canvas_h - (int)(output * canvas_h); + if(i > 0) + { + canvas->draw_line(i - 1, y1, i, y2); + } + y1 = y2; + } + +// Draw output points + HistogramPoint *current = plugin->config.points[plugin->mode].first; + int number = 0; + while(current) + { + int x = (int)((current->x - HIST_MIN_INPUT) * canvas_w / FLOAT_RANGE); + int y = (int)(canvas_h - current->y * canvas_h); + if(number == plugin->current_point) + canvas->draw_box(x - BOX_SIZE / 2, y - BOX_SIZE / 2, BOX_SIZE, BOX_SIZE); + else + canvas->draw_rectangle(x - BOX_SIZE / 2, y - BOX_SIZE / 2, BOX_SIZE, BOX_SIZE); + +//Draw gradients + if (plugin->config.smoothMode > HISTOGRAM_LINEAR) + { + int x1,x2,y1,y2; + canvas->set_color(0x0000ff); + x2 = (int)((current->x + current->xoffset_right - HIST_MIN_INPUT) * canvas_w / FLOAT_RANGE); + x1 = (int)((current->x + current->xoffset_left - HIST_MIN_INPUT) * canvas_w / FLOAT_RANGE); + y2 = (int)(canvas_h - (current->y + current->xoffset_right * current->gradient) * canvas_h); + y1 = (int)(canvas_h - (current->y + current->xoffset_left * current->gradient) * canvas_h); +/* x2 = x + (title3_x - title2_x)/20; + x1 = x - (title3_x - title2_x)/20; + y1 = y + (int)(current->gradient * (float)(canvas_h)/20.0); + y2 = y - (int)(current->gradient * (float)(canvas_h)/20.0); +// int y2 = (int)(canvas_h - canvas_h * (current->y + current->gradient /10));*/ + canvas->draw_line(x1,y1,x2,y2); + + canvas->draw_circle(x1 - BOX_SIZE / 4, y1 - BOX_SIZE / 4, BOX_SIZE/2, BOX_SIZE/2); + canvas->draw_circle(x2 - BOX_SIZE / 4, y2 - BOX_SIZE / 4, BOX_SIZE/2, BOX_SIZE/2); + canvas->set_color(0x00ff00); + } + + current = NEXT; + number++; + } + + +// Draw 0 and 100% lines. + canvas->set_color(0xff0000); + canvas->draw_line(title2_x - canvas->get_x(), + 0, + title2_x - canvas->get_x(), + canvas_h); + canvas->draw_line(title3_x - canvas->get_x(), + 0, + title3_x - canvas->get_x(), + canvas_h); +} + +void HistogramWindow::update_canvas() +{ + int *accum = plugin->accum[plugin->mode]; + int accum_per_canvas_i = HISTOGRAM_SLOTS / canvas_w + 1; + float accum_per_canvas_f = (float)HISTOGRAM_SLOTS / canvas_w; + int normalize = 0; + int max = 0; + + for(int i = 0; i < HISTOGRAM_SLOTS; i++) + { + if(accum && accum[i] > normalize) normalize = accum[i]; + } + + + if(normalize) + { + for(int i = 0; i < canvas_w; i++) + { + int accum_start = (int)(accum_per_canvas_f * i); + int accum_end = accum_start + accum_per_canvas_i; + max = 0; + for(int j = accum_start; j < accum_end; j++) + { + max = MAX(accum[j], max); + } + +// max = max * canvas_h / normalize; + max = (int)(log(max) / log(normalize) * canvas_h); + + canvas->set_color(0xffffff); + canvas->draw_line(i, 0, i, canvas_h - max); + canvas->set_color(0x000000); + canvas->draw_line(i, canvas_h - max, i, canvas_h); + } + } + else + { + canvas->set_color(0xffffff); + canvas->draw_box(0, 0, canvas_w, canvas_h); + } + + + draw_canvas_overlay(); + canvas->flash(); +} + + + + + + + + +HistogramCanvas::HistogramCanvas(HistogramMain *plugin, + HistogramWindow *gui, + int x, + int y, + int w, + int h) + : BC_SubWindow(x, + y, + w, + h, + 0xffffff) +{ + this->plugin = plugin; + this->gui = gui; +} + +int HistogramCanvas::button_press_event() +{ + int result = 0; + if(is_event_win() && cursor_inside()) + { + if(!plugin->dragging_point) + { + HistogramPoint *new_point = 0; + gui->deactivate(); +// Search for existing point under cursor + HistogramPoint *current = plugin->config.points[plugin->mode].first; + plugin->current_point = -1; + int dragID = 0; + while(current) + { + int x = (int)((current->x - HIST_MIN_INPUT) * gui->canvas_w / FLOAT_RANGE); + int y = (int)(gui->canvas_h - current->y * gui->canvas_h); + +/* Check for click on main point */ + if(get_cursor_x() >= x - BOX_SIZE / 2 && + get_cursor_y() >= y - BOX_SIZE / 2 && + get_cursor_x() < x + BOX_SIZE / 2 && + get_cursor_y() < y + BOX_SIZE / 2) + { + plugin->current_point = + plugin->config.points[plugin->mode].number_of(current); + plugin->point_x_offset = get_cursor_x() - x; + plugin->point_y_offset = get_cursor_y() - y; + dragID = 1; + break; + } + if (plugin->config.smoothMode == HISTOGRAM_LINEAR) + break; + + int xright = + (int)((current->x + current->xoffset_right - HIST_MIN_INPUT) * gui->canvas_w / FLOAT_RANGE); + int yright = + (int)(gui->canvas_h - (current->y + current->xoffset_right * current->gradient) * + gui->canvas_h); + +/* Check for click on right handle */ + if(get_cursor_x() >= xright - BOX_SIZE / 2 && + get_cursor_y() >= yright - BOX_SIZE / 2 && + get_cursor_x() < xright + BOX_SIZE / 2 && + get_cursor_y() < yright + BOX_SIZE / 2) + { + plugin->current_point = + plugin->config.points[plugin->mode].number_of(current); + plugin->point_x_offset = get_cursor_x() - xright; + plugin->point_y_offset = get_cursor_y() - yright; + dragID = 2; + break; + } + +/* Check for click on left handle */ + int xleft = + (int)((current->x + current->xoffset_left - HIST_MIN_INPUT) * gui->canvas_w / FLOAT_RANGE); + int yleft = + (int)(gui->canvas_h - (current->y + current->xoffset_left * current->gradient) * + gui->canvas_h); + if(get_cursor_x() >= xleft - BOX_SIZE / 2 && + get_cursor_y() >= yleft - BOX_SIZE / 2 && + get_cursor_x() < xleft + BOX_SIZE / 2 && + get_cursor_y() < yleft + BOX_SIZE / 2) + { + plugin->current_point = + plugin->config.points[plugin->mode].number_of(current); + plugin->point_x_offset = get_cursor_x() - xleft; + plugin->point_y_offset = get_cursor_y() - yleft; + dragID = 3; + break; + } + + + current = NEXT; + } + + if(plugin->current_point < 0) + { +// Create new point under cursor + float current_x = (float)get_cursor_x() * + FLOAT_RANGE / + get_w() + + HIST_MIN_INPUT; + float current_y = 1.0 - + (float)get_cursor_y() / + get_h(); + new_point = + plugin->config.points[plugin->mode].insert(current_x, current_y); + plugin->current_point = + plugin->config.points[plugin->mode].number_of(new_point); + plugin->point_x_offset = 0; + plugin->point_y_offset = 0; + +// Default gradient +// Get 2 points surrounding current position + float x1,x2,y1,y2; + + HistogramPoint *current = plugin->config.points[plugin->mode].first; + int done = 0; + while(current && !done) + { + if(current->x > current_x) + { + x2 = current->x; + y2 = current->y; + done = 1; + } + else + current = NEXT; + } + + current = plugin->config.points[plugin->mode].last; + done = 0; + while(current && !done) + { + if(current->x <= current_x) + { + x1 = current->x; + y1 = current->y; + done = 1; + } + else + current = PREVIOUS; + } + new_point->gradient = (y2 - y1) / (x2 - x1); + dragID = 1; + + } + + + plugin->dragging_point = dragID; + result = 1; + + plugin->config.boundaries(); + gui->update_input(); + gui->update_canvas(); + if(new_point) + { + plugin->send_configure_change(); + } + } + } + return result; +} + +int HistogramCanvas::cursor_motion_event() +{ + if(plugin->dragging_point) + { + HistogramPoint * current_point = plugin->config.points[plugin->mode].get_item_number(plugin->current_point); + + float current_x = + (float)(get_cursor_x() - plugin->point_x_offset) * + FLOAT_RANGE / + get_w() + + HIST_MIN_INPUT; + float current_y = 1.0 - + (float)(get_cursor_y() - plugin->point_y_offset) / + get_h(); + + switch(plugin->dragging_point) + { + case 1: /* Main point dragged */ + current_point->x = current_x; + current_point->y = current_y; + break; + case 2: /* Right control point dragged */ + if (current_x - current_point->x > 0) + { + current_point->xoffset_right = current_x - current_point->x; + current_point->gradient = (current_y - current_point->y) / (current_x - current_point->x); + } + break; + case 3: /* Left control point dragged */ + if (current_x - current_point->x < 0) + { + current_point->xoffset_left = current_x - current_point->x; + current_point->gradient = (current_point->y - current_y) / (current_point->x - current_x); + } + break; + } + + plugin->config.boundaries(); + gui->update_input(); + gui->update_canvas(); + plugin->send_configure_change(); + return 1; + } + return 0; +} + +int HistogramCanvas::button_release_event() +{ + if(plugin->dragging_point) + { +// Test for out of order points to delete. + HistogramPoint *current = + plugin->config.points[plugin->mode].get_item_number(plugin->current_point); + HistogramPoint *prev = PREVIOUS; + HistogramPoint *next = NEXT; + + if((prev && prev->x >= current->x) || + (next && next->x <= current->x)) + { + delete current; + plugin->current_point = -1; + plugin->config.boundaries(); + gui->update_input(); + gui->update_canvas(); + plugin->send_configure_change(); + } + + plugin->dragging_point = 0; + } + return 0; +} + + + + + + + +HistogramReset::HistogramReset(HistogramMain *plugin, + int x, + int y) + : BC_GenericButton(x, y, _("Reset")) +{ + this->plugin = plugin; +} +int HistogramReset::handle_event() +{ + plugin->config.reset(0); + HistogramWindow *window = (HistogramWindow *)plugin->thread->window; + window->update(1); + window->update_canvas(); + plugin->send_configure_change(); + return 1; +} + + + + + + + + + +HistogramSlider::HistogramSlider(HistogramMain *plugin, + HistogramWindow *gui, + int x, + int y, + int w, + int h, + int is_input) + : BC_SubWindow(x, y, w, h) +{ + this->plugin = plugin; + this->gui = gui; + this->is_input = is_input; + operation = NONE; +} + +int HistogramSlider::input_to_pixel(float input) +{ + return (int)((input - HIST_MIN_INPUT) / FLOAT_RANGE * get_w()); +} + +int HistogramSlider::button_press_event() +{ + if(is_event_win() && cursor_inside()) + { +// int w = get_w(); + int h = get_h(); + int half_h = get_h() / 2; + + gui->deactivate(); + + if(operation == NONE) + { + int x1 = input_to_pixel(plugin->config.output_min[plugin->mode]) - + gui->mid_picon->get_w() / 2; + int x2 = x1 + gui->mid_picon->get_w(); + if(get_cursor_x() >= x1 && get_cursor_x() < x2 && + get_cursor_y() >= half_h && get_cursor_y() < h) + { + operation = DRAG_MIN_OUTPUT; + } + } + + if(operation == NONE) + { + int x1 = input_to_pixel(plugin->config.output_max[plugin->mode]) - + gui->mid_picon->get_w() / 2; + int x2 = x1 + gui->mid_picon->get_w(); + if(get_cursor_x() >= x1 && get_cursor_x() < x2 && + get_cursor_y() >= half_h && get_cursor_y() < h) + { + operation = DRAG_MAX_OUTPUT; + } + } + return 1; + } + return 0; +} + +int HistogramSlider::button_release_event() +{ + if(operation != NONE) + { + operation = NONE; + return 1; + } + return 0; +} + +int HistogramSlider::cursor_motion_event() +{ + if(operation != NONE) + { + float value = (float)get_cursor_x() / get_w() * FLOAT_RANGE + HIST_MIN_INPUT; + CLAMP(value, HIST_MIN_INPUT, HIST_MAX_INPUT); + + switch(operation) + { + case DRAG_MIN_OUTPUT: + value = MIN(plugin->config.output_max[plugin->mode], value); + plugin->config.output_min[plugin->mode] = value; + break; + case DRAG_MAX_OUTPUT: + value = MAX(plugin->config.output_min[plugin->mode], value); + plugin->config.output_max[plugin->mode] = value; + break; + } + + plugin->config.boundaries(); + gui->update_output(); + + plugin->send_configure_change(); + return 1; + } + return 0; +} + +void HistogramSlider::update() +{ + int w = get_w(); + int h = get_h(); + int half_h = get_h() / 2; +// int quarter_h = get_h() / 4; + int mode = plugin->mode; + int r = 0xff; + int g = 0xff; + int b = 0xff; + + clear_box(0, 0, w, h); + + switch(mode) + { + case HISTOGRAM_RED: + g = b = 0x00; + break; + case HISTOGRAM_GREEN: + r = b = 0x00; + break; + case HISTOGRAM_BLUE: + r = g = 0x00; + break; + } + + for(int i = 0; i < w; i++) + { + int color = (int)(i * 0xff / w); + set_color(((r * color / 0xff) << 16) | + ((g * color / 0xff) << 8) | + (b * color / 0xff)); + + draw_line(i, 0, i, half_h); + } + + float min; + float max; + min = plugin->config.output_min[plugin->mode]; + max = plugin->config.output_max[plugin->mode]; + + draw_pixmap(gui->min_picon, + input_to_pixel(min) - gui->min_picon->get_w() / 2, + half_h + 1); + draw_pixmap(gui->max_picon, + input_to_pixel(max) - gui->max_picon->get_w() / 2, + half_h + 1); + + flash(); + flush(); +} + + + + + + + + + +HistogramAuto::HistogramAuto(HistogramMain *plugin, + int x, + int y) + : BC_CheckBox(x, y, plugin->config.automatic, _("Automatic")) +{ + this->plugin = plugin; +} + +int HistogramAuto::handle_event() +{ + plugin->config.automatic = get_value(); + plugin->send_configure_change(); + return 1; +} + + + + +HistogramSplit::HistogramSplit(HistogramMain *plugin, + int x, + int y) + : BC_CheckBox(x, y, plugin->config.split, _("Split picture")) +{ + this->plugin = plugin; +} + +int HistogramSplit::handle_event() +{ + plugin->config.split = get_value(); + plugin->send_configure_change(); + return 1; +} + + + + +HistogramMode::HistogramMode(HistogramMain *plugin, + int x, + int y, + int value, + char *text) + : BC_Radial(x, y, plugin->mode == value, text) +{ + this->plugin = plugin; + this->value = value; +} +int HistogramMode::handle_event() +{ + plugin->mode = value; + plugin->current_point= -1; + HistogramWindow *window = (HistogramWindow *)plugin->thread->window; + window->update_canvas(); + window->update_mode(); + window->update_input(); + window->update_canvas(); + window->update_output(); + window->output->update(); +// plugin->send_configure_change(); + return 1; +} + + + + + + + + + +HistogramOutputText::HistogramOutputText(HistogramMain *plugin, + HistogramWindow *gui, + int x, + int y, + float *output) + : BC_TumbleTextBox(gui, + output ? (float)*output : 0.0, + (float)HIST_MIN_INPUT, + (float)HIST_MAX_INPUT, + x, + y, + 60) +{ + this->plugin = plugin; + this->output = output; + set_precision(DIGITS); + set_increment(PRECISION); +} + + +int HistogramOutputText::handle_event() +{ + if(output) + { + *output = atof(get_text()); + } + + HistogramWindow *window = (HistogramWindow *)plugin->thread->window; + window->output->update(); + plugin->send_configure_change(); + return 1; +} + + + + + + + + +HistogramInputText::HistogramInputText(HistogramMain *plugin, + HistogramWindow *gui, + int x, + int y, + int do_x) + : BC_TumbleTextBox(gui, + 0.0, + (float)HIST_MIN_INPUT, + (float)HIST_MAX_INPUT, + x, + y, + 60) +{ + this->do_x = do_x; + this->plugin = plugin; + this->gui = gui; + set_precision(DIGITS); + set_increment(PRECISION); +} + + +int HistogramInputText::handle_event() +{ + if(plugin->current_point >= 0 && + plugin->current_point < plugin->config.points[plugin->mode].total()) + { + HistogramPoint *point = + plugin->config.points[plugin->mode].get_item_number( + plugin->current_point); + + if(point) + { + if(do_x) + point->x = atof(get_text()); + else + point->y = atof(get_text()); + + plugin->config.boundaries(); + gui->update_canvas(); + + HistogramWindow *window = (HistogramWindow *)plugin->thread->window; + window->output->update(); + plugin->send_configure_change(); + } + } + return 1; +} + +void HistogramInputText::update() +{ + if(plugin->current_point >= 0 && + plugin->current_point < plugin->config.points[plugin->mode].total()) + { + HistogramPoint *point = + + plugin->config.points[plugin->mode].get_item_number( + plugin->current_point); + + if(point) + { + if(do_x) + BC_TumbleTextBox::update(point->x); + else + BC_TumbleTextBox::update(point->y); + } + else + { + BC_TumbleTextBox::update((float)0.0); + } + } + else + { + BC_TumbleTextBox::update((float)0.0); + } + +} + + +HistogramSmoothMode::HistogramSmoothMode(HistogramMain*plugin, + HistogramWindow *gui, + int x, + int y) + : BC_PopupMenu(x, y, 120, to_text(plugin->config.smoothMode), 1) +{ + this->plugin = plugin; + this->gui = gui; +} +void HistogramSmoothMode::create_objects() +{ + add_item(new BC_MenuItem(to_text(HISTOGRAM_LINEAR))); + add_item(new BC_MenuItem(to_text(HISTOGRAM_POLYNOMINAL))); + add_item(new BC_MenuItem(to_text(HISTOGRAM_BEZIER))); +} + +char* HistogramSmoothMode::to_text(int mode) +{ + switch(mode) + { + case HISTOGRAM_LINEAR: + return _("Linear"); + case HISTOGRAM_POLYNOMINAL: + return _("Polynominal"); + case HISTOGRAM_BEZIER: + return _("Bezier"); + } + return _("None"); +} + +int HistogramSmoothMode::from_text(char *text) +{ + if(!strcmp(text, to_text(HISTOGRAM_LINEAR))) + return HISTOGRAM_LINEAR; + if(!strcmp(text, to_text(HISTOGRAM_POLYNOMINAL))) + return HISTOGRAM_POLYNOMINAL; + if(!strcmp(text, to_text(HISTOGRAM_BEZIER))) + return HISTOGRAM_BEZIER; + return HISTOGRAM_LINEAR; +} + +int HistogramSmoothMode::handle_event() +{ + plugin->config.smoothMode = from_text(get_text()); + gui->update_canvas(); + plugin->send_configure_change(); + return 1; +} + + + + + + + + + + + + + + diff --git a/cinelerra-5.0/plugins/histogram_bezier/bistogramwindow.h b/cinelerra-5.0/plugins/histogram_bezier/bistogramwindow.h new file mode 100644 index 00000000..dbc85658 --- /dev/null +++ b/cinelerra-5.0/plugins/histogram_bezier/bistogramwindow.h @@ -0,0 +1,204 @@ + +/* + * CINELERRA + * Copyright (C) 2008 Adam Williams + * + * 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 + * + */ + +#ifndef HISTOGRAMWINDOW_H +#define HISTOGRAMWINDOW_H + + + +#include "bistogram.inc" +#include "bistogramwindow.inc" +#include "pluginvclient.h" + + +class HistogramSmoothMode : public BC_PopupMenu +{ +public: + HistogramSmoothMode(HistogramMain *client, + HistogramWindow *window, + int x, + int y); + void create_objects(); + static char* to_text(int shape); + static int from_text(char *text); + int handle_event(); + HistogramMain *plugin; + HistogramWindow *gui; +}; + +class HistogramSlider : public BC_SubWindow +{ +public: + HistogramSlider(HistogramMain *plugin, + HistogramWindow *gui, + int x, + int y, + int w, + int h, + int is_input); + + void update(); + int button_press_event(); + int button_release_event(); + int cursor_motion_event(); + int input_to_pixel(float input); + + int operation; + enum + { + NONE, + DRAG_INPUT, + DRAG_MIN_OUTPUT, + DRAG_MAX_OUTPUT, + }; + int is_input; + HistogramMain *plugin; + HistogramWindow *gui; +}; + +class HistogramAuto : public BC_CheckBox +{ +public: + HistogramAuto(HistogramMain *plugin, + int x, + int y); + int handle_event(); + HistogramMain *plugin; +}; + +class HistogramSplit : public BC_CheckBox +{ +public: + HistogramSplit(HistogramMain *plugin, + int x, + int y); + int handle_event(); + HistogramMain *plugin; +}; + +class HistogramMode : public BC_Radial +{ +public: + HistogramMode(HistogramMain *plugin, + int x, + int y, + int value, + char *text); + int handle_event(); + HistogramMain *plugin; + int value; +}; + +class HistogramReset : public BC_GenericButton +{ +public: + HistogramReset(HistogramMain *plugin, + int x, + int y); + int handle_event(); + HistogramMain *plugin; +}; + + +class HistogramOutputText : public BC_TumbleTextBox +{ +public: + HistogramOutputText(HistogramMain *plugin, + HistogramWindow *gui, + int x, + int y, + float *output); + int handle_event(); + HistogramMain *plugin; + float *output; +}; + +class HistogramInputText : public BC_TumbleTextBox +{ +public: + HistogramInputText(HistogramMain *plugin, + HistogramWindow *gui, + int x, + int y, + int do_x); + + int handle_event(); + void update(); + + HistogramMain *plugin; + HistogramWindow *gui; + int do_x; +}; + +class HistogramCanvas : public BC_SubWindow +{ +public: + HistogramCanvas(HistogramMain *plugin, + HistogramWindow *gui, + int x, + int y, + int w, + int h); + int button_press_event(); + int cursor_motion_event(); + int button_release_event(); + HistogramMain *plugin; + HistogramWindow *gui; +}; + +class HistogramWindow : public PluginClientWindow +{ +public: + HistogramWindow(HistogramMain *plugin); + ~HistogramWindow(); + + void create_objects(); + void update(int do_input); + void update_mode(); + void update_canvas(); + void draw_canvas_overlay(); + void update_input(); + void update_output(); + int keypress_event(); + + HistogramSlider *output; + HistogramAuto *automatic; + HistogramSplit *split; + HistogramSmoothMode *smoothModeChoser; + HistogramMode *mode_v, *mode_r, *mode_g, *mode_b /*, *mode_a */; + HistogramOutputText *output_min; + HistogramOutputText *output_max; + HistogramOutputText *threshold; + HistogramInputText *input_x; + HistogramInputText *input_y; + HistogramCanvas *canvas; + HistogramMain *plugin; + int canvas_w; + int canvas_h; + int title1_x; + int title2_x; + int title3_x; + int title4_x; + BC_Pixmap *max_picon, *mid_picon, *min_picon; +}; + + +#endif diff --git a/cinelerra-5.0/plugins/histogram_bezier/bistogramwindow.inc b/cinelerra-5.0/plugins/histogram_bezier/bistogramwindow.inc new file mode 100644 index 00000000..cc9e1137 --- /dev/null +++ b/cinelerra-5.0/plugins/histogram_bezier/bistogramwindow.inc @@ -0,0 +1,28 @@ + +/* + * CINELERRA + * Copyright (C) 2008 Adam Williams + * + * 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 + * + */ + +#ifndef HISTOGRAMWINDOW_INC +#define HISTOGRAMWINDOW_INC + +class HistogramWindow; +class HistogramThread; + +#endif diff --git a/cinelerra-5.0/plugins/histogram_bezier/histogram.C b/cinelerra-5.0/plugins/histogram_bezier/histogram.C deleted file mode 100644 index 72af090b..00000000 --- a/cinelerra-5.0/plugins/histogram_bezier/histogram.C +++ /dev/null @@ -1,1124 +0,0 @@ - -/* - * CINELERRA - * Copyright (C) 2008 Adam Williams - * - * 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 -#include -#include -#include - -#include "bcdisplayinfo.h" -#include "bcsignals.h" -#include "clip.h" -#include "bchash.h" -#include "filexml.h" -#include "histogram.h" -#include "histogramconfig.h" -#include "histogramwindow.h" -#include "keyframe.h" -#include "language.h" -#include "loadbalance.h" -#include "cicolors.h" -#include "vframe.h" - - - -class HistogramMain; -class HistogramEngine; -class HistogramWindow; - - - - - -REGISTER_PLUGIN(HistogramMain) - - - - - - - - - - - - - - - -HistogramMain::HistogramMain(PluginServer *server) - : PluginVClient(server) -{ - - engine = 0; - for(int i = 0; i < HISTOGRAM_MODES; i++) - { - lookup[i] = 0; - smoothed[i] = 0; - linear[i] = 0; - accum[i] = 0; - } - current_point = -1; - mode = HISTOGRAM_VALUE; - dragging_point = 0; - input = 0; - output = 0; -} - -HistogramMain::~HistogramMain() -{ - - for(int i = 0; i < HISTOGRAM_MODES;i++) - { - delete [] lookup[i]; - delete [] smoothed[i]; - delete [] linear[i]; - delete [] accum[i]; - } - delete engine; -} - -char* HistogramMain::plugin_title() { return _("Histogram"); } -int HistogramMain::is_realtime() { return 1; } - - - -SHOW_GUI_MACRO(HistogramMain, HistogramThread) - -SET_STRING_MACRO(HistogramMain) - -RAISE_WINDOW_MACRO(HistogramMain) - -LOAD_CONFIGURATION_MACRO(HistogramMain, HistogramConfig) - -void HistogramMain::render_gui(void *data) -{ - if(thread) - { - calculate_histogram((VFrame*)data); - - if(config.automatic) - { - calculate_automatic((VFrame*)data); - } - - thread->window->lock_window("HistogramMain::render_gui"); - thread->window->update_canvas(); - if(config.automatic) - { - thread->window->update_input(); - } - thread->window->unlock_window(); - } -} - -void HistogramMain::update_gui() -{ - if(thread) - { - thread->window->lock_window("HistogramMain::update_gui"); - int reconfigure = load_configuration(); - if(reconfigure) - { - thread->window->update(0); - if(!config.automatic) - { - thread->window->update_input(); - } - } - thread->window->unlock_window(); - } -} - - -int HistogramMain::load_defaults() -{ - char directory[BCTEXTLEN], string[BCTEXTLEN]; -// set the default directory - sprintf(directory, "%shistogram.rc", BCASTDIR); - -// load the defaults - defaults = new BC_Hash(directory); - defaults->load(); - - for(int j = 0; j < HISTOGRAM_MODES; j++) - { - while(config.points[j].last) delete config.points[j].last; - - sprintf(string, "TOTAL_POINTS_%d", j); - int total_points = defaults->get(string, 0); - - for(int i = 0; i < total_points; i++) - { - HistogramPoint *point = new HistogramPoint; - sprintf(string, "INPUT_X_%d_%d", j, i); - point->x = defaults->get(string, point->x); - sprintf(string, "INPUT_Y_%d_%d", j, i); - point->y = defaults->get(string, point->y); - sprintf(string, "GRADIENT_%d_%d", j, i); - point->gradient = defaults->get(string, point->gradient); - sprintf(string, "XOFFSET_LEFT_%d_%d", j, i); - point->xoffset_left = defaults->get(string, point->xoffset_left); - sprintf(string, "XOFFSET_RIGHT_%d_%d", j, i); - point->xoffset_right = defaults->get(string, point->xoffset_right); - config.points[j].append(point); - } - } - - - for(int i = 0; i < HISTOGRAM_MODES; i++) - { - sprintf(string, "OUTPUT_MIN_%d", i); - config.output_min[i] = defaults->get(string, config.output_min[i]); - sprintf(string, "OUTPUT_MAX_%d", i); - config.output_max[i] = defaults->get(string, config.output_max[i]); - } - - config.automatic = defaults->get("AUTOMATIC", config.automatic); - mode = defaults->get("MODE", mode); - CLAMP(mode, 0, HISTOGRAM_MODES - 1); - config.threshold = defaults->get("THRESHOLD", config.threshold); - config.split = defaults->get("SPLIT", config.split); - config.smoothMode = defaults->get("INTERPOLATION", config.smoothMode); - config.boundaries(); - return 0; -} - - -int HistogramMain::save_defaults() -{ - char string[BCTEXTLEN]; - - - - for(int j = 0; j < HISTOGRAM_MODES; j++) - { - int total_points = config.points[j].total(); - sprintf(string, "TOTAL_POINTS_%d", j); - defaults->update(string, total_points); - HistogramPoint *current = config.points[j].first; - int number = 0; - while(current) - { - sprintf(string, "INPUT_X_%d_%d", j, number); - defaults->update(string, current->x); - sprintf(string, "INPUT_Y_%d_%d", j, number); - defaults->update(string, current->y); - sprintf(string, "GRADIENT_%d_%d", j, number); - defaults->update(string, current->gradient); - sprintf(string, "XOFFSET_LEFT_%d_%d", j, number); - defaults->update(string, current->xoffset_left); - sprintf(string, "XOFFSET_RIGHT_%d_%d", j, number); - defaults->update(string, current->xoffset_right); - current = NEXT; - number++; - } - } - - - for(int i = 0; i < HISTOGRAM_MODES; i++) - { - sprintf(string, "OUTPUT_MIN_%d", i); - defaults->update(string, config.output_min[i]); - sprintf(string, "OUTPUT_MAX_%d", i); - defaults->update(string, config.output_max[i]); - } - - defaults->update("AUTOMATIC", config.automatic); - defaults->update("MODE", mode); - defaults->update("THRESHOLD", config.threshold); - defaults->update("SPLIT", config.split); - defaults->update("INTERPOLATION", config.smoothMode); - defaults->save(); - return 0; -} - - - -void HistogramMain::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("HISTOGRAM"); - - char string[BCTEXTLEN]; - - - for(int i = 0; i < HISTOGRAM_MODES; i++) - { - sprintf(string, "OUTPUT_MIN_%d", i); - output.tag.set_property(string, config.output_min[i]); - sprintf(string, "OUTPUT_MAX_%d", i); - output.tag.set_property(string, config.output_max[i]); -//printf("HistogramMain::save_data %d %f %d\n", config.input_min[i], config.input_mid[i], config.input_max[i]); - } - - output.tag.set_property("AUTOMATIC", config.automatic); - output.tag.set_property("THRESHOLD", config.threshold); - output.tag.set_property("SPLIT", config.split); - output.tag.set_property("INTERPOLATION", config.smoothMode); - output.append_tag(); - output.append_newline(); - - - - - - for(int j = 0; j < HISTOGRAM_MODES; j++) - { - output.tag.set_title("POINTS"); - output.append_tag(); - output.append_newline(); - - - HistogramPoint *current = config.points[j].first; - while(current) - { - output.tag.set_title("POINT"); - output.tag.set_property("X", current->x); - output.tag.set_property("Y", current->y); - output.tag.set_property("GRADIENT", current->gradient); - output.tag.set_property("XOFFSET_LEFT", current->xoffset_left); - output.tag.set_property("XOFFSET_RIGHT", current->xoffset_right); - output.append_tag(); - output.append_newline(); - current = NEXT; - } - - - output.tag.set_title("/POINTS"); - output.append_tag(); - output.append_newline(); - } - - - - - - - output.terminate_string(); -} - -void HistogramMain::read_data(KeyFrame *keyframe) -{ - FileXML input; - - input.set_shared_input(keyframe->get_data(), strlen(keyframe->get_data())); - - int result = 0; - int current_input_mode = 0; - - - while(!result) - { - result = input.read_tag(); - - if(!result) - { - if(input.tag.title_is("HISTOGRAM")) - { - char string[BCTEXTLEN]; - for(int i = 0; i < HISTOGRAM_MODES; i++) - { - sprintf(string, "OUTPUT_MIN_%d", i); - config.output_min[i] = input.tag.get_property(string, config.output_min[i]); - sprintf(string, "OUTPUT_MAX_%d", i); - config.output_max[i] = input.tag.get_property(string, config.output_max[i]); -//printf("HistogramMain::read_data %d %f %d\n", config.input_min[i], config.input_mid[i], config.input_max[i]); - } - config.automatic = input.tag.get_property("AUTOMATIC", config.automatic); - config.threshold = input.tag.get_property("THRESHOLD", config.threshold); - config.split = input.tag.get_property("SPLIT", config.split); - config.smoothMode = input.tag.get_property("INTERPOLATION", config.smoothMode); - } - else - if(input.tag.title_is("POINTS")) - { - if(current_input_mode < HISTOGRAM_MODES) - { - HistogramPoints *points = &config.points[current_input_mode]; - while(points->last) - delete points->last; - while(!result) - { - result = input.read_tag(); - if(!result) - { - if(input.tag.title_is("/POINTS")) - { - break; - } - else - if(input.tag.title_is("POINT")) - { - points->insert( - input.tag.get_property("X", 0.0), - input.tag.get_property("Y", 0.0)); - points->last->gradient = - input.tag.get_property("GRADIENT", 1.0); - points->last->xoffset_left = - input.tag.get_property("XOFFSET_LEFT", -0.02); - points->last->xoffset_right = - input.tag.get_property("XOFFSET_RIGHT", 0.02); - } - } - } - - } - current_input_mode++; - } - } - } - - config.boundaries(); - -} - -float HistogramMain::calculate_linear(float input, - int subscript, - int use_value) -{ - int done = 0; - float output; - - if(input < 0) - { - output = 0; - done = 1; - } - - if(input > 1) - { - output = 1; - done = 1; - } - - if(!done) - { - - float x1 = 0; - float y1 = 0; - float grad1 = 1.0; - float x1right = 0; - float x2 = 1; - float y2 = 1; - float grad2 = 1.0; - float x2left = 0; - - - -// Get 2 points surrounding current position - HistogramPoints *points = &config.points[subscript]; - HistogramPoint *current = points->first; - int done = 0; - while(current && !done) - { - if(current->x > input) - { - x2 = current->x; - y2 = current->y; - grad2 = current->gradient; - x2left = current->xoffset_left; - done = 1; - } - else - current = NEXT; - } - - current = points->last; - done = 0; - while(current && !done) - { - if(current->x <= input) - { - x1 = current->x; - y1 = current->y; - grad1 = current->gradient; - done = 1; - x1right = current->xoffset_right; - } - else - current = PREVIOUS; - } - - - - - if(!EQUIV(x2 - x1, 0)) - { - if (config.smoothMode == HISTOGRAM_LINEAR) - output = (input - x1) * (y2 - y1) / (x2 - x1) + y1; - else if (config.smoothMode == HISTOGRAM_POLYNOMINAL) - { - /* Construct third grade polynom between every two points */ - float dx = x2 - x1; - float dy = y2 - y1; - float delx = input - x1; - output = 1 / (dx * dx * dx) * (grad2 * dx + grad1 * dx - 2*dy) * delx * delx * delx + 1 / (dx * dx) * (3*dy - 2* grad1*dx - grad2*dx) * delx * delx + grad1*delx + y1; - } - else if (config.smoothMode == HISTOGRAM_BEZIER) - { - /* Using standart DeCasteljau algorithm */ - float y1right = y1 + grad1 * x1right; - float y2left = y2 + grad2 * x2left; - - float t = (input - x1) / (x2 - x1); - - float pointAy = y1 + (y1right - y1) * t; - float pointBy = y1right + (y2left - y1right) * t; - float pointCy = y2left + (y2 - y2left) * t; - float pointABy = pointAy + (pointBy - pointAy) * t; - float pointBCy = pointBy + (pointCy - pointBy) * t; - output = pointABy + (pointBCy - pointABy) * t; - - } - } - - else -// Linear - output = input * y2; - - - -// - - - } - -// Apply value curve - if(use_value) - { - output = calculate_linear(output, HISTOGRAM_VALUE, 0); - } - - - float output_min = config.output_min[subscript]; - float output_max = config.output_max[subscript]; - float output_left; - float output_right; - float output_linear; - -// Compress output for value followed by channel - output = output_min + - output * - (output_max - output_min); - - - return output; -} - -float HistogramMain::calculate_smooth(float input, int subscript) -{ - float x_f = (input - HIST_MIN_INPUT) * HISTOGRAM_SLOTS / FLOAT_RANGE; - int x_i1 = (int)x_f; - int x_i2 = x_i1 + 1; - CLAMP(x_i1, 0, HISTOGRAM_SLOTS - 1); - CLAMP(x_i2, 0, HISTOGRAM_SLOTS - 1); - CLAMP(x_f, 0, HISTOGRAM_SLOTS - 1); - - float smooth1 = smoothed[subscript][x_i1]; - float smooth2 = smoothed[subscript][x_i2]; - float result = smooth1 + (smooth2 - smooth1) * (x_f - x_i1); - CLAMP(result, 0, 1.0); - return result; -} - - -void HistogramMain::calculate_histogram(VFrame *data) -{ - - if(!engine) engine = new HistogramEngine(this, - get_project_smp() + 1, - get_project_smp() + 1); - - if(!accum[0]) - { - for(int i = 0; i < HISTOGRAM_MODES; i++) - accum[i] = new int[HISTOGRAM_SLOTS]; - } - engine->process_packages(HistogramEngine::HISTOGRAM, data); - - for(int i = 0; i < engine->get_total_clients(); i++) - { - HistogramUnit *unit = (HistogramUnit*)engine->get_client(i); - if(i == 0) - { - for(int j = 0; j < HISTOGRAM_MODES; j++) - memcpy(accum[j], unit->accum[j], sizeof(int) * HISTOGRAM_SLOTS); - } - else - { - for(int j = 0; j < HISTOGRAM_MODES; j++) - { - int *out = accum[j]; - int *in = unit->accum[j]; - for(int k = 0; k < HISTOGRAM_SLOTS; k++) - out[k] += in[k]; - } - } - } - -// Remove top and bottom from calculations. Doesn't work in high -// precision colormodels. - for(int i = 0; i < HISTOGRAM_MODES; i++) - { - accum[i][0] = 0; - accum[i][HISTOGRAM_SLOTS - 1] = 0; - } -} - - -void HistogramMain::calculate_automatic(VFrame *data) -{ - calculate_histogram(data); - config.reset_points(); - -// Do each channel - for(int i = 0; i < 3; i++) - { - int *accum = this->accum[i]; - int pixels = data->get_w() * data->get_h(); - float white_fraction = 1.0 - (1.0 - config.threshold) / 2; - int threshold = (int)(white_fraction * pixels); - int total = 0; - float max_level = 1.0; - float min_level = 0.0; - -// Get histogram slot above threshold of pixels - for(int j = 0; j < HISTOGRAM_SLOTS; j++) - { - total += accum[j]; - if(total >= threshold) - { - max_level = (float)j / HISTOGRAM_SLOTS * FLOAT_RANGE + HIST_MIN_INPUT; - break; - } - } - -// Get slot below 99% of pixels - total = 0; - for(int j = HISTOGRAM_SLOTS - 1; j >= 0; j--) - { - total += accum[j]; - if(total >= threshold) - { - min_level = (float)j / HISTOGRAM_SLOTS * FLOAT_RANGE + HIST_MIN_INPUT; - break; - } - } - - - config.points[i].insert(max_level, 1.0); - config.points[i].insert(min_level, 0.0); - - } -} - - - - - - -int HistogramMain::process_realtime(VFrame *input_ptr, VFrame *output_ptr) -{ -SET_TRACE - int need_reconfigure = load_configuration(); - -SET_TRACE - - if(!engine) engine = new HistogramEngine(this, - get_project_smp() + 1, - get_project_smp() + 1); - this->input = input_ptr; - this->output = output_ptr; - - send_render_gui(input_ptr); - - if(input_ptr->get_rows()[0] != output_ptr->get_rows()[0]) - { - output_ptr->copy_from(input_ptr); - } - -SET_TRACE -// Generate tables here. The same table is used by many packages to render -// each horizontal stripe. Need to cover the entire output range in each -// table to avoid green borders - if(need_reconfigure || - !lookup[0] || - !smoothed[0] || - !linear[0] || - config.automatic) - { -SET_TRACE -// Calculate new curves - if(config.automatic) - { - calculate_automatic(input); - } -SET_TRACE - -// Generate transfer tables for integer colormodels. - for(int i = 0; i < 3; i++) - tabulate_curve(i, 1); -SET_TRACE - } - - - - -// Apply histogram - engine->process_packages(HistogramEngine::APPLY, input); - -SET_TRACE - - return 0; -} - -void HistogramMain::tabulate_curve(int subscript, int use_value) -{ - int i; - if(!lookup[subscript]) - lookup[subscript] = new int[HISTOGRAM_SLOTS]; - if(!smoothed[subscript]) - smoothed[subscript] = new float[HISTOGRAM_SLOTS]; - if(!linear[subscript]) - linear[subscript] = new float[HISTOGRAM_SLOTS]; - - float *current_smooth = smoothed[subscript]; - float *current_linear = linear[subscript]; - -// Make linear curve - for(i = 0; i < HISTOGRAM_SLOTS; i++) - { - float input = (float)i / HISTOGRAM_SLOTS * FLOAT_RANGE + HIST_MIN_INPUT; - current_linear[i] = calculate_linear(input, subscript, use_value); - } - - - - - - -// Make smooth curve - float prev = 0.0; - for(i = 0; i < HISTOGRAM_SLOTS; i++) - { -// current_smooth[i] = current_linear[i] * 0.001 + -// prev * 0.999; - current_smooth[i] = current_linear[i]; - prev = current_smooth[i]; - } - - -// Generate lookup tables for integer colormodels - if(input) - { - switch(input->get_color_model()) - { - case BC_RGB888: - case BC_RGBA8888: - for(i = 0; i < 0x100; i++) - lookup[subscript][i] = - (int)(calculate_smooth((float)i / 0xff, subscript) * 0xff); - break; -// All other integer colormodels are converted to 16 bit RGB - default: - for(i = 0; i < 0x10000; i++) - lookup[subscript][i] = - (int)(calculate_smooth((float)i / 0xffff, subscript) * 0xffff); - break; - } - } -} - - - - - - - - - - - - -HistogramPackage::HistogramPackage() - : LoadPackage() -{ -} - - - - -HistogramUnit::HistogramUnit(HistogramEngine *server, - HistogramMain *plugin) - : LoadClient(server) -{ - this->plugin = plugin; - this->server = server; - for(int i = 0; i < HISTOGRAM_MODES; i++) - accum[i] = new int[HISTOGRAM_SLOTS]; -} - -HistogramUnit::~HistogramUnit() -{ - for(int i = 0; i < HISTOGRAM_MODES; i++) - delete [] accum[i]; -} - -void HistogramUnit::process_package(LoadPackage *package) -{ - HistogramPackage *pkg = (HistogramPackage*)package; - - if(server->operation == HistogramEngine::HISTOGRAM) - { - -#define HISTOGRAM_HEAD(type) \ -{ \ - for(int i = pkg->start; i < pkg->end; i++) \ - { \ - type *row = (type*)data->get_rows()[i]; \ - for(int j = 0; j < w; j++) \ - { - -#define HISTOGRAM_TAIL(components) \ -/* v = (r * 76 + g * 150 + b * 29) >> 8; */ \ - v = MAX(r, g); \ - v = MAX(v, b); \ - r += -HISTOGRAM_MIN * 0xffff / 100; \ - g += -HISTOGRAM_MIN * 0xffff / 100; \ - b += -HISTOGRAM_MIN * 0xffff / 100; \ - v += -HISTOGRAM_MIN * 0xffff / 100; \ - CLAMP(r, 0, HISTOGRAM_SLOTS); \ - CLAMP(g, 0, HISTOGRAM_SLOTS); \ - CLAMP(b, 0, HISTOGRAM_SLOTS); \ - CLAMP(v, 0, HISTOGRAM_SLOTS); \ - accum_r[r]++; \ - accum_g[g]++; \ - accum_b[b]++; \ - accum_v[v]++; \ - row += components; \ - } \ - } \ -} - - - - - VFrame *data = server->data; - int w = data->get_w(); - int h = data->get_h(); - int *accum_r = accum[HISTOGRAM_RED]; - int *accum_g = accum[HISTOGRAM_GREEN]; - int *accum_b = accum[HISTOGRAM_BLUE]; - int *accum_v = accum[HISTOGRAM_VALUE]; - int r, g, b, a, y, u, v; - - switch(data->get_color_model()) - { - case BC_RGB888: - HISTOGRAM_HEAD(unsigned char) - r = (row[0] << 8) | row[0]; - g = (row[1] << 8) | row[1]; - b = (row[2] << 8) | row[2]; - HISTOGRAM_TAIL(3) - break; - case BC_RGB_FLOAT: - HISTOGRAM_HEAD(float) - r = (int)(row[0] * 0xffff); - g = (int)(row[1] * 0xffff); - b = (int)(row[2] * 0xffff); - HISTOGRAM_TAIL(3) - break; - case BC_YUV888: - HISTOGRAM_HEAD(unsigned char) - y = (row[0] << 8) | row[0]; - u = (row[1] << 8) | row[1]; - v = (row[2] << 8) | row[2]; - plugin->yuv.yuv_to_rgb_16(r, g, b, y, u, v); - HISTOGRAM_TAIL(3) - break; - case BC_RGBA8888: - HISTOGRAM_HEAD(unsigned char) - r = (row[0] << 8) | row[0]; - g = (row[1] << 8) | row[1]; - b = (row[2] << 8) | row[2]; - HISTOGRAM_TAIL(4) - break; - case BC_RGBA_FLOAT: - HISTOGRAM_HEAD(float) - r = (int)(row[0] * 0xffff); - g = (int)(row[1] * 0xffff); - b = (int)(row[2] * 0xffff); - HISTOGRAM_TAIL(4) - break; - case BC_YUVA8888: - HISTOGRAM_HEAD(unsigned char) - y = (row[0] << 8) | row[0]; - u = (row[1] << 8) | row[1]; - v = (row[2] << 8) | row[2]; - plugin->yuv.yuv_to_rgb_16(r, g, b, y, u, v); - HISTOGRAM_TAIL(4) - break; - case BC_RGB161616: - HISTOGRAM_HEAD(uint16_t) - r = row[0]; - g = row[1]; - b = row[2]; - HISTOGRAM_TAIL(3) - break; - case BC_YUV161616: - HISTOGRAM_HEAD(uint16_t) - y = row[0]; - u = row[1]; - v = row[2]; - plugin->yuv.yuv_to_rgb_16(r, g, b, y, u, v); - HISTOGRAM_TAIL(3) - break; - case BC_RGBA16161616: - HISTOGRAM_HEAD(uint16_t) - r = row[0]; - g = row[1]; - b = row[2]; - HISTOGRAM_TAIL(3) - break; - case BC_YUVA16161616: - HISTOGRAM_HEAD(uint16_t) - y = row[0]; - u = row[1]; - v = row[2]; - plugin->yuv.yuv_to_rgb_16(r, g, b, y, u, v); - HISTOGRAM_TAIL(4) - break; - } - } - else - if(server->operation == HistogramEngine::APPLY) - { - - - -#define PROCESS(type, components) \ -{ \ - for(int i = pkg->start; i < pkg->end; i++) \ - { \ - type *row = (type*)input->get_rows()[i]; \ - for(int j = 0; j < w; j++) \ - { \ - if ( plugin->config.split && ((j + i * w / h) < w) ) \ - continue; \ - row[0] = lookup_r[row[0]]; \ - row[1] = lookup_g[row[1]]; \ - row[2] = lookup_b[row[2]]; \ - row += components; \ - } \ - } \ -} - -#define PROCESS_YUV(type, components, max) \ -{ \ - for(int i = pkg->start; i < pkg->end; i++) \ - { \ - type *row = (type*)input->get_rows()[i]; \ - for(int j = 0; j < w; j++) \ - { \ - if ( plugin->config.split && ((j + i * w / h) < w) ) \ - continue; \ -/* Convert to 16 bit RGB */ \ - if(max == 0xff) \ - { \ - y = (row[0] << 8) | row[0]; \ - u = (row[1] << 8) | row[1]; \ - v = (row[2] << 8) | row[2]; \ - } \ - else \ - { \ - y = row[0]; \ - u = row[1]; \ - v = row[2]; \ - } \ - \ - plugin->yuv.yuv_to_rgb_16(r, g, b, y, u, v); \ - \ -/* Look up in RGB domain */ \ - r = lookup_r[r]; \ - g = lookup_g[g]; \ - b = lookup_b[b]; \ - \ -/* Convert to 16 bit YUV */ \ - plugin->yuv.rgb_to_yuv_16(r, g, b, y, u, v); \ - \ - if(max == 0xff) \ - { \ - row[0] = y >> 8; \ - row[1] = u >> 8; \ - row[2] = v >> 8; \ - } \ - else \ - { \ - row[0] = y; \ - row[1] = u; \ - row[2] = v; \ - } \ - row += components; \ - } \ - } \ -} - -#define PROCESS_FLOAT(components) \ -{ \ - for(int i = pkg->start; i < pkg->end; i++) \ - { \ - float *row = (float*)input->get_rows()[i]; \ - for(int j = 0; j < w; j++) \ - { \ - if ( plugin->config.split && ((j + i * w / h) < w) ) \ - continue; \ - float r = row[0]; \ - float g = row[1]; \ - float b = row[2]; \ - \ - r = plugin->calculate_smooth(r, HISTOGRAM_RED); \ - g = plugin->calculate_smooth(g, HISTOGRAM_GREEN); \ - b = plugin->calculate_smooth(b, HISTOGRAM_BLUE); \ - \ - row[0] = r; \ - row[1] = g; \ - row[2] = b; \ - \ - row += components; \ - } \ - } \ -} - - - VFrame *input = plugin->input; - VFrame *output = plugin->output; - int w = input->get_w(); - int h = input->get_h(); - int *lookup_r = plugin->lookup[0]; - int *lookup_g = plugin->lookup[1]; - int *lookup_b = plugin->lookup[2]; - int r, g, b, y, u, v, a; - switch(input->get_color_model()) - { - case BC_RGB888: - PROCESS(unsigned char, 3) - break; - case BC_RGB_FLOAT: - PROCESS_FLOAT(3); - break; - case BC_RGBA8888: - PROCESS(unsigned char, 4) - break; - case BC_RGBA_FLOAT: - PROCESS_FLOAT(4); - break; - case BC_RGB161616: - PROCESS(uint16_t, 3) - break; - case BC_RGBA16161616: - PROCESS(uint16_t, 4) - break; - case BC_YUV888: - PROCESS_YUV(unsigned char, 3, 0xff) - break; - case BC_YUVA8888: - PROCESS_YUV(unsigned char, 4, 0xff) - break; - case BC_YUV161616: - PROCESS_YUV(uint16_t, 3, 0xffff) - break; - case BC_YUVA16161616: - PROCESS_YUV(uint16_t, 4, 0xffff) - break; - } - } -} - - - - - - -HistogramEngine::HistogramEngine(HistogramMain *plugin, - int total_clients, - int total_packages) - : LoadServer(total_clients, total_packages) -{ - this->plugin = plugin; -} - -void HistogramEngine::init_packages() -{ - switch(operation) - { - case HISTOGRAM: - total_size = data->get_h(); - break; - case APPLY: - total_size = data->get_h(); - break; - } - - - int package_size = (int)((float)total_size / - get_total_packages() + 1); - int start = 0; - - for(int i = 0; i < get_total_packages(); i++) - { - HistogramPackage *package = (HistogramPackage*)get_package(i); - package->start = total_size * i / get_total_packages(); - package->end = total_size * (i + 1) / get_total_packages(); - } - -// Initialize clients here in case some don't get run. - for(int i = 0; i < get_total_clients(); i++) - { - HistogramUnit *unit = (HistogramUnit*)get_client(i); - for(int i = 0; i < HISTOGRAM_MODES; i++) - bzero(unit->accum[i], sizeof(int) * HISTOGRAM_SLOTS); - } - -} - -LoadClient* HistogramEngine::new_client() -{ - return new HistogramUnit(this, plugin); -} - -LoadPackage* HistogramEngine::new_package() -{ - return new HistogramPackage; -} - -void HistogramEngine::process_packages(int operation, VFrame *data) -{ - this->data = data; - this->operation = operation; - LoadServer::process_packages(); -} - - - diff --git a/cinelerra-5.0/plugins/histogram_bezier/histogram.h b/cinelerra-5.0/plugins/histogram_bezier/histogram.h deleted file mode 100644 index afb8fb0e..00000000 --- a/cinelerra-5.0/plugins/histogram_bezier/histogram.h +++ /dev/null @@ -1,139 +0,0 @@ - -/* - * CINELERRA - * Copyright (C) 2008 Adam Williams - * - * 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 - * - */ - -#ifndef HISTOGRAM_H -#define HISTOGRAM_H - - -#include "histogram.inc" -#include "histogramconfig.h" -#include "histogramwindow.inc" -#include "loadbalance.h" -#include "cicolors.h" -#include "pluginvclient.h" - -enum -{ - HISTOGRAM_LINEAR, - HISTOGRAM_POLYNOMINAL, - HISTOGRAM_BEZIER, -}; - - -class HistogramMain : public PluginVClient -{ -public: - HistogramMain(PluginServer *server); - ~HistogramMain(); - - int process_realtime(VFrame *input_ptr, VFrame *output_ptr); - int is_realtime(); - int load_defaults(); - int save_defaults(); - void save_data(KeyFrame *keyframe); - void read_data(KeyFrame *keyframe); - void update_gui(); - void render_gui(void *data); - - PLUGIN_CLASS_MEMBERS(HistogramConfig, HistogramThread) - -// Convert input to linear output - float calculate_linear(float input, int mode, int do_value); - float calculate_smooth(float input, int subscript); -// Convert input to smoothed output by looking up in smooth table. - float calculate_curve(float input); -// Calculate automatic settings - void calculate_automatic(VFrame *data); -// Calculate histogram - void calculate_histogram(VFrame *data); -// Calculate the linear, smoothed, lookup curves - void tabulate_curve(int subscript, int use_value); - - - - YUV yuv; - VFrame *input, *output; - HistogramEngine *engine; - int *lookup[HISTOGRAM_MODES]; - float *smoothed[HISTOGRAM_MODES]; - float *linear[HISTOGRAM_MODES]; - int *accum[HISTOGRAM_MODES]; -// Input point being dragged or edited - int current_point; -// Current channel being viewed - int mode; - int dragging_point; - int point_x_offset; - int point_y_offset; -}; - -class HistogramPackage : public LoadPackage -{ -public: - HistogramPackage(); - int start, end; -}; - -class HistogramUnit : public LoadClient -{ -public: - HistogramUnit(HistogramEngine *server, HistogramMain *plugin); - ~HistogramUnit(); - void process_package(LoadPackage *package); - HistogramEngine *server; - HistogramMain *plugin; - int *accum[5]; -}; - -class HistogramEngine : public LoadServer -{ -public: - HistogramEngine(HistogramMain *plugin, - int total_clients, - int total_packages); - void process_packages(int operation, VFrame *data); - void init_packages(); - LoadClient* new_client(); - LoadPackage* new_package(); - HistogramMain *plugin; - int total_size; - - - int operation; - enum - { - HISTOGRAM, - APPLY - }; - VFrame *data; -}; - - - - - - - - - - - -#endif diff --git a/cinelerra-5.0/plugins/histogram_bezier/histogram.inc b/cinelerra-5.0/plugins/histogram_bezier/histogram.inc deleted file mode 100644 index bfbd7e3d..00000000 --- a/cinelerra-5.0/plugins/histogram_bezier/histogram.inc +++ /dev/null @@ -1,58 +0,0 @@ - -/* - * CINELERRA - * Copyright (C) 2008 Adam Williams - * - * 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 - * - */ - -#ifndef HISTOGRAM_INC -#define HISTOGRAM_INC - - - - - -// modes -#define HISTOGRAM_MODES 4 -#define HISTOGRAM_RED 0 -#define HISTOGRAM_GREEN 1 -#define HISTOGRAM_BLUE 2 -#define HISTOGRAM_VALUE 3 - -// Number of divisions in histogram. -// 65536 + min and max range to speed up the tabulation -#define HISTOGRAM_SLOTS 0x13333 -#define FLOAT_RANGE 1.2 -// Minimum value in percentage -#define HISTOGRAM_MIN -10 -#define HIST_MIN_INPUT -0.1 -// Maximum value in percentage -#define HISTOGRAM_MAX 110 -#define HIST_MAX_INPUT 1.1 - -#define PRECISION 0.001 -#define DIGITS 3 -#define THRESHOLD_SCALE 1000 - -#define BOX_SIZE 10 - - -class HistogramEngine; -class HistogramMain; - - -#endif diff --git a/cinelerra-5.0/plugins/histogram_bezier/histogramconfig.C b/cinelerra-5.0/plugins/histogram_bezier/histogramconfig.C deleted file mode 100644 index a3cdcf8d..00000000 --- a/cinelerra-5.0/plugins/histogram_bezier/histogramconfig.C +++ /dev/null @@ -1,299 +0,0 @@ - -/* - * CINELERRA - * Copyright (C) 2008 Adam Williams - * - * 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 "clip.h" -#include "histogramconfig.h" -#include "units.h" - -#include - - - - -HistogramPoint::HistogramPoint() - : ListItem() -{ -} - -HistogramPoint::~HistogramPoint() -{ -} - -int HistogramPoint::equivalent(HistogramPoint *src) -{ - return EQUIV(x, src->x) && EQUIV(y, src->y) && EQUIV(gradient, src->gradient); -} - - - - -HistogramPoints::HistogramPoints() - : List() -{ - insert(0.0,0.0); - first->gradient = 1.0; - first->xoffset_left = 0.0; - first->xoffset_right = 0.05; - insert(1.0,1.0); - last->gradient = 1.0; - last->xoffset_left = -0.05; - last->xoffset_right = 0.0; - -} - -HistogramPoints::~HistogramPoints() -{ -} - -HistogramPoint* HistogramPoints::insert(float x, float y) -{ - HistogramPoint *current = first; - -// Get existing point after new point - while(current) - { - if(current->x > x) - break; - else - current = NEXT; - } - -// Insert new point before current point - HistogramPoint *new_point = new HistogramPoint; - if(current) - { - insert_before(current, new_point); - } - else -// Append new point to list - { - append(new_point); - } - - new_point->x = x; - new_point->y = y; - new_point->xoffset_left = -0.05; - new_point->xoffset_right = 0.05; - - - return new_point; -} - -void HistogramPoints::boundaries() -{ - HistogramPoint *current = first; - while(current) - { - CLAMP(current->x, 0.0, 1.0); - CLAMP(current->y, 0.0, 1.0); - current = NEXT; - } -} - -int HistogramPoints::equivalent(HistogramPoints *src) -{ - HistogramPoint *current_this = first; - HistogramPoint *current_src = src->first; - while(current_this && current_src) - { - if(!current_this->equivalent(current_src)) return 0; - current_this = current_this->next; - current_src = current_src->next; - } - - if(!current_this && current_src || - current_this && !current_src) - return 0; - return 1; -} - -void HistogramPoints::copy_from(HistogramPoints *src) -{ - while(last) - delete last; - HistogramPoint *current = src->first; - while(current) - { - HistogramPoint *new_point = new HistogramPoint; - new_point->x = current->x; - new_point->y = current->y; - append(new_point); - current = NEXT; - } -} - -void HistogramPoints::interpolate(HistogramPoints *prev, - HistogramPoints *next, - double prev_scale, - double next_scale) -{ - HistogramPoint *current = first; - HistogramPoint *current_prev = prev->first; - HistogramPoint *current_next = next->first; - - while(current && current_prev && current_next) - { - current->x = current_prev->x * prev_scale + - current_next->x * next_scale; - current->y = current_prev->y * prev_scale + - current_next->y * next_scale; - current = NEXT; - current_prev = current_prev->next; - current_next = current_next->next; - } -} - - - - - - - - - - - - - - -HistogramConfig::HistogramConfig() -{ - reset(1); -} - -void HistogramConfig::reset(int do_mode) -{ - reset_points(); - - - for(int i = 0; i < HISTOGRAM_MODES; i++) - { - output_min[i] = 0.0; - output_max[i] = 1.0; - } - - if(do_mode) - { - automatic = 0; - threshold = 0.1; - split = 0; - smoothMode = 0; - } -} - -void HistogramConfig::reset_points() -{ - for(int i = 0; i < HISTOGRAM_MODES; i++) - { - while(points[i].last) delete points[i].last; - points[i].insert(0.0,0.0); - points[i].last->gradient = 1.0; - points[i].insert(1.0,1.0); - points[i].last->gradient = 1.0; - } -} - - -void HistogramConfig::boundaries() -{ - for(int i = 0; i < HISTOGRAM_MODES; i++) - { - points[i].boundaries(); - CLAMP(output_min[i], HIST_MIN_INPUT, HIST_MAX_INPUT); - CLAMP(output_max[i], HIST_MIN_INPUT, HIST_MAX_INPUT); - output_min[i] = Units::quantize(output_min[i], PRECISION); - output_max[i] = Units::quantize(output_max[i], PRECISION); - } - CLAMP(threshold, 0, 1); -} - -int HistogramConfig::equivalent(HistogramConfig &that) -{ - for(int i = 0; i < HISTOGRAM_MODES; i++) - { - if(!points[i].equivalent(&that.points[i]) || - !EQUIV(output_min[i], that.output_min[i]) || - !EQUIV(output_max[i], that.output_max[i])) return 0; - } - - if(automatic != that.automatic || - !EQUIV(threshold, that.threshold)) return 0; - - return 1; -} - -void HistogramConfig::copy_from(HistogramConfig &that) -{ - for(int i = 0; i < HISTOGRAM_MODES; i++) - { - points[i].copy_from(&that.points[i]); - output_min[i] = that.output_min[i]; - output_max[i] = that.output_max[i]; - } - - automatic = that.automatic; - threshold = that.threshold; - split = that.split; - smoothMode = that.smoothMode; -} - -void HistogramConfig::interpolate(HistogramConfig &prev, - HistogramConfig &next, - int64_t prev_frame, - int64_t next_frame, - int64_t current_frame) -{ - double next_scale = (double)(current_frame - prev_frame) / (next_frame - prev_frame); - double prev_scale = 1.0 - next_scale; - - for(int i = 0; i < HISTOGRAM_MODES; i++) - { - points[i].interpolate(&prev.points[i], &next.points[i], next_scale, prev_scale); - output_min[i] = prev.output_min[i] * prev_scale + next.output_min[i] * next_scale; - output_max[i] = prev.output_max[i] * prev_scale + next.output_max[i] * next_scale; - } - - threshold = prev.threshold * prev_scale + next.threshold * next_scale; - automatic = prev.automatic; - split = prev.split; - smoothMode = prev.smoothMode; -} - - -void HistogramConfig::dump() -{ - for(int j = 0; j < HISTOGRAM_MODES; j++) - { - printf("HistogramConfig::dump mode=%d\n", j); - HistogramPoints *points = &this->points[j]; - HistogramPoint *current = points->first; - while(current) - { - printf("%f,%f ", current->x, current->y); - fflush(stdout); - current = NEXT; - } - printf("\n"); - } -} - - - diff --git a/cinelerra-5.0/plugins/histogram_bezier/histogramconfig.h b/cinelerra-5.0/plugins/histogram_bezier/histogramconfig.h deleted file mode 100644 index 4d4c6641..00000000 --- a/cinelerra-5.0/plugins/histogram_bezier/histogramconfig.h +++ /dev/null @@ -1,96 +0,0 @@ - -/* - * CINELERRA - * Copyright (C) 2008 Adam Williams - * - * 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 - * - */ - -#ifndef HISTOGRAMCONFIG_H -#define HISTOGRAMCONFIG_H - - -#include "histogram.inc" -#include "histogramconfig.inc" -#include "linklist.h" -#include - -class HistogramPoint : public ListItem -{ -public: - HistogramPoint(); - ~HistogramPoint(); - - int equivalent(HistogramPoint *src); - float x, y; - float gradient; - float xoffset_left; - float xoffset_right; -}; - - -class HistogramPoints : public List -{ -public: - HistogramPoints(); - ~HistogramPoints(); - -// Insert new point - HistogramPoint* insert(float x, float y); - int equivalent(HistogramPoints *src); - void boundaries(); - void copy_from(HistogramPoints *src); - void interpolate(HistogramPoints *prev, - HistogramPoints *next, - double prev_scale, - double next_scale); -}; - -class HistogramConfig -{ -public: - HistogramConfig(); - - int equivalent(HistogramConfig &that); - void copy_from(HistogramConfig &that); - void interpolate(HistogramConfig &prev, - HistogramConfig &next, - int64_t prev_frame, - int64_t next_frame, - int64_t current_frame); -// Used by constructor and reset button - void reset(int do_mode); - void reset_points(); - void boundaries(); - void dump(); - -// Range 0 - 1.0 -// Input points - HistogramPoints points[HISTOGRAM_MODES]; -// Output points - float output_min[HISTOGRAM_MODES]; - float output_max[HISTOGRAM_MODES]; - int automatic; - float threshold; - int split; - int smoothMode; -}; - - -#endif - - - diff --git a/cinelerra-5.0/plugins/histogram_bezier/histogramconfig.inc b/cinelerra-5.0/plugins/histogram_bezier/histogramconfig.inc deleted file mode 100644 index de386501..00000000 --- a/cinelerra-5.0/plugins/histogram_bezier/histogramconfig.inc +++ /dev/null @@ -1,31 +0,0 @@ - -/* - * CINELERRA - * Copyright (C) 2008 Adam Williams - * - * 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 - * - */ - -#ifndef HISTOGRAMCONFIG_INC -#define HISTOGRAMCONFIG_INC - - -class HistogramPoint; -class HistogramPoints; -class HistogramConfig; - - -#endif diff --git a/cinelerra-5.0/plugins/histogram_bezier/histogramwindow.C b/cinelerra-5.0/plugins/histogram_bezier/histogramwindow.C deleted file mode 100644 index 79e6198f..00000000 --- a/cinelerra-5.0/plugins/histogram_bezier/histogramwindow.C +++ /dev/null @@ -1,1064 +0,0 @@ - -/* - * CINELERRA - * Copyright (C) 2008 Adam Williams - * - * 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 "bcsignals.h" -#include "histogram.h" -#include "histogramconfig.h" -#include "histogramwindow.h" -#include "keys.h" -#include "language.h" - - -#include -#include - -PLUGIN_THREAD_OBJECT(HistogramMain, HistogramThread, HistogramWindow) - - - -HistogramWindow::HistogramWindow(HistogramMain *plugin, int x, int y) - : BC_Window(plugin->gui_string, - x, - y, - 440, - 480, - 440, - 480, - 0, - 1, - 1) -{ - this->plugin = plugin; -} - -HistogramWindow::~HistogramWindow() -{ -} - -static VFrame max_picon_image(max_picon_png); -static VFrame mid_picon_image(mid_picon_png); -static VFrame min_picon_image(min_picon_png); - -int HistogramWindow::create_objects() -{ - int x = 10, y = 10, x1 = 10; - BC_Title *title = 0; - - max_picon = new BC_Pixmap(this, &max_picon_image); - mid_picon = new BC_Pixmap(this, &mid_picon_image); - min_picon = new BC_Pixmap(this, &min_picon_image); - add_subwindow(mode_v = new HistogramMode(plugin, - x, - y, - HISTOGRAM_VALUE, - _("Value"))); - x += 70; - add_subwindow(mode_r = new HistogramMode(plugin, - x, - y, - HISTOGRAM_RED, - _("Red"))); - x += 70; - add_subwindow(mode_g = new HistogramMode(plugin, - x, - y, - HISTOGRAM_GREEN, - _("Green"))); - x += 70; - add_subwindow(mode_b = new HistogramMode(plugin, - x, - y, - HISTOGRAM_BLUE, - _("Blue"))); -// x += 70; -// add_subwindow(mode_a = new HistogramMode(plugin, -// x, -// y, -// HISTOGRAM_ALPHA, -// _("Alpha"))); - - x = x1; - y += 30; - add_subwindow(title = new BC_Title(x, y, _("Input X:"))); - x += title->get_w() + 10; - input_x = new HistogramInputText(plugin, - this, - x, - y, - 1); - input_x->create_objects(); - - x += input_x->get_w() + 10; - add_subwindow(title = new BC_Title(x, y, _("Input Y:"))); - x += title->get_w() + 10; - input_y = new HistogramInputText(plugin, - this, - x, - y, - 0); - input_y->create_objects(); - - y += 30; - x = x1; - - canvas_w = get_w() - x - x; - canvas_h = get_h() - y - 170; - title1_x = x; - title2_x = x + (int)(canvas_w * -HIST_MIN_INPUT / FLOAT_RANGE); - title3_x = x + (int)(canvas_w * (1.0 - HIST_MIN_INPUT) / FLOAT_RANGE); - title4_x = x + (int)(canvas_w); - add_subwindow(canvas = new HistogramCanvas(plugin, - this, - x, - y, - canvas_w, - canvas_h)); - draw_canvas_overlay(); - canvas->flash(); - - y += canvas->get_h() + 1; - add_subwindow(new BC_Title(title1_x, - y, - "-10%")); - add_subwindow(new BC_Title(title2_x, - y, - "0%")); - add_subwindow(new BC_Title(title3_x - get_text_width(MEDIUMFONT, "100"), - y, - "100%")); - add_subwindow(new BC_Title(title4_x - get_text_width(MEDIUMFONT, "110"), - y, - "110%")); - - y += 20; - add_subwindow(title = new BC_Title(x, y, _("Output min:"))); - x += title->get_w() + 10; - output_min = new HistogramOutputText(plugin, - this, - x, - y, - &plugin->config.output_min[plugin->mode]); - output_min->create_objects(); - x += output_min->get_w() + 10; - add_subwindow(new BC_Title(x, y, _("Output Max:"))); - x += title->get_w() + 10; - output_max = new HistogramOutputText(plugin, - this, - x, - y, - &plugin->config.output_max[plugin->mode]); - output_max->create_objects(); - - x = x1; - y += 30; - - add_subwindow(output = new HistogramSlider(plugin, - this, - x, - y, - get_w() - 20, - 30, - 0)); - output->update(); - y += 40; - - - add_subwindow(automatic = new HistogramAuto(plugin, - x, - y)); - - x += 120; - add_subwindow(new HistogramReset(plugin, - x, - y)); - x += 100; - add_subwindow(new BC_Title(x, y, _("Threshold:"))); - x += 100; - threshold = new HistogramOutputText(plugin, - this, - x, - y, - &plugin->config.threshold); - threshold->create_objects(); - x = x1; - y += 40; - add_subwindow(split = new HistogramSplit(plugin, x, y)); - y += 6; - x += 150; - add_subwindow(new BC_Title(x,y, _("Interpolation:"))); - x += 120; - add_subwindow(smoothModeChoser = new HistogramSmoothMode(plugin, this, x, y)); - smoothModeChoser->create_objects(); - - show_window(); - - return 0; -} - -WINDOW_CLOSE_EVENT(HistogramWindow) - -int HistogramWindow::keypress_event() -{ - int result = 0; - if(get_keypress() == BACKSPACE || - get_keypress() == DELETE) - { - if(plugin->current_point >= 0) - { - HistogramPoint *current = - plugin->config.points[plugin->mode].get_item_number(plugin->current_point); - delete current; - plugin->current_point = -1; - update_input(); - update_canvas(); - plugin->send_configure_change(); - result = 1; - } - } - return result; -} - -void HistogramWindow::update(int do_input) -{ - automatic->update(plugin->config.automatic); - threshold->update(plugin->config.threshold); - update_mode(); - - if(do_input) update_input(); - update_output(); -} - -void HistogramWindow::update_input() -{ - input_x->update(); - input_y->update(); -} - -void HistogramWindow::update_output() -{ - output->update(); - output_min->update(plugin->config.output_min[plugin->mode]); - output_max->update(plugin->config.output_max[plugin->mode]); -} - -void HistogramWindow::update_mode() -{ - mode_v->update(plugin->mode == HISTOGRAM_VALUE ? 1 : 0); - mode_r->update(plugin->mode == HISTOGRAM_RED ? 1 : 0); - mode_g->update(plugin->mode == HISTOGRAM_GREEN ? 1 : 0); - mode_b->update(plugin->mode == HISTOGRAM_BLUE ? 1 : 0); - output_min->output = &plugin->config.output_min[plugin->mode]; - output_max->output = &plugin->config.output_max[plugin->mode]; -} - -void HistogramWindow::draw_canvas_overlay() -{ - canvas->set_color(0x00ff00); - int y1; - -// Calculate output curve - plugin->tabulate_curve(plugin->mode, 0); - -// Draw output line - for(int i = 0; i < canvas_w; i++) - { - float input = (float)i / - canvas_w * - FLOAT_RANGE + - HIST_MIN_INPUT; - float output = plugin->calculate_smooth(input, plugin->mode); - - int y2 = canvas_h - (int)(output * canvas_h); - if(i > 0) - { - canvas->draw_line(i - 1, y1, i, y2); - } - y1 = y2; - } - -// Draw output points - HistogramPoint *current = plugin->config.points[plugin->mode].first; - int number = 0; - while(current) - { - int x = (int)((current->x - HIST_MIN_INPUT) * canvas_w / FLOAT_RANGE); - int y = (int)(canvas_h - current->y * canvas_h); - if(number == plugin->current_point) - canvas->draw_box(x - BOX_SIZE / 2, y - BOX_SIZE / 2, BOX_SIZE, BOX_SIZE); - else - canvas->draw_rectangle(x - BOX_SIZE / 2, y - BOX_SIZE / 2, BOX_SIZE, BOX_SIZE); - -//Draw gradients - if (plugin->config.smoothMode > HISTOGRAM_LINEAR) - { - int x1,x2,y1,y2; - canvas->set_color(0x0000ff); - x2 = (int)((current->x + current->xoffset_right - HIST_MIN_INPUT) * canvas_w / FLOAT_RANGE); - x1 = (int)((current->x + current->xoffset_left - HIST_MIN_INPUT) * canvas_w / FLOAT_RANGE); - y2 = (int)(canvas_h - (current->y + current->xoffset_right * current->gradient) * canvas_h); - y1 = (int)(canvas_h - (current->y + current->xoffset_left * current->gradient) * canvas_h); -/* x2 = x + (title3_x - title2_x)/20; - x1 = x - (title3_x - title2_x)/20; - y1 = y + (int)(current->gradient * (float)(canvas_h)/20.0); - y2 = y - (int)(current->gradient * (float)(canvas_h)/20.0); -// int y2 = (int)(canvas_h - canvas_h * (current->y + current->gradient /10));*/ - canvas->draw_line(x1,y1,x2,y2); - - canvas->draw_circle(x1 - BOX_SIZE / 4, y1 - BOX_SIZE / 4, BOX_SIZE/2, BOX_SIZE/2); - canvas->draw_circle(x2 - BOX_SIZE / 4, y2 - BOX_SIZE / 4, BOX_SIZE/2, BOX_SIZE/2); - canvas->set_color(0x00ff00); - } - - current = NEXT; - number++; - } - - -// Draw 0 and 100% lines. - canvas->set_color(0xff0000); - canvas->draw_line(title2_x - canvas->get_x(), - 0, - title2_x - canvas->get_x(), - canvas_h); - canvas->draw_line(title3_x - canvas->get_x(), - 0, - title3_x - canvas->get_x(), - canvas_h); -} - -void HistogramWindow::update_canvas() -{ - int *accum = plugin->accum[plugin->mode]; - int accum_per_canvas_i = HISTOGRAM_SLOTS / canvas_w + 1; - float accum_per_canvas_f = (float)HISTOGRAM_SLOTS / canvas_w; - int normalize = 0; - int max = 0; - - for(int i = 0; i < HISTOGRAM_SLOTS; i++) - { - if(accum && accum[i] > normalize) normalize = accum[i]; - } - - - if(normalize) - { - for(int i = 0; i < canvas_w; i++) - { - int accum_start = (int)(accum_per_canvas_f * i); - int accum_end = accum_start + accum_per_canvas_i; - max = 0; - for(int j = accum_start; j < accum_end; j++) - { - max = MAX(accum[j], max); - } - -// max = max * canvas_h / normalize; - max = (int)(log(max) / log(normalize) * canvas_h); - - canvas->set_color(0xffffff); - canvas->draw_line(i, 0, i, canvas_h - max); - canvas->set_color(0x000000); - canvas->draw_line(i, canvas_h - max, i, canvas_h); - } - } - else - { - canvas->set_color(0xffffff); - canvas->draw_box(0, 0, canvas_w, canvas_h); - } - - - draw_canvas_overlay(); - canvas->flash(); -} - - - - - - - - -HistogramCanvas::HistogramCanvas(HistogramMain *plugin, - HistogramWindow *gui, - int x, - int y, - int w, - int h) - : BC_SubWindow(x, - y, - w, - h, - 0xffffff) -{ - this->plugin = plugin; - this->gui = gui; -} - -int HistogramCanvas::button_press_event() -{ - int result = 0; - if(is_event_win() && cursor_inside()) - { - if(!plugin->dragging_point) - { - HistogramPoint *new_point = 0; - gui->deactivate(); -// Search for existing point under cursor - HistogramPoint *current = plugin->config.points[plugin->mode].first; - plugin->current_point = -1; - int dragID = 0; - while(current) - { - int x = (int)((current->x - HIST_MIN_INPUT) * gui->canvas_w / FLOAT_RANGE); - int y = (int)(gui->canvas_h - current->y * gui->canvas_h); - -/* Check for click on main point */ - if(get_cursor_x() >= x - BOX_SIZE / 2 && - get_cursor_y() >= y - BOX_SIZE / 2 && - get_cursor_x() < x + BOX_SIZE / 2 && - get_cursor_y() < y + BOX_SIZE / 2) - { - plugin->current_point = - plugin->config.points[plugin->mode].number_of(current); - plugin->point_x_offset = get_cursor_x() - x; - plugin->point_y_offset = get_cursor_y() - y; - dragID = 1; - break; - } - if (plugin->config.smoothMode == HISTOGRAM_LINEAR) - break; - - int xright = - (int)((current->x + current->xoffset_right - HIST_MIN_INPUT) * gui->canvas_w / FLOAT_RANGE); - int yright = - (int)(gui->canvas_h - (current->y + current->xoffset_right * current->gradient) * - gui->canvas_h); - -/* Check for click on right handle */ - if(get_cursor_x() >= xright - BOX_SIZE / 2 && - get_cursor_y() >= yright - BOX_SIZE / 2 && - get_cursor_x() < xright + BOX_SIZE / 2 && - get_cursor_y() < yright + BOX_SIZE / 2) - { - plugin->current_point = - plugin->config.points[plugin->mode].number_of(current); - plugin->point_x_offset = get_cursor_x() - xright; - plugin->point_y_offset = get_cursor_y() - yright; - dragID = 2; - break; - } - -/* Check for click on left handle */ - int xleft = - (int)((current->x + current->xoffset_left - HIST_MIN_INPUT) * gui->canvas_w / FLOAT_RANGE); - int yleft = - (int)(gui->canvas_h - (current->y + current->xoffset_left * current->gradient) * - gui->canvas_h); - if(get_cursor_x() >= xleft - BOX_SIZE / 2 && - get_cursor_y() >= yleft - BOX_SIZE / 2 && - get_cursor_x() < xleft + BOX_SIZE / 2 && - get_cursor_y() < yleft + BOX_SIZE / 2) - { - plugin->current_point = - plugin->config.points[plugin->mode].number_of(current); - plugin->point_x_offset = get_cursor_x() - xleft; - plugin->point_y_offset = get_cursor_y() - yleft; - dragID = 3; - break; - } - - - current = NEXT; - } - - if(plugin->current_point < 0) - { -// Create new point under cursor - float current_x = (float)get_cursor_x() * - FLOAT_RANGE / - get_w() + - HIST_MIN_INPUT; - float current_y = 1.0 - - (float)get_cursor_y() / - get_h(); - new_point = - plugin->config.points[plugin->mode].insert(current_x, current_y); - plugin->current_point = - plugin->config.points[plugin->mode].number_of(new_point); - plugin->point_x_offset = 0; - plugin->point_y_offset = 0; - -// Default gradient -// Get 2 points surrounding current position - float x1,x2,y1,y2; - - HistogramPoint *current = plugin->config.points[plugin->mode].first; - int done = 0; - while(current && !done) - { - if(current->x > current_x) - { - x2 = current->x; - y2 = current->y; - done = 1; - } - else - current = NEXT; - } - - current = plugin->config.points[plugin->mode].last; - done = 0; - while(current && !done) - { - if(current->x <= current_x) - { - x1 = current->x; - y1 = current->y; - done = 1; - } - else - current = PREVIOUS; - } - new_point->gradient = (y2 - y1) / (x2 - x1); - dragID = 1; - - } - - - plugin->dragging_point = dragID; - result = 1; - - plugin->config.boundaries(); - gui->update_input(); - gui->update_canvas(); - if(new_point) - { - plugin->send_configure_change(); - } - } - } - return result; -} - -int HistogramCanvas::cursor_motion_event() -{ - if(plugin->dragging_point) - { - HistogramPoint * current_point = plugin->config.points[plugin->mode].get_item_number(plugin->current_point); - - float current_x = - (float)(get_cursor_x() - plugin->point_x_offset) * - FLOAT_RANGE / - get_w() + - HIST_MIN_INPUT; - float current_y = 1.0 - - (float)(get_cursor_y() - plugin->point_y_offset) / - get_h(); - - switch(plugin->dragging_point) - { - case 1: /* Main point dragged */ - current_point->x = current_x; - current_point->y = current_y; - break; - case 2: /* Right control point dragged */ - if (current_x - current_point->x > 0) - { - current_point->xoffset_right = current_x - current_point->x; - current_point->gradient = (current_y - current_point->y) / (current_x - current_point->x); - } - break; - case 3: /* Left control point dragged */ - if (current_x - current_point->x < 0) - { - current_point->xoffset_left = current_x - current_point->x; - current_point->gradient = (current_point->y - current_y) / (current_point->x - current_x); - } - break; - } - - plugin->config.boundaries(); - gui->update_input(); - gui->update_canvas(); - plugin->send_configure_change(); - return 1; - } - return 0; -} - -int HistogramCanvas::button_release_event() -{ - if(plugin->dragging_point) - { -// Test for out of order points to delete. - HistogramPoint *current = - plugin->config.points[plugin->mode].get_item_number(plugin->current_point); - HistogramPoint *prev = PREVIOUS; - HistogramPoint *next = NEXT; - - if((prev && prev->x >= current->x) || - (next && next->x <= current->x)) - { - delete current; - plugin->current_point = -1; - plugin->config.boundaries(); - gui->update_input(); - gui->update_canvas(); - plugin->send_configure_change(); - } - - plugin->dragging_point = 0; - } - return 0; -} - - - - - - - -HistogramReset::HistogramReset(HistogramMain *plugin, - int x, - int y) - : BC_GenericButton(x, y, _("Reset")) -{ - this->plugin = plugin; -} -int HistogramReset::handle_event() -{ - plugin->config.reset(0); - plugin->thread->window->update(1); - plugin->thread->window->update_canvas(); - plugin->send_configure_change(); - return 1; -} - - - - - - - - - -HistogramSlider::HistogramSlider(HistogramMain *plugin, - HistogramWindow *gui, - int x, - int y, - int w, - int h, - int is_input) - : BC_SubWindow(x, y, w, h) -{ - this->plugin = plugin; - this->gui = gui; - this->is_input = is_input; - operation = NONE; -} - -int HistogramSlider::input_to_pixel(float input) -{ - return (int)((input - HIST_MIN_INPUT) / FLOAT_RANGE * get_w()); -} - -int HistogramSlider::button_press_event() -{ - if(is_event_win() && cursor_inside()) - { - int min; - int max; - int w = get_w(); - int h = get_h(); - int half_h = get_h() / 2; - - gui->deactivate(); - - if(operation == NONE) - { - int x1 = input_to_pixel(plugin->config.output_min[plugin->mode]) - - gui->mid_picon->get_w() / 2; - int x2 = x1 + gui->mid_picon->get_w(); - if(get_cursor_x() >= x1 && get_cursor_x() < x2 && - get_cursor_y() >= half_h && get_cursor_y() < h) - { - operation = DRAG_MIN_OUTPUT; - } - } - - if(operation == NONE) - { - int x1 = input_to_pixel(plugin->config.output_max[plugin->mode]) - - gui->mid_picon->get_w() / 2; - int x2 = x1 + gui->mid_picon->get_w(); - if(get_cursor_x() >= x1 && get_cursor_x() < x2 && - get_cursor_y() >= half_h && get_cursor_y() < h) - { - operation = DRAG_MAX_OUTPUT; - } - } - return 1; - } - return 0; -} - -int HistogramSlider::button_release_event() -{ - if(operation != NONE) - { - operation = NONE; - return 1; - } - return 0; -} - -int HistogramSlider::cursor_motion_event() -{ - if(operation != NONE) - { - float value = (float)get_cursor_x() / get_w() * FLOAT_RANGE + HIST_MIN_INPUT; - CLAMP(value, HIST_MIN_INPUT, HIST_MAX_INPUT); - - switch(operation) - { - case DRAG_MIN_OUTPUT: - value = MIN(plugin->config.output_max[plugin->mode], value); - plugin->config.output_min[plugin->mode] = value; - break; - case DRAG_MAX_OUTPUT: - value = MAX(plugin->config.output_min[plugin->mode], value); - plugin->config.output_max[plugin->mode] = value; - break; - } - - plugin->config.boundaries(); - gui->update_output(); - - plugin->send_configure_change(); - return 1; - } - return 0; -} - -void HistogramSlider::update() -{ - int w = get_w(); - int h = get_h(); - int half_h = get_h() / 2; - int quarter_h = get_h() / 4; - int mode = plugin->mode; - int r = 0xff; - int g = 0xff; - int b = 0xff; - - clear_box(0, 0, w, h); - - switch(mode) - { - case HISTOGRAM_RED: - g = b = 0x00; - break; - case HISTOGRAM_GREEN: - r = b = 0x00; - break; - case HISTOGRAM_BLUE: - r = g = 0x00; - break; - } - - for(int i = 0; i < w; i++) - { - int color = (int)(i * 0xff / w); - set_color(((r * color / 0xff) << 16) | - ((g * color / 0xff) << 8) | - (b * color / 0xff)); - - draw_line(i, 0, i, half_h); - } - - float min; - float max; - min = plugin->config.output_min[plugin->mode]; - max = plugin->config.output_max[plugin->mode]; - - draw_pixmap(gui->min_picon, - input_to_pixel(min) - gui->min_picon->get_w() / 2, - half_h + 1); - draw_pixmap(gui->max_picon, - input_to_pixel(max) - gui->max_picon->get_w() / 2, - half_h + 1); - - flash(); - flush(); -} - - - - - - - - - -HistogramAuto::HistogramAuto(HistogramMain *plugin, - int x, - int y) - : BC_CheckBox(x, y, plugin->config.automatic, _("Automatic")) -{ - this->plugin = plugin; -} - -int HistogramAuto::handle_event() -{ - plugin->config.automatic = get_value(); - plugin->send_configure_change(); - return 1; -} - - - - -HistogramSplit::HistogramSplit(HistogramMain *plugin, - int x, - int y) - : BC_CheckBox(x, y, plugin->config.split, _("Split picture")) -{ - this->plugin = plugin; -} - -int HistogramSplit::handle_event() -{ - plugin->config.split = get_value(); - plugin->send_configure_change(); - return 1; -} - - - - -HistogramMode::HistogramMode(HistogramMain *plugin, - int x, - int y, - int value, - char *text) - : BC_Radial(x, y, plugin->mode == value, text) -{ - this->plugin = plugin; - this->value = value; -} -int HistogramMode::handle_event() -{ - plugin->mode = value; - plugin->current_point= -1; - plugin->thread->window->update_canvas(); - plugin->thread->window->update_mode(); - plugin->thread->window->update_input(); - plugin->thread->window->update_canvas(); - plugin->thread->window->update_output(); - plugin->thread->window->output->update(); -// plugin->send_configure_change(); - return 1; -} - - - - - - - - - -HistogramOutputText::HistogramOutputText(HistogramMain *plugin, - HistogramWindow *gui, - int x, - int y, - float *output) - : BC_TumbleTextBox(gui, - output ? (float)*output : 0.0, - (float)HIST_MIN_INPUT, - (float)HIST_MAX_INPUT, - x, - y, - 60) -{ - this->plugin = plugin; - this->output = output; - set_precision(DIGITS); - set_increment(PRECISION); -} - - -int HistogramOutputText::handle_event() -{ - if(output) - { - *output = atof(get_text()); - } - - plugin->thread->window->output->update(); - plugin->send_configure_change(); - return 1; -} - - - - - - - - -HistogramInputText::HistogramInputText(HistogramMain *plugin, - HistogramWindow *gui, - int x, - int y, - int do_x) - : BC_TumbleTextBox(gui, - 0.0, - (float)HIST_MIN_INPUT, - (float)HIST_MAX_INPUT, - x, - y, - 60) -{ - this->do_x = do_x; - this->plugin = plugin; - this->gui = gui; - set_precision(DIGITS); - set_increment(PRECISION); -} - - -int HistogramInputText::handle_event() -{ - if(plugin->current_point >= 0 && - plugin->current_point < plugin->config.points[plugin->mode].total()) - { - HistogramPoint *point = - plugin->config.points[plugin->mode].get_item_number( - plugin->current_point); - - if(point) - { - if(do_x) - point->x = atof(get_text()); - else - point->y = atof(get_text()); - - plugin->config.boundaries(); - gui->update_canvas(); - - plugin->thread->window->output->update(); - plugin->send_configure_change(); - } - } - return 1; -} - -void HistogramInputText::update() -{ - if(plugin->current_point >= 0 && - plugin->current_point < plugin->config.points[plugin->mode].total()) - { - HistogramPoint *point = - - plugin->config.points[plugin->mode].get_item_number( - plugin->current_point); - - if(point) - { - if(do_x) - BC_TumbleTextBox::update(point->x); - else - BC_TumbleTextBox::update(point->y); - } - else - { - BC_TumbleTextBox::update((float)0.0); - } - } - else - { - BC_TumbleTextBox::update((float)0.0); - } - -} - - -HistogramSmoothMode::HistogramSmoothMode(HistogramMain*plugin, - HistogramWindow *gui, - int x, - int y) - : BC_PopupMenu(x, y, 120, to_text(plugin->config.smoothMode), 1) -{ - this->plugin = plugin; - this->gui = gui; -} -void HistogramSmoothMode::create_objects() -{ - add_item(new BC_MenuItem(to_text(HISTOGRAM_LINEAR))); - add_item(new BC_MenuItem(to_text(HISTOGRAM_POLYNOMINAL))); - add_item(new BC_MenuItem(to_text(HISTOGRAM_BEZIER))); -} - -char* HistogramSmoothMode::to_text(int mode) -{ - switch(mode) - { - case HISTOGRAM_LINEAR: - return _("Linear"); - case HISTOGRAM_POLYNOMINAL: - return _("Polynominal"); - case HISTOGRAM_BEZIER: - return _("Bezier"); - } -} -int HistogramSmoothMode::from_text(char *text) -{ - if(!strcmp(text, to_text(HISTOGRAM_LINEAR))) - return HISTOGRAM_LINEAR; - if(!strcmp(text, to_text(HISTOGRAM_POLYNOMINAL))) - return HISTOGRAM_POLYNOMINAL; - if(!strcmp(text, to_text(HISTOGRAM_BEZIER))) - return HISTOGRAM_BEZIER; -} - -int HistogramSmoothMode::handle_event() -{ - plugin->config.smoothMode = from_text(get_text()); - gui->update_canvas(); - plugin->send_configure_change(); -} - - - - - - - - - - - - - - diff --git a/cinelerra-5.0/plugins/histogram_bezier/histogramwindow.h b/cinelerra-5.0/plugins/histogram_bezier/histogramwindow.h deleted file mode 100644 index 8634d98a..00000000 --- a/cinelerra-5.0/plugins/histogram_bezier/histogramwindow.h +++ /dev/null @@ -1,211 +0,0 @@ - -/* - * CINELERRA - * Copyright (C) 2008 Adam Williams - * - * 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 - * - */ - -#ifndef HISTOGRAMWINDOW_H -#define HISTOGRAMWINDOW_H - - - -#include "histogram.inc" -#include "histogramwindow.inc" -#include "pluginvclient.h" - - -class HistogramSmoothMode : public BC_PopupMenu -{ -public: - HistogramSmoothMode(HistogramMain *client, - HistogramWindow *window, - int x, - int y); - void create_objects(); - static char* to_text(int shape); - static int from_text(char *text); - int handle_event(); - HistogramMain *plugin; - HistogramWindow *gui; -}; - -class HistogramSlider : public BC_SubWindow -{ -public: - HistogramSlider(HistogramMain *plugin, - HistogramWindow *gui, - int x, - int y, - int w, - int h, - int is_input); - - void update(); - int button_press_event(); - int button_release_event(); - int cursor_motion_event(); - int input_to_pixel(float input); - - int operation; - enum - { - NONE, - DRAG_INPUT, - DRAG_MIN_OUTPUT, - DRAG_MAX_OUTPUT, - }; - int is_input; - HistogramMain *plugin; - HistogramWindow *gui; -}; - -class HistogramAuto : public BC_CheckBox -{ -public: - HistogramAuto(HistogramMain *plugin, - int x, - int y); - int handle_event(); - HistogramMain *plugin; -}; - -class HistogramSplit : public BC_CheckBox -{ -public: - HistogramSplit(HistogramMain *plugin, - int x, - int y); - int handle_event(); - HistogramMain *plugin; -}; - -class HistogramMode : public BC_Radial -{ -public: - HistogramMode(HistogramMain *plugin, - int x, - int y, - int value, - char *text); - int handle_event(); - HistogramMain *plugin; - int value; -}; - -class HistogramReset : public BC_GenericButton -{ -public: - HistogramReset(HistogramMain *plugin, - int x, - int y); - int handle_event(); - HistogramMain *plugin; -}; - - -class HistogramOutputText : public BC_TumbleTextBox -{ -public: - HistogramOutputText(HistogramMain *plugin, - HistogramWindow *gui, - int x, - int y, - float *output); - int handle_event(); - HistogramMain *plugin; - float *output; -}; - -class HistogramInputText : public BC_TumbleTextBox -{ -public: - HistogramInputText(HistogramMain *plugin, - HistogramWindow *gui, - int x, - int y, - int do_x); - - int handle_event(); - void update(); - - HistogramMain *plugin; - HistogramWindow *gui; - int do_x; -}; - -class HistogramCanvas : public BC_SubWindow -{ -public: - HistogramCanvas(HistogramMain *plugin, - HistogramWindow *gui, - int x, - int y, - int w, - int h); - int button_press_event(); - int cursor_motion_event(); - int button_release_event(); - HistogramMain *plugin; - HistogramWindow *gui; -}; - -class HistogramWindow : public BC_Window -{ -public: - HistogramWindow(HistogramMain *plugin, int x, int y); - ~HistogramWindow(); - - void create_objects(); - int close_event(); - void update(int do_input); - void update_mode(); - void update_canvas(); - void draw_canvas_overlay(); - void update_input(); - void update_output(); - int keypress_event(); - - HistogramSlider *output; - HistogramAuto *automatic; - HistogramSplit *split; - HistogramSmoothMode *smoothModeChoser; - HistogramMode *mode_v, *mode_r, *mode_g, *mode_b /*, *mode_a */; - HistogramOutputText *output_min; - HistogramOutputText *output_max; - HistogramOutputText *threshold; - HistogramInputText *input_x; - HistogramInputText *input_y; - HistogramCanvas *canvas; - HistogramMain *plugin; - int canvas_w; - int canvas_h; - int title1_x; - int title2_x; - int title3_x; - int title4_x; - BC_Pixmap *max_picon, *mid_picon, *min_picon; -}; - - - -PLUGIN_THREAD_HEADER(HistogramMain, HistogramThread, HistogramWindow) - - - - -#endif diff --git a/cinelerra-5.0/plugins/histogram_bezier/histogramwindow.inc b/cinelerra-5.0/plugins/histogram_bezier/histogramwindow.inc deleted file mode 100644 index cc9e1137..00000000 --- a/cinelerra-5.0/plugins/histogram_bezier/histogramwindow.inc +++ /dev/null @@ -1,28 +0,0 @@ - -/* - * CINELERRA - * Copyright (C) 2008 Adam Williams - * - * 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 - * - */ - -#ifndef HISTOGRAMWINDOW_INC -#define HISTOGRAMWINDOW_INC - -class HistogramWindow; -class HistogramThread; - -#endif