void CAtmoColorPicker::outputColor(int red,int green,int blue) { CAtmoConnection *pAtmoConnection = this->m_pAtmoDynData->getAtmoConnection(); CAtmoConfig *pAtmoConfig = this->m_pAtmoDynData->getAtmoConfig(); if((pAtmoConnection==NULL) || (pAtmoConnection->isOpen()==ATMO_FALSE)) return; pColorPacket packet; AllocColorPacket(packet, pAtmoConfig->getZoneCount()); for(int i=0;i<packet->numColors;i++) { packet->zone[i].r = red; packet->zone[i].g = green; packet->zone[i].b = blue; } if(pAtmoConfig->isUseSoftwareWhiteAdj()) packet = CAtmoTools::WhiteCalibration(pAtmoConfig, packet); packet = CAtmoTools::ApplyGamma(pAtmoConfig, packet); pAtmoConnection->SendData( packet ); delete (char *)packet; }
void CAtmoTools::ShowShutdownColor(CAtmoDynData *pDynData) { pDynData->LockCriticalSection(); CAtmoConnection *atmoConnection = pDynData->getAtmoConnection(); CAtmoConfig *atmoConfig = pDynData->getAtmoConfig(); if((atmoConnection != NULL) && (atmoConfig!=NULL) && atmoConfig->isSetShutdownColor()) { int i; pColorPacket packet; AllocColorPacket(packet, atmoConfig->getZoneCount()); // set a special color? on shutdown of the software? mostly may use black or so ... // if this function ist disabled ... atmo will continuing to show the last color... for(i = 0; i < packet->numColors; i++) { packet->zone[i].r = atmoConfig->getShutdownColor_Red(); packet->zone[i].g = atmoConfig->getShutdownColor_Green(); packet->zone[i].b = atmoConfig->getShutdownColor_Blue(); } packet = CAtmoTools::ApplyGamma(atmoConfig, packet); if(atmoConfig->isUseSoftwareWhiteAdj()) packet = CAtmoTools::WhiteCalibration(atmoConfig, packet); atmoConnection->SendData(packet); delete (char *)packet; } pDynData->UnLockCriticalSection(); }
STDMETHODIMP CAtmoRemoteControlImplEx::setStaticColor(BYTE red, BYTE green, BYTE blue) { m_pAtmoDynData->LockCriticalSection(); CAtmoConnection *connection = this->m_pAtmoDynData->getAtmoConnection(); if((connection!=NULL) && (connection->isOpen())) { CAtmoConfig *pConfig = m_pAtmoDynData->getAtmoConfig(); pColorPacket newColors; int zoneCount = pConfig->getZoneCount(); AllocColorPacket(newColors, zoneCount); for(int i=0;i<zoneCount;i++) { newColors->zone[i].r = red; newColors->zone[i].g = green; newColors->zone[i].b = blue; } newColors = CAtmoTools::ApplyGamma(pConfig, newColors); if(pConfig->isUseSoftwareWhiteAdj()) newColors = CAtmoTools::WhiteCalibration(pConfig, newColors); connection->SendData(newColors); delete (char *)newColors; } this->m_pAtmoDynData->UnLockCriticalSection(); return S_OK; }
pColorPacket CAtmoOutputFilter::PercentFilter(pColorPacket filter_input, ATMO_BOOL init) { // last values needed for the percentage filter if (init) // Initialization { if(m_percent_filter_output_old) delete[] m_percent_filter_output_old; m_percent_filter_output_old = NULL; return(NULL); } if(!m_percent_filter_output_old || (m_percent_filter_output_old->numColors!=filter_input->numColors)) { delete[] m_percent_filter_output_old; AllocColorPacket(m_percent_filter_output_old, filter_input->numColors); ZeroColorPacket(m_percent_filter_output_old); } int percentNew = this->m_pAtmoConfig->getLiveViewFilter_PercentNew(); pColorPacket filter_output; AllocColorPacket(filter_output, filter_input->numColors); for (int zone = 0; zone < filter_input->numColors; zone++) { filter_output->zone[zone].r = (filter_input->zone[zone].r * (100-percentNew) + m_percent_filter_output_old->zone[zone].r * percentNew) / 100; filter_output->zone[zone].g = (filter_input->zone[zone].g * (100-percentNew) + m_percent_filter_output_old->zone[zone].g * percentNew) / 100; filter_output->zone[zone].b = (filter_input->zone[zone].b * (100-percentNew) + m_percent_filter_output_old->zone[zone].b * percentNew) / 100; } CopyColorPacket( filter_output, m_percent_filter_output_old ); delete[] filter_input; return filter_output; }
pColorPacket CAtmoOutputFilter::MeanFilter(pColorPacket filter_input, ATMO_BOOL init) { // needed vor the running mean value filter // needed for the percentage filter static int filter_length_old; char reinitialize = 0; long int tmp; pColorPacket filter_output; if (init) // Initialization { if(m_mean_filter_output_old) delete[] m_mean_filter_output_old; m_mean_filter_output_old = NULL; if(m_mean_values) delete[] m_mean_values; m_mean_values = NULL; if(m_mean_sums) delete[] m_mean_sums; m_mean_sums = NULL; return (NULL); } if(!m_mean_filter_output_old || (m_mean_filter_output_old->numColors!=filter_input->numColors)) { delete[] m_mean_filter_output_old; AllocColorPacket(m_mean_filter_output_old, filter_input->numColors); ZeroColorPacket(m_mean_filter_output_old); } if(!m_mean_values || (m_mean_values->numColors!=filter_input->numColors)) { delete[] m_mean_values; AllocColorPacket(m_mean_values, filter_input->numColors); ZeroColorPacket(m_mean_values); } if(!m_mean_sums || (m_mean_sums->numColors!=filter_input->numColors)) { delete[] m_mean_sums; AllocLongColorPacket(m_mean_sums, filter_input->numColors); ZeroLongColorPacket(m_mean_sums); } AllocColorPacket(filter_output, filter_input->numColors); int AtmoSetup_Filter_MeanLength = m_pAtmoConfig->getLiveViewFilter_MeanLength(); int AtmoSetup_Filter_PercentNew = m_pAtmoConfig->getLiveViewFilter_PercentNew(); int AtmoSetup_Filter_MeanThreshold = m_pAtmoConfig->getLiveViewFilter_MeanThreshold(); // if filter_length has changed if (filter_length_old != AtmoSetup_Filter_MeanLength) { // force reinitialization of the filter reinitialize = 1; } filter_length_old = AtmoSetup_Filter_MeanLength; if (filter_length_old < 20) filter_length_old = 20; // avoid division by 0 for (int zone = 0; zone < filter_input->numColors; zone++) { // calculate the mean-value filters m_mean_sums->longZone[zone].r += (long int)(filter_input->zone[zone].r - m_mean_values->zone[zone].r); // red tmp = m_mean_sums->longZone[zone].r / ((long int)filter_length_old / 20); if(tmp<0) tmp = 0; else { if(tmp>255) tmp = 255; } m_mean_values->zone[zone].r = (unsigned char)tmp; m_mean_sums->longZone[zone].g += (long int)(filter_input->zone[zone].g - m_mean_values->zone[zone].g); // green tmp = m_mean_sums->longZone[zone].g / ((long int)filter_length_old / 20); if(tmp<0) tmp = 0; else { if(tmp>255) tmp = 255; } m_mean_values->zone[zone].g = (unsigned char)tmp; m_mean_sums->longZone[zone].b += (long int)(filter_input->zone[zone].b - m_mean_values->zone[zone].b); // blue tmp = m_mean_sums->longZone[zone].b / ((long int)filter_length_old / 20); if(tmp<0) tmp = 0; else { if(tmp>255) tmp = 255; } m_mean_values->zone[zone].b = (unsigned char)tmp; // 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 = (m_mean_values->zone[zone].r - filter_input->zone[zone].r) * (m_mean_values->zone[zone].r - filter_input->zone[zone].r) + (m_mean_values->zone[zone].g - filter_input->zone[zone].g) * (m_mean_values->zone[zone].g - filter_input->zone[zone].g) + (m_mean_values->zone[zone].b - filter_input->zone[zone].b) * (m_mean_values->zone[zone].b - filter_input->zone[zone].b); /* if (dist > 0) { dist = (long int)sqrt((double)dist); } avoid sqrt(0) (TODO: necessary?) I think its cheaper to calculate the square of something ..? insteas geting the square root? */ double distMean = ((double)AtmoSetup_Filter_MeanThreshold * 3.6f); distMean = distMean * distMean; /* compare calculated distance with the filter threshold if ((dist > (long int)((double)AtmoSetup.Filter_MeanThreshold * 3.6f)) || ( reinitialize == 1)) */ if ((dist > distMean) || ( reinitialize == 1)) { // filter jump detected -> set the long filters to the result of the short filters filter_output->zone[zone] = m_mean_values->zone[zone] = filter_input->zone[zone]; m_mean_sums->longZone[zone].r = filter_input->zone[zone].r * (filter_length_old / 20); m_mean_sums->longZone[zone].g = filter_input->zone[zone].g * (filter_length_old / 20); m_mean_sums->longZone[zone].b = filter_input->zone[zone].b * (filter_length_old / 20); } else { // apply an additional percent filter and return calculated values filter_output->zone[zone].r = (m_mean_values->zone[zone].r * (100-AtmoSetup_Filter_PercentNew) + m_mean_filter_output_old->zone[zone].r * AtmoSetup_Filter_PercentNew) / 100; filter_output->zone[zone].g = (m_mean_values->zone[zone].g * (100-AtmoSetup_Filter_PercentNew) + m_mean_filter_output_old->zone[zone].g * AtmoSetup_Filter_PercentNew) / 100; filter_output->zone[zone].b = (m_mean_values->zone[zone].b * (100-AtmoSetup_Filter_PercentNew) + m_mean_filter_output_old->zone[zone].b * AtmoSetup_Filter_PercentNew) / 100; } } CopyColorPacket(filter_output, m_mean_filter_output_old); delete[] filter_input; return(filter_output); }
EffectMode CAtmoTools::SwitchEffect(CAtmoDynData *pDynData, EffectMode newEffectMode) { // may need a critical section?? if(pDynData == NULL) { return emUndefined; } pDynData->LockCriticalSection(); CAtmoConfig *atmoConfig = pDynData->getAtmoConfig(); if(atmoConfig == NULL) { pDynData->UnLockCriticalSection(); return emUndefined; } CAtmoConnection *atmoConnection = pDynData->getAtmoConnection(); EffectMode oldEffectMode = atmoConfig->getEffectMode(); CThread *currentEffect = pDynData->getEffectThread(); CAtmoInput *currentInput = pDynData->getLiveInput(); CAtmoPacketQueue *currentPacketQueue = pDynData->getLivePacketQueue(); if(oldEffectMode == emLivePicture) { /* in case of disabling the live mode first we have to stop the input then the effect thread! */ if(currentInput != NULL) { pDynData->setLiveInput( NULL ); currentInput->Close(); delete currentInput; currentInput = NULL; } } // stop and delete/cleanup current Effect Thread... pDynData->setEffectThread( NULL ); if(currentEffect != NULL) { currentEffect->Terminate(); delete currentEffect; currentEffect = NULL; } if(oldEffectMode == emLivePicture) { /* and last we kill the PacketQueue used for communication between the threads */ pDynData->setLivePacketQueue( NULL ); delete currentPacketQueue; currentPacketQueue = NULL; } if((atmoConnection!=NULL) && (atmoConnection->isOpen()==ATMO_TRUE)) { // neuen EffectThread nur mit aktiver Connection starten... switch(newEffectMode) { case emUndefined: // do nothing also in that case (avoid compiler warning) break; case emDisabled: { // get values from config - and put them to all channels? pColorPacket packet; AllocColorPacket(packet, atmoConfig->getZoneCount()); for(int i=0; i < packet->numColors; i++) { packet->zone[i].r = 0; packet->zone[i].g = 0; packet->zone[i].b = 0; } atmoConnection->SendData( packet ); atmoConnection->SendData( packet ); delete (char *)packet; break; } case emStaticColor: { // get values from config - and put them to all channels? pColorPacket packet; AllocColorPacket(packet, atmoConfig->getZoneCount()); for(int i=0; i < packet->numColors; i++){ packet->zone[i].r = atmoConfig->getStaticColor_Red(); packet->zone[i].g = atmoConfig->getStaticColor_Green(); packet->zone[i].b = atmoConfig->getStaticColor_Blue(); } packet = CAtmoTools::ApplyGamma( atmoConfig, packet ); if(atmoConfig->isUseSoftwareWhiteAdj()) packet = CAtmoTools::WhiteCalibration(atmoConfig, packet); atmoConnection->SendData( packet ); atmoConnection->SendData( packet ); delete (char *)packet; break; } case emLivePicture: { currentEffect = new CAtmoLiveView(pDynData); #if !defined(_ATMO_VLC_PLUGIN_) CAtmoPacketQueueStatus *packetMon = NULL; if(atmoConfig->getShow_statistics()) { packetMon = new CAtmoPacketQueueStatus(pDynData->getAppHinstance(), (HWND)NULL); packetMon->createWindow(); packetMon->showWindow(SW_SHOW); } currentPacketQueue = new CAtmoPacketQueue(packetMon); pDynData->setLivePictureSource(lpsScreenCapture); //Atmo liveview option GDi <Win7 / DekstopDuplication >Win8 int AtmoSetup_Mode = atmoConfig->getLiveView_Mode(); if (AtmoSetup_Mode == 1) { currentInput = new CAtmoDesktopDuplicationCaptureInput( pDynData ); } else { currentInput = new CAtmoGdiDisplayCaptureInput( pDynData ); } #else currentPacketQueue = new CAtmoPacketQueue(); pDynData->setLivePictureSource(lpsExtern); currentInput = new CAtmoExternalCaptureInput( pDynData ); #endif break; } #if !defined(_ATMO_VLC_PLUGIN_) case emColorChange: currentEffect = new CAtmoColorChanger(atmoConnection, atmoConfig); break; case emLrColorChange: currentEffect = new CAtmoLeftRightColorChanger(atmoConnection, atmoConfig); break; #endif } } atmoConfig->setEffectMode( newEffectMode ); pDynData->setLivePacketQueue( currentPacketQueue ); pDynData->setEffectThread( currentEffect ); pDynData->setLiveInput( currentInput ); if(currentEffect != NULL) currentEffect->Run(); if(currentInput != NULL) currentInput->Open(); pDynData->UnLockCriticalSection(); return oldEffectMode; }
pColorPacket CAtmoColorCalculator::AnalyzeHSV(tHSVColor *HSV_Img) { int i; // counter int AtmoSetup_EdgeWeighting = m_pAtmoConfig->getLiveView_EdgeWeighting(); int AtmoSetup_WidescreenMode = m_pAtmoConfig->getLiveView_WidescreenMode(); int AtmoSetup_DarknessLimit = m_pAtmoConfig->getLiveView_DarknessLimit(); int AtmoSetup_BrightCorrect = m_pAtmoConfig->getLiveView_BrightCorrect(); int AtmoSetup_SatWinSize = m_pAtmoConfig->getLiveView_SatWinSize(); int AtmoSetup_NumZones = m_pAtmoConfig->getZoneCount(); tHSVColor *temp_Img; if(AtmoSetup_NumZones != m_LastNumZones) { delete[] m_Weight; delete[] m_hue_hist; delete[] m_windowed_hue_hist; delete[] m_most_used_hue_last; delete[] m_most_used_hue; delete[] m_sat_hist; delete[] m_windowed_sat_hist; delete[] m_most_used_sat; delete[] m_Zone_Weights; delete[] m_average_v; delete[] m_average_counter; m_Weight = new int[AtmoSetup_NumZones * IMAGE_SIZE]; m_Zone_Weights = new int*[AtmoSetup_NumZones]; for(int i = 0; i < AtmoSetup_NumZones; i++) m_Zone_Weights[i] = &m_Weight[i * IMAGE_SIZE]; m_hue_hist = new long int[(h_MAX+1) * AtmoSetup_NumZones]; m_windowed_hue_hist = new long int[(h_MAX+1) * AtmoSetup_NumZones]; m_most_used_hue_last = new int[AtmoSetup_NumZones]; m_most_used_hue = new int[AtmoSetup_NumZones]; memset( m_most_used_hue_last, 0, sizeof(int) * AtmoSetup_NumZones); m_sat_hist = new long int[(s_MAX+1) * AtmoSetup_NumZones]; m_windowed_sat_hist = new long int[(s_MAX+1) * AtmoSetup_NumZones]; m_most_used_sat = new int[AtmoSetup_NumZones]; m_average_v = new long int[AtmoSetup_NumZones]; m_average_counter = new int[AtmoSetup_NumZones]; m_LastNumZones = AtmoSetup_NumZones; } // calculate only if setup has changed if ((AtmoSetup_EdgeWeighting != m_LastEdgeWeighting) || (AtmoSetup_WidescreenMode != m_LastWidescreenMode) || (m_pAtmoConfig->getZonesTopCount() != m_LastLayout_TopCount) || (m_pAtmoConfig->getZonesBottomCount() != m_LastLayout_BottomCount) || (m_pAtmoConfig->getZonesLRCount() != m_LastLayout_LRCount) || (m_pAtmoConfig->m_UpdateEdgeWeightningFlag != 0) ) { for(i = 0 ;i < AtmoSetup_NumZones; i++) { CAtmoZoneDefinition *pZoneDef = m_pAtmoConfig->getZoneDefinition(i); if(pZoneDef) { pZoneDef->UpdateWeighting(m_Zone_Weights[i], AtmoSetup_WidescreenMode, AtmoSetup_EdgeWeighting); #ifdef _debug_zone_weight_ char filename[128]; sprintf(filename, "zone_%d_gradient_debug.bmp",i); pZoneDef->SaveZoneBitmap( filename ); sprintf(filename, "zone_%d_weight_%d_debug.bmp",i,AtmoSetup_EdgeWeighting); pZoneDef->SaveWeightBitmap(filename, m_Zone_Weights[i] ); #endif } } m_pAtmoConfig->m_UpdateEdgeWeightningFlag = 0; m_LastEdgeWeighting = AtmoSetup_EdgeWeighting; m_LastWidescreenMode = AtmoSetup_WidescreenMode; m_LastLayout_TopCount = m_pAtmoConfig->getZonesTopCount(); m_LastLayout_BottomCount = m_pAtmoConfig->getZonesBottomCount(); m_LastLayout_LRCount = m_pAtmoConfig->getZonesLRCount(); } AtmoSetup_DarknessLimit = AtmoSetup_DarknessLimit * 10; /***************************************************************************/ /* Hue */ /***************************************************************************/ /*----------------------------*/ /* hue histogram builtup */ /*----------------------------*/ // HSV histogram // long int hue_hist[CAP_MAX_NUM_ZONES][h_MAX+1]; // average brightness (value) // m_average_v m_average_counter // clean histogram --> calloc memset(m_hue_hist, 0, sizeof(long int) * (h_MAX+1) * AtmoSetup_NumZones); memset(m_average_v, 0, sizeof(long int) * AtmoSetup_NumZones); memset(m_average_counter, 0, sizeof(int) * AtmoSetup_NumZones); temp_Img = HSV_Img; i = 0; for (int row = 0; row < CAP_HEIGHT; row++) { for (int column = 0; column < CAP_WIDTH; column++) { // forget black bars: perform calculations only if pixel has some luminosity if ((*temp_Img).v > AtmoSetup_DarknessLimit) { // builtup histogram for the x Zones of the Display for (int zone = 0; zone < AtmoSetup_NumZones; zone++) { // Add weight to channel // Weight(zone, pixel_nummer) m_Weight[((zone) * (IMAGE_SIZE)) + (pixel_nummer)] // m_hue_hist[zone*(h_MAX+1) + HSV_Img[i].h] += m_Zone_Weights[zone][i] * HSV_Img[i].v; m_hue_hist[zone*(h_MAX+1) + (*temp_Img).h] += m_Zone_Weights[zone][i] * temp_Img->v; if(m_Zone_Weights[zone][i] > 0) { m_average_v[zone] += temp_Img->v; m_average_counter[zone]++; } } // calculate brightness average } temp_Img++; i++; } } /*----------------------------*/ /* hue histogram windowing */ /*----------------------------*/ // windowed HSV histogram // long int w_hue_hist[CAP_MAX_NUM_ZONES][h_MAX+1]; -> m_windowed_hue_hist // clean windowed histogram memset(m_windowed_hue_hist, 0, sizeof(long int) * (h_MAX+1) * AtmoSetup_NumZones); // steps in each direction; eg. 2 => -2 -1 0 1 2 windowing int hue_windowsize = m_pAtmoConfig->getLiveView_HueWinSize(); for (i = 0; i < h_MAX+1; i++) // walk through histogram [0;h_MAX] { // windowing from -hue_windowsize -> +hue_windowsize for (int mywin = -hue_windowsize; mywin < hue_windowsize+1; mywin++) { // addressed histogram candlestick int myidx = i + mywin; // handle beginning of windowing -> roll back if (myidx < 0) { myidx = myidx + h_MAX + 1; } // handle end of windowing -> roll forward if (myidx > h_MAX) { myidx = myidx - h_MAX - 1; } // Apply windowing to all x zones for (int zone = 0; zone < AtmoSetup_NumZones; zone++) { // apply lite triangular window design with gradient of 10% per discrete step m_windowed_hue_hist[(zone * (h_MAX+1)) + i] += m_hue_hist[(zone * (h_MAX+1)) + myidx] * ((hue_windowsize+1)-abs(mywin)); // apply window } } } /*--------------------------------------*/ /* analyze histogram for most used hue */ /*--------------------------------------*/ // index of last maximum // static int most_used_hue_last[CAP_MAX_NUM_ZONES] = {0, 0, 0, 0, 0}; --> m_most_used_hue_last // resulting hue for each channel //int most_used_hue[CAP_MAX_NUM_ZONES]; --> m_most_used_hue FindMostUsed(AtmoSetup_NumZones, m_most_used_hue, m_windowed_hue_hist); for (int zone = 0; zone < AtmoSetup_NumZones; zone++) { float percent = (float)m_windowed_hue_hist[zone * (h_MAX+1) + m_most_used_hue_last[zone]] / (float)m_windowed_hue_hist[zone * (h_MAX+1) + m_most_used_hue[zone]]; if (percent > 0.93f) // less than 7% difference? m_most_used_hue[zone] = m_most_used_hue_last[zone]; // use last index else m_most_used_hue_last[zone] = m_most_used_hue[zone]; } /* memset(m_most_used_hue, 0, sizeof(int) * AtmoSetup_NumZones); for (int zone = 0; zone < AtmoSetup_NumZones; zone++) { long int value = 0; for (i = 0; i < h_MAX+1; i++) // walk through histogram { long int tmp = m_windowed_hue_hist[ (zone * (h_MAX+1)) + i ]; if (tmp > value) // if new value bigger then old one { m_most_used_hue[zone] = i; // remember index value = tmp; // w_hue_hist[zone][i]; // and value } } float percent = (float)m_windowed_hue_hist[zone * (h_MAX+1) + m_most_used_hue_last[zone]] / (float)value; if (percent > 0.93f) // less than 7% difference? { m_most_used_hue[zone] = m_most_used_hue_last[zone]; // use last index } m_most_used_hue_last[zone] = m_most_used_hue[zone]; // save current index of most used hue } */ /***************************************************************************/ /* saturation */ /***************************************************************************/ // sat histogram // long int sat_hist[CAP_MAX_NUM_ZONES][s_MAX+1]; -> m_sat_hist // hue of the pixel we are working at int pixel_hue = 0; // clean histogram memset(m_sat_hist, 0, sizeof(long int) * (s_MAX+1) * AtmoSetup_NumZones); /*--------------------------------------*/ /* saturation histogram builtup */ /*--------------------------------------*/ i = 0; temp_Img = HSV_Img; for (int row = 0; row < CAP_HEIGHT; row++) { for (int column = 0; column < CAP_WIDTH; column++) { // forget black bars: perform calculations only if pixel has some luminosity if ((*temp_Img).v > AtmoSetup_DarknessLimit) { // find histogram position for pixel pixel_hue = (*temp_Img).h; // TODO: brightness calculation(if we require it some time) for (int zone = 0; zone < AtmoSetup_NumZones; zone++) { // only use pixel for histogram if hue is near most_used_hue if ((pixel_hue > m_most_used_hue[zone] - hue_windowsize) && (pixel_hue < m_most_used_hue[zone] + hue_windowsize)) { // build histogram // sat_hist[channel][HSV_Img[i].s] += Weight[i].channel[channel] * HSV_Img[i].v; m_sat_hist[zone * (s_MAX+1) + (*temp_Img).s ] += m_Zone_Weights[zone][i] * (*temp_Img).v; } } } i++; temp_Img++; } } /*--------------------------------------*/ /* saturation histogram windowing */ /*--------------------------------------*/ // windowed HSV histogram // long int w_sat_hist[CAP_MAX_NUM_ZONES][s_MAX+1]; --> m_windowed_sat_hist // clean windowed histogram memset(m_windowed_sat_hist, 0, sizeof(long int) * (s_MAX+1) * AtmoSetup_NumZones); // steps in each direction; eg. 2 => -2 -1 0 1 2 windowing int sat_windowsize = AtmoSetup_SatWinSize; // walk through histogram [0;h_MAX] for (i = 0; i < s_MAX + 1; i++) { // windowing from -hue_windowsize -> +hue_windowsize for (int mywin = -sat_windowsize; mywin < sat_windowsize+1; mywin++) { // addressed histogram candlestick int myidx = i + mywin; // handle beginning of windowing -> roll back if (myidx < 0) { myidx = myidx + s_MAX + 1; } // handle end of windowing -> roll forward if (myidx > h_MAX) { myidx = myidx - s_MAX - 1; } for (int zone = 0; zone < AtmoSetup_NumZones; zone++) { /* apply lite triangular window design with gradient of 10% per discrete step */ /* w_sat_hist[channel][i] += sat_hist[channel][myidx] * ((sat_windowsize+1)-abs(mywin)); // apply window */ m_windowed_sat_hist[zone * (s_MAX+1) + i] += m_sat_hist[zone* (h_MAX+1) + myidx] * ((sat_windowsize+1)-abs(mywin)); // apply window } } } /*--------------------------------------*/ /* analyze histogram for most used sat */ /*--------------------------------------*/ // resulting sat (most_used_hue) for each channel // int most_used_sat[CAP_MAX_NUM_ZONES];->m_most_used_sat FindMostUsed(AtmoSetup_NumZones, m_most_used_sat, m_windowed_sat_hist); /* memset(m_most_used_sat, 0, sizeof(int) * AtmoSetup_NumZones); for (int zone = 0; zone < AtmoSetup_NumZones; zone++) { int value = 0; // walk trough histogram for (i = 0; i < s_MAX+1; i++) { // if new value bigger then old one int tmp = m_windowed_sat_hist[zone * (s_MAX+1) + i]; // if (w_sat_hist[channel][i] > value) if (tmp > value) { // remember index m_most_used_sat[zone] = i; // and value value = tmp; } } } */ /*----------------------------------------------------------*/ /* calculate average brightness within HSV image */ /* uniform Brightness for all channels is calculated */ /*----------------------------------------------------------*/ /* code integrated into "hue histogram builtup" to save some looping time! int l_counter = 0; // average brightness (value) long int value_avg = 0; i = 0; for (int row = 0; row < CAP_HEIGHT; row++) { for (int column = 0; column < CAP_WIDTH; column++) { // find average value: only use bright pixels for luminance average if (HSV_Img[i].v > AtmoSetup_DarknessLimit) { // build brightness average value_avg += HSV_Img[i].v; l_counter++; } i++; } } // calculate brightness average if (l_counter > 0) { value_avg = value_avg / l_counter; } else { value_avg = AtmoSetup_DarknessLimit; } */ /*----------------------------*/ /* adjust and copy results */ /*----------------------------*/ tHSVColor hsv_pixel; // storage container for resulting RGB values pColorPacket output_colors; AllocColorPacket(output_colors, AtmoSetup_NumZones); // adjust brightness // int new_value = (int) ((float)value_avg * ((float)AtmoSetup_BrightCorrect / 100.0)); // if (new_value > 255) new_value = 255; // ensure brightness isn't set too high // hsv_pixel.v = (unsigned char)new_value; /* // calculate brightness average for(int zone = 0; zone < AtmoSetup_NumZones; zone++) { if(m_average_counter[zone] > 0) m_average_v[zone] = m_average_v[zone] / m_average_counter[zone] else m_average_v[zone] = AtmoSetup_DarknessLimit; } */ for (int zone = 0; zone < AtmoSetup_NumZones; zone++) { if(m_average_counter[zone] > 0) m_average_v[zone] = m_average_v[zone] / m_average_counter[zone]; else m_average_v[zone] = AtmoSetup_DarknessLimit; m_average_v[zone] = (int)((float)m_average_v[zone] * ((float)AtmoSetup_BrightCorrect / 100.0)); hsv_pixel.v = (unsigned char)ATMO_MAX(ATMO_MIN(m_average_v[zone],255),0); hsv_pixel.h = m_most_used_hue[zone]; hsv_pixel.s = m_most_used_sat[zone]; // convert back to rgb output_colors->zone[zone] = HSV2RGB(hsv_pixel); } return output_colors; }
void CAtmoBasicEffect::Interpolation(int iSteps, int iPause, pColorPacket fadeTo) { int s_1; // zählvariablen int s_2; pColorPacket ausgabe; pColorPacket output; // Stepsize for each fading step float *interpolation_r = new float[fadeTo->numColors]; // Differenz zw. 2 R/G/B werten zur Interpolation float *interpolation_g = new float[fadeTo->numColors]; float *interpolation_b = new float[fadeTo->numColors]; if(!m_RGB_alt || (m_RGB_alt->numColors != fadeTo->numColors) ) { delete (char *)m_RGB_alt; m_RGB_alt=NULL; for ( s_1 = 0; s_1 < fadeTo->numColors ; s_1++ ) { interpolation_r[s_1] = (float)(fadeTo->zone[s_1].r) / (float)iSteps; interpolation_g[s_1] = (float)(fadeTo->zone[s_1].g) / (float)iSteps; interpolation_b[s_1] = (float)(fadeTo->zone[s_1].b) / (float)iSteps; } } else { for ( s_1 = 0; s_1 < fadeTo->numColors ; s_1++ ) { interpolation_r[s_1] = (float)(fadeTo->zone[s_1].r - m_RGB_alt->zone[s_1].r) / (float)iSteps; interpolation_g[s_1] = (float)(fadeTo->zone[s_1].g - m_RGB_alt->zone[s_1].g) / (float)iSteps; interpolation_b[s_1] = (float)(fadeTo->zone[s_1].b - m_RGB_alt->zone[s_1].b) / (float)iSteps; } } AllocColorPacket(ausgabe, fadeTo->numColors); // fading... color... for ( s_2 = 1; s_2<=iSteps ; s_2++ ) // anfang interpolation und ausgabe { if(m_RGB_alt) { for(int zone = 0; zone<fadeTo->numColors; zone++) { ausgabe->zone[zone].r = m_RGB_alt->zone[zone].r + (int)((float)s_2 * interpolation_r[zone]); ausgabe->zone[zone].g = m_RGB_alt->zone[zone].g + (int)((float)s_2 * interpolation_g[zone]); ausgabe->zone[zone].b = m_RGB_alt->zone[zone].b + (int)((float)s_2 * interpolation_b[zone]); } } else { for(int zone = 0; zone<fadeTo->numColors; zone++) { ausgabe->zone[zone].r = (int)((float)s_2 * interpolation_r[zone]); ausgabe->zone[zone].g = (int)((float)s_2 * interpolation_g[zone]); ausgabe->zone[zone].b = (int)((float)s_2 * interpolation_b[zone]); } } DupColorPacket(output, ausgabe); output = CAtmoTools::ApplyGamma(m_AtmoConfig, output); if(m_AtmoConfig->isUseSoftwareWhiteAdj()) output = CAtmoTools::WhiteCalibration(m_AtmoConfig, output); m_AtmoConnection->SendData(output); delete (char *)output; if(ThreadSleep(iPause) == ATMO_FALSE) break; } // save last color as start color for next run delete (char *)m_RGB_alt; delete []interpolation_r; delete []interpolation_g; delete []interpolation_b; m_RGB_alt = ausgabe; }