Jump to content

Recommended Posts

@MJW Your solution worked!

 

Releasing the code here for testing purpose.

 

 

// Name: Axis-Based Shift Grouped Pixel to Boundary
// Submenu: Effects / Distortion
// Author: Reptorian
// Title: Axis-Based Shift Grouped Pixel to Boundary
// Version: 1.0
// Desc: Extended version of Gravity by MadJik. 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] ;
        }
    }
}

 

 

 

Edited by Reptillian
  • Like 1
Link to post
Share on other sites
2 hours ago, toe_head2001 said:

Obviously, writing outside of the selection is still a bad practice, and just wastes compute resources.

 

Would you expand of this. Do you just mean the write has no effect, so the effort is wasted, or does it waste resources in some other way? If it just wastes the effort to compute the unused pixels, is that behavior that's intended to remain that way, so that it can be relied on? There are probably lots of cases where it would be convenient to clip at most to the selection's bounding rectangle, and not worry that there will be some wasted computations if the user happens to have an elliptical selection.

 

Also, does  is writing outside the ROI in Render() allowed, in the sense that it will properly write into pixels if they're selected? To paraphrase Ghostbusters, are the ROI bounds more guidelines than rules?

  • Like 1
Link to post
Share on other sites
26 minutes ago, MJW said:

Do you just mean the write has no effect, so the effort is wasted

 

Yeah, pretty much.

 

28 minutes ago, MJW said:

is that behavior that's intended to remain that way, so that it can be relied on?

 

I believe so. If pixels outside of the selection are modified, that would be considered a bug.

 

30 minutes ago, MJW said:

Also, does writing outside the ROI in Render() allowed, in the sense that it will properly write into pixels if they're selected?

 

Yes, it will work. Using the ROI is, of course, the recommended route, and probably the most efficient.

  • Like 1
Link to post
Share on other sites
  • 1 month later...

Swirl can be found in Effects > Distort submenu.

Spoiler

// Name: Swirl
// Submenu: Distort
// Author: NSD
// Title: Swirl
// Version: 1.0
// Desc:
// Keywords:
// URL:

#region UICode
DoubleSliderControl intensity = 0.0; // [-1,1] Amount / Direction
DoubleSliderControl zoom = 0; // [0.0,0.999] Zoom
PanSliderControl pan = Pair.Create(0.0, 0.0); // Center
#endregion

void Render(Surface dst, Surface src, Rectangle rect)
{
    int x, y;
    double offx, offy, dx, dy, th, rd, ct, offset, xPan, yPan, zm;
    ColorBgra CurrentPixel;

    Rectangle sel = EnvironmentParameters.SelectionBounds;
    dst.CopySurface(src, rect.Location, rect);

    ct = intensity * 0.2;
    offset = Math.PI / 2.0;

    xPan = (pan.First + 1) / 2 * (sel.Right - sel.Left) + sel.Left;
    yPan = (pan.Second + 1) / 2 * (sel.Bottom - sel.Top) + sel.Top;

    zm  = 1 - zoom;

    for (y = rect.Top; y < rect.Bottom; y++)
    {
        if (IsCancelRequested) return;

        for (x = rect.Left; x < rect.Right; x++)
        {
            dx = x - xPan;
            dy = y - yPan;

            rd = Math.Sqrt((dx * dx + dy * dy) * zm);
            th = Math.Atan2(dx, -dy) - offset;

            offx = rd * Math.Cos(th + ct * rd);
            offy = rd * Math.Sin(th + ct * rd);

            offx += xPan;
            offy += yPan;

            CurrentPixel = src.GetBilinearSampleWrapped((float)offx, (float)offy);
            dst[x,y] = CurrentPixel;
        }
    }
}

 

 

 

Swirl.zip

  • Like 2
  • Upvote 1
Link to post
Share on other sites
  • 1 month later...
  • 1 month later...
On 8/31/2020 at 11:42 AM, NSD said:

This plugin can be found in the Effects Menu.
You need to put OptionBasedLibrary v0.7.8 dlc and dll files in paint.net folder and
WarpTextOnPath dll and dlc files in Effects folder.

 

The UI:
gyPoYl0.png

 

 

WarpTextOnPath.zip 174.27 kB · 10 downloads

Is there a way to install this on the Windows Store version of Paint?

I feel kind of gypped that I purchased the app to support the developer after a good decade of free use, and it seems super difficultr to install plugins now :/

Link to post
Share on other sites

It is not difficult. It requires a once-only setup of the correct folder structure. See the instructions in the yellow panel on this page: https://www.getpaint.net/doc/latest/InstallPlugins.html#4

Link to post
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...