Bitmaps zeichen: Paar Fragen



  • Hi,

    ich möchte gerne ein Konsolen-Programm schreiben (ohne Fenster!) mit C# das mir eine Bitmap erstellt und zeichnet.

    Auf der Bitmap soll ein Text ausgegeben werden in Arial z. B. "Hallo Bitmap!", 1 Horizontale Linie, ein Rechteck und die Bitmap soll mit der Farbe "Blau" "geleert" werden.

    Soweit sogut. Dazu hab ich erstmal so angefangen:

    using System;
    using System.Drawing;
    using System.Drawing.Drawing2D;
    using System.Drawing.Imaging;
    
    namespace ConsoleApplication1
    {
        class Program
        {
            static void Main (string[] args)
            {
                Bitmap test = new Bitmap (100, 100, PixelFormat.Format24bppRgb);
    
                for (int i = 0; i < test.Width; ++i)
                    test.SetPixel (i, 10, Color.GhostWhite);
    
                test.Save ("test.bmp");
            }
        }
    }
    

    Nur, die Bitmap-Klasse bietet keine Funktionen wie z. B. "DrawRectangle" bzw. "Fill" um die Bitmap mit blau zu füllen oder das Rechteck zu zeichnen. Auch das Linienzeichnen finde ich momentan noch sehr unschön 😞

    Wie kann ich denn den Rest machen?

    Danke euch im voraus schon mal 🙂



  • Du must dir ein Graphics-Object erstellen, dann stehen dir die vermissten Funktionen zur Verfügung.

    Etwa so:

    using System;
    using System.Drawing;
    using System.Drawing.Drawing2D;
    using System.Drawing.Imaging;
    
    namespace ConsoleApplication1
    {
        class Program
        {
            static void Main(string[] args)
            {
                Bitmap test = new Bitmap(100, 100, PixelFormat.Format24bppRgb); // Deine Bitmap
                for (int i = 0; i < test.Width; i++) // für die Breite
                {
                    for (int j = 0; j < test.Height; j++) // für die Höhe
                    {
                        test.SetPixel(i, j, Color.Blue); // alles Blau färben
                    }
    
                }
                Graphics gfx = Graphics.FromImage(test); // Graphics-Object aus Bitmap erstellen
                gfx.FillRectangle(Brushes.Bisque, 5, 50, 90, 40); // Dein Rechteck
                gfx.DrawString("Hallo Bitmap", new Font("Arial", 10.0f), Brushes.Black, 5.0f, 15.0f); // Dein String
                gfx.DrawLine(Pens.GhostWhite, 1, 10, 99, 10); // Deine Linie
    
                //for (int i = 0; i < test.Width; ++i)
                //    test.SetPixel(i, 10, Color.GhostWhite);
    
                gfx.Dispose(); // Graphics-Object aufräumen
                test.Save("test.bmp"); // ...und ins Ausführungverzeichnis speichern
            }
        }
    }
    

    Code ist getestet!



  • @michme
    unglaublich! das ist echt genial, sowas hab ich noch nicht erlebt, das das so easy mit C# ist!!!!

    Unendlich vielen Dank für deinen Code 🙂 Der hat mir richtig neue Möglichkeiten aufgezeigt in die ich nun weiter forschen kann 🙂 Vielen vielen dank!



  • Freut mich 🙂

    Um die Sache zu beschleunigen, ersetze die Schleifen zum einfärben mit folgendem:

    Nach

    Graphics gfx = ...;
    

    kommt

    gfx.Clear(Color.Blue);
    

    Dies färbt die Bitmap wesentlich(sichtbar!) schneller als das Setzen der einzelnen Pixel mit SetPixel.



  • Kleine Bemerkung:

    Wann immer man solchen Code mit 'Disposeable'-Objekten schreibt, sollte man *immer* einen 'using'-Block verwenden. Also *nicht* so:

    Graphics g = Graphics.FromImage(bitmap);
    // Malen ...
    g.Dispose();
    

    sondern so:

    using (Graphics g = Graphics.FromImage(bitmap)) {
        // Malen
    }
    

    Das macht erstens den Code übersichtlicher und verhindert zweitens Speicherlecks beim Auftreten von Exceptions.



  • ich hab jetzt diese using-blöcke schon oft gesehen, was ist das eigentlich?

    Ist das so eine art "if" ohne else, bei dem man ein objekt im "if" erstellen kann und danach benutzen kann, und wenn dieses objekt im "if" nicht erstellt werden konnte, wird dieser block übersprungen? 😕



  • C#'ler schrieb:

    Ist das so eine art "if" ohne else, bei dem man ein objekt im "if" erstellen kann und danach benutzen kann, und wenn dieses objekt im "if" nicht erstellt werden konnte, wird dieser block übersprungen? 😕

    Nein. 'using' sorgt einfach nur dafür, dass das Block, was man im Using-Kopf erstellt, am Ende des Blocks per 'Dispose' automatisch entsorgt wird.

    Technisch betrachtet macht 'using' *dasselbe* wie folgendes Sprachkonstrukt:

    {
        Graphics g = null;
    
        try {
            g = Graphics.FromImage(bitmap);
            // Malen …
        }
        finally {
            if (g != null) g.Dispose();
        }
    }
    

    Es ist halt nur um einiges lesbarer.



  • FACK! Nur leider wird dies selbst in den Beispielen der MSDN _nicht_ konsequent eingesetzt.



  • michme schrieb:

    FACK! Nur leider wird dies selbst in den Beispielen der MSDN _nicht_ konsequent eingesetzt.

    Ja, die Beispiele von Microsoft sind sowieso leider alle mit Vorsicht zu genießen. Genügend viele davon sind ungenau, schlechte Lösungen, funktionieren nur teilweise oder sogar gar nicht. Die Beispiele halten sich weder an die Coding Guidelines noch an die genaue Semantik des .NET-Frameworks.


Anmelden zum Antworten