Histogram

Source code

//=======================================================================
// Luminance and colors histograms.
// QUAGLIOZZI ERIC - © 2009   All rights reserved
//=======================================================================

/*
   Usable for low res (72 dpi) and double res (144 dpi) 
   bitmap  16 bit colors.
   ---------------------------------------------------------
   | Do not use with other resolutions, may system crash ! |
   ---------------------------------------------------------
*/



//--------------------------- Macros and constants ----------------------

#if defined(_MSC_VER)     // If compiling with VC++...

    #define private        static __inline
    #define longint        __int64
    
#elif defined(__GNUC__)  // If compiling with GCC...

    #define private        static inline
    #define longint        long long int
    
#else

    #error "Unknown Compiler!"
    
#endif

#define EndianSwap32(n) (((((unsigned long) n) << 24) & 0xFF000000) | \
                         ((((unsigned long) n) <<  8) & 0x00FF0000) | \
                         ((((unsigned long) n) >>  8) & 0x0000FF00) | \
                         ((((unsigned long) n) >> 24) & 0x000000FF))
                         

#define FixedPoint 12    // 12 bit fixed point operations: 20:12
#define ONEHALF 0x00800  // 0.5 , 12 bit fixed point

#define MAXGRAY    63 // 0x3F
#define TABLESIZE  64

// Luminance = 0.3R + 0.59G + 0.11B
#define Rc  0x04CD    // 0.3*4096 <=> 0.3 in 12 bit fixed point
#define Gc  0x0971    // 0.59*4096 <=> 0.59 in 12 bit fixed point
#define Bc  0x01C2    // 0.11*4096 <=> 0.11 in 12 bit fixed point


//--------------------------- Types ------------------------------------


typedef unsigned long Call68KFuncType(const void * emulStateP,
                                      unsigned long trapOrFunction,
                                      const void * argsOnStackP,
                                      unsigned long argsSizeAndwantA0);

typedef unsigned long NativeFuncType(const void * emulStateP,
                                     void * userData68KP,
                                     Call68KFuncType * call68KFuncP);

typedef struct {
    char hb_object_header[14];
    short swTransparent;
    unsigned char    * pData;
    short w;
    short wl;
    short h;
    short bitdepth;
    unsigned char swTranspColorH;
    unsigned char swTranspColorL;
    unsigned char swTranspIndex;
} ImageData;


typedef struct {
    long DATA[TABLESIZE];
} HistogramData;


typedef struct {
    char hb_object_header[14];
    short         DebugShort;
    long          maxL;               // max of luminance
    long          maxR;               // max of red
    long          maxG;               // max of green
    long          maxB;               // max of blue
    ImageData     * pSourceImage;     // source bitmap
    HistogramData * pHistoL;          // Luminance histogram
    HistogramData * pHistoR;          // red histogram
    HistogramData * pHistoG;          // green histogram
    HistogramData * pHistoB;          // blue histogram
} HISTOGRAM;    


typedef struct _ParamsType
  {
    HISTOGRAM       * pHist;
  } ParamsType;


//----------------------- Histogram Function ----------------------------


unsigned long FuncHistogram(const void * emulStateP, void * userData68KP,
                                           Call68KFuncType * call68KFuncP)
{
  ParamsType    * p;                  //pointer: params structure
  HISTOGRAM     * pHist;              //pointer: class structure

  unsigned char * Psource;
  unsigned int    w, h, wlimit;
  unsigned int    i, j, ir;
  long   Rs,Gs,Bs;
  long   Gray, coeff;
  long   RGB;

  // >>>>  Do local copy of params

  p=(ParamsType *) userData68KP;
  pHist = p->pHist;

  w = pHist->pSourceImage->w;
  h = pHist->pSourceImage->h;
  wlimit = pHist->pSourceImage->wl;
  Psource = pHist->pSourceImage->pData;
  
  //clear tables
  for (i=0;i<TABLESIZE;i++)
  { pHist->pHistoL->DATA[i]=0;
    pHist->pHistoR->DATA[i]=0;
    pHist->pHistoG->DATA[i]=0;
    pHist->pHistoB->DATA[i]=0;
  }
   
  for (j=0;j<h;j++)  
  {
     ir=0;
     for (i=0; i<w; i++)
     {
       // Get R & G & B of source in 16 bits colors
       RGB = (Psource[ir]<<8)|Psource[ir+1];
       Rs=(RGB >> 11) & 0x001F;
       Gs=(RGB >> 5) & 0x003F;
       Bs= RGB & 0x001F;
       // normalized to 5 bits (rgb 565)
       Gs = Gs >>1;
       // Gray = 0.3R + 0.59G + 0.11B
       Gray  = Rs * Rc;
       Gray += Gs * Gc;
       Gray += Bs * Bc;
       Gray = (Gray+ONEHALF)>>FixedPoint;
       if (Gray>MAXGRAY) Gray=MAXGRAY;
       //update histogram data
       pHist->pHistoL->DATA[Gray]++;
       pHist->pHistoR->DATA[Rs]++;
       pHist->pHistoG->DATA[Gs]++;
       pHist->pHistoB->DATA[Bs]++;
       ir +=2;
     }
     Psource+=wlimit;
  }
  
  //swap data to be directly readable with 68k proc.
  //and define max
  pHist->maxL = 0;
  pHist->maxR = 0;
  pHist->maxG = 0;
  pHist->maxB = 0;
  for (i=0;i<TABLESIZE;i++)
  { 
    if(pHist->pHistoL->DATA[i]>pHist->maxL)
       pHist->maxL = pHist->pHistoL->DATA[i];
    pHist->pHistoL->DATA[i]=EndianSwap32(pHist->pHistoL->DATA[i]);
    if(pHist->pHistoR->DATA[i]>pHist->maxR)
       pHist->maxR = pHist->pHistoR->DATA[i];
    pHist->pHistoR->DATA[i]=EndianSwap32(pHist->pHistoR->DATA[i]);
    if(pHist->pHistoG->DATA[i]>pHist->maxG)
       pHist->maxG = pHist->pHistoG->DATA[i];
    pHist->pHistoG->DATA[i]=EndianSwap32(pHist->pHistoG->DATA[i]);
    if(pHist->pHistoB->DATA[i]>pHist->maxB)
       pHist->maxB = pHist->pHistoB->DATA[i];
    pHist->pHistoB->DATA[i]=EndianSwap32(pHist->pHistoB->DATA[i]);
  }  
  pHist->maxL = EndianSwap32(pHist->maxL);
  pHist->maxR = EndianSwap32(pHist->maxR);
  pHist->maxG = EndianSwap32(pHist->maxG);
  pHist->maxB = EndianSwap32(pHist->maxB);
  return 0;
}

//========================================================================