Android Question drawing variable transparency to reveal underlying image?

Dave O

Well-Known Member
Licensed User
Longtime User
Hi all,

I'm trying to figure out how to reveal an image by putting a black bitmap on top of it, then letting the user draw on the screen to gradually reveal the image.

(Think of it as rubbing soot off a window so you can see through it.)

I can draw with transparency to completely reveal the image in one stroke, but what I really want is a gradual reveal. I imagine this would be setting the transparency of the "rubbed" area to smaller and smaller alpha values of black, so that more of the underlying image shows through.

I've tried AcceleratedSurface, but I can't figure out how to combine the black layer with the circle I'm drawing on it. Not sure if the Porter-Duff modes help here either.

Any ideas? Thanks!


Licensed User
Longtime User
"Scratch and win"?
"Scratch ticket"?

I did it, some time ago (8/8/2014 :()

It was just and example for an italian friend, so texts and names are in italian.
Also, at that time I needed to use the Klaus' code module "Scale" - now you can remove it and use LoadBitmapResize.

2 images attached separately (because of their size).


    12.3 KB · Views: 254
  • grattami.jpg
    168.5 KB · Views: 232
  • haiperso.png
    362.2 KB · Views: 239
Upvote 0

Dave O

Well-Known Member
Licensed User
Longtime User
@LucaMs thanks for your quick reply.

I've tried your example and it does what I've already stated above - make the stroke transparent in one pass.

However, what I'm really after is a gradual reveal - something where the transparency is increased (or the black color removed) bit by bit as the area is touched by more strokes.
Upvote 0


B4X founder
Staff member
Licensed User
Longtime User

B4J code, should be trivial to port to B4A (or B4i):
Sub Process_Globals
   Private fx As JFX
   Private MainForm As Form
   Private xui As XUI
   Private pnl As B4XView
   Private mask As B4XView
   Private bc As BitmapCreator
   Private scale As Float
End Sub

Sub AppStart (Form1 As Form, Args() As String)
   MainForm = Form1
   scale = xui.Scale * 2
   pnl = xui.CreatePanel("pnl")
   MainForm.RootPane.AddNode(pnl, 10dip, 10dip, 400dip, 200dip)
   Dim img As B4XView = CreateImageView
   pnl.AddView(img, 0, 0, pnl.Width, pnl.Height)
   img.SetBitmap(xui.LoadBitmapResize(File.DirAssets, "grattami.jpg", img.Width, img.Height, False))
   mask = CreateImageView
   pnl.AddView(mask, 0, 0, pnl.Width, pnl.Height)
   bc.Initialize(mask.Width / scale, mask.Height / scale)
   bc.DrawRect(bc.TargetRect, xui.Color_Black, True, 0)
   bc.SetBitmapToImageView(bc.Bitmap, mask)
End Sub

Sub pnl_Touch (Action As Int, X As Float, Y As Float)
   If Action = pnl.TOUCH_ACTION_MOVE Then
       Dim r As B4XRect
       r.Initialize(Max(0, x / scale - 10), Max(0, y / scale - 10), 0, 0)
       r.Right = Min(bc.mWidth, r.Left + 20)
       r.Bottom = Min(bc.mHeight, r.Top + 20)
       bc.SetBitmapToImageView(bc.Bitmap, mask)
   End If
End Sub

Sub MakeMoreTransparent(rect As B4XRect)
   Dim pm As PremultipliedColor
   For y = rect.Top To rect.Bottom - 1
       For x = rect.Left To rect.Right - 1
           bc.GetPremultipliedColor(x, y, pm)
           pm.a = Bit.And(pm.a, 0xff) * 0.9
           bc.SetPremultipliedColor(x, y, pm)
End Sub

Sub CreateImageView As B4XView
   Dim iv1 As ImageView
   Return iv1
End Sub

Note that this code will work with black masks. It will require a bit more work to support other masks.
Upvote 0

Dave O

Well-Known Member
Licensed User
Longtime User
Thanks @Erel , if I understand your code correctly, it's taking the area being touched (as a rect), getting the mask's corresponding area, then looping through all pixels in that rect to reduce the alpha value of each by 10% each time.

I was wondering if I needed to get down to pixel level, so thanks for confirming that. I'll chew on this and try porting it to my Android app. (I have not yet graduated to using XUI because I haven't gone beyond Android yet, though I eventually will need to.)

Thanks again!
Upvote 0