Translation from other languages to g'mic scripting language

People who know other languages and their language (Please feel free to mention more languages. If you want to be added, feel free to request me to add you here.):

@David_Tschumperle - C++
@Reptorian - C# (PDN Plugins), and C++
@grosgood - Python, C, C++, Java (Not so literate in it)

The purpose of this thread is to have gmic developers aid in helping convert scripts from other languages. Another purpose is to add translation of some functions into the gmic language. Python diag() was solved in another thread.

There are many filters that are on gmic which the original filter was developed on other languages. Iā€™m not too sure on where to go from here, so I will just mention a brief example.


For example, I will mention TRā€™s Pixel Sharpener:

It is a plugin that is created for Paint.NET.

Code to TR's Pixel Sharpener
// Submenu: Photo
// Name: TR's Pixel Sharpener
// Title: TR's Pixel Sharpener - v2.0
// Author: TechnoRobbo
// URL: http://www.technorobbo]http://www.technorobbo

#region UICode

double Amount1 = 0.75; // [0,1] Sharpen Amount
int Amount2 = 1; // [1,5] Blur Width
byte Amount3 = 0; // Blur Type|Photo|Horizontal Motion|Vertical Motion

#endregion

 

void Render(Surface dst, Surface src, Rectangle rect)

{
    Rectangle sel = EnvironmentParameters.GetSelection(src.Bounds).GetBoundsInt();
    Surface proxy = src.Clone();
    double blur = (Amount2 - 1)* 2 + 3;
    double qblur= blur * blur;
    double eblur = Math.Floor(blur /2);
    double sblur = Math.Floor(blur /-2);      

    ColorBgra CP;

    double Coeff =Amount1;
    double mult = qblur * Coeff + eblur / Amount2 ;

    for (int y = rect.Top; y < rect.Bottom; y++)
    {
        for (int x = rect.Left; x < rect.Right; x++)
        {

            CP = src[x,y];
            int[] sum = {(int)((double)CP.R * mult ),(int)((double)CP.G * mult ),(int)((double)CP.B * mult) };

            for (int i = (int)sblur; i<=eblur; i++){
                for (int j = (int)sblur; j<=eblur; j++){
                    if (i!=0 & j!=0)
                    {

                        float nx = x + j;
                        float ny = y + i;
                        if (Amount3==2) nx = x;
                        if (Amount3==1) ny = y;

                        CP = src.GetBilinearSampleClamped(nx,ny);
                        sum[0] -= (int)((double)CP.R * Coeff);
                        sum[1] -=(int)((double)CP.G * Coeff);
                        sum[2] -= (int)((double)CP.B * Coeff);
                    }
                }
            }

            CP.R = Int32Util.ClampToByte(sum[0]);
            CP.G = Int32Util.ClampToByte(sum[1]);
            CP.B = Int32Util.ClampToByte(sum[2]);

            dst[x,y] = CP;

        }
    }
}

Translation:

G'MIC version (Extended after translation)
#@cli rep_trps: eq. to 'rep_tr_pixel_sharpener'. : (+)
rep_trps: rep_tr_pixel_sharpener $*
#@cli rep_tr_pixel_sharpener: sharpen,_internal_blur>=0,_type= { 0=Photo | 1= Horizontal | 2= Vertical | 3= One-Axis Angle | 4= Two-Axis Angle | 5= Two-Axis Disconnected},-360<=_sharpening_angle_a<=360,-360<=_sharpening_angle_b<=360
#@cli : Extended version of the original TR's Pixel Sharpener for Paint.NET. Some code were changed to make more sense or is more practical. Negative values are enabled for first variable in the G'MIC version. The original code this was based on was created by TechnoRobbo. Source code - https://forums.getpaint.net/topic/26783-trs-pixel-sharpener-plugin-v20-dec-21-2014/
#@cli : (eq. to 'rep_trps').\n
#@cli : Default values: '_internal_blur=0','_blur_type=0','_sharpening_angle=0'\n
#@cli : Author: Reptorian.
rep_tr_pixel_sharpener:
skip ${2=0},${3=0},${4=0},${5=0}
f "begin(
  const ang=pi*($4/180);
  const ang2=pi*($5/180);
  const cos_ang=cos(ang);
  const sin_ang=sin(ang);
  const cos_ang2=cos(ang2);
  const sin_ang2=sin(ang2);
  rot_x(a,b)=a*cos_ang-b*sin_ang;
  rot_y(a,b)=a*sin_ang+b*cos_ang;
  rot_y_alt(a,b)=a*sin_ang2+b*cos_ang2;
  const blur=(round(abs($2)+1)-1)*2+3;
  const qblur=sqr(blur);
  const eblur=floor(blur/2);
  const sblur=floor(blur/-2);
  const coeff=$1/100;
  const mult=qblur*coeff+eblur/round(abs($2)+1);
  const choice=abs($3)<=2?abs($3):0;
  $3==5?(
   fnx()=x+rot_x(j,k);
   fny()=y+rot_y_alt(j,k);
  ):
  $3==4?(
   fnx()=x+rot_x(j,k);
   fny()=y+rot_y(j,k);
  ):
  $3==3?(
   fnx()=x+rot_x(j,0);
   fny()=y+rot_y(j,0);
  ):
  $3==2?(
   fnx()=x;
   fny()=y+k;
  ):
  $3==1?(
   fnx()=x+j;
   fny()=y;
  ):(
   fnx()=x+j;
   fny()=y+k;
  );
 );
 sum=i*mult;
 for(k=int(sblur),k<=eblur,k++,
  for(j=int(sblur),j<=eblur,j++,
   if(k!=0&j!=0,
    nx=fnx();
    ny=fny();
    nfcalc=i(nx,ny,z,c,0,1);
    sum-=nfcalc*coeff;
   );
  );
 );
 sum;"

You see the difference between the two version? There is no for(x,y) within the gā€™mic translation because gā€™mic has the option to generate images using implicit loops. There is also macro functions declared within the gmic version. src[x,y] can be seen as the equilavent of I(#0) or i#0 because within the C# PDN plugin, that means the pixel located at indice of x,y.

Itā€™s hard to explain how to convert it, but I think the examples should do well to demonstrate their similarity.

Please do not use this translation system.
Itā€™s now a bit old and has the very bad behavior or multiplying the number of filters.

The new translation system uses a more classical file that contains a list of words / sentences :

This is about translating coding languages or programming languages, not languages in general.

Also, for me, C, C++. Semi-illiterate in Java

To my mind, the heart of the matter is to grasp the key ideas that a language snippet encodes. With that in hand, the particularities and peculiarities of computer languages fall away and become ā€“ well, uninteresting, and re-encoding the key ideas in the target language is a mundane exercise in transcription.

To transcribe from a source to a target language relying just on oneā€™s grasp of the source and target languagesā€™ syntax and library call semantics, in the hope that the key ideas will somehow ā€œgo acrossā€, is largely a fruitless exercise ā€“ possibly excepting trivial cases where the source and target languages both support some well-known and commonly used API function - say, convoluting a Gaussian kernel of a certain diameter, with similar boundary policies, over
an image. Likely, there are image processing libraries in both source and target languages that permit a 1:1 mapping of such API functions.

In my experience, the frequency of such happy circumstances are few and far in between. More commonly, it is an exercise of stripping away language syntax and semantics to get at the key ideas which the particular language encodes, and the success of that endeavor depends not so much on knowledge of computer languages as it does on image processing theories and practices, so that one can readily recognize a key idea for what it is ā€“ in spite of the weeds and vines of the encoding language.

Indeed, with key ideas already in mind, who needs a source encoding? As far as I know, Redfield has never published its Fractalius algorithm. It took Rod of Gimpchat fame and @David_Tschumperle to devise a ā€˜lookalikeā€™ based on an iteration of -linear_blur and -sharpen. That lookalike may not even bear any particular relation to Redfieldā€™s implementation ā€“ and who cares? Rod and David worked out a look-alike ends, then devised a new means to get to that end, Fractalius furnishing just a kind of inspiring motivation.

I donā€™t wish to suggest that looking at various language implementations of this or that effect is a bad idea. But I think a language implementation of an interesting effect is better regarded as a source of inspiration rather than a blueprint. Of greater importance is oneā€™s savvy about how images come to be, plus a little bit of creativity (perhaps madness) to enable one to leave the more trodden pathways and break out on their own. Thatā€™s where the fun is. Have at it.

2 Likes