วาดพิกเซลเดียวบน Windows Forms


94

ฉันติดอยู่ในการพยายามเปิดพิกเซลเดียวใน Windows Form

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 หรือ a + หรือช่องเล็ก ๆ แต่สำหรับข้อมูลที่ไม่สำคัญฉันต้องการแค่พิกเซลเดียว
Mark T

คำตอบทั้งหมดที่ฉันเห็นดูเหมือนจะมากเกินไปสำหรับพิกเซลเดียว? ทำไมมันดูง่ายกว่าแค่ทำบัฟเฟอร์ [y * width + x] = color;
NoMoreZealots

คำตอบ:


114

สิ่งนี้จะตั้งค่าพิกเซลเดียว:

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
@ ร. Bemrose: DrawRectangle()จริงๆแล้วมันขึ้นอยู่กับวัตถุปากกาคุณส่งผ่านไป ถ้ามีPen.Alignment = PenAlignment.OutsetมันจะวาดPen.Widthเส้นหนาพิกเซลรอบ ๆ สี่เหลี่ยมผืนผ้าที่กำหนด แต่ถ้าคุณระบุPen.Alignment = PenAlignment.Insetก็จะวาด Pen.Width พิกเซลหนา "outline" ภายในสี่เหลี่ยมผืนผ้าที่กำหนด
Cipi

2
นี่เป็นคำตอบที่ไม่น่าพอใจมาก แม้ว่าจะกำหนดพิกเซลเดียว แต่ข้อกำหนดนี้ไม่ได้กำหนดให้กำหนดพิกเซลตามตัวอักษรเสมอไป ทุกครั้งที่ฉันต้องการสิ่งนี้ซึ่งบ่อยครั้งฉันต้องการจุดที่จะวาดด้วยปากกาเดียวกับที่วาดด้วยเส้นไม่ใช่แปรง กล่าวอีกนัยหนึ่งคือเราต้องการเส้นที่สั้นกว่า 2 พิกเซล ฉันสงสัยว่านั่นคือสิ่งที่ OP ต้องการ
RobertT

6
ฉันไม่ชอบคำตอบนี้ วิธีนี้ไม่มีประสิทธิภาพสูง
user626528

19

เพียงเพื่อแสดงรหัสที่สมบูรณ์สำหรับคำตอบของ Henk Holterman:

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

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

18

Graphicsวัตถุไม่ได้นี้เพราะมันเป็นนามธรรมและสามารถนำมาใช้เพื่อให้ครอบคลุมรูปแบบกราฟิกแบบเวกเตอร์ ในบริบทนั้นการตั้งค่าพิกเซลเดียวจะไม่สมเหตุสมผล Bitmapรูปแบบภาพไม่ได้GetPixel()และSetPixel()แต่ไม่กราฟิกวัตถุที่สร้างขึ้นบนหนึ่ง สำหรับสถานการณ์ของคุณตัวเลือกของคุณดูเหมือนเป็นเพียงสิ่งเดียวเพราะไม่มีวิธีเดียวที่เหมาะกับทุกขนาดในการตั้งค่าพิกเซลเดียวสำหรับวัตถุกราฟิกทั่วไป (และคุณไม่รู้ว่ามันคืออะไรในฐานะตัวควบคุม / รูปแบบของคุณ อาจเป็นบัฟเฟอร์สองครั้ง ฯลฯ )

ทำไมต้องกำหนดพิกเซลเดียว?


9

ในกรณีที่ฉันวาดพิกเซลเดียวจำนวนมาก (สำหรับการแสดงข้อมูลที่กำหนดเองต่างๆ) ฉันมักจะวาดเป็นบิตแมปจากนั้นจึงขีดทับลงบนหน้าจอ

การดำเนินการ Bitmap GetPixel และ SetPixel นั้นไม่ได้รวดเร็วเป็นพิเศษเนื่องจากมีการตรวจสอบขอบเขตที่แย่มาก แต่มันค่อนข้างง่ายที่จะสร้างคลาส 'บิตแมปที่รวดเร็ว' ซึ่งสามารถเข้าถึงบิตแมปได้อย่างรวดเร็ว


2

MSDN Page บน GetHdc

ฉันคิดว่านี่คือสิ่งที่คุณกำลังมองหา คุณจะต้องได้รับ HDC จากนั้นใช้การโทร GDI เพื่อใช้ SetPixel โปรดทราบว่า COLORREF ใน GDI เป็น DWORD ที่เก็บสี BGR ไม่มีช่องอัลฟาและไม่ใช่ RGB เหมือนกับโครงสร้างสีของ GDI +

นี่เป็นส่วนเล็ก ๆ ของโค้ดที่ฉันเขียนขึ้นเพื่อทำงานเดียวกันให้สำเร็จ:

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 แต่คุณสามารถใช้ DrawRectangle ที่มีความกว้างและความสูงเป็น 1 เพื่อวาดพิกเซลเดียว


2
ลองดี แต่ด้วยขนาด 1 จะดึงพิกเซล 2x2 (วาดไว้ข้างเส้นแล้วคุณจะเห็นว่ามันกว้างขึ้นสองเท่า) และแน่นอนว่าด้วยขนาดที่เป็นศูนย์ก็ไม่ได้วาดอะไรเลย
Mark T

ถูกต้องความผิดพลาดของฉัน :) สิ่งที่ดี FillRectangle ทำเคล็ดลับ
Rytmis

0

วาดเส้น 2px โดยใช้ปากกากับ DashStyle.DashStyle.Dot วาดพิกเซลเดียว

    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.