B4J Code Snippet Create PNG File for Map Markers

I needed a method to create .png files "on the fly" - to be used as custom map markers in my AB Material app.
Normally, this data is exposed when hovering over the current map marker - but I wanted to show this info for every marker shown, as an additional marker along side...

Borrowing from many examples found on this forum, I managed this.

These files are just temporary in the app, and are periodically cleaned out (deleted).

The B4XMainPage Class file...
B4X:
Sub Class_Globals
    Private mCanvas As Canvas
    Private fx As JFX
    Type TextMetric (Width As Double,Height As Double)
  
End Sub

Public Sub Initialize

End Sub

'This event will be called once, before the page becomes visible.
Private Sub B4XPage_Created (Root1 As B4XView)
  
    File.MakeDir(File.DirApp,"tmplbl")
  
    Dim rand As Int = Rnd(1,5000)
    Dim t As String = " Spd: "&rand&"  Time: "&DateTime.Time(DateTime.Now)&" Truck #: ( "&(rand+376)&" )"
    Dim ret As String = Makelabel(t,rand) 
  
    Log(" File created: "&ret)

    ExitApplication2(0)
  
End Sub


Sub Makelabel(t As String, rand As Int) As String
  
    mCanvas.Initialize("")
    Dim fs As Double = 16
  
    Dim TM As TextMetric = MeasureText(t,fx.DefaultFont( fs))

    Log(" Height: "&TM.Height & "   Width: " & TM.Width)

    Dim width, height As Double
    width = TM.Width + 6
    height = TM.Height + 1
  
    mCanvas.SetSize(width,height)
    mCanvas.DrawRect( 0  , 0,  width, height,  fx.Colors.White,  True,  1) 'check size
    mCanvas.DrawText2(t,   1, 16 ,fx.DefaultFont(fs),fx.Colors.Black,"LEFT",TM.Width)
  
  
    Dim fn As String = rand&"_"&DateTime.Now
    Dim Dir As String
    Dir = File.DirApp&"\tmplbl"
    Dim Out As OutputStream
    Out = File.OpenOutput(Dir, fn&".png", False)
  
    mCanvas.Snapshot.WriteToStream(Out)
    Out.Close
    Return fn&".png"
  
End Sub


Sub MeasureText(Text As String,TFont As Font) As TextMetric
    Dim TB,Bounds As JavaObject
    Dim TM As TextMetric

    TB.InitializeStatic("javafx.scene.text.TextBuilder")
    Bounds = TB.RunMethodJO("create",Null).RunMethodJO("text",Array(Text)).RunMethodJO("font",Array(TFont)).RunMethodJO("build",Null).RunMethodJO("getLayoutBounds",Null)

    TM.Width = Bounds.RunMethod("getWidth",Null)
    TM.Height = Bounds.RunMethod("getHeight",Null)
    Return TM
End Sub


New Project attached: mkpng.zip
 

Attachments

  • MakePNGLabel.zip
    6.4 KB · Views: 361
  • mkpng.zip
    1.5 KB · Views: 332
Last edited:

Harris

Expert
Licensed User
Longtime User
Included in the first post is the actual "Make PNG" project that I use in my ABM app.

It is simple to use, just create a map with the "key" as the file name (png) and the "value" as the text to display on the image, and pass the map file name as a parameter to the jar called with shell.

Another complex "map of maps" is used to display these markers from within the ABM app - (showlbl_clicked method).

Runs very quickly and produces my desired results...

The overall code is very simplistic. It was the many hours of experimenting / refactoring to make it work that was difficult.
However, B4X makes it so much easier than all the other alternatives...

B4X:
         Dim mapname As String = rand&"_map.map"
    
        File.WriteMap( File.DirApp&"/www/"&ABMShared.AppName&"/images/tmplbl",  mapname,  mamap )
    
        Dim shl As Shell
        shl.Initialize("shl", "java.exe",     Array As String("-cp", "mkpng.jar", "b4j.example.main", mapname))
        shl.WorkingDirectory = File.DirApp
        shl.Run(10000) 'set a timeout of 10 seconds
        
        Wait For shl_ProcessCompleted (Success As Boolean, ExitCode As Int, StdOut As String, StdErr As String)
        If Success And ExitCode = 0 Then
            Log("Success creating png's ")
        Else
            Log("Error: " & StdErr)
        End If

        showlbl_clicked("")  ' show images on the Google Map...

Show / Hide these image markers...
B4X:
Sub showlbl_clicked(target As String)

    Dim sloc1 As ABMSwitch = page.NavigationBar.ExtraContent.Component("showlbl")
    Dim b As Boolean = sloc1.State

    If b Then
    
        For Each key As String In markmap.Keys
            Dim kval As Map = markmap.Get(key)
            Dim fname As String = kval.Get("fname")
            Dim latt As Double = kval.Get("lt")
            Dim lont As Double = kval.Get("ln")
            Dim path As String
            ' info label...
            If File.Exists(File.DirApp&"/www/"&ABMShared.AppName&"/images/tmplbl", fname) Then
                path = "../images/tmplbl/"&fname
                gm1.AddMarkerEx( fname ,   latt,  lont+0.0007, " " ,  " ", path,  False )
            Else
                Log(" Marker File not found: "&kval)
            End If
        Next
    
    Else
    ' hide extra markers
        For Each key As String In markmap.Keys
            gm1.RemoveMarker(key)
        Next
    
    End If
End Sub

Result: (speed and time for each primary marker)

gmap.PNG
 
Last edited:
Top