[solved] Exporting a Canvas content as jpg, png file

Hello

I would like to export the content of a Canvas as a jpg, png file for example. I went through some topics in this forum and I have tested some of the proposed solutions (see below) using f.GetSaveFolderItem. It fails : at any time, the file that I created does not exist (f.Exists = false)

It seems to be normal according to the Language reference : “The GetSaveFolderItem function does not create the file. It simply returns a FolderItem that represents the potential file. To create the actual file, you will need to call or Create shared method for TextOutputStream or the Create shared method of the BinaryStream.”

For your understanding : Affichage is the Canvas - Fenetre is the Window containing Affichage


// ----------------------------------------//
// sauvegarde des courbes au format png //
// ----------------------------------------//

Dim f As FolderItem
dim g as graphics
//using the addition and conversion operators…

f = GetSaveFolderItem( “image/png”,"" )

If f.Exists then
//file saved
dim imp as new Picture( Affichage.Width, Affichage.Height, 32)
Affichage.DrawInto imp.Graphics, 0, 0

dim gheight as Integer = g.Width/imp.Width*imp.Height
imp.Save(f,imp.SaveAsPng)

Else
MsgBox(“le fichier n’existe pas”)
End if


The only one example which is “working” is the following

// ----------------------------------------//
// sauvegarde des courbes au format png //
// ----------------------------------------//

Dim f As FolderItem
dim g as graphics
dim pagesetup as new PrinterSetup

g = openPrinterDialog(pageSetup,Fenetre) // Fenetre is the name of the window containing the Canvas “Affichage”

if g<>nil then
dim imp as new Picture( Affichage.Width, Affichage.Height, 32)
Affichage.DrawInto imp.Graphics, 0, 0
dim gheight as Integer = g.Width/imp.Width*imp.Height

g.DrawPicture imp, 0, 0, g.Width, gheight, 0, 0, imp.Width, imp.Height

end if

I get the relevant popup menu for printing, and I can choose “Print as Pdf” and open the PDF in a PDF viewer. From ther, I can export in whatever format. User friendly, isn’ it ?

Do you get a solution ?

Thanks

P.S : I posted this topic 3 hours ago in the French forum. Sorry for any English mistakes.

I think you’re misunderstanding how to use FolderItem and the Exists property.

The way your code reads it will only overwrite the file if it exists already. With SaveDialog (and the shortcut method you’re using) the dialog will handle asking the user to replace, so as long as the FolderItem returned is not nil, you can assume you are allowed to write to that location per the user.

An example of this working as such:

dim fSave as FolderItem = GetSaveFolderItem( "image/png","" )

// If fSave is nil, then the user hit "Cancel"
if fSave = nil then return

if fSave.Exists = true then
  fSave.Delete

  if fSave.LastErrorCode <> 0 then
    // A delete error occurred, handle it.

  end
end

//
// All your picture generation code goes here
//

oPicture.Save(fSave, Picture.SaveAsJPEG)

Thanks for your answser, but I surely didn’t understand everiything, as it still fails with a NilObjectException.

Just to be complet, this code is triggered by an OKbutton.Action event

dim fSave as FolderItem = GetSaveFolderItem( “image/png”,"" )
dim g as graphics

// If fSave is nil, then the user hit “Cancel”
if fSave = nil then return

if fSave.Exists = true then
fSave.Delete

if fSave.LastErrorCode <> 0 then
// A delete error occurred, handle it.
Msgbox(“erreur fichier”)
Quit

end
end

dim imp as new Picture( Affichage.Width, Affichage.Height, 32)
Affichage.DrawInto imp.Graphics, 0, 0

dim gheight as Integer = g.Width/imp.Width*imp.Height
imp.Save(fsave,imp.SaveAsPng)

I tried this :

dim fSave as FolderItem = GetSaveFolderItem( “image/png”,"" )
dim g as graphics

// If fSave is nil, then the user hit “Cancel”
if fSave = nil then return

if fSave.Exists = true then

dim imp as new Picture( Affichage.Width, Affichage.Height, 32)
Affichage.DrawInto imp.Graphics, 0, 0

dim gheight as Integer = g.Width/imp.Width*imp.Height
imp.Save(fsave,imp.SaveAsPng)

'fSave.Delete

if fSave.LastErrorCode <> 0 then
// A delete error occurred, handle it.
Msgbox(“erreur fichier”)
Quit

end
end

Neither error or saved file

You changed the wrong things with my example. It seems like you are still misunderstanding the purpose of GetSaveFolderItem, which I tried to explain simply. It may be the language barrier, so someone who knows French may be of more assistance. ( @Michel Bujardet care to comment?)

The only thing to do if the file exists already is delete it.
The rest of the method assumes the write is allowed (which we can as explained in my first post).

Insert your drawing code here:

//
// All your picture generation code goes here
//

Error handling here:

// A delete error occurred, handle it.

The rest of the example may be left alone.

Well, except make sure the format lines up with the filter in the GetSaveFolderDialog.
#ForumCode

[quote=369169:@Patrice PELLE]Thanks for your answser, but I surely didn’t understand everiything, as it still fails with a NilObjectException.

Just to be complet, this code is triggered by an OKbutton.Action event

dim fSave as FolderItem = GetSaveFolderItem( “image/png”,"" )
dim g as graphics

// If fSave is nil, then the user hit “Cancel”
if fSave = nil then return

if fSave.Exists = true then
fSave.Delete

if fSave.LastErrorCode <> 0 then
// A delete error occurred, handle it.
Msgbox(“erreur fichier”)
Quit

end
end

dim imp as new Picture( Affichage.Width, Affichage.Height, 32)
Affichage.DrawInto imp.Graphics, 0, 0

dim gheight as Integer = g.Width/imp.Width*imp.Height
imp.Save(fsave,imp.SaveAsPng)
[/quote]
On the code above, delete this

if fSave.Exists = true then
    fSave.Delete
    if fSave.LastErrorCode <> 0 then
        // A delete error occurred, handle it.
        Msgbox("erreur fichier")
        Quit
    end
end

This code is not necessary. If a user selects an existing file, the file will be overwritten.

[quote=369169:@Patrice PELLE]
I tried this :

dim fSave as FolderItem = GetSaveFolderItem( “image/png”,"" )
dim g as graphics

// If fSave is nil, then the user hit “Cancel”
if fSave = nil then return

if fSave.Exists = true then

dim imp as new Picture( Affichage.Width, Affichage.Height, 32)
Affichage.DrawInto imp.Graphics, 0, 0

dim gheight as Integer = g.Width/imp.Width*imp.Height
imp.Save(fsave,imp.SaveAsPng)

'fSave.Delete

if fSave.LastErrorCode <> 0 then
// A delete error occurred, handle it.
Msgbox(“erreur fichier”)
Quit

end
end

Neither error or saved file[/quote]
Same with this code, delete line if fSave.Exists = true then and one of End on the code above.

If a file exists it will not always be overwritten depending on which methods you are using.
It’s safer to delete the file if it exists before trying to write.

Also, interesting how you offered nothing to help the OP.
It seems like you only posted to correct someone in a non-vital way.

Real nice. Appreciate that a whole lot. Thanks.

[quote=369180:@Tim Parnell]Also, interesting how you offered nothing to help the OP.
It seems like you only posted to correct someone in a non-vital way.

Real nice. Appreciate that a whole lot. Thanks.[/quote]
Sorry? Do you see these lines of code?

if fSave.Exists = true then
.
.
.
end

I was pointing out why his code didn’t work.

[quote=369169:@Patrice PELLE]
Neither error or saved file[/quote]
So?

Peut-etre…

[code]dim fSave as FolderItem = GetSaveFolderItem( “image/png”,"" )
dim g as graphics

// If fSave is nil, then the user hit “Cancel”
if fSave = nil then

else
//fsave is not nil

try
dim imp as new Picture( Affichage.Width, Affichage.Height, 32)
Affichage.DrawInto imp.Graphics, 0, 0
imp.Save(fsave, picture.SaveAsPng)
catch
Msgbox(“erreur fichier”)
end try

end if
[/code]

Thanks to all of you.

In fact, the bug wasn’t where I though. Before I posted to this forum, I tried to debug my code which was a bit different :

instead of

"if f.exists = true then… "

i wrote “if f<> nil then…”

As I mentionned, I got a NilObjectException error. Looking in the debugger, I found that f didn’t exist. More than a bit confused by the reference language explanation, I was convinced that the error came from the folderitem handling.

As your solutions still failed, I looked deeper and discovered that this NilObjectException error referred to the graphics “g” I created and didn’t really use (a quick copy of a code I found in this forum).

This code is working as I wanted

[i]dim fSave as FolderItem = GetSaveFolderItem( “image/png”,"" )

dim imp as new Picture( Affichage.Width, Affichage.Height, 32)

// If fSave is nil, then the user hit “Cancel”
if fSave = nil then return

if fSave.Exists = true then
fSave.Delete

if fSave.LastErrorCode <> 0 then
// A delete error occurred, handle it.
MsgBox(“Fichier inexistant”)
Quit

end
end

Affichage.DrawInto imp.Graphics, 0, 0

imp.Save(fsave,imp.SaveAsPng)[/i]

Thanks for your kindness and sory , I should have found this bug before posting :frowning:

Be sure to check both at the same time:

if f <> nil then
if f.exists then

[quote=369438:@Detlef Kahner]if f <> nil then
if f.exists then[/quote]

You can even put thos in a 1-liner

If f<>Nil And f.Exist Then

Because if f<>Nil fails, the execution stops there.