【问题标题】:Getting pixel color from PictureBox after drawing lines画线后从 PictureBox 获取像素颜色
【发布时间】:2013-03-20 02:31:01
【问题描述】:

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

【问题讨论】:

    标签: c# winforms


    【解决方案1】:

    通过Paint事件或OnPaint方法在控件占用的屏幕上绘制与在控件内部查看的位图上绘制是有区别的时间>。您执行前者,但试图从后者获取像素。

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

    例如,从我的头顶:

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

    那么当你在图片框中的Image对象上做GetPixel时,你会得到你刚刚画的线的像素值。

    【讨论】:

    • 我想再次复制图像,Bitmap bitmap = (Bitmap) Picture1.Image; 将确保图像包含所有绘图?
    • @user1032613 不,不。您必须看到屏幕上的图像和图片框中的图像之间的差异。任何窗口和任何控件都可以在您的屏幕上绘制。您已经为您的图片框提供了一个图像,它会获取该图像并将其绘制在您的屏幕上。当您在Paint 事件中绘制内容时,您正在屏幕上进行绘制。当您执行Picture1.Image 时,您会从它那里得到您提供给图片框的图像,而这不是您在屏幕上看到的图像。
    【解决方案2】:

    使用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;
    }
    

    【讨论】:

      【解决方案3】:

      必须对上面 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;
          }
      

      【讨论】:

        猜你喜欢
        • 2014-11-14
        • 2021-07-05
        • 1970-01-01
        • 2014-08-05
        • 1970-01-01
        • 2013-07-21
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多