绘制线条后从PictureBox获取像素颜色

时间:2013-03-20 02:31:02

标签: c# winforms

我有一个装有位图的PictureBox,例如照片:

Picture1.Image = new Bitmap("photo.bmp");

Picture1_Paint()事件中,我在照片上画了一条线:

e.Graphics.DrawLine(myPen, pointA, pointB);

现在,我想显示点击像素的RGB信息:

Bitmap bitmap = (Bitmap) Picture1.Image;  /* Making sure I'm using the image being displayed */
Color color = bitmap.GetPixel(e.X, e.Y);
lblSelectedColor.Text = color.R.ToString() + ", " + color.G.ToString() + ", " + color.B.ToString();

问题是:我得到的RGB值是原始照片上该像素的颜色,不包括我的线条图。例如,如果在天空中绘制一条粗红线,当我点击该红线时,我仍然会从照片中获得天蓝色。

我想获取PictureBox中显示的任何颜色信息,包括我绘制的线条或椭圆。

3 个答案:

答案 0 :(得分:1)

通过Paint事件或OnPaint方法在控件占用的屏幕上绘制与绘制内部查看的位图之间存在差异控件。你做前者但是试图从后者获得一个像素。

您必须为图片创建Paint对象,而不是直接在Graphics事件中绘图。然后将图像分配给图片框的Image属性。

例如,从我的头脑中:

Image image = /* ... */;
using (Graphics g = Graphics.FromImage(image))
{
    g.DrawLine(myPen, pointA, pointB);
}
picture1.Image = image;

然后当您在图片框中的GetPixel对象上执行Image时,您将获得刚绘制的线条的像素值。

答案 1 :(得分:1)

必须对上述杰里米(Jeremy)的答案进行更改,以使其对我有用。 ReleaseDC的原型似乎与他发布的原型不同。这对我有用:

    [DllImport("Gdi32.dll")]
    public static extern int GetPixel(
        System.IntPtr hdc,    // handle to DC
          int nXPos,  // x-coordinate of pixel
          int nYPos   // y-coordinate of pixel
     );

    [DllImport("User32.dll")]
    public static extern IntPtr GetDC(IntPtr wnd);

    [DllImport("User32.dll")] 
    public static extern bool ReleaseDC(IntPtr hWnd, IntPtr hDC);

    //For best results, use a component like a Panel and use it's handle (panel1.Handle) and e.X and e.Y on a component's MouseDown event
    private Color GetColorAtPoint(Point? p = null, IntPtr? handle = null)
    {
        var hwnd = handle ?? IntPtr.Zero; // Handle;
        Point point = p ?? MousePosition;
        var dc = GetDC(hwnd);
        Color c = ColorTranslator.FromWin32(GetPixel(dc, point.X, point.Y));
        ReleaseDC(hwnd, dc);
        return c;
    }

答案 2 :(得分:0)

使用Bob Powell's Eye Dropper,代码如下:

using System;
using System.Runtime.InteropServices;
using System.Drawing;
using System.Collections;
using System.ComponentModel;
using System.Windows.Forms;
using System.Data;


namespace pixelcolor
{
  /// <summary>
  /// Summary description for Form1.
  /// </summary>
  public class Form1 : System.Windows.Forms.Form
  {


    [DllImport("Gdi32.dll")]
    public static extern int GetPixel(
    System.IntPtr hdc,    // handle to DC
    int nXPos,  // x-coordinate of pixel
    int nYPos   // y-coordinate of pixel
    );

    [DllImport("User32.dll")]
    public static extern IntPtr GetDC(IntPtr wnd);

    [DllImport("User32.dll")]
    public static extern void ReleaseDC(IntPtr dc);


    private System.Windows.Forms.Panel panel1;
    private System.Timers.Timer timer1;

    /// <summary>
    /// Required designer variable.
    /// </summary>
    private System.ComponentModel.Container components = null;

    public Form1()
    {
      //
      // Required for Windows Form Designer support
      //
      InitializeComponent();
      this.SetStyle(ControlStyles.ResizeRedraw,true);
    }

    /// <summary>
    /// Clean up any resources being used.
    /// </summary>
    protected override void Dispose( bool disposing )
    {
      if( disposing )
      {
        if (components != null)
        {
          components.Dispose();
        }
      }
      base.Dispose( disposing );
    }

    #region Windows Form Designer generated code
    /// <summary>
    /// Required method for Designer support - do not modify
    /// the contents of this method with the code editor.
    /// </summary>
    private void InitializeComponent()
    {
      this.panel1 = new System.Windows.Forms.Panel();
      this.timer1 = new System.Timers.Timer();
      ((System.ComponentModel.ISupportInitialize)(this.timer1)).BeginInit();
      this.SuspendLayout();
      //
      // panel1
      //
      this.panel1.BorderStyle = System.Windows.Forms.BorderStyle.Fixed3D;
      this.panel1.Location = new System.Drawing.Point(216, 8);
      this.panel1.Name = "panel1";
      this.panel1.Size = new System.Drawing.Size(64, 56);
      this.panel1.TabIndex = 0;
      //
      // timer1
      //
      this.timer1.Enabled = true;
      this.timer1.SynchronizingObject = this;
      this.timer1.Elapsed += new System.Timers.ElapsedEventHandler(this.timer1_Elapsed);
      //
      // Form1
      //
      this.AutoScaleBaseSize = new System.Drawing.Size(5, 13);
      this.BackColor = System.Drawing.Color.White;
      this.ClientSize = new System.Drawing.Size(292, 273);
      this.Controls.Add(this.panel1);
      this.Name = "Form1";
      this.Text = "Form1";
      this.Paint += new System.Windows.Forms.PaintEventHandler(this.Form1_Paint);
      ((System.ComponentModel.ISupportInitialize)(this.timer1)).EndInit();
      this.ResumeLayout(false);

    }
    #endregion

    /// <summary>
    /// The main entry point for the application.
    /// </summary>
    [STAThread]
    static void Main()
    {
      Application.Run(new Form1());
    }

    private void Form1_Paint(object sender, System.Windows.Forms.PaintEventArgs e)
    {
      Random r=new Random(1);

      for(int x=0;x<100;x++)
      {
        SolidBrush b=new SolidBrush(Color.FromArgb(r.Next(255),r.Next(255),r.Next(255)));
        e.Graphics.FillRectangle(b,r.Next(this.ClientSize.Width),r.Next(this.ClientSize.Height),r.Next(100),r.Next(100));
      }
    }

    private void timer1_Elapsed(object sender, System.Timers.ElapsedEventArgs e)
    {
      Point p=Control.MousePosition;
      IntPtr dc=GetDC(IntPtr.Zero);
      this.panel1.BackColor=ColorTranslator.FromWin32(GetPixel(dc,p.X,p.Y));
      ReleaseDC(dc);
    }
  }
}

如果您想在PictureBox或您自己的表单中对颜色进行采样,那么您只需要获取该对象的DC。这可以使用CreateGraphics,Graphics.GetHdc和Graphics.ReleaseHdc来完成。下面的列表显示了一个MouseMove处理程序,可用于从表单中获取像素颜色。

protected override void OnMouseMove(MouseEventArgs e)
{
  Graphics g=this.CreateGraphics();
  IntPtr myDC=g.GetHdc();
  Color c=ColorTranslator.FromWin32(GetPixel(myDC,e.X,e.Y));
  g.ReleaseHdc(myDC);

  this.panel1.BackColor=c;
}