Search code examples
c#picturebox

How do I get the color of a specific pixel from a picture box?


I have a picture box in one of my programs which displays my images just fine. What's displayed consists of a chosen "BackColor" and some filled rectangles using a brush and some lines using a pen. I have no imported images. I need to retrieve the color value of a specified pixel on the picture box. I've tried the following:

Bitmap b = new Bitmap(pictureBox1.Image);          
                Color colour = b.GetPixel(X,Y)

But pictureBox1.Image always returns null. Does .Image only work with imported images? If not how can I get this to work? Are there any alternatives?


Solution

  • Yes you can, but should you?

    Here is the change your code needs:

    Bitmap b = new Bitmap(pictureBox1.ClientSize.Width, pictureBox1.Height);
    pictureBox1.DrawToBitmap(b, pictureBox1.ClientRectangle);
    Color colour = b.GetPixel(X, Y);
    b.Dispose();
    

    But there is really no way around giving the PictureBox a real Image to work with somewhere if you want to do real work with it, meaning if you want to use its possibilities e.g. its SizeMode.

    Simply drawing on its background is just not the same. Here is a minimal code to get a real Bitmap assigned:

    public Form1()
    {
       InitializeComponent();
       pictureBox1.Image = new Bitmap(pictureBox1.ClientSize.Width, 
                                      pictureBox1.ClientSize.Height); 
       using (Graphics graphics = Graphics.FromImage(pictureBox1.Image))
       { 
         graphics.FillRectangle(Brushes.CadetBlue, 0, 0, 99, 99);
         graphics.FillRectangle(Brushes.Beige, 66, 55, 66, 66);
         graphics.FillRectangle(Brushes.Orange, 33, 44, 55, 66);
       }  
    }
    

    However if you really don't want to assign an Image you can make the PictureBox draw itself onto a real Bitmap. Note that you must draw the Rectangles etc in the Paint event for this to work! (Actually you must use the Paint event for other reasons as well!)

    Now you can test either way e.g. with a Label and your mouse:

    private void pictureBox1_MouseDown(object sender, MouseEventArgs e)
    {
        if (pictureBox1.Image != null)
        {   // the 'real thing':
            Bitmap bmp = new Bitmap(pictureBox1.Image);
            Color colour = bmp.GetPixel(e.X, e.Y);
            label1.Text = colour.ToString();
            bmp.Dispose();
        }
        else
        {   // just the background:
            Bitmap bmp = new Bitmap(pictureBox1.ClientSize.Width, pictureBox1.Height);
            pictureBox1.DrawToBitmap(bmp, pictureBox1.ClientRectangle);
            Color colour = bmp.GetPixel(e.X, e.Y);
            label1.Text += "ARGB :" + colour.ToString();
            bmp.Dispose();
        }
    }
    
    private void pictureBox1_Paint(object sender, PaintEventArgs e)
    {
        e.Graphics.FillRectangle(Brushes.DarkCyan, 0, 0, 99, 99);
        e.Graphics.FillRectangle(Brushes.DarkKhaki, 66, 55, 66, 66);
        e.Graphics.FillRectangle(Brushes.Wheat, 33, 44, 55, 66);
    }