Jump to content

Marcsine

Newbies
  • Posts

    1
  • Joined

  • Last visited

Posts posted by Marcsine

  1. I'm a beginner regarding Paint.net plugins. I just wrote a Floyd-Steinberg dithering effect, and it works mostly fine. The only problem is that there are visible seams for images larger than about 128x128. I suspect this is due to Paint.NET calling the render function multiple times, which results in artifacts between different rendering regions, since the color error is not correctly dispersed between each.

     

    Even in JPEG form, these seams are visible.

    test.thumb.jpg.7b1517ae669fc2a26a8fd624d510f16f.jpg

     

    The only way I can think to remedy this would be to force a single call to the render function, but I have no idea how to do that. I'm well aware that such a solution would slow down the effect by a significant amount of time. Of course, if there's a better answer, I'm open to any ideas.

     

    Here's the code. I'd like to fix this issue before properly refactoring, so I apologize for the mess.

    void Render(Surface dst, Surface src, Rectangle rect)
    {
        #if DEBUG
        Debug.WriteLine("Start");
        #endif
    
        ColorBgra PrimaryColor = EnvironmentParameters.PrimaryColor;
        ColorBgra SecondaryColor = EnvironmentParameters.SecondaryColor;
    
        ColorBgra CurrentPixel, newCol;
        int brightness;
        float e;
        int[,] propagate = {{1, 0, 7}, {-1, 1, 3}, {0, 1, 5}, {1, 1, 1}}; //Floyd-Steinberg filter
    
        for (int y = rect.Top; y < rect.Bottom; y++)
        {
            if (IsCancelRequested) return;
            for (int x = rect.Left; x < rect.Right; x++)
            {
                dst[x,y] = src[x,y]; //Copy all pixels to dst, we'll need to edit them on the fly
            }
        }
    
        for (int y = rect.Top; y < rect.Bottom; y++)
        {
            if (IsCancelRequested) return;
            for (int x = rect.Left; x < rect.Right; x++)
            {
                //Change current color to white or black with threshold
                CurrentPixel = dst[x,y];
                brightness = HsvColor.FromColor(CurrentPixel).Value;
                newCol = brightness <= 50 ? PrimaryColor : SecondaryColor;
                newCol.A = CurrentPixel.A;
                dst[x,y] = newCol;
    
                //Calculate error
                e = 1f/16f * (brightness <= 50 ? brightness : brightness - 100);
    
                for (int i = 0; i < propagate.GetLength(0); i++) {
                    int dx = propagate[i, 0] + x;
                    int dy = propagate[i, 1] + y;
                    float de = propagate[i, 2] * e;
    
                    if (dx < rect.Right && dx >= rect.Left && dy < rect.Bottom && dy >= rect.Top)
                    {
                        //Disperse current error based on filter
                        HsvColor col = HsvColor.FromColor(dst[dx,dy]);
                        col.Value = (int)Math.Max(0, Math.Min(100, col.Value + de));
                        ColorBgra bruh = ColorBgra.FromColor(col.ToColor());
                        dst[dx,dy] = bruh;
                    }
                }
            }
        }
    
        #if DEBUG
        Debug.WriteLine("Done");
        #endif
    }

     

×
×
  • Create New...