0

I have a Windows Forms application that takes a screenshot of a specific portion of the screen, then displays it in a picture box (pictureBox1). It works when I don't try to convert it, but I want to convert the image to grayscale or black and white. The problem is when I convert it to grayscale, it still shows the original picture in the picture box.

Here is a picture, how the application looks when it runs properly

Here is the code when it works, without the conversion:

private void button1_Click(object sender, EventArgs e)
{
        Rectangle rectangle = new Rectangle(660, 200, 600, 100);
        pictureBox1.Height = rectangle.Height;
        pictureBox1.Width = rectangle.Width;

        imageUploader(rectangle);
}

public void imageUploader(Rectangle rectangle)
{
        Bitmap bitmap = new Bitmap(rectangle.Width, rectangle.Height, PixelFormat.Format32bppArgb);
        Graphics graphics = Graphics.FromImage(bitmap);
        graphics.CopyFromScreen(rectangle.Left, rectangle.Top, 0, 0, bitmap.Size, CopyPixelOperation.SourceCopy);

        bitmap.Save("proba.jpeg", ImageFormat.Jpeg);

        pictureBox1.Image = bitmap;
} 

Here is the conversion method, which I tried out:

public void toGrayscale(Bitmap bitmap)
    {
        Color c;

        for (int y = 0; y < bitmap.Height; y++)
        {
            for (int x = 0; x < bitmap.Width; x++)
            {
                c = bitmap.GetPixel(x,y);
                Color newColor = Color.FromArgb(c.R,0,0);
                bitmap.SetPixel(x,y,newColor);
            }
        }
    }

After I used this conversion (see below) the image showed up in the picture box, but it wasn't grayscale.

Here is the modified imageUploader void with the conversion:

    public void imageUploader(Rectangle rectangle)
    {
        Bitmap bitmap = new Bitmap(rectangle.Width, rectangle.Height, PixelFormat.Format32bppArgb);
        toGrayscale(bitmap);
        Graphics graphics = Graphics.FromImage(bitmap);
        graphics.CopyFromScreen(rectangle.Left, rectangle.Top, 0, 0, bitmap.Size, CopyPixelOperation.SourceCopy);

        bitmap.Save("proba.jpeg", ImageFormat.Jpeg);

        pictureBox1.Image = bitmap;
    } 
harcipulyka
  • 117
  • 1
  • 6
  • The very same question was posted a few hours ago. What gives?? – TaW Apr 03 '19 at 17:02
  • Also: You don't convert the bitmap to grayscale at all. All you do is change the old pixels. But then you copy new, colored pixel into it. – TaW Apr 03 '19 at 17:04
  • I uploaded it yesterday, but a member wasn't quite satisfied with the question. And I updated the toGrayscale method but it still doesn't work. – harcipulyka Apr 03 '19 at 18:05
  • You can write a better and faster greyscale converter but you should use a ColorMatrix for the job. – TaW Apr 03 '19 at 19:50

2 Answers2

0

You are converting an empty Bitmap to greyscale, then copying over the (nominally) greyscaled Bitmap with an image from the screen. Here is your code, annotated to describe what it is doing:

// This line creates an empty Bitmap.
Bitmap bitmap = new Bitmap(rectangle.Width, rectangle.Height, PixelFormat.Format32bppArgb);
// This line converts the empty Bitmap to grayscale.
toGrayscale(bitmap);
// This line creates a Graphics drawing surface from your bitmap.
Graphics graphics = Graphics.FromImage(bitmap);
// This line overwrites the image data from your bitmap with an image from the screen.
graphics.CopyFromScreen(rectangle.Left, rectangle.Top, 0, 0, bitmap.Size, CopyPixelOperation.SourceCopy);

You need to find some way to take the data you got from the screen and make it greyscale. You have not done this. You have made a greyscale image, but then you have thrown it away by writing other data on top of it. It happens that that replacement data is not greyscale.

Hammerite
  • 21,755
  • 6
  • 70
  • 91
0

It appears that your issue is here:

    public void imageUploader(Rectangle rectangle)
    {
        Bitmap bitmap = new Bitmap(rectangle.Width, rectangle.Height, PixelFormat.Format32bppArgb);
        toGrayscale(bitmap);
        Graphics graphics = Graphics.FromImage(bitmap);
        graphics.CopyFromScreen(rectangle.Left, rectangle.Top, 0, 0, bitmap.Size, CopyPixelOperation.SourceCopy);

        bitmap.Save("proba.jpeg", ImageFormat.Jpeg);

        pictureBox1.Image = bitmap;
    }

You're converting each pixel of the bitmap to greyscale (oddly it looks like you're only grabbing the red channel) then copying from the screen, which overwrites your conversion. To fix it, all you should need to do is move the toGreyscale after you copy from the screen, like this:

    public void imageUploader(Rectangle rectangle)
    {
        Bitmap bitmap = new Bitmap(rectangle.Width, rectangle.Height, PixelFormat.Format32bppArgb);
        Graphics graphics = Graphics.FromImage(bitmap);
        graphics.CopyFromScreen(rectangle.Left, rectangle.Top, 0, 0, bitmap.Size, CopyPixelOperation.SourceCopy);
        toGrayscale(bitmap);  # Moved after the copy from screen
        bitmap.Save("proba.jpeg", ImageFormat.Jpeg);

        pictureBox1.Image = bitmap;
    }

This should fix the issue.

Will T
  • 544
  • 1
  • 3
  • 17