/* * filter.c: Filter class for the Atmolight-plugin * * See the README file for copyright information and how to reach the author. * * $Id$ */ #include #include #include #include "math.h" #include "defs.h" #include "setup.h" #include "filter.h" // --- cAtmoFilter----------------------------------------------------------- cAtmoFilter::cAtmoFilter() { // Initialization ResetFilter(); } cAtmoFilter::~cAtmoFilter() { } void cAtmoFilter::ResetFilter(void) { // reset filter values MeanFilter(true); PercentFilter(true); } tColorPacket cAtmoFilter::Filtering(tColorPacket ColorPacket) { filter_input = ColorPacket; // apply filter switch (AtmoSetup.Filter_Mode) { case combined: MeanFilter(false); break; case percent: PercentFilter(false); break; case no_filter: default: filter_output = filter_input; break; } return filter_output; } void cAtmoFilter::PercentFilter(bool init) { static tColorPacket filter_output_old; // needed for the percentage filter if (init) // Initialization { memset(&filter_output_old, 0, sizeof(filter_output_old)); return; } for (int ch = 0; ch < 5; ch++) { filter_output.channel[ch].r = (filter_input.channel[ch].r * (100-AtmoSetup.Filter_PercentNew) + filter_output_old.channel[ch].r * AtmoSetup.Filter_PercentNew) / 100; filter_output.channel[ch].g = (filter_input.channel[ch].g * (100-AtmoSetup.Filter_PercentNew) + filter_output_old.channel[ch].g * AtmoSetup.Filter_PercentNew) / 100; filter_output.channel[ch].b = (filter_input.channel[ch].b * (100-AtmoSetup.Filter_PercentNew) + filter_output_old.channel[ch].b * AtmoSetup.Filter_PercentNew) / 100; } filter_output_old = filter_output; } void cAtmoFilter::MeanFilter(bool init) { static tColorPacketLongInt mean_sums; // needed vor the running mean value filter static tColorPacket mean_values; static tColorPacket filter_output_old; // needed for the percentage filter static int filter_length_old; char reinitialize = 0; if (init) // Initialization { memset(&filter_output_old, 0, sizeof(filter_output_old)); memset(&mean_sums, 0, sizeof(mean_sums)); memset(&mean_values, 0, sizeof(mean_values)); return; } if (filter_length_old != AtmoSetup.Filter_MeanLength) // if filter_length has changed { reinitialize = 1; // force reinitialization of the filter } filter_length_old = AtmoSetup.Filter_MeanLength; if (filter_length_old < 20) filter_length_old = 20; // avoid division by 0 for (int ch = 0; ch < 5; ch++) { // calculate the mean-value filters mean_sums.channel[ch].r += (long int)(filter_input.channel[ch].r - mean_values.channel[ch].r); // red mean_values.channel[ch].r = mean_sums.channel[ch].r / ((long int)filter_length_old / 20); mean_sums.channel[ch].g += (long int)(filter_input.channel[ch].g - mean_values.channel[ch].g); // green mean_values.channel[ch].g = mean_sums.channel[ch].g / ((long int)filter_length_old / 20); mean_sums.channel[ch].b += (long int)(filter_input.channel[ch].b - mean_values.channel[ch].b); // blue mean_values.channel[ch].b = mean_sums.channel[ch].b / ((long int)filter_length_old / 20); // check, if there is a jump -> check if differences between actual values and filter values are too big long int dist; // distance between the two colors in the 3D RGB space dist = (mean_values.channel[ch].r - filter_input.channel[ch].r)*(mean_values.channel[ch].r - filter_input.channel[ch].r)+ (mean_values.channel[ch].g - filter_input.channel[ch].g)*(mean_values.channel[ch].g - filter_input.channel[ch].g)+ (mean_values.channel[ch].b - filter_input.channel[ch].b)*(mean_values.channel[ch].b - filter_input.channel[ch].b); if (dist > 0) { dist = (long int)sqrt((double)dist); } // avoid sqrt(0) (TODO: necessary?) // compare calculated distance with the filter threshold if ((dist > (long int)((double)AtmoSetup.Filter_MeanThreshold * 3.6f)) || ( reinitialize == 1)) { // filter jump detected -> set the long filters to the result of the short filters filter_output.channel[ch] = mean_values.channel[ch] = filter_input.channel[ch]; mean_sums.channel[ch].r = filter_input.channel[ch].r * (filter_length_old / 20); mean_sums.channel[ch].g = filter_input.channel[ch].g * (filter_length_old / 20); mean_sums.channel[ch].b = filter_input.channel[ch].b * (filter_length_old / 20); } else { // apply an additional percent filter and return calculated values filter_output.channel[ch].r = (mean_values.channel[ch].r * (100-AtmoSetup.Filter_PercentNew) + filter_output_old.channel[ch].r * AtmoSetup.Filter_PercentNew) / 100; filter_output.channel[ch].g = (mean_values.channel[ch].g * (100-AtmoSetup.Filter_PercentNew) + filter_output_old.channel[ch].g * AtmoSetup.Filter_PercentNew) / 100; filter_output.channel[ch].b = (mean_values.channel[ch].b * (100-AtmoSetup.Filter_PercentNew) + filter_output_old.channel[ch].b * AtmoSetup.Filter_PercentNew) / 100; } } filter_output_old = filter_output; }