# RGB-Gray Linear Interpolation

## Recommended Posts

Inspired by @ReMake, I have decided to take my version which contains more variety. (Two different source codes for this is provided below. C# and G'MIC-QT). All this filter does is to interpolate between rgb and grayscale value.

It's under Effects/Colors

------

Source code in C#

// Name: RGB-Gray Linear Interpolation
// Author: Reptorian
// Title: RGB to Gray Linear Interpolation
// Version: 1.0
// Desc: Interpolate between rgb value and grayscale value
// URL: forums.getpaint.net
// Help:
#region UICode
ListBoxControl Mode = 1; // GrayMode|Weighted|Luminosity A|Luminosity B|HSL Lightness|Minimum Channel|Maximum Channel|Average
IntSliderControl RedFactor = 255; // [0,360] Red Factor
IntSliderControl GreenFactor = 255; // [0,360] Green Factor
IntSliderControl BlueFactor = 255; // [0,360] Blue Factor
DoubleSliderControl RedWeight = 1; // [0,1] {Mode} Red Weight
DoubleSliderControl GreenWeight = 1; // [0,1] {Mode} Green Weight
DoubleSliderControl BlueWeight = 1; // [0,1] {Mode} Blue Weight
#endregion

private int Weighted(int rval,int gval, int bval, double rw, double gw, double bw)
{
double rfactor=(double)(rw*rval);
double gfactor=(double)(gw*gval);
double bfactor=(double)(bw*bval);
double endval=rfactor+gfactor+bfactor;
return (int)(endval);
}

private int Luma_A(int rval,int gval, int bval)
{
double rfactor=(double)(0.22248840*rval);
double gfactor=(double)(0.71690369*gval);
double bfactor=(double)(0.06060791*bval);
double endval=rfactor+gfactor+bfactor;
return (int)(endval);
}

private int Luma_B(int rval,int gval, int bval)
{
double rfactor=(double)(0.2989*rval);
double gfactor=(double)(0.5870*gval);
double bfactor=(double)(0.1140*bval);
double endval=rfactor+gfactor+bfactor;
return (int)(endval);
}

private int lightness(int rval,int gval, int bval)
{
int max_factor=Math.Max(Math.Max(rval,gval),Math.Max(gval,bval));
int min_factor=Math.Min(Math.Min(rval,gval),Math.Min(gval,bval));
double grayval=(double)((max_factor+min_factor)/2);
return (int)(grayval);
}

private int max(int rval,int gval, int bval)
{
return Math.Max(Math.Max(rval,gval),Math.Max(gval,bval));
}

private int min(int rval,int gval, int bval)
{
return Math.Min(Math.Min(rval,gval),Math.Min(gval,bval));
}

private int average(int rval,int gval, int bval)
{
double avg = (double)((rval+gval+bval)/3);
return (int)(avg);
}

private ColorBgra Interpolation(int rval,int gval,int bval,int rlvl,int glvl,int blvl,int gray,int A)
{
int rr = (rval * rlvl + gray * (255 - rlvl)) / 255;
int gg = (gval * glvl + gray * (255 - glvl)) / 255;
int bb = (bval * blvl + gray * (255 - blvl)) / 255;
return ColorBgra.FromBgraClamped(bb,gg,rr,A);
}

void Render(Surface dst, Surface src, Rectangle rect)
{
// Delete any of these lines you don't need
Rectangle selection = EnvironmentParameters.SelectionBounds;
int Gray=0;
double totalweight=RedWeight+GreenWeight+BlueWeight;
double red_weight=RedWeight/totalweight;
double green_weight=GreenWeight/totalweight;
double blue_weight=BlueWeight/totalweight;

ColorBgra CurrentPixel;
for (int y = rect.Top; y < rect.Bottom; y++)
{
if (IsCancelRequested) return;
for (int x = rect.Left; x < rect.Right; x++)
{
CurrentPixel = src[x,y];
int R=(int)(CurrentPixel.R);
int G=(int)(CurrentPixel.G);
int B=(int)(CurrentPixel.B);
int A=(int)(CurrentPixel.A);

switch (Mode)
{
case 0:
Gray = Weighted(R,G,B,red_weight,green_weight,blue_weight);
break;
case 1:
Gray = Luma_A(R,G,B);
break;
case 2:
Gray = Luma_B(R,G,B);
break;
case 3:
Gray = lightness(R,G,B);
break;
case 4:
Gray = min(R,G,B);
break;
case 5:
Gray = max(R,G,B);
break;
case 6:
Gray = average(R,G,B);
break;
}

ColorBgra Final=Interpolation(R,G,B,RedFactor,GreenFactor,BlueFactor,Gray,A);
dst[x,y] = Final;
}
}
}

Source Code in G'MIC-QT

#@cli rep_lerp_rgb_gray: eq. to rep_linear_interpolation_rgb_gray : (+)
rep_lerp_rgb_gray: rep_linear_interpolation_rgb_gray \$*
#@cli rep_linear_interpolation_rgb_gray: 0%>=_red_factor(%)<=100%,0%>=_green_factor(%)<=100%,0%>=_blue_factor(%)<=100%,_gray_mode={ 0=luminosity | 1=luminosity_alternative | 2=lightness | 3=minimum_channel | 4=maximum_channel | 5=average } : 0%>=_red_factor(%)<=100%,0%>=_green_factor(%)<=100%,0%>=_blue_factor(%)<=100%,_red_weight,green_weight,blue_weight
rep_linear_interpolation_rgb_gray:
skip \${4=0},\${5=},\${6=}
total_arg=0
if isnum(\$1) total_arg+=1 fi
if isnum(\$2) total_arg+=1 fi
if isnum(\$3) total_arg+=1 fi
if isnum(\$4) total_arg+=1 fi
if isnum(\$5) total_arg+=1 fi
if isnum(\$6) total_arg+=1 fi
if \$total_arg==5 error "narg!=5=F" fi

if abs(\$1)>2 error "|"\$"1|<=2=F" fi
if abs(\$2)>2 error "|"\$"2|<=2=F" fi
if abs(\$3)>2 error "|"\$"3|<=2=F" fi

f "
begin(
rlvl=abs(\$1);
glvl=abs(\$2);
blvl=abs(\$3);

if(narg(\$*)>5,
tw=abs(\$4)+abs(\$5)+abs(\$6);
c1f=abs(\$4)/tw;
c2f=abs(\$5)/tw;
c3f=abs(\$6)/tw;
graymode(a,b,c)=a*c1f+b*c2f+c*c3f;
,
if(\$4==0,graymode(a,b,c)=a*0.22248840+b*0.71690369+c*0.06060791;,
if(\$4==1,graymode(a,b,c)=a*0.2989+b*0.5870+c*0.1140;,
if(\$4==2,graymode(a,b,c)=(max(a,b,c)+min(a,b,c))/2;,
if(\$4==3,graymode(a,b,c)=min(a,b,c);,
if(\$4==4,graymode(a,b,c)=max(a,b,c);,
graymode(a,b,c)=avg(a,b,c);
);
);
);
);
);
);
);
gl=graymode(i0,i1,i2);
[lerp(gl,i0,rlvl),lerp(gl,i1,glvl),lerp(gl,i2,blvl)]
"

#@gui RGB-Gray Linear Interpolation: fx_rep_lerp_rgb_gray,fx_rep_lerp_rgb_gray_preview(0)
#@gui : _=note("<b>Formula</b>")
#@gui : Mode=choice(0,"Luminosity A","Luminosity B","Lightness","Minimum","Maximum","Average",Weighted")
#@gui : Limit Factor to 100%=bool(0)
#@gui : sep=separator(),_=note("<b>Channel Factor</b>")
#@gui : Red Factor (%)=float(100,0,150)
#@gui : Green Factor (%)=float(100,0,150)
#@gui : Blue Factor (%)=float(100,0,150)
#@gui : Red Factor (%)=float(100,0,100)
#@gui : Green Factor (%)=float(100,0,100)
#@gui : Blue Factor (%)=float(100,0,100)
#@gui : Red Weight=float(1,0,1)
#@gui : Green Weight=float(100,0,1)
#@gui : Blue Weight=float(100,0,1)
#@gui : sep=separator(),_=note("<b>Preview</b>"),Preview Type=choice("Full","Forward Horizontal","Forward Vertical","Backward Horizontal","Backward Vertical","Duplicate Top","Duplicate Left","Duplicate Bottom","Duplicate Right","Duplicate Horizontal","Duplicate Vertical","Checkered","Checkered Inverse"), Preview Split=point(50,50,0,0,200,200,200,0,10)_0
#@gui : sep=separator(),note=note("<small>Author: Reptorian. Latest Update: <i>2020/14/3</i>.</small>")
fx_rep_lerp_rgb_gray:
if \$1==6
if \$2 rep_lerp_rgb_gray \$6%,\$7%,\$8%,\${9-11}
else  rep_lerp_rgb_gray \$3%,\$4%,\$5%,\${9-11}
fi
else
if \$2 rep_lerp_rgb_gray \$6%,\$7%,\$8%,\$1
else  rep_lerp_rgb_gray \$3%,\$4%,\$5%,\$1
fi
fi
fx_rep_lerp_rgb_gray_preview:
gui_split_preview "fx_rep_lerp_rgb_gray \${1-11}",\${-3--1}
u "{\$1}"\
"{\$2}"\
"{\$3}_"{\$2?0:2}\
"{\$4}_"{\$2?0:2}\
"{\$5}_"{\$2?0:2}\
"{\$6}_"{\$2?2:0}\
"{\$7}_"{\$2?2:0}\
"{\$8}_"{\$2?2:0}\
"{\$9}_"{\$1==6?2:0}\
"{\$10}_"{\$1==6?2:0}\
"{\$11}_"{\$1==6?2:0}\
"{\$12}"\
"{\$13,14}"

Edited by Reptillian
Typos elimination again...
• 2
• 1

G'MIC Filter Developer

##### Share on other sites

Your code does not save transparent areas of the image by replacing them with white.

`int A = CurrentPixel.A;`

under

`int B = CurrentPixel.B;`

Add int A after the gray variable in Interpolation()

`private ColorBgra Interpolation(int rval, int gval, int bval, int rlvl, int glvl, int blvl, int gray, int A)`

and add A to ColorBgra Final

`ColorBgra Final = Interpolation(R, G, B, RedFactor, GreenFactor, BlueFactor, Gray, A);`

The code snippet

```if(rr>255){rr=255;}
if(rr<0){rr=0;}
if(gg>255){gg=255;}
if(gg<0){gg=0;}
if(bb>255){bb=255;}
if(bb<0){bb=0;}
return ColorBgra.FromBgr((byte)(bb),(byte)(gg),(byte)(rr));```

can be deleted and replaced with line

`return ColorBgra.FromBgraClamped(bb, gg, rr, A);`

In Luma_A () and Luma_B () in the lines

`double bfactor=(double)(0.06060791*gval);`

and

`double bfactor=(double) (0.1140*gval);`

probably a typo (gval or bval)?

Interesting effect in any case.

##### Share on other sites

All typos fixed and added alpha support. Thanks, Remake.

G'MIC Filter Developer

## Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

×   Pasted as rich text.   Paste as plain text instead

Only 75 emoji are allowed.

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

×
×