Android Question Where to find BitmapCreator Version 4.70 ?

Syd Wright

Active Member
Licensed User
I recently found BitmapCreator version 4.30 (bitmapcreator.bas) here:
https://www.b4x.com/android/forum/threads/xui2d-bitmapcreator-drawing-methods.98148/#content

Where can I maybe find the bas module for version 4.70? I don't (yet) have B4A version 8.8 or higher.

Just to also report that I have compared the speed of version 3.60 (in my B4A version 8.30) with this bas module version 4.30 and observe that the latter performs about 30% slower:
I am making a navigator for Open Street Map (OSM), using many routnes with bitmapcreator. On average I can now load a (vector)map with 40 maptiles in 1 second, whereas in version 4.30 it takes about 1.30 seconds.
I don't have the source code for version 3.60 so can't determine the cause.

PS:
I also tried bas module version 4.50, found here:
https://www.b4x.com/android/forum/threads/b4x-x2-xui2d-box2d-game-engine.95208/page-2 (thread #22)
I assume I need a higher B4A version because it can't find "InternalCanvasDrawTask".
 
Last edited:

Syd Wright

Active Member
Licensed User
Thank you very much. Is this version maybe also available as a separate .bas module (in order to possibly modify the code myself)?
 
Last edited:

Syd Wright

Active Member
Licensed User
Do you maybe also have the sourcode of BitmapCreator v3.60 which appears to perform much faster than v4.70? I would like to find out why.
 
Last edited:

Erel

Administrator
Staff member
Licensed User
1. There is no reason to use the source code of BitmapCreator.
2. The old version shouldn't be faster than the new version. Make sure to test it with the libraries in release mode. If you think that it is indeed the case then please upload a small project that demonstrates it.
 

Syd Wright

Active Member
Licensed User
1. There is no reason to use the source code of BitmapCreator.
2. The old version shouldn't be faster than the new version. Make sure to test it with the libraries in release mode. If you think that it is indeed the case then please upload a small project that demonstrates it.
Okay, thank you for taking the time to look into this issue.

Below is my orginal test project that draws about a dozen of different shapes.
When using the jar and xls of BC v3.60 the total time to draw everything is 220 msec. (see the Log's).
After simply replacing the jar and xls by BC v4.70 (in the AnywhereSoftware libraries folder) the total time is 1010 msec (i.e. 5 times slower!). In my actual OSM renderer project the difference is even larger (more than 6 times). All in Release mode.

NB: The code for some shapes I have made (or adapted) myself, others are from the Forum. I am using a Samsung Tab 8.4 with Android v.6.0.1. Maximum drawing speed is of utter importance because I am making an OSM tiles renderer (which so far is going quite well). The project needs the XUI library. I am using B4A v8.30.

B4X:
#Region  Project Attributes
    #ApplicationLabel: B4A Example
    #VersionCode: 1
    #VersionName:
    'SupportedOrientations possible values: unspecified, landscape or portrait.
    #SupportedOrientations: unspecified
    #CanInstallToExternalStorage: False
#End Region

#Region  Activity Attributes
    #FullScreen: False
    #IncludeTitle: True
#End Region

Sub Process_Globals

End Sub

Sub Globals
    Type PointXY(X As Int, Y As Int)
    Dim PointList1 As List
    Dim BC1 As BitmapCreator
    Dim Button1 As Button
    Dim PolyX1(1000) As Long
    Dim PolyY1(1000) As Long
    Dim PolyX2(1000) As Long
    Dim PolyY2(1000) As Long
    Dim PolyLen1 As Long
    Dim PolyLen2 As Long
    Dim PolyMap1 As Map
End Sub

Sub Activity_Create(FirstTime As Boolean)
    Dim Duur0 As Long
    Dim Duur1 As Long

    Button1.Initialize("Button1")
    Activity.AddView(Button1,10%x,10%y,80%x,80%y)
    PointList1.Initialize
    BC1.Initialize(Button1.Width, Button1.Height)
    PolyMap1.Initialize
 
    Dim BMP1 As B4XBitmap = Null
 
    Duur0= DateTime.now
    Duur1= DateTime.now
    Drawline2(150,10,1000,1000,Colors.RGB(250,0,0),10)
       Log("Line draw time= " & (DateTime.Now-Duur1) & " msec")

    Duur1= DateTime.now
    Drawline2(600,200,500,600,Colors.RGB(0,0,250),20)
       Log("Line draw time= " & (DateTime.Now-Duur1) & " msec")

    Duur1= DateTime.now
    DrawCircleOpen(800,600,500,Colors.RGB(0,250,0),10)
       Log("Circle Open time= " & (DateTime.Now-Duur1) & " msec")
 
    Duur1= DateTime.now
    DrawCircleFull(1280,600,300,Colors.RGB(0,250,250),10)
       Log("Circle full time= " & (DateTime.Now-Duur1) & " msec")
 
    PolyX1(0)=100
    PolyY1(0)=100
    PolyX1(1)=200
    PolyY1(1)=200
    PolyX1(2)=300
    PolyY1(2)=150
    PolyX1(3)=100
    PolyY1(3)=400
    PolyX1(4)=50
    PolyY1(4)=200
    PolyX1(5)=100
    PolyY1(5)=100
    PolyLen1=6
 
    Duur1= DateTime.now
    DrawPolyOpen(Colors.RGB(200,250,150),3)
       Log("Poly Open time= " & (DateTime.Now-Duur1) & " msec")
 
    PolyX1(0)=100
    PolyY1(0)=700
    PolyX1(1)=200
    PolyY1(1)=900
    PolyX1(2)=300
    PolyY1(2)=850
    PolyX1(3)=100
    PolyY1(3)=1100
    PolyX1(4)=50
    PolyY1(4)=900
    PolyX1(5)=100
    PolyY1(5)=700
    PolyLen1=6
 
    Duur1= DateTime.now
    DrawPolyFull(Colors.RGB(100,250,150),1)
       Log("Poly full time= " & (DateTime.Now-Duur1) & " msec")

    PolyX1(0)=40
    PolyY1(0)=50
    PolyX1(1)=80
    PolyY1(1)=53
    PolyX1(2)=82
    PolyY1(2)=98
    PolyX1(3)=36
    PolyY1(3)=95
    PolyX1(4)=40
    PolyY1(4)=50
    PolyLen1=5
 
    Duur1= DateTime.now
    For n=1 To 100
      DrawPolyFull(Colors.RGB(180,180,180),1)
    Next
       Log("100 huisjes time= " & (DateTime.Now-Duur1) & " msec")
 
    PolyX2(0)=700
    PolyY2(0)=0
    PolyX2(1)=800
    PolyY2(1)=200
    PolyX2(2)=1200
    PolyY2(2)=150
    PolyX2(3)=700
    PolyY2(3)=600
    PolyX2(4)=650
    PolyY2(4)=200
    PolyX2(5)=500
    PolyY2(5)=100
    PolyLen2=6

    Duur1= DateTime.now
    DrawRoad1(Colors.RGB(180,60,20),Colors.RGB(250,180,50),18, 10)
       Log("Poly Road1 time= " & (DateTime.Now-Duur1) & " msec")

    Duur1= DateTime.now
    DrawTriangleOpen(330,550,450,800,180,700,Colors.RGB(200,200,20), 10)
       Log("Poly Triangle time= " & (DateTime.Now-Duur1) & " msec")

    Duur1= DateTime.now
    DrawTriangleFull(530,650,650,920,420,990,Colors.RGB(250,250,60), 10)
       Log("Poly Triangle time= " & (DateTime.Now-Duur1) & " msec")
 
    Log("Total time1= " & (DateTime.Now-Duur0) & " msec")

    BMP1= BC1.Bitmap
    Button1.SetBackgroundImage(BMP1)
    Log("Total time2= " & (DateTime.Now-Duur0) & " msec")
End Sub

Sub Activity_Resume

End Sub

Sub Activity_Pause (UserClosed As Boolean)

End Sub

Sub Drawline1(x1 As Int, y1 As Int, x2 As Int, y2 As Int, Color As Int)        'Faster for single lines (Wid=1)
    Dim Dx,Dy,Diff As Int
    Dim x,y As Float
    Dim a As ARGBColor

    BC1.ColorToARGB(Color, a)
    Dx = x2 - x1
    Dy = y2 - y1
    Diff=Max(Abs(Dx),Abs(Dy))
    x = x1
    y = y1
    Dim tx = Dx / Diff, ty = Dy / Diff As Float
    For D=0 To Diff
      If (x>=0 And x<BC1.mWidth) And (y>=0 And y<BC1.mHeight) Then BC1.SetARGB(x,y,a)
      x = x + tx
      y = y + ty
    Next
End Sub

Sub Drawline2(x1 As Int, y1 As Int, x2 As Int, y2 As Int, Color As Int, Wid1 As Int)
    Dim Dx,Dy,Diff As Int
    Dim Rect1 As B4XRect
    Dim x,y As Float
    Dim a As ARGBColor

    BC1.ColorToARGB(Color, a)
    Dx = x2 - x1
    Dy = y2 - y1
    Diff=Max(Abs(Dx),Abs(Dy))
    x = x1
    y = y1
    Dim Tx = Dx / Diff, Ty = Dy / Diff As Float
    For D=0 To Diff
       If (x>=0 And x<BC1.mWidth) And (y>=0 And y<BC1.mHeight) Then
            Rect1.Initialize(x-Wid1/2,y-Wid1/2,x+Wid1/2,y+Wid1/2)
            BC1.FillRect(Color,Rect1)
       End If
       x = x + Tx
       y = y + Ty
    Next
End Sub

Sub DrawCircleOpen(x As Int, y As Int, Radial As Int , Color As Int, Wid1 As Int)
    Dim X1, Y1 As Double
    Dim Rect1 As B4XRect
 
    For i=0 To 720
      X1 = X + Radial * CosD(i/2)
      Y1 = Y + Radial * SinD(i/2)
      Rect1.Initialize(X1-Wid1/2,Y1-Wid1/2,X1+Wid1/2,Y1+Wid1/2)
      BC1.FillRect(Color,Rect1)
    Next
End Sub

Sub DrawCircleFull(X As Int, Y As Int, Radial As Int , Color As Int, Wid1 As Int)
    Dim Rect1 As B4XRect
    Dim X1, Y1, X2, Y2, Hulp1 As Long
    Dim XMin1, XMax1, YMin1, YMax1, Xwid1, Yhig1 As Long

    XMin1=X-Radial
    XMax1=Radial+X
    YMin1=Y-Radial
    YMax1=Radial+Y
 
    Xwid1= XMax1-XMin1
    Yhig1= YMax1-YMin1
 
    Hulp1 =(Yhig1+1) * (Xwid1+1)
    Dim Array1(Hulp1) As Int
 
    For i=1 To 2160 Step 1
      X1 = X + Radial * CosD(i/6)
      Y1 = Y + Radial * SinD(i/6)
      Array1((Y1-YMin1)*Yhig1 + (X1-XMin1)) = 1
    Next

    For Y=0 To Yhig1
      For X=0 To Xwid1
          If Array1(Y*Yhig1+X)=1 Then    
          X1=X + XMin1
          Y1=Y + YMin1
          Exit
        End If
      Next
      For X=Xwid1 To 0 Step -1
          If Array1(Y*Yhig1+X)=1 Then    
          X2= X + XMin1
          Y2= Y + YMin1
             Rect1.Initialize(X1,Y1,X2,Y2+1)    'Faster than using Drawline1(X1,Y,X,Y,Color)
             BC1.FillRect(Color,Rect1)
          Exit
        End If
      Next
    Next
End Sub

Sub DrawRoad1(Color1 As Int, Color2 As Int, Wid1 As Int, Wid2 As Int)
    Dim X1, Y1, X2, Y2 As Long
    X1=PolyX2(0)
    Y1=PolyY2(0)
    If Wid1>0 Then
      For i=1 To PolyLen2-1
        X2=PolyX2(i)
        Y2=PolyY2(i)
        Drawline2(X1,Y1,X2,Y2,Color1,Wid1)
        X1=X2
        Y1=Y2
      Next
    End If
 
    If Wid2>0 Then
      X1=PolyX2(0)
      Y1=PolyY2(0)
      For i=1 To PolyLen2-1
        X2=PolyX2(i)
        Y2=PolyY2(i)
        Drawline2(X1,Y1,X2,Y2,Color2,Wid2)
        X1=X2
        Y1=Y2
      Next
    End If
End Sub

Sub DrawPolyOpen(Color As Int, Wid1 As Int)
    Dim X1, Y1, X2, Y2 As Long
    X1=PolyX1(0)
    Y1=PolyY1(0)
    For i=1 To PolyLen1-1
      X2=PolyX1(i)
      Y2=PolyY1(i)
      'Log("X2=" & X2 & ", Y2=" & Y2)
      Drawline2(X1,Y1,X2,Y2,Color,Wid1)
      X1=X2
      Y1=Y2
    Next
End Sub

Sub DrawPolyFull(Color As Int, Wid1 As Int)
    Dim X0, X1, X2, Y0, Y1, Y2 As Long
    Dim X, Y As Float
    Dim XMin1, XMax1, YMin1, YMax1, Xwid1, Yhig1 As Long
    Dim Hulp1 As Long
    Dim SetPix1 As Int
 
    Dim Rect1 As B4XRect
    Dim Dx,Dy,Diff As Int
 
    XMin1= PolyX1(0)
    XMax1= PolyX1(0)
    YMin1= PolyY1(0)
    YMax1= PolyY1(0)

    For i=0 To PolyLen1-1
      X1=PolyX1(i)
      Y1=PolyY1(i)
      If X1<XMin1 Then XMin1 = X1
      If X1>XMax1 Then XMax1 = X1
      If Y1<YMin1 Then YMin1 = Y1
      If Y1>YMax1 Then YMax1 = Y1
    Next
 
    Xwid1= XMax1-XMin1
    Yhig1= YMax1-YMin1
 
    Hulp1 =(Yhig1+1) * (Xwid1+1)
    Dim Array1(Hulp1) As Int
 
    X1=PolyX1(0)
    Y1=PolyY1(0)
    PolyMap1.Clear
 
    For i=1 To PolyLen1-1
      X2=PolyX1(i)
      Y2=PolyY1(i)
      'Log("X1= " & X1 & ", Y1= " & Y1 & ", X2= " & X2 & ", Y2= " & Y2)
      Dx = X2 - X1
      Dy = Y2 - Y1
      Diff = Max(Abs(Dx),Abs(Dy))
      X = X1
      Y = Y1
      Dim Tx = Dx / Diff, Ty = Dy / Diff As Float
      For D=0 To Diff
          X0=X
        Y0=Y
        Array1((Y0-YMin1)*Xwid1 + (X0-XMin1))=1
        X = X + Tx
        Y = Y + Ty
      Next
   
      X1=X2
      Y1=Y2
    Next

    Y0=YMin1
    Do While Y0<YMax1
      SetPix1=0
      X0=XMin1
      Do While X0<XMax1
        If Array1((Y0-YMin1)*Xwid1 + (X0-XMin1)) = 1 Then
          'Log(SetPix1 & ": " & X0 & ", " & Y0)
            If SetPix1=0 Then
            X1=X0
            SetPix1=1
          Else  
            SetPix1=0
               Rect1.Initialize(X1,Y0,X0,Y0+1)    'Hor.line: faster than with Drawline1(X1,Y,X,Y,Color)
               BC1.FillRect(Color,Rect1)
          End If
          X0=X0+1
        End If
        X0=X0+1
      Loop
      Y0=Y0+1
    Loop
End Sub

Sub DrawTriangleOpen(X1 As Int, Y1 As Int, X2 As Int, Y2 As Int, X3 As Int, Y3 As Int, Color As Int, Wid1 As Int)
    PolyX1(0)=X1
    PolyY1(0)=Y1
    PolyX1(1)=X2
    PolyY1(1)=Y2
    PolyX1(2)=X3
    PolyY1(2)=Y3
    PolyX1(3)=X1
    PolyY1(3)=Y1
    PolyLen1=4
    DrawPolyOpen(Color,Wid1)
End Sub

Sub DrawTriangleFull(X1 As Int, Y1 As Int, X2 As Int, Y2 As Int, X3 As Int, Y3 As Int, Color As Int, Wid1 As Int)
    PolyX1(0)=X1
    PolyY1(0)=Y1
    PolyX1(1)=X2
    PolyY1(1)=Y2
    PolyX1(2)=X3
    PolyY1(2)=Y3
    PolyX1(3)=X1
    PolyY1(3)=Y1
    PolyLen1=4
    DrawPolyFull(Color,Wid1)
End Sub
 
Last edited:

Erel

Administrator
Staff member
Licensed User
This is not the correct way to use BitmapCreator. You should use the built-in drawing methods.
Your drawing methods are very inefficient.
First step is to use the drawing methods that accept a BCBrush, otherwise a new brush is created each call.

You will get better performance and better results with the built-in methods (such as anti-aliasing).

Anyway, the source code of v3.60 is not available online. You might find an old copy in the forum.
 

Syd Wright

Active Member
Licensed User
This is not the correct way to use BitmapCreator. You should use the built-in drawing methods.
Your drawing methods are very inefficient.
First step is to use the drawing methods that accept a BCBrush, otherwise a new brush is created each call.

You will get better performance and better results with the built-in methods (such as anti-aliasing).

Anyway, the source code of v3.60 is not available online. You might find an old copy in the forum.
I have now used BC v4.73 and done what you suggested. On average my test project now completes in 72 msec, so about 3 times faster than my results with v3.60. By further optimization I probably will get even better results.
This is great, thank you very much!
 

Syd Wright

Active Member
Licensed User
In my quest for speed optimization I have noticed that it is not a good idea to pass a BC object to a sub:

B4X:
    Dim BC1 as BitmapCreator  '(under Action_Create)

Duration1= DateTime.now
Drawline2(BC1,150,10,1000,1000,Colors.RGB(250,0,0),10)
Log("Line draw time1= " & (DateTime.Now-Duration1) & " msec")

Sub Drawline2(BC As BitmapCreator, x1 As Int, y1 As Int, x2 As Int, y2 As Int, Color As Int, Wid1 As Int)
    BC.DrawLine(x1,y1,x2,y2,Color,Wid1)
End Sub
This code takes 22 msec. compared to:
B4X:
Duration1= DateTime.now
BC1.DrawLine(150,10,1000,1000,Colors.RGB(250,0,0),10)
Log("Line draw time2= " & (DateTime.Now-Duration1) & " msec")
which only takes 3 msec.!
 
Last edited:

agraham

Expert
Licensed User
The overhead is probably in building the parameter list on the stack then performing the the Sub call instead of doing it in line rather than it being in the nature of what is being passed. That said I am surprised that the overhead is that much! :confused:
 

Erel

Administrator
Staff member
Licensed User
I'm sure that it is not significant and not something that should be considered.

Please upload a small project that demonstrates it.
 

Erel

Administrator
Staff member
Licensed User
BTW, you are still using the inefficient method that creates a new BCBrush each call.
 

Syd Wright

Active Member
Licensed User
I'm sure that it is not significant and not something that should be considered.

Please upload a small project that demonstrates it.
Here is a Test project (with BC v4.70). The results are shown in green:
B4X:
Sub Process_Globals
End Sub

Sub Globals
    Dim BC1 As BitmapCreator
    Dim Duration1 As Long
End Sub

Sub Activity_Create(FirstTime As Boolean)
    BC1.Initialize(2000,2000)
    TEST1
    TEST2
    TEST3
    TEST4
End Sub

'Single line:
Sub TEST1                            'RESULT1 = 20 msec.
    Duration1= DateTime.now
    BC1.DrawLine(150,10,1000,1000,Colors.RGB(250,0,0),10)
    Log("Line draw time1= " & (DateTime.Now-Duration1) & " msec")
End Sub

Sub TEST2                            'RESULT2 = 2 msec.
    Duration1= DateTime.now
    Drawline2(BC1,150,10,1000,1000,Colors.RGB(250,0,0),10)
    Log("Line draw time2= " & (DateTime.Now-Duration1) & " msec")
End Sub

'100 lines:
Sub TEST3                            'RESULT3 = 175 msec.
    Duration1= DateTime.now
    For n=0 To 100
      BC1.DrawLine(150,10,1000,1000,Colors.RGB(250,0,0),10)
    Next
    Log("Line draw time3= " & (DateTime.Now-Duration1) & " msec")
End Sub

Sub TEST4                            'RESULT4 = 150 msec.
    Duration1= DateTime.now
    For n=0 To 100
      Drawline2(BC1,150,10,1000,1000,Colors.RGB(250,0,0),10)
    Next
    Log("Line draw time4= " & (DateTime.Now-Duration1) & " msec")
End Sub

Sub Drawline2(BC As BitmapCreator, x1 As Int, y1 As Int, x2 As Int, y2 As Int, Color As Int, Wid1 As Int)
    BC.DrawLine(x1,y1,x2,y2,Color,Wid1)
End Sub
PS: I have now optimized my OSM map project and, as you suggested, I have only defined brushes once. The results are about 25% faster, so thank you for the advice.
 
Last edited:

Erel

Administrator
Staff member
Licensed User
Measuring the time of a single call is meaningless.

It is enough to run it 10 times to see that the numbers are the same:
B4X:
For i = 1 To 10
   TEST1
   TEST2
   TEST3
   TEST4
Next

Line draw time1= 0 msec
Line draw time2= 1 msec
Line draw time3= 29 msec
Line draw time4= 29 msec
Line draw time1= 1 msec
Line draw time2= 0 msec
Line draw time3= 29 msec
Line draw time4= 30 msec
Line draw time1= 0 msec
Line draw time2= 0 msec
Line draw time3= 30 msec
Line draw time4= 29 msec
Line draw time1= 0 msec
Line draw time2= 1 msec
Line draw time3= 29 msec
Line draw time4= 29 msec
Line draw time1= 0 msec
Line draw time2= 0 msec
Line draw time3= 30 msec
Line draw time4= 30 msec


Worth watching the performance video tutorial. This is a good case of preoptimization that doesn't change anything.

https://www.b4x.com/etp.html?vimeography_gallery=1&vimeography_video=256924581
 

Syd Wright

Active Member
Licensed User
Thank you very much. I watched your useful video.

These are my results after running the tests 10 times, like you did.
Did you change anything in the code of my test project?
My results (in TEST3 and TEST4) are about 7 times slower! Any suggestions please how to improve performance?

Line draw time1= 22 msec
Line draw time2= 2 msec
Line draw time3= 213 msec
Line draw time4= 195 msec
Line draw time1= 2 msec
Line draw time2= 2 msec
Line draw time3= 201 msec
Line draw time4= 217 msec
Line draw time1= 2 msec
Line draw time2= 2 msec
Line draw time3= 203 msec
Line draw time4= 215 msec
Line draw time1= 2 msec
Line draw time2= 3 msec
Line draw time3= 215 msec
Line draw time4= 167 msec
Line draw time1= 2 msec
Line draw time2= 2 msec
Line draw time3= 170 msec
Line draw time4= 182 msec
Line draw time1= 2 msec
Line draw time2= 2 msec
Line draw time3= 166 msec
Line draw time4= 178 msec
Line draw time1= 1 msec
Line draw time2= 1 msec
Line draw time3= 162 msec
Line draw time4= 171 msec
Line draw time1= 2 msec
Line draw time2= 2 msec

PS: I am using BC v4.70 and B4A v8.30 on a Samsung TAB 8.4 with Android 6.0.1.
 

agraham

Expert
Licensed User
It's probably your device which is a few years old now. Whatever Erel is using it is fast!. Results across my six devices for Tests 3 and 4 range from about 40mS for a Xaiomi Mi Max 3 to over 400mS for a Huawei MediaPad T3 7.
 

Syd Wright

Active Member
Licensed User
It's probably your device which is a few years old now. Whatever Erel is using it is fast!. Results across my six devices for Tests 3 and 4 range from about 40mS for a Xaiomi Mi Max 3 to over 400mS for a Huawei MediaPad T3 7.
Ah, this is very useful feedback. My Samsung Galaxy Tab 8.4 is not the slowest tablet: Quad core 1.9 GHz.
Hopefully Erel will tell us what device he is using. I tried the latest BitmapCreator v4.73, thinking that this might be the reason why Erel's results are so good, but it makes no difference compared to v4.70.
 

Erel

Administrator
Staff member
Licensed User
I've just tested it on a powerful device (Google Pixel 2). Nothing special.
 
Top