AtmoCalculations.cpp
上传用户:kjfoods
上传日期:2020-07-06
资源大小:29949k
文件大小:14k
源码类别:

midi

开发平台:

Unix_Linux

  1. /*
  2.  * calculations.c: calculations needed by the input devices
  3.  *
  4.  * See the README file for copyright information and how to reach the author.
  5.  *
  6.  * $Id: b8d4443b42e01a3be04810c934561a99b260bba1 $
  7.  */
  8. #include <stdlib.h>
  9. #include <string.h>
  10. #include "AtmoDefs.h"
  11. #include "AtmoCalculations.h"
  12. #include "AtmoConfig.h"
  13. #include "AtmoZoneDefinition.h"
  14. // set accuracy of color calculation
  15. #define h_MAX   255
  16. #define s_MAX   255
  17. #define v_MAX   255
  18. // macros
  19. #define MIN(X, Y)  ((X) < (Y) ? (X) : (Y))
  20. #define MAX(X, Y)  ((X) > (Y) ? (X) : (Y))
  21. #define POS_DIV(a, b)  ( (a)/(b) + ( ((a)%(b) >= (b)/2 ) ? 1 : 0) )
  22. tColorPacket CalcColorsAnalyzeHSV(CAtmoConfig *pAtmoConfig, tHSVColor *HSV_Img)
  23. {
  24.   int i; // counter
  25.   // static tWeightPacket Weight[IMAGE_SIZE];
  26.   // Flip instead having a array with (64x48) entries of values for each channel
  27.   // I have x arrays of 64x48 so each channel has its own array...
  28.   // (or gradient which is use to judge about the pixels)
  29.   static int Weight[ATMO_NUM_CHANNELS][IMAGE_SIZE];
  30.   /***************************************************************************/
  31.   /* Weight                                                                  */
  32.   /***************************************************************************/
  33.   static int LastEdgeWeighting = -1;
  34.   static int LastWidescreenMode = -1;
  35.   int AtmoSetup_EdgeWeighting  = pAtmoConfig->getLiveView_EdgeWeighting();
  36.   int AtmoSetup_WidescreenMode = pAtmoConfig->getLiveView_WidescreenMode();
  37.   int AtmoSetup_DarknessLimit  = pAtmoConfig->getLiveView_DarknessLimit();
  38.   int AtmoSetup_BrightCorrect  = pAtmoConfig->getLiveView_BrightCorrect();
  39.   int AtmoSetup_SatWinSize     = pAtmoConfig->getLiveView_SatWinSize();
  40.   // calculate only if setup has changed
  41.   if ((AtmoSetup_EdgeWeighting != LastEdgeWeighting) ||
  42.       (AtmoSetup_WidescreenMode != LastWidescreenMode))
  43.   {
  44.      for(i =0 ;i < ATMO_NUM_CHANNELS; i++)
  45.          pAtmoConfig->getZoneDefinition(i)->UpdateWeighting(&Weight[i][0],
  46.                                                             AtmoSetup_WidescreenMode,
  47.                                                             AtmoSetup_EdgeWeighting);
  48.     /*
  49.     original code from VDR sources... my one is just more flexible?*g*
  50.   i = 0;
  51.     for (int row = 0; row < CAP_HEIGHT; row++)
  52.     {
  53.   float row_norm = (float)row / ((float)CAP_HEIGHT - 1.0f);       // [0;Height] -> [0;1]
  54.   float weight_3 = pow(1.0f - row_norm, AtmoSetup_EdgeWeighting); // top
  55.   float weight_4 = pow(row_norm, AtmoSetup_EdgeWeighting);       // bottom
  56.       for (int column = 0; column < CAP_WIDTH; column++)
  57.       {
  58.         // if widescreen mode, top and bottom of the picture are not
  59.         if ((AtmoSetup_WidescreenMode == 1) && ((row <= CAP_HEIGHT/8) || (row >= (7*CAP_HEIGHT)/8)))
  60.         {
  61.           Weight[i].channel[0] = Weight[i].channel[1] = Weight[i].channel[2] = Weight[i].channel[3] = Weight[i].channel[4] = 0;
  62.         }
  63.         else
  64.         {
  65.           float column_norm = (float)column / ((float)CAP_WIDTH - 1.0f); // [0;Width] -> [0;1]
  66.   Weight[i].channel[0] = 255;
  67.   Weight[i].channel[1] = (int)(255.0 * (float)pow((1.0 - column_norm), AtmoSetup_EdgeWeighting));
  68.   Weight[i].channel[2] = (int)(255.0 * (float)pow(column_norm, AtmoSetup_EdgeWeighting));
  69.           Weight[i].channel[3] = (int)(255.0 * (float)weight_3);
  70.           Weight[i].channel[4] = (int)(255.0 * (float)weight_4);
  71.         }
  72.         i++;
  73.       }
  74.     }
  75.     */
  76. LastEdgeWeighting = AtmoSetup_EdgeWeighting;
  77.     LastWidescreenMode = AtmoSetup_WidescreenMode;
  78.   }
  79.   /***************************************************************************/
  80.   /* Hue                                                                     */
  81.   /***************************************************************************/
  82.   /*----------------------------*/
  83.   /* hue histogram builtup      */
  84.   /*----------------------------*/
  85.   // HSV histogram
  86.   long int hue_hist[ATMO_NUM_CHANNELS][h_MAX+1];
  87.   // clean histogram
  88.   memset(&hue_hist, 0, sizeof(hue_hist));
  89.   i = 0;
  90.   for (int row = 0; row < CAP_HEIGHT; row++)
  91.   {
  92.     for (int column = 0; column < CAP_WIDTH; column++)
  93.     {
  94.       // forget black bars: perform calculations only if pixel has some luminosity
  95.   if (HSV_Img[i].v > 10*AtmoSetup_DarknessLimit)
  96.       {
  97.         // builtup histogram for the 5 channels
  98.         for (int channel = 0; channel < ATMO_NUM_CHANNELS; channel++)
  99.         {
  100.           // Add weight to channel
  101.           hue_hist[channel][HSV_Img[i].h] += Weight[channel][i] * HSV_Img[i].v;
  102.         }
  103.       }
  104.       i++;
  105.     }
  106.   }
  107.   /*----------------------------*/
  108.   /* hue histogram windowing    */
  109.   /*----------------------------*/
  110.   // windowed HSV histogram
  111.   long int w_hue_hist[ATMO_NUM_CHANNELS][h_MAX+1];
  112.   // clean windowed histogram
  113.   memset(&w_hue_hist, 0, sizeof(w_hue_hist));
  114.   // steps in each direction; eg. 2 => -2 -1 0 1 2 windowing
  115.   int hue_windowsize = pAtmoConfig->getLiveView_HueWinSize();
  116.   for (i = 0; i < h_MAX+1; i++) // walk through histogram [0;h_MAX]
  117.   {
  118.     // windowing from -hue_windowsize -> +hue_windowsize
  119.     for (int mywin = -hue_windowsize; mywin < hue_windowsize+1; mywin++)
  120.     {
  121.       // adressed histogram candlestick
  122.       int myidx = i + mywin;
  123.       // handle beginning of windowing -> roll back
  124.       if (myidx < 0)     { myidx = myidx + h_MAX + 1; }
  125.       // handle end of windowing -> roll forward
  126.       if (myidx > h_MAX) { myidx = myidx - h_MAX - 1; }
  127.       // Apply windowing to all 5 channels
  128.       for (int channel = 0; channel < ATMO_NUM_CHANNELS; channel++)
  129.       {
  130.         // apply lite triangular window design with gradient of 10% per discrete step
  131.         w_hue_hist[channel][i] += hue_hist[channel][myidx] * ((hue_windowsize+1)-abs(mywin)); // apply window
  132.       }
  133.     }
  134.   }
  135.   /*--------------------------------------*/
  136.   /* analyze histogram for most used hue  */
  137.   /*--------------------------------------*/
  138.   // index of last maximum
  139.   static int most_used_hue_last[ATMO_NUM_CHANNELS] = {0, 0, 0, 0, 0};
  140.   // resulting hue for each channel
  141.   int most_used_hue[ATMO_NUM_CHANNELS];
  142.   memset(&most_used_hue, 0, sizeof(most_used_hue));
  143.   for (int channel = 0; channel < ATMO_NUM_CHANNELS; channel++)
  144.   {
  145.     int value = 0;
  146.     for (i = 0; i < h_MAX+1; i++) // walk through histogram
  147.     {
  148.       if (w_hue_hist[channel][i] > value) // if new value bigger then old one
  149.       {
  150.         most_used_hue[channel] = i;     // remember index
  151.         value = w_hue_hist[channel][i]; // and value
  152.       }
  153.     }
  154.     float percent = (float)w_hue_hist[channel][most_used_hue_last[channel]] / (float)value;
  155.     if (percent > 0.93f) // less than 7% difference?
  156.     {
  157.       most_used_hue[channel] = most_used_hue_last[channel]; // use last index
  158.     }
  159.     most_used_hue_last[channel] = most_used_hue[channel]; // save current index of most used hue
  160.   }
  161.   /***************************************************************************/
  162.   /* saturation                                                              */
  163.   /***************************************************************************/
  164.   // sat histogram
  165.   long int sat_hist[ATMO_NUM_CHANNELS][s_MAX+1];
  166.   // hue of the pixel we are working at
  167.   int pixel_hue = 0;
  168.   // clean histogram
  169.   memset(&sat_hist, 0, sizeof(sat_hist));
  170.   /*--------------------------------------*/
  171.   /* saturation histogram builtup         */
  172.   /*--------------------------------------*/
  173.   i = 0;
  174.   for (int row = 0; row < CAP_HEIGHT; row++)
  175.   {
  176.     for (int column = 0; column < CAP_WIDTH; column++)
  177.     {
  178.       // forget black bars: perform calculations only if pixel has some luminosity
  179.   if (HSV_Img[i].v > 10*AtmoSetup_DarknessLimit)
  180.       {
  181.         // find histogram position for pixel
  182.         pixel_hue = HSV_Img[i].h;
  183.         // TODO:   brightness calculation(if we require it some time)
  184.         for (int channel = 0; channel < ATMO_NUM_CHANNELS; channel++)
  185.         {
  186.           // only use pixel for histogram if hue is near most_used_hue
  187.           if ((pixel_hue > most_used_hue[channel] - hue_windowsize) &&
  188.               (pixel_hue < most_used_hue[channel] + hue_windowsize))
  189.           {
  190.             // build histogram
  191.             // sat_hist[channel][HSV_Img[i].s] += Weight[i].channel[channel] * HSV_Img[i].v;
  192.             sat_hist[channel][HSV_Img[i].s] += Weight[channel][i] * HSV_Img[i].v;
  193.           }
  194.         }
  195.       }
  196.       i++;
  197.     }
  198.   }
  199.   /*--------------------------------------*/
  200.   /* saturation histogram windowing       */
  201.   /*--------------------------------------*/
  202.    // windowed HSV histogram
  203.    long int w_sat_hist[ATMO_NUM_CHANNELS][s_MAX+1];
  204.    // clean windowed histogram
  205.    memset(&w_sat_hist, 0, sizeof(w_sat_hist));
  206.    // steps in each direction; eg. 2 => -2 -1 0 1 2 windowing
  207.    int sat_windowsize = AtmoSetup_SatWinSize;
  208.    // walk through histogram [0;h_MAX]
  209.    for (i = 0; i < s_MAX + 1; i++)
  210.    {
  211.      // windowing from -hue_windowsize -> +hue_windowsize
  212.      for (int mywin = -sat_windowsize; mywin < sat_windowsize+1; mywin++)
  213.      {
  214.        // adressed histogram candlestick
  215.        int myidx = i + mywin;
  216.        // handle beginning of windowing -> roll back
  217.        if (myidx < 0)     { myidx = myidx + s_MAX + 1; }
  218.        // handle end of windowing -> roll forward
  219.        if (myidx > h_MAX) { myidx = myidx - s_MAX - 1; }
  220.        for (int channel = 0; channel < ATMO_NUM_CHANNELS; channel++)
  221.        {
  222.          /*
  223.             apply lite triangular window design with
  224.             gradient of 10% per discrete step
  225.          */
  226.          w_sat_hist[channel][i] += sat_hist[channel][myidx] *
  227.                                   ((sat_windowsize+1)-abs(mywin)); // apply window
  228.        }
  229.      }
  230.    }
  231.   /*--------------------------------------*/
  232.   /* analyze histogram for most used sat  */
  233.   /*--------------------------------------*/
  234.    // resulting sat (most_used_hue) for each channel
  235.   int most_used_sat[ATMO_NUM_CHANNELS];
  236.   memset(&most_used_sat, 0, sizeof(most_used_sat));
  237.   for (int channel = 0; channel < ATMO_NUM_CHANNELS; channel++)
  238.   {
  239.     int value = 0;
  240.     // walk trough histogram
  241.     for (i = 0; i < s_MAX+1; i++)
  242.     {
  243.       // if new value bigger then old one
  244.       if (w_sat_hist[channel][i] > value)
  245.       {
  246.         // remember index
  247.         most_used_sat[channel] = i;
  248.         // and value
  249.         value = w_sat_hist[channel][i];
  250.       }
  251.     }
  252.   }
  253.   /*----------------------------------------------------------*/
  254.   /* calculate average brightness within HSV image            */
  255.   /* uniform Brightness for all channels is calculated        */
  256.   /*----------------------------------------------------------*/
  257.   int l_counter = 0;
  258.   // average brightness (value)
  259.   long int value_avg = 0;
  260.   // TODO: extract into a function? in sat-histo-built
  261.   i = 0;
  262.   for (int row = 0; row < CAP_HEIGHT; row++)
  263.   {
  264.     for (int column = 0; column < CAP_WIDTH; column++)
  265.     {
  266.       // find average value: only use bright pixels for luminance average
  267.   if (HSV_Img[i].v > 10*AtmoSetup_DarknessLimit)
  268.       {
  269.         // build brightness average
  270.         value_avg += HSV_Img[i].v;
  271.         l_counter++;
  272.       }
  273.       i++;
  274.     }
  275.   }
  276.   // calculate brightness average
  277.   if (l_counter > 0) { value_avg = value_avg / l_counter; }
  278.     else { value_avg = 10 * AtmoSetup_DarknessLimit; }
  279.   /*----------------------------*/
  280.   /* adjust and copy results    */
  281.   /*----------------------------*/
  282.   tHSVColor hsv_pixel;
  283.   // storage container for resulting RGB values
  284.   tColorPacket ColorChannels;
  285.   for (int channel = 0; channel < ATMO_NUM_CHANNELS; channel++)
  286.   {
  287.     // copy values
  288.     hsv_pixel.h = most_used_hue[channel];
  289.     hsv_pixel.s = most_used_sat[channel];
  290.     // adjust brightness
  291.     int new_value = (int) ((float)value_avg * ((float)AtmoSetup_BrightCorrect / 100.0));
  292.     if (new_value > 255) { new_value = 255; } // ensure brightness isn't set too high
  293.     hsv_pixel.v = (unsigned char)new_value;
  294.     // convert back to rgb
  295.     ColorChannels.channel[channel] = HSV2RGB(hsv_pixel);
  296.   }
  297.   return ColorChannels;
  298. }
  299. tHSVColor RGB2HSV(tRGBColor color)
  300. {
  301.  int min, max, delta;
  302.  int r, g, b;
  303.  int h = 0;
  304.  tHSVColor hsv;
  305.  r = color.r;
  306.  g = color.g;
  307.  b = color.b;
  308.  min = MIN(MIN(r, g), b);
  309.  max = MAX(MAX(r, g), b);
  310.  delta = max - min;
  311.  hsv.v = (unsigned char) POS_DIV( max*v_MAX, 255 );
  312.  if (delta == 0) // This is a gray, no chroma...
  313.  {
  314.    h = 0;        // HSV results = 0 / 1
  315.    hsv.s = 0;
  316.  }
  317.  else // Chromatic data...
  318.  {
  319.    hsv.s = (unsigned char) POS_DIV( (delta*s_MAX) , max );
  320.    int dr = (max - r) + 3*delta;
  321.    int dg = (max - g) + 3*delta;
  322.    int db = (max - b) + 3*delta;
  323.    int divisor = 6*delta;
  324.    if (r == max)
  325.    {
  326.      h = POS_DIV(( (db - dg) * h_MAX ) , divisor);
  327.    }
  328.    else if (g == max)
  329.    {
  330.      h = POS_DIV( ((dr - db) * h_MAX) , divisor) + (h_MAX/3);
  331.    }
  332.    else if (b == max)
  333.    {
  334.      h = POS_DIV(( (dg - dr) * h_MAX) , divisor) + (h_MAX/3)*2;
  335.    }
  336.    if ( h < 0 )     { h += h_MAX; }
  337.    if ( h > h_MAX ) { h -= h_MAX; }
  338.  }
  339.  hsv.h = (unsigned char)h;
  340.  return hsv;
  341. }
  342. tRGBColor HSV2RGB(tHSVColor color)
  343. {
  344.  tRGBColor rgb = {0, 0, 0};
  345.  float h = (float)color.h/(float)h_MAX;
  346.  float s = (float)color.s/(float)s_MAX;
  347.  float v = (float)color.v/(float)v_MAX;
  348.  if (s == 0)
  349.  {
  350.    rgb.r = (int)((v*255.0)+0.5);
  351.    rgb.g = rgb.r;
  352.    rgb.b = rgb.r;
  353.  }
  354.  else
  355.  {
  356.    h = h * 6.0f;
  357.    if (h == 6.0) { h = 0.0; }
  358.    int i = (int)h;
  359.    float f = h - i;
  360.    float p = v*(1.0f-s);
  361.    float q = v*(1.0f-(s*f));
  362.    float t = v*(1.0f-(s*(1.0f-f)));
  363.    if (i == 0)
  364.    {
  365.      rgb.r = (int)((v*255.0)+0.5);
  366.      rgb.g = (int)((t*255.0)+0.5);
  367.      rgb.b = (int)((p*255.0)+0.5);
  368.    }
  369.    else if (i == 1)
  370.    {
  371.      rgb.r = (int)((q*255.0)+0.5);
  372.      rgb.g = (int)((v*255.0)+0.5);
  373.      rgb.b = (int)((p*255.0)+0.5);
  374.    }
  375.    else if (i == 2)
  376.    {
  377.      rgb.r = (int)((p*255.0)+0.5);
  378.      rgb.g = (int)((v*255.0)+0.5);
  379.      rgb.b = (int)((t*255.0)+0.5);
  380.    }
  381.    else if (i == 3)
  382.    {
  383.      rgb.r = (int)((p*255.0)+0.5);
  384.      rgb.g = (int)((q*255.0)+0.5);
  385.      rgb.b = (int)((v*255.0)+0.5);
  386.    }
  387.    else if (i == 4)
  388.    {
  389.      rgb.r = (int)((t*255.0)+0.5);
  390.      rgb.g = (int)((p*255.0)+0.5);
  391.      rgb.b = (int)((v*255.0)+0.5);
  392.    }
  393.    else
  394.    {
  395.      rgb.r = (int)((v*255.0)+0.5);
  396.      rgb.g = (int)((p*255.0)+0.5);
  397.      rgb.b = (int)((q*255.0)+0.5);
  398.    }
  399.  }
  400.  return rgb;
  401. }