Android Code Snippet [B4X] [BitmapCreator] Change Color of Bitmap

Alexander Stolte

Expert
Licensed User
Hello,

the Output is not optimal. Have a look down, to Erels code snip for better results.

With this snip, you can easy change a Bitmap/Icon Color. This only makes sense if the picture is monochrome with a transparent background like Icons.

Usage:
B4X:
ImageView1.Bitmap = ChangeImageColor(ImageView1.Bitmap,Colors.Green)
Function:
B4X:
Sub ChangeImageColor(icon As B4XBitmap,clr As Int) As B4XBitmap
    Dim bc As BitmapCreator
 
    bc.Initialize(icon.Width,icon.Height)
    bc.CopyPixelsFromBitmap(icon)
 
For y = 0 To bc.mHeight -1
    For x = 0 To bc.mWidth -1
     
        If bc.IsTransparent(x,y) = False Then
         
                bc.SetColor(x,y,clr)
                 
        End If
     
    Next
 
Next
 
Return bc.Bitmap

End Sub
Example:
Screenshot_20180726-194018__01.jpg

Right Original and Left the changed Version.
The Output is not optimal, maybe you know to make it better, then i will update.
 
Last edited:

Sandman

Well-Known Member
Licensed User
It might be worth mentioning that your method is actually destroying the image quality as it doesn't consider the transparancy values. It's easy to see in the pic you posted, the edges of the white house (the original) are very smooth, because there's lots of different levels of transparancy there. The edges of the green house looks very rough.

Thankfully this is simple to fix. Stop using IsTransparent, as that only answers whether the pixel is completely transparent. Instead use a method that gives the level of transparancy and multiply that with clr. That will produce a perfect result.
 

Erel

Administrator
Staff member
Licensed User


B4X:
Sub Activity_Create(FirstTime As Boolean)
   Activity.LoadLayout("1")
   Dim xui As XUI
   Dim bmp As B4XBitmap = xui.LoadBitmap(File.DirAssets, "baseline_settings_phone_black_48dp.png")
   SetBitmapWithFitOrFill(ImageView1, bmp)
   SetBitmapWithFitOrFill(ImageView2, ChangeColorBasedOnAlphaLevel(bmp, xui.Color_Red))
   SetBitmapWithFitOrFill(ImageView3, ChangeColorBasedOnAlphaLevel(bmp, xui.Color_Blue))
   SetBitmapWithFitOrFill(ImageView4, ChangeColorBasedOnAlphaLevel(bmp, xui.Color_Green))
   SetBitmapWithFitOrFill(ImageView5, ChangeColorBasedOnAlphaLevel(bmp, 0xFFA30075))
   SetBitmapWithFitOrFill(ImageView6, ChangeColorBasedOnAlphaLevel(bmp, 0xFF00FFE7))
End Sub

Sub ChangeColorBasedOnAlphaLevel(bmp As B4XBitmap, NewColor As Int) As B4XBitmap
   Dim bc As BitmapCreator
   bc.Initialize(bmp.Width, bmp.Height)
   bc.CopyPixelsFromBitmap(bmp)
   Dim a1, a2 As ARGBColor
   bc.ColorToARGB(NewColor, a1)
   For y = 0 To bc.mHeight - 1
       For x = 0 To bc.mWidth - 1
           bc.GetARGB(x, y, a2)
           If a2.a > 0 Then
               a2.r = a1.r
               a2.g = a1.g
               a2.b = a1.b
               bc.SetARGB(x, y, a2)
           End If
       Next
   Next
   Return bc.Bitmap
End Sub

Public Sub SetBitmapWithFitOrFill (vTargetView As B4XView, bmp As B4XBitmap)
   vTargetView.SetBitmap(bmp)
   #if B4A
   'B4XView.SetBitmap sets the gravity in B4A to CENTER. This will prevent the bitmap from being scaled as needed so
   'we switch to FILL
   Dim iv As ImageView = vTargetView
   iv.Gravity = Gravity.FILL
   #End If
End Sub
I'm using SetBitmapWithFitOrFill as the icon size is actually 96x96 and the ImageViews are 48x48. This provides better results.
We can also use Bitmap.Resize to resize the image however the performance of SetBitmapWithFitOrFill is better (in most cases it doesn't really matter).
 
Top