Jump to content
How to Install Plugins ×

Image Modulo Toolkit - 10/09/2020


Recommended Posts

Even though I have done this sort of thing for G'MIC-QT as a cli command, I decided to make it as a plugin just out of doing something different. What this plugin does is modulo functions, but on the end of modulo expression, the value is added by 1. Essentially useful for gradient map preparation, and that's the main reason why this exist. It can also be used for glitch art.

 

Plugin DownloadImage Modulo Toolkit.zip - ( Added new features in 10/09/2020 - Clipboard, Invert )

 

After you install the plugin, it's under Adjustments menu.

 

Here's examples of how it works using various Mode option and 64 as the maximum resulting number.

 

Target Image

 

uEqws17.png

 

Regular Modulo

 

0HtqEwz.png

 

Regular Modulo Continuous

 

f85lS0R.png

 

Divisive Modulo

 

NT4NAqO.png

 

Divisive Modulo Continuous

 

Vb2ArrX.png

 

Modulo Addition

 

FU15Z0T.png

 

Modulo Addition Continuous

 

uteFLCj.png

-------------

Introduction to new features

 

Clipboard - The main purpose of using this is to create new gradients from existing gradient.

Invert*

 

- Before -

 

ido448u.png

- After -

 

nQKdvZ5.png

Invert* = This is mainly used to choose darkening option over lightening option in case of Modulo Addition series

-------------

Special note : I will not be adding features to this plugin. If you want to add features, you are welcome to do so and post it in this thread. Otherwise, I will refer you to my g'mic-qt filter which is Modulus Operations which is under Testing->Reptorian

 

License : GPLv3

 

- Source codes -

CodeLab

 



// Name: Image Modulo Toolkit
// Submenu: Adjustment
// Author: Reptorian
// Title: Image Modulo Toolkit
// Version: 2
// Desc: Adjust image values based on I%(Amount+1)
// Keywords: Modulo
// URL:
// Help:
#region UICode
ListBoxControl<ModuloMode> moduloMode = ModuloMode.Modulo; // Mode | Modulo | Modulo Continuous | Divisive Modulo | Divisive Modulo Continuous | Modulo Addition | Modulo Addition Continuous
IntSliderControl maxNumber = 255; // [1,255] {!ClipboardMode} Maximum Number
CheckboxControl ClipboardMode = false; // Use Clipboard
CheckboxControl Negate = false;// Invert
#endregion

// m_clip surface
Surface m_clip = null;
Surface m_maxNum = null;

private Surface clipboardSurface = null;
private bool readClipboard = false;

protected override void OnDispose(bool disposing)
{
    if (disposing)
    {
        if (m_clip != null) m_clip.Dispose();
        m_clip = null;
        if (clipboardSurface != null) clipboardSurface.Dispose();
        clipboardSurface = null;
    }

    base.OnDispose(disposing);
}

void PreRender(Surface dst, Surface src)
{
    int R1,G1,B1,R2,G2,B2;
    
    ColorBgra CurrentPixel;
    ColorBgra ClipPixel;
    
    m_maxNum = new Surface(src.Size);
    
    float DivMultR,DivMultG,DivMultB,DivMultClipR,DivMultClipG,DivMultClipB;
    
    int maxR,maxG,maxB,maxClipR,maxClipG,maxClipB;
    DivMultR = DivMultG = DivMultB = DivMultClipR = DivMultClipG = DivMultClipB = 255f/maxNumber;
    
    maxR = maxG = maxB = maxClipR = maxClipG = maxClipB = maxNumber;
    R1 = G1 = B1 = R2 = G2 = B2 = 255;
    
    if (m_clip == null)
    {
        m_clip = new Surface(src.Size);
    }

    if (!readClipboard && ClipboardMode)
    {
        readClipboard = true;
        clipboardSurface = Services.GetService<IClipboardService>().TryGetSurface();
    }

    for (int y = 0; y < m_clip.Size.Height; y++)
    {
        if (IsCancelRequested) return;
        for (int x = 0; x < m_clip.Size.Width; x++)
        {
            CurrentPixel = src[x, y];
            int R = CurrentPixel.R;
            int G = CurrentPixel.G;
            int B = CurrentPixel.B;

            if (readClipboard){
                    if (clipboardSurface != null)
                {
                    m_clip[x,y] = clipboardSurface.GetBilinearSampleWrapped(x, y);
                }
                else
                {
                    m_clip[x,y] = Color.Transparent;
                }
                ClipPixel=m_clip[x,y];
                maxClipR = ClipPixel.R > 0 ? ClipPixel.R : 1;
                maxClipG = ClipPixel.G > 0 ? ClipPixel.G : 1;
                maxClipB = ClipPixel.B > 0 ? ClipPixel.B : 1;
                DivMultClipR = 255f / maxClipR;
                DivMultClipG = 255f / maxClipG;
                DivMultClipB = 255f / maxClipB;
            }

            switch (moduloMode)
            {
                case ModuloMode.Modulo:
                    R1 = (byte)(R % (maxR + 1));
                    G1 = (byte)(G % (maxG + 1));
                    B1 = (byte)(B % (maxB + 1));
                    R2 = (byte)(R % (maxClipR + 1));
                    G2 = (byte)(G % (maxClipG + 1));
                    B2 = (byte)(B % (maxClipB + 1));
                    break;
                case ModuloMode.ModuloContinuous:
                    int TR1 = R / (maxR + 1);
                    int TG1 = G / (maxG + 1);
                    int TB1 = B / (maxB + 1);
                    R1 = (TR1 % 2 == 1) ? (byte)(maxNumber - (R % (maxR + 1))) : (byte)(R % (maxR + 1));
                    G1 = (TG1 % 2 == 1) ? (byte)(maxNumber - (G % (maxG + 1))) : (byte)(G % (maxG + 1));
                    B1 = (TB1 % 2 == 1) ? (byte)(maxNumber - (B % (maxB + 1))) : (byte)(B % (maxB + 1));
                    int TR2 = R / (maxClipR + 1);
                    int TG2 = G / (maxClipG + 1);
                    int TB2 = B / (maxClipB + 1);
                    R2 = (TR2 % 2 == 1) ? (byte)(maxClipR - (R % (maxClipR + 1))) : (byte)(R % (maxClipR + 1));
                    G2 = (TG2 % 2 == 1) ? (byte)(maxClipG - (G % (maxClipG + 1))) : (byte)(G % (maxClipG + 1));
                    B2 = (TB2 % 2 == 1) ? (byte)(maxClipB - (B % (maxClipB + 1))) : (byte)(B % (maxClipB + 1));
                    break;
                case ModuloMode.DivisiveModulo:
                    if (maxR != 1) { R1 = (byte)(R * DivMultR);}
                    if (maxG != 1) { G1 = (byte)(G * DivMultG);}
                    if (maxB != 1) { B1 = (byte)(B * DivMultB);}
                    if (maxClipR != 1) { R2 = (byte)(R * DivMultClipR);}
                    if (maxClipG != 1) { G2 = (byte)(G * DivMultClipG);}
                    if (maxClipB != 1) { B2 = (byte)(B * DivMultClipB);}
                    break;
                case ModuloMode.DivisiveModuloContinuous:
                    if (maxR != 1){ float MR1 = R * DivMultR; int CR21 = (int)(MR1 / 256); R1 = (CR21 % 2 == 0) ? (int)(MR1) % 256 : 255 - ((int)(MR1) % 256);}
                    if (maxG != 1){ float MG1 = G * DivMultG; int CG21 = (int)(MG1 / 256); G1 = (CG21 % 2 == 0) ? (int)(MG1) % 256 : 255 - ((int)(MG1) % 256);}
                    if (maxB != 1){ float MB1 = B * DivMultB; int CB21 = (int)(MB1 / 256); B1 = (CB21 % 2 == 0) ? (int)(MB1) % 256 : 255 - ((int)(MB1) % 256);}
                    if (maxClipR != 1){ float MR2 = R * DivMultClipR; int CR22 = (int)(MR2 / 256); R2 = (CR22 % 2 == 0) ? (int)(MR2) % 256 : 255 - ((int)(MR2) % 256);}
                    if (maxClipG != 1){ float MG2 = G * DivMultClipG; int CG22 = (int)(MG2 / 256); G2 = (CG22 % 2 == 0) ? (int)(MG2) % 256 : 255 - ((int)(MG2) % 256);}
                    if (maxClipB != 1){ float MB2 = B * DivMultClipB; int CB22 = (int)(MB2 / 256); B2 = (CB22 % 2 == 0) ? (int)(MB2) % 256 : 255 - ((int)(MB2) % 256);}
                    break;
                case ModuloMode.ModuloAddition:
                    R1 = (byte)((R + maxR) % 256);
                    G1 = (byte)((G + maxG) % 256);
                    B1 = (byte)((B + maxB) % 256);
                    R2 = (byte)((R + maxClipR) % 256);
                    G2 = (byte)((G + maxClipG) % 256);
                    B2 = (byte)((B + maxClipB) % 256);
                    break;
                case ModuloMode.ModuloAdditionContinuous:
                    R1 = ((R + maxR) > 255) ? (int)(255 - (R + maxR) % 256) : R + maxR;
                    G1 = ((G + maxG) > 255) ? (int)(255 - (G + maxG) % 256) : G + maxG;
                    B1 = ((B + maxB) > 255) ? (int)(255 - (B + maxB) % 256) : B + maxB;
                    R2 = ((R + maxClipR) > 255) ? (int)(255 - (R + maxClipR) % 256) : R + maxClipR;
                    G2 = ((G + maxClipG) > 255) ? (int)(255 - (G + maxClipG) % 256) : G + maxClipG;
                    B2 = ((B + maxClipB) > 255) ? (int)(255 - (B + maxClipB) % 256) : B + maxClipB;
                    break;
            }

            if(Negate){
                R1 = 255 - R1;
                G1 = 255 - G1;
                B1 = 255 - B1;
                R2 = 255 - R2;
                G2 = 255 - G2;
                B2 = 255 - B2;
            }

            m_maxNum[x,y] = ColorBgra.FromBgraClamped(B1, G1, R1, CurrentPixel.A);
            m_clip[x,y] = ColorBgra.FromBgraClamped(B2, G2, R2, CurrentPixel.A);
        }
    }
}

void Render(Surface dst, Surface src, Rectangle rect)
{
    ColorBgra CurrentPixel;

    // Step through each row of the current rectangle
    for (int y = rect.Top; y < rect.Bottom; y++)
    {
        if (IsCancelRequested) return;
        // Step through each pixel on the current row of the rectangle
        for (int x = rect.Left; x < rect.Right; x++)
        {
            ColorBgra m_maxPixel = m_maxNum[x,y];
            ColorBgra m_clipPixel = m_clip[x,y];
            if (ClipboardMode){CurrentPixel = m_clipPixel;}
            else {CurrentPixel = m_maxPixel;}

            dst[x,y] = CurrentPixel;
        }
    }
}

enum ModuloMode
{
    Modulo,
    ModuloContinuous,
    DivisiveModulo,
    DivisiveModuloContinuous,
    ModuloAddition,
    ModuloAdditionContinuous
}

 

G'MIC-QT

Spoiler

 




#@cli rep_modo_mc: eq. to 'rep_modular_operation_multiple_channels' : (+)
rep_modo_mc: rep_modular_operation_multiple_channels $*
#@cli rep_modular_operation_multiple_channels: operation,max_channel_value,channel_value(%)...operation_n,max_channel_value_n,channel_value_n
#@cli : Apply modular operation for every 2 layers, and for each channels. Either by blending or applying modf function to every 2 layer per channels.
#@cli : (eq. to 'rep_modo_mc').\n
#@cli : If there is only one set of rep_modo variables,max_channel_value,channel_value, then the values applied here will be applied to the rest of the channels per layers.
#@cli : If there is more than one set, then values will be applied with periodic condition.
#@cli : If channel_value is less than 0 and greater than or equal to -1, then rep_modular_operation function will use layer blending techniques for 2 layers for every 2 layers. If channel value is less than -1, then operation is disabled on that channel (Only applicable with more than one set of rep_modo variables, and one more layer.).\n
#@cli : Note: You can actually assign cmyk mode with this filter by typing 'u cmyk' before 'rep_modo_mc' as the filter will detect if using cmyk instead.\n
#@cli : See 'gmic h rep_modf' for more details on variables.\n
#@cli : Author: Reptorian.
rep_modular_operation_multiple_channels:
cmyk=0
if '${}'=='cmyk' cmyk=1 fi

tcr={$cmyk?4:3}

total_set_of_operation={narg($*)/3}
if $total_set_of_operation!=int($total_set_of_operation) error narg("$*")/3==F fi
oper_cond={max(0,$total_set_of_operation-2)}

if $oper_cond
 {$oper_cond+1},1,1,3,"begin(argset=[${1--1}]);argset[3*x+c];" 
 s. c
 oper_set={crop(#-3)}
 maxchanval_set={crop(#-2)}
 perc_set={crop(#-1)}
 rm[-3--1]
else
 oper_set=$1
 maxchanval_set=$2
 perc_set=$3
fi

if $total_set_of_operation>1
 nset={$total_set_of_operation-1}
else
 nset=1
fi

if $!==1
 if s==2||s>$tcr
  ss={s-1}  
  t_color_oper_set={vector$nset($oper_set)}
  t_color_maxchanval_set={vector$nset($maxchanval_set)}
  t_color_perc_set={vector$nset($perc_set)} 
  color_oper=[{vector$tcr($t_color_oper_set)}]
  color_maxchanval=[{vector$tcr($t_color_maxchanval_set)}]
  color_perc=[{vector$tcr($t_color_perc_set)}]
  repeat $ss
   sh. $>
   if ($color_perc)[$>]>=0
    modf. {($color_oper)[$>]},{($color_maxchanval)[$>]},{abs(($color_perc)[$>])}
   fi
   rm.
  done  
  if $-1>=0
   sh. $ss
   modf. $-3,$-2,$-1
   rm.
  fi  
 else 
  color_oper=[{vectors($oper_set)}]
  color_maxchanval=[{vectors($maxchanval_set)}]
  color_perc=[{vectors($perc_set)}]
  repeat s
   sh. $>
   if ($color_perc)[$>]>=0
    modf. {($color_oper)[$>]},{($color_maxchanval)[$>]},{abs(($color_perc)[$>])}
   fi
   rm.
  done  
 fi
else
 if min($perc_set)>=0&&$-1>=0
  repeat $! l[$>]
   if s==2||s>$tcr
    ss={s-1}
    t_color_oper_set={vector$nset($oper_set)}
    t_color_maxchanval_set={vector$nset($maxchanval_set)}
    t_color_perc_set={vector$nset($perc_set)}
    color_oper=[{vector$tcr($t_color_oper_set)}]
    color_maxchanval=[{vector$tcr($t_color_maxchanval_set)}]
    color_perc=[{vector$tcr($t_color_perc_set)}]
   else
    ss={s}
    color_oper=[{vectors($oper_set)}]
    color_maxchanval=[{vectors($maxchanval_set)}]
    color_perc=[{vectors($perc_set)}]
   fi
   repeat $ss
    sh. $>
    if ($color_perc)[$>]>=0
     modf. {($color_oper)[$>]},{($color_maxchanval)[$>]},{abs(($color_perc)[$>])}
    fi
    rm.
   done
   if s==2||s>$tcr
    sh. {s-1}
    modf. ${-3--1}
    rm.
   fi
  endl done
 else
  repeat int($!/2) l[{$>*2},{$>*2+1}]
   loc_a={$>*2}
   loc_b={$>*2+1}
   if s#0!=s#1 error (s#0#$loc_a!=s#1#$loc_b)==F fi
   if s==2||s>$tcr
    ss={s-1}
    t_color_oper_set={vector$nset($oper_set)}
    t_color_maxchanval_set={vector$nset($maxchanval_set)}
    t_color_perc_set={vector$nset($perc_set)}
    color_oper=[{vector$tcr($t_color_oper_set)}]
    color_maxchanval=[{vector$tcr($t_color_maxchanval_set)}]
    color_perc=[{vector$tcr($t_color_perc_set)}]
   else
    ss={s}
    color_oper=[{vectors($oper_set)}]
    color_maxchanval=[{vectors($maxchanval_set)}]
    color_perc=[{vectors($perc_set)}]
   fi
   repeat $ss
    if ($color_perc)[$>]>=-1
     sh[0] $>
     sh[1] $>
     rep_modo[-2,-1] {($color_oper)[$>]},{($color_maxchanval)[$>]},{($color_perc)[$>]}
     rm[-2,-1]
    fi
   done
   if ($-1>=-1)&&(s==2||s>$tcr)
    v + echo pass v -
    sh[0] {s#0-1}
    sh[1] {s#0-1}
    rep_modo[-2,-1] ${-3--1}
    rm[-2,-1]
   fi
  endl done
 fi
fi
#@cli rep_modo: eq. to 'rep_modular_operation'. : (+)
rep_modo: rep_modular_operation $*
#@cli rep_modular_operation: operation,max_channel_value,channel_value(%)
#@cli : Apply modular operation to every 2 layers. Either by blending layers or applying modf function to every 2 layers.
#@cli : (eq. to 'rep_modo').\n
#@cli : If channel_value is less than 0, then rep_modular_operation function will use layer blending techniques for 2 layers for every 2 layers.
#@cli : See 'gmic h rep_modf' for more details.\n
#@cli : Author: Reptorian.
rep_modular_operation:rv={int($!/2)}
if $!>1&&$3<0
 repeat $rv l[{$>*2},{$>*2+1}] +modf[-1] $1,$2,[-2] modf[0] $1,$2,[1] rm.. endl done
else
 if $!%2
  if $!>2
   modf[^-1] $1,$2,$3
  else
   modf $1,$2,$3
  fi
 else
  modf $1,$2,$3
 fi
fi
#@cli modf: eq. to 'modular_formula'. : (+)
modf: if ${is_image_arg\ $3} pass$3 0 modular_formula $1,$2,[-1] rm.
else modular_formula ${1-3}
fi
#@cli modular_formula : operation,max_channel_value,channel_value(%) : operation,max_channel_value,[image]
#@cli : Apply modular formulas into selected images. 'channel_value' can be values outside the channel ranges of image.
#@cli : (eq. to 'modf').\n
#@cli : operation can be { 0=modulo | 1=modulo continuous | 2=divisive | 3=divisive continuous | 4=additive | 5=additive continuous}
#@cli : Author: Reptorian.
modular_formula:
if ${is_image_arg\ $3} arg_img=-2 e[] "Apply modular formulas using image as reference for variable value."
else arg_img=-1 e[] "Apply modular formulas using {$3*abs($2)} as variable value. "
fi
if $1<0||$1>5 error ""$"1<6||"$"1>=0 => F" fi
if $1!=int($1) error ""$"1!=INT" fi
if $arg_img==-2 pass$3 1 fi
f[0-{$arg_img}] "begin(eps=10^-8;image=1;skip=1;);
 if(image,
  if("$arg_img"==-2
   ,var3_mod=i#-1/abs($2);
   ,var3_mod=$3;image-=1;
  );
  if(!var3_mod,var3_mod=eps);
  maxnum=$1<2?var3_mod*abs($2)+eps:abs($2)+eps;
  var3_mod=var3_mod*abs($2);
  mf(a)=a-maxnum*floor(a/maxnum);
  amf(a)=(if(floor(a/maxnum)%2,(maxnum-eps)-mf(a),mf(a)));
 );
 if(skip,skip-=1;
   if($1>3,
    if(!($1%2)
      ,calc(a)=mf(a+var3_mod);
      ,calc(a)=amf(a+var3_mod);
     );
   ,if($1>1,
    if(!($1%2)
      ,calc(a)=mf(a*(abs($2)/var3_mod));
      ,calc(a)=amf(a*(abs($2)/var3_mod));
     );
   ,if(!($1%2)
      ,calc(a)=mf(a);
      ,calc(a)=amf(a);
     );
    );
   );
 );
 calc(i);
 end(if(!image,
   maxnum=maxnum;
   var3_mod=var3_mod;
  );
  if(!skip;
   if($1>3,
    if(!($1%2)
      ,calc(a)=mf(a+var3_mod);
      ,calc(a)=amf(a+var3_mod);
     );
   ,if($1>1,
    if(!($1%2)
      ,calc(a)=mf(a*(abs($2)/var3_mod));
      ,calc(a)=amf(a*(abs($2)/var3_mod));
     );
   ,if(!($1%2)
      ,calc(a)=mf(a);
      ,calc(a)=amf(a);
     );
    );
   );
  );
 );
"
replace_nan 0
if $arg_img==-2 rm. fi
#@gui Modulos Operation:fx_rep_modo,fx_rep_modo_preview
#@gui :_=note("<b>Initial</b>")
#@gui :Colour Space=choice(0,"RGB","sRGB","RYB","CMY","CMYK","HCY","HSI","HSL","HSV","LAB","LCH","YIQ","YUV","YCbCr","YCbCrGLIC","XYZ","YES","Kodak 1","Ohta")
#@gui :Edit Multiple Channels at once?=bool(0)
#@gui :Reverse Layers?=bool(0)
#@gui :_=separator(),_=note("<b>Operation</b>")
#@gui :Channel Set=choice(0,"Color Channels","Alpha")
#@gui :Channel=choice(0,"First","Second","Third")
#@gui :Channel=choice(0,"First","Second","Third","Fourth")
#@gui :Channel=choice(0,"First","Second","Third","Fourth","Fifth")
#@gui :Operation=choice(3,"Modulo","Modulo - Continuous","Divisive Modulo","Divisive Modulo - Continuous","Additive Modulo","Additive Modulo Continuous")
#@gui :Factor (%)=float(100,0,100)
#@gui :Use Layer as Factor instead?=bool(0)
#@gui :Negate?=bool(0)
#@gui :Operation=choice(3,"Modulo","Modulo - Continuous","Divisive Modulo","Divisive Modulo - Continuous","Additive Modulo","Additive Modulo Continuous")
#@gui :Factor (%)=float(100,0,100)
#@gui :Use Layer as Factor instead?=bool(0)
#@gui :Negate?=bool(0)
#@gui :Disable Effect for Channel #1=bool(0)
#@gui :Operation=choice(3,"Modulo","Modulo - Continuous","Divisive Modulo","Divisive Modulo - Continuous","Additive Modulo","Additive Modulo Continuous")
#@gui :Factor (%)=float(100,0,100)
#@gui :Use Layer as Factor instead?=bool(0)
#@gui :Negate?=bool(0)
#@gui :Disable Effect for Channel #2=bool(0)
#@gui :Operation=choice(3,"Modulo","Modulo - Continuous","Divisive Modulo","Divisive Modulo - Continuous","Additive Modulo","Additive Modulo Continuous")
#@gui :Factor (%)=float(100,0,100)
#@gui :Use Layer as Factor instead?=bool(0)
#@gui :Negate?=bool(0)
#@gui :Disable Effect for Channel #3=bool(0)
#@gui :Operation=choice(3,"Modulo","Modulo - Continuous","Divisive Modulo","Divisive Modulo - Continuous","Additive Modulo","Additive Modulo Continuous")
#@gui :Factor (%)=float(100,0,100)
#@gui :Use Layer as Factor instead?=bool(0)
#@gui :Negate?=bool(0)
#@gui :Disable Effect for Channel #4=bool(0)
#@gui :Operation=choice(3,"Modulo","Modulo - Continuous","Divisive Modulo","Divisive Modulo - Continuous","Additive Modulo","Additive Modulo Continuous")
#@gui :Factor (%)=float(100,0,100)
#@gui :Use Layer as Factor instead?=bool(0)
#@gui :Negate Alpha?=bool(0)
#@gui :Disable Effect for Alpha=bool(1)
#@gui :Disable Effect for Colour Channel #1=bool(0)
#@gui :Disable Effect for Colour Channel #2=bool(0)
#@gui :Disable Effect for Colour Channel #3=bool(0)
#@gui :Disable Effect for Colour Channel #4=bool(0)
#@gui :Disable Effect for Alpha Channel?=bool(1)
#@gui :_=separator(), 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 :_=separator(), _=note("<small>Author: Reptorian. Latest Update: <i>2020/10/14</i>.</small>")
fx_rep_modo:
if ($1>=0&&$1<4)||$1>=9 color_id=[{vector3(255)}]
elif $1==4 color_id=[{vector4(255)}]
elif $1<9 color_id=[360,1,1]
fi

if $1==4 v_n={$2?(!$37&&$11):(!$16&&$15)},{$2?(!$38&&$11):(!$21&&$20)},{$2?(!$39&&$11):(!$26&&$25)},{$2?(!$40&&$11):(!$31&&$30)},{$2?(!$41&&$11):(!$36&&$35)}
else v_n={$2?(!$37&&$11):(!$16&&$15)},{$2?(!$38&&$11):(!$21&&$20)},{$2?(!$39&&$11):(!$26&&$25)},{$2?(!$41&&$11):(!$36&&$35)}
fi

use_negate=max($v_n)
v_n=[$v_n]

color_channels={$1==4?4:3}

convert_colors_fwd=${arg\ $1+1,,rgb2srgb,rgb2ryb,rgb2cmy,,rgb2hcy,rgb2hsi,rgb2hsl,rgb2hsv,rgb2lab8,rgb2lch8,rgb2yiq8,rgb2yuv8,rgb2ycbcr,rgb2ycbcrglic,rgb2xyz8,rgb2yes8,rgb2k18,rgb2ohta8}
convert_colors_bwd=${arg\ $1+1,,srgb2rgb,ryb2rgb,cmy2rgb,,hcy2rgb,hsi2rgb,hsl2rgb,hsv2rgb,lab82rgb,lch82rgb,yiq82rgb,yuv82rgb,ycbcr2rgb,ycbcrglic2rgb,xyz82rgb,yes82rgb,k182rgb,ohta82rgb}

if $1
 repeat $! l[$>]
  if $1!=4
   sh. 0,2
   $convert_colors_fwd.
   rm.
  else
   if s==3 rgb2cmyk
   elif s==4 s c,-3 rgb2cmyk.. a c
   fi
   u cmyk
  fi
 endl done
fi

if $color_channels==3 
 modo_variables={$2?$8:$12},{($color_id)[0]},{$2?($37?-2:($10?-1:$9%)):($16?-2:($14?-1:$13%))},{$2?$8:$17},{($color_id)[1]},{$2?($38?-2:($10?-1:$9%)):($21?-2:($19?-1:$18%))},{$2?$8:$22},{($color_id)[2]},{$2?($39?-2:($10?-1:$9%)):($26?-2:($24?-1:$23%))},$32,255,{($2?$41:$36)?-2:($34?-1:$33%)}
else 
 modo_variables={$2?$8:$12},{($color_id)[0]},{$2?($37?-2:($10?-1:$9%)):($16?-2:($14?-1:$13%))},{$2?$8:$17},{($color_id)[1]},{$2?($38?-2:($10?-1:$9%)):($21?-2:($19?-1:$18%))},{$2?$8:$22},{($color_id)[2]},{$2?($39?-2:($10?-1:$9%)):($26?-2:($24?-1:$23%))},{$2?$8:$27},{($color_id)[3]},{$2?($40?-2:($10?-1:$9%)):($30?-2:($29?-1:$28%))},$32,255,{($2?$41:$36)?-2:($34?-1:$33%)}
fi

rep_modo_mc $modo_variables

if $use_negate
 repeat $! l[$>]
  ss={s-1}
  repeat s
   if $>!=$ss if ($v_n)[$>] sh. $> f. ($color_id)[$>]-i rm. fi
   else if ($v_n)[$>] sh. $> f. 255-i rm. fi
   fi
  done
 endl done
fi

if $1
 repeat $! l[$>]
  if $1!=4
   sh. 0,2
   $convert_colors_bwd.
   rm.
  else
   if s==4 cmyk2rgb
   elif s==5 s c,-4 cmyk2rgb.. a c 
   fi
  fi
 endl done
fi

if !$3 rv fi
if '$_host'=='paintdotnet' k[0] fi

fx_rep_modo_preview:
two_plus_layer={$!>1}
ms=${-max_s}
rv gui_split_preview "fx_rep_modo ${1-41}",${-3--1}
contain_alpha={$ms>3}
activate_individual_channels={!$2?2}
mode_0={$contain_alpha&&$2?2}
mode_1={!$contain_alpha&&!$2?2}
mode_2={$1!=4?(($contain_alpha&&!$2)?2):((!$contain_alpha&&!$2)?2)}
mode_3={!$2?(($1==4&&$contain_alpha)?2)}
use_channel_1_a={$5==0?2}
use_channel_1_b={$6==0?2}
use_channel_1_c={$7==0?2}
use_channel_2_a={$5==1?2}
use_channel_2_b={$6==1?2}
use_channel_2_c={$7==1?2}
use_channel_3_a={$5==2?2}
use_channel_3_b={$6==2?2}
use_channel_3_c={$7==2?2}
activate_a={!$2?(($mode_1?$use_channel_1_a:($mode_2?$use_channel_1_b:$use_channel_1_c))?2)}
activate_b={($mode_1?$use_channel_2_a:($mode_2?$use_channel_2_b:$use_channel_2_c))?2}
activate_c={($mode_1?$use_channel_3_a:($mode_2?$use_channel_3_b:$use_channel_3_c))?2}
activate_d={$1==4?($mode_2?($6==3?2):($mode_3?($7==3?2)))}
activate_e={$2?($mode_0?($4==1?2)):($contain_alpha?($1!=4?($mode_2?($6==3?2):($7==4?2)):($mode_3?$7==4?2)))}
activate_csm={$2&&!$4?2}
activate_bottom_sec={$2?2}
u "{$1}"\
"{$2}"\
"{$3}"\
"{$4}_"{$mode_0}\
"{$5}_"{$mode_1}\
"{$6}_"{$mode_2}\
"{$7}_"{$mode_3}\
"{$8}_"{$activate_csm}\
"{$9}_"{$activate_csm}\
"{$10}_"{$two_plus_layer?$activate_csm}\
"{$11}_"{$activate_csm}\
"{$12}_"{$activate_a}\
"{$13}_"{$activate_a}\
"{$14}_"{$two_plus_layer?$activate_a}\
"{$15}_"{$activate_a}\
"{$16}_"{$activate_a}\
"{$17}_"{$activate_b}\
"{$18}_"{$activate_b}\
"{$19}_"{$two_plus_layer?$activate_b}\
"{$20}_"{$activate_b}\
"{$21}_"{$activate_b}\
"{$22}_"{$activate_c}\
"{$23}_"{$activate_c}\
"{$24}_"{$two_plus_layer?$activate_c}\
"{$25}_"{$activate_c}\
"{$26}_"{$activate_c}\
"{$27}_"{$activate_d}\
"{$28}_"{$activate_d}\
"{$29}_"{$two_plus_layer?$activate_d}\
"{$30}_"{$activate_d}\
"{$31}_"{$activate_d}\
"{$32}_"{$activate_e}\
"{$33}_"{$activate_e}\
"{$34}_"{$two_plus_layer?$activate_e}\
"{$35}_"{$activate_e}\
"{$36}_"{!$2?$activate_e}\
"{$37}_"{$activate_bottom_sec}\
"{$38}_"{$activate_bottom_sec}\
"{$39}_"{$activate_bottom_sec}\
"{$40}_"{$2?($1==4?2)}\
"{$41}_"{($2&&$contain_alpha)?2}\
"{$42}"\
"{$43,$44}"

 

 

 

 

EDIT: @toe_head2001 has provided cleaner code of the current plugin. So I inserted it in here for quicker access.

EDIT: Added new features in 10/09/2020

EDIT: Added G'MIC-QT source code to the g'mic-qt filter, and a special note for feature requests.

 

 

Edited by Reptillian
Update post
  • Like 1
  • Upvote 1

G'MIC Filter Developer

Link to comment
Share on other sites

If you're interested in some feedback for your C# code, I've made some cleanups to your code. Hopefully you'll learn something new. :)

 

Spoiler

// Name: Image Modulo Toolkit
// Submenu: Adjustment
// Author: Reptorian
// Title: Image Modulo Toolkit
// Version: 1
// Desc: Adjust image values based on I%(Amount+1)
// Keywords: Modulo
// URL:
// Help:
#region UICode
ListBoxControl<ModuloMode> moduloMode = ModuloMode.Modulo; // Mode | Modulo | Modulo Continuous | Divisive Modulo | Divisive Modulo Continuous | Modulo Addition | Modulo Addition Continuous
IntSliderControl maxNumber = 255; // [1,255] Maximum Number
#endregion

void Render(Surface dst, Surface src, Rectangle rect)
{
    ColorBgra CurrentPixel;
    float DivMult = 255f / maxNumber;

    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 = CurrentPixel.R;
            int G = CurrentPixel.G;
            int B = CurrentPixel.B;

            switch (moduloMode)
            {
                case ModuloMode.Modulo:
                    R = (byte)(R % (maxNumber + 1));
                    G = (byte)(G % (maxNumber + 1));
                    B = (byte)(B % (maxNumber + 1));
                    break;
                case ModuloMode.ModuloContinuous:
                    int TR = R / (maxNumber + 1);
                    int TG = G / (maxNumber + 1);
                    int TB = B / (maxNumber + 1);
                    R = (TR % 2 == 1) ? (byte)(maxNumber - (R % (maxNumber + 1))) : (byte)(R % (maxNumber + 1));
                    G = (TG % 2 == 1) ? (byte)(maxNumber - (G % (maxNumber + 1))) : (byte)(G % (maxNumber + 1));
                    B = (TB % 2 == 1) ? (byte)(maxNumber - (B % (maxNumber + 1))) : (byte)(R % (maxNumber + 1));
                    break;
                case ModuloMode.DivisiveModulo:
                    if (maxNumber != 1)
                    {
                        R = (byte)(R * DivMult);
                        G = (byte)(G * DivMult);
                        B = (byte)(B * DivMult);
                    }
                    break;
                case ModuloMode.DivisiveModuloContinuous:
                    if (maxNumber != 1)
                    {
                        float MR = R * DivMult;
                        float MG = G * DivMult;
                        float MB = B * DivMult;
                        int CR2 = (int)(MR / 256);
                        int CG2 = (int)(MG / 256);
                        int CB2 = (int)(MB / 256);
                        R = (CR2 % 2 == 0) ? (int)(MR) % 256 : 255 - ((int)(MR) % 256);
                        G = (CG2 % 2 == 0) ? (int)(MG) % 256 : 255 - ((int)(MG) % 256);
                        B = (CB2 % 2 == 0) ? (int)(MB) % 256 : 255 - ((int)(MB) % 256);
                    }
                    break;
                case ModuloMode.ModuloAddition:
                    R = (byte)((R + maxNumber) % 256);
                    G = (byte)((G + maxNumber) % 256);
                    B = (byte)((B + maxNumber) % 256);
                    break;
                case ModuloMode.ModuloAdditionContinuous:
                    R = ((R + maxNumber) > 255) ? (int)(255 - (R + maxNumber) % 256) : R + maxNumber;
                    G = ((G + maxNumber) > 255) ? (int)(255 - (G + maxNumber) % 256) : G + maxNumber;
                    B = ((B + maxNumber) > 255) ? (int)(255 - (B + maxNumber) % 256) : B + maxNumber;
                    break;
            }

            dst[x, y] = ColorBgra.FromBgraClamped(B, G, R, CurrentPixel.A);
        }
    }
}

enum ModuloMode
{
    Modulo,
    ModuloContinuous,
    DivisiveModulo,
    DivisiveModuloContinuous,
    ModuloAddition,
    ModuloAdditionContinuous
}

 

 

  • Upvote 2

(September 25th, 2023)  Sorry about any broken images in my posts. I am aware of the issue.

bp-sig.png
My Gallery  |  My Plugin Pack

Layman's Guide to CodeLab

Link to comment
Share on other sites

28 minutes ago, toe_head2001 said:

If you're interested in some feedback for your C# code, I've made some cleanups to your code. Hopefully you'll learn something new. :)

 

  Reveal hidden contents


// Name: Image Modulo Toolkit
// Submenu: Adjustment
// Author: Reptorian
// Title: Image Modulo Toolkit
// Version: 1
// Desc: Adjust image values based on I%(Amount+1)
// Keywords: Modulo
// URL:
// Help:
#region UICode
ListBoxControl<ModuloMode> moduloMode = ModuloMode.Modulo; // Mode | Modulo | Modulo Continuous | Divisive Modulo | Divisive Modulo Continuous | Modulo Addition | Modulo Addition Continuous
IntSliderControl maxNumber = 255; // [1,255] Maximum Number
#endregion

void Render(Surface dst, Surface src, Rectangle rect)
{
    ColorBgra CurrentPixel;
    float DivMult = 255f / maxNumber;

    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 = CurrentPixel.R;
            int G = CurrentPixel.G;
            int B = CurrentPixel.B;

            switch (moduloMode)
            {
                case ModuloMode.Modulo:
                    R = (byte)(R % (maxNumber + 1));
                    G = (byte)(G % (maxNumber + 1));
                    B = (byte)(B % (maxNumber + 1));
                    break;
                case ModuloMode.ModuloContinuous:
                    int TR = R / (maxNumber + 1);
                    int TG = G / (maxNumber + 1);
                    int TB = B / (maxNumber + 1);
                    R = (TR % 2 == 1) ? (byte)(maxNumber - (R % (maxNumber + 1))) : (byte)(R % (maxNumber + 1));
                    G = (TG % 2 == 1) ? (byte)(maxNumber - (G % (maxNumber + 1))) : (byte)(G % (maxNumber + 1));
                    B = (TB % 2 == 1) ? (byte)(maxNumber - (B % (maxNumber + 1))) : (byte)(R % (maxNumber + 1));
                    break;
                case ModuloMode.DivisiveModulo:
                    if (maxNumber != 1)
                    {
                        R = (byte)(R * DivMult);
                        G = (byte)(G * DivMult);
                        B = (byte)(B * DivMult);
                    }
                    break;
                case ModuloMode.DivisiveModuloContinuous:
                    if (maxNumber != 1)
                    {
                        float MR = R * DivMult;
                        float MG = (float)(G * DivMult);
                        float MB = (float)(B * DivMult);
                        int CR2 = (int)(MR / 256);
                        int CG2 = (int)(MG / 256);
                        int CB2 = (int)(MB / 256);
                        R = (CR2 % 2 == 0) ? (int)(MR) % 256 : 255 - ((int)(MR) % 256);
                        G = (CG2 % 2 == 0) ? (int)(MG) % 256 : 255 - ((int)(MG) % 256);
                        B = (CB2 % 2 == 0) ? (int)(MB) % 256 : 255 - ((int)(MB) % 256);
                    }
                    break;
                case ModuloMode.ModuloAddition:
                    R = (byte)((R + maxNumber) % 256);
                    G = (byte)((G + maxNumber) % 256);
                    B = (byte)((B + maxNumber) % 256);
                    break;
                case ModuloMode.ModuloAdditionContinuous:
                    R = ((R + maxNumber) > 255) ? (int)(255 - (R + maxNumber) % 256) : R + maxNumber;
                    G = ((G + maxNumber) > 255) ? (int)(255 - (G + maxNumber) % 256) : G + maxNumber;
                    B = ((B + maxNumber) > 255) ? (int)(255 - (B + maxNumber) % 256) : B + maxNumber;
                    break;
            }

            dst[x, y] = ColorBgra.FromBgraClamped(B, G, R, CurrentPixel.A);
        }
    }
}

enum ModuloMode
{
    Modulo,
    ModuloContinuous,
    DivisiveModulo,
    DivisiveModuloContinuous,
    ModuloAddition,
    ModuloAdditionContinuous
}

 

 

This is just once in a while thing I just did. Any changes as in cleanup or new features in codes, I'll be putting it in the first post and the first post can be edited if I haven't. I don't plan to work on it anymore.

G'MIC Filter Developer

Link to comment
Share on other sites

6 hours ago, welshblue said:

It definitely helps to speed things up on a few techniques. (post image is down so I can't post a result)

 

Possibly tell people where to find it ?  I checked all sub menus before looking at the source code and realising it was in Adjustments

 

 

On the question, it's done. What other uses you found other than gradient map preparation or glitch art?

G'MIC Filter Developer

Link to comment
Share on other sites

On 12/10/2019 at 2:54 AM, welshblue said:

I checked all sub menus before looking at the source code and realizing it was in Adjustments

Before I added my comment above, I had to use the Plugin Browser to find where this plugin resided.
There have been a few times where the creator of a plugin failed to include information about where the plugin could be found.
I see that Reptillian has corrected this omission.


 

Link to comment
Share on other sites

Link to comment
Share on other sites

  • Reptillian changed the title to Image Modulo Toolkit - 10/09/2020

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...