在Windows窗体上绘制单个像素


92

我一直试图在Windows窗体上打开单个像素。

graphics.DrawLine(Pens.Black, 50, 50, 51, 50); // draws two pixels

graphics.DrawLine(Pens.Black, 50, 50, 50, 50); // draws no pixels

API确实应该有一种方法来设置一个像素的颜色,但我看不到。

我正在使用C#。


我制作了一个控件,该控件绘制了一些非常漂亮的科学图形(具有我在任何商业控件中都不需要的附加功能)。我可以用和X或+或小框来绘制数据点。但是对于不重要的数据,我只想要一个像素。
Mark T

我看到的所有答案似乎对一个像素来说真的过分杀伤力了吗?为什么只做一个缓冲区[y * width + x] = color似乎更容易?
NoMoreZealots

Answers:


113

这将设置一个像素:

e.Graphics.FillRectangle(aBrush, x, y, 1, 1);

18
谁会猜到DrawRectangle绘制2x2,而FillRectange绘制1x1,且具有相同的参数?谢谢。
Mark T

9
@Mark:确实有某种意义... DrawRectangle说“绘制从此宽度和高度的x和y开始的轮廓”,因此它同时绘制了起点和终点(x,y; x + 1,y ; x,y + 1; x + 1,y + 1)以及它们之间的线。FillRectangle说:“绘制从此宽度和高度的x,y开始的固体表面”。顺便说一句,FillRectangle需要笔刷而不是笔。
Powerlord

5
@R。Bemrose:实际上,这取决于您传递给的Pen对象DrawRectangle()。如果有Pen.Alignment = PenAlignment.Outset,它将Pen.Width在给定的矩形周围绘制像素粗轮廓。但是,如果指定Pen.Alignment = PenAlignment.Inset,它将在给定的矩形内绘制Pen.Width像素厚的“轮廓”。
Cipi

2
这是一个非常不令人满意的答案。尽管这设置了单个像素,但要求并不总是设置文字像素。一直以来,我经常需要用点笔而不是画笔来画点。换句话说,我们需要一条短于2个像素的线。我怀疑这是OP所需要的。
RobertT 2012年

6
我不喜欢这个答案。这种方式效率很低。
2013年

18

Graphics对象没有此对象,因为它是一种抽象,可以用来覆盖矢量图形格式。在这种情况下,设置单个像素没有任何意义。该Bitmap图像格式确实有GetPixel()SetPixel(),但没有一个图形对象建立在一个。对于您的方案,您的选择确实似乎是唯一的选择,因为没有一种通用的方法可以为常规图形对象设置单个像素(而且您不知道它到底是什么,作为控件/窗体)可以是双缓冲的,等等)

为什么需要设置单个像素?


18

只是为了展示Henk Holterman答案的完整代码:

Brush aBrush = (Brush)Brushes.Black;
Graphics g = this.CreateGraphics();

g.FillRectangle(aBrush, x, y, 1, 1);

9

在绘制大量单个像素(用于各种自定义数据显示)的地方,我倾向于将它们绘制到位图,然后将其涂抹到屏幕上。

Bitmap GetPixel和SetPixel操作不是特别快,因为它们进行了大量的边界检查,但是创建“快速位图”类可以快速访问位图非常容易。


2

GetHdc上的MSDN页面

我认为这就是您想要的。您将需要获取HDC,然后使用GDI调用来使用SetPixel。注意,GDI中的COLORREF是存储BGR颜色的DWORD。没有Alpha通道,也没有像GDI +的颜色结构那样的RGB。

这是我为完成同一任务而编写的一小段代码:

public class GDI
{
    [System.Runtime.InteropServices.DllImport("gdi32.dll")]
    internal static extern bool SetPixel(IntPtr hdc, int X, int Y, uint crColor);
}

{
    ...
    private void OnPanel_Paint(object sender, PaintEventArgs e)
    {
        int renderWidth = GetRenderWidth();
        int renderHeight = GetRenderHeight();
        IntPtr hdc = e.Graphics.GetHdc();

        for (int y = 0; y < renderHeight; y++)
        {
            for (int x = 0; x < renderWidth; x++)
            {
                Color pixelColor = GetPixelColor(x, y);

                // NOTE: GDI colors are BGR, not ARGB.
                uint colorRef = (uint)((pixelColor.B << 16) | (pixelColor.G << 8) | (pixelColor.R));
                GDI.SetPixel(hdc, x, y, colorRef);
            }
        }

        e.Graphics.ReleaseHdc(hdc);
    }
    ...
}

1

显然,DrawLine绘制的线比实际指定的长度短一个像素。似乎没有DrawPoint / DrawPixel / whatnot,但是您可以使用Width和height设置为1的DrawRectangle绘制单个像素。


2
不错的尝试,但尺寸为1时,它会绘制2x2像素。(将其绘制在一行的旁边,您会看到它的宽度是它的两倍。)当然,尺寸为零时,它什么也不会绘制。
Mark T

是的,我的错。:)好事FillRectangle可以解决问题。
Rytmis

0

使用带有DashStyle.DashStyle.Dot的笔绘制一条2px的线将绘制单个Pixel。

    private void Form1_Paint(object sender, PaintEventArgs e)
    {
        using (Pen p = new Pen(Brushes.Black))
        {
            p.DashStyle = System.Drawing.Drawing2D.DashStyle.Dot;
            e.Graphics.DrawLine(p, 10, 10, 11, 10);
        }
    }
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.