Jump to content
How to Install Plugins ×

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.

 

67vCWrZ.png

 

Download - RGB to Linear Interpolation.dll

It's under Effects/Colors

 

------

License - CeCiLLv2.0 - https://cecill.info/licences/Licence_CeCILL_V2-en.html

Source code in C#

 

 

 // Name: RGB-Gray Linear Interpolation
// Submenu: Effects\Colors
// Author: Reptorian
// Title: RGB to Gray Linear Interpolation
// Version: 1.0
// Desc: Interpolate between rgb value and grayscale value
// Keywords: interpolation,adjustment
// 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...
  • Like 2
  • Upvote 1

G'MIC Filter Developer

Link to comment
Share on other sites

Some comments and suggestions:

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

To fix this, add

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.

  • Like 2
Link to comment
Share on other sites

Join the conversation

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

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

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

×
×
  • Create New...