Pelles C forum

C language => Expert questions => Topic started by: Grincheux on February 26, 2021, 07:22:33 PM

Title: Convolution function
Post by: Grincheux 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) ;
-----------------

Title: Re: Convolution function
Post by: John Z 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
Title: Re: Convolution function
Post by: Grincheux 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
Title: Re: Convolution function
Post by: Grincheux on March 02, 2021, 08:31:42 AM
I forgot to show the result.


(https://www.mediafire.com/convkey/9f01/zogr9kgp0zh4y2q4g.jpg) (https://www.mediafire.com/view/zogr9kgp0zh4y2q/Result.jpg/file)
Title: Re: Convolution function
Post by: John Z 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
Title: Re: Convolution function
Post by: Grincheux 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
Title: Re: Convolution function
Post by: Grincheux 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 (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 (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 (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
(https://www.mediafire.com/convkey/2cf9/elswpt9li5m186x4g.jpg) (https://www.mediafire.com/view/elswpt9li5m186x/Bonnie_%2526_Clyde.jpg/file)

The new one
(https://www.mediafire.com/convkey/cf14/hevqwm04sndfqia4g.jpg) (https://www.mediafire.com/view/hevqwm04sndfqia/FY000000909-D01-Bonnie_%2526_Clyde-01.jpg/file)

The PhotoFiltre file :
https://www.mediafire.com/file/cazbgy27im02uib/FY000000909-D01-Bonnie_%2526_Clyde-01.pfi/file (https://www.mediafire.com/file/cazbgy27im02uib/FY000000909-D01-Bonnie_%2526_Clyde-01.pfi/file)
Title: Re: Convolution function
Post by: John Z 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? 
Title: Re: Convolution function
Post by: Grincheux 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!
Title: Re: Convolution function
Post by: frankie 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 (https://en.wikipedia.org/wiki/Hungarian_notation), adopted also by MS for its, now rare, plain C code.

Excerpt from ISO/IEC 9899:2011:
§7.1.3 Reserved identifiers

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.
Title: Re: Convolution function
Post by: Grincheux 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
Title: Re: Convolution function
Post by: frankie 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
Title: Re: Convolution function
Post by: Grincheux on March 20, 2021, 06:08:03 PM
Frankie Game, Set and Match  :o
Title: Re: Convolution function
Post by: frankie on March 20, 2021, 09:04:17 PM
 ;D ;D ;D
Ok, drawed match.