Jump to content

What would be the ideal c# equilavant for doing this?


Recommended Posts

For future reference as I have plans to do a codelab version of Random Gradient Bars, I would like to know what would be the codelab equivalent.

 

const number_of_bars=((trimmed_ang>=cut_ang)&&(trimmed_ang<cut_ang2))?ceil((abs(1/sin(ang))*ww)/total_width):ceil((abs(1/cos(ang))*hh)/total_width);

v_base=vectornumber_of_bars(0);                                                                                                                          
v_shift=v_base;

$8!=0?fill(v_shift,u(-$8,$8));

 

v_base is a vector of size number_of_bars filled with 0.

v_shift is equal to v_base

 

fill(vector,u(-$8,$8)) fills v_shift with random value between -$8 and $8. $8 being any number that is not inf or nan. u(n1,n2) basically means a random value between n1 and n2.

 

The generic idea is what I want, not the part of the math involved into calculating number_of_bars.

 

Also, what if I want to increment a vector variable by 1 or 2?

Edited by Reptillian

G'MIC Filter Developer

Link to comment
Share on other sites

I'd be a lot easier if you'd just explain in words what you want to do, instead of posting in a computer language I don't know.

 

I don't know if this might answer your question, by the typical way to do the same action on all members of an array is to use a "foreach" loop.

Link to comment
Share on other sites

2 minutes ago, MJW said:

I'd be a lot easier if you'd just explain in words what you want to do, instead of posting in a computer language I don't know.

Well, in words, I would like to create a vector of an arbitrary size as a variable. And then I would make another variable the same as the former variable. Then, I would like to fill the last variable with random numbers between a specified set of numbers.

G'MIC Filter Developer

Link to comment
Share on other sites

2 minutes ago, MJW said:

The usual arbitrary-length array-like class is List<T>

I looked it up here - https://docs.microsoft.com/en-us/dotnet/api/system.collections.generic.list-1?view=net-5.0

 

I don't see a way to specify the length of array.

 

I was thinking more of this - https://www.c-sharpcorner.com/article/what-are-c-sharp-dynamic-arrays/

 

Now, the question is that if I'm supposed to use clear() as you pointed out to me with Popcorn Fractal.

 

And I think a for loop utilizing .Add would be easier. I also read of Array.Resize().

 

So, which approach would be better?

G'MIC Filter Developer

Link to comment
Share on other sites

If you could describe what the algorithm is doing and trying to accomplish, that would be helpful. I don't yet even understand why the array needs to be of arbitrary length.

 

The best method to resize an array structure depends on how often it needs to be resized. If it's only once or twice, Array.Resize() is fine, and has the advantage of simplicity.  Resizing an array allocates new contiguous memory, large enough to hold all the elements, old and new; copies all the old elements; then deallocates the old memory. Classes like List<T> keep separate values for the amount of memory allocated and the current number of elements, so that as long as there's enough memory, only the number of elements needs to change. If there isn't enough memory, it resizes in basically the same way as an array, except extra memory, above the number of elements,  is allocated to allow for expansion.

 

As far as the discussion of dynamic arrays on c-sharpcorner, I hesitate to say this, because I'll probably end up looking like a fool, but I don't think that guy knows what he's talking about. He doesn't seem to understand that the array variable is a pointer (in the general meaning of the term), so you can always do something like:

 

int[] array = new int[10];
 .
 .
 .
array = new int[20];

 

That's not because array  is some sort of special dynamic array; it's because array is a class variable, so it's the address of the actual memory structure ("structure" as a general description, not a C# struct). The second statement replaces the current memory structure with a different one. Assuming there are no other references to the first, it will eventually be garbage collected.

 

EDIT: If the only reason you need an arbitrary-length array is to do something like the example above, you're in luck: that's just how arrays work in C#. The only purpose for using for Resize() is to copy over the elements from the current array into the newly-allocated memory.

Link to comment
Share on other sites

I will attempt to do the idea of recreating gmic Random Gradient Bars (This is a extended version of pyrochild gradient bars with my own code solution) in the weekend. The reason why array needs to be of an arbitrary length is that my algorithm utilize vectors, and the number of element is equal to the numbers of angled bars that can fit from the length of the corner of image to the other corner of image. Each bar is utilized to find the array to use within an array. The math within the code is off, but it's hard to notice regardless when using it in practice, but I'm open to suggestions. More on below.

 

Here's the bar picture for reference:

 

h983Xje.png

 

Also on the code part:

 

7 hours ago, MJW said:

If you could describe what the algorithm is doing and trying to accomplish, that would be helpful.

 

I really wanted to avoid sharing the gmic code as I know I'm the only one here that can read it with proficiency. Maybe it will help give a idea of how it works. Everything within the content of {w*%sub}....{$13?4:2},"" block is the algorithm without using subsampling, and that creates a new image (which is irrelevant in PDN), and then resize to have it anti-aliased (which can be done with for loop using a block of n*n size). There's still some more below the code.

 

The pre-defined variable are x,y,w,h:

 

They stand for:

x = x-coordinate in pixel coordinate

y = y-coordinate in pixel coordinate

w = width of image

h = height of image

 

fmod(a,b) is essentially a macro function. It can be seen as the same as a function where you utilized a,b as argument, and the output returns in the end. The arguments can be scalar or vector. If there is a vector, then you will see a[n] or something like that.

 

macro() is also a macro function, but it doesn't need variables. The output is generated from the existing lines.

 

When you see $3?():(); while there is no equal sign, that is the same as if else. Furthermore, if else in gmic assumes that non-zero number is true, and zero is false.

When you see it with equal sign, that assigns a number to a variable depending on output of if else statement.

 

u(a,b) means a random double number between a,b.

 

% with a number right to it is a modulus operation, otherwise it divides the number left to it by 100.

 

v[n] means the value of an array found in position of n in the entire array of v.

 

fill(vector,formula) or formula(vector,indice,formula) fills a 1D array with formula on the end. Similar to using a for loop to fill a 1D array.

 

vectorm(n) fills a one-dimensional array with size of m with content of n (this can be a scalar or another array) with periodic condition. If m is a variable, then the array will of that size.

vector5(2) = [2,2,2,2,2]

vector5(2,1) = [2,1,2,1,2]

 

 

Spoiler

#@cli rep_randgradbar : eq. to 'rep_random_gradient_bars' : (+)
rep_randgradbar:rep_random_gradient_bars $*
#@cli rep_random_gradient_bars: width>0,spacing>0,-360<=_angle<=360,-90<_skew_angle<90,-1<=_pos_x<=1,-1<=_pos_y<=1,_sublevel>=0,_gradient_shift,_gradient_mul_a,gradient_mul_b,_bar_modulo={ -1=random | 0=cut | 1=periodic | 2=continuous },_random_modulo_out={ 0=cut_and_periodic | 1=cut_and_continuous | 2=periodic_and_continuous },_gradient_color={ 0=B&W | 1=Duotone | 2=Rand-RGB | 3=Rand-HSV },_space_color={ 0=Alpha | 1=Binary Duotone | 2=Gradient Duotone },_symmetry_mode={ 0=none | 1=sym_a | 2=sym_b },_use_inverse={ 0=n/a | 1=random-inverse },_bar_color_a=[,,],_bar_color_b
#@cli : Create image filled with random bars.
#@cli :
#@cli : (eq. to 'rep_randgradbar')
rep_random_gradient_bars:
skip ${3=0},${4=0},${5=0},${6=0},${7=1},${8=0},${9=1},${10=100},${11=-1},${12=},${13=0},${14=0},${15=0},${16=0},${17="[0,0,0]"},${18="[255,255,255]"}
check "($1>0&&$2>=0&&abs($4)<90)"

sub={abs($7)+1}

repeat $! l[$>]
 ow={w}
 oh={h}
 {w*$sub},{h*$sub},1,{$13?4:2},"begin(
   const ww=w-1;
   const hh=h-1;
   const sd=max(ww,hh)/min(ww,hh);
   const sx=ww>hh?sd:1;
   const sy=ww>hh?1:sd;
   const wwsx=ww*sx;
   const hhsy=hh*sy;
   const pyth_img=sqrt(ww^2+hh^2);
   const ww_div_sx=ww/sx;
   const hh_div_sy=hh/sy;
   const cx=ww/2;
   const cy=hh/2;
   const ox=cx-(ww*-$5);
   const oy=cy-(hh*$6);
   const skew_ang=-($4/180)*pi;
   const mdist=tan(skew_ang)*pyth_img;
   const ang=-($3/180)*pi;
   const cos_ang=cos(ang);
   const sin_ang=sin(ang);
   const cut_ang=atan2(cy,cy);
   const cut_ang2=pi-cut_ang;
   const bar_width=$1*"$sub";
   const space_width=$2*"$sub";
   const total_width=bar_width+space_width;
   const half_total_width=total_width>1?total_width/2;
   const symmetry_mode=$15%3;
  
   ($1==1&&$2<2)?(
    const spacing=$2>0?.5:0;
    abs($2)?(calc_spacing()=int(point_x)%2?1;):(calc_spacing()=1;);
   ):(
    const spacing=1-(space_width/(total_width-1));
    calc_spacing()=abs(1-fmod(point_x,total_width)/total_width-.5)*2<=spacing;
   );
  
   rot_x(a,b)=a*cos_ang-b*sin_ang;
   rot_y(a,b)=a*sin_ang+b*cos_ang;
   fmod(a,b)=a-b*floor(a/b);
   fmod_cont(a,b)=floor(a/b)%2?b-fmod(a,b):fmod(a,b);
   fcut(a,b)=(cut(a,-b,b)+b)/2;
 
   const trimmed_ang=fmod(ang,pi);
   const number_of_bars=((trimmed_ang>=cut_ang)&&(trimmed_ang<cut_ang2))?ceil((abs(1/sin(ang))*ww)/total_width):ceil((abs(1/cos(ang))*hh)/total_width);
   const shift_bars=int(number_of_bars/2);
  
   symmetry_mode==1?(calc_bar()=(-1*abs(floor(point_x/total_width))+shift_bars)%number_of_bars;):
   symmetry_mode==2?(calc_bar()=(abs(floor(point_x/total_width))+shift_bars)%number_of_bars;):
                    (calc_bar()=(floor(point_x/total_width)+shift_bars)%number_of_bars;);
  
   v_base=vectornumber_of_bars(0);
   v_shift=v_base;
   v_mult=v_base;
   v_use_invert=v_base;
  
   $8!=0?fill(v_shift,u(-$8,$8));
   fill(v_mult,u($9,$10));
   $16?fill(v_use_invert,round(u(0,1))==1?1:0);
  
   const use_only_one_mode=$11>=0;
  
   use_only_one_mode?(
    const modulo_out=$11%3;
    modulo_out==2?v_modulo_mode=vectornumber_of_bars(2):
    modulo_out==1?v_modulo_mode=vectornumber_of_bars(1):
                  v_modulo_mode=vectornumber_of_bars(0); 
   ):(
    narg($12)?(
     v_modulo_mode=v_base;
     const modulo_out=$12%3;
     modulo_out==0?fill(v_modulo_mode,round(u(0,1))):
     modulo_out==1?fill(v_modulo_mode,round(u(0,1))*2):
                   fill(v_modulo_mode,round(u(0,1))+1);
    ):(
     v_modulo_mode=v_base;
     fill(v_modulo_mode,round(u(0,2))););
   );
   
   rgb2hsv(a)=(
    R=a[0];
    G=a[1];
    B=a[2];
    M = max(R,G,B);
    C = M - min(R,G,B);
    H = 60*(C==0?0:M==R?((G - B)/C)%6:M==G?(B - R)/C + 2:(R - G)/C + 4);
    S = M<=0?0:C/M;
    [H,S,M/255];
   );
   
   ($14||$13==1)?(
    color_a=$17;
    color_b=$18;
    $13==3?(
     color_a=rgb2hsv(color_a);
     color_b=rgb2hsv(color_b);
    );
   ); 
   
   const bc=$13%4; #bc==bar color mode#
   const sc=$14%3; #sc==space color mode#

   bc==3?(
    v_hue=v_base;
    fill(v_hue,u(0,360));
    sc==2?(
     calc_gradient()=spaces?[v_hue[bar],1,final_gradient,255]:[lerp(color_b,color_a,cut(gradient*2+.5,0,1)),255];
    ):
    sc==1?(
     calc_gradient()=spaces?[v_hue[bar],1,final_gradient,255]:[gradient>=0?color_a:color_b,255];
    ):(
     calc_gradient()=[v_hue[bar],1,final_gradient,255*spaces];
    );
   ):
   bc==2?(
    v_rgb_r=v_base;
    v_rgb_g=v_base;
    v_rgb_b=v_base;
    fill(v_rgb_r,u(0,255));
    fill(v_rgb_g,u(0,255));
    fill(v_rgb_b,u(0,255));
    sc==2?(
     calc_gradient()=spaces?[final_gradient*v_rgb_r[bar],final_gradient*v_rgb_g[bar],final_gradient*v_rgb_b[bar],255]:[lerp(color_b,color_a,cut(gradient*2+.5,0,1)),255];
    ):
    sc==1?(
     calc_gradient()=spaces?[final_gradient*v_rgb_r[bar],final_gradient*v_rgb_g[bar],final_gradient*v_rgb_b[bar],255]:[gradient>=0?color_a:color_b,255];
    ):(
     calc_gradient()=[final_gradient*v_rgb_r[bar],final_gradient*v_rgb_g[bar],final_gradient*v_rgb_b[bar],255*spaces];
    );
   ):
   bc==1?(
    sc==2?(
     calc_gradient()=spaces?[lerp(color_a,color_b,final_gradient),255]:[lerp(color_b,color_a,cut(gradient*2+.5,0,1)),255];
    ):
    sc==1?(
     calc_gradient()=spaces?[lerp(color_a,color_b,final_gradient),255]:[gradient>=0?color_a:color_b,255];
    ):(
     calc_gradient()=[lerp(color_a,color_b,final_gradient),255*spaces];
    );
   ):(
    sc==2?(
     calc_gradient()=spaces?[final_gradient,255]:[cut(gradient*2+.5,0,1),255];
    ):
    sc==1?(
     calc_gradient()=spaces?[final_gradient,255]:[gradient>=0,255]
    ):(
     calc_gradient()=[final_gradient,255*spaces];
    );
   );
  
  );
 
  initial_x=(x-ox)/ww*sx;
  initial_y=(y-oy)/hh*sy;
  gradient=-rot_y(initial_x,initial_y)*hh_div_sy/pyth_img;
  point_x=rot_x(initial_x,initial_y)*ww_div_sx+gradient*mdist+half_total_width;
  bar=calc_bar();
  spaces=calc_spacing();
  new_gradient=gradient*v_mult[bar]+v_shift[bar];
  use_modulo_out=v_modulo_mode[bar];
  use_modulo_out==2?(final_gradient=v_use_invert[bar]?1-fmod_cont(new_gradient,1):fmod_cont(new_gradient,1);):
  use_modulo_out==1?(final_gradient=v_use_invert[bar]?1-fmod(new_gradient,1):fmod(new_gradient,1);):
                    (final_gradient=v_use_invert[bar]?1-fcut(new_gradient,1):fcut(new_gradient,1););
  calc_gradient();
  "
  rm..
  if $13==3 hsv2rgb. fi
  if $sub!=1 r. $ow,$oh,100%,100%,5 fi
endl done

 

 

initial_x=coordinate from -1,1

initial_y=coordinate from -1,1

gradient=Reference shade for each bar

point_x=Used to define bars.

bar= find bar number.

spaces= find which are spaces between bar, and which are not. Output is either 1 or 0. If it is 1, then it's a bar, otherwise, it's a space.

new_gradient rescale and multiply using index number at array.

use_modulo_out = which modulo functions to use. fcut means that it'll be a gradient that will be limited to ranges of zero to one. fmod is just assigning gradient to modulus of 1. fmod_continuous is the continuous version of mode.

 

rm removes image. The dot next to it is the indicate. rm.. removes the second last image. rm. removes the last image. rm... removes the last third image.

hsv2rgb of course converts the image from HSV space to RGB.

r resizes the image, and in this case, it resize to original image size with bicubic interpolation.

 

The rest you don't need to know.

 

Edited by Reptillian

G'MIC Filter Developer

Link to comment
Share on other sites

@MJW

 

I found my answer though I have a feeling something might turn out wrong (I can't say for sure). I didn't need to do resize or anything though I might think this is costly.

 

Spoiler

// Name:
// Submenu:
// Author:
// Title:
// Version:
// Desc:
// Keywords:
// URL:
// Help:
#region UICode
ReseedButtonControl seed = 0; // Reseed
IntSliderControl bar_size = 0; // [0,256] Bar Size
IntSliderControl space_size = 0; // [0,256] Space Size
AngleControl degree = 45; // [-180,180] Angle
DoubleSliderControl skew_degree = 0; // [-89,89] Skew Angle
PanSliderControl origin = Pair.Create(0.0,0.0); // Origin
IntSliderControl sublevel = 0; // [0,3] Subsampling
DoubleSliderControl shift = 0; // [0,100] Shift
DoubleSliderControl mult_1 = 0.1; // [0.1,256] Multiplier A
DoubleSliderControl mult_2 = 0.1; // [0.1,256] Multiplier B
ListBoxControl repetition_mode = 0; // Repetition|Random|Cut|Periodic|Continuous
ListBoxControl repetition_bars_modes = 0; // Random Bar Repetition Options|All|Cut and Periodic|Cut and Continuous|Periodic and Continuous
ListBoxControl space_mode = 0; // Space Mode|Alpha|Cut|Gradient
ListBoxControl symmetry = 0; // Symmetry Mode|N/A|A|B
CheckboxControl inversion_mode = false; // Use Inversion
ColorWheelControl space_color_a = ColorBgra.FromBgr(0, 140, 255); // [DarkOrange] Space Color A
ColorWheelControl space_color_b = ColorBgra.FromBgr(0, 215, 255); // [Gold] Space Color B
#endregion

double[] v_base = null;
double[] v_shift = null;
double[] v_mult = null;
double[] v_invert = null;
double[] v_hue = null;
int[] v_rgb_r = null;
int[] v_rgb_g = null;
int[] v_rgb_b = null;
double ang;
int number_of_bars;
int shift_bars;

double lerp(double a,double b,double t){
    return a * (1 - t) + b * t ;
}

void PreRender(Surface dst, Surface src)
{
    int ww = src.Width - 1 ;
    int hh = src.Height - 1 ;
    double cx = (double)(ww) / 2 ;
    double cy = (double)(hh) / 2 ;
    double cut_ang = Math.Atan2(cy,cx) ;
    double cut_ang_2 = Math.PI - cut_ang ;
    ang = ( degree / 180 ) / Math.PI ;
    double trimmed_ang = ang % Math.PI ;
    bool use_shift = shift > 0 ;

    if ((trimmed_ang>=cut_ang)&&(trimmed_ang<cut_ang)){
        number_of_bars =(int) ((double)(ww)*Math.Ceiling(Math.Abs(1/Math.Sin(ang))));
    }
    else
    {
        number_of_bars =(int)((double)(hh)*Math.Ceiling(Math.Abs(1/Math.Cos(ang))));
    }

    shift_bars = number_of_bars / 2;

    v_base = new double[number_of_bars];

    for(int n = 0 ; n < number_of_bars ; n++){
        v_base[n] = 0;
    }

    v_shift = v_base ;
    v_mult = v_base ;
    v_invert = v_base;

    int i_shift_dist;
    double shift_dist;
    int precision = 10000;

    int precision_shift = (int)(shift * precision) ;

    if (use_shift){
        for(int n = 0 ; n < number_of_bars ; n++){
            i_shift_dist = RandomNumber.Next(precision_shift) ;
            shift_dist = (double) (i_shift_dist) / 10000 ;
            if (RandomNumber.Next(255) > 128){
                v_shift[n] = shift_dist;
            }
            
            else{
                v_shift[n] = -shift_dist;
            }
        }
    }

    int i_mult_lerp ;
    double multdist ;

    for(int n = 0 ; n < number_of_bars ; n++){
        i_mult_lerp = RandomNumber.Next(10000);
        multdist = lerp(mult_1,mult_2,(double)(i_mult_lerp)/10000);
        v_mult[n] = multdist;
    }

    if (inversion_mode){
        for(int n = 0 ; n < number_of_bars ; n++){
            if (RandomNumber.Next(255) > 128){
                v_invert[n] = 1;
            }
        }
    }
}

void Render(Surface dst, Surface src, Rectangle rect)
{
    // Delete any of these lines you don't need
    Rectangle selection = EnvironmentParameters.SelectionBounds;
    int centerX = ((selection.Right - selection.Left) / 2) + selection.Left;
    int centerY = ((selection.Bottom - selection.Top) / 2) + selection.Top;
    ColorBgra primaryColor = EnvironmentParameters.PrimaryColor;
    ColorBgra secondaryColor = EnvironmentParameters.SecondaryColor;
    int brushWidth = (int)EnvironmentParameters.BrushWidth;

    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];
            // TODO: Add pixel processing code here
            // Access RGBA values this way, for example:
            // currentPixel.R = primaryColor.R;
            // currentPixel.G = primaryColor.G;
            // currentPixel.B = primaryColor.B;
            // currentPixel.A = primaryColor.A;
            dst[x,y] = currentPixel;
        }
    }
}

 

EDIT: More completed code, but the v_mult for loop is giving me a instance of a object error.

 

Edited by Reptillian

G'MIC Filter Developer

Link to comment
Share on other sites

1 hour ago, Reptillian said:

v_shift = v_base;

v_mult = v_base;

v_invert = v_base;

 

Don't do this with Arrays in C#.  Arrays don't work like that.

 

 

You need something like this:

v_shift = new double[v_base.Length];
Array.Copy(v_base, v_shift, v_base.Length);

 

  • Like 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

Thank you so much for that. That fixed the instance of object error. Down to one error. Pretty sure it should work since the gmic version does work with number_of_bars. I was not able to successfully do the #if Debug thing though.

 

Error message:

System.OverflowException: Array dimensions exceeded supported range.
   at PaintDotNet.Effects.UserScript.PreRender(Surface dst, Surface src)
   at PaintDotNet.Effects.UserScript.OnSetRenderInfo(EffectConfigToken token, RenderArgs dstArgs, RenderArgs srcArgs)
   at PaintDotNet.Effects.CodeLab.OnSetRenderInfo(EffectConfigToken parameters, RenderArgs dstArgs, RenderArgs srcArgs)

 

Current Code:

Spoiler


// Name:
// Submenu:
// Author:
// Title:
// Version:
// Desc:
// Keywords:
// URL:
// Help:

#region UICode
ReseedButtonControl seed = 0; // Reseed
IntSliderControl bar_size = 0; // [0,256] Bar Size
IntSliderControl space_size = 0; // [0,256] Space Size
AngleControl degree = 45; // [-180,180] Angle
DoubleSliderControl skew_degree = 0; // [-89,89] Skew Angle
PanSliderControl origin = Pair.Create(0.0,0.0); // Origin
IntSliderControl sublevel = 0; // [0,3] Subsampling
DoubleSliderControl shift = 0; // [0,100] Shift
DoubleSliderControl mult_1 = 0.1; // [0.1,256] Multiplier A
DoubleSliderControl mult_2 = 0.1; // [0.1,256] Multiplier B
ListBoxControl repetition_mode = 0; // Repetition|Random|Cut|Periodic|Continuous
ListBoxControl repetition_random_repetition_modes = 0; // Random Bar Repetition|All|Cut and Periodic|Cut and Continuous|Periodic and Continuous
ListBoxControl space_mode = 0; // Space Mode|Alpha|Cut|Gradient
ListBoxControl symmetry = 0; // Symmetry Mode|N/A|A|B
CheckboxControl inversion_mode = false; // Use Inversion
ColorWheelControl space_color_a = ColorBgra.FromBgr(0, 140, 255); // [DarkOrange] Space Color A
ColorWheelControl space_color_b = ColorBgra.FromBgr(0, 215, 255); // [Gold] Space Color B
#endregion

double[] v_base = null;
double[] v_shift = null;
double[] v_mult = null;
bool[] v_invert = null;
double[] v_hue = null;
int[] v_modulo_out = null;
int[] v_rgb_r = null;
int[] v_rgb_g = null;
int[] v_rgb_b = null;
double ang;
int number_of_bars;
int shift_bars;

double lerp(double a,double b,double t){
    return a * (1 - t) + b * t ;
}

void PreRender(Surface dst, Surface src)
{
    int ww = src.Width - 1 ;
    int hh = src.Height - 1 ;
    double cx = (double)(ww) / 2 ;
    double cy = (double)(hh) / 2 ;
    double cut_ang = Math.Atan2(cy,cx) ;
    double cut_ang_2 = Math.PI - cut_ang ;
    ang = ( degree / 180 ) / Math.PI ;
    double trimmed_ang = ang % Math.PI ;
    bool use_shift = shift > 0 ;
    int total_width = bar_size + space_size;

    if ((trimmed_ang>=cut_ang)&&(trimmed_ang<cut_ang)){
        number_of_bars =(int)(Math.Ceiling((double)(ww)*Math.Abs(1/Math.Sin(ang))/total_width));
    }
    else
    {
        number_of_bars =(int)(Math.Ceiling((double)(hh)*Math.Abs(1/Math.Cos(ang))/total_width));
    }

    Debug.WriteLine(number_of_bars);

    shift_bars = number_of_bars / 2;

    v_base = new double[number_of_bars];
    v_modulo_out = new int[number_of_bars];
    v_invert = new bool[number_of_bars];

    for(int n = 0 ; n < number_of_bars ; n++){
        v_base[n] = 0;
        v_invert[n] = false ;
    }

    v_shift = new double[v_base.Length];
    v_mult = new double[v_base.Length];
    Array.Copy(v_base, v_shift, v_base.Length);    
    Array.Copy(v_base, v_mult, v_base.Length);

    int i_shift_dist;
    double shift_dist;
    int precision = 10000;

    int precision_shift = (int)(shift * precision) ;

    if (use_shift){
        for(int n = 0 ; n < number_of_bars ; n++){
            i_shift_dist = RandomNumber.Next(precision_shift) ;
            shift_dist = (double) (i_shift_dist) / precision ;
            if (RandomNumber.Next(255) > 128){
                v_shift[n] = shift_dist;
            }
            
            else{
                v_shift[n] = -shift_dist;
            }
        }
    }

    int i_mult_lerp ;
    double multdist ;

    for(int n = 0 ; n < number_of_bars ; n++){
        i_mult_lerp = RandomNumber.Next(10000);
        multdist = lerp(mult_1,mult_2,(double)(i_mult_lerp)/10000);
        v_mult[n] = multdist;
    }

    if (inversion_mode){
        for(int n = 0 ; n < number_of_bars ; n++){
            if (RandomNumber.Next(255) > 128){
                v_invert[n] = true;
            }
        }
    }

    if (repetition_mode > 0) {

    }
    else{

    }
}

void Render(Surface dst, Surface src, Rectangle rect)
{
    // Delete any of these lines you don't need
    Rectangle selection = EnvironmentParameters.SelectionBounds;
    int centerX = ((selection.Right - selection.Left) / 2) + selection.Left;
    int centerY = ((selection.Bottom - selection.Top) / 2) + selection.Top;
    ColorBgra primaryColor = EnvironmentParameters.PrimaryColor;
    ColorBgra secondaryColor = EnvironmentParameters.SecondaryColor;
    int brushWidth = (int)EnvironmentParameters.BrushWidth;

    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];
            // TODO: Add pixel processing code here
            // Access RGBA values this way, for example:
            // currentPixel.R = primaryColor.R;
            // currentPixel.G = primaryColor.G;
            // currentPixel.B = primaryColor.B;
            // currentPixel.A = primaryColor.A;
            dst[x,y] = currentPixel;
        }
    }
}

 

 

Edited by Reptillian

G'MIC Filter Developer

Link to comment
Share on other sites

6 minutes ago, toe_head2001 said:

The calculated value of number_of_bars is -2147483648.  An array length can be negative. 😉

How did you get the value of number_of_bars?

 

The formula should be

const number_of_bars=((trimmed_ang>=cut_ang)&&(trimmed_ang<cut_ang2))?ceil((abs(1/sin(ang))*ww)/total_width):ceil((abs(1/cos(ang))*hh)/total_width);

 

And that doesn't lead -214758.... There must be something I did wrong.

 

EDIT: Ah, yes, the stupid divide by 0 error. I just fixed it by adding min of bar size to 1.

Edited by Reptillian

G'MIC Filter Developer

Link to comment
Share on other sites

4 minutes ago, Reptillian said:

How did you get the value of number_of_bars?

 

I commented out all the code that caused the exception, and then your debug print worked just fine.

  • Like 1

(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

Ok, looks like I'm near completion.

 

Problem:

 

System.NullReferenceException: Object reference not set to an instance of an object.
   at PaintDotNet.Effects.UserScript.PreRender(Surface dst, Surface src)
   at PaintDotNet.Effects.UserScript.OnSetRenderInfo(EffectConfigToken token, RenderArgs dstArgs, RenderArgs srcArgs)
   at PaintDotNet.Effects.CodeLab.OnSetRenderInfo(EffectConfigToken parameters, RenderArgs dstArgs, RenderArgs srcArgs)

 

Spoiler

// Name:
// Submenu:
// Author:
// Title:
// Version:
// Desc:
// Keywords:
// URL:
// Help:

#region UICode
ReseedButtonControl seed = 0; // Reseed
IntSliderControl bar_size = 1; // [1,256] Bar Size
IntSliderControl space_size = 0; // [0,256] Space Size
AngleControl degree = 45; // [-180,180] Angle
DoubleSliderControl skew_degree = 0; // [-89,89] Skew Angle
PanSliderControl origin = Pair.Create(0.0,0.0); // Origin
IntSliderControl sublevel = 0; // [0,3] Subsampling
DoubleSliderControl shift = 0; // [0,100] Shift
DoubleSliderControl mult_1 = 0.1; // [0.1,256] Multiplier A
DoubleSliderControl mult_2 = 0.1; // [0.1,256] Multiplier B
ListBoxControl repetition_mode = 0; // Repetition|Random|Cut|Periodic|Continuous
ListBoxControl repetition_random_repetition_modes = 0; // Random Bar Repetition|All|Cut and Periodic|Cut and Continuous|Periodic and Continuous
ListBoxControl space_mode = 0; // Space Mode|Alpha|Cut|Gradient
ListBoxControl color_space = 0; // Repetition|Gray|Duotone|Random-RGB|Random-HSV
ListBoxControl symmetry = 0; // Symmetry Mode|N/A|A|B
CheckboxControl inversion_mode = false; // Use Inversion
ColorWheelControl space_color_a = ColorBgra.FromBgr(0, 140, 255); // [DarkOrange] Space Color A
ColorWheelControl space_color_b = ColorBgra.FromBgr(0, 215, 255); // [Gold] Space Color B
#endregion
double[] v_base = null;
double[] v_shift = null;
double[] v_mult = null;
int[] v_modulo_out = null;
bool[] v_invert = null;
int[] v_hue = null;
int[] v_rgb_r = null;
int[] v_rgb_g = null;
int[] v_rgb_b = null;
double ang;
int number_of_bars;
int shift_bars;

double rot_x(double a, double b, double cos_ang,double sin_ang){
    return a*cos_ang-b*sin_ang;
}

double rot_y(double a, double b, double cos_ang,double sin_ang){
    return a*sin_ang-b*cos_ang;
}

double lerp(double a,double b,double t){
    return a * (1 - t) + b * t ;
}

double fmod_cont(double a,double b){
    return (Math.Floor(a/b)%2==1)?b-(a%b):a%b;
}

double fcut(double a,double b){
    return (a < -b) ? -b : (a > b) ? b : a;
}

void PreRender(Surface dst, Surface src)
{
    int ww = src.Width - 1 ;
    int hh = src.Height - 1 ;
    double cx = (double)(ww) / 2 ;
    double cy = (double)(hh) / 2 ;
    double cut_ang = Math.Atan2(cy,cx) ;
    double cut_ang_2 = Math.PI - cut_ang ;
    ang = ( degree / 180 ) / Math.PI ;
    double trimmed_ang = ang % Math.PI ;
    bool use_shift = shift > 0 ;
    int total_width = bar_size + space_size;
    double d_total_width = (double)(total_width);
    double d_ww = (double)(ww);
    double d_hh = (double)(hh);

    if ((trimmed_ang>=cut_ang)&&(trimmed_ang<cut_ang)){
        number_of_bars =(int)(Math.Ceiling((Math.Abs(1/Math.Sin(ang))*d_ww)/d_total_width));
    }
    else
    {
        number_of_bars =(int)(Math.Ceiling((Math.Abs(1/Math.Cos(ang))*d_hh)/d_total_width));
    }
    Debug.WriteLine(number_of_bars);

    shift_bars = number_of_bars / 2;

    v_base = new double[number_of_bars];
    v_modulo_out = new int[number_of_bars];
    v_invert = new bool[number_of_bars];
    v_shift = new double[number_of_bars];   

    for(int n = 0 ; n < number_of_bars ; n++){
        v_base[n] = 0;
        v_invert[n] = false ;
    }


    Array.Copy(v_base, v_shift, v_base.Length);

    double shift_dist;
    int precision = 100000;

    if (use_shift){
        for(int n = 0 ; n < number_of_bars ; n++){
            shift_dist = (double)(RandomNumber.Next(precision)) / (double)(precision) ;
            shift_dist*=shift;
            if (RandomNumber.Next(255) > 128){
                v_shift[n] = shift_dist;
            }
            else{
                v_shift[n] = -shift_dist;
            }
        }
    }

    if (repetition_mode > 0) {
        int rep_pos=repetition_mode - 1 ;
        for(int n = 0 ; n < number_of_bars ; n++){
            v_modulo_out[n]=rep_pos;
        }
    }
    else{
        switch(repetition_random_repetition_modes){
            case 1:
                for(int n = 0 ; n < number_of_bars ; n++){
                    v_modulo_out[n] = RandomNumber.Next(1);
                }
                break;
            case 2:
                for(int n = 0 ; n < number_of_bars ; n++){
                    v_modulo_out[n] = RandomNumber.Next(1)*2;
                }
                break;
            case 3:
                for(int n = 0 ; n < number_of_bars ; n++){
                    v_modulo_out[n] = RandomNumber.Next(1)+1;
                }                
                break;
            default:
                for(int n = 0 ; n < number_of_bars ; n++){
                    v_modulo_out[n] = RandomNumber.Next(2);
                }  
                break;
        }
    }

    if (inversion_mode){
        for(int n = 0 ; n < number_of_bars ; n++){
            if (RandomNumber.Next(255) > 128){
                v_invert[n] = true;
            }
        }
    }

    v_hue = new int[number_of_bars];
    v_rgb_r = new int[number_of_bars];
    v_rgb_g = new int[number_of_bars];
    v_rgb_b = new int[number_of_bars];
    v_mult = new double[number_of_bars];

    for(int n = 0 ; n < number_of_bars ; n++){
        v_hue[n] = RandomNumber.Next(359);
        v_rgb_r[n] = RandomNumber.Next(255);
        v_rgb_g[n] = RandomNumber.Next(255);
        v_rgb_b[n] = RandomNumber.Next(255);
        v_mult[n] = lerp(mult_1,mult_2,(double)(RandomNumber.Next(precision))/(double)(precision));
    }

}


void Render(Surface dst, Surface src, Rectangle rect)
{
    // Delete any of these lines you don't need
    int ww = src.Width - 1 ;
    int hh = src.Height - 1 ;
    double d_ww = (double)(ww);
    double d_hh = (double)(hh);
    double sd = Math.Max(d_ww,d_hh)/Math.Min(d_ww,d_hh);
    double sx = d_ww>d_hh?sd:1;
    double sy = d_ww>d_hh?1:sd;
    double cx = (double)(ww) / 2 ;
    double cy = (double)(hh) / 2 ;
    double ox = cx - ((double)(ww)*origin.First);
    double oy = cy - ((double)(hh)*origin.Second);
    double ww_div_sx = (double)(ww)/sx;
    double hh_div_sy = (double)(hh)/sy;
    double pyth_img = Math.Sqrt(d_ww*d_ww+d_hh*d_hh);
    double skew_ang = (skew_degree/180)*Math.PI;
    double cos_ang = Math.Cos(ang);
    double sin_ang = Math.Sin(ang);
    double mdist = Math.Tan(skew_ang)*pyth_img;
    int total_width = bar_size + space_size;
    bool width_test = total_width>1;
    bool bar_and_space_test = bar_size==1&&space_size<2;
    int half_total_width = width_test ? total_width / 2 : 0 ;
    double initial_x,initial_y,spacing,gradient,point_x,new_gradient,final_gradient;
    int bar,bar_id,use_modulo_out,result;
    bool spaces;

    if (bar_and_space_test){
        spacing = (space_size>0)?.5:0;
    }
    else{
        spacing = 1 - ((double)(space_size)/((double)(total_width)-1));
    }

    for (int y = rect.Top; y < rect.Bottom; y++)
    {
        if (IsCancelRequested) return;
        for (int x = rect.Left; x < rect.Right; x++)
        {
            initial_x = (x - ox)/(double)(ww)*sx;
            initial_y = (y - oy)/(double)(hh)*sy;
            gradient = -rot_y(initial_x,initial_y,cos_ang,sin_ang)*hh_div_sy/pyth_img;
            point_x = rot_x(initial_x,initial_y,cos_ang,sin_ang)*ww_div_sx+gradient*mdist+(double)(half_total_width);
            bar_id = (int)(Math.Floor(point_x/(double)(total_width)));

            switch(symmetry){
                case 2:
                    bar=(-1*Math.Abs(bar_id)+shift_bars)%number_of_bars;
                    break;
                case 1:
                    bar=(Math.Abs(bar_id)+shift_bars)%number_of_bars;
                    break;
                default:
                    bar=(bar_id+shift_bars)%number_of_bars;
                    break;
            }

            if(bar_and_space_test){
                if(space_size>0){
                    spaces = (int)(point_x) % 2 == 1;
                }
                else{
                    spaces = true;
                }
            }
            else{
                spaces= Math.Abs(1-(point_x%(double)(total_width))-.5)*2<=spacing;
            }

            new_gradient=gradient*v_mult[bar]+v_shift[bar];
            use_modulo_out=v_modulo_out[bar];

            switch(use_modulo_out){
                case 2: final_gradient=v_invert[bar]?1-fmod_cont(new_gradient,1):fmod_cont(new_gradient,1);
                    break;
                case 1: final_gradient=v_invert[bar]?1-new_gradient%1:new_gradient%1;
                    break;
                default: final_gradient=v_invert[bar]?1-fcut(new_gradient,1):fcut(new_gradient,1);
                    break;
            }
            result = (int)(Math.Round(final_gradient*255));
            dst[x,y] = ColorBgra.FromBgr((byte)(result),(byte)(result),(byte)(result));
        }
    }
}

 

 

G'MIC Filter Developer

Link to comment
Share on other sites

Don't use the RandomNumber field.  It's only meant to be used "behind the scenes" for a reseed button, and doesn't even initialize until Render().

 

Just create your own instance of Random inside PreRender().

For example:

Random myRandom = new Random(int.Max);

myRandom.Next(359)

 

  • Like 1

(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

Well, there seem to be a error after fixing that.

 

System.IndexOutOfRangeException: Index was outside the bounds of the array.
   at PaintDotNet.Effects.UserScript.Render(Surface dst, Surface src, Rectangle rect)
   at PaintDotNet.Effects.UserScript.Render(EffectConfigToken parameters, RenderArgs dstArgs, RenderArgs srcArgs, Rectangle[] rois, Int32 startIndex, Int32 length)
   at PaintDotNet.Effects.CodeLab.Render(EffectConfigToken parameters, RenderArgs dstArgs, RenderArgs srcArgs, Rectangle[] rois, Int32 startIndex, Int32 length)

 

Spoiler

// Name:
// Submenu:
// Author:
// Title:
// Version:
// Desc:
// Keywords:
// URL:
// Help:

#region UICode
ReseedButtonControl seed = 0; // Reseed
IntSliderControl bar_size = 1; // [1,256] Bar Size
IntSliderControl space_size = 0; // [0,256] Space Size
AngleControl degree = 45; // [-180,180] Angle
DoubleSliderControl skew_degree = 0; // [-89,89] Skew Angle
PanSliderControl origin = Pair.Create(0.0,0.0); // Origin
IntSliderControl sublevel = 0; // [0,3] Subsampling
DoubleSliderControl shift = 0; // [0,100] Shift
DoubleSliderControl mult_1 = 0.1; // [0.1,256] Multiplier A
DoubleSliderControl mult_2 = 0.1; // [0.1,256] Multiplier B
ListBoxControl repetition_mode = 0; // Repetition|Random|Cut|Periodic|Continuous
ListBoxControl repetition_random_repetition_modes = 0; // Random Bar Repetition|All|Cut and Periodic|Cut and Continuous|Periodic and Continuous
ListBoxControl space_mode = 0; // Space Mode|Alpha|Cut|Gradient
ListBoxControl color_space = 0; // Repetition|Gray|Duotone|Random-RGB|Random-HSV
ListBoxControl symmetry = 0; // Symmetry Mode|N/A|A|B
CheckboxControl inversion_mode = false; // Use Inversion
ColorWheelControl space_color_a = ColorBgra.FromBgr(0, 140, 255); // [DarkOrange] Space Color A
ColorWheelControl space_color_b = ColorBgra.FromBgr(0, 215, 255); // [Gold] Space Color B
#endregion
double[] v_base = null;
double[] v_shift = null;
double[] v_mult = null;
int[] v_modulo_out = null;
bool[] v_invert = null;
int[] v_hue = null;
int[] v_rgb_r = null;
int[] v_rgb_g = null;
int[] v_rgb_b = null;
double ang;
int number_of_bars;
int shift_bars;

double rot_x(double a, double b, double cos_ang,double sin_ang){
    return a*cos_ang-b*sin_ang;
}

double rot_y(double a, double b, double cos_ang,double sin_ang){
    return a*sin_ang-b*cos_ang;
}

double lerp(double a,double b,double t){
    return a * (1 - t) + b * t ;
}

double fmod_cont(double a,double b){
    return (Math.Floor(a/b)%2==1)?b-(a%b):a%b;
}

double fcut(double a,double b){
    return (a < -b) ? -b : (a > b) ? b : a;
}

void PreRender(Surface dst, Surface src)
{
    Random myRandom = new Random(int.MaxValue);
    int ww = src.Width - 1 ;
    int hh = src.Height - 1 ;
    double cx = (double)(ww) / 2 ;
    double cy = (double)(hh) / 2 ;
    double cut_ang = Math.Atan2(cy,cx) ;
    double cut_ang_2 = Math.PI - cut_ang ;
    ang = ( degree / 180 ) / Math.PI ;
    double trimmed_ang = ang % Math.PI ;
    bool use_shift = shift > 0 ;
    int total_width = bar_size + space_size;
    double d_total_width = (double)(total_width);
    double d_ww = (double)(ww);
    double d_hh = (double)(hh);

    if ((trimmed_ang>=cut_ang)&&(trimmed_ang<cut_ang)){
        number_of_bars =(int)(Math.Ceiling((Math.Abs(1/Math.Sin(ang))*d_ww)/d_total_width));
    }
    else
    {
        number_of_bars =(int)(Math.Ceiling((Math.Abs(1/Math.Cos(ang))*d_hh)/d_total_width));
    }

    shift_bars = number_of_bars / 2;

    v_base = new double[number_of_bars];
    v_modulo_out = new int[number_of_bars];
    v_invert = new bool[number_of_bars];
    v_shift = new double[number_of_bars];   

    for(int n = 0 ; n < number_of_bars ; n++){
        v_base[n] = 0;
        v_invert[n] = false ;
    }


    Array.Copy(v_base, v_shift, v_base.Length);

    double shift_dist;
    int precision = 100000;

    if (use_shift){
        for(int n = 0 ; n < number_of_bars ; n++){
            shift_dist = (double)(myRandom.Next(precision)) / (double)(precision) ;
            shift_dist*=shift;
            if (RandomNumber.Next(255) > 128){
                v_shift[n] = shift_dist;
            }
            else{
                v_shift[n] = -shift_dist;
            }
        }
    }

    if (repetition_mode > 0) {
        int rep_pos=repetition_mode - 1 ;
        for(int n = 0 ; n < number_of_bars ; n++){
            v_modulo_out[n]=rep_pos;
        }
    }
    else{
        switch(repetition_random_repetition_modes){
            case 1:
                for(int n = 0 ; n < number_of_bars ; n++){
                    v_modulo_out[n] = myRandom.Next(1);
                }
                break;
            case 2:
                for(int n = 0 ; n < number_of_bars ; n++){
                    v_modulo_out[n] = myRandom.Next(1)*2;
                }
                break;
            case 3:
                for(int n = 0 ; n < number_of_bars ; n++){
                    v_modulo_out[n] = myRandom.Next(1)+1;
                }                
                break;
            default:
                for(int n = 0 ; n < number_of_bars ; n++){
                    v_modulo_out[n] = myRandom.Next(1);
                }  
                break;
        }
    }

    if (inversion_mode){
        for(int n = 0 ; n < number_of_bars ; n++){
            if (myRandom.Next(255) > 128){
                v_invert[n] = true;
            }
        }
    }

    v_hue = new int[number_of_bars];
    v_rgb_r = new int[number_of_bars];
    v_rgb_g = new int[number_of_bars];
    v_rgb_b = new int[number_of_bars];
    v_mult = new double[number_of_bars];

    for(int n = 0 ; n < number_of_bars ; n++){
        v_hue[n] = myRandom.Next(359);
        v_rgb_r[n] = myRandom.Next(255);
        v_rgb_g[n] = myRandom.Next(255);
        v_rgb_b[n] = myRandom.Next(255);
        v_mult[n] = lerp(mult_1,mult_2,(double)(myRandom.Next(precision))/(double)(precision));
    }

}


void Render(Surface dst, Surface src, Rectangle rect)
{
    // Delete any of these lines you don't need
    int ww = src.Width - 1 ;
    int hh = src.Height - 1 ;
    double d_ww = (double)(ww);
    double d_hh = (double)(hh);
    double sd = Math.Max(d_ww,d_hh)/Math.Min(d_ww,d_hh);
    double sx = d_ww>d_hh?sd:1;
    double sy = d_ww>d_hh?1:sd;
    double cx = (double)(ww) / 2 ;
    double cy = (double)(hh) / 2 ;
    double ox = cx - ((double)(ww)*origin.First);
    double oy = cy - ((double)(hh)*origin.Second);
    double ww_div_sx = (double)(ww)/sx;
    double hh_div_sy = (double)(hh)/sy;
    double pyth_img = Math.Sqrt(d_ww*d_ww+d_hh*d_hh);
    double skew_ang = (skew_degree/180)*Math.PI;
    double cos_ang = Math.Cos(ang);
    double sin_ang = Math.Sin(ang);
    double mdist = Math.Tan(skew_ang)*pyth_img;
    int total_width = bar_size + space_size;
    bool width_test = total_width>1;
    bool bar_and_space_test = bar_size==1&&space_size<2;
    int half_total_width = width_test ? total_width / 2 : 0 ;
    double initial_x,initial_y,spacing,gradient,point_x,new_gradient,final_gradient;
    int bar,bar_id,use_modulo_out,result;
    bool spaces;

    if (bar_and_space_test){
        spacing = (space_size>0)?.5:0;
    }
    else{
        spacing = 1 - ((double)(space_size)/((double)(total_width)-1));
    }

    for (int y = rect.Top; y < rect.Bottom; y++)
    {
        if (IsCancelRequested) return;
        for (int x = rect.Left; x < rect.Right; x++)
        {
            initial_x = (x - ox)/(double)(ww)*sx;
            initial_y = (y - oy)/(double)(hh)*sy;
            gradient = -rot_y(initial_x,initial_y,cos_ang,sin_ang)*hh_div_sy/pyth_img;
            point_x = rot_x(initial_x,initial_y,cos_ang,sin_ang)*ww_div_sx+gradient*mdist+(double)(half_total_width);
            bar_id = (int)(Math.Floor(point_x/(double)(total_width)));

            switch(symmetry){
                case 2:
                    bar=(-1*Math.Abs(bar_id)+shift_bars)%number_of_bars;
                    break;
                case 1:
                    bar=(Math.Abs(bar_id)+shift_bars)%number_of_bars;
                    break;
                default:
                    bar=(bar_id+shift_bars)%number_of_bars;
                    break;
            }

            if(bar_and_space_test){
                if(space_size>0){
                    spaces = (int)(point_x) % 2 == 1;
                }
                else{
                    spaces = true;
                }
            }
            else{
                spaces= Math.Abs(1-(point_x%(double)(total_width))-.5)*2<=spacing;
            }

            new_gradient=gradient*v_mult[bar]+v_shift[bar];
            use_modulo_out=v_modulo_out[bar];

            switch(use_modulo_out){
                case 2: final_gradient=v_invert[bar]?1-fmod_cont(new_gradient,1):fmod_cont(new_gradient,1);
                    break;
                case 1: final_gradient=v_invert[bar]?1-new_gradient%1:new_gradient%1;
                    break;
                default: final_gradient=v_invert[bar]?1-fcut(new_gradient,1):fcut(new_gradient,1);
                    break;
            }
            result = (int)(Math.Round(final_gradient*255));
            dst[x,y] = ColorBgra.FromBgr((byte)(result),(byte)(result),(byte)(result));
        }
    }
}

 

 

Seem to be within Render though bar should always be within the index ranges.  After that I think the random gradient will appear.

G'MIC Filter Developer

Link to comment
Share on other sites

Since you're using bar as the index, make sure its value is not less than zero.

 

This line looks questionable in that regard.

bar=(-1*Math.Abs(bar_id)+shift_bars)%number_of_bars;

 

(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

I know that line is questionable. It is positive only in context of gmic which internal is c++. -1 should be the end of index rather than less than 0.

 

-1 % 3 = 2 basically.

 

So, my solution is to create my own function to get around this problem? Ok, I think I will do that.

Edited by Reptillian

G'MIC Filter Developer

Link to comment
Share on other sites

@toe_head2001 @MJW Thank you both for your help and insight, I just finally got a working code. Not working like I wanted to, but needs tweaks.

 

Spoiler

// Name:
// Submenu:
// Author:
// Title:
// Version:
// Desc:
// Keywords:
// URL:
// Help:

#region UICode
ReseedButtonControl seed = 0; // Reseed
IntSliderControl bar_size = 1; // [1,256] Bar Size
IntSliderControl space_size = 0; // [0,256] Space Size
AngleControl degree = 45; // [-180,180] Angle
DoubleSliderControl skew_degree = 0; // [-89,89] Skew Angle
PanSliderControl origin = Pair.Create(0.0,0.0); // Origin
IntSliderControl sublevel = 0; // [0,3] Subsampling
DoubleSliderControl shift = 0; // [0,100] Shift
DoubleSliderControl mult_1 = 0.1; // [0.1,256] Multiplier A
DoubleSliderControl mult_2 = 0.1; // [0.1,256] Multiplier B
ListBoxControl repetition_mode = 0; // Repetition|Random|Cut|Periodic|Continuous
ListBoxControl repetition_random_repetition_modes = 0; // Random Bar Repetition|All|Cut and Periodic|Cut and Continuous|Periodic and Continuous
ListBoxControl space_mode = 0; // Space Mode|Alpha|Cut|Gradient
ListBoxControl color_space = 0; // Repetition|Gray|Duotone|Random-RGB|Random-HSV
ListBoxControl symmetry = 0; // Symmetry Mode|N/A|A|B
CheckboxControl inversion_mode = false; // Use Inversion
ColorWheelControl space_color_a = ColorBgra.FromBgr(0, 140, 255); // [DarkOrange] Space Color A
ColorWheelControl space_color_b = ColorBgra.FromBgr(0, 215, 255); // [Gold] Space Color B
#endregion
double[] v_base = null;
double[] v_shift = null;
double[] v_mult = null;
int[] v_modulo_out = null;
bool[] v_invert = null;
int[] v_hue = null;
int[] v_rgb_r = null;
int[] v_rgb_g = null;
int[] v_rgb_b = null;
double ang;
int number_of_bars;
int shift_bars;

int mod(double a,double b)
{
  return (int)(a - b * Math.Floor(a/b));
}

double rot_x(double a, double b, double cos_ang,double sin_ang){
    return a*cos_ang-b*sin_ang;
}

double rot_y(double a, double b, double cos_ang,double sin_ang){
    return a*sin_ang-b*cos_ang;
}

double lerp(double a,double b,double t){
    return a * (1 - t) + b * t ;
}

double fmod_cont(double a,double b){
    return (Math.Floor(a/b)%2==1)?b-(a%b):a%b;
}

double fcut(double a,double b){
    return (a < -b) ? -b : (a > b) ? b : a;
}

void PreRender(Surface dst, Surface src)
{
    Random myRandom = new Random(int.MaxValue);
    int ww = src.Width - 1 ;
    int hh = src.Height - 1 ;
    double cx = (double)(ww) / 2 ;
    double cy = (double)(hh) / 2 ;
    double cut_ang = Math.Atan2(cy,cx) ;
    double cut_ang_2 = Math.PI - cut_ang ;
    ang = ( degree / 180 ) / Math.PI ;
    double trimmed_ang = ang % Math.PI ;
    bool use_shift = shift > 0 ;
    int total_width = bar_size + space_size;
    double d_total_width = (double)(total_width);
    double d_ww = (double)(ww);
    double d_hh = (double)(hh);

    if ((trimmed_ang>=cut_ang)&&(trimmed_ang<cut_ang)){
        number_of_bars =(int)(Math.Ceiling((Math.Abs(1/Math.Sin(ang))*d_ww)/d_total_width));
    }
    else
    {
        number_of_bars =(int)(Math.Ceiling((Math.Abs(1/Math.Cos(ang))*d_hh)/d_total_width));
    }

    shift_bars = number_of_bars / 2;

    v_base = new double[number_of_bars];
    v_modulo_out = new int[number_of_bars];
    v_invert = new bool[number_of_bars];
    v_shift = new double[number_of_bars];   

    for(int n = 0 ; n < number_of_bars ; n++){
        v_base[n] = 0;
        v_invert[n] = false ;
    }


    Array.Copy(v_base, v_shift, v_base.Length);

    double shift_dist;
    int precision = 100000;

    if (use_shift){
        for(int n = 0 ; n < number_of_bars ; n++){
            shift_dist = (double)(myRandom.Next(precision)) / (double)(precision) ;
            shift_dist*=shift;
            if (RandomNumber.Next(255) > 128){
                v_shift[n] = shift_dist;
            }
            else{
                v_shift[n] = -shift_dist;
            }
        }
    }

    if (repetition_mode > 0) {
        int rep_pos=repetition_mode - 1 ;
        for(int n = 0 ; n < number_of_bars ; n++){
            v_modulo_out[n]=rep_pos;
        }
    }
    else{
        switch(repetition_random_repetition_modes){
            case 1:
                for(int n = 0 ; n < number_of_bars ; n++){
                    v_modulo_out[n] = myRandom.Next(1);
                }
                break;
            case 2:
                for(int n = 0 ; n < number_of_bars ; n++){
                    v_modulo_out[n] = myRandom.Next(1)*2;
                }
                break;
            case 3:
                for(int n = 0 ; n < number_of_bars ; n++){
                    v_modulo_out[n] = myRandom.Next(1)+1;
                }                
                break;
            default:
                for(int n = 0 ; n < number_of_bars ; n++){
                    v_modulo_out[n] = myRandom.Next(1);
                }  
                break;
        }
    }

    if (inversion_mode){
        for(int n = 0 ; n < number_of_bars ; n++){
            if (myRandom.Next(255) > 128){
                v_invert[n] = true;
            }
        }
    }

    v_hue = new int[number_of_bars];
    v_rgb_r = new int[number_of_bars];
    v_rgb_g = new int[number_of_bars];
    v_rgb_b = new int[number_of_bars];
    v_mult = new double[number_of_bars];

    for(int n = 0 ; n < number_of_bars ; n++){
        v_hue[n] = myRandom.Next(359);
        v_rgb_r[n] = myRandom.Next(255);
        v_rgb_g[n] = myRandom.Next(255);
        v_rgb_b[n] = myRandom.Next(255);
        v_mult[n] = lerp(mult_1,mult_2,(double)(myRandom.Next(precision))/(double)(precision));
    }

}


void Render(Surface dst, Surface src, Rectangle rect)
{
    // Delete any of these lines you don't need
    int ww = src.Width - 1 ;
    int hh = src.Height - 1 ;
    double d_ww = (double)(ww);
    double d_hh = (double)(hh);
    double sd = Math.Max(d_ww,d_hh)/Math.Min(d_ww,d_hh);
    double sx = d_ww>d_hh?sd:1;
    double sy = d_ww>d_hh?1:sd;
    double cx = (double)(ww) / 2 ;
    double cy = (double)(hh) / 2 ;
    double ox = cx - ((double)(ww)*origin.First);
    double oy = cy - ((double)(hh)*origin.Second);
    double ww_div_sx = (double)(ww)/sx;
    double hh_div_sy = (double)(hh)/sy;
    double pyth_img = Math.Sqrt(d_ww*d_ww+d_hh*d_hh);
    double skew_ang = (skew_degree/180)*Math.PI;
    double cos_ang = Math.Cos(ang);
    double sin_ang = Math.Sin(ang);
    double mdist = Math.Tan(skew_ang)*pyth_img;
    int total_width = bar_size + space_size;
    bool width_test = total_width>1;
    bool bar_and_space_test = bar_size==1&&space_size<2;
    int half_total_width = width_test ? total_width / 2 : 0 ;
    double initial_x,initial_y,spacing,gradient,point_x,new_gradient,final_gradient;
    int bar,bar_id,use_modulo_out,result;
    bool spaces;

    if (bar_and_space_test){
        spacing = (space_size>0)?.5:0;
    }
    else{
        spacing = 1 - ((double)(space_size)/((double)(total_width)-1));
    }

    for (int y = rect.Top; y < rect.Bottom; y++)
    {
        if (IsCancelRequested) return;
        for (int x = rect.Left; x < rect.Right; x++)
        {
            initial_x = (x - ox)/(double)(ww)*sx;
            initial_y = (y - oy)/(double)(hh)*sy;
            gradient = -rot_y(initial_x,initial_y,cos_ang,sin_ang)*hh_div_sy/pyth_img;
            point_x = rot_x(initial_x,initial_y,cos_ang,sin_ang)*ww_div_sx+gradient*mdist+(double)(half_total_width);
            bar_id = (int)(Math.Floor(point_x/(double)(total_width)));

            switch(symmetry){
                case 2:
                    bar=mod(-1*Math.Abs(bar_id)+shift_bars,number_of_bars);
                    break;
                case 1:
                    bar=mod(Math.Abs(bar_id)+shift_bars,number_of_bars);
                    break;
                default:
                    bar=(bar_id+shift_bars)%number_of_bars;
                    bar=mod(bar_id+shift_bars,number_of_bars);
                    break;
            }

            if(bar_and_space_test){
                if(space_size>0){
                    spaces = (int)(point_x) % 2 == 1;
                }
                else{
                    spaces = true;
                }
            }
            else{
                spaces= Math.Abs(1-(point_x%(double)(total_width))-.5)*2<=spacing;
            }

            new_gradient=gradient*v_mult[bar]+v_shift[bar];
            use_modulo_out=v_modulo_out[bar];

            switch(use_modulo_out){
                case 2: final_gradient=v_invert[bar]?1-fmod_cont(new_gradient,1):fmod_cont(new_gradient,1);
                    break;
                case 1: final_gradient=v_invert[bar]?1-new_gradient%1:new_gradient%1;
                    break;
                default: final_gradient=v_invert[bar]?1-fcut(new_gradient,1):fcut(new_gradient,1);
                    break;
            }
            result = (int)(Math.Round(final_gradient*255));
            dst[x,y] = ColorBgra.FromBgr((byte)(result),(byte)(result),(byte)(result));
        }
    }
}

 

 

G'MIC Filter Developer

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