Gambarlah satu piksel pada Formulir Windows

93

Saya terjebak saat mencoba mengaktifkan satu piksel pada Formulir Windows.

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

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

API seharusnya memiliki metode untuk mengatur warna satu piksel, tetapi saya tidak melihatnya.

Saya menggunakan C #.

Mark T.
sumber
Saya membuat kontrol yang memplot beberapa grafik ilmiah yang sangat bagus (dengan kemampuan tambahan yang saya perlukan tidak tersedia di kontrol komersial mana pun). Saya dapat memplot titik data dengan dan X atau a + atau kotak kecil. Tetapi untuk data yang tidak penting, saya hanya menginginkan satu piksel.
Mark T
Semua jawaban yang saya lihat sepertinya benar-benar berlebihan untuk satu piksel? Mengapa tampaknya lebih mudah hanya dengan melakukan buffer [y * width + x] = color;
NoMoreZealots

Jawaban:

114

Ini akan menetapkan satu piksel:

e.Graphics.FillRectangle(aBrush, x, y, 1, 1);
Henk Holterman
sumber
18
Siapa sangka DrawRectangle menggambar 2x2 tetapi FillRectange menggambar 1x1 dengan argumen yang sama? Terima kasih.
Mark T
9
@Mark: Ini masuk akal ... DrawRectangle mengatakan "menggambar garis besar mulai dari x dan y dengan lebar dan tinggi ini," jadi menggambar titik awal dan akhir (x, y; x + 1, y ; x, y + 1; x + 1, y + 1) dan garis di antara keduanya. FillRectangle mengatakan "gambar permukaan padat mulai dari x, y dengan lebar dan tinggi ini." Kebetulan, FillRectangle membutuhkan Brush, bukan Pen.
Powerlord
5
@R. Bemrose: Sebenarnya, itu tergantung pada objek Pena yang kamu tuju DrawRectangle(). Jika memilikinya, Pen.Alignment = PenAlignment.Outsetitu akan menggambar Pen.Widthgaris tebal piksel di sekeliling persegi panjang yang diberikan. Tetapi jika Anda menentukannya Pen.Alignment = PenAlignment.Inset, Pen.Width piksel akan menggambar "garis tepi" tebal di dalam persegi panjang yang diberikan.
Cipi
2
Ini jawaban yang sangat tidak memuaskan. Meskipun ini menetapkan satu piksel, persyaratannya tidak selalu untuk menetapkan piksel literal. Sepanjang waktu saya membutuhkan ini, yang seringkali, saya membutuhkan titik untuk digambar dengan pena yang sama dengan yang digambar dengan garis, bukan kuas. Dengan kata lain, kita membutuhkan garis yang lebih pendek dari 2 piksel. Saya menduga itulah yang dibutuhkan OP.
RobertT
6
Saya tidak suka jawaban ini. Cara ini sangat tidak efisien.
pengguna626528
19

Sekadar menunjukkan kode lengkap untuk jawaban Henk Holterman:

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

g.FillRectangle(aBrush, x, y, 1, 1);
WoodyDRN
sumber
18

The Graphicsobjek tidak memiliki ini, karena ini merupakan abstraksi dan dapat digunakan untuk menutupi format grafis vektor. Dalam konteks itu, menyetel satu piksel tidak masuk akal. The Bitmapformat gambar memang memiliki GetPixel()danSetPixel() , tetapi tidak objek grafis yang dibangun di atas satu. Untuk skenario Anda, opsi Anda benar-benar tampak seperti satu-satunya karena tidak ada satu-satunya cara untuk menetapkan satu piksel untuk objek grafik umum (dan Anda tidak tahu PERSIS apa itu, sebagai kontrol / bentuk Anda. bisa menjadi buffer ganda, dll.)

Mengapa Anda perlu menyetel satu piksel?

Adam Robinson
sumber
9

Saat saya menggambar banyak piksel tunggal (untuk berbagai tampilan data yang disesuaikan), saya cenderung menggambarnya ke bitmap dan kemudian memadukannya ke layar.

Operasi Bitmap GetPixel dan SetPixel tidak terlalu cepat karena melakukan banyak pemeriksaan batas, tetapi cukup mudah untuk membuat kelas 'bitmap cepat' yang memiliki akses cepat ke bitmap.

Will Dean
sumber
2

Halaman MSDN di GetHdc

Saya pikir inilah yang Anda cari. Anda perlu mendapatkan HDC dan kemudian menggunakan panggilan GDI untuk menggunakan SetPixel. Perhatikan, bahwa COLORREF di GDI adalah DWORD yang menyimpan warna BGR. Tidak ada saluran alfa, dan itu bukan RGB seperti struktur Warna GDI +.

Ini adalah bagian kecil dari kode yang saya tulis untuk menyelesaikan tugas yang sama:

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);
    }
    ...
}
maupun
sumber
1

Rupanya DrawLine menggambar garis yang satu piksel pendek dari panjang yang ditentukan sebenarnya. Sepertinya tidak ada DrawPoint / DrawPixel / yang lainnya, tetapi Anda dapat menggunakan DrawRectangle dengan lebar dan tinggi disetel ke 1 untuk menggambar satu piksel.

Rytmis
sumber
2
Usaha yang bagus, tetapi dengan ukuran 1 gambarnya 2x2 piksel. (Gambarlah di sebelah garis, dan Anda bisa melihatnya dua kali lebarnya.) Dan dengan ukuran nol, tentu saja, itu tidak menarik apa-apa.
Mark T
Benar, salahku. :) Untung saja FillRectangle berhasil.
Rytmis
0

Menggambar Garis 2px menggunakan Pena dengan DashStyle.DashStyle.Dot menggambar satu 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
sumber