C# 绘制线条后从PictureBox获取像素颜色
我有一个装有位图的PictureBox,比如说,一张照片:C# 绘制线条后从PictureBox获取像素颜色,c#,winforms,C#,Winforms,我有一个装有位图的PictureBox,比如说,一张照片: Picture1.Image=新位图(“photo.bmp”) 在Picture1_Paint()事件中,我在照片上画了一条线: e.Graphics.drawine(myPen、pointA、pointB) 现在,我想显示单击像素的RGB信息: Bitmap bitmap = (Bitmap) Picture1.Image; /* Making sure I'm using the image being displayed */
Picture1.Image=新位图(“photo.bmp”)代码>
在Picture1_Paint()
事件中,我在照片上画了一条线:
e.Graphics.drawine(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中显示的任何内容的颜色信息,包括我绘制的线条或椭圆。通过Paint
事件或OnPaint
方法在控件占用的屏幕上绘制与在控件内查看的位图上绘制之间存在差异。你做前者,但试图从后者得到一个像素
您必须为图像创建一个图形
对象并直接在其上绘制,而不是在绘制
事件中绘制。然后将图像指定给图片框的image
属性
例如,从我的头顶:
Image image = /* ... */;
using (Graphics g = Graphics.FromImage(image))
{
g.DrawLine(myPen, pointA, pointB);
}
picture1.Image = image;
然后,当您对图片框中的Image
对象执行GetPixel
操作时,您将获得刚才绘制的线的像素值。使用;代码如下:
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);
}
}
}
我不得不对上面杰里米的答案做一个修改,让它对我有用。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;
}
我想再次复制图像,Bitmap Bitmap=(Bitmap)Picture1.Image
是否会确保图像包含所有图形?@user1032613否。您必须看到屏幕上的图像与picturebox中的图像之间的差异。任何窗口和控件都可以在屏幕上绘制。你给了你的picturebox一个图像,它会把这个图像画在你的屏幕上。在Paint
事件中绘制某物时,您正在屏幕上绘制。当您执行Picture1.Image
操作时,您将从图片盒中获得您提供给图片盒的图像,而这不是您在屏幕上看到的图像。
[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;
}