Reptillian Posted November 7, 2020 Author Share Posted November 7, 2020 4 minutes ago, MJW said: Different ROIs are processed by different cores, simultaneously. You don't have to do anything besides include the pixel-processing code in Render() for that to happen. I tested it, it is so much more efficient. Quote G'MIC Filter Developer Link to comment Share on other sites More sharing options...
MJW Posted November 7, 2020 Share Posted November 7, 2020 To expand on that a bit, PDN, internally, divides the selection up into a bunch of sub-regions called ROIs. It hands them off the different cores for processing, so one core is rendering one ROI, while simultaneously other cores are rendering different ROIs. 1 Quote Link to comment Share on other sites More sharing options...
Reptillian Posted November 7, 2020 Author Share Posted November 7, 2020 (edited) @MJW I just tested removed background option. It could only fit on glitch art which is to say it's not intentional. Any remedy? Edited November 7, 2020 by Reptillian Quote G'MIC Filter Developer Link to comment Share on other sites More sharing options...
MJW Posted November 7, 2020 Share Posted November 7, 2020 Could you post the current version of the code? Scratch that. I see it posted the plugin's thread. Quote Link to comment Share on other sites More sharing options...
Reptillian Posted November 7, 2020 Author Share Posted November 7, 2020 Spoiler // Name: Rotate By Torus Map // Submenu: Distort // Author: Reptorian // Title: Rotation by Torus Map // Version: 1 // Desc: Rotates images using a Torus Map. // Keywords: distortion // URL: https://forums.getpaint.net/profile/85868-reptillian/ // Help: #region UICode DoubleSliderControl v_circ_a = 45; // [0,100] Circumference A (%) DoubleSliderControl v_circ_b = 100; // [0,100] Circumference B (%) DoubleSliderControl angle = 45; // [-720,720] Angle ListBoxControl distortmode = 3; // {!enable_distortion_blend} Distortion Mode|Soft|Medium|Hard|Alternative Hard|Distroy|Inverse-Distroy|Quad Extrude|Hexagonal ListBoxControl distortmode_a = 0; // {enable_distortion_blend} Distortion Mode A|Soft|Medium|Hard|Alternative Hard|Distroy|Inverse-Distroy|Quad Extrude|Hexagonal ListBoxControl distortmode_b = 3; // {enable_distortion_blend} Distortion Mode B|Soft|Medium|Hard|Alternative Hard|Distroy|Inverse-Distroy|Quad Extrude|Hexagonal DoubleSliderControl v_distort_blend = 50; // [0,100] {enable_distortion_blend} Distortion Mode Blending (%) CheckboxControl enable_distortion_blend = true; // Enable Distortion Blending Mode? PanSliderControl distpos = Pair.Create(0.000, 0.000); // Distortion Position CheckboxControl wraparound_mode = true; // Wraparound Distortion? CheckboxControl remove_background = false; // Remove Background? ListBoxControl outofrange_boundary_choice = 0; // Boundary|None|Neumann|Periodic|Mirror #endregion double ww,hh,cx,cy,offx,offy,eps,sx,sy,new_min,new_max,pi,distort_blend; float f_w,f_h,f_ww,f_hh; int boundary; double vallim_x(double v){ return v - ww * Math.Floor(v/(ww+eps)); } double vallim_y(double v){ return v - hh * Math.Floor(v/(hh+eps)); } double start_x(double v){ if (wraparound_mode){ return vallim_x(v+offx);} else { return v+offx;} } double start_y(double v){ if (wraparound_mode){ return vallim_y(v+offy);} else { return v+offy;} } double nm(double v){ return (v-new_min)*(1/(new_max - new_min)); } double limcut(double v){ return Math.Max(0,Math.Min(1,v)); } int bndcut(double v){ return v>1||v<0?0:1; } double ang2rad(double v){ return Math.PI * (v/180) ; } double rot_x(double a, double b, double c){ return a * Math.Cos(ang2rad(c)) - b * Math.Sin(ang2rad(c)); } double rot_y(double a, double b, double c){ return a * Math.Sin(ang2rad(c)) + b * Math.Cos(ang2rad(c)); } double sur_x(double v){ return (v/ww - .5) * 2 * sx; } double sur_y(double v){ return (v/hh - .5) * 2 * sy; } double unsur_x(double v){ return (v/(2*sx) + .5) * ww; } double unsur_y(double v){ return (v/(2*sy) + .5) * hh; } double lerp(double a,double b){ return a * distort_blend + b * (1 - distort_blend); } float mod(float a,float b){ return a - b * (float)(Math.Floor(a/b)); } float neumann_x(float x){ return Math.Min(f_ww,Math.Max(x,0)); } float neumann_y(float y){ return Math.Min(f_hh,Math.Max(y,0)); } float periodic_x(float x){ return x-f_ww*(float)(Math.Floor(x/f_ww)); } float periodic_y(float y){ return y-f_hh*(float)(Math.Floor(y/f_hh)); } float mirror_x(float x){ float mx = mod(x,f_w*2); if (mx>=f_w) {return 2*f_w - mx - 1;} else {return Math.Abs(mx);} } float mirror_y(float y){ float my = mod(y,f_h*2); if (my>=f_h) {return 2*f_h - my - 1;} else {return Math.Abs(my);} } float out_posx(float posx){ switch(outofrange_boundary_choice){ case 0: return posx; case 1: return neumann_x(posx); case 2: return periodic_x(posx); case 3: return mirror_x(posx); } return 0; } float out_posy(float posy){ switch(outofrange_boundary_choice){ case 0: return posy; case 1: return neumann_y(posy); case 2: return periodic_y(posy); case 3: return mirror_y(posy); } return 0; } double mode_choice(double v,int mode){ switch(mode){ case 0: return (Math.Cos(v*(2*pi)-pi)+1)/2; case 1: return Math.Abs(Math.Cos(v*pi+pi/2)); case 2: return Math.Sqrt(1-Math.Pow(Math.Abs(v-.5)*2,2)); case 3: return Math.Pow(1-Math.Pow(Math.Abs(v-.5)*2,2),1/(2+(1-v))); case 4: return Math.Cos(v*pi)*boundary; case 5: return Math.Cos(v*pi)*boundary*-1; case 6: return 1 - Math.Abs(v-.5) * 2; case 7: double r = (1-Math.Abs(v-.5)*2)*2; return r > 1 ? 1 : r ; } return 0; } double mode(double v){ if (enable_distortion_blend){ return lerp(mode_choice(v,distortmode_a),mode_choice(v,distortmode_b)); } else{ return mode_choice(v,distortmode); } } void Render(Surface dst, Surface src, Rectangle rect) { int w = src.Width; int h = src.Height; f_w = (float)(w); f_h = (float)(h); f_ww = (float)(w)-1; f_hh = (float)(h)-1; double d_w = (double)(w); double d_h = (double)(h); double sd = Math.Max(d_w,d_h)/Math.Min(d_w,d_h); double circ_a = v_circ_a / 100; double circ_b = v_circ_b / 100; double maxang = angle * -1; sx = w > h ? sd : 1 ; sy = w > h ? 1 : sd ; ww = d_w - 1; hh = d_h - 1; cx = ww/2; cy = hh/2; offx = cx * distpos.First * -1; offy = cy * distpos.Second * -1; eps = Math.Pow(10,-10); new_min=Math.Min(circ_a,circ_b); new_max=Math.Max(circ_a,circ_b); distort_blend = v_distort_blend / 100; pi = Math.PI; double xx,yy,radial_gradient,norm_gradient,z_depth,XX,YY,diff_x,diff_y,tyy,nxx,nyy; float posx,posy; ColorBgra tempcolor; for (int y = rect.Top; y < rect.Bottom; y++) { if (IsCancelRequested) return; tyy=start_y((double)(y)); for (int x = rect.Left; x < rect.Right; x++) { nxx=start_x((double)(x)); nyy=tyy; xx=sur_x(nxx); yy=sur_y(nyy); radial_gradient=nm(Math.Sqrt(xx*xx+yy*yy)); norm_gradient=limcut(radial_gradient); boundary=bndcut(radial_gradient); z_depth=mode(norm_gradient)*maxang; XX=rot_x(xx,yy,z_depth); YY=rot_y(xx,yy,z_depth); XX=unsur_x(XX); YY=unsur_y(YY); diff_x=XX-nxx; diff_y=YY-nyy; posx=(float)(x)+(float)(diff_x); posy=(float)(y)+(float)(diff_y); if(outofrange_boundary_choice>0){ posx=Math.Max(0,Math.Min(f_ww,out_posx(posx))); posy=Math.Max(0,Math.Min(f_hh,out_posy(posy))); } tempcolor=src.GetBilinearSample(posx,posy); if (remove_background){ dst[x,y]=ColorBgra.FromBgra(tempcolor.B,tempcolor.G,tempcolor.R,boundary == 1 ? tempcolor.A : (byte)(0)); } else{ dst[x,y] = tempcolor; } } } } Quote G'MIC Filter Developer Link to comment Share on other sites More sharing options...
Reptillian Posted November 7, 2020 Author Share Posted November 7, 2020 Looks like I ran out of approaches to fixing the remove background option. I do not think it's possible. Quote G'MIC Filter Developer Link to comment Share on other sites More sharing options...
MJW Posted November 7, 2020 Share Posted November 7, 2020 This is unrelated to the background problem (which I've yet to figure out), but you can make the code more efficient by moving as much of the code as you can prior to the render loops into PreRender(). Not only is it more efficient, it's also clearer, because it shows what is always the same for all rendering. It will, of course require some variable be moved to outside the methods, to communicate them between PreRender() and Render(). Quote Link to comment Share on other sites More sharing options...
MJW Posted November 7, 2020 Share Posted November 7, 2020 Just now, Reptillian said: Looks like I ran out of approaches to fixing the remove background option. I do not think it's possible. Why wouldn't it be possible? Quote Link to comment Share on other sites More sharing options...
Reptillian Posted November 7, 2020 Author Share Posted November 7, 2020 Just now, MJW said: Why wouldn't it be possible? I tested different ways to use boundary since when boundary is at 1, that means there is a distortion. No matter how I structure the conditional, and the result, the background problem will stay there. There were 10 different ways I coded it, and exhausted all options I could think of. Quote G'MIC Filter Developer Link to comment Share on other sites More sharing options...
MJW Posted November 7, 2020 Share Posted November 7, 2020 What I think you should do first is follow my suggestion of putting the initialization in PreRender(). That may possibly fix the problem, or at least make it easier to find. If you have variables outside the methods (like all the variables defined at the top of the file), they can never be set to different values for different Render() routines, even temporarily. If they are, one Render() routine can end up using the values set in a different Render() routine. By doing the initialization in PreRender(), this is pretty much avoided. Any variable that can't be initialized in PreRender() should be local to Render(), not defined outside it. I rather suspect the problem you're seeing may be related to this. Also, why not just do: tempcolor = (remove_background && (boundary == 0)) ? ColorBgra.Transparent : src.GetBilinearSample(posx, posy); Isn't that the goal, to make it transparent outside the boundary? Do you really need to preserve the old RGB if the alpha is 0? Quote Link to comment Share on other sites More sharing options...
MJW Posted November 7, 2020 Share Posted November 7, 2020 One more thing: This plugin would greatly benefit from an antialiasing option. Quote Link to comment Share on other sites More sharing options...
Reptillian Posted November 7, 2020 Author Share Posted November 7, 2020 It seems that the plugin is even more broken than I thought after testing mirror boundary. All of that would be fixed with PreRender at the sacrifise of speed. I don't know how to add antialiasing there. Quote G'MIC Filter Developer Link to comment Share on other sites More sharing options...
MJW Posted November 7, 2020 Share Posted November 7, 2020 Put the initialization in PreRender() while leaving the rendering where it is, and I think everything will be clearer. Adding antialiasing is quite easy. I can explain it once you get the plugin working as is. Basically, you change the render loop so it calls a method (subroutine) to compute the color, instead of doing it inline, then paste in a couple of routines. I wrote some step-by-step instructions on it, but they may make it seem more difficult then it is. Quote Link to comment Share on other sites More sharing options...
MJW Posted November 7, 2020 Share Posted November 7, 2020 If you can make the program work in PreRender(), you can make it work in Render(). What you might have to do, though, is add a few extra arguments to routines that get called, instead of relying of "global" (i.e., class-level) variables to communicate. As I mentioned, global variables can never be used for values that might be different between Render() instances. Quote Link to comment Share on other sites More sharing options...
Reptillian Posted November 7, 2020 Author Share Posted November 7, 2020 1 minute ago, MJW said: If you can make the program work in PreRender(), you can make it work in Render(). What you might have to do, though, is add a few extra arguments to routines that get called, instead of relying of "global" (i.e, class-level) variables to communicate. As I mentioned, global variable can never be used for values that might be different between Render() instances. So, that is why it does not work how I like yet. In that case, I will address those. Quote G'MIC Filter Developer Link to comment Share on other sites More sharing options...
MJW Posted November 7, 2020 Share Posted November 7, 2020 I think the main problem in that the variable "boundary" is global. Make it local. If a subroutine needs it, pass it as an argument. EDIT: mode_choice() uses boundary. You''ll need to add an argument for it. Quote Link to comment Share on other sites More sharing options...
Recommended Posts
Join the conversation
You can post now and register later. If you have an account, sign in now to post with your account.