Method that turns image to BW does not work

38 Views Asked by At

public float ToBlackAndWhite(BlackWhiteMode mode)
    {
        var data = _bmp.LockBits(new Rectangle(0, 0, Width, Height), ImageLockMode.ReadWrite, _bmp.PixelFormat);

        var IsWhite = mode switch
        {
            BlackWhiteMode.Brightness => new Predicate<Color>(x => x.GetBrightness() > 0.5),
            BlackWhiteMode.Hue => new Predicate<Color>(x => x.GetHue() > 180),
            _ => new Predicate<Color>(x => x.GetSaturation() > 0.5)
        };
        
        int sum = 0;
        unsafe
        {
            var pixelSize = Image.GetPixelFormatSize(_bmp.PixelFormat) / 8;

            var ptr = (byte*)data.Scan0;

            byte* row;
            byte* pixel;
            for (int y = 0; y < data.Height; y++)
            {
                row = ptr + y * data.Stride;

                for (int x = 0; x < data.Width; x++)
                {
                    pixel = row + x * pixelSize;

                    if (IsWhite(new(pixel[2], pixel[1], pixel[0])))
                    {
                        pixel[2] = MAX;
                        pixel[1] = MAX;
                        pixel[0] = MAX;
                        sum--;
                    }
                    else
                    {
                        pixel[2] = MIN;
                        pixel[1] = MIN;
                        pixel[0] = MIN;
                        sum++;
                    }
                }
            }
        }

        _bmp.UnlockBits(data);

        return (float)Math.Abs(sum) / PixelCount;
    }

This method locks a System.Drawing.Bitmap and replaces all pixels with black or white pixels based of the IsWhite Predicate (Pixel nearer to black = black, nearer to white = white). But every image I tried only returns a full white or full black image. Why does that happen?

I also have this method that replaces transparent pixels with full visible pixels that uses the same method and it works fine.

public void InvertTransparency()
    {
        var data = _bmp.LockBits(new Rectangle(0, 0, Width, Height), ImageLockMode.ReadWrite, _bmp.PixelFormat);

        unsafe
        {
            var pixelSize = Image.GetPixelFormatSize(_bmp.PixelFormat) / 8;

            var ptr = (byte*)data.Scan0;

            byte* row;
            byte* pixel;

            ulong r = 0;
            ulong g = 0;
            ulong b = 0;
            for (int y = 0; y < data.Height; y++)
            {
                row = ptr + y * data.Stride;

                for (int x = 0; x < data.Width; x++)
                {
                    pixel = row + x * pixelSize;

                    r += pixel[2];
                    g += pixel[1];
                    b += pixel[0];
                }
            }

            var invertedAvg = new Color(
                MAX - (r / (ulong)PixelCount),
                MAX - (g / (ulong)PixelCount),
                MAX - (b / (ulong)PixelCount));


            for (int y = 0; y < data.Height; y++)
            {
                row = ptr + y * data.Stride;

                for (int x = 0; x < data.Width; x++)
                {
                    pixel = row + x * pixelSize;

                    if (pixel[3] < 128)
                    {
                        pixel[3] = MAX;
                        pixel[2] = invertedAvg.R;
                        pixel[1] = invertedAvg.G;
                        pixel[0] = invertedAvg.B;
                        continue;
                    }

                    if (pixel[3] != MAX)
                        pixel[3] = MAX;
                }
            }
        }

        _bmp.UnlockBits(data);
    }

Thank you for helping :)

1

There are 1 best solutions below