Blur filter

Source code

//=================================================================
//
// Enhanced BLUR Filter - QUAGLIOZZI ERIC
//
// © 2007 QUAGLIOZZI Eric
//
//=================================================================

/*
   Usable for low res (72 dpi) and double res (144 dpi) bitmap
   using 8 and 16 bits 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


//---------------- 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);


//RGB Palette Structure
typedef struct {
    unsigned char RGB4[1024];
} PalmOSPalette;    

//Inverse Palette Structure
typedef struct {
    unsigned char Index[216];
} PalmOSInverse;    

//Structure for Blur Effect
typedef struct
  {
    char hb_object_header[14];        //HB++ class header
    short             BlurKind;       //BlurKind (0= few blur, 1= more blur)
    unsigned char     * pSrc;         // bitmapsource  pointer
    unsigned char     * pBlur;        // buffer for blur filter  pointer
    PalmOSPalette     * pPal;         // pointrer to array of indexed colors
    PalmOSInverse     * pIndex;       // Fast RGB colors structure pointer
    short             BMPW;           // Real Width
    short             BMPH;           // Real Height
    short             bitdepth;       // bitdepth: 1=8 bit, 2=16 bit
  } BlurStruc;

  //global ARM structure access
typedef struct _ParamsType
  {
    BlurStruc    * pBLST;          //pointer to HB++ blur Structure
  }  ParamsType;


//--------- Extended Blur Filter Function -------------------------


unsigned long ExBlurFunc(const void * emulStateP, void * userData68KP,
                         Call68KFuncType * call68KFuncP)
{
  ParamsType    * p;                  //pointer to params structure
  BlurStruc     * pblst;
  unsigned char * src;
  unsigned char * blur;
  PalmOSPalette * Pal;
  PalmOSInverse * PalInv;
  
  unsigned char   * dest, * blur1,  * blur2, * blur3, * blurtemp;
  short    w, h, wl;
  short    i, j, id1;
  short    bitdepth;
  short    R,G,B;
  short    RGB,Denom,IDcol;


  // Do local copy of params
  p=(ParamsType *) userData68KP;
  pblst = p->pBLST;
  bitdepth=pblst->bitdepth;
  w=pblst->BMPW; wl=w<<(bitdepth-1); if(wl & 0x0001) wl++;
  h=pblst->BMPH; 
  src=pblst->pSrc; 
  blur=pblst->pBlur; 
  Pal=pblst->pPal;
  PalInv=pblst->pIndex;
  if(pblst->BlurKind ==0) Denom=4; else Denom=3;
  
  //perform a  kind of smooth blur...
  /* here static matrix :
         | 1 1 1 |               |1 1 1 |
         | 1 8 1 | * 1/16  or    |1 0 1 | * 1/8
         | 1 1 1 |               |1 1 1 |
  */         
  dest = blur;
  src=pblst->pSrc;
  //copy first 3 lines
  for(j=0;j<3;j++)
  { for(i=0; i<w; i++)
    {
      if(bitdepth==1)
      { // 256 colors
        dest[i]=src[i];
      }
      else
      { // 65536 colors
        id1 = i<<1;
        dest[id1]=src[id1]; 
        dest[id1+1]=src[id1+1]; 
      }
    }
    src  += wl;
    dest += wl;
  }
    
  //Apply filter matrix
  dest  = pblst->pSrc;
  blur1 = blur;
  blur2 = blur1 + wl;
  blur3 = blur2 + wl;

  //on first line
  if(bitdepth==1)
  { for(i=0;i<w;i++)
    {
      if(i<(w-1))
      { id1 = blur1[i+1]<<2;
        R=Pal->RGB4[id1+1]; G=Pal->RGB4[id1+2];  B=Pal->RGB4[id1+3];    
        id1 = blur2[i+1]<<2;
        R+=Pal->RGB4[id1+1]; G+=Pal->RGB4[id1+2]; B+=Pal->RGB4[id1+3];    
      }
      else
      { id1 = blur1[i-1]<<2; 
        R=Pal->RGB4[id1+1]; G=Pal->RGB4[id1+2]; B=Pal->RGB4[id1+3];    
        id1 = blur2[i-1]<<2;
        R+=Pal->RGB4[id1+1]; G+=Pal->RGB4[id1+2]; B+=Pal->RGB4[id1+3];    
      }
      id1 = blur1[i]<<2; 
      R+=Pal->RGB4[id1+1]; G+=Pal->RGB4[id1+2];  B+=Pal->RGB4[id1+3];    
      id1 = blur2[i]<<2; 
      R+=Pal->RGB4[id1+1]; G+=Pal->RGB4[id1+2];  B+=Pal->RGB4[id1+3];    
      R=R>>2;  G=G>>2;  B=B>>2;    
      R=(((R+26)<<2)+R+26)>>8;
      G=(((G+26)<<2)+G+26)>>8;  
      B=(((B+26)<<2)+B+26)>>8;           
      IDcol = (R<<5)+(R<<2)+(G<<2)+(G<<1)+B;
      dest[i]= (char)(PalInv->Index[IDcol]);  // copy new color;
    }
  }
  else
  { for(i=0;i<w;i++)
    {
      if(i<(w-1))
      { id1 = (i+1)<<1; 
        RGB = (blur1[id1]<<8) | blur1[id1+1];
        R=(RGB >> 11) & 0x001F;
        G=(RGB >> 5) & 0x003F;
        B= RGB & 0x001F;      
        RGB = (blur2[id1]<<8) | blur2[id1+1];
        R+=(RGB >> 11) & 0x001F;
        G+=(RGB >> 5) & 0x003F;
        B+= RGB & 0x001F;      
      }
      else
      { id1 = (i-1)<<1;
        RGB = (blur1[id1]<<8) | blur1[id1+1];
        R=(RGB >> 11) & 0x001F;
        G=(RGB >> 5) & 0x003F;
        B= RGB & 0x001F;      
        RGB = (blur2[id1]<<8) | blur2[id1+1];
        R+=(RGB >> 11) & 0x001F;
        G+=(RGB >> 5) & 0x003F;
        B+= RGB & 0x001F;      
      }
      id1 = i<<1;
      RGB = (blur1[id1]<<8) | blur1[id1+1];
      R+=(RGB >> 11) & 0x001F;
      G+=(RGB >> 5) & 0x003F;
      B+= RGB & 0x001F;      
      RGB = (blur2[id1]<<8) | blur2[id1+1];
      R+=(RGB >> 11) & 0x001F;
      G+=(RGB >> 5) & 0x003F;
      B+= RGB & 0x001F;      
      R=R>>2; G=G>>2; B=B>>2;      
      dest[id1] = (R<<3)|(G>>3); dest[id1+1]= (G<<5)|(B);        
    }
  }

  dest +=wl;

  //on core
  for(j=1;j<(h-1);j++)
  {   
   //first pixel
   if(bitdepth==1)
   { 
     id1 = blur1[0]<<2;
     R=Pal->RGB4[id1+1]; G=Pal->RGB4[id1+2]; B=Pal->RGB4[id1+3];    
     id1 = blur2[0]<<2;
     R+=Pal->RGB4[id1+1]; G+=Pal->RGB4[id1+2]; B+=Pal->RGB4[id1+3];    
     id1 = blur3[0]<<2;
     R+=Pal->RGB4[id1+1]; G+=Pal->RGB4[id1+2]; B+=Pal->RGB4[id1+3];    
     id1 = blur2[1]<<2;
     R+=Pal->RGB4[id1+1]; G+=Pal->RGB4[id1+2]; B+=Pal->RGB4[id1+3];    
     //average = 1/4
     R=R>>2; if(R>255) R=255;
     G=G>>2; if(G>255) G=255;
     B=B>>2; if(B>255) B=255;       
     //retrieve nearest indexed color     
     // (x*5)>>8 is about x/51
     R=(((R+26)<<2)+R+26)>>8;  G=(((G+26)<<2)+G+26)>>8;  B=(((B+26)<<2)+B+26)>>8;           
     IDcol = (R<<5)+(R<<2)+(G<<2)+(G<<1)+B;
     //copy new color
     dest[0]= (char)(PalInv->Index[IDcol]);  // copy new color;
   }
   else
   {
     RGB = (blur1[0]<<8) | blur1[0+1];
     R=(RGB >> 11) & 0x001F;  G=(RGB >> 5) & 0x003F;  B= RGB & 0x001F;      
     RGB = (blur2[0]<<8) | blur2[0+1];
     R+=(RGB >> 11) & 0x001F;  G+=(RGB >> 5) & 0x003F;  B+= RGB & 0x001F;      
     RGB = (blur3[0]<<8) | blur3[0+1];
     R+=(RGB >> 11) & 0x001F;  G+=(RGB >> 5) & 0x003F;  B+= RGB & 0x001F;      
     RGB = (blur2[2]<<8) | blur2[2+1];
     R+=(RGB >> 11) & 0x001F;  G+=(RGB >> 5) & 0x003F;  B+= RGB & 0x001F;      
     R=R>>2; G=G>>2; B=B>>2;      
     dest[0] = (R<<3)|(G>>3);   dest[0+1]= (G<<5)|(B);        
   }
   
   //inside line 
    for(i=1; i<(w-1); i++)
   {  
     if(bitdepth==1)
     { // 256 colors
       // ===> col=-1
       //row=-1

       id1 =blur1[i-1]<<2;
       R=Pal->RGB4[id1+1];
       G=Pal->RGB4[id1+2];
       B=Pal->RGB4[id1+3];    
       //row=0
       id1 =blur2[i-1]<<2;
       R+=Pal->RGB4[id1+1];
       G+=Pal->RGB4[id1+2];
       B+=Pal->RGB4[id1+3];    
       //row=1
       id1 =blur3[i-1]<<2;
       R+=Pal->RGB4[id1+1];
       G+=Pal->RGB4[id1+2];
       B+=Pal->RGB4[id1+3];    
       // ===> col=0
       //row=-1
       id1 =blur1[i]<<2;
       R+=Pal->RGB4[id1+1];
       G+=Pal->RGB4[id1+2];
       B+=Pal->RGB4[id1+3];    
      //row=0
      if(pblst->BlurKind ==0)
      {
        id1 =blur2[i]<<2;
        R+=(Pal->RGB4[id1+1])<<3;
        G+=(Pal->RGB4[id1+2])<<3;
        B+=(Pal->RGB4[id1+3])<<3;           
      }

      //row=1
      id1 =blur3[i]<<2;
      R+=Pal->RGB4[id1+1];
      G+=Pal->RGB4[id1+2];
      B+=Pal->RGB4[id1+3];    
      // ===> col=1
      //row=-1
      id1 =blur1[i+1]<<2;
      R+=Pal->RGB4[id1+1];
      G+=Pal->RGB4[id1+2];
      B+=Pal->RGB4[id1+3];    
      //row=0
      id1 =blur2[i+1]<<2;
      R+=Pal->RGB4[id1+1];
      G+=Pal->RGB4[id1+2];
      B+=Pal->RGB4[id1+3];    
      //row=1
      id1 =blur3[i+1]<<2;
      R+=Pal->RGB4[id1+1];
      G+=Pal->RGB4[id1+2];
      B+=Pal->RGB4[id1+3];    

      //average = 1/8 or 1/16
      R=R>>Denom; if(R>255) R=255;
      G=G>>Denom; if(G>255) G=255;
      B=B>>Denom; if(B>255) B=255;       

      //retrieve nearest indexed color     
      // (x*5)>>8 is about x/51
      R=(((R+26)<<2)+R+26)>>8;           
      G=(((G+26)<<2)+G+26)>>8;           
      B=(((B+26)<<2)+B+26)>>8;           
      IDcol = (R<<5)+(R<<2)+(G<<2)+(G<<1)+B;

      //copy new color
      dest[i]= (char)(PalInv->Index[IDcol]);  // copy new color;
     }
     else
     { // 65536 colors
       // ===> col=-1
       id1 = (i-1)<<1;
       
       //row=-1
       RGB = (blur1[id1]<<8) | blur1[id1+1];
       R=(RGB >> 11) & 0x001F;
       G=(RGB >> 5) & 0x003F;
       B= RGB & 0x001F;    
       //row=0
       RGB = (blur2[id1]<<8) | blur2[id1+1];
       R+=(RGB >> 11) & 0x001F;
       G+=(RGB >> 5) & 0x003F;
       B+= RGB & 0x001F;           
       //row=+1
       RGB = (blur3[id1]<<8) | blur3[id1+1];
       R+=(RGB >> 11) & 0x001F;
       G+=(RGB >> 5) & 0x003F;
       B+= RGB & 0x001F;
  
       // ===> col=0
       id1 += 2;           
          
       //row=-1
       RGB = (blur1[id1]<<8) | blur1[id1+1];
       R+=(RGB >> 11) & 0x001F;
       G+=(RGB >> 5) & 0x003F;
       B+= RGB & 0x001F;    
           
       //row=0
       if(pblst->BlurKind ==0)
       {
         RGB = (blur2[id1]<<8) | blur2[id1+1];
         R+=((RGB >> 11) & 0x001F)<<3;
         G+=((RGB >> 5) & 0x003F)<<3;
         B+= (RGB & 0x001F)<<3;           
       }
           
       //row=+1
       RGB = (blur3[id1]<<8) | blur3[id1+1];
       R+=(RGB >> 11) & 0x001F;
       G+=(RGB >> 5) & 0x003F;
       B+= RGB & 0x001F;
           
       // ===> col=+1
       id1 += 2;           
           
       //row=-1
       RGB = (blur1[id1]<<8) | blur1[id1+1];
       R+=(RGB >> 11) & 0x001F;
       G+=(RGB >> 5) & 0x003F;
       B+= RGB & 0x001F;    
       //row=0
       RGB = (blur2[id1]<<8) | blur2[id1+1];
       R+=(RGB >> 11) & 0x001F;
       G+=(RGB >> 5) & 0x003F;
       B+= RGB & 0x001F;           
       //row=+1
       RGB = (blur3[id1]<<8) | blur3[id1+1];
       R+=(RGB >> 11) & 0x001F;
       G+=(RGB >> 5) & 0x003F;
       B+= RGB & 0x001F;
           
       //average = 1/8 or 1/16
       R=R>>Denom;  if(R>0x1F) R=0x1F;
       G=G>>Denom;  if(G>0x3F) G=0x3F;
       B=B>>Denom;  if(B>0x1F) B=0x1F;       
       //new color
       id1 = i<<1;           
       dest[id1]  = (R<<3)|(G>>3);
       dest[id1+1]= (G<<5)|(B);           
     }        
   }
   //last pixel
   if(bitdepth==1)
   { 
     id1 = blur1[w-1]<<2;
     R=Pal->RGB4[id1+1]; G=Pal->RGB4[id1+2]; B=Pal->RGB4[id1+3];    
     id1 = blur2[w-1]<<2;
     R+=Pal->RGB4[id1+1]; G+=Pal->RGB4[id1+2]; B+=Pal->RGB4[id1+3];    
     id1 = blur3[w-1]<<2;
     R+=Pal->RGB4[id1+1]; G+=Pal->RGB4[id1+2]; B+=Pal->RGB4[id1+3];    
     id1 = blur2[w-2]<<2;
     R+=Pal->RGB4[id1+1]; G+=Pal->RGB4[id1+2]; B+=Pal->RGB4[id1+3];    
     //average = 1/4
     R=R>>2; if(R>255) R=255;
     G=G>>2; if(G>255) G=255;
     B=B>>2; if(B>255) B=255;       
     //retrieve nearest indexed color
     // (x*5)>>8 is about x/51
     R=(((R+26)<<2)+R+26)>>8;  G=(((G+26)<<2)+G+26)>>8;  B=(((B+26)<<2)+B+26)>>8;           
     IDcol = (R<<5)+(R<<2)+(G<<2)+(G<<1)+B;
     //copy new color
     dest[w-1]= (char)(PalInv->Index[IDcol]);  // copy new color;
   }
   else
   {
     id1 =(w-2)<<1;
     RGB = (blur2[id1]<<8) | blur2[id1+1];
     R=(RGB >> 11) & 0x001F;  G=(RGB >> 5) & 0x003F;  B= RGB & 0x001F;      
     id1 += 2;
     RGB = (blur1[id1]<<8) | blur1[id1+1];
     R+=(RGB >> 11) & 0x001F;  G+=(RGB >> 5) & 0x003F;  B+= RGB & 0x001F;      
     RGB = (blur2[id1]<<8) | blur2[id1+1];
     R+=(RGB >> 11) & 0x001F;  G+=(RGB >> 5) & 0x003F;  B+= RGB & 0x001F;      
     RGB = (blur3[id1]<<8) | blur3[id1+1];
     R+=(RGB >> 11) & 0x001F;  G+=(RGB >> 5) & 0x003F;  B+= RGB & 0x001F;      
     R=R>>2; G=G>>2; B=B>>2;      
     dest[id1] = (R<<3)|(G>>3);   dest[id1+1]= (G<<5)|(B);        
   }
   
  //move buffer lines
  dest += wl;
  blurtemp = blur1;
  blur1 = blur2;
  blur2 = blur3;
  blur3 =blurtemp;
  blurtemp = dest + wl;
  for(i=0; i<=w; i++) 
   { 
    if(bitdepth==1)
    { // 256 colors
      blur3[i]=blurtemp[i];; 
    }
    else
    { // 65536 colors
      id1 = i<<1;
      blur3[id1]=blurtemp[id1];  blur3[id1+1]=blurtemp[id1+1]; 
    }
   }
 }
  
  //on last line
  if(bitdepth==1)
  { for(i=0;i<w;i++)
    {
      if(i<(w-1))
      { id1 = blur2[i+1]<<2; 
        R=Pal->RGB4[id1+1];  G=Pal->RGB4[id1+2];  B=Pal->RGB4[id1+3];    
        id1 = blur1[i+1]<<2; 
        R+=Pal->RGB4[id1+1]; G+=Pal->RGB4[id1+2]; B+=Pal->RGB4[id1+3];    
      }
      else
      { id1 = blur2[i-1]<<2; 
        R=Pal->RGB4[id1+1];  G=Pal->RGB4[id1+2];  B=Pal->RGB4[id1+3];    
        id1 = blur1[i-1]<<2; 
        R+=Pal->RGB4[id1+1]; G+=Pal->RGB4[id1+2]; B+=Pal->RGB4[id1+3];    
      }
      id1 = blur2[i]<<2; 
      R+=Pal->RGB4[id1+1];  G+=Pal->RGB4[id1+2];  B+=Pal->RGB4[id1+3];    
      id1 = blur1[i]<<2; 
      R+=Pal->RGB4[id1+1];  G+=Pal->RGB4[id1+2];  B+=Pal->RGB4[id1+3];    
      R=R>>2;  G=G>>2;  B=B>>2;    
      R=(((R+26)<<2)+R+26)>>8;           
      G=(((G+26)<<2)+G+26)>>8;           
      B=(((B+26)<<2)+B+26)>>8;           
      IDcol = (R<<5)+(R<<2)+(G<<2)+(G<<1)+B;
      dest[i]= (char)(PalInv->Index[IDcol]);  // copy new color;
    }
  }
  else
  { for(i=0;i<w;i++)
    {
      if(i<(w-1))
      { id1 = (i+1)<<1; 
        RGB = (blur2[id1]<<8) | blur2[id1+1];
        R=(RGB >> 11) & 0x001F;
        G=(RGB >> 5) & 0x003F;
        B= RGB & 0x001F;      
        RGB = (blur1[id1]<<8) | blur1[id1+1];
        R+=(RGB >> 11) & 0x001F;
        G+=(RGB >> 5) & 0x003F;
        B+= RGB & 0x001F;      
      }
      else
      { id1 = (i-1)<<1;
        RGB = (blur2[id1]<<8) | blur2[id1+1];
        R=(RGB >> 11) & 0x001F;
        G=(RGB >> 5) & 0x003F;
        B= RGB & 0x001F;      
        RGB = (blur1[id1]<<8) | blur1[id1+1];
        R+=(RGB >> 11) & 0x001F;
        G+=(RGB >> 5) & 0x003F;
        B+= RGB & 0x001F;      
      }
      id1 = i<<1;
      RGB = (blur2[id1]<<8) | blur2[id1+1];
      R+=(RGB >> 11) & 0x001F;
      G+=(RGB >> 5) & 0x003F;
      B+= RGB & 0x001F;      
      RGB = (blur1[id1]<<8) | blur1[id1+1];
      R=(R+(RGB >> 11) & 0x001F)>>2;
      G=(G+(RGB >> 5) & 0x003F)>>2;
      B=(B+ RGB & 0x001F)>>2;      
      dest[id1]  = (R<<3)|(G>>3);
      dest[id1+1]= (G<<5)|(B);        
    }
  }

  return 0;
}

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