Seite 1 von 1

Canvas speichern - gelöst :-)

Verfasst: 24.03.2015 13:17
von GerhardHoeberth
Ich habe vor Jahren mit VB6 programmiert und habe mir jetzt - da .NET keine Alternative ist, PureBasic gekauft.
Bin aber hier nun wieder blutiger Anfänger :-(

Seit Tagen durchsuche ich hier das Forum nach einer Antwort auf mein Problem. Da ich nicht fündig geworden bin (was sicherlich auch daran liegt, dass ich das meiste noch gar nicht verstehe und daher auch nicht nachvollziehen kann) poste ich jetzt mal meine Frage.

Ich möchte auf einem Canvas zeichnen und dann das Bild abspeichern. Weiß aber nicht, sie ich den Inhalt des Canvas auf ein Image bekomme.
Ich habe dazu drei Dateien (test2.pbf, test2.pbi und test2.pb)

test2.pbf

Code: Alles auswählen

Global Window_0

Global Button_0, Canvas_0, Button_1

Declare Speichern(EventType)
Declare Zeichne(EventType)

Procedure OpenWindow_0(x = 0, y = 0, width = 750, height = 500)
  Window_0 = OpenWindow(#PB_Any, x, y, width, height, "", #PB_Window_SystemMenu | #PB_Window_MinimizeGadget | #PB_Window_MaximizeGadget | #PB_Window_SizeGadget | #PB_Window_ScreenCentered)
  Button_0 = ButtonGadget(#PB_Any, 50, 120, 90, 40, "Start", #PB_Button_Left)
  GadgetToolTip(Button_0, "startet zeichnen")
  Canvas_0 = CanvasGadget(#PB_Any, 220, 10, 480, 480)
  Button_1 = ButtonGadget(#PB_Any, 50, 240, 90, 40, "Speichern")
EndProcedure

Procedure Window_0_Events(event)
  Select event
    Case #PB_Event_CloseWindow
      ProcedureReturn #False

    Case #PB_Event_Menu
      Select EventMenu()
      EndSelect

    Case #PB_Event_Gadget
      Select EventGadget()
        Case Button_0
          Zeichne(EventType())          
        Case Button_1
          Speichern(EventType())          
      EndSelect
  EndSelect
  ProcedureReturn #True
EndProcedure
test2.pbi

Code: Alles auswählen

OpenWindow_0()

Repeat
  
  pgrlauf = Window_0_Events(WaitWindowEvent())
  
Until pgrlauf = #False 

End
test2.pb

Code: Alles auswählen

IncludeFile "test2.pbf"
IncludeFile "test2.pbi"

Procedure Zeichne(EventType)
  a = 480
  b = 480
  StartDrawing(CanvasOutput(Canvas_0))
  For i = 0 To a - 1
    For j = 0 To b - 1
      Plot(i, j, RGB(Mod((i/3)*(j/5), 255), Mod(i*j, 255), Mod(a, 255)))
    Next j  
  Next i  
  StopDrawing()

EndProcedure

Procedure Speichern(EventType)
  File$ = SaveFileRequester("Save Image...", "Mandala", "BMP-Images|*.bmp", 0)
  If File$ And (FileSize(File$) = -1 Or MessageRequester("CanvasGadget", "Overwrite this file? " + File$, #PB_MessageRequester_YesNo) = #PB_MessageRequester_Yes)
    
   
       If SaveImage(CanvasOutput(Canvas_0), File$, #PB_ImagePlugin_BMP ) = 0
          MessageRequester("CanvasGadget", "Cannot save image: " + File$)
       EndIf
              
    EndIf            
  
EndProcedure
Ergebnis ist aber [ERROR] Das angegebene #Image ist nicht initialisiert. :bluescreen:

So funktioniert es offenbar nicht :-(
Wie überträgt man also den Inhalt eines Canvas auf ein Image, das man dann speichern kann?

herzlichen Gruß
Gerhard

Re: Canvas speichern

Verfasst: 24.03.2015 14:03
von edel
Kopiere den Inhalt des Canvasgadget in ein neues Bild und speichere dieses.

Beispiel :

Code: Alles auswählen

Enumeration Window
  #WINDOW
EndEnumeration

Enumeration Gadget
  #GAD_START
  #GAD_SAVE
  #GAD_CANV
EndEnumeration

Procedure SaveImageFromCanvas(CanvasNr, FileName.s)  
  Protected result.l
  ;ermittelt die groesse des Bildes uber das Gadget
  Protected cx = GadgetWidth(CanvasNr) 
  Protected cy = GadgetHeight(CanvasNr)
  ; erstellt ein temporaeres leeres Bild
  
  Protected ImgNr = CreateImage(#PB_Any, cx, cy)
  
  ; holt das Bild vom Canvasgadget
  Protected CanvasImageID = GetGadgetAttribute(CanvasNr, #PB_Canvas_Image)
  
  ;oeffnet die Ausgabe auf das leere Bild
  StartDrawing(ImageOutput(ImgNr))
  ;kopiert CanvasImageID in das leere Bild
  DrawImage(CanvasImageID, 0, 0)
  StopDrawing()
  
  ;speichert das Bild
  result = SaveImage(ImgNr, FileName)
  ;löscht das temporaere bild wieder
  FreeImage(ImgNr)
  
  ProcedureReturn result
EndProcedure

Procedure Event_Button_Start()
  
  StartDrawing(CanvasOutput(#GAD_CANV))
  
  a = OutputWidth()
  b =  OutputHeight()
  
  For i = 0 To a - 1
    For j = 0 To b - 1
      Plot(i, j, RGB(Mod((i/3)*(j/5), 255), Mod(i*j, 255), Mod(a, 255)))
    Next j  
  Next i  
  StopDrawing()  
  
EndProcedure

Procedure Event_Button_Save()
  Protected FileName.s
  
  FileName = SaveFileRequester("", "mandala.bmp", "BMP-Images|*.bmp", 0)
  
  If FileName
    SaveImageFromCanvas(#GAD_CANV, FileName)  
  EndIf
  
EndProcedure


Procedure Main()
  
  If OpenWindow(#WINDOW, #PB_Ignore, #PB_Ignore, 600, 400, "")
    
    ButtonGadget(#GAD_START, 5, 5, 100, 23, "Start")
    ButtonGadget(#GAD_SAVE, 5, 35, 100, 23, "Save")
    CanvasGadget(#GAD_CANV, 110, 5, 485, 390, #PB_Canvas_Border)
    
    BindGadgetEvent(#GAD_START, @Event_Button_Start(), #PB_EventType_LeftClick)
    BindGadgetEvent(#GAD_SAVE, @Event_Button_Save(), #PB_EventType_LeftClick)
    
    Repeat
    Until WaitWindowEvent() = #PB_Event_CloseWindow
    
    
  EndIf
  
EndProcedure:End Main()


Re: Canvas speichern

Verfasst: 24.03.2015 15:03
von GerhardHoeberth
edel hat geschrieben:Kopiere den Inhalt des Canvasgadget in ein neues Bild und speichere dieses.
Vielen herzlichen Dank für die rasche Antwort.
Ich habs bei mir eingefügt und ausprobiert ... ES FUNKTIONIERT :lol: :D

jetzt muss ich es nur noch durcharbeiten, um es auch zu verstehen und schon hab ich wieder was dazu gelernt ;-)

herzlichen Gruß
Gerhard

PS: Gibt es hier eine Möglichkeit, ein Thema als "abgeschlossen" oder "beantwortet" zu markieren?
Und gibt es eine Möglichkeit, einem Mitglied, das einem geholfen hat, einen Dankpunkt zukommen zu lassen?

Re: Canvas speichern

Verfasst: 24.03.2015 17:02
von Andesdaf
alternativ könntest du auch direkt auf das Image zeichnen.

Code: Alles auswählen

IncludeFile "test2.pbf"
IncludeFile "test2.pbi"

Procedure Zeichne(Output)
  a = 480
  b = 480
  StartDrawing(Output)
  For i = 0 To a - 1
    For j = 0 To b - 1
      Plot(i, j, RGB(Mod((i/3)*(j/5), 255), Mod(i*j, 255), Mod(a, 255)))
    Next j 
  Next i 
  StopDrawing()

EndProcedure

Procedure Speichern(EventType)
  Protected cx = GadgetWidth(Canvas_0)
  Protected cy = GadgetHeight(Canvas_0)
  Protected ImgNr = CreateImage(#PB_Any, cx, cy)
  File$ = SaveFileRequester("Save Image...", "Mandala", "BMP-Images|*.bmp", 0)
  If File$ And (FileSize(File$) = -1 Or MessageRequester("CanvasGadget", "Overwrite this file? " + File$, #PB_MessageRequester_YesNo) = #PB_MessageRequester_Yes)
   
       Zeichne(ImageOutput(ImgNr))
       If SaveImage(ImgNr, File$, #PB_ImagePlugin_BMP ) = 0
          MessageRequester("CanvasGadget", "Cannot save image: " + File$)
       EndIf
             
    EndIf           
 
EndProcedure
Dann müsstest du statt Zeichne(EventType()) in der test2.pbf Zeichne(CanvasOutput(Canvas_0)) aufrufen.
Ob das mit dem Formdesigner geht weiß ich aber gerade nicht aus dem Stand.

Re: Canvas speichern

Verfasst: 24.03.2015 17:05
von ts-soft
GerhardHoeberth hat geschrieben:PS: Gibt es hier eine Möglichkeit, ein Thema als "abgeschlossen" oder "beantwortet" zu markieren?
Und gibt es eine Möglichkeit, einem Mitglied, das einem geholfen hat, einen Dankpunkt zukommen zu lassen?
Die Möglichkeit gibt es hier nicht, wobei die auch nicht jeder als sinnvoll erachtet. Einige fügen "erledigt" oder ähnlich,
nachträglich in den Titel ein (1. Beitrag, Editieren!).
Viel wichtiger ist es immer einen sinnvollen Titel zu haben (hat geklappt :allright: ), damit die Suchfunktion auch mal greift.

Danke Button gibt es offiziell nicht, aber den kann man nachträglich einfügen, siehe hier: http://www.purebasic.fr/german/viewtopi ... 38#p287738
ansonsten macht es auch ein einfaches danke schön :wink:

PS: Interessante Homepage, wenn auch ganz anderes Thema.

Gruß
Thomas

Re: Canvas speichern

Verfasst: 24.03.2015 23:56
von GerhardHoeberth
Andesdaf hat geschrieben:alternativ könntest du auch direkt auf das Image zeichnen.
Man kann direkt auf ein Image zeichnen? Wozu benötige ich dann überhaupt das Canvas-Objekt? :shock:

Re: Canvas speichern - gelöst :-)

Verfasst: 25.03.2015 00:05
von NicTheQuick
Damit kann man das Bild gut anzeigen. Und da es Double Buffering nutzt, kann man darin auch interaktiv das Bild ändern. Mit einem ImageGadget geht das nicht besonders gut.

Re: Canvas speichern

Verfasst: 25.03.2015 09:57
von Nino
GerhardHoeberth hat geschrieben:Man kann direkt auf ein Image zeichnen? Wozu benötige ich dann überhaupt das Canvas-Objekt? :shock:
Vergleiche doch mal die Eigenschaften von CanvasGadget() und ImageGadget(). :-)

Re: Canvas speichern

Verfasst: 25.03.2015 14:27
von GerhardHoeberth
Nino hat geschrieben:Vergleiche doch mal die Eigenschaften von CanvasGadget() und ImageGadget(). :-)
Wenn ich das richtig sehe, gibt es bei Canvas wesentlich mehr Möglichkeiten von Events?

In meinem Fall wäre dann wohl tatsächlich das Image die bessere Wahl, weil ich die Zeichnung nur automatisiert nach bestimmten Parametern erstellen lassen will und keinesfalls ein Mausevent benötige...
Danke für die Links :-)

Gerhard