Getting frame dimensions from Image

Monkey Forums/Monkey Programming/Getting frame dimensions from Image

Nobuyuki(Posted 2012) [#1]
is there any way to get the internal, individual frameWidth and frameHeight values from an Image object after it's been created? I'm writing something to parse in and display complex strings on screen, and the font being displayed is not guaranteed at runtime.

At first, I thought I could avoid requiring extra arguments to specify the character size of the font using GetFont(), but that would require Image objects have public members that specify the frame size. I don't see this in the documentation! Short of requiring those extra arguments, or storing the frame sizes for my fonts in keypairs associated with the Image, what would be a good way to approach this?

I guess the problem stems from assuming that user fontmaps will always be loaded in strip form, and that .Height can reasonably be assumed to be the character height. This isn't true in my case. I guess they could be derived from frame numbers and the dimensions, though...

Anyway, please consider this a request to expose more members of Image :)


Gil(Posted 2012) [#2]
So...

[monkeycode]w = Image.Width()
h = Image.Height()[/monkeycode]


...doesn't return what you need?


Gil(Posted 2012) [#3]
In looking over graphics.monkey, I see that the Frame class only has two fields - x and y. The frame size is derived from the Image width and height that contains it, so they are the same thing, thus Image.Width() should return the frame width and the same for the height.

Hope that helps, or maybe I don't quite understand your question. :)


Jesse(Posted 2012) [#4]
SetFont Description:


Sets the font for use with DrawText.

The font parameter may be Null, in which case an internal 7x11 white-on-black font is used and the firstChar parameter is ignored.

Note: The font functionality in mojo is very limited and intended mainly for debugging purposes



it uses mono space mono size fonts. so all of the images are equal size. made from a strip of images.

so if you want to do parsing and formatting of variable width/height fonts, you are going to have to use one of the custom modules already created such as Angel font, Font Machine, or your own custom made module.


Nobuyuki(Posted 2012) [#5]
Gil: The frame size is definitely not the image's width and height. In the larger overload for LoadImage, you actually must specify frameWidth and frameHeight in addition to frameCount. I haven't looked at graphics.monkey to see if it retains these values or not, but it would seem to make sense for Image to do so rather than derive the frame size each time it needs to get it for displaying a slice.

Jesse: I'm writing my own function based on DrawText. DrawText is a built-in draw routine, which is why I'm using it. I'm not using AngelFont or FontMachine in this project because they can incur large overheads and complicate my codebase. I've already written a monospace character map with ligatures for thin characters, so there's no point to switching to a variable-width font now. I merely want the frame size to properly adjust paragraph line tracking in my display routine without requiring an argument specifying the font's character height.


Jesse(Posted 2012) [#6]
yes but DrawText is based on the SetFont function and therefore uses the same rules. if you are extending it you are going to have to modify the load font function

this is the loadFon:
[monkeycode]
Function SetFont( font:Image,firstChar=32 )
If Not font
If Not context.defaultFont
context.defaultFont=LoadImage( "mojo_font.png",96,Image.XPadding )
Endif
font=context.defaultFont
firstChar=32
Endif
context.font=font
context.firstChar=firstChar
End
[/monkeycode]
and the DrawText:
[monkeycode]
Function DrawText( text$,x#,y#,xalign#=0,yalign#=0 )
#If CONFIG="debug"
DebugRenderDevice
#End
If Not context.font Return

Local w=context.font.Width
Local h=context.font.Height

x-=Floor( w * text.Length * xalign )
y-=Floor( h * yalign )

For Local i=0 Until text.Length
Local ch=text[i]-context.firstChar
If ch>=0 And ch<context.font.Frames
DrawImage context.font,x+i*w,y,ch
Endif
Next

End
[/monkeycode]

as you can see the frame width is the context font width and is the same for all of the characters in the text.

it gets the width from the stored standard character width and uses if for every character in the string. it doesn't do variable text width or text height. and furthermore frame size is the image width and image height of the characters in the font. as stated by Gil

and is why in the quote above on post #4 it says:

Note: The font functionality in mojo is very limited and intended mainly for debugging purposes




Gil(Posted 2012) [#7]
Nobuyuki: Actually the frame size IS the image width and height. :)

If you are using the simple version of LoadImage(), which assumes a horizontal strip of length frameCount, in which case the frame height is the same as the image height and the frame width is expected to be the image width / frameCount. The Load() method sets the Images width and height to reflect this.

The extended version of LoadImage() allows you to specify the width and height and number of frames in the case that you are NOT using a horizontal strip but rather an image atlas, in which case it needs to know the exact measurements of the frames beforehand so it can correctly extract each frame from the total image area.

In either case, the Image field vars width and height will reflect the frame size of the images contained within the larger Image.
Don't take my word for it...take a look at graphics.monkey. :)

Cheers!


Nobuyuki(Posted 2012) [#8]
Gil: Thanks. I wouldn't have expected it, but I looked at graphics.monkey, and you're right. Based on the documentation, I would've expected Width and Height to return the total texture size!

Anyway, my code isn't very complex yet, it's just an easy way to display a paragraph using string literals, but I'm going to be adding in some String.Replace stuff to replace characters with ligatures, which will do for my purposes. Just in case it's useful to anyone who (understandably) isn't using AngelFont/Fontmachine:

[monkeycode]
Method DrawParagraph:Void(input:String, x:Float, y:Float, xAlign:Float=0, yAlign:Float=0)
Local piece:String[] = input.Split("~n")

For Local i:Int = 0 Until piece.Length
DrawText(piece[i], x, y + (i*GetFont().Height), xAlign, yAlign)
Next
End Method
[/monkeycode]

no tracking is required, nor is it provided in this example since it's baked into my font, but it could easily be added, and I suppose the call to GetFont() removed in the process, if made a mandatory argument.


Gil(Posted 2012) [#9]
You're welcome. I've found that reading through the code is the BEST documentation. :)


Jesse(Posted 2012) [#10]
Yea, thanks for ignoring me too. ;)


Nobuyuki(Posted 2012) [#11]
Jesse: I didn't end up having to directly modify any built-in mojo routines in order to achieve what I was looking to do. Gil was very helpful. Thanks for trying, but it wasn't what I was looking for.

(P.S. order of ligaturization matters!)



Jesse(Posted 2012) [#12]
sorry, I guess I wasn't helpful even if I was pointing out the same thing Gil was.
Just ignore. I guess my explanation was lost in the translation. ;)


Nobuyuki(Posted 2012) [#13]
Don't worry about it. I think my explanation in the original post could've been better.