94

I'm stuck trying to turn on a single pixel on a Windows Form.

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

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

The API really should have a method to set the color of one pixel, but I don't see one.

I am using C#.

Adriano Carneiro
  • 53,285
  • 12
  • 85
  • 120
Mark T
  • 3,292
  • 3
  • 29
  • 42
  • I made a control which plots some very nice scientific graphs (with added capabilities I need not available in any commercial controls). I can plot a data point with and X or a + or a small box. But for unimportant data, I just want a single pixel. – Mark T Apr 17 '09 at 16:10
  • All the answers I see seem like they really are overkill for a single pixel? Why does it seem easier just to do a buffer[y*width+x]=color; – NoMoreZealots Feb 14 '19 at 00:13

8 Answers8

114

This will set a single pixel:

e.Graphics.FillRectangle(aBrush, x, y, 1, 1);
Henk Holterman
  • 236,989
  • 28
  • 287
  • 464
  • 19
    Who would have guessed that DrawRectangle draws a 2x2 but FillRectange draws a 1x1 with the same arguments? Thanks. – Mark T Apr 17 '09 at 16:20
  • 9
    @Mark: It does make a sort of sense... DrawRectangle says "draw an outline starting at x and y of this width and height," so it draws both the start and end points (x,y; x+1,y;x,y+1; x+1,y+1) and lines between them. FillRectangle says "draw a solid surface starting at x,y of this width and height." Incidentally, FillRectangle takes a Brush, not a Pen. – Powerlord Apr 17 '09 at 16:42
  • 5
    @R. Bemrose: Actually, it depends on the Pen object you pass to `DrawRectangle()`. If it has `Pen.Alignment = PenAlignment.Outset` it will draw `Pen.Width` pixels thick outline round the given rectangle. But if you specify `Pen.Alignment = PenAlignment.Inset` it will draw Pen.Width pixels thick "outline" inside the given rectangle. – Cipi Jul 25 '11 at 13:36
  • 2
    This is a very unsatisfactory answer. Although this sets a single pixel, the requirement is not always to set a literal pixel. All the times I've needed this, which is often, I've needed the dot to be drawn by the same pen that lines are drawn with, not a brush. In other words, we need a line that is shorter that 2 pixels. I suspect that is what the OP needed. – RobertT Feb 18 '12 at 13:39
  • 6
    I don't like this answer. This way is highly inefficient. – user626528 Feb 22 '13 at 10:51
  • If drawing on graphic with SmoothingMode = AntiAlias, the filled rectangle will start in the middle of the pixel at (x,y) meaning it will draw aliased between 4 pixels. To center the rectangle at (x,y) and thus draw on just the one pixel, subtract 0.5 from x and y. `e.Graphics.FillRectangle(aBrush, x - 0.5f, y - 0.5f, 1.0f, 1.0f);` – Adam Jan 05 '21 at 19:09
19

Just to show complete code for Henk Holterman answer:

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

g.FillRectangle(aBrush, x, y, 1, 1);
WoodyDRN
  • 1,013
  • 18
  • 22
18

The Graphics object doesn't have this, since it's an abstraction and could be used to cover a vector graphics format. In that context, setting a single pixel wouldn't make sense. The Bitmap image format does have GetPixel() and SetPixel(), but not a graphics object built on one. For your scenario, your option really seems like the only one because there's no one-size-fits-all way to set a single pixel for a general graphics object (and you don't know EXACTLY what it is, as your control/form could be double-buffered, etc.)

Why do you need to set a single pixel?

Adam Robinson
  • 171,726
  • 31
  • 271
  • 330
10

Where I'm drawing lots of single pixels (for various customised data displays), I tend to draw them to a bitmap and then blit that onto the screen.

The Bitmap GetPixel and SetPixel operations are not particularly fast because they do an awful lot of boundschecking, but it's quite easy to make a 'fast bitmap' class which has quick access to a bitmap.

Will Dean
  • 37,648
  • 10
  • 84
  • 116
2

MSDN Page on GetHdc

I think this is what you are looking for. You will need to get the HDC and then use the GDI calls to use SetPixel. Note, that a COLORREF in GDI is a DWORD storing a BGR color. There is no alpha channel, and it is not RGB like the Color structure of GDI+.

This is a small section of code that I wrote to accomplish the same task:

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);
    }
    ...
}
nor
  • 73
  • 5
2

Drawing a Line 2px using a Pen with DashStyle.DashStyle.Dot draws a single 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);
        }
    }
Eddy
  • 31
  • 2
1

If you are drawing on a graphic with SmoothingMode = AntiAlias, most drawing methods will draw more than one pixel. If you only want one pixel drawn, create a 1x1 bitmap, set the bitmap's pixel to the desired color, then draw the bitmap on the graphic.

using (var pixel = new Bitmap(1, 1, e.Graphics))
{
    pixel.SetPixel(0, 0, color);
    e.Graphics.DrawImage(pixel, x, y);
}
Adam
  • 160
  • 8
1

Apparently DrawLine draws a line that is one pixel short of the actual specified length. There doesn't seem to be a DrawPoint/DrawPixel/whatnot, but instead you can use DrawRectangle with width and height set to 1 to draw a single pixel.

Rytmis
  • 29,686
  • 8
  • 57
  • 69
  • 2
    Nice try, but with size 1 it draws 2x2 pixels. (Draw it next to a line, and you can see it is twice as wide.) And with size zero, of course, it draws nothing. – Mark T Apr 17 '09 at 16:16
  • Right, my mistake. :) Good thing FillRectangle does the trick. – Rytmis Apr 17 '09 at 16:24