NO

Author Topic: Convolution function  (Read 647 times)

Offline Grincheux

  • Member
  • *
  • Posts: 146
  • Never be pleased, always improve
    • Arachne
Convolution function
« on: February 26, 2021, 07:22:33 pm »
Hello,

I am writing a convolution function but I am not sure to follow the good way.
Could you help me?

Code: [Select]
typedef struct tagFILTRES_PERSO
{
    char            szName[64] ;
    int             ColsNumber ;
    int             Divisor ;
    int             Bias ;
    int             Matrix[3][3] ;
} FILTRES_PERSO, *LPFILTRES_PERSO ;

FILTRES_PERSO   Filtre  =   {"FX000000241",3,   1,  0,{  -7,   7,   0,  -7,  -7,   7,   2,  -2,   0}} ;

//  Image must be int 32 bits (Alpha, Red, Green, Blue)
//  Width and Height mut be > 16 pixels
//  The Divisor must not be equal to 0. If it is equal to 0, the function set it to 1.

int Convolve_3x3(int __iWidth,int __iHeight,LPBYTE __lpImageBits,LPFILTRES_PERSO __lpFiltre)
{
    LPBYTE  _lpxy1, _lpxy2, _lpxy3 ;
    LPBYTE  _lpTmp ;

    int     _Red, _Green, _Blue, _Rgb ;
    int     _x1, _x2, _x3, _y1, _y2, _y3 ;
    int     _x, _y, _xx, _yy ;
    int     _i, _j ;

    if(!__lpFiltre)                 return (FALSE) ;
    if(!__lpImageBits)              return (FALSE) ;

    if(__iWidth < 16)               return (FALSE) ;
    if(__iHeight < 16)              return (FALSE) ;

    if(__lpFiltre->Divisor == 0)
        __lpFiltre->Divisor = 1 ;

    _lpTmp = __lpImageBits ;

    _xx = 4 ;                                                // Column #1
    _yy = (__iWidth * 4) + 4 ;                      // Line #1

    _lpTmp += _xx ;

    for(_x = 1 ; _x < __iWidth - 2 ; _x++)
    {
        _x1 = _xx - 4 ;                                // X - 1    Offset 0    Previous column
        _x2 = _xx ;                                    // X        Offset 4    Current column
        _x3 = _xx + 4 ;                             // X + 1    Offset 8    Next column

        _xx += 4 ;

        for(_y = 1 ; _y < __iHeight - 2; _y++)
        {
            _y1 = (__iWidth * 4) * (_y - 1) ;         // Y - 1    Previous line
            _y2 = (__iWidth * 4) * _y ;                // Y        Current line
            _y3 = (__iWidth * 4) * (_y + 1) ;       // Y + 1    Next line

            _lpxy1 = _lpTmp + _x1 + _y1 ;
            _lpxy2 = _lpTmp + _x2 + _y2 ;
            _lpxy3 = _lpTmp + _x3 + _y3 ;

            _Red    = (((*_lpxy1) & 0x00FF0000) >> 16) + (((*_lpxy2) & 0x00FF0000) >> 16) + (((*_lpxy3) & 0x00FF0000) >> 16) ;
            _Green  = (((*_lpxy1) & 0x0000FF00) >>  8) + (((*_lpxy2) & 0x0000FF00) >>  8) + (((*_lpxy3) & 0x0000FF00) >>  8) ;
            _Blue   = (((*_lpxy1) & 0x000000FF)      ) + (((*_lpxy2) & 0x000000FF)      ) + (((*_lpxy3) & 0x000000FF)      ) ;

            for(_i = 0 ; _i < 3 ; _i++)
            {
                for(_j = 0 ; _j < 3 ; _j++)
                {
                    _Red    *=  __lpFiltre->Matrix[_i][_j] ;      //  Red * Coef
                    _Green  *=  __lpFiltre->Matrix[_i][_j] ;    //  Green * Coef
                    _Blue   *=  __lpFiltre->Matrix[_i][_j] ;     //  Blue * Coef
                }
            }

            _Red /= __lpFiltre->Divisor ;
            _Green /= __lpFiltre->Divisor ;
            _Blue /= __lpFiltre->Divisor ;

            if(_Red < 0)        _Red = 0 ;
            if(_Green < 0)     _Green = 0 ;
            if(_Blue < 0)       _Blue = 0 ;

            if(_Red > 255)      _Red = 255 ;
            if(_Green > 255)   _Green = 255 ;
            if(_Blue > 255)     _Blue = 255 ;

            _Rgb = (_Red << 16) | (_Green << 8) | _Blue ;
            *(_lpTmp + _x2 + _y2) = _Rgb ;
        }
    }

    return (TRUE) ;
}

-----------------
    Calling :       Convolve_3x3(_BitmapWidth,_BitmapHeight,_lpImageBits,&Filtre) ;
-----------------

« Last Edit: February 26, 2021, 07:24:59 pm by Grincheux »
-------------------------
Kenavo / Bye

Offline John Z

  • Member
  • *
  • Posts: 188
Re: Convolution function
« Reply #1 on: February 28, 2021, 03:05:20 pm »
;) no clue.  Is this purpose edge detection?  Seems comparable to edge detection in IrfanView which I use extensively.

John z

Offline Grincheux

  • Member
  • *
  • Posts: 146
  • Never be pleased, always improve
    • Arachne
Re: Convolution function
« Reply #2 on: March 02, 2021, 03:42:21 am »
Now I find the same results that XnView!
The problem was coming from the compiler.

I thought that I could compute the convolution like this :
Code: [Select]
               _Red   =   (((*_lpx1y1 >> 16) & 255) * _c1) +
                        (((*_lpx2y1 >> 16) & 255) * _c2) +
                        (((*_lpx3y1 >> 16) & 255) * _c3) +
                        (((*_lpx1y2 >> 16) & 255) * _c4) +
                        (((*_lpx2y2 >> 16) & 255) * _c5) +
                        (((*_lpx3y2 >> 16) & 255) * _c6) +
                        (((*_lpx1y3 >> 16) & 255) * _c7) +
                        (((*_lpx2y3 >> 16) & 255) * _c8) +
                        (((*_lpx3y3 >> 16) & 255) * _c9) ;

It was wrong, I had to compute the convolution like this:
Code: [Select]
               _r1 = ((*_lpx1y1 >> 16) & 255) * _c1 ;
               _r2 = ((*_lpx2y1 >> 16) & 255) * _c2 ;
               _r3 = ((*_lpx3y1 >> 16) & 255) * _c3 ;
               _r4 = ((*_lpx1y2 >> 16) & 255) * _c4 ;
               _r5 = ((*_lpx2y2 >> 16) & 255) * _c5 ;
               _r6 = ((*_lpx3y2 >> 16) & 255) * _c6 ;
               _r7 = ((*_lpx1y3 >> 16) & 255) * _c7 ;
               _r8 = ((*_lpx2y3 >> 16) & 255) * _c8 ;
               _r9 = ((*_lpx3y3 >> 16) & 255) * _c9 ;

               _Red = _r1 + _r2 + _r3 + _r4 + _r5 + _r6 + _r7 + _r8 + _r9 ;

               if(_Red < 0)   _Red = 0 ;
               if(_Red > 255)   _Red = 255;

For me, it is a bug into the C Compiler Mr Pelle.

The final source code is:
Code: [Select]
int Convolve_3x3(int __iWidth,int __iHeight,LPBYTE __lpImageBits,LPFILTRES_PERSO __lpFiltre,int __iApplyDivisor,int __iChannelRed,int __iChannelGreen,int __iChannelBlue)
{
   LPDWORD   _lpx1y1, _lpx1y2, _lpx1y3, _lpx2y1, _lpx2y2, _lpx2y3, _lpx3y1, _lpx3y2, _lpx3y3 ;
   LPDWORD   _lpTmp ;

   int      _Red, _Green, _Blue ;
   int      _c1, _c2, _c3, _c4, _c5, _c6, _c7, _c8, _c9 ;
   int      _r1, _r2, _r3, _r4, _r5, _r6, _r7, _r8, _r9 ;
   int      _g1, _g2, _g3, _g4, _g5, _g6, _g7, _g8, _g9 ;
   int      _b1, _b2, _b3, _b4, _b5, _b6, _b7, _b8, _b9 ;
   DWORD   _iChannel ;
   int      _x1, _x2, _x3, _y1, _y2, _y3, _Rgb ;
   int      _x, _y, _xx ;

   if(!__lpFiltre)               return (FALSE) ;
   if(!__lpImageBits)            return (FALSE) ;

   if(__iWidth < 16)            return (FALSE) ;
   if(__iHeight < 16)            return (FALSE) ;

   if((__iApplyDivisor < 0) || (__iApplyDivisor > 1))   return (FALSE) ;

   if((__iChannelRed < 0)   || (__iChannelRed > 1))   return (FALSE) ;
   if((__iChannelGreen < 0) || (__iChannelGreen > 1))   return (FALSE) ;
   if((__iChannelBlue < 0)  || (__iChannelBlue > 1))   return (FALSE) ;

   _iChannel = 0 ;

   if(__iChannelRed)   _iChannel |= 1 ;
   if(__iChannelGreen)   _iChannel |= 2 ;
   if(__iChannelBlue)   _iChannel |= 4 ;

   _c1 = __lpFiltre->Matrix[0][0] ;      // Y1 X1
   _c2 = __lpFiltre->Matrix[0][1] ;      // Y1 X2
   _c3 = __lpFiltre->Matrix[0][2] ;      // Y1 X3
   _c4 = __lpFiltre->Matrix[1][0] ;      // Y2 X1
   _c5 = __lpFiltre->Matrix[1][1] ;      // Y2 X2
   _c6 = __lpFiltre->Matrix[1][2] ;      // Y2 X3
   _c7 = __lpFiltre->Matrix[2][0] ;      // Y3 X1
   _c8 = __lpFiltre->Matrix[2][1] ;      // Y3 X2
   _c9 = __lpFiltre->Matrix[2][2] ;      // Y3 X3

   __lpFiltre->Divisor = 0 ;

   if(__iApplyDivisor)
   {
      __lpFiltre->Divisor += _c1 ;
      __lpFiltre->Divisor += _c2 ;
      __lpFiltre->Divisor += _c3 ;
      __lpFiltre->Divisor += _c4 ;
      __lpFiltre->Divisor += _c5 ;
      __lpFiltre->Divisor += _c6 ;
      __lpFiltre->Divisor += _c7 ;
      __lpFiltre->Divisor += _c8 ;
      __lpFiltre->Divisor += _c9 ;

      __lpFiltre->Divisor /= 9 ;
   }

   if(__lpFiltre->Divisor == 0)
      __lpFiltre->Divisor = 1 ;

   _Red = _Green = _Blue = _Rgb = 0 ;

   _lpTmp = (LPDWORD) __lpImageBits ;

   _lpTmp++ ;

   _xx = 1 ;                                 // Column #1

   for(_x = 1 ; _x < __iWidth - 2 ; _x++)
   {
      _x1 = _xx - 1 ;                           // X - 1   Offset 0   Previous column
      _x2 = _xx ;                              // X      Offset 4   Current column
      _x3 = _xx + 1 ;                           // X + 1   Offset 8   Next column

      _xx++ ;

      for(_y = 1 ; _y < __iHeight - 2 ; _y++)
      {
         _y1 = __iWidth * (_y - 1) ;               // Y - 1   Previous line
         _y2 = __iWidth * _y ;                  // Y      Current line
         _y3 = __iWidth * (_y + 1) ;               // Y + 1   Next line

         _lpx1y1 = _lpTmp + _x1 + _y1 ;            // C1   X1,Y1
         _lpx1y2 = _lpTmp + _x1 + _y2 ;            // C4   X1,Y2
         _lpx1y3 = _lpTmp + _x1 + _y3 ;            // C7   X1,Y3

         _lpx2y1 = _lpTmp + _x2 + _y1 ;            // C2   X2,Y1
         _lpx2y2 = _lpTmp + _x2 + _y2 ;            // C5   X2,Y2
         _lpx2y3 = _lpTmp + _x2 + _y3 ;            // C8   X2,Y3

         _lpx3y1 = _lpTmp + _x3 + _y1 ;            // C3   X3,Y3
         _lpx3y2 = _lpTmp + _x3 + _y2 ;            // C6   X3,Y2
         _lpx3y3 = _lpTmp + _x3 + _y3 ;            // C9   X3,Y3

         if(__lpFiltre->Divisor == 1)
         {
            if(__iChannelRed)
            {
               _r1 = ((*_lpx1y1 >> 16) & 255) * _c1 ;
               _r2 = ((*_lpx2y1 >> 16) & 255) * _c2 ;
               _r3 = ((*_lpx3y1 >> 16) & 255) * _c3 ;
               _r4 = ((*_lpx1y2 >> 16) & 255) * _c4 ;
               _r5 = ((*_lpx2y2 >> 16) & 255) * _c5 ;
               _r6 = ((*_lpx3y2 >> 16) & 255) * _c6 ;
               _r7 = ((*_lpx1y3 >> 16) & 255) * _c7 ;
               _r8 = ((*_lpx2y3 >> 16) & 255) * _c8 ;
               _r9 = ((*_lpx3y3 >> 16) & 255) * _c9 ;

               _Red = _r1 + _r2 + _r3 + _r4 + _r5 + _r6 + _r7 + _r8 + _r9 ;

               if(_Red < 0)   _Red = 0 ;
               if(_Red > 255)   _Red = 255;
            }

            if(__iChannelGreen)
            {
               _g1 = ((*_lpx1y1 >>  & 255) * _c1 ;
               _g2 = ((*_lpx2y1 >>  & 255) * _c2 ;
               _g3 = ((*_lpx3y1 >>  & 255) * _c3 ;
               _g4 = ((*_lpx1y2 >>  & 255) * _c4 ;
               _g5 = ((*_lpx2y2 >>  & 255) * _c5 ;
               _g6 = ((*_lpx3y2 >>  & 255) * _c6 ;
               _g7 = ((*_lpx1y3 >>  & 255) * _c7 ;
               _g8 = ((*_lpx2y3 >>  & 255) * _c8 ;
               _g9 = ((*_lpx3y3 >>  & 255) * _c9 ;

               _Green = _g1 + _g2 + _g3 + _g4 + _g5 + _g6 + _g7 + _g8 + _g9 ;

               if(_Green < 0)      _Green = 0 ;
               if(_Green > 255)   _Green = 255;
            }

            if(__iChannelBlue)
            {
               _b1 = (*_lpx1y1 & 255) * _c1 ;
               _b2 = (*_lpx2y1 & 255) * _c2 ;
               _b3 = (*_lpx3y1 & 255) * _c3 ;
               _b4 = (*_lpx1y2 & 255) * _c4 ;
               _b5 = (*_lpx2y2 & 255) * _c5 ;
               _b6 = (*_lpx3y2 & 255) * _c6 ;
               _b7 = (*_lpx1y3 & 255) * _c7 ;
               _b8 = (*_lpx2y3 & 255) * _c8 ;
               _b9 = (*_lpx3y3 & 255) * _c9 ;

               _Blue = _b1 + _b2 + _b3 + _b4 + _b5 + _b6 + _b7 + _b8 + _b9 ;

               if(_Blue < 0)   _Blue = 0 ;
               if(_Blue > 255)   _Blue = 255;
            }
         }
         else
         {
            if(__iChannelRed)
            {
               _r1 = (((*_lpx1y1 >> 16) & 255) * _c1) / __lpFiltre->Divisor ;
               _r2 = (((*_lpx2y1 >> 16) & 255) * _c2) / __lpFiltre->Divisor ;
               _r3 = (((*_lpx3y1 >> 16) & 255) * _c3) / __lpFiltre->Divisor ;
               _r4 = (((*_lpx1y2 >> 16) & 255) * _c4) / __lpFiltre->Divisor ;
               _r5 = (((*_lpx2y2 >> 16) & 255) * _c5) / __lpFiltre->Divisor ;
               _r6 = (((*_lpx3y2 >> 16) & 255) * _c6) / __lpFiltre->Divisor ;
               _r7 = (((*_lpx1y3 >> 16) & 255) * _c7) / __lpFiltre->Divisor ;
               _r8 = (((*_lpx2y3 >> 16) & 255) * _c8) / __lpFiltre->Divisor ;
               _r9 = (((*_lpx3y3 >> 16) & 255) * _c9) / __lpFiltre->Divisor ;

               _Red = _r1 + _r2 + _r3 + _r4 + _r5 + _r6 + _r7 + _r8 + _r9 ;

               if(_Red < 0)   _Red = 0 ;
               if(_Red > 255)   _Red = 255;
            }

            if(__iChannelGreen)
            {
               _g1 = (((*_lpx1y1 >>  & 255) * _c1) / __lpFiltre->Divisor ;
               _g2 = (((*_lpx2y1 >>  & 255) * _c2) / __lpFiltre->Divisor ;
               _g3 = (((*_lpx3y1 >>  & 255) * _c3) / __lpFiltre->Divisor ;
               _g4 = (((*_lpx1y2 >>  & 255) * _c4) / __lpFiltre->Divisor ;
               _g5 = (((*_lpx2y2 >>  & 255) * _c5) / __lpFiltre->Divisor ;
               _g6 = (((*_lpx3y2 >>  & 255) * _c6) / __lpFiltre->Divisor ;
               _g7 = (((*_lpx1y3 >>  & 255) * _c7) / __lpFiltre->Divisor ;
               _g8 = (((*_lpx2y3 >>  & 255) * _c8) / __lpFiltre->Divisor ;
               _g9 = (((*_lpx3y3 >>  & 255) * _c9) / __lpFiltre->Divisor ;

               _Green = _g1 + _g2 + _g3 + _g4 + _g5 + _g6 + _g7 + _g8 + _g9 ;

               if(_Green < 0)      _Green = 0 ;
               if(_Green > 255)   _Green = 255;
            }

            if(__iChannelBlue)
            {
               _b1 = ((*_lpx1y1 & 255) * _c1) / __lpFiltre->Divisor ;
               _b2 = ((*_lpx2y1 & 255) * _c2) / __lpFiltre->Divisor ;
               _b3 = ((*_lpx3y1 & 255) * _c3) / __lpFiltre->Divisor ;
               _b4 = ((*_lpx1y2 & 255) * _c4) / __lpFiltre->Divisor ;
               _b5 = ((*_lpx2y2 & 255) * _c5) / __lpFiltre->Divisor ;
               _b6 = ((*_lpx3y2 & 255) * _c6) / __lpFiltre->Divisor ;
               _b7 = ((*_lpx1y3 & 255) * _c7) / __lpFiltre->Divisor ;
               _b8 = ((*_lpx2y3 & 255) * _c8) / __lpFiltre->Divisor ;
               _b9 = ((*_lpx3y3 & 255) * _c9) / __lpFiltre->Divisor ;

               _Blue = _b1 + _b2 + _b3 + _b4 + _b5 + _b6 + _b7 + _b8 + _b9 ;

               if(_Blue < 0)   _Blue = 0 ;
               if(_Blue > 255)   _Blue = 255;
            }
         }

         switch(_iChannel)
         {
            case   0 :   _Rgb = 0 ;                                 break ;
            case   1 :   _Rgb = (_Red   << 16) | (_Red   << | _Red ;      break ;
            case   2 :   _Rgb = (_Green << 16) | (_Green << | _Green ;   break ;
            case   3 :   _Rgb = (_Red   << 16) | (_Green << ;            break ;
            case   4 :   _Rgb = (_Blue  << 16) | (_Blue  << | _Blue ;      break ;
            case   5 :   _Rgb = (_Red   << 16) | _Blue ;                  break ;
            case   6 :   _Rgb = (_Green <<  | _Blue ;                  break ;
            case   7 :   _Rgb = (_Red   << 16) | (_Green << | _Blue ;      break ;
         }

         *(_lpTmp + _x1 + _y1) = _Rgb ;
      }
   }

   return (TRUE) ;
}

Rather making the sum, it it possible to compute the MAX, the MIN, the AVERAGE.

When computing a SOBEL filter, you call the function with your filter then the filter must be changed as follow before calling again the function.

*** BEFORE ***
Code: [Select]
   _c1 = __lpFiltre->Matrix[0][0] ;      // Y1 X1
   _c2 = __lpFiltre->Matrix[0][1] ;      // Y1 X2
   _c3 = __lpFiltre->Matrix[0][2] ;      // Y1 X3
   _c4 = __lpFiltre->Matrix[1][0] ;      // Y2 X1
   _c5 = __lpFiltre->Matrix[1][1] ;      // Y2 X2
   _c6 = __lpFiltre->Matrix[1][2] ;      // Y2 X3
   _c7 = __lpFiltre->Matrix[2][0] ;      // Y3 X1
   _c8 = __lpFiltre->Matrix[2][1] ;      // Y3 X2
   _c9 = __lpFiltre->Matrix[2][2] ;      // Y3 X3
*** AFTER ***
Code: [Select]
   _c1 = __lpFiltre->Matrix[0][0] ;      // Y1 X1
   _c4 = __lpFiltre->Matrix[0][1] ;      // Y1 X2
   _c7 = __lpFiltre->Matrix[0][2] ;      // Y1 X3
   _c2 = __lpFiltre->Matrix[1][0] ;      // Y2 X1
   _c5 = __lpFiltre->Matrix[1][1] ;      // Y2 X2
   _c8 = __lpFiltre->Matrix[1][2] ;      // Y2 X3
   _c3 = __lpFiltre->Matrix[2][0] ;      // Y3 X1
   _c6 = __lpFiltre->Matrix[2][1] ;      // Y3 X2
   _c9 = __lpFiltre->Matrix[2][2] ;      // Y3 X3

THEN DO

   __lpFiltre->Matrix[0][0] = _c1 ;      // Y1 X1
   __lpFiltre->Matrix[0][1] = _c2;      // Y1 X2
   __lpFiltre->Matrix[0][2] = _c3;      // Y1 X3
   __lpFiltre->Matrix[1][0] = _c4;      // Y2 X1
   __lpFiltre->Matrix[1][1] = _c5 ;      // Y2 X2
   __lpFiltre->Matrix[1][2] = _c6 ;      // Y2 X3
   __lpFiltre->Matrix[2][0] = _c7 ;      // Y3 X1
   __lpFiltre->Matrix[2][1] = _c8 ;      // Y3 X2
   __lpFiltre->Matrix[2][2] = _c9 ;      // Y3 X3
« Last Edit: March 02, 2021, 08:39:16 am by Grincheux »
-------------------------
Kenavo / Bye

Offline Grincheux

  • Member
  • *
  • Posts: 146
  • Never be pleased, always improve
    • Arachne
Re: Convolution function
« Reply #3 on: March 02, 2021, 08:31:42 am »
I forgot to show the result.


-------------------------
Kenavo / Bye

Offline John Z

  • Member
  • *
  • Posts: 188
Re: Convolution function
« Reply #4 on: March 02, 2021, 12:58:21 pm »
Wow, well you persevered and achieved desired results...

Could it be that part of the problem is this warning in the help file?
Quote
Note! Do not select names for identifiers that begin with two underscores, or with an underscore followed by an uppercase letter. The C standard allows identifier names that begin with these character combinations to be reserved for compiler use.

 _Red   <=  underscore followed by an uppercase letter …..
int      _Red, _Green, _Blue ; //

So it may be working accidentally right now.....

 John Z

Offline Grincheux

  • Member
  • *
  • Posts: 146
  • Never be pleased, always improve
    • Arachne
Re: Convolution function
« Reply #5 on: March 02, 2021, 02:54:25 pm »
I don't know.


I am working on convolution functions 5x5, 7x7 and 9x9
Then I add complex filters like SOBEL, PREWITT, KIRCH and ROBINSON.


I will post my differents steps.
Thank You John
-------------------------
Kenavo / Bye

Offline Grincheux

  • Member
  • *
  • Posts: 146
  • Never be pleased, always improve
    • Arachne
Re: Convolution function
« Reply #6 on: March 05, 2021, 06:02:31 pm »
Don't be afraid I have my mask for writing!

I have made a sample application to test the filters.
The application has 19954 filters build into it!
It must generate 19954 images?
No, because I drop identical images, computing for each a hash (Keccak) stored into a databse.
After if the file size is smaller than the original, I drop it too.
It is not possible to tell how many images will be created.
Into the applcation folder there is a test directory.
For using the application, just put an image into the folder the application is.
If there are more than one image file, it uses the first.
The application onmy wants JPEG files.

It can be downloaded here : https://www.mediafire.com/file/pazgwnpkv8scvw8/MakeFilters.7z/file

The program has been tested on colored, sepia and grey images.
Actually I am running the test and there are 644 files for 2244 filters!

I made a folder with some test image : https://www.mediafire.com/folder/pzxj2kljcsbv4/Tests

Into the source code there is a convolution function for 5x5, but it is not tested again.
For the Robinson filters I create the 8 filters (N/NE/E/SE/S/SO/W/NO), idem for sobel, 2 filters and for Kirsch, 4 filters (N/S/E/W).

One thing is funny with filters, you cann se the image moving. This is because some filters move the new images to the top, or to the bottom, or to the right or th left.

I have used the filters with Photofiltre (http://www.photofiltre-studio.com/pf7.htm).
Edit a image created with a filter. It becomes the background.
Paste the original image into photofiltre (CTRL V). Use each of the blend modes, or use Gimp.

The original image


The new one


The PhotoFiltre file :
https://www.mediafire.com/file/cazbgy27im02uib/FY000000909-D01-Bonnie_%2526_Clyde-01.pfi/file
« Last Edit: March 05, 2021, 06:22:46 pm by Grincheux »
-------------------------
Kenavo / Bye

Offline John Z

  • Member
  • *
  • Posts: 188
Re: Convolution function
« Reply #7 on: March 06, 2021, 12:00:52 am »
Wow - I just don't know what I would use it for. 

I'll download though and try a few things.  Hope I have enough memory for 644 images  ;D

Did you change the underscore caps variables (_R ..) or just let it work that way?  Just wondering if that had an effect or not.

I'm think I might implement a "Wu's Color Quantizer" for BMP - just thinking at this stage.

John Z

P.S. How is that radio project coming? 

Offline Grincheux

  • Member
  • *
  • Posts: 146
  • Never be pleased, always improve
    • Arachne
Re: Convolution function
« Reply #8 on: March 06, 2021, 02:51:11 am »
Hello John,
I have changed but no effect, so I set it to my coding conventions :
One underscore for local variables and two underscores for parameters. No underscore for global variables.
I have now to create some source code for some filters not yet implemented.
After it will be possible to merge the original image and the filter result.
Merging modes are similar to these used by GIMP.
The code is written for the modes there is no big work to joi the filters and the merge modes.

For my radio project, I have my SWL paper and code F5205SWL.
One of my cats came on my desl and make the baofeng falling down!
Can't use it now, broken.
I have seen a little radio, not expensive, I will buy it. I just wait to have more work, C19!
« Last Edit: March 06, 2021, 02:54:36 am by Grincheux »
-------------------------
Kenavo / Bye

Offline frankie

  • Global Moderator
  • Member
  • *****
  • Posts: 1805
Re: Convolution function
« Reply #9 on: March 06, 2021, 12:52:07 pm »
Hello John,
I have changed but no effect, so I set it to my coding conventions :
One underscore for local variables and two underscores for parameters. No underscore for global variables.

While you're free to use any convention you like, you must be advised anyway that it is uncompliant with the standard, that, at least in this case, reserve a full subsection to clarify what are to be considered reserved identifiers.
For your convenience I copycat the paragraph below. If you want use a more compliant convention you can have a look at the Hungarian notation, adopted also by MS for its, now rare, plain C code.

Excerpt from ISO/IEC 9899:2011:
§7.1.3 Reserved identifiers
  • Each header declares or defines all identifiers listed in its associated subclause, and optionally declares or defines identifiers listed in its associated future library directions subclause and identifiers which are always reserved either for any use or for use as file scope identifiers.
    • All identifiers that begin with an underscore and either an uppercase letter or another underscore are always reserved for any use.
    • All identifiers that begin with an underscore are always reserved for use as identifiers with file scope in both the ordinary and tag name spaces.
    • Each macro name in any of the following subclauses (including the future library directions) is reserved for use as specified if any of its associated headers is included; unless explicitly stated otherwise (see 7.1.4).
    • All identifiers with external linkage in any of the following subclauses (including the future library directions) and errno are always reserved for use as identifiers with external linkage.181)
    • Each identifier with file scope listed in any of the following subclauses (including the future library directions) is reserved for use as a macro name and as an identifier with file scope in the same name space if any of its associated headers is included.
    No other identifiers are reserved.
  • If the program declares or defines an identifier in a context in which it is reserved (other than as allowed by 7.1.4), or defines a reserved identifier as a macro name, the behavior is undefined
  • If the program removes (with #undef) any macro definition of an identifier in the first group listed above, the behavior is undefined.

Consider also that object symbols are composed by prefixing the C identifier name with an underscore (see identifiers with external linkage above), in standard C, not MS convention that use also decoration, so the mess between program identifiers, system identifiers and symbol names, as identifiers with external linkage, become epic.
As said you're eventually free to follow your way.
« Last Edit: March 06, 2021, 12:59:48 pm by frankie »

Offline Grincheux

  • Member
  • *
  • Posts: 146
  • Never be pleased, always improve
    • Arachne
Re: Convolution function
« Reply #10 on: March 18, 2021, 08:44:37 pm »
You seem to right, but in this case one can consider a bug into any compiler that accept local and parameters variable to begin with an underscore. I have seen many C grammars, it is not forbidden to use the underscore anywhere in the variable name.

I thought that it was link any other character. In my mind when I have a variable "_Toto" the compiler must create "__Toto".
And when I have a "__Toto" variable it becomes "___Toto".

That is only valid for external variables, when there is no external variables defined, the syntax is accepted.

I don't want the war.
I like that kind of discuss because it is possible to learn many things.


But the problem I had was not caused by the syntax, for me it was a bug.


Thank You Frankie. ;D
-------------------------
Kenavo / Bye

Offline frankie

  • Global Moderator
  • Member
  • *****
  • Posts: 1805
Re: Convolution function
« Reply #11 on: March 19, 2021, 06:30:37 pm »
You seem to right, but in this case one can consider a bug into any compiler that accept local and parameters variable to begin with an underscore. I have seen many C grammars, it is not forbidden to use the underscore anywhere in the variable name.
No war, never  :)
Maybe I haven't been clear enough, you can use the underscore, and the compiler will never prevent you to do so.
The standard prohibit the use of symbols beginning with underscores for application code, but you are allowed to use them when using system  or library headers or symbols.
The compiler don't, and can't, block you because you must be allowed to create a compiler header or library, and must be allowed to use those symbols in your application code.
So the compiler will not complain, but the code isn't compliant with the standard.
Said that you're free to do whatever you want... only your code isn't formally correct ;D ;D ;D ;D

Offline Grincheux

  • Member
  • *
  • Posts: 146
  • Never be pleased, always improve
    • Arachne
Re: Convolution function
« Reply #12 on: March 20, 2021, 06:08:03 pm »
Frankie Game, Set and Match  :o
-------------------------
Kenavo / Bye

Offline frankie

  • Global Moderator
  • Member
  • *****
  • Posts: 1805
Re: Convolution function
« Reply #13 on: March 20, 2021, 09:04:17 pm »
 ;D ;D ;D
Ok, drawed match.
« Last Edit: March 20, 2021, 09:07:54 pm by frankie »