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には実際には1ピクセルの色を設定するメソッドが必要ですが、1つは表示されません。

C#を使用しています。


私は、いくつかの非常に素晴らしい科学グラフをプロットするコントロールを作成しました(商用コントロールで使用する必要がない機能が追加されています)。Xまたは+または小さなボックスでデータポイントをプロットできます。しかし、重要でないデータについては、1つのピクセルだけが必要です。
マークT

私が目にするすべての回答は、実際には単一のピクセルに対して過剰であるように見えますか?バッファ[y * width + x] = color;を実​​行するだけで簡単に見えるのはなぜですか?
NoMoreZealots 2019

回答:


113

これは単一のピクセルを設定します:

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

18
DrawRectangleは2x2を描画するが、FillRectangeは同じ引数で1x1を描画することを誰が推測したでしょうか?ありがとう。
マークT

9
@マーク:それは一種の理にかなっています... DrawRectangleは「この幅と高さのxとyで始まる輪郭を描く」と言っているので、始点と終点(x、y; x + 1、y)の両方を描画します; x、y + 1; x + 1、y + 1)とそれらの間の線。FillRectangleは、「この幅と高さのx、yから始まるソリッドサーフェスを描画する」と言います。ちなみに、FillRectangleはペンではなくブラシを取ります。
Powerlord 2009

5
@R。Bemrose:実際には、渡す先のPenオブジェクトによって異なりますDrawRectangle()。ある場合は、指定された長方形の周りにピクセルの太い輪郭Pen.Alignment = PenAlignment.Outsetを描きPen.Widthます。しかし、指定Pen.Alignment = PenAlignment.Insetした場合は、指定された長方形の内側に「輪郭」の太いPen.Widthピクセルが描画されます。
Cipi 2011

2
これは非常に不十分な答えです。これは単一のピクセルを設定しますが、必ずしもリテラルピクセルを設定する必要はありません。いつもこれが必要でしたが、多くの場合、ブラシではなく、線を描くのと同じペンでドットを描く必要がありました。つまり、2ピクセルよりも短いラインが必要です。それがOPに必要なものだと思います。
RobertT

6
この答えは好きではありません。この方法は非常に非効率的です。
user626528 2013

18

Graphicsオブジェクトは、それは抽象化だから、これを持っていないと、ベクターグラフィックス形式をカバーするために使用することができます。そのような状況では、単一のピクセルを設定しても意味がありません。Bitmap画像フォーマットは持っているGetPixel()SetPixel()1上に構築されたグラフィックスオブジェクトを、しかしありません。あなたのシナリオでは、一般的なグラフィックスオブジェクトに単一のピクセルを設定するための1つのサイズですべてに対応する方法がなく、コントロール/フォームとしてそれが何であるかを正確に知らないため、オプションは本当に唯一のオプションのように見えますダブルバッファリングなども可能です)

なぜ単一のピクセルを設定する必要があるのですか?


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であることに注意してください。アルファチャネルはなく、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は、実際に指定された長さより1ピクセル短い線を描画します。DrawPoint / DrawPixel / whatnotは​​ないようですが、代わりに幅と高さを1に設定してDrawRectangleを使用して、単一のピクセルを描画できます。


2
いい感じですが、サイズ1では2x2ピクセルを描画します。(線の横に描画すると、幅が2倍になります。)サイズがゼロの場合は、何も描画されません。
マークT

そう、間違いです。:)良いことFillRectangleはトリックを行います。
リトミス2009

0

DashStyle.DashStyle.Dotでペンを使用して線を2ピクセル描画すると、1つのピクセルが描画されます。

    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);
        }
    }
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.