Bitmap Fonts - Speed up Trimming?
BlitzMax Forums/BlitzMax Programming/Bitmap Fonts - Speed up Trimming?
| ||
I'm writing a bitmap font library. It's fully-functional, but it needs a lot of optimization, specifically in the trimming of space off the sides of the character images. How is this typically done? Currently I'm going through every pixel and finding the right- and left-most solid pixels in each image, then drawing the image to the backbuffer, then grabbing the image using the coordinates I found earlier. It works perfectly, but it's incredibly slow--it takes about 2 seconds to trim a font. Any suggestions? |
| ||
If you are getting the font from a truetype and you are drawing the characters into images to create the bitmap font, which it kinda sounds like you are, then you can use the following blitzmax function to get the pixel width of the character. Just feed it one character at a time: Function TextWidth( text$ ) Returns the width, in pixels, of text based on the current image font. Description Get width of text Information This command is useful for calculating horizontal alignment of text when using the DrawText command. Its found in the Max2d module. |
| ||
Unfortunately I'm not--I'm using the bitmap fonts found here. Basically my problem was trimming off the empty space on the sides of each character efficiently--however I've found a different method and I've managed to cut the trimming time down to about 20 ms, and I've cut the loading time down to about 15 ms. Anyways here's the finished library if anybody wants it: '*********************************************************************************************************************************** ' B I T M A P F O N T L I B R A R Y '*********************************************************************************************************************************** Rem This library will allow you To draw bitmap fonts obtained from bitmap font image. How To use it: -First, Load a font like so: Local Font:TBitmapFont = TBitmapFont.Load(FileName) where FileName is the filename of a bitmap font image. -Then draw text with the Draw() method: Font.Draw("Hello, world!", 100, 100) You can change the scale and rotation of the font as well, using SetScale() and SetAngle(). You can also change the spacing of the font using SetSpacing(). You may need to set the spacing to a negative value in order to obtain the appearance you desire. You can also change the handle of the font with SetHandle(). The handle of the font is the center at which the font is rotated and scaled. Additionally you can center the font using SetCentered() and setting it to 1, which will automatically set the handle in the center of any text you draw. EndRem ''*********************************************************************************************************************************** Type TBitmapFont Field Image:TImage Field Offset:Int[190] Field Spacing:Float Field CellWidth:Int Field CellHeight:Int Field HandleX:Float Field HandleY:Float Field Angle:Float Field ScaleX:Float Field ScaleY:Float Field Centered:Int Method GetWidth:Int(Text:String) Local CurIndex:Int Local CurWidth:Int For Local I:Int = 1 To Len(Text) CurIndex = Asc(Mid(Text, I, 1)) - 32 CurWidth :+ (Offset[CurIndex * 2 + 1] - Offset[CurIndex * 2]) + Spacing Next Return CurWidth EndMethod Method GetHeight:Int() Return ImageHeight(Image) EndMethod Method SetSpacing(Space:Float) Spacing = Space EndMethod Method GetSpacing:Int() Return Spacing EndMethod Method SetHandle(X:Float, Y:Float) HandleX = X HandleY = Y EndMethod Method GetHandle(X:Float Var, Y:Float Var) X = HandleX Y = HandleY EndMethod Method SetCentered(IsCentered:Int) Centered = IsCentered EndMethod Method SetAngle(Ang:Float) Angle = Ang EndMethod Method GetAngle:Float() Return Angle EndMethod Method SetScale(X:Float, Y:Float) ScaleX = X ScaleY = Y EndMethod Method GetScale(X:Float Var, Y:Float Var) X = ScaleX Y = ScaleY EndMethod Method Draw(Text:String, X:Int, Y:Int) SetTransform(Angle, ScaleX, ScaleY) Local CurIndex:Int Local OrigX:Int = X Local OldHX:Float Local OldHY:Float If Centered OldHX = HandleX OldHY = HandleY HandleX = GetWidth(Text) / 2 HandleY = GetHeight() / 2 EndIf For Local I:Int = 1 To Len(Text) CurIndex = Asc(Mid(Text, I, 1)) - 32 SetImageHandle(Image, -((X - Offset[CurIndex * 2]) - (OrigX + HandleX)), HandleY) DrawImage(Image, OrigX, Y, CurIndex) X :+ Offset[CurIndex * 2 + 1] - Offset[CurIndex * 2] X :+ Spacing Next HandleX = OldHX HandleY = OldHY EndMethod Method Trim() Local Pixmap:TPixmap For Local I:Int = 0 To 94 Pixmap = LockImage(Image, I) Pixmap = Pixmap.Convert(PF_RGBA8888) Local LeftMax:Int = CellHeight - 1 Local RightMax:Int = 0 For Local Y:Int = 0 To CellHeight - 1 For Local X:Int = 0 To CellWidth - 1 Local Color:Int = Pixmap.ReadPixel(X, Y) If Color Shr 24 & $000000FF > 128 If X < LeftMax LeftMax = X EndIf Exit EndIf Next Next For Local Y:Int = 0 To CellHeight - 1 For Local X:Int = CellWidth - 1 To 0 Step -1 Local Color:Int = Pixmap.ReadPixel(X, Y) If Color Shr 24 & $000000FF > 128 If X > RightMax RightMax = X EndIf Exit EndIf Next Next If RightMax = 0 RightMax = CellWidth - CellWidth / 3 EndIf If LeftMax = CellWidth - 1 LeftMax = CellWidth / 3 EndIf LeftMax = LeftMax - Spacing / 2 RightMax = RightMax + Spacing / 2 If RightMax > CellWidth - 1 RightMax = CellWidth - 1 EndIf If LeftMax < 0 LeftMax = 0 EndIf Offset[I * 2] = LeftMax Offset[I * 2 + 1] = RightMax UnlockImage(Image, I) Next EndMethod Function Load:TBitmapFont(FileName:String) Local Font:TBitmapFont = New TBitmapFont Local FontImage:TImage = LoadImage(LoadBank(FileName)) Local CellWidth:Int = ImageWidth(FontImage) / 10 Local CellHeight:Int = ImageHeight(FontImage) / 10 FontImage = LoadAnimImage(LoadBank(FileName), CellWidth, CellHeight, 0, 95) If Not FontImage Notify("The bitmap font image you specified does not exist, or is not of a supported file format.", True) End EndIf Font.Image = FontImage Font.CellWidth = CellWidth Font.CellHeight = CellHeight Font.ScaleX = 1.0 Font.ScaleY = 1.0 Font.Trim() Return Font EndFunction EndType How To use it: -First, Load a font like so: Local Font:TBitmapFont = TBitmapFont.Load(FileName) where FileName is the filename of a bitmap font image. -Then draw text with the Draw() method: Font.Draw("Hello, world!", 100, 100) You can change the scale and rotation of the font as well, using Font.SetScale() and Font.SetAngle(). You can also change the spacing of the font using Font.SetSpacing(). You may need to set the spacing to a negative value in order to obtain the appearance you desire. You can also change the handle of the font with Font.SetHandle(). The handle of the font is the center at which the font is rotated and scaled. Additionally you can center the font using Font.SetCentered() and setting it to 1, which will automatically set the handle in the center of any text you draw. Here's a little example that demonstrates loading, centering, scaling, rotating, and drawing a font: SuperStrict Include "TBitmapFont.bmx" Graphics 1024, 768, 1 SetBlend(ALPHABLEND) SetClsColor(0, 50, 200) Local Font:TBitmapFont = TBitmapFont.Load("OrangeWithShadow.png") Font.SetSpacing(-4) Font.SetCentered(1) Local Counter:Float Local ScaleX:Float Local ScaleY:Float Local Ang:Float Repeat Cls Font.SetAngle(0.0) Font.SetScale(1.0, 1.0) Font.Draw("Bitmap Font Library - Demo", GraphicsWidth() / 2, 20) Counter :+ 1.0 ScaleX = Sin(Counter) * 3.0 Font.SetScale(ScaleX, 3.0) Font.Draw("Hello, world!", MouseX(), MouseY()) ScaleY = Sin(Counter) * 3.0 Font.SetScale(3.0, ScaleY) Font.Draw("Hello, world!", MouseX(), MouseY() - 90) Ang = Sin(Counter) * 30.0 Font.SetScale(2.0, 2.0) Font.SetAngle(Ang) Font.Draw("Hello, world!", MouseX(), MouseY() + 90) Flip Until AppTerminate() Or KeyHit(KEY_ESCAPE) Note: You'll need the 'Orange' font found here to run the demo. |
| ||
Are those bitmap fonts free to use? he mentions the games are free but i didn't see anything about the fonts |
| ||
Yes, as he says here and here. :) |
| ||
you know you are not using this correctly:Pixmap.Convert(PF_RGBA8888) that is not going to convert the original pixmap "automatically". |
| ||
Fontext can be used to make fonts for this code. |
| ||
? |
| ||
Jesse - what is it that you don't understand? |
| ||
this: Fontext can be used to make fonts for this code. I didn't know where you were comming from. I got it now. I just realized that you were the creator of Fontext.:) http://www.blitzbasic.com/Community/posts.php?topic=65909 |
| ||
Jesse: Ahh, I see--is it just a matter of using the Pixmap returned by Convert() or is the their extra work involved? Beaker: Good to know. :) |
| ||
it needs to be like this pixmap = Pixmap.Convert(PF_RGBA8888) |
| ||
Thank you, I've edited it. |