2 * AtmoOutputFilter.cpp: Post Processor for the color data retrieved from
5 * mostly 1:1 from vdr-linux-src "filter.c" copied
7 * See the README.txt file for copyright information and how to reach the author(s).
17 #include "AtmoOutputFilter.h"
21 CAtmoOutputFilter::CAtmoOutputFilter(CAtmoConfig *atmoConfig )
23 this->m_pAtmoConfig = atmoConfig;
24 this->m_percent_filter_output_old = NULL;
25 this->m_mean_filter_output_old = NULL;
26 this->m_mean_values = NULL;
27 this->m_mean_sums = NULL;
31 CAtmoOutputFilter::~CAtmoOutputFilter(void)
33 if(m_percent_filter_output_old)
34 delete (char *)m_percent_filter_output_old;
36 if(m_mean_filter_output_old)
37 delete (char *)m_mean_filter_output_old;
40 delete (char *)m_mean_values;
43 delete (char *)m_mean_sums;
46 void CAtmoOutputFilter::ResetFilter(void)
48 // reset filter values
49 MeanFilter(NULL, true);
50 PercentFilter(NULL, true);
53 pColorPacket CAtmoOutputFilter::Filtering(pColorPacket ColorPacket)
55 switch (m_pAtmoConfig->getLiveViewFilterMode())
62 return MeanFilter(ColorPacket, false);
66 return PercentFilter(ColorPacket, false);
73 pColorPacket CAtmoOutputFilter::PercentFilter(pColorPacket filter_input, ATMO_BOOL init)
75 // last values needed for the percentage filter
76 if (init) // Initialization
78 if(m_percent_filter_output_old)
79 delete (char *)m_percent_filter_output_old;
80 m_percent_filter_output_old = NULL;
84 if(!m_percent_filter_output_old || (m_percent_filter_output_old->numColors!=filter_input->numColors)) {
85 delete m_percent_filter_output_old;
86 AllocColorPacket(m_percent_filter_output_old, filter_input->numColors);
87 ZeroColorPacket(m_percent_filter_output_old);
90 int percentNew = this->m_pAtmoConfig->getLiveViewFilter_PercentNew();
92 pColorPacket filter_output;
93 AllocColorPacket(filter_output, filter_input->numColors);
95 for (int zone = 0; zone < filter_input->numColors; zone++)
97 filter_output->zone[zone].r = (filter_input->zone[zone].r *
98 (100-percentNew) + m_percent_filter_output_old->zone[zone].r * percentNew) / 100;
100 filter_output->zone[zone].g = (filter_input->zone[zone].g *
101 (100-percentNew) + m_percent_filter_output_old->zone[zone].g * percentNew) / 100;
103 filter_output->zone[zone].b = (filter_input->zone[zone].b *
104 (100-percentNew) + m_percent_filter_output_old->zone[zone].b * percentNew) / 100;
107 CopyColorPacket( filter_output, m_percent_filter_output_old );
109 delete (char *)filter_input;
111 return filter_output;
114 pColorPacket CAtmoOutputFilter::MeanFilter(pColorPacket filter_input, ATMO_BOOL init)
116 // needed vor the running mean value filter
118 // needed for the percentage filter
119 static int filter_length_old;
120 char reinitialize = 0;
122 pColorPacket filter_output;
124 if (init) // Initialization
126 if(m_mean_filter_output_old)
127 delete (char *)m_mean_filter_output_old;
128 m_mean_filter_output_old = NULL;
131 delete (char *)m_mean_values;
132 m_mean_values = NULL;
135 delete (char *)m_mean_sums;
140 if(!m_mean_filter_output_old || (m_mean_filter_output_old->numColors!=filter_input->numColors)) {
141 delete m_mean_filter_output_old;
142 AllocColorPacket(m_mean_filter_output_old, filter_input->numColors);
143 ZeroColorPacket(m_mean_filter_output_old);
146 if(!m_mean_values || (m_mean_values->numColors!=filter_input->numColors)) {
147 delete m_mean_values;
148 AllocColorPacket(m_mean_values, filter_input->numColors);
149 ZeroColorPacket(m_mean_values);
152 if(!m_mean_sums || (m_mean_sums->numColors!=filter_input->numColors)) {
154 AllocLongColorPacket(m_mean_sums, filter_input->numColors);
155 ZeroLongColorPacket(m_mean_sums);
158 AllocColorPacket(filter_output, filter_input->numColors);
161 int AtmoSetup_Filter_MeanLength = m_pAtmoConfig->getLiveViewFilter_MeanLength();
162 int AtmoSetup_Filter_PercentNew = m_pAtmoConfig->getLiveViewFilter_PercentNew();
163 int AtmoSetup_Filter_MeanThreshold = m_pAtmoConfig->getLiveViewFilter_MeanThreshold();
165 // if filter_length has changed
166 if (filter_length_old != AtmoSetup_Filter_MeanLength)
168 // force reinitialization of the filter
171 filter_length_old = AtmoSetup_Filter_MeanLength;
173 if (filter_length_old < 20) filter_length_old = 20; // avoid division by 0
175 for (int zone = 0; zone < filter_input->numColors; zone++)
177 // calculate the mean-value filters
178 m_mean_sums->longZone[zone].r +=
179 (long int)(filter_input->zone[zone].r - m_mean_values->zone[zone].r); // red
180 tmp = m_mean_sums->longZone[zone].r / ((long int)filter_length_old / 20);
181 if(tmp<0) tmp = 0; else { if(tmp>255) tmp = 255; }
182 m_mean_values->zone[zone].r = (unsigned char)tmp;
184 m_mean_sums->longZone[zone].g +=
185 (long int)(filter_input->zone[zone].g - m_mean_values->zone[zone].g); // green
186 tmp = m_mean_sums->longZone[zone].g / ((long int)filter_length_old / 20);
187 if(tmp<0) tmp = 0; else { if(tmp>255) tmp = 255; }
188 m_mean_values->zone[zone].g = (unsigned char)tmp;
190 m_mean_sums->longZone[zone].b +=
191 (long int)(filter_input->zone[zone].b - m_mean_values->zone[zone].b); // blue
192 tmp = m_mean_sums->longZone[zone].b / ((long int)filter_length_old / 20);
193 if(tmp<0) tmp = 0; else { if(tmp>255) tmp = 255; }
194 m_mean_values->zone[zone].b = (unsigned char)tmp;
196 // check, if there is a jump -> check if differences between actual values and filter values are too big
198 long int dist; // distance between the two colors in the 3D RGB space
199 dist = (m_mean_values->zone[zone].r - filter_input->zone[zone].r) *
200 (m_mean_values->zone[zone].r - filter_input->zone[zone].r) +
201 (m_mean_values->zone[zone].g - filter_input->zone[zone].g) *
202 (m_mean_values->zone[zone].g - filter_input->zone[zone].g) +
203 (m_mean_values->zone[zone].b - filter_input->zone[zone].b) *
204 (m_mean_values->zone[zone].b - filter_input->zone[zone].b);
207 if (dist > 0) { dist = (long int)sqrt((double)dist); }
208 avoid sqrt(0) (TODO: necessary?)
209 I think its cheaper to calculate the square of something ..? insteas geting the square root?
211 double distMean = ((double)AtmoSetup_Filter_MeanThreshold * 3.6f);
212 distMean = distMean * distMean;
215 compare calculated distance with the filter threshold
216 if ((dist > (long int)((double)AtmoSetup.Filter_MeanThreshold * 3.6f)) || ( reinitialize == 1))
219 if ((dist > distMean) || ( reinitialize == 1))
221 // filter jump detected -> set the long filters to the result of the short filters
222 filter_output->zone[zone] = m_mean_values->zone[zone] = filter_input->zone[zone];
224 m_mean_sums->longZone[zone].r = filter_input->zone[zone].r *
225 (filter_length_old / 20);
226 m_mean_sums->longZone[zone].g = filter_input->zone[zone].g *
227 (filter_length_old / 20);
228 m_mean_sums->longZone[zone].b = filter_input->zone[zone].b *
229 (filter_length_old / 20);
233 // apply an additional percent filter and return calculated values
235 filter_output->zone[zone].r = (m_mean_values->zone[zone].r *
236 (100-AtmoSetup_Filter_PercentNew) +
237 m_mean_filter_output_old->zone[zone].r * AtmoSetup_Filter_PercentNew) / 100;
239 filter_output->zone[zone].g = (m_mean_values->zone[zone].g *
240 (100-AtmoSetup_Filter_PercentNew) +
241 m_mean_filter_output_old->zone[zone].g * AtmoSetup_Filter_PercentNew) / 100;
243 filter_output->zone[zone].b = (m_mean_values->zone[zone].b *
244 (100-AtmoSetup_Filter_PercentNew) +
245 m_mean_filter_output_old->zone[zone].b * AtmoSetup_Filter_PercentNew) / 100;
249 CopyColorPacket(filter_output, m_mean_filter_output_old);
251 delete (char *)filter_input;
253 return(filter_output);