Android Question [B4X] Best way to put Text on Bitmap/Imageview?

fredo

Well-Known Member
Licensed User
In this use case, graphics of technical documentation are displayed using an image view.

To ensure multilingualism, the description texts are not contained in the graphic, but should be placed on the screen at runtime, depending on the language setting.

For example, "Lorem ipsum dolor sit amet" should be at position (1) and "Stet clita kasd gubergren" should be at position (2).

The whole thing should be as pixel-accurate as possible to the graphics, independent of the display characteristics of the end devices.

2019-10-20_15-19-52.jpg





Since there is no experience with bitmaps, canvas or the like, a tip for the most sensible approach would be helpful.



Note: Labels created at runtime were tested, but appeared on different devices (5" and 10") at wrong positions.

B4X:
private Sub C0FillContentPage_Doc001[/INDENT]
    c0tab4ImageView1.Gravity = Gravity.TOP
    c0tab4ImageView1.Bitmap = LoadBitmapResize(File.DirAssets, "raptorengine01.png", c0tab4ImageView1.Width, c0tab4ImageView1.Height, True)
    Dim ImageViewWidthRaw As Int = 300dip
    Dim ScaleFactor As Float = (c0tab4ImageView1.Width / ImageViewWidthRaw )
    For Each v As View In c0tab4BackPanel.GetAllViewsRecursive
        If v Is Label Then
            Dim labelX As Label = v
            If labelX.Tag & "!" <> "!" Then
                Dim tc As TextAtCoord = Starter.md.HandImageTexts.Get("k" & labelX.Tag)
                If tc <> Null Then
                    labelX.Text = tc.Text
                    labelX.Left = c0tab4ImageView1.Left + tc.X  * ScaleFactor
                    labelX.Top  = c0tab4ImageView1.Top  + tc.Y  * ScaleFactor
                    labelX.TextSize = 12
                    labelX.Tag = tc
                End If
            End If
        End If
    Next
End Sub
 
Last edited:

emexes

Expert
Licensed User
If you have the pixel (x, y) locations of where you would like the text to appear, and these presumably are in pixels of the original image raptorengine01.png, then
you could convert them to "fraction of image size" locations, and use these to position the text in the same proportional location of the ImageView on the screen (which presumably has .Width and .Height properties that are the screen-pixel size of raptorengine01.png after it has been scaled to fit the ImageView).

edit: Yikes, that was hard to explain in writing. Key word is "proportional".

It might be useful to have a gravity attribute for each text location, to indicate if the text should be placed to the left or right or above or below or centered on the (x, y) location.

Also, you might need to nudge the Label so that it is fully within the image ie not bits missing off the edge. Something like:
B4X:
Dim ImageLeft As Int = ImageView.Left
Dim ImageRight As Int = ImageView.Left + ImageView.Width
Dim ImageTop As Int = ImageView.Top
Dim ImageBottom As Int = ImageView.Top + ImageView.Height

If Label.Left < ImageLeft Then Label.Left = ImageLeft    'if label is outside left edge of image, then move it back to left edge
If Label.Left + Label.Width > ImageRight Then Label.Left = ImageRight - Label.Width    'if label is outside right edge of image, then move it back to right edge
If Label.Top < ImageTop Then Label.Top = ImageTop
If Label.Top + Label.Height > Image.Bottom Then Label.Top = ImageTop - Label.Height
 
Upvote 0

fredo

Well-Known Member
Licensed User
...you could convert them to "fraction of image size" locations...
That worked fine. Thank you for the inspiration!

The solution via the website is still a bit cumbersome, but it works for the present case.

Maybe I will create a small B4J tool to generate a code fragment from clicked x,y points.


B4X:
Type TextAtCoord(Name As String, Text As String, X As Float, Y As Float, W As Float, H As Float)

' ...

    DocImageTexts.Initialize
    For Each k As String In DocRapEngMap.Keys

        Dim TextPart() As String = Regex.Split("~", LookupADefault(sqlActiveDb, $"SELECT dval1||'~'||dval2 FROM motordoc WHERE poskey='${k}'"$, "0~nil"))
        Dim tc As TextAtCoord
        tc.Initialize
        tc.Name = k
        tc.Text = Starter.loc.Localize(TextPart(1))

        ' --> https://www.mobilefish.com/services/record_mouse_coordinates/record_mouse_coordinates.php
        Dim PixRefValue As Int = 610 ' x,y values for Image 610x610pix
        Select Case TextPart(0).Replace(".0", "")
            Case 0
                DocImageTexts.Put("k0",  tc)
            Case 1
                tc.X = 10 /PixRefValue
                tc.Y = 153 /PixRefValue
                tc.W = 160 /PixRefValue
                tc.H = 68 /PixRefValue
                DocImageTexts.Put("k1",  tc)
            Case 2
                tc.X = 414 /PixRefValue
                tc.Y = 110 /PixRefValue
                tc.W = 200 /PixRefValue
                tc.H = 36 /PixRefValue
                DocImageTexts.Put("k2",  tc)
            Case 3
                tc.X = 333 /PixRefValue
                tc.Y = 51 /PixRefValue
                tc.W = 277 /PixRefValue
                tc.H = 36 /PixRefValue
                DocImageTexts.Put("k3",  tc)
            Case 4
                tc.X = 218 /PixRefValue
                tc.Y = 7   /PixRefValue
                tc.W = 390 /PixRefValue
                tc.H = 36 /PixRefValue
                DocImageTexts.Put("k4",  tc)
            Case 5
                tc.X = 477 /PixRefValue
                tc.Y = 196 /PixRefValue
                tc.W = 135 /PixRefValue
                tc.H = 112 /PixRefValue
                DocImageTexts.Put("k5",  tc)
            Case 6
                tc.X = 418 /PixRefValue
                tc.Y = 426 /PixRefValue
                tc.W = 194 /PixRefValue
                tc.H = 68 /PixRefValue
                DocImageTexts.Put("k6",  tc)
        End Select
    Next

'...

    For Each v As View In c0tab4BackPanel.GetAllViewsRecursive
        If v Is Label Then
            Dim labelX As Label = v
            If labelX.Tag & "!" <> "!" Then
                Dim tc As TextAtCoord = Starter.md.DocImageTexts.Get("k" & labelX.Tag)
                If tc <> Null Then
                    labelX.Text = tc.Text
                    labelX.Left = c0tab4ImageView1.Left + tc.X  * c0tab4ImageView1.Width
                    labelX.Top  = c0tab4ImageView1.Top  + tc.Y  * c0tab4ImageView1.Width
                    labelX.Width = tc.W * c0tab4ImageView1.Width
                    labelX.Height = tc.H * c0tab4ImageView1.Width
                    labelX.TextSize = 12
                    labelX.Tag = tc
                End If
            End If
        End If
    Next

'....
 
Upvote 0
Top