Seite 1 von 1

ResizeImage() und ImageID()

Verfasst: 02.02.2007 14:44
von Gisela
Eine Verständnisfrage zu ResizeImage()

Habe ein kleines Progrämmchen zur Anzeige von Grafiken mit Zoomfunktion geschrieben. Klappt jetzt auch so, wie ich mir das gedacht habe. In der Hilfe zu ResizeImage() steht, daß durch diese Funktion das Handle der Grafik geändert wird. Nun möchte ich vor einem weiteren Zoomvorgang dieses Image wieder freigeben mit FreeImage(). Klappt jedoch nicht, weil ResizeImage anscheinend nicht wirklich eine ImageID zurückliefert. Die Funktion IsImage() liefert mir hier immer den Wert 0.

Bedeutet das, daß ich mir nach und nach den Speicher zumülle? Oder bin ich da ganz auf dem Holzweg?

Code: Alles auswählen


EnableExplicit
Define MainWindow.l           ;Hauptfenster
Define Event.l                ;Window-Ereignisse
Define MenuEvent.l            ;ausgewählter Menüeintrag

Define GadgetList.l           ;Gadget-Liste
Define MapScroll.l            ;Scrollbereich für die Map
Define MapImage.l             ;ID der Map-Grafik
Define NewMapImage.l          ;gezoomte Grafik
Define MapImageGadget.l       ;Gadget zur Grafikanzeige
Define Factor.l               ;Zoomfaktor

Define MenuID.l               ;ID für das Menü

Define fl_Quit.l              ;Flag für Programmende
Define Filename.s             ;Dateiname der Grafik
Define StdPath.s              ;Standard-Pfad
Define ImageX.l, ImageY.l


;Menüeinträge
Enumeration 100
  #MENU_OPEN
  #MENU_END
EndEnumeration

;Zoomfaktoren separat anlegen (gehören aber auch zum Menü)
Enumeration 0 Step 2
  #MENU_ZOOMx1 = 1
  #MENU_ZOOMx2 = 2
  #MENU_ZOOMx4
  #MENU_ZOOMx6
  #MENU_ZOOMx8
  #MENU_ZOOMx10
  #MENU_ZOOMx12
  #MENU_ZOOMx14
  #MENU_ZOOMx16
  #MENU_ZOOMx18
  #MENU_ZOOMx20
EndEnumeration

;Hauptfenster
#WindowFlags = #PB_Window_ScreenCentered| #PB_Window_SystemMenu| #PB_Window_MinimizeGadget| #PB_Window_MaximizeGadget| #PB_Window_SizeGadget
MainWindow = OpenWindow(#PB_Any, 0, 0, 640, 480, "MMM", #WindowFlags)
If MainWindow = 0
  End
EndIf

;Menü anlegen
If CreateMenu(MenuID, WindowID(MainWindow))
  MenuTitle("Datei")
    MenuItem(#MENU_OPEN, "Öffnen...")
    MenuBar()
    MenuItem(#MENU_END, "Beenden")
  MenuTitle("Zoom")
    MenuItem(#MENU_ZOOMx1, "Originalgröße")
    MenuItem(#MENU_ZOOMx2, "x 2")
    MenuItem(#MENU_ZOOMx4, "x 4")
    MenuItem(#MENU_ZOOMx6, "x 6")
    MenuItem(#MENU_ZOOMx8, "x 8")
    MenuItem(#MENU_ZOOMx10, "x 10")
    MenuItem(#MENU_ZOOMx12, "x 12")
    MenuItem(#MENU_ZOOMx14, "x 14")
    MenuItem(#MENU_ZOOMx16, "x 16")
    MenuItem(#MENU_ZOOMx18, "x 18")
    MenuItem(#MENU_ZOOMx20, "x 20")
EndIf


;unterstützte Bildformate
UseJPEGImageDecoder()
UsePNGImageDecoder()
UseTGAImageDecoder()
UseTIFFImageDecoder()

;Hauptschleife
Repeat

  Event = WaitWindowEvent()
  Select Event
  
    ;Menübefehle
    Case #PB_Event_Menu
    
      MenuEvent = EventMenu()
      Select MenuEvent
      
        Case #MENU_OPEN
          Filename = OpenFileRequester("Öffnen", StdPath, "Image Files (*.bmp,*.jpg,*.tiff,*.png,*.tga)|*.bmp;*.jpg;*.tiff;*.png;*.tga|All Files (*.*)|*.*", 0)
          If Filename
            StdPath = Filename
            ;wenn schon eine Grafik geladen war, dann erst mal aufräumen
            If MapImage
              FreeGadget(MapScroll)
              FreeGadget(MapImageGadget)
              FreeImage(MapImage)
            EndIf
            ;Bild laden und in die Gadgetliste eintragen
            MapImage = LoadImage(#PB_Any, Filename)
            ImageX = ImageWidth(MapImage)
            ImageY = ImageHeight(MapImage)
            If MapImage
              CreateGadgetList(WindowID(MainWindow))
                MapScroll = ScrollAreaGadget(#PB_Any, 0, 0, WindowWidth(MainWindow), WindowHeight(MainWindow)-MenuHeight(), ImageX, ImageY, 30)    
                MapImageGadget = ImageGadget(#PB_Any, 0, 0, ImageX, ImageY, ImageID(MapImage))          
              CloseGadgetList()
            EndIf
            
          EndIf
        
        ;Zoomfunktion  
        Case #MENU_ZOOMx1 To #MENU_ZOOMx20
          If IsImage(NewMapImage)
            FreeImage(NewMapImage)
          EndIf
          Factor = MenuEvent
          NewMapImage = ResizeImage(MapImage, ImageX*Factor, ImageY*Factor, #PB_Image_Raw)
          ResizeGadget(MapImageGadget, #PB_Ignore, #PB_Ignore, ImageX*Factor, ImageY*Factor)
          SetGadgetState(MapImageGadget, NewMapImage)
          SetGadgetAttribute(MapScroll, #PB_ScrollArea_InnerWidth, ImageX*Factor)
          SetGadgetAttribute(MapScroll, #PB_ScrollArea_InnerHeight, ImageY*Factor)
          
        Case #MENU_END
          fl_Quit = 1
          
      EndSelect
      
    ;auf Größenänderungen des Hauptfensters reagieren
    Case #PB_Event_SizeWindow
      If MapScroll
        ResizeGadget(MapScroll, #PB_Ignore, #PB_Ignore, WindowWidth(MainWindow), WindowHeight(MainWindow)-MenuHeight())
      EndIf
      
    Case #PB_Event_CloseWindow
      fl_Quit = 1
      
  EndSelect
    
Until fl_Quit = 1


Code editiert - spaces bei den window-flags eingefügt,
damit das forenfenster nicht so breit gezogen wird.
@All: macht das doch mal bitte von vorne herein.
Kaeru fecit

Verfasst: 02.02.2007 14:56
von Green Snake
Die ResizeImage() - Funktion verändert das Handle, nicht aber die ID des Images :D


Du brauchst das Handle nur neu ermitteln, um z.B. ein ImageGadget zu updaten.

Verfasst: 02.02.2007 14:58
von ts-soft
ResizeImage gibt kein Handle zurück und SetGadgetState benötigt das Handle :wink:

Code: Alles auswählen


EnableExplicit
Define MainWindow.l           ;Hauptfenster
Define Event.l                ;Window-Ereignisse
Define MenuEvent.l            ;ausgewählter Menüeintrag

Define GadgetList.l           ;Gadget-Liste
Define MapScroll.l            ;Scrollbereich für die Map
Define MapImage.l             ;ID der Map-Grafik
Define NewMapImage.l          ;gezoomte Grafik
Define MapImageGadget.l       ;Gadget zur Grafikanzeige
Define Factor.l               ;Zoomfaktor

Define MenuID.l               ;ID für das Menü

Define fl_Quit.l              ;Flag für Programmende
Define Filename.s             ;Dateiname der Grafik
Define StdPath.s              ;Standard-Pfad
Define ImageX.l, ImageY.l


;Menüeinträge
Enumeration 100
  #MENU_OPEN
  #MENU_END
EndEnumeration

;Zoomfaktoren separat anlegen (gehören aber auch zum Menü)
Enumeration 0 Step 2
  #MENU_ZOOMx1 = 1
  #MENU_ZOOMx2 = 2
  #MENU_ZOOMx4
  #MENU_ZOOMx6
  #MENU_ZOOMx8
  #MENU_ZOOMx10
  #MENU_ZOOMx12
  #MENU_ZOOMx14
  #MENU_ZOOMx16
  #MENU_ZOOMx18
  #MENU_ZOOMx20
EndEnumeration

;Hauptfenster
#WindowFlags = #PB_Window_ScreenCentered| #PB_Window_SystemMenu| #PB_Window_MinimizeGadget| #PB_Window_MaximizeGadget| #PB_Window_SizeGadget
MainWindow = OpenWindow(#PB_Any, 0, 0, 640, 480, "MMM", #WindowFlags)
If MainWindow = 0
  End
EndIf

;Menü anlegen
If CreateMenu(MenuID, WindowID(MainWindow))
  MenuTitle("Datei")
    MenuItem(#MENU_OPEN, "Öffnen...")
    MenuBar()
    MenuItem(#MENU_END, "Beenden")
  MenuTitle("Zoom")
    MenuItem(#MENU_ZOOMx1, "Originalgröße")
    MenuItem(#MENU_ZOOMx2, "x 2")
    MenuItem(#MENU_ZOOMx4, "x 4")
    MenuItem(#MENU_ZOOMx6, "x 6")
    MenuItem(#MENU_ZOOMx8, "x 8")
    MenuItem(#MENU_ZOOMx10, "x 10")
    MenuItem(#MENU_ZOOMx12, "x 12")
    MenuItem(#MENU_ZOOMx14, "x 14")
    MenuItem(#MENU_ZOOMx16, "x 16")
    MenuItem(#MENU_ZOOMx18, "x 18")
    MenuItem(#MENU_ZOOMx20, "x 20")
EndIf


;unterstützte Bildformate
UseJPEGImageDecoder()
UsePNGImageDecoder()
UseTGAImageDecoder()
UseTIFFImageDecoder()

;Hauptschleife
Repeat

  Event = WaitWindowEvent()
  Select Event
 
    ;Menübefehle
    Case #PB_Event_Menu
   
      MenuEvent = EventMenu()
      Select MenuEvent
     
        Case #MENU_OPEN
          Filename = OpenFileRequester("Öffnen", StdPath, "Image Files (*.bmp,*.jpg,*.tiff,*.png,*.tga)|*.bmp;*.jpg;*.tiff;*.png;*.tga|All Files (*.*)|*.*", 0)
          If Filename
            StdPath = Filename
            ;wenn schon eine Grafik geladen war, dann erst mal aufräumen
            If MapImage
              FreeGadget(MapScroll)
              FreeGadget(MapImageGadget)
              FreeImage(MapImage)
            EndIf
            ;Bild laden und in die Gadgetliste eintragen
            MapImage = LoadImage(#PB_Any, Filename)
            ImageX = ImageWidth(MapImage)
            ImageY = ImageHeight(MapImage)
            If MapImage
              CreateGadgetList(WindowID(MainWindow))
                MapScroll = ScrollAreaGadget(#PB_Any, 0, 0, WindowWidth(MainWindow), WindowHeight(MainWindow)-MenuHeight(), ImageX, ImageY, 30)   
                MapImageGadget = ImageGadget(#PB_Any, 0, 0, ImageX, ImageY, ImageID(MapImage))         
              CloseGadgetList()
            EndIf
           
          EndIf
       
        ;Zoomfunktion 
        Case #MENU_ZOOMx1 To #MENU_ZOOMx20
          Factor = MenuEvent
          ResizeImage(MapImage, ImageX*Factor, ImageY*Factor, #PB_Image_Raw)
          ResizeGadget(MapImageGadget, #PB_Ignore, #PB_Ignore, ImageX*Factor, ImageY*Factor)
          SetGadgetState(MapImageGadget, ImageID(MapImage))
          SetGadgetAttribute(MapScroll, #PB_ScrollArea_InnerWidth, ImageX*Factor)
          SetGadgetAttribute(MapScroll, #PB_ScrollArea_InnerHeight, ImageY*Factor)
         
        Case #MENU_END
          fl_Quit = 1
         
      EndSelect
     
    ;auf Größenänderungen des Hauptfensters reagieren
    Case #PB_Event_SizeWindow
      If MapScroll
        ResizeGadget(MapScroll, #PB_Ignore, #PB_Ignore, WindowWidth(MainWindow), WindowHeight(MainWindow)-MenuHeight())
      EndIf
     
    Case #PB_Event_CloseWindow
      fl_Quit = 1
     
  EndSelect
   
Until fl_Quit = 1
Hab jetzt nur das Resize angepaßt und nicht alles durchgesehen!

Verfasst: 02.02.2007 15:10
von Gisela
*AHA-Erlebnis = ON*
Danke euch!
*AHA-Erlebnis = OFF*

Allerdings ist mir jetzt immer noch nicht ganz klar, wie die Speicherverwaltung bei ResizeImage vorgenommen wird. Denke doch, daß erst mal neuer Speicher für das vergrößerte/verkleinerte Bild allokiert werden muss. Was passiert mit dem alten? Wird dieser automatisch freigegeben?

Nebenbei:
Auch mal ein großes Lob an dieses Board. Habe in den letzten Tagen sehr viel an Infos hier erlesen können. Ohne würde ich wohl immer noch darüber grübeln, wie ich die Zoomfunktion mit Point() und Box() Befehlen nachbilde ;-))

Verfasst: 02.02.2007 15:25
von ts-soft
>> Was passiert mit dem alten? Wird dieser automatisch freigegeben?
Ja, darum brauchste Dich nicht kümmern. Sowas passiert autom., aber nicht
unbedingt unmittelbar (windows läßt sich manchmal Zeit :wink: )
Bei Strings ist es dasselbe, wenn ein String an einen anderen angehängt wird
und nicht genügend speicher hinter dem string frei ist, erhält der string eine
neue Adresse, wo es passt. Wäre schlimm wenn man sich da um die Freigabe
kümmern müßte :freak:

Verfasst: 02.02.2007 15:37
von Gisela
Dank dir.
Stimmt, ist wohl recht nützlich, wenn man sich um die Speicherverwaltung nicht kümmern muss

...

wobei ..
heißt das, ich könnte mir die FreeGadget und FreeImage-Anweisungen dann sparen, wenn ich ein neues Bild lade?
Finde es eigentlich chicer, nicht mehr benötigte Speicherbereiche freizugeben, sofern ein Funktion dafür zur Verfügung steht.

Verfasst: 02.02.2007 15:43
von ts-soft
>> heißt das, ich könnte mir die FreeGadget und FreeImage-Anweisungen dann sparen, wenn ich ein neues Bild lade?
Hab nicht so genau geguckt, aber normallerweise braucht man ein
ImageGadget nicht freigeben, weil es mit neuen Inhalt gefüllt wird, dasselbe
gilt für Images. Wenn Du temporäre Bilder oder ähnlich erstellst, dann ist es
besser diese freizugeben, das ist hier aber nicht der Fall.

Verfasst: 02.02.2007 16:13
von Gisela
hmmmmmmm *grübel*

jetzt weiß ich auch wieder, warum ich beim Öffnen einer neuen Datei erst mal die alten Sachen (Image, Gadgets) wieder freigegeben habe. Wenn ich diese drei Free-Anweisungen kommentiere, verhält sich das Programm folgendermaßen:

- beim Laden des ersten Bildes nach dem Programmstart wird die geladene Grafik normal angezeigt.
- beim nächsten Laden wird die Größe des ImageGadget zwar auf die Maße des neu geladenen Bildes gesetzt, der Inhalt des Bildes ist jedoch noch der des alten Bildes
- wird das Event #PB_Event_SizeWindow durchlaufen, dann wird das neu geladene Bild korrekt angezeigt.

Nach längerem Probieren kam ich dann zu dieser Lösung, daß Image, ImageGadget und ScrollAreaGadget erst freigegeben werden, sofern sie schon einmal angelegt waren. Somit wurde eine neu geladene Grafik auch sofort korrekt angezeigt.

Verfasst: 02.02.2007 16:26
von ts-soft

Code: Alles auswählen

EnableExplicit
Define MainWindow.l           ;Hauptfenster
Define Event.l                ;Window-Ereignisse
Define MenuEvent.l            ;ausgewählter Menüeintrag

Define GadgetList.l           ;Gadget-Liste
Define MapScroll.l            ;Scrollbereich für die Map
Define MapImage.l             ;ID der Map-Grafik
Define NewMapImage.l          ;gezoomte Grafik
Define MapImageGadget.l       ;Gadget zur Grafikanzeige
Define Factor.l               ;Zoomfaktor

Define MenuID.l               ;ID für das Menü

Define fl_Quit.l              ;Flag für Programmende
Define Filename.s             ;Dateiname der Grafik
Define StdPath.s              ;Standard-Pfad
Define ImageX.l, ImageY.l


;Menüeinträge
Enumeration 100
  #MENU_OPEN
  #MENU_END
EndEnumeration

;Zoomfaktoren separat anlegen (gehören aber auch zum Menü)
Enumeration 0 Step 2
  #MENU_ZOOMx1 = 1
  #MENU_ZOOMx2 = 2
  #MENU_ZOOMx4
  #MENU_ZOOMx6
  #MENU_ZOOMx8
  #MENU_ZOOMx10
  #MENU_ZOOMx12
  #MENU_ZOOMx14
  #MENU_ZOOMx16
  #MENU_ZOOMx18
  #MENU_ZOOMx20
EndEnumeration

;Hauptfenster
#WindowFlags = #PB_Window_ScreenCentered| #PB_Window_SystemMenu| #PB_Window_MinimizeGadget| #PB_Window_MaximizeGadget| #PB_Window_SizeGadget
MainWindow = OpenWindow(#PB_Any, 0, 0, 640, 480, "MMM", #WindowFlags)
If  CreateGadgetList(WindowID(MainWindow))
  MapScroll = ScrollAreaGadget(#PB_Any, 0, 0, WindowWidth(MainWindow), WindowHeight(MainWindow)-MenuHeight(), ImageX, ImageY, 30)
  MapImageGadget = ImageGadget(#PB_Any, 0, 0, ImageX, ImageY, 0)
EndIf

If MainWindow = 0
  End
EndIf

;Menü anlegen
If CreateMenu(MenuID, WindowID(MainWindow))
  MenuTitle("Datei")
  MenuItem(#MENU_OPEN, "Öffnen...")
  MenuBar()
  MenuItem(#MENU_END, "Beenden")
  MenuTitle("Zoom")
  MenuItem(#MENU_ZOOMx1, "Originalgröße")
  MenuItem(#MENU_ZOOMx2, "x 2")
  MenuItem(#MENU_ZOOMx4, "x 4")
  MenuItem(#MENU_ZOOMx6, "x 6")
  MenuItem(#MENU_ZOOMx8, "x 8")
  MenuItem(#MENU_ZOOMx10, "x 10")
  MenuItem(#MENU_ZOOMx12, "x 12")
  MenuItem(#MENU_ZOOMx14, "x 14")
  MenuItem(#MENU_ZOOMx16, "x 16")
  MenuItem(#MENU_ZOOMx18, "x 18")
  MenuItem(#MENU_ZOOMx20, "x 20")
EndIf


;unterstützte Bildformate
UseJPEGImageDecoder()
UsePNGImageDecoder()
UseTGAImageDecoder()
UseTIFFImageDecoder()

;Hauptschleife
Repeat

  Event = WaitWindowEvent()
  Select Event

    ;Menübefehle
    Case #PB_Event_Menu

      MenuEvent = EventMenu()
      Select MenuEvent

        Case #MENU_OPEN
          Filename = OpenFileRequester("Öffnen", StdPath, "Image Files (*.bmp,*.jpg,*.tiff,*.png,*.tga)|*.bmp;*.jpg;*.tiff;*.png;*.tga|All Files (*.*)|*.*", 0)
          If Filename
            StdPath = Filename
            MapImage = LoadImage(#PB_Any, Filename)
            ImageX = ImageWidth(MapImage)
            ImageY = ImageHeight(MapImage)
            Factor = MenuEvent
            ResizeImage(MapImage, ImageX*Factor, ImageY*Factor, #PB_Image_Raw)
            ResizeGadget(MapImageGadget, #PB_Ignore, #PB_Ignore, ImageX*Factor, ImageY*Factor)
            SetGadgetState(MapImageGadget, ImageID(MapImage))
            SetGadgetAttribute(MapScroll, #PB_ScrollArea_InnerWidth, ImageX*Factor)
            SetGadgetAttribute(MapScroll, #PB_ScrollArea_InnerHeight, ImageY*Factor)
          EndIf

          ;Zoomfunktion
        Case #MENU_ZOOMx1 To #MENU_ZOOMx20
          Factor = MenuEvent
          ResizeImage(MapImage, ImageX*Factor, ImageY*Factor, #PB_Image_Raw)
          ResizeGadget(MapImageGadget, #PB_Ignore, #PB_Ignore, ImageX*Factor, ImageY*Factor)
          SetGadgetState(MapImageGadget, ImageID(MapImage))
          SetGadgetAttribute(MapScroll, #PB_ScrollArea_InnerWidth, ImageX*Factor)
          SetGadgetAttribute(MapScroll, #PB_ScrollArea_InnerHeight, ImageY*Factor)

        Case #MENU_END
          fl_Quit = 1

      EndSelect

      ;auf Größenänderungen des Hauptfensters reagieren
    Case #PB_Event_SizeWindow
      If MapScroll
        ResizeGadget(MapScroll, #PB_Ignore, #PB_Ignore, WindowWidth(MainWindow), WindowHeight(MainWindow)-MenuHeight())
      EndIf

    Case #PB_Event_CloseWindow
      fl_Quit = 1

  EndSelect

Until fl_Quit = 1
Ich weiß nicht, obs so sein soll, kannste ja mal testen. Das doppelte im Event-Ereignis noch in eine Procedure packen, war ich jetzt zu faul :wink:

Verfasst: 02.02.2007 16:36
von Gisela
jau danke, klappt. Lediglich den Zoomfaktor muss ich wieder auf 1 setzen, wenn ich ein neues Bild öffne.

So siehts auch sauberer aus. Beim Programmstart die benötigten Gadgets initial erstellen und später dann nur noch die erforderlichen Gadget-Attribute setzen.