B4J Question return Bitmap from 2 Bitmaps [b4x]

ilan

Expert
Licensed User
Longtime User
hi, its more a b4x question then a b4j question. i just post it here because the code i write is in b4j because its much simpler but i need it for b4i.

anyway, i want to return a bitmap from 2 bitmaps drawn one of each other. what would be the best way to do it? (as much b4x as possible)

i do it with b4xcanvas, is it ok? is there a better way? this is my code right now but i dont like it a lot although it works fine. any suggestions are welcome.

B4X:
#Region Project Attributes
    #MainFormWidth: 600
    #MainFormHeight: 600
#End Region

Sub Process_Globals
    Type vec2(left As Float, top As Float, width As Float, height As Float)
    Private fx As JFX
    Private MainForm As Form
    Dim xui As XUI
End Sub

Sub AppStart (Form1 As Form, Args() As String)
    MainForm = Form1
    'MainForm.RootPane.LoadLayout("Layout1") 'Load the layout file.
    MainForm.Show
   
    Dim bmp1, bmp2 As B4XBitmap
    bmp1 = xui.LoadBitmap(File.DirAssets,"smiling-kid-boy-cartoon-character-vector-15054701.jpg")
    bmp2 = xui.LoadBitmap(File.DirAssets,"22-223255_cartoon-trophy-clipart-trophy-clipart.png")
   
    Dim imgv As ImageView
    imgv.Initialize("")   
    imgv.PreserveRatio = True
    MainForm.RootPane.AddNode(imgv,50dip,50dip,150dip,200dip)
   
    Dim v As vec2
    v.Initialize
    v.left = bmp1.Width*0.7
    v.top = bmp1.Height*0.7
    v.width = bmp1.Width*0.3
    v.height = bmp1.Height*0.3
   
    imgv.SetImage(combine2bitmaps(bmp1,bmp2,createrect(v)))
End Sub

Sub createrect(vec As vec2) As B4XRect
    Dim rect As B4XRect
    rect.Initialize(vec.left,vec.top,vec.left+vec.width,vec.top+vec.height)
    Return rect
End Sub

Sub combine2bitmaps(firstBmp As B4XBitmap, secondBmp As B4XBitmap, SecondImageRect As B4XRect) As B4XBitmap
    Dim p As B4XView = xui.CreatePanel("")
    p.SetLayoutAnimated(0,0,0,firstBmp.Width,firstBmp.Height)
    Dim c As B4XCanvas
    c.Initialize(p)
    c.DrawBitmap(firstBmp,c.TargetRect)
    c.DrawBitmap(secondBmp, SecondImageRect)
    Dim res As B4XBitmap = c.CreateBitmap
    c.Release
    Return res
End Sub

'Return true to allow the default exceptions handler to handle the uncaught exception.
Sub Application_Error (Error As Exception, StackTrace As String) As Boolean
    Return True
End Sub

when i initialize the b4xcanvas i must enter a targetview so i create a panel but never add it to anywhere, is this ok?

result:

1595494811851.png


EDIT: Code has been updated to Erels suggestion.
 

Attachments

  • 22-223255_cartoon-trophy-clipart-trophy-clipart.png
    22-223255_cartoon-trophy-clipart-trophy-clipart.png
    44.6 KB · Views: 181
  • smiling-kid-boy-cartoon-character-vector-15054701.jpg
    smiling-kid-boy-cartoon-character-vector-15054701.jpg
    54.4 KB · Views: 180
Last edited:

Erel

B4X founder
Staff member
Licensed User
Longtime User
It is simple to make it cross platform:
B4X:
Sub combine2bitmaps(firstBmp As B4XBitmap, secondBmp As B4XBitmap, SecondImageRect As B4XRect) As B4XBitmap
    Dim p As B4XView = xui.CreatePanel("")
    p.SetLayoutAnimated(0,0,0,firstBmp.Width,firstBmp.Height)
    Dim c As B4XCanvas
    c.Initialize(p)
    c.DrawBitmap(firstBmp,c.TargetRect)
    c.DrawBitmap(secondBmp, SecondImageRect )
    Dim res As B4XBitmap = c.CreateBitmap
   c.Release
    Return  res
End Sub
 
Upvote 0

ilan

Expert
Licensed User
Longtime User
It is simple to make it cross platform:
B4X:
Sub combine2bitmaps(firstBmp As B4XBitmap, secondBmp As B4XBitmap, SecondImageRect As B4XRect) As B4XBitmap
    Dim p As B4XView = xui.CreatePanel("")
    p.SetLayoutAnimated(0,0,0,firstBmp.Width,firstBmp.Height)
    Dim c As B4XCanvas
    c.Initialize(p)
    c.DrawBitmap(firstBmp,c.TargetRect)
    c.DrawBitmap(secondBmp, SecondImageRect )
    Dim res As B4XBitmap = c.CreateBitmap
   c.Release
    Return  res
End Sub

thanx erel, this is exactly what i needed a more b4x code :)
 
Upvote 0

ilan

Expert
Licensed User
Longtime User
A possible optimization, which is relevant if you plan to use it more than a few times, is to reuse the canvas.

actually this exactly what i plan to do. i am creating a gif in my app and i want to add AR effects to it so basically another gif on it. so i will extract the gif to bitmaps and add it in front of my bitmaps and create from them a single gif together so reusing the canvas is a good idea. it will all be inside a loop. so how can i reuse the canvas in this case?

thanks, ilan
 
Upvote 0

ilan

Expert
Licensed User
Longtime User
Ok i know how do it. I will pass a list with bitmaps to this function and release the canvas after i finish using all bitmaps.

thanx
 
Upvote 0

Erel

B4X founder
Staff member
Licensed User
Longtime User
If you are worried about performance then a better solution is to create a custom view made of two ImageViews and put each image in a different ImageView. This way you will let the hardware acceleration do its job.
Instead of resizing the second image, you should resize the second ImageView (explanation: https://www.b4x.com/android/forum/threads/b4x-bitmapsasync.119589/post-748442).

The code to set the bitmap should look like this:
B4X:
Target.SetBitmap(bmp)
#if B4A
Dim iiv As ImageView = Target
iiv.Gravity = Gravity.FILL
#End If
 
Upvote 0

ilan

Expert
Licensed User
Longtime User
If you are worried about performance then a better solution is to create a custom view made of two ImageViews and put each image in a different ImageView. This way you will let the hardware acceleration do its job.
Instead of resizing the second image, you should resize the second ImageView (explanation: https://www.b4x.com/android/forum/threads/b4x-bitmapsasync.119589/post-748442).

The code to set the bitmap should look like this:
B4X:
Target.SetBitmap(bmp)
#if B4A
Dim iiv As ImageView = Target
iiv.Gravity = Gravity.FILL
#End If

the only performance i am worried about is the resizing and creating the bitmaps. the app will not show the bitmaps inside imageview. i just create the bitmaps and pass them to the "create gif" class that expect a list of bitmaps. so i just need to create from 2 bitmaps 1 bitmaps and this about 5 to 8 frames. so this process will run 5 to 8 times in a loop. so the imageviews in this case are not needed in my opinion. i will work on it today and post the results. i really like b4i its so simple to use and very powerful :)
 
Upvote 0

emexes

Expert
Licensed User
put each image in a different ImageView. This way you will let the hardware acceleration do its job.
This seems obvious, but just in case: if the image backgrounds are transparent, then having each object in its own (image)view is one small step from being animated. 🥳
 
Upvote 0

ilan

Expert
Licensed User
Longtime User
ok its now 1:32 am and i have got far with my app :)
so, in the end, i did add 2 imageviews because I show the animation in the app and with the imageviews it runs very smoothly as erel already mentioned above.

it is a huge update for an existing app but 1 thing is still missing and that's the special effects that I want to implement buts I am too tired to finish it right now so keep something for tomorrow 😁
 
Last edited:
Upvote 0
Top