vb@rchiv
VB Classic
VB.NET
ADO.NET
VBA
C#
Top-Preis! AP-Access-Tools-CD Volume 1  
 vb@rchiv Quick-Search: Suche startenErweiterte Suche starten   Impressum  | Datenschutz  | vb@rchiv CD Vol.6  | Shop Copyright ©2000-2024
 
zurück

 Sie sind aktuell nicht angemeldet.Funktionen: Einloggen  |  Neu registrieren  |  Suchen

VB.NET - Ein- und Umsteiger
PictureBox Maximale Größe 
Autor: BasicOpa
Datum: 08.11.23 14:05

Hallo und guten Tag.

Probem mit VB.Net 2015: "Nicht genügend Speicherplatz". Task-Manager zeigt zum betreffenden Zeitpunkt 18,6 (!) GB verfügbaren Speicher. Image-Größe ca. 560 MB.

Daraus ergeben sich für mich folgende Fragen ... in der Hoffung hier Anworten zu bekommen:

1. Ist die Größe einer PictureBox grundsätzlich begrenzt? Wenn ja, bei welchem Wert an Pixeln? Wenn nein, wo und ggf. wie kann die Begrenzung einem vorhandenen Bedarf (ggf. während der Laufzeit) angepasst werden?

2. Wenn eine Begrenung vom System-Umfeld abhängt, wie kann sie zur Laufzeit ermittelt werden? Zweck: Größenanpassung des anzuzeigenden Images.

Vorab schon mal vielen Dank für jede Antwort

Beste Grüße
BasicOpa
Themenbaum einblendenGesamtübersicht  |  Zum Thema  |  Suchen

Re: PictureBox Maximale Größe 
Autor: Manfred X
Datum: 08.11.23 15:21

Hallo!

Die sichtbare Größe eines Picturebox-Control ist durch die Größe des Parent-Formulars begrenzt.
Größere Bilder können in diesem Control automatisch gezoomt dargestellt werden
(Sizemode-Eigenschaft).

Die maximale Größe einer Bitmap ist durch den verfügbaren Speicherplatz begrenzt.
Der Speicherbedarf ist durch Größe die enschlüsselten Bitmap gegeben.
Je nach Format werden dabei pro Pixel 8, 24, 32 oder 64 Bit benötigt.

Auf meinem System werden 24-Bit-Bitmaps bis zur Größe von etwa 26000 * 26000 Pixel
akzeptiert. Bei größeren Bitmaps kommt die Meldung "invalider Parameter".

Kann es sein, dass Du im Programm nacheinander mehrere Bitmap-Objekte (z.B. aus Dateien)
oder Graphics-Objekte erstellst, ohne sie nach Gebrauch wieder freizugeben (Dispose)?
In dem Fall bleiben Windows-Ressourcen im Speicher "liegen".
Themenbaum einblendenGesamtübersicht  |  Zum Thema  |  Suchen

Re: PictureBox Maximale Größe 
Autor: BasicOpa
Datum: 09.11.23 17:54

Hallo Manfred,

vielen Dank für deine schnelle Antwort, die mir gewiss weiter hilft, glechzeitig aber auch zusätzliche Fragen nach sich zieht.

Ich denke es ist sinnvoll, wenn ich so kurz wie möglich beschreibe, um welche Art mein Problem ist:
Innerhalb einer recht komplexen Anwendung wird jeweils der Gleisplan einer virtuellen Modellbahn-Anlage angezeigt. Solch ein Plan ist oft deutlich größer, als das Fenster in dem er innerhalb der Anwendung angezeigt wird. Deshalb wird eine Bitmap in der tatsächlich benötigten Größe zur Laufzeit angelegt, in die der jeweilige Gleisverlauf gezeichnet wird. Diese Bitmap wird dann in eine PictureBox übertragen, die ebenfalls größenmäßig angepasst ist. In Festergröße liegt ein Panel über der PictureBox, mittels dem dann ausschnittsweise innerhalb der PictureBox navigiert wird.

Das funktioniert mit einem identischen Programm, dass mittel VB.Net 2005 erstellt und kompiliert wurde sowohl im Debug- als auch Exe-Modus. Mit VB.Net 2015 treten die Speicherprobleme auf.

1. Ist meine Annahme richtig, dass der tatsächliche verfügbare Arbeitsspeicher (z.B. 24 GB) zunächst mit dem Problem nichts zu tun hat?

2. Ist es richtig, dass die maximalen Größen der Bitmap und der PictureBox getrennt betrachtet werden müssen?

Wenn das soweit stimmt, dann ...

3. Zur Bitmap: Verstehe ich es richtig, dass die maximale Größe eine interne Festlegung ist, die vom gewählten Format anhängt (8, 24, 32, 64 Bit) Um welches "Format" handelt es sich?. Habe ich einen Einfluss auf jenes "Format". Wenn ja, wo und wie? Während der Dimensionierung? Mit welchem Parameter?

Hintergrund: Ich vermute dass das Formt Einluss auf die Qualität der Grafik hat. Da es sich in meinem Fall um eine sehr einfache Darstellung von einfarbigen Linien handelt, läge es nahe, den niedrigsten Wert (8) vorzugeben, um damit die maximale Größenbegrenzung zu erweitern (?)

4. Zur PictureBox: Die Begrenzung "Parent-Form" habe ich verstanden. Allerdings muss die PictureBox immer den ganzen Plan aufnehmen. Er kann in Gänze "gezoomt" werden, aber nicht so weit, dass er ins Anwendungsfenster der Parent-Form passt. Deshalb die Maßname des darüber gelegten Panels. Das funktioniert ja auch.

Bleibt also die Frage, wo und wie die maximale Größe von PictureBoxen festgestellt und ggf. auch verändert werden kann.

5. Zuletzt: Wie kann ich den Ausnahmefehler "Nicht genügend Arbeitsspeicher", ebenso "Ungültiges Format" (Tritt bei Dimensionierung der Bitmap auf) abfangen, um darauf adäquat zu reagieren.Es geht darum, den "Absturz" der Anwendung zu vermeiden. Statt dessen können interne Zoom-Maßnamhem so lange wiederholt werden, bis die Darstellung möglivh ist.

Ich weiß, viele Frage. Und ich hoffe, dass ich damit noch gerade im Rahmen möglicher Auskünfte bleibe

Viele Grüße
BasicOpa
Themenbaum einblendenGesamtübersicht  |  Zum Thema  |  Suchen

Re: PictureBox Maximale Größe 
Autor: Manfred X
Datum: 09.11.23 19:09

Hallo!

Zu dem von Dir fetsgestellten Unterschied zwischen VS 2005 und VS 2015
kann ich nichts sagen. Ich nutze VS 2022.

So weit ich festgestellt habe, scheint die Größe einer Bitmap durch
den Wert Integer.Maxvalue begrenzt zu sein.
Es gilt offenbar folgende Grenze:
Länge in Pixel * Breite in Pixel * Byte/Pixel < Integer.Maxvalue - einige Verarbeitungsbytes
- und zwar bei einer Auflösung von 96 Pixel pro Zoll.

Der Faktor Byte/Pixel beträgt bei 24Bit-Bitmaps 3 Byte und bei 64Bit-Bitmaps 8 Byte.
Das Pixelformat eines Bildes ist durch den Inhalt der geladenen Bilddatei bestimmt.

Ich vermute, Dein Problem könnte woanders liegen.
Du schreibst, Du hättest eine recht komplexe Anwendung erstellt.
Hast Du im Code sicher gestellt, dass erstellte Bitmaps und Pictureboxen nach
Gebrauch stets wieder freigegeben werden? (Using-Block oder Dispose-Methode).

Das Picturebox-Control und die darin angezeigte Bitmap sind zwei verschiedene
Objekte. Meines Wissens erhält die Instanz der Picturebox (Image-Eigenschaft)
eine Referenz auf die Bitmap.

VS-Dokumentation:
"Wenn Sie dasselbe Bild in mehreren PictureBox Steuerelementen verwenden möchten,
erstellen Sie für jedes PictureBoxBild einen Klon des Bildes.
Der Zugriff auf dasselbe Bild aus mehreren Steuerelementen bewirkt, dass eine Ausnahme
auftritt."
(Der Clon einer Bitmap belegt weiteren Speicher.)

Die Overflow-Ausnahme lässt sich in einem Try-Catch-Block auffangen.

Wie groß sind Deine Bild-Dateien?
Themenbaum einblendenGesamtübersicht  |  Zum Thema  |  Suchen

Re: PictureBox Maximale Größe 
Autor: BasicOpa
Datum: 10.11.23 13:59

Hallo Manfred, einmal mehr: Vielen Dank.

Ein Beispiel: Dimensionierung:
Dim Gleisplan As New Bitmap(GpX, GpY, PixelFormat.Format32bppArgb)
Dim g As Graphics = Graphics.FromImage(GleisPlan)
Werte zur Luafzeit: 24361, 5966

Nach deiner Formel sollte das Ergegnis deutich kleiner sein, als ein Integer.Maxvalue, wobei ich allerdfings den Faktor Bytes/Pixel, der bei meiner Dimensionierung anzuwenden wäre, aus Unkenntnis nicht berücksichtigt habe. Wie komme ich zu diesem Wert?

Es wird kein Bild geladen, sondern mittels g.DrawLine gezeichnet.

Nach der Übernahme der Bitmap in die PictureBox lösche ich die Bitmap mit "Gleisplan = Nothing". Bei deutlich kleineren Bitmaps funktioniert das. Verwende ich statt dessen "Gleisplan.dispose()" kommt ein Laufzeitfehler "Ungültige Parameter".

Innerhalb enes Programm-Aufrufs geht es immer nur um einen Gleisplan. Und der wird immer nur in ein und derselben PictureBox angeziegt.

Viele Grüße
BasicOpa
Themenbaum einblendenGesamtübersicht  |  Zum Thema  |  Suchen

Re: PictureBox Maximale Größe 
Autor: Manfred X
Datum: 10.11.23 14:31

Hallo!

Die meisten Klassen beziehen sich auf das Net-Framework (bzw. Net-Core).
Instanzen solcher Klassen werden an Windows (Garbage Collector) zum Löschen
freigegeben, sobald in der erstellenden Anwendung die letzte Referenz darauf
aufgehoben worden ist.

Es gibt aber Klassen, die nutzen uralte Windows-Methoden (Ressourcen).
Diese Klassen sind im Managementsystem des Net-Framework- (bzw. Net-Core)
nicht direkt zugänglich.
Es muss ein expliziter Aufruf der Dispose-Methode der Klasse erfolgen,
um die Windows-Ressourcen im Speicher wieder frei zu geben.
Das gilt für viele Windows.Forms.Controls und die entsprechenden
Klassen zum Zeichnen, sowie für Bitmaps.

Sei BMP eine Bitmap-Instanz:
Im Code gibt der Aufruf bmp.dispose die Windows-Ressourcen frei.
Das Bitmap-Objekt bmp ist jetzt noch vorhanden und referenziert,
aber es kann nicht länger genutzt werden.
Danach solltest Du im Code bmp = nothing setzen und dadurch die
(letzte) Referenz aufheben.
Einige Sekunden danach löscht Windows (GC) das Objekt aus dem Speicher.

Eine 32-Bit-Bitmap nutzt 32 Bit für die Farbcodierung eines Pixel,
das sind also 4 Byte.

Folgender Code funktioniert bei mir problemlos (Net-Core 6):
    Dim Gpx, GPy As Integer
    Gpx = 24361
    GPy = 5966
 
    Dim Gleisplan As New Bitmap(GpX, GpY, PixelFormat.Format32bppArgb)
 
    Using g As Graphics = Graphics.FromImage(Gleisplan),
            pn As New System.Drawing.Pen(Color.Blue, 4)
        g.Clear(Color.Yellow)
        g.DrawLine(pn, 0, 0, 24000, 5500)
    End Using
    Gleisplan.Save("G:\downloads\gleisplan.png", _
      Drawing.Imaging.ImageFormat.Png)
 
    Gleisplan.Dispose()
    Gleisplan = Nothing
Klappt auch bei FW 4.
Welche Framework-Version verwendest Du?

Beitrag wurde zuletzt am 10.11.23 um 15:01:19 editiert.
Themenbaum einblendenGesamtübersicht  |  Zum Thema  |  Suchen

Demo-Formular zur Bitmap-Freigabe 
Autor: Manfred X
Datum: 11.11.23 08:07

Public Class Form1
 
    Dim pb As New PictureBox With
        {.Parent = Me, .Top = 10, .Left = 10, .Width = 300, .Height = 300,
        .SizeMode = PictureBoxSizeMode.Zoom, .BackColor = Color.White,
        .BorderStyle = BorderStyle.Fixed3D}
 
    Dim WithEvents btnCreateBitmap As New Button With
        {.Parent = Me, .Top = 320, .Left = 10, .Width = 300, .Text = "Create"}
    Dim WithEvents btnKillBitmap As New Button With
        {.Parent = Me, .Top = 360, .Left = 10, .Width = 300, .Text = "Kill"}
    Dim WithEvents btnSaveBitmap As New Button With
        {.Parent = Me, .Top = 400, .Left = 10, .Width = 300, .Text = "Save"}
 
    Dim Gleisplan As Bitmap
    Dim rndm As New Random(Now.Millisecond)
 
 
    Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load
 
        Me.MinimumSize = New Size(350, 500)
    End Sub
 
 
    Private Sub CreateBitmap()
 
        DeleteBitmap() 'Freigabe sicher stellen
 
        Dim Gpx, GPy, x1, y1, x2, y2 As Integer
        Gpx = 24361
        GPy = 5966
 
        Gleisplan = New Bitmap(Gpx, GPy,
             Imaging.PixelFormat.Format32bppArgb)
 
        pb.Image = Gleisplan
 
        Using g As Graphics = Graphics.FromImage(Gleisplan),
                pn As New System.Drawing.Pen(Color.Blue, 8)
            g.Clear(Color.Yellow)
            For i As Integer = 0 To 10
                x2 = x1
                y2 = y1
                x1 = CInt(rndm.NextDouble() * Gpx)
                y1 = CInt(rndm.NextDouble() * GPy)
                g.DrawLine(pn, x1, y1, x2, y2)
            Next i
        End Using
 
    End Sub
 
 
    Private Sub SaveBitmap()
        If Gleisplan Is Nothing Then Exit Sub
 
        Dim filepath As String = "G:\downloads\gleisplan.png"
        IO.File.Delete(filepath)
        Gleisplan.Save(filepath, Drawing.Imaging.ImageFormat.Png)
    End Sub
 
 
    Private Sub DeleteBitmap()
 
        'Referenz in der Picturebox aufheben
        pb.Image = Nothing
 
        If Gleisplan IsNot Nothing Then
            'Windows-Resourcen (Handles etc.) der Bitmap entfernen
            Gleisplan.Dispose
            'Letzte Referenz auf die Bitmap aufheben
            '(Löschen der Net-Klasse anfordern)
            Gleisplan = Nothing
        End If
    End Sub
 
    Private Sub btnKillBitmap_Click(sender As Object, e As EventArgs) Handles _
      btnKillBitmap.Click
        DeleteBitmap()
    End Sub
 
    Private Sub btnCreateBitmap_Click(sender As Object, e As EventArgs) Handles _
      btnCreateBitmap.Click
        CreateBitmap()
    End Sub
 
    Private Sub btnSaveBitmap_Click(sender As Object, e As EventArgs) Handles _
      btnSaveBitmap.Click
        SaveBitmap()
    End Sub
End Class
Themenbaum einblendenGesamtübersicht  |  Zum Thema  |  Suchen

Re: Demo-Formular zur Bitmap-Freigabe 
Autor: BasicOpa
Datum: 11.11.23 14:19

Hallo Manfred,
herzlichen Dank für eine so ausführliche Hilfe.

Ich werden den Code in eine Testumgebung übernehmen. Ich hoffe, dass ich bei der Ausführung die eine oder andere Einzelheit auch noch verstehen werde- Wenn nicht, traue ich mich einfach noch mal zu fragen.

Zur Frage des benutzen FW. Ich verwende 4.6.

Bei doeser Gelegenheit komme ich noch mal eine Frage zurück: Ich denke, auch in deinem Beispieltest geht es um das Pixelformat "png", bei dem 4 Bytes für die Darstellung eines Pixels benötigt werden. Bei meinem Anspruch an Grafik-Qualitat würde das "jpg" durchaus reichen. Was wäre zu ändern, wenn ich dieses verwende. Und von welcher Anzahl von Bytes pro Pixel wäre dann auszugehen?

Viele Grüße
BasicOpa
Themenbaum einblendenGesamtübersicht  |  Zum Thema  |  Suchen

Re: Demo-Formular zur Bitmap-Freigabe 
Autor: Manfred X
Datum: 11.11.23 15:42

Hallo!

Die Zahl der Bits, die pro Pixel gespeichert werden, bestimmt,
wie viele Farben darstellbar sind.
Dazu kommen eventuell weitere Angaben z,B. zur Transparenz.

Wenn Du pro Pixel nur eine geringe Farbenanzahl benötigst, kannst Du
auf ein "indiziertes Pixelformat" zurückgreifen (z.B. 256 Farben bei
nur 8 Bit pro Pixel).
In dem Fall wird pro Pixel keine Farbinformation gespeichert, sondern
eine Farb-Palette wird angelegt und jedes Pixel enthält einen Zeiger
auf einen Paletteneintrag.
Allerdings kann das Graphics-Objekt solche Formate nicht bearbeiten.
(Das Sperren der Bildinformation im Speicher und direkter Zugriff
auf die Bilddaten wäre erforderlich.)

Probiere beim Anlegen einer Bitmap das Format:
Imaging.PixelFormat.Format16bppRgb555
Es verwendet 2 Byte pro Pixel.
Bei der von Dir angegebenen Bildgröße werden dann weniger als
300 MB im Hauptspeicher belegt.


Die dateibezogenen Formate BMP, PNG, JPG, TIF, WebP usw. geben an,
auf welche Weise die Bildinformationen beim Speichern in einer Datei
komprimiert werden. Dabei kann es zu Informationsverlusten kommen.

Speziell für das JPG-Format gilt, dasss es keine reine Komprimierung
zur Verfügung stellt, sondern dass ein "Ersatzbild" berechnet wird,
das dem Original zwar täuschend ähnlich sieht, aber mathematische
Eigenschaften besitzt, die eine stärkere Komprimierung ermöglichen.

Ich rate deshalb zur Verwendung der PNG-Komprimierung.
Sie arbeitet nahezu verlustfrei, liefert allerdings relativ große
Bild-Dateien.
Themenbaum einblendenGesamtübersicht  |  Zum Thema  |  Suchen

Re: Demo-Formular zur Bitmap-Freigabe 
Autor: BasicOpa
Datum: 12.11.23 15:35

Hallo Manfred,

Mir ist eingefallen, du hast zuvor schon mal das MaxValue eines Integers im Zusammenhang der möglichen Größenbegrenung einer Bitmap erwähnt. Ich habe ein bisschen rumprobiert und glaube sogar, einen abfragbaren Grenzwert auf folgnede, einfache Weise ermitteln zu können. Und zwar an jenem kontreten Besipiel: 24369 * 5966 = 145385454 * 16 = 2326167264. Dieser Wert übersteigt den Wert des IntegerValues und in meiner Anwendung tritt das Speicherproblem auf. Reduziere ich die Größe der Bitmap in Schritten, bis der so ermittelte Vergleichswert auf knapp über 2000000000 sinkt, tritt das Speicherproblem nicht mehr auf. Ich glaube nicht, dass dies ein Zufall ist.

In meiner Anwendung nutzt es mich nichts, das Bild in einer PictureBox mittels "SizeMode" auf die PictureBox anzupassen. Sondern ich muss umgekehrt die PictureBox auf die Größe des Gleisplans anpassen. Weil die jedoch in aller Regel damit größer sein müsste als das Parentfenster, liegt ein Panel über dem Fenster mittels dem in der "überhämgenden" PictureBox navigiert werden kann.

Wenn ich also die Größengrenze der als Grundlage der Zeichnung anzulegenden Bitmap kenne, kann ich die Maße der Gleisplanelemente, also der einzelnen Gleise schrittweise so lange reduzieren, bis der betreffende Grenzwert unterschritten ist und es somt zu keinem Laufzeitfehler mehr kommen kann.

Nochmal herzlichen Dank für die sehr ausführliche Hilfe.

Beste Grüße
BasicOpa
Themenbaum einblendenGesamtübersicht  |  Zum Thema  |  Suchen

Re: Demo-Formular zur Bitmap-Freigabe 
Autor: Manfred X
Datum: 12.11.23 16:44

Hallo!

Du rechnest falsch! Der Faktor 16 existiert nicht.
Ein Byte umfasst 8 Bits.
Selbst ein 64BitsPerPixel-Format benötigt nur 8 Byte pro Pixel.
Das von mir oben vorgeschlagene Format benötigt nur 2 Byte Pro Pixel.
Du musst Dein Gleisplan-Bild nicht verkleinern, um einen Überlauf
zu verhindern.
Erstelle ein Testprojekt und kopiere meinen Beispielcode in
eine System.Windows.Form.

Die Sizemode-Einstellung der Picturebox hat nichts mit dem
Speicherbedarf einer Bitmap zu tun, sondern regelt nur die
Darstellung des Image in der Picturebox (also den sichtbaren
Abschnitt am Bildschirm).
Die Zoom-Einstellung der Picturebox habe ich nur benutzt,
um das Beispiel kurz und übersichtlich gestalten zu können.
Themenbaum einblendenGesamtübersicht  |  Zum Thema  |  Suchen

Re: Demo-Formular zur Bitmap-Freigabe 
Autor: BasicOpa
Datum: 13.11.23 00:06

Hallo Manfred,

ich benutzte bei dem dargestellten Vorgehen nicht das vorgeschlagene Imaging.PixelFormat.Format16bppRgb555. Denn, mein Versuch damit wurde sofort nach dem Start der Anwendung mit einem Lauffzeitfehler beendet (Ungültiger Parameter) Ich habe Imaging.PixelFormat.Format32bppArgb) verwendet. Und ob und wie es auch immer zu erklären ist oder auch nicht, habe ich mit zahlreichen Tests exakt unterhalb jener IntegerValue Maxgrenze mit der Ausführung meiner Anwendung kein Problem gehabt.

Gleichwohl werde ich natürlich dein erstelltes Demo-Formular mit diesen wie auch mit erweiteren Ausmaßen in mein Projekt einbinden. Ich bin gespannt, welche Grenzen sich dann zeigen werden. Ich berichte davon.

Viele Grüße
BasicOpa

Beitrag wurde zuletzt am 13.11.23 um 00:12:27 editiert.
Themenbaum einblendenGesamtübersicht  |  Zum Thema  |  Suchen

Re: Demo-Formular zur Bitmap-Freigabe 
Autor: BasicOpa
Datum: 13.11.23 14:26

Hallo Manfred,

ja, mit dem Code deiner "Form1" wird ein gelber Balken gezeichnet. Allerdings nicht in Größe der Bitmap, sondern in jener, in welcher die PictureBox definiert wurde. Ich glaube, das ist im komkreten Zusammengang nicht relevant.

In diesem Test sind sowohl die verwendeten Abmessungen, als auch die identische Dimensionierung der Bitmap angwendet. Bei mir tritt das Problem auf. In deiner Form1 nicht. Den Verdacht, es könnte bei mir am Fehlen entsprechender Löschvorgänge der Bitmap liegen, kann vergessen werden, weil der Fehler bei mir schon mit dem allerersten Aufruf auftritt.

Ich habe zum Test deiner Form1 einmal schrittweise um jeweils 1000 Pixel den Y-Parameter hochgesetzt. Das geht - auch bei jeweiligem Neustart - solange gut, bis der Y-Wert 13000 erreicht ist. Dann brincht auch diese Variante ab. Allerdings mit "Ungültiger Parameter".

Abgesehen von der Ursachenermittlung, die mich freilich interessiert, denke ich an meine praktische Anwendung. Ich muss mit jedem noch so großen Gleisplan klarkommen, insofern, als die Anwendung nicht mit einen Laufzeitfehler beendet werden darf. Die beste Lösung ist also, wenn ich die Grenze des Möglichen kenne und beim Überschreiten dieser das Programm entsprechend reagieren lasse. Das habe ich dann im Griff. Ein weitere "Notlösung" wäre, den Laufzeitfehler abzufangen. Ich habe die Bitmap-Dimensionierung - bei der ja der Laufzeitfehler auftritt - in eine "Try-Chach"-Abfrage eingebunden. Die allerdings reagiert nicht. Bleibt also die Frage, ob und ggf. wie sich die "Notlösung" auf andere Weise realisieren ließe?

Viele Grüße
BasicOpa
Themenbaum einblendenGesamtübersicht  |  Zum Thema  |  Suchen

Re: Demo-Formular zur Bitmap-Freigabe 
Autor: Manfred X
Datum: 13.11.23 17:15

Hallo!

Die Anzeige des Balkens im Beispielformular ergibt sich aus dem Unterschied
im Seitenverhältnis der Bitmap zum Seitenverhältnis des Bildes (gezoomt).

Bei Verwendung des 16er Formats (= 2 Byte pro Pixel = 32000 Farben)
können Bilder bis zur Größe 32500 * 32500 bearbeitet werden.
Das liegt knapp unter dem dem Integer.MaxValue-Wert.

Mit etwas Programmieraufwand lassen sich Bilder jeder Größe verarbeiten.
Man speichert das Bild im Bitmap-Format (unkomprimiert) auf der Festplatte
und holt sich je nach Einstellung der Scroller für die vertikale und
horizontale Position im Bild nur den entsprechenden Abschnitt des
Bildes aus dem geöffneten Filestream (in ein Array) und setzt dieses
Array als Bildpixel-Info zur Anzeige in die Bitmap.

Einige Grundlagen findest Du hier:
https://www.vbarchiv.net/workshop/details.php?id=100
Man erstellt eine Bitmap und setzt den jeweils zu bearbeitenden Bildabschnitt
aus den aufgearbeiteten Daten des Filestreams an die Speicherposition der
Bitmap-Daten.
Das habe ich bisher zwar nie probiert, es könnte aber funktionieren.
(Interop.Marshalling)
Aber ausgepasst: Bei Fehlern beim Entwickeln stürzt VS gerne mal ab.
Immer zuerst das Projekt sichern, ehe man Debuggt.

VS 2022 hat ein eigenes Bildbearbeitungs-Tool.
Was es leistet kann ich aber nicht beurteilen.
https://learn.microsoft.com/de-de/visualstudio/designers/image-editor?view=vs-2022
Themenbaum einblendenGesamtübersicht  |  Zum Thema  |  Suchen

Re: PictureBox Maximale Größe 
Autor: sv00010
Datum: 13.11.23 20:18

BasicOpa schrieb:
Zitat:


Nach der Übernahme der Bitmap in die PictureBox lösche ich
die Bitmap mit &quot;Gleisplan = Nothing&quot;. Bei deutlich
kleineren Bitmaps funktioniert das.


Vermutlich solltest du danach GC.Collect() ausführen.
Damit ordnest du an, dass JETZT eine Garbage Collection durchgeführt wird
und nicht irgendwann, wenn es dem .net Framework gerade passt.

Beitrag wurde zuletzt am 13.11.23 um 20:20:54 editiert.
Themenbaum einblendenGesamtübersicht  |  Zum Thema  |  Suchen

Re: PictureBox Maximale Größe 
Autor: Manfred X
Datum: 13.11.23 21:16

Hallo!

Vor der Freigabe der letzten Referenz auf die Bitmap muss die Dispose-Methode
gerufen werden. Der Aufruf der Finalisierung der Bitmap durch den GC
kann die Windows-Handles und die dadurch belegten Speicherbereiche
nicht löschen.
Themenbaum einblendenGesamtübersicht  |  Zum Thema  |  Suchen

Re: PictureBox Maximale Größe 
Autor: Kuno60
Datum: 14.11.23 00:09

Hallo!

Nach der Übernahme der Bitmap in die PictureBox, kann Gleisplan = Nothing gesetzt werden, was aber keinen großen Nutzen bringt.
Es wird lediglich der Verweis auf die Bitmap gelöscht, der aber weiterhin von der PictureBox gehalten wird. Dispose darf man nicht aufrufen, da dann die Bitmap zerstört wird und auch in der PictureBox nicht mehr zur Verfügung steht.

Visual Studio 2015 benötigt deutlich mehr Speicher als Visual Studio 2005. Da kann der Speicher schnell knapp werden. Bitmaps werden im nicht-verwalteten-Speicher angelegt.
Bei mir ist die Grenze bei etwa 21000 x 21000 bei 32 Bit ARGB. Darüber kommt beim Zeichnen in die Bitmap:
"Ein Ausnahmefehler des Typs "System.OutOfMemoryException" ist in System.Drawing.dll aufgetreten."

Dieser Fehler tritt nicht auf, wenn ich das Projekt als 64 Bit kompiliere. Die Obergrenze der Bitmap liegt dann bei etwa 23.000 x 23.000, was dem Integer.MaxValue entspricht (2^31 = 2.147.483.648 / 4 Byte = 536.870.912 daraus die Wurzel ergibt 23.170).

Tipps:
- Probiere es mit 64 Bit.
- Verwende eine kleinere Bitmap.
- Benutze ein kleineres PixelFormat (bei 24 Bit RGB ist der Standard-Hintergrund Schwarz statt Transparent)

Oder, wenn du nicht zwingend eine Bitmap brauchst, zeichne direkt in eine PictureBox oder in ein UserControl, über das Paint-Ereignis. Die Grafik kann dann auch über Transformation verschoben und skaliert werden.

VG

Beitrag wurde zuletzt am 14.11.23 um 00:27:17 editiert.
Themenbaum einblendenGesamtübersicht  |  Zum Thema  |  Suchen

Re: PictureBox Maximale Größe 
Autor: Manfred X
Datum: 14.11.23 05:20

Hallo!

Vor dem Löschen des letzten Verweises auf die Bitmap MUSS Dispose gerufen werden,
weil sonst keine Freigabe des Bild-Speichers und der Graphik-Ressourcen erfolgt.

Es spielt keine Rolle, ob das Projekt als 32- oder 64-Bit kompiliert wird, weil
die Verwaltung der Graphikressourcen in Windows.Forms die gleichen
Windows-Apis nutzt.

Die maximale Größe einer Bitmap im Speicher liegt bei etwa 2GB.
Bitmaps können "theoretisch" 32000*32000 Bit umfassen, wobei die
Verteilung diese Produkts auf Höhe oder Breite flexibel ist.

Ob eine Bitmap zu einem bestimmten Zeitpunkt tatsächlich
angelegt werden kann, hängt davon ab, ob der dadurch angeforderte
zusammenhängende Hauptspeicher-Block verfügbar ist.
Ist der Speicher durch andere Anwendungen "fragmentiert" worden,
scheitert die Erstellung der Bitmap. Das kann zu einer Argument-Ausnahme
führen, nicht unbedingt zu einer Speichermangel-Ausnahme.
Es ist also nicht genau vorherzusagen, ob genügend Speicher verfügbar ist.
Die von mir gemachten Angaben beziehen sich auf eine Lage, in der keine
weiteren Anwendungen mit hohem Speicherbedarf ausgeführt werden.

Was genau verstehst Du unter "direkt in eine Picturebox zeichnen"? CreateGraphics?

Der Speicherbedarf einer Bitmap ist unabhängig davon, welche Visual Studio-Version
oder welche Framework- bzw. Core-Version man verwendet. Die Verwaltung obliegt
nicht deren Management.

Beitrag wurde zuletzt am 14.11.23 um 05:46:24 editiert.
Themenbaum einblendenGesamtübersicht  |  Zum Thema  |  Suchen

Re: PictureBox Maximale Größe 
Autor: sv00010
Datum: 14.11.23 07:47

Es wäre gut, genau diese leider wichtigen Kleinigkeiten, in einem Grundlagen-Kurs zusammenzufassen.
Dies könnte wichtig sein, weil wenig Speicher zu verbrauchen usw. ist zwar lästig, aber auch wichtig.

Beitrag wurde zuletzt am 14.11.23 um 07:48:36 editiert.
Themenbaum einblendenGesamtübersicht  |  Zum Thema  |  Suchen

Re: PictureBox Maximale Größe 
Autor: Manfred X
Datum: 14.11.23 08:37

Hallo!

Das ist alles nicht so kompliziert gestaltet, wie es sich liest.
Wer zur Laufzeit DYNAMISCH Objekte erstellt und auch wieder löscht,
muss prüfen, ob in diesen Klassen eine Dispose-Methode implementiert ist.
Solche Klassen nutzt man in einem Using-Block oder man muss darauf
achten, deren Dispose-Methode zu rufen, ehe man die letzte Referenz aufhebt.
Themenbaum einblendenGesamtübersicht  |  Zum Thema  |  Suchen

Re: PictureBox Maximale Größe 
Autor: Kuno60
Datum: 15.11.23 12:17

Hallo!

Manfred X schrieb:
Zitat:

Vor dem Löschen des letzten Verweises auf die Bitmap MUSS Dispose gerufen werden, weil sonst keine Freigabe des Bild-Speichers und der Graphik-Ressourcen erfolgt.


Das ist Richtig. Aber im Fall von BasicOpa, darf Dispose nicht nach der Übergabe an die PictureBox aufgerufen werden, da die Gleisplan Bitmap nicht temporär ist, sonder über die gesamte Laufzeit besteht.
Erst beim Beenden der Anwendung muss Dispose aufgerufen werden.

Zitat:

Es spielt keine Rolle, ob das Projekt als 32- oder 64-Bit kompiliert wird, weil die Verwaltung der Graphikressourcen in Windows.Forms die gleichen Windows-Apis nutzt.


Stimmt zwar, aber trotzdem traten bei mir bei 64-Bit keine "OutOfMemory" Fehler auf. Warum das so ist, weiß ich auch nicht.
Wenn die Bitmap aber zu groß ist, wird trotzdem der Fehler "Ungültiges Argument" ausgelöst.

Zitat:

Ob eine Bitmap zu einem bestimmten Zeitpunkt tatsächlich angelegt werden kann, hängt davon ab, ob der dadurch angeforderte zusammenhängende Hauptspeicher-Block verfügbar ist. Ist der Speicher durch andere Anwendungen fragmentiert worden, scheitert die Erstellung der Bitmap. Das kann zu einer Argument-Ausnahme führen, nicht unbedingt zu einer Speichermangel-Ausnahme. Es ist also nicht genau vorherzusagen, ob genügend Speicher
verfügbar ist.


Genau, eine Bitmap wird von der GDI+ erstellt und wenn diese nicht genug zusammenhängenden Speicher reservieren kann, wird der Fehler "Ungültiges Argument" ausgelöst.

Zitat:

Was genau verstehst Du unter "direkt in eine Picturebox zeichnen", CreateGraphics?


Nicht mit CreateGraphics.
So:
  Private Sub PictureBox1_Paint(sender As Object, e As PaintEventArgs) Handles _
    PictureBox1.Paint
    Dim g As Graphics = e.Graphics
    g.SmoothingMode = SmoothingMode.HighQuality
    g.DrawLine(Pens.Red, 5, 5, 100, 100)
    g.DrawLine(Pens.Blue, 25, 5, 200, 100)
  End Sub
Themenbaum einblendenGesamtübersicht  |  Zum Thema  |  Suchen

Re: PictureBox Maximale Größe 
Autor: Manfred X
Datum: 15.11.23 13:55

Hallo!

Beim Beenden einer Anwendung muss kein Dispose gerufen werden.

Die Dispose-Methode der IDISPOSABLE-Schnittstelle ruft man während der
Laufzeit einer Anwendung, bevor die letzte Referenz auf ein Objekt aufgehoben
wird, das nicht der Net-Verwaltung unterliegt.
Das ist notwendig, damit die nächsten Speicheranforderungen dieser oder
anderer Anwendungen nicht scheitern.

Die OutOfMemory-Ausnahme tritt gewöhnlich auf, wenn der im Code angeforderte Speicher
durch die CLR der Anwendung nicht zugewiesen werden kann.
Die Invalid Parameter-Ausnahme tritt auf, wenn die Erstellung des internen
Bitmap-Handles scheitert. Aus welchen Gründen auch immer. (Typ-Überlauf etc.)
Themenbaum einblendenGesamtübersicht  |  Zum Thema  |  Suchen

Re: PictureBox Maximale Größe 
Autor: BasicOpa
Datum: 15.11.23 17:25

Hallo zusammen,

aufgrund der zahreichen Hinweise komme ich der Lösung zu meinem Problem viele Schritte näher.

Eine Frage indes konnte nicht beantwortet werden. Nämlich, wie ein in jenem Zusammenhang auftretender Laufzeitfehler angefangen werden kann. Mittels "Try - Catch" jedenfalls nicht. Oder ich habe nicht herausgefunden, wo genau und was in die Klammer einzubinden ist.

Warum ist das wichtig für mich?

Ich habe gelernt, dass es so etwas wie eine Fausregel gibt, was die Maxgröße von Bitmaps anbelangt. Darauf kann ich mich einstellen, in dem ich Größen jeseits gar nicht erst zulasse. Ich habe aber auch gelernt, dass jene Fausregel nicht verlässlich ist, weil die Systemumgebung sie nach unten korrigieren kann. Also drohen stets Laufzeitfehler. Das ist gar nicht schön ... und deshalb wäre so wichtig diese Situationen abzufangen. Vielleicht hat jemand ja noch eine zündende Idee?

Beste Grüße
BasicOpa
Themenbaum einblendenGesamtübersicht  |  Zum Thema  |  Suchen

Re: PictureBox Maximale Größe 
Autor: Manfred X
Datum: 15.11.23 21:50

Hallo!
Einfach den Try-Catch-Block in die obige Funktion meines Beispiels
einfügen und bei einer Ausnahme im Catch abbrechen.
    Private Sub CreateBitmap()
 
 
        DeleteBitmap() 'Freigabe sicher stellen
 
        Dim Gpx, GPy, x1, y1, x2, y2 As Integer
        Gpx = 24361
        GPy = 5966
 
        Try
            Gleisplan = New Bitmap(Gpx, GPy,
             Imaging.PixelFormat.Format32bppArgb)
 
        Catch ex As Exception
            MsgBox("Bitmap kann nicht erstellt werden" & vbCrLf & ex.Message)
            DeleteBitmap()
            Exit Sub
        End Try
 
        pb.Image = Gleisplan
 
        Using g As Graphics = Graphics.FromImage(Gleisplan),
                pn As New System.Drawing.Pen(Color.Blue, 8)
            g.Clear(Color.Yellow)
            For i As Integer = 0 To 10
                x2 = x1
                y2 = y1
                x1 = CInt(rndm.NextDouble() * Gpx)
                y1 = CInt(rndm.NextDouble() * GPy)
                g.DrawLine(pn, x1, y1, x2, y2)
            Next i
        End Using
 
    End Sub
Themenbaum einblendenGesamtübersicht  |  Zum Thema  |  Suchen

Sie sind nicht angemeldet!
Um auf diesen Beitrag zu antworten oder neue Beiträge schreiben zu können, müssen Sie sich zunächst anmelden.

Einloggen  |  Neu registrieren

Funktionen:  Zum Thema  |  GesamtübersichtSuchen 

nach obenzurück
 
   

Copyright ©2000-2024 vb@rchiv Dieter Otter
Alle Rechte vorbehalten.
Microsoft, Windows und Visual Basic sind entweder eingetragene Marken oder Marken der Microsoft Corporation in den USA und/oder anderen Ländern. Weitere auf dieser Homepage aufgeführten Produkt- und Firmennamen können geschützte Marken ihrer jeweiligen Inhaber sein.

Diese Seiten wurden optimiert für eine Bildschirmauflösung von mind. 1280x1024 Pixel