Laden...

Beim Arbeiten mit Bitmaps wird der Arbeitsspeicher voll gemüllt!

Erstellt von Coooder vor 11 Jahren Letzter Beitrag vor 11 Jahren 3.470 Views
C
Coooder Themenstarter:in
180 Beiträge seit 2011
vor 11 Jahren
Beim Arbeiten mit Bitmaps wird der Arbeitsspeicher voll gemüllt!

hallo leute 😃

ich hab da nen kleines problem ... ich lasse mir ein Bild anzeigen und will dann darin mit der maus einige sachen schwarz übermalen ... prinzipiell geht das auch, ich ändere die entsprechenden pixel der System.Drawing.Bitmap in schwarz und wandel das die Bitmap dann um damit ich sie in einem wpf image container anzeigen lassen kann ... naja und dabei kloppt er den speicher voll ... hier ma die methoden:

private void screenshotImg_MouseMove(object sender, MouseEventArgs e)
        {
            if (e.LeftButton == MouseButtonState.Pressed && crossOut)
            {
                int mx = Convert.ToInt32(Mouse.GetPosition(screenshotImg).X);
                int my = Convert.ToInt32(Mouse.GetPosition(screenshotImg).Y - 10);
                int x;
                int y;

                for (int i = 0; i < 10; i++)
                    for (int ii = 0; ii < 20; ii++)
                    {
                        x = mx + i;
                        y = my + ii;
                        if (x > 0 && y > 0 && x < screenshotImg.Width && y < screenshotImg.Height)
                            if (ScreenShot.BitmapToEdit.GetPixel(x, y) != System.Drawing.Color.Black)
                                ScreenShot.BitmapToEdit.SetPixel(x, y, System.Drawing.Color.Black);
                    }
                screenshotImg.Source = Pictures.BmpToImageSource(ScreenShot.BitmapToEdit);
            }
        }
public static ImageSource BmpToImageSource(Bitmap bmp)
        {
            return System.Windows.Interop.Imaging.CreateBitmapSourceFromHBitmap(bmp.GetHbitmap(), IntPtr.Zero, Int32Rect.Empty, BitmapSizeOptions.FromEmptyOptions());
        }

hoffe mir kann da einer helfen, vielen dank schon mal im vorraus 😃

C
258 Beiträge seit 2011
vor 11 Jahren

Hallo,

Räumt der GC den speicher wieder auf wenn du nichts machst?

Ich denke es liegt daran das du dir nach jedem MouseMove eine neue BitMap Source erstellst die auch irgendjeamnd wieder aufräumen muss.

am besten du zeichnest dir deine BMP einfach selbst per OnPaint.

Hinweis von talla vor 11 Jahren

Eigentlich gehört das Thema in ein entsprechendes GUI Forum, aber da es zumindest in der Ausgangsfrage um Interop von mehreren geht, hab ichs mal hier ins Grafikforum verschoben.

6.862 Beiträge seit 2003
vor 11 Jahren

Hallo,

Erster Fehler - Doku nicht gelesen...
In der Doku zur Bitmap.GetHBitmap Methode steht

You are responsible for calling the GDI DeleteObject method to free the memory used by the GDI bitmap object. Da du das nicht machst, wird dann Speicher natürlich zugehaun.

Zweiter Fehler:
Von hinten durch die Brust ins Auge...
Wozu zum Teufel lässt du dir von einem Bild, wo du ja anscheinend als ImageSource direkt vorliegen hast

...ich lasse mir ein Bild anzeigen... ein Windows Forms Bitmap erzeugen um das zu editieren und dann noch zusätzlich über umkopieren von unmanaged Spiecher wieder ein WPF ImageSource zu erstellen?
Benutz einfach die WriteableBitmap Klasse von WPF und gut ist.

Selbst ohne das selbstverursachte Memoryleak von dir verbraucht deine Variante wesentlich mehr Speicher als die reine WPF Variante da du ja bei jedem MouseMove neue Bilder erzeugst. Es reicht doch nur bei dem einen bestehenden jeweils die Pixel zu setzen.

Baka wa shinanakya naoranai.

Mein XING Profil.

C
224 Beiträge seit 2009
vor 11 Jahren

Hi,

war Get-/SetPixel nicht extrem langsam?
Ich würde:
*einen Speicher (z.B. Bytearray) vorhalten. *Control.MouseDown-/Move -> setze Control.Invalidate(Ausschnitt) *Control.Paint-> kopiere Bytearray Ausschnitt zu ein Bitmap oder Bitmap Ausschnitt über Bitmap.LockBits *Control.Paint-> zeichne Bitmap Ausschnitt

Evtl. hat noch jm. bessere Ideen. Sowas in der Art gab es bestimmt schon 100x im Forum.
Hier z.B.:

GetPixel und SetPixel um Längen geschlagen. 800 mal schneller

Gruß,
CoLo

C
224 Beiträge seit 2009
vor 11 Jahren

... oder Du benutzt die WriteableBitmap Klasse von Talla xD.

C
Coooder Themenstarter:in
180 Beiträge seit 2011
vor 11 Jahren

ok, danke für die informationen.
aber ich hab so ein bischen probs dabei das so an zu wenden.
Bei der Bitmap handelt es sich um einen Screenshot den ich so erstelle.

public static Bitmap CreateScreenshot(int left, int top, int width, int height)
        {
            BitmapToEdit = new Bitmap(width, height);

            Graphics g = Graphics.FromImage(BitmapToEdit);
            g.CopyFromScreen(left, top, 0, 0, new System.Drawing.Size(width, height));

            g.Dispose();
            return BitmapToEdit;
        }

mit einer WriteableBitmap klappt es leider nicht, zumindest nicht so. Und ich hab nix passendes gefunden für eine WriteableBitmap. Man kann leider auch keine WriteableBitmap aus einer normalen Bitmap erzeugen.

6.862 Beiträge seit 2003
vor 11 Jahren

Hallo,

das du erst einen Screenshot erzeugst, erwähnst du ja gar nicht im Ursprungsbeitrag. Da kann man dann durchaus das CopyFromScreen verwenden. Aber aus dem Bitmap kannst du natürlich ein WriteableBitmap erzeugen. Mit LockBits holst du dir vom Bitmap die BitmapData und mit den Infos kannst du mit WriteableBitmap.WritePixels die Daten übernehmen.

Ansonsten gibst den sonst üblichen Weg von Bitmap in BitmapImage und mit dem BitmapImage kannst du dann ne WriteableBitmap erzeugen.

Baka wa shinanakya naoranai.

Mein XING Profil.

C
Coooder Themenstarter:in
180 Beiträge seit 2011
vor 11 Jahren

okay, ich habs nun so umgebaut und es scheint alles zu funktionieren 😃
Das speicher problem is auch gelöst!
Danke schonmal soweit!