1

我有一个加载了位图的 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 中显示的任何内容的颜色信息,包括我绘制的线条或椭圆。

4

3 回答 3

1

通过事件或方法在控件占用的屏幕上绘制与在控件内部查看的位图上绘制是有区别的。你做前者,但试图从后者获得一个像素。PaintOnPaint

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

例如,从我的头顶:

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

然后当你在图片框中GetPixelImage对象上做时,你会得到你刚刚画的线的像素值。

于 2013-03-20T02:33:32.913 回答
1

使用鲍勃鲍威尔的滴管;这是代码:

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;
}
于 2013-03-20T02:55:23.723 回答
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;
    }
于 2020-12-12T05:23:20.333 回答