Reptillian Posted May 13, 2020 Share Posted May 13, 2020 (edited) This is a distortion plugin that can be found under 'effect/distort'. What this does is shift pixels to boundary with the option to set direction, influence level, threshold level, and position. Note: There is two difficult to fix bug. If someone wants to try fixing it, then you're more than welcome to, but please share the changes if you do. 1. Transparent dots appears with some settings. 2. Very rarely, the plugin crash. Wait for the render to finish before changing settings. ---------------------------------- Here's the test image which is a strange attractor. (IMGUR doesn't support alpha) With setting on position -53% ; Influence - 71% ; Threshold - 70 ; Axis to Vertical. And of course, the obligatory interface picture To download this plugin -> Shifted Group Pixel to Boundary.dll ---------------------------------- License : CeCiLL v2.0 - https://cecill.info/licences/Licence_CeCILL_V2-en.html Codelab Source code // Name: Axis-Based Shift Grouped Pixel to Boundary // Submenu: Effects / Distortion // Author: Reptorian // Title: Axis-Based Shift Grouped Pixel to Boundary // Version: 0.7 // Desc: Converted from G'MIC-QT rep_sptbwgp cli filter which is also created by Reptorian. // Keywords: Gravity // URL: https://forums.getpaint.net/profile/85868-reptillian/ // Help: #region UICode DoubleSliderControl positionperc = -100; // [-100,100] Position of Pixels (%) DoubleSliderControl influenceperc = 100; // [0,100] Influence Factor (%) IntSliderControl alpha_threshold = 255; // [1,255] Alpha Threshold ListBoxControl axis = 1; // Axis|Horizontal|Vertical #endregion int[] rowNonZeroAlphas = null; int[] columnNonZeroAlphas = null; ColorBgra[,] altsrf = null; void PreRender(Surface dst, Surface src) { int w=src.Width,h=src.Height; columnNonZeroAlphas = new int[w];rowNonZeroAlphas = new int[h]; altsrf = new ColorBgra[w,h]; int non_alpha_count = 0; int tx,ty,nx,ny,fx,fy,N; double tny,tnx; double position = (positionperc / 100 + 1) / 2; double influence_factor = influenceperc / 100; double invert_factor = 1 - influence_factor; if (axis==1) { for (int x = 0 ; x < w ; x++) { non_alpha_count = 0 ; for (int y = 0; y < h; y++){if (src[x,y].A >= alpha_threshold){non_alpha_count++;}} columnNonZeroAlphas[x] = non_alpha_count ; } for (int x = 0 ; x < w ; x++) { ny = h - 1; if (columnNonZeroAlphas[x] != 0) { N = columnNonZeroAlphas[x]; ty = h - N; ny-=(int)(Math.Round(ty * position)); for (int y = h - 1 ; y >= 0 ; y--) { if (N != 0) { if (src[x,y].A >= alpha_threshold) { tny = influence_factor * (double)(ny) + invert_factor * (double)(y); if (position == 1) { fy = (int)(Math.Floor(tny)) ; } else { fy = (int)(Math.Ceiling(tny)) ; } N--; altsrf[x,fy] = src[x,y] ; ny--; } } else {break;} } } } } else { for (int y = 0 ; y < h ; y++) { non_alpha_count = 0 ; for (int x = 0; x < w; x++){if (src[x,y].A >= alpha_threshold){non_alpha_count++;}} rowNonZeroAlphas[y] = non_alpha_count ; } for (int y = 0 ; y < h ; y++) { nx = 0; if (rowNonZeroAlphas[y] != 0) { N = rowNonZeroAlphas[y]; tx = w - N; nx+=(int)(Math.Round(tx * position)); for (int x = 0 ; x < w ; x++) { if (N != 0) { if (src[x,y].A >= alpha_threshold) { tnx = influence_factor * (double)(nx) + invert_factor * (double)(x); if (position == 1) { fx = (int)(Math.Ceiling(tnx)) ; } else { fx = (int)(Math.Floor(tnx)) ; } N--; altsrf[fx,y] = src[x,y] ; nx++; } } else {break;} } } } } } void Render(Surface dst, Surface src, Rectangle rect) { Rectangle selection = EnvironmentParameters.SelectionBounds; for (int y = rect.Top; y < rect.Bottom; y++) { if (IsCancelRequested) return; for (int x = rect.Left; x < rect.Right; x++) { dst[x,y] = altsrf[x,y] ; } } } G'MIC-QT rep_sptbwgp source code #@cli rep_sptbwgp: (eq. to rep_shift_pixel_to_boundary_with_group_pixels) rep_sptbwgp: rep_shift_pixel_to_boundary_with_group_pixels $* #@cli rep_shift_pixel_to_boundary_with_group_pixels: -1<=_position<=1, _axis={ 0=Horizontal | 1=Vertical }, 0<=_influence_factor<=1, _threshold>=0,_channel_mode #@cli : Shifts pixels to boundary by percentage using grouped pixels. position less than .5 means shift will be negative, and position greater than .5 means shift will be positive. #@cli : Assign an argument to _channel_mode if you want to disable restricting effect on alpha channel or avoid manipulating 4 channels image in case of CMYKA image. Only use in rare cases! #@cli : Default values: '_position=-1','_axis=1','_influence_factor=1','_threshold=0','_channel_mode=' rep_shift_pixel_to_boundary_with_group_pixels: skip ${1=-1},${2=1},${3=1},${4=0},${5=} any_channels=0 tcr=3 influence_factor={min(abs($3),1)} position={(($1+1)/2)} if $4>0 m "sptbwgp_remove_alpha_threshold : f i>=$4?i" else m "sptbwgp_remove_alpha_threshold : f i?i" fi if $4>0 m "sptbwgp_filter_nonzero : 100%,100%,100%,1,i(#0,x,y,z,s#-1-1)>=$4?1" else m "sptbwgp_filter_nonzero : 100%,100%,100%,1,i(#0,x,y,z,s#-1-1)?1" fi if $2 m "sptbwgp_create_strip : {w},1,1,1,sum(crop(#-1,x,0,0,0,1,h#-1,1,1))" else m "sptbwgp_create_strip : {h},1,1,1,sum(crop(#-1,0,x,0,0,w#-1,1,1,1))" fi if $position<0 position=0 elif $position>1 position=1 fi if narg($5) if $5>=0 tcr+=1 else any_channels=1 fi fi if $influence_factor repeat $! l[$>] if (s==2||s>$tcr)||$any_channels tic sh {s-1} sptbwgp_remove_alpha_threshold. rm. sptbwgp_filter_nonzero. sptbwgp_create_strip alpinfo={crop(i#-1)} rm[-2,-1] if $2 100%,100%,100%,100%,begin(alpi=[$alpinfo];);if(alpi[x]==h,I#0); else 100%,100%,100%,100%,begin(alpi=[$alpinfo];);if(alpi[y]==w,I#0); fi eval ${-math_lib}" const influence_factor="$influence_factor"; const invert_factor=1-influence_factor; const position="$position"; const alp=s-1; alpi=["$alpinfo"]; if($2 , if(position==1 ,func(a)=ceil(a); ,func(a)=floor(a); ); , if(position==1 ,func(a)=floor(a); ,func(a)=ceil(a); ); ); if($2, for(xx=0,xx<w,xx++, nyy=h-1; if(alpi[xx]&&alpi[xx]<h, N=alpi[xx]; tyy=h-N; nyy-=tyy*position; for(yy=h-1,yy>-1,yy--, if(N, if(i(#0,xx,yy,z,alp), N--; tnyy=influence_factor*nyy+invert_factor*yy; I(#1,xx,func(tnyy))=I(#0,xx,yy); nyy--; ); ,break(); ); ); ); ); , for(yy=0,yy<h,yy++, nxx=0; if(alpi[yy]&&alpi[yy]<w, N=alpi[yy]; txx=w-N; nxx+=txx*position; for(xx=0,xx<w,xx++, if(N, if(i(#0,xx,yy,z,alp), N--; tnxx=influence_factor*nxx+invert_factor*xx; I(#1,func(tnxx),yy)=I(#0,xx,yy); nxx++; ); ,break(); ); ); ); ); ); " rm.. toc fi endl done fi uncommand sptbwgp_filter_nonzero,sptbwgp_create_strip,sptbwgp_remove_alpha_threshold #@gui Grouped Pixel Axis-Based Shift : fx_rep_sptbwgp,fx_rep_sptbwgp_preview #@gui : note=note("Based off MadJik's Paint.NET Gravity Plugin. New feature are shift position, and influence factor."),sep=separator() #@gui : Shift Position (%)=float(0,-100,100) #@gui : Influence Factor (%)=float(0,0,100) #@gui : Threshold (%)=float(0,0,100) #@gui : Axis=choice(0,"Horizontal","Vertical") #@gui : sep=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 : sep=separator(), note=note("<small>Author: Reptorian. Latest Update: <i>2019/5/14</i>.</small>") fx_rep_sptbwgp: position={$1%} axis=$4 threshold={$3%*255} influence={$2%} rep_sptbwgp $position,$axis,$influence,$threshold Edited May 19, 2020 by Reptillian 1 Quote G'MIC Filter Developer Link to comment Share on other sites More sharing options...
Djisves Posted May 14, 2020 Share Posted May 14, 2020 15 hours ago, Reptillian said: Note: There is a difficult to fix bug. Can you give details please? Quote Link to comment Share on other sites More sharing options...
Reptillian Posted May 14, 2020 Author Share Posted May 14, 2020 (edited) 4 hours ago, Djisves said: Can you give details please? Done. 1st requires a new algorithm that is fast. 2nd is a issue that I can't seem to get around. Both gmic-qt and pdn plugin has this issue though they're rare in both case. I do have a theory on solving the first one though results would be a little different. Edited May 14, 2020 by Reptillian 1 Quote G'MIC Filter Developer 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.