0

I'm new to C# and for my second project I'm trying to write an algorithm that dithers a Bitmap using Floyd-Steinberg method, I followed Coding Trains Video but I get a bunch of errors where RGB values are out of bounds, for example, some times values are 256 and sometimes it's even negatives.

Here is the important chunk of code.

static public Bitmap Imagedither(Bitmap original)
{
    for (int y = 0; y < original.Height - 1; y++)
    {
        for (int x = 1; x < original.Width - 1; x++)
        {
            Color oldPixel = original.GetPixel(x, y);
            Color newPixel = roundColor(oldPixel, 1);
            original.SetPixel(x, y, newPixel);
            Error error = new Error(oldPixel.R - newPixel.R, oldPixel.G - newPixel.G, oldPixel.B - newPixel.B);

            original.SetPixel(x + 1, y    , AddError(original.GetPixel(x + 1, y), error, 7 / 16.0));
            original.SetPixel(x - 1, y + 1, AddError(original.GetPixel(x - 1, y + 1), error, 3 / 16.0));
            original.SetPixel(x    , y + 1, AddError(original.GetPixel(x, y + 1), error, 5 / 16.0));
            original.SetPixel(x + 1, y + 1, AddError(original.GetPixel(x + 1, y + 1), error, 1 / 16.0));
        }
    }
    return original;
}

static public Color roundColor(Color color, int factor)
{
    double R = (double)factor * color.R / 255.0;
    double newR = Math.Round(R) * (255 / factor);
    double G = (double)factor * color.G / 255.0;
    double newG = Math.Round(G) * (255 / factor);
    double B = (double)factor * color.B / 255.0;
    double newB = Math.Round(B) * (255 / factor);
    return Color.FromArgb((int)newR, (int)newG, (int)newB);
}

static public Color AddError(Color pixel, Error error, double amount)
{
    int R = (int)(pixel.R + (error.R * amount));
    int G = (int)(pixel.G + (error.G * amount));
    int B = (int)(pixel.B + (error.B * amount));
    return Color.FromArgb(R > 255 ? 255 : R, G > 255 ? 255 : G, B > 255 ? 255 : B);
}

public class Error
{
    public double R { get; set; }
    public double G { get; set; }
    public double B { get; set; }
    public Error() { }
    public Error(double r, double g, double b)
    {
        R = r;
        G = g;
        B = b;
    }
}
ikaikastine
  • 601
  • 8
  • 22
Googli
  • 15
  • 5
  • 1
    @TaW I don't think so, because everywhere I looked everyone had 255, even Coding Train. – Googli Mar 05 '20 at 20:08
  • You are right. Which lines come up with the errors? Doesn't the debugger help? - This line can create negative values: `Error error = new Error(oldPixel.R - newPixel.R, oldPixel.G - newPixel.G, oldPixel.B `- newPixel.B);` - Instead of limiting only too large values you need to clamp them on both sides, maybe like so `int R = Math.Max(0, Math.Min(255,(int)(pixel.R + (error.R * amount))));`.. – TaW Mar 06 '20 at 10:38
  • @Taw Your solution worked, but I am still wondering why it needed to be clamped. Oh, and the error comes up on the line `return Color.FromArgb(R > 255 ? 255 : R, G > 255 ? 255 : G, B > 255 ? 255 : B);` I think there is some kind of error in calculating the RGB values and the Class Error can have negative values. – Googli Mar 06 '20 at 20:22

0 Answers0