⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 atmocalculations.cpp

📁 VLC Player Source Code
💻 CPP
字号:
/* * calculations.c: calculations needed by the input devices * * See the README file for copyright information and how to reach the author. * * $Id$ */#include <stdlib.h>#include <string.h>#include "AtmoDefs.h"#include "AtmoCalculations.h"#include "AtmoConfig.h"#include "AtmoZoneDefinition.h"// set accuracy of color calculation#define h_MAX   255#define s_MAX   255#define v_MAX   255// macros#define MIN(X, Y)  ((X) < (Y) ? (X) : (Y))#define MAX(X, Y)  ((X) > (Y) ? (X) : (Y))#define POS_DIV(a, b)  ( (a)/(b) + ( ((a)%(b) >= (b)/2 ) ? 1 : 0) )tColorPacket CalcColorsAnalyzeHSV(CAtmoConfig *pAtmoConfig, tHSVColor *HSV_Img){  int i; // counter  // static tWeightPacket Weight[IMAGE_SIZE];  // Flip instead having a array with (64x48) entries of values for each channel  // I have x arrays of 64x48 so each channel has its own array...  // (or gradient which is use to judge about the pixels)  static int Weight[ATMO_NUM_CHANNELS][IMAGE_SIZE];  /***************************************************************************/  /* Weight                                                                  */  /***************************************************************************/  static int LastEdgeWeighting = -1;  static int LastWidescreenMode = -1;  int AtmoSetup_EdgeWeighting  = pAtmoConfig->getLiveView_EdgeWeighting();  int AtmoSetup_WidescreenMode = pAtmoConfig->getLiveView_WidescreenMode();  int AtmoSetup_DarknessLimit  = pAtmoConfig->getLiveView_DarknessLimit();  int AtmoSetup_BrightCorrect  = pAtmoConfig->getLiveView_BrightCorrect();  int AtmoSetup_SatWinSize     = pAtmoConfig->getLiveView_SatWinSize();  // calculate only if setup has changed  if ((AtmoSetup_EdgeWeighting != LastEdgeWeighting) ||      (AtmoSetup_WidescreenMode != LastWidescreenMode))  {     for(i =0 ;i < ATMO_NUM_CHANNELS; i++)         pAtmoConfig->getZoneDefinition(i)->UpdateWeighting(&Weight[i][0],                                                            AtmoSetup_WidescreenMode,                                                            AtmoSetup_EdgeWeighting);    /*    original code from VDR sources... my one is just more flexible?*g* 	i = 0;    for (int row = 0; row < CAP_HEIGHT; row++)    {	  float row_norm = (float)row / ((float)CAP_HEIGHT - 1.0f);       // [0;Height] -> [0;1]	  float weight_3 = pow(1.0f - row_norm, AtmoSetup_EdgeWeighting); // top	  float weight_4 = pow(row_norm, AtmoSetup_EdgeWeighting);       // bottom      for (int column = 0; column < CAP_WIDTH; column++)      {        // if widescreen mode, top and bottom of the picture are not        if ((AtmoSetup_WidescreenMode == 1) && ((row <= CAP_HEIGHT/8) || (row >= (7*CAP_HEIGHT)/8)))        {          Weight[i].channel[0] = Weight[i].channel[1] = Weight[i].channel[2] = Weight[i].channel[3] = Weight[i].channel[4] = 0;        }        else        {          float column_norm = (float)column / ((float)CAP_WIDTH - 1.0f); // [0;Width] -> [0;1]		  Weight[i].channel[0] = 255;		  Weight[i].channel[1] = (int)(255.0 * (float)pow((1.0 - column_norm), AtmoSetup_EdgeWeighting));		  Weight[i].channel[2] = (int)(255.0 * (float)pow(column_norm, AtmoSetup_EdgeWeighting));          Weight[i].channel[3] = (int)(255.0 * (float)weight_3);          Weight[i].channel[4] = (int)(255.0 * (float)weight_4);        }        i++;      }    }    */	LastEdgeWeighting = AtmoSetup_EdgeWeighting;    LastWidescreenMode = AtmoSetup_WidescreenMode;  }  /***************************************************************************/  /* Hue                                                                     */  /***************************************************************************/  /*----------------------------*/  /* hue histogram builtup      */  /*----------------------------*/  // HSV histogram  long int hue_hist[ATMO_NUM_CHANNELS][h_MAX+1];  // clean histogram  memset(&hue_hist, 0, sizeof(hue_hist));  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 (HSV_Img[i].v > 10*AtmoSetup_DarknessLimit)      {        // builtup histogram for the 5 channels        for (int channel = 0; channel < ATMO_NUM_CHANNELS; channel++)        {          // Add weight to channel          hue_hist[channel][HSV_Img[i].h] += Weight[channel][i] * HSV_Img[i].v;        }      }      i++;    }  }  /*----------------------------*/  /* hue histogram windowing    */  /*----------------------------*/  // windowed HSV histogram  long int w_hue_hist[ATMO_NUM_CHANNELS][h_MAX+1];  // clean windowed histogram  memset(&w_hue_hist, 0, sizeof(w_hue_hist));  // steps in each direction; eg. 2 => -2 -1 0 1 2 windowing  int hue_windowsize = 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++)    {      // adressed 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 5 channels      for (int channel = 0; channel < ATMO_NUM_CHANNELS; channel++)      {        // apply lite triangular window design with gradient of 10% per discrete step        w_hue_hist[channel][i] += hue_hist[channel][myidx] * ((hue_windowsize+1)-abs(mywin)); // apply window      }    }  }  /*--------------------------------------*/  /* analyze histogram for most used hue  */  /*--------------------------------------*/  // index of last maximum  static int most_used_hue_last[ATMO_NUM_CHANNELS] = {0, 0, 0, 0, 0};  // resulting hue for each channel  int most_used_hue[ATMO_NUM_CHANNELS];  memset(&most_used_hue, 0, sizeof(most_used_hue));  for (int channel = 0; channel < ATMO_NUM_CHANNELS; channel++)  {    int value = 0;    for (i = 0; i < h_MAX+1; i++) // walk through histogram    {      if (w_hue_hist[channel][i] > value) // if new value bigger then old one      {        most_used_hue[channel] = i;     // remember index        value = w_hue_hist[channel][i]; // and value      }    }    float percent = (float)w_hue_hist[channel][most_used_hue_last[channel]] / (float)value;    if (percent > 0.93f) // less than 7% difference?    {      most_used_hue[channel] = most_used_hue_last[channel]; // use last index    }    most_used_hue_last[channel] = most_used_hue[channel]; // save current index of most used hue  }  /***************************************************************************/  /* saturation                                                              */  /***************************************************************************/  // sat histogram  long int sat_hist[ATMO_NUM_CHANNELS][s_MAX+1];  // hue of the pixel we are working at  int pixel_hue = 0;  // clean histogram  memset(&sat_hist, 0, sizeof(sat_hist));  /*--------------------------------------*/  /* saturation histogram builtup         */  /*--------------------------------------*/  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 (HSV_Img[i].v > 10*AtmoSetup_DarknessLimit)      {        // find histogram position for pixel        pixel_hue = HSV_Img[i].h;        // TODO:   brightness calculation(if we require it some time)        for (int channel = 0; channel < ATMO_NUM_CHANNELS; channel++)        {          // only use pixel for histogram if hue is near most_used_hue          if ((pixel_hue > most_used_hue[channel] - hue_windowsize) &&              (pixel_hue < most_used_hue[channel] + hue_windowsize))          {            // build histogram            // sat_hist[channel][HSV_Img[i].s] += Weight[i].channel[channel] * HSV_Img[i].v;            sat_hist[channel][HSV_Img[i].s] += Weight[channel][i] * HSV_Img[i].v;          }        }      }      i++;    }  }  /*--------------------------------------*/  /* saturation histogram windowing       */  /*--------------------------------------*/   // windowed HSV histogram   long int w_sat_hist[ATMO_NUM_CHANNELS][s_MAX+1];   // clean windowed histogram   memset(&w_sat_hist, 0, sizeof(w_sat_hist));   // 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++)     {       // adressed 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 channel = 0; channel < ATMO_NUM_CHANNELS; channel++)       {         /*            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       }     }   }  /*--------------------------------------*/  /* analyze histogram for most used sat  */  /*--------------------------------------*/   // resulting sat (most_used_hue) for each channel  int most_used_sat[ATMO_NUM_CHANNELS];  memset(&most_used_sat, 0, sizeof(most_used_sat));  for (int channel = 0; channel < ATMO_NUM_CHANNELS; channel++)  {    int value = 0;    // walk trough histogram    for (i = 0; i < s_MAX+1; i++)    {      // if new value bigger then old one      if (w_sat_hist[channel][i] > value)      {        // remember index        most_used_sat[channel] = i;        // and value        value = w_sat_hist[channel][i];      }    }  }  /*----------------------------------------------------------*/  /* calculate average brightness within HSV image            */  /* uniform Brightness for all channels is calculated        */  /*----------------------------------------------------------*/  int l_counter = 0;  // average brightness (value)  long int value_avg = 0;  // TODO: extract into a function? in sat-histo-built  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 > 10*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 = 10 * AtmoSetup_DarknessLimit; }  /*----------------------------*/  /* adjust and copy results    */  /*----------------------------*/  tHSVColor hsv_pixel;  // storage container for resulting RGB values  tColorPacket ColorChannels;  for (int channel = 0; channel < ATMO_NUM_CHANNELS; channel++)  {    // copy values    hsv_pixel.h = most_used_hue[channel];    hsv_pixel.s = most_used_sat[channel];    // 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;    // convert back to rgb    ColorChannels.channel[channel] = HSV2RGB(hsv_pixel);  }  return ColorChannels;}tHSVColor RGB2HSV(tRGBColor color){ int min, max, delta; int r, g, b; int h = 0; tHSVColor hsv; r = color.r; g = color.g; b = color.b; min = MIN(MIN(r, g), b); max = MAX(MAX(r, g), b); delta = max - min; hsv.v = (unsigned char) POS_DIV( max*v_MAX, 255 ); if (delta == 0) // This is a gray, no chroma... {   h = 0;        // HSV results = 0 / 1   hsv.s = 0; } else // Chromatic data... {   hsv.s = (unsigned char) POS_DIV( (delta*s_MAX) , max );   int dr = (max - r) + 3*delta;   int dg = (max - g) + 3*delta;   int db = (max - b) + 3*delta;   int divisor = 6*delta;   if (r == max)   {     h = POS_DIV(( (db - dg) * h_MAX ) , divisor);   }   else if (g == max)   {     h = POS_DIV( ((dr - db) * h_MAX) , divisor) + (h_MAX/3);   }   else if (b == max)   {     h = POS_DIV(( (dg - dr) * h_MAX) , divisor) + (h_MAX/3)*2;   }   if ( h < 0 )     { h += h_MAX; }   if ( h > h_MAX ) { h -= h_MAX; } } hsv.h = (unsigned char)h; return hsv;}tRGBColor HSV2RGB(tHSVColor color){ tRGBColor rgb = {0, 0, 0}; float h = (float)color.h/(float)h_MAX; float s = (float)color.s/(float)s_MAX; float v = (float)color.v/(float)v_MAX; if (s == 0) {   rgb.r = (int)((v*255.0)+0.5);   rgb.g = rgb.r;   rgb.b = rgb.r; } else {   h = h * 6.0f;   if (h == 6.0) { h = 0.0; }   int i = (int)h;   float f = h - i;   float p = v*(1.0f-s);   float q = v*(1.0f-(s*f));   float t = v*(1.0f-(s*(1.0f-f)));   if (i == 0)   {     rgb.r = (int)((v*255.0)+0.5);     rgb.g = (int)((t*255.0)+0.5);     rgb.b = (int)((p*255.0)+0.5);   }   else if (i == 1)   {     rgb.r = (int)((q*255.0)+0.5);     rgb.g = (int)((v*255.0)+0.5);     rgb.b = (int)((p*255.0)+0.5);   }   else if (i == 2)   {     rgb.r = (int)((p*255.0)+0.5);     rgb.g = (int)((v*255.0)+0.5);     rgb.b = (int)((t*255.0)+0.5);   }   else if (i == 3)   {     rgb.r = (int)((p*255.0)+0.5);     rgb.g = (int)((q*255.0)+0.5);     rgb.b = (int)((v*255.0)+0.5);   }   else if (i == 4)   {     rgb.r = (int)((t*255.0)+0.5);     rgb.g = (int)((p*255.0)+0.5);     rgb.b = (int)((v*255.0)+0.5);   }   else   {     rgb.r = (int)((v*255.0)+0.5);     rgb.g = (int)((p*255.0)+0.5);     rgb.b = (int)((q*255.0)+0.5);   } } return rgb;}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -