loading a picture into a canvas and using drawstring

I need to load a graphic into a picture, set some text over it, then set it as an image in a canvas, however, I’m getting a NilObjectException error. The graphic is in my app’s Resources folder (I’ve verified this).

[code]Dim p As Picture
Dim xfi As Xojo.IO.Folderitem
Dim fi As Folderitem
Dim filename as string

fileName = “graphic01.png”

Try
xfi = Xojo.IO.SpecialFolder.GetResource(fileName.ToText)
Catch e As xojo.Core.InvalidArgumentException
Return
End Try

fi = GetFolderItem(xfi.path,Folderitem.PathTypeNative)

If fi <> Nil Then
p = Picture.Open(fi)
p.Graphics.Bold = True
p.Graphics.Italic = False
p.Graphics.TextFont = “Arial”
p.Graphics.TextSize = 20
p.Graphics.ForeColor = &cff0000
p.Graphics.DrawString(TextArea1.text, 10, 10)
Canvas3.Backdrop = p
else

End If
[/code]

I want to save the contents of the canvas as a PNG after this.

Use the TPSF module to get access to the build step folders with the classic framework. You’ll save some headaches here. https://github.com/devtimi/TPSF/

It’s as easy as TPSF.Resources.Child("graphic01.png")

Edit: Oh, I found where you might possibly be getting the NOE. You’re opening the given folder item but assuming it’s creating a picture. If Picture.Open fails for any reason, you won’t have a picture to work with. You need to check that the picture isn’t nil after attempting the open.

Thanks. using TPSF now and it’s loading the graphic, however, any calls to p.graphics are causing it to crash. Using code from the LR there.

A crash or an exception? What is the value of p? Does it have a value in the debugger?

p = Picture.Open(fi)

is getting you an imutable picture.
Create a new pictur of the same size, and copy the loaded one to it.
The copy will have a graphics property

still seems to be choking on the Graphics. I get a NilObjectException if any of the p.Graphics lines are uncommented. seems to be loading the image just fine when it doesn’t crash.

Dim p  As New Picture(500, 60, 32)
Dim fi As Folderitem
Dim filename as string

filename = "graphic01.png"

fi = TPSF.Resources.Child(filename)

p = Picture.Open(fi)

//p.Graphics.Bold = true     //doesn't crash if these are commented out...
//p.Graphics.TextSize = 20
//p.Graphics.ForeColor = &cffffff
//p.Graphics.DrawString("hello there", 10, 10)

me.Backdrop = p

cough…

[quote]p = Picture.Open(fi)

is getting you an imutable picture.
Create a new picture of the same size, and copy the loaded one to it.
The copy will have a graphics property[/quote]

p = Picture.Open(fi) dim p2 as picture p2 = new picture (p.width,p.height,32) p2.graphics.drawpicture p,0,0 p2.Graphics.Bold = true p2.Graphics.TextSize = 20 p2.Graphics.ForeColor = &cffffff p2.Graphics.DrawString("hello there", 10, 10) me.Backdrop = p2

oh sorry. misunderstood. that works perfectly. Thanks!

Another question: I seem to be having trouble centering the string on the picture. I’m using

p2.Graphics.DrawString(caption, (g.width/2 - g.stringwidth(caption)/2), stringHeight)

For g.stringwidth(caption) I’m getting 244 in the debugger, but when I measure the number of pixels that the text takes up in the final image, it looks like 406 and there is 517 pixels to the left of the text and about 355 to the right (image is 1260 pixels wide), so it’s off-center to the right for some reason. I tried monkeying around with the centering but nothing seems to get it right. Apparently g.stringwidth isn’t measured in pixels?

a. compute the centered value in its own line.

b. how do you “measure” the string width (244 vs 406)?

use a variable instead of having g.drawstring compute it?

i set a variable (not used) that I looked at in debugger: stringWidth = g.stringwidth(caption) and it gave me 244.
I measured the number of pixels on the final image by using a selection box in the Preview app.

Assuming one line of text, and ignoring the case where it might be too big for the picture:
take the width of the graphic, subtract the width of the string, and divide that by 2

p2.Graphics.DrawString   caption, (p2.Graphics.width - p2.Graphics.stringwidth(caption)) / 2, stringheight

is g the same graphic as p.graphics?
If no, is one using hdpi and the other not?

that fixed it, but you have an extra period between p2.graphics.stringwidth(caption) though in case anyone looks at this in the future. not sure why i never tried that. i thought i tried every variation. thanks for your quick solution.