Probleme bei vielen ImageIDs

Für allgemeine Fragen zur Programmierung mit PureBasic.
Sven
Beiträge: 374
Registriert: 23.09.2004 12:01

Probleme bei vielen ImageIDs

Beitrag von Sven »

Ich erstelle auf einem Panelgadget mehrere ImageButtonGadgets, denen ich dynamisch mit #PB_Any erzeugte Bilder (für farbige Buttons) zuweise und die ImageID in einer LinkedList speichere. Bei großer Anzahl der Gadgets werden dann irgendwann (etwa 300) keine Bilder mehr erzeugt. Gibt es eine Obergrenze für die Anzahl von Images (Von der Bildgröße ist es hier nicht abhängig.), wodurch wird die Anzahl begrenzt?

Sven
Benutzeravatar
Laurin
Beiträge: 1639
Registriert: 23.09.2004 18:04
Wohnort: /dev/eth0

Beitrag von Laurin »

Es müsste eine Obergrenze für die Anzahl der Images geben. Die errechnet sich aus dem verfügbaren Speicher.

Mehr RAM + Virtuellen Speicher = mehr Images

Mal simpel ausgedrückt. Eventuell beeinflußt der Video-RAM deiner Grafikkarte auch die Anzahl.


Ich bin allerdings der Meinung, dass PB ein Problem mit der Kombination von Images und Gadgets hat. Ein ListIcon kann beispielsweise irgendwie nur 4 Bilder anzeigen. Warum nur 4? Keine Ahnung.
(Muss mal schaun, ob das in der neuen Beta auch noch so ist.)


Greetz Laurin
Now these points of data make a beautiful line.
And we're out of beta. We're releasing on time.
Sven
Beiträge: 374
Registriert: 23.09.2004 12:01

Beitrag von Sven »

>> Es müsste eine Obergrenze für die Anzahl der Images geben.

Daran liegt es aber anscheinend nicht. Es werden immer etwa gleich viele Images erzeugt, egal ob sie 16x16 oder 60x60 groß sind.

Außerdem nimmt die Anzahl der möglichen Images bei mehreren Durchläufen kontinuierlich ab, obwohl ich sie mit IsImage(imgid) => FreeImage(imgid) wieder freigebe.

Ratlos.

Sven
Benutzeravatar
Laurin
Beiträge: 1639
Registriert: 23.09.2004 18:04
Wohnort: /dev/eth0

Beitrag von Laurin »

Die Image-Sache in PB hat vermutlich irgendwo ein Speicherleck. Das würde jedenfalls erklären, warum man immer weniger Images erzeugen kann.

Poste mal deinen Code. Denn könnte man dann vielleicht zu Fred weiterreichen. Eventuell findet er das Problem dann.


Greetz Laurin
Now these points of data make a beautiful line.
And we're out of beta. We're releasing on time.
Sven
Beiträge: 374
Registriert: 23.09.2004 12:01

Beitrag von Sven »

Poste mal deinen Code.
Schwierig, ist ziemlich viel auf mehrere Prozeduren verteilt. Hier der Teil, in dem das Image erzeugt wird. Es wird dann einen ImageButtonGadget zugewiesen, wenn die Prozedur erfolgreich, sonst wird nur ein ButtonGadget erstellt.

Code: Alles auswählen

Procedure.l ObjectDesign(xs.w, ys.w)
  If xs < 10 : xs = 10 : EndIf  ;Mindestgröße Image
  If ys < 10 : ys = 10 : EndIf 
  If obj()\img <> ""  ;wenn Bilddatei angegeben
    obj()\imgid = LoadImage(#PB_Any, obj()\img)  ;Bild laden
  Else
    obj()\imgid = CreateImage(#PB_Any, xs, ys)  ;Bild erzeugen
  EndIf
  If IsImage(obj()\imgid)  ;Bild erfolgreich erzeugt
    ResizeImage(obj()\imgid, xs, ys)  ;Größe anpassen
    If StartDrawing(ImageOutput())
      If obj()\img = ""  ;wenn keine Bilddatei angegeben
        FrontColor(Red(obj()\bcol), Green(obj()\bcol), Blue(obj()\bcol))
        Box(0, 0, xs, ys)  ;Hintergrund zeichnen
      EndIf
      If obj()\name <> ""  ;wenn Name angegeben
        FrontColor(Red(obj()\fcol), Green(obj()\fcol), Blue(obj()\fcol))
        If obj()\font <> "" And obj()\fs > 0
          fid.l = LoadFont(#PB_Any, obj()\font, obj()\fs, obj()\fa)  ;nur zum Zeichnen laden
          If IsFont(fid)
            DrawingFont(UseFont(fid))  ;geladener Font
          Else
            DrawingFont(#PB_Default)  ;interner Font
          EndIf
        EndIf
        DrawingMode(1)  ;Text-Hintergrund transparent
        Locate((xs - TextLength(obj()\name)) / 2 - 2, (ys - obj()\fs) / 2 - 2)
        DrawText(obj()\name)  ;Text zeichnen
        If IsFont(fid)
          CloseFont(fid)  ;Font entfernen
        EndIf
      EndIf
      StopDrawing()     
    EndIf
    ProcedureReturn #True
  Else
    ProcedureReturn #False
  EndIf
EndProcedure
Die Image-Sache in PB hat vermutlich irgendwo ein Speicherleck.
Das würde auch erklären, warum die Systemresourcen scheinbar immer weiter schwinden. (Obwohl der SystemMonitor keinen nennenswerten Speicherbedarf anzeigt).

Sven
celli
Beiträge: 24
Registriert: 11.01.2005 18:45

Beitrag von celli »

soweit ich weiss hat windows selber eine begrenzung der erstellbaren fenster...da images ( oder image-buttons ) ja auch nur selber fenster sind ( wie das der name des betriebssystemes schon sagt ) kann es auch daher kommen aber doch unwahrscheinlich ...
begrenzung für win98 waren es 16.800 und ein paar zerquetschte fenster

erstelle lieber mit der win-api selber die buttons .... mein tip !
Sven
Beiträge: 374
Registriert: 23.09.2004 12:01

Beitrag von Sven »

>>begrenzung für win98 waren es 16.800 und ein paar zerquetschte fenster

Und da liege ich noch weit darunter. Außerdem ist es relativ unabhängig davon, ob noch andere Programme Gadgets / Fenster erstellen...

>>erstelle lieber mit der win-api selber die buttons .... mein tip !

Hilft nix, das Problem liegt definitiv daran, dass nur eine begrenzte Anzahl (etwa 380 bei mir unter Win98) Images indiziert werden können, unabhängig von den ImageGadgets. Und dass die Images auch mit FreeImage() nicht wieder korrekt freigegeben werden, denn die Anzahl möglicher Images sinkt bei mehreren Durchläufen (Indizieren, Freigeben, neu Indizieren...) drastisch bis zum Absturz, nach Neustart sind wieder 380 möglich...

Auch scheint IsImage() nicht so "kugelsicher" wie in der Hilfe behauptet, denn unter Umständen liefert bei

Code: Alles auswählen

  iid = CreateImage(#PB_Any, xs, ys)  ;Bild erzeugen
  If iid <> 0 And IsImage(iid)  ;Bild erfolgreich erzeugt
    If StartDrawing(ImageOutput())
    ...
das StartDrawing eine garstige Fehlermeldung von wegen Output => NULL...

Was soll das?

Sven
Benutzeravatar
computerkranker
Beiträge: 66
Registriert: 12.10.2004 21:21

Beitrag von computerkranker »

In der PB Imageverwaltung scheint allgemein was nicht zustimmen.
In der Hilfe steht ja nun auch drin dass man Image nur bis zu einer Größe von 8192 Pixel erzeugen kann. Das habe ich noch nicht hin bekommen. Bei mir ist bei 4405x4405 Schluss. Hauptspeicher habe ich mit 1GB wohl genug und wird noch nicht mal im Ansatz belastet.

Wenn ich das untere Beispiel einmal starte dann bleibt es bei 4405 stehen, wie ich es auch erwartet habe. Bei meinen Laptop mit 512MB geht das ganze bis 5381. Starte ich es zweimal, dann läuft es weiter. Besonderst Interessant wird es, wenn man den Code nur einmal startet und wartet bis er stehen bleibt, dann ein zweites mal startet und den Imagespeicher in einen der Programme mal frei gibt und mal nicht.
Sehr komisch, Programm 1 läuft dann weiter, wobei es ab und zu mal kein Image erzeugen kann.:freak:

Einfach 2x starten. Einmal mit den anfangs Wert 4000 und einmal 1.
Beispiel:

Code: Alles auswählen

CreateGadgetList(OpenWindow(0,0,0,300,240,#PB_Window_SystemMenu|#PB_Window_ScreenCentered ,"Test"))
TextGadget(0,0,0,300,24,"")
TextGadget(1,0,30,300,24,"")
TextGadget(2,0,60,300,24,"")
TextGadget(3,0,90,300,24,"")
TextGadget(4,0,120,300,24,"")
TextGadget(5,0,150,300,24,"")
CheckBoxGadget(6,0,180,300,24,"UseImage benutzen") 
CheckBoxGadget(7,0,210,300,24,"Imagespeicherhalten")
SetGadgetState(7,#True)
size=Val(InputRequester("Eingabe","Anfangssize eingeben:","1"))
If size<1
  size=1
EndIf
MainState=0
Repeat 
  Event=WindowEvent() 
  If Event
  Else
    If IsImage(0)
      FreeImage(0)
    EndIf
    CreateImage(0,size,size)
    If IsImage(0)
      size+1
      SetGadgetText(0,"Testsize: "+Str(size))
      If GetGadgetState(6)
        UseImage(0)
        SetGadgetText(1,"Image 0 width: "+Str(ImageWidth()))
        SetGadgetText(2,"Image 0 height: "+Str(ImageHeight()))
      Else
        SetGadgetText(1,"")
        SetGadgetText(2,"")
      EndIf
    Else
      SetGadgetText(1,"")
      SetGadgetText(2,"")
      If IsImage(1)
        SetGadgetText(3,"Testimage erzeugt")
        If GetGadgetState(6)
          UseImage(1)
          SetGadgetText(4,"Image 1 width: "+Str(ImageWidth()))
          SetGadgetText(5,"Image 1 height: "+Str(ImageHeight()))
        Else
          SetGadgetText(4,"")
          SetGadgetText(5,"")
        EndIf
      Else
        CreateImage(1,size-1,size-1)
        SetGadgetText(3,"Testimage nicht erzeugt("+Str(size)+")")
        SetGadgetText(4,"")
        SetGadgetText(5,"")
      EndIf
      SetGadgetText(0,"Fehler bei: "+Str(size))
      Delay(25)
      If GetGadgetState(7)=0
        If IsImage(1)
          FreeImage(1)
        EndIf
      EndIf
    EndIf 
  EndIf 
Until Event=#PB_Event_CloseWindow 
Kann natürlich auch an was anderen liegen, dann weis ich aber nicht an was.
celli
Beiträge: 24
Registriert: 11.01.2005 18:45

Beitrag von celli »

windows kann nur eine bestimmte anzahl an images,fenser,buttons..usw. verwalten...unabhängig wie gross der arbeitsspeicher ist...

speicher doch die images in den arbeitsspeicher und ruf sie dann bei gelegenheit auf ( wenn sie sichtbar sein sollen) ... da du immer nur eine gewissen anzahl auch dartsellen kannst (-> auflösung )

so brauchst du nur eine struktur aufzubauen die halt die nötigen adressen,grösse,prozeduren-adressen(beim clicken,mouseover,mousedown) und andere eigenschaften speichert und die sichbaren buttons dann mit dieser struktur verbinden... so das sie bei verschiedenen bilder auf einen anderen event(prozedur) auslösen.

gruss
celli
Antworten