Click here to Skip to main content
16,015,594 members
Please Sign up or sign in to vote.
1.00/5 (1 vote)
See more:
hi,,,this is my code,,,when i call Gfill,,,after getpixel method a value of c is 0,,,what is my problem?

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;

namespace GFill
{
    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();
        }

        int MouseX, MouseY;
       // Color ColorOfPixel(Point P);
        private void button1_Click(object sender, EventArgs e)
        {
           

        }

        private void GFill(int x, int y, int bcolor, int Fcolor)
        {
            Graphics g = this.CreateGraphics();
            Bitmap bmp = new Bitmap(this.Width,this.Height);
            bmp.SetPixel(0, 0, Color.Blue);
            int c = bmp.GetPixel(x, y).ToArgb();
                if ((x >= 0) && (x <= 640) && (y >= 0) && (y <= 480))
                {
                    if ((c != bcolor) && (c != Fcolor))
                    {
                        g.DrawImageUnscaled(bmp, x, y);
                        GFill(x + 1, y, bcolor, Fcolor);
                        GFill(x, y + 1, bcolor, Fcolor);
                        GFill(x - 1, y, bcolor, Fcolor);
                        GFill(x, y - 1, bcolor, Fcolor);
                    }
                }
            }

        private void Form1_Paint(object sender, PaintEventArgs e)
        {
            Rectangle rectangle1 = new Rectangle(100, 200, 200, 100);
            e.Graphics.DrawRectangle(Pens.Black, rectangle1);
        }

        private void Form1_MouseClick(object sender, MouseEventArgs e)
        {
            MouseX = MousePosition.X;
            MouseY = MousePosition.Y;
            GFill(MouseX, MouseY, this.BackColor.ToArgb(), this.ForeColor.ToArgb());
            Application.DoEvents();
        }


    }
}
Posted
Comments
BillWoodruff 5-Dec-13 0:13am    
Do keep in mind that where a mouse is clicked in a displayed graphic at run-time may correspond to any number of bitmap pixels ... depending on bitmap resolution and color-depth, and monitor resolution and color-depth.

You're creating a new Bitmap in each invocation of GFill, so you're always looking at the newly created bitmap, not the actual image of the form!

Create one Bitmap in Form1_MouseClick, copy the initial image of the form into the bitmap, and pass it to GFill. Do the filling operation and then call the g.DrawImageUnscaled(bmp, 0, 0); after GFill returns.

Aside: GetPixel and SetPixel are notorously slow. Search here on CodeProject (or with Google) to find better ways of doing this.

[Edit: getting the initial client area bitmap left as an exercise... :-) Google is your friend here!]
C#
private void Form1_MouseClick(object sender, MouseEventArgs e)
{
  Graphics g = this.CreateGraphics();
  Rectangle rect = this.ClientRectangle;
  Bitmap bmp = new Bitmap(rect.Width, rect.Height, g);
  //Get form's client area bitmap into bmp
  BitmapData bmpData = bmp.LockBits(rect, ImageLockMode.ReadWrite, PixelFormat.Format32bppArgb);
  int[] pixels = new int[bmpData.Height * bmpData.Width];
  Marshal.Copy(bmpData.Scan0, pixels, 0, pixels.Length);
  GFill(Color.Blue.ToArgb(), e.X, e.Y, this.BackColor.ToArgb(), this.ForeColor.ToArgb(), bmp.Width, bmp.Height, pixels);
  Marshal.Copy(pixels, 0, bmpData.Scan0, pixels.Length);
  bmp.UnlockBits(bmpData);
  g.DrawImageUnscaled(bmp, 0, 0);
}

private void GFill(int newColor, int x, int y, int bcolor, int Fcolor, int width, int height, int[] pixels)
{
  if ((x >= 0) && (x < width) && (y >= 0) && (y < height))
  {
    int offset = x + y * width;
    int c = pixels[offset];
    if ((c != newColor) && (c != bcolor) && (c != Fcolor))
    {
      pixels[offset] = newColor;
      GFill(newColor, x + 1, y, bcolor, Fcolor, width, height, pixels);
      GFill(newColor, x, y + 1, bcolor, Fcolor, width, height, pixels);
      GFill(newColor, x - 1, y, bcolor, Fcolor, width, height, pixels);
      GFill(newColor, x, y - 1, bcolor, Fcolor, width, height, pixels);
    }
  }
}


Notice: I added a check for the pixel at x,y already newColor to prevent re-filling areas already done.
This fill routine will overflow the stack fairly quickly!!!
 
Share this answer
 
v3
Comments
Sergey Alexandrovich Kryukov 4-Dec-13 16:41pm    
Correct, my 5.
I added explanation on what to do alternatively; please see Solution 3. Your answer is, of course, credited.
—SA
BillWoodruff 4-Dec-13 22:22pm    
+5 Excellent answer !
In addition to the correct Solution 1:

For such a massive bit operations, you should never use GetPixel/SetPixel, which is prohibitively slow and would be good only for working with very few pixels. Instead, use System.Drawing.Bitmap.LockBits:
http://msdn.microsoft.com/en-us/library/system.drawing.bitmap.lockbits%28v=vs.110%29.aspx[^].

The code samples and description of these two methods in MSDN will help you to understand what they do and how to use them.

Another pretty bad thing is Application.DoEvents. If you need to do something in parallel, use threads; but this is a different story.

[EDIT]

Please see my comments below. If you need to pick up a pixel from screen, you are doing it wrong.
See, for example:
http://stackoverflow.com/questions/1483928/how-to-read-the-color-of-a-screen-pixel[^],
http://bobpowell.net/eyedropper.aspx[^].

The clean way to do it without using P/Invoke is also this: get a screen coordinate of your click, take a copy of a little fragment of the screen (ideally, of a size of one pixel), and use System.Drawing.Graphics.CopyFromScreen:
http://msdn.microsoft.com/en-us/library/system.drawing.graphics.copyfromscreen%28v=vs.110%29.aspx[^].

It will give you an instance of System.Drawing.Graphics to read from screen, possibly even with GetPixel.

To get screen coordinates of the click, use http://msdn.microsoft.com/en-us/library/system.windows.forms.control.pointtoscreen%28v=vs.110%29.aspx[^].

—SA
 
Share this answer
 
v2
Comments
ali_vampire 4-Dec-13 16:55pm    
my problem is how to detect a pixel of a point when i click on it,,,dont important about performance of commands,,,
Sergey Alexandrovich Kryukov 4-Dec-13 17:52pm    
Of course it is not important because this is one pixel. By some reason I had an impression that you operate with your pixels in a loop, but not I agree with you.
But now, the problem is that you are getting a pixel from some bitmap created from scratch, not from your screen. It makes no sense. Please tell me what do you want to achieve? To pick up a pixel from screen? Then do just that. Please see the update to my answer, after [EDIT].
—SA
Matt T Heffron 4-Dec-13 19:19pm    
From what you have, it appears that what you want is:
click on a point,
starting at this point: do a 4-connected-flood-fill of the form with the pixels which are either ForeColor or the BackColor of the form as the flood boundaries.
Right?
See my revised Solution 1
In your code you set pixel 0,0 to blue and in the next line you are examining value of pixel x, y.
Almost certainly x!=0 and y!=0.

C#
Bitmap bmp = new Bitmap(this.Width,this.Height);
bmp.SetPixel(0, 0, Color.Blue);
int c = bmp.GetPixel(x, y).ToArgb();
 
Share this answer
 
Comments
ali_vampire 4-Dec-13 16:06pm    
so how can i use getpixel?
i use this line but i have an error again

bmp.SetPixel(x,y, Color.Blue);
Adam Zgagacz 4-Dec-13 16:24pm    
I'm not sure I understand your problem. In the piece of code you posted you assign value to the single pixel, then you are checking different pixel and wondering why you don't see value you put somewhere else.

if you do:

bmp.SetPixel(0, 0, Color.Blue);
int c = bmp.GetPixel(0, 0).ToArgb();

you will se value.
ali_vampire 4-Dec-13 16:37pm    
for example when i clicked on a(204,305) on the form,,,i need getpixel of these points,,,
Adam Zgagacz 4-Dec-13 16:55pm    
See solution #3 by SA. There is no point to talk more about SetPixel GetPixel.

This content, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)



CodeProject, 20 Bay Street, 11th Floor Toronto, Ontario, Canada M5J 2N8 +1 (416) 849-8900