Android Question Problem with canvas

LucianoB

Member
Licensed User
Longtime User
Good morning to everybody.
I'm having an issue with canvas and I already spent 3 days trying to fix it.
I have an imageview in pnlimage, and two other panels and two canvas. When the imageview shows a picture I then draw some red circles on it, like a selection area. Then, through a button, I select an eraser, like a rubber eraser, and I want to erase the red circles or part of them, drawing transparent filled circles. Everything works fine in the imageview but if I save the resulting picture what I have is that where I used the rubber, instead to have transparent area, I have black area. I want it to be transparent like in the imageview. This is my code.
please can somebody help me? thank you again in advance.
If needed I can post the small project.
Attached is the resulting picture.

B4X:
Sub Globals
    Public pnlimage,pnlDrawing,pnlBackground As Panel
    Public deletearea As Boolean
    Public dir As String = File.DirAssets
    Public filename As String = "airplane_wing.jpg"
    Public cvsDrawing, cvsbackground As Canvas
    Public imageview2 As ImageView
    Public img2 As Bitmap
    Public rectDest,rectPanels As Rect
    Public x1,y1,x2,y2 As Int
End Sub

Sub Activity_Create(firsttime As Boolean)
   
        Activity.LoadLayout("Main")
        imageview2.Bitmap=LoadBitmap(dir,filename)
        pnlDrawing.Initialize("pnlDrawing")
        pnlimage.AddView(pnlDrawing,imageview2.Left ,imageview2.Top , imageview2.Width ,imageview2.Height )
        cvsDrawing.Initialize(pnlDrawing)
        pnlBackground.Initialize("pnlBackground")
        pnlimage.AddView(pnlBackground, imageview2.Left ,imageview2.Top , imageview2.Width ,imageview2.Height)
        cvsbackground.Initialize(pnlBackground)
        rectPanels.Initialize(0, 0, pnlDrawing.Width, pnlDrawing.Height)
        rectDest.Initialize(0, 0, imageview2.Width, imageview2.Height)
        cvsDrawing.Initialize(pnlDrawing)
        cvsDrawing.DrawBitmap(LoadBitmap(dir,filename), Null, rectDest)'''no questa

End Sub

Sub pnlDrawing_Touch (Action As Int, x As Float, y As Float)
   
Select Action
     Case Activity.ACTION_DOWN
        ' memorizes the coordinates where the finger touches the screen
        ' these are the line begin coordinates
        x1 = x
        y1 = y
        x2 = x
        y2 = y
       
    Case Activity.ACTION_MOVE
        If deletearea = False Then
            ' erases the current line
            cvsbackground.DrawLine(x1, y1, x2, y2, Colors.Transparent  , 3dip)
            ' gets the new line end coordinates
            x2 = x
            y2 = y
            ' draws the new line
            cvsbackground.DrawLine(x1, y1, x2, y2, Colors.Blue, 3dip)
        Else
            '======>>>    HERE I TRY TO DELETE THE RED CIRCLES BUT THE RESULT ARE BLACK CIRCLES
            cvsDrawing.DrawCircle(x,y,30dip,Colors.Transparent,True,30dip)
            pnlDrawing.Invalidate
        End If
        pnlDrawing.Invalidate
       
    Case Activity.ACTION_UP
        ' erases the current line from pnlDrawing Panel
        cvsbackground.DrawLine(x1, y1, x2, y2, Colors.Transparent  , 3dip)
        pnlDrawing.Invalidate
        Dim r As Int = Sqrt(Power(Abs(x2-x1),2)+Power(Abs(y2-y1),2))
        cvsDrawing.DrawCircle(x1, y1, r, Colors.Red, False, 5dip)
        cvsDrawing.RemoveClip
        pnlDrawing.Invalidate
    End Select
End Sub

Sub btnRubber_Click
    If deletearea=False Then
        deletearea=True
        Return
    End If
    If deletearea=True Then
        deletearea=False
        Return
    End If
End Sub


Sub Activity_Pause (UserClosed As Boolean)
End Sub

Sub Button6_Click    'save picture
    File.Delete(dir, filename)
    Dim Out As OutputStream
    Out = File.OpenOutput(File.DirRootExternal, filename, False)
    cvsDrawing.Bitmap.WriteToStream(Out, 100, "JPEG")
    Out.Flush
    Out.Close
End Sub
 

Attachments

  • airplane_wing.jpg
    airplane_wing.jpg
    234.4 KB · Views: 250

LucianoB

Member
Licensed User
Longtime User
Thanks for your prompt reply Erel.
Well, I'm still learning on how to use canvas. This is why RemoveClip is there which surely is not needed.
Attached is my small project.
 

Attachments

  • MyProject1.zip
    37.1 KB · Views: 284
Upvote 0

sorex

Expert
Licensed User
Longtime User
the problem is that you save to JPG and that format doesn't support transparency nor alpha blending.

use PNG instead.
 
Upvote 0

LucianoB

Member
Licensed User
Longtime User
Thank you sorex for your advice.
I converted my source picture to png format and used it in my imageview and changed the code to this but the issue remains.
B4X:
Sub Button6_Click    'save picture
    File.Delete(dir, filename)
    Dim Out As OutputStream
    Out = File.OpenOutput(File.DirRootExternal, filename, False)
    cvsDrawing.Bitmap.WriteToStream(Out, 100, "PNG")
    Out.Flush
    Out.Close
End Sub
 
Upvote 0

LucianoB

Member
Licensed User
Longtime User
I got you. ok
When I drew the red circles I hit "rubber" button, then I pass my finger over the red circles. on the path where I passed the finger the red circles become transparent showing the picture. Then I save with "save" button. Then I use file manager to open the saved picture to see the results because I will use this picture later for something else.
 
Upvote 0

sorex

Expert
Licensed User
Longtime User
ok, I can confirm that it can work fine.

here's when it's opened in photoshop.

piccy.png
 
Upvote 0

ilan

Expert
Licensed User
Longtime User
I think you should use 1 panel and 1 imageview

Panel should be above imageview and draw with canvas on this panel after you finish
draw everything from that panel to your imageview and save the image.
 
Upvote 0

sorex

Expert
Licensed User
Longtime User
he actually has 2 images views to prevent the holes when drawing those transparent circles.

this is what worked here but I was hiding the 2nd image to see the hole

B4X:
Sub Activity_Create(firsttime As Boolean)
   
        Activity.LoadLayout("Main")
        imageview2.Bitmap=LoadBitmap(dir,filename)
        imageview2.Visible=False
        pnlDrawing.Initialize("pnlDrawing")
        pnlimage.AddView(pnlDrawing,imageview2.Left ,imageview2.Top , imageview2.Width ,imageview2.Height )
        cvsDrawing.Initialize(imageview2)
        pnlBackground.Initialize("pnlBackground")
        pnlimage.AddView(pnlBackground, imageview2.Left ,imageview2.Top , imageview2.Width ,imageview2.Height)
        cvsbackground.Initialize(pnlBackground)
        rectPanels.Initialize(0, 0, pnlDrawing.Width, pnlDrawing.Height)
        rectDest.Initialize(0, 0, imageview2.Width, imageview2.Height)
        cvsDrawing.Initialize(pnlDrawing)
        cvsDrawing.DrawBitmap(LoadBitmap(dir,filename), Null, rectDest)'''no questa

End Sub

Sub pnlDrawing_Touch (Action As Int, x As Float, y As Float)
   
Select Action
     Case Activity.ACTION_DOWN
        ' memorizes the coordinates where the finger touches the screen
        ' these are the line begin coordinates
        x1 = x
        y1 = y
        x2 = x
        y2 = y
       
    Case Activity.ACTION_MOVE
        If deletearea = False Then
            ' erases the current line
            cvsbackground.DrawLine(x1, y1, x2, y2, Colors.Transparent  , 3dip)
            ' gets the new line end coordinates
            x2 = x
            y2 = y
            ' draws the new line
            cvsbackground.DrawLine(x1, y1, x2, y2, Colors.Blue, 3dip)
        Else
            '======>>>    HERE I TRY TO DELETE THE RED CIRCLES BUT THE RESULT ARE BLACK CIRCLES
            cvsDrawing.DrawCircle(x,y,30dip,Colors.Transparent,True,30dip)
            pnlDrawing.Invalidate
        End If
        pnlDrawing.Invalidate
       
    Case Activity.ACTION_UP
        ' erases the current line from pnlDrawing Panel
        cvsbackground.DrawLine(x1, y1, x2, y2, Colors.Transparent  , 3dip)
        pnlDrawing.Invalidate
        Dim r As Int = Sqrt(Power(Abs(x2-x1),2)+Power(Abs(y2-y1),2))
        cvsDrawing.DrawCircle(x1, y1, r, Colors.Transparent, True, 0dip)
'        cvsDrawing.RemoveClip
        pnlDrawing.Invalidate
    End Select
End Sub

Sub btnRubber_Click
    If deletearea=False Then
        deletearea=True
        Return
    End If
    If deletearea=True Then
        deletearea=False
        Return
    End If
End Sub


Sub Activity_Pause (UserClosed As Boolean)
End Sub

Sub Button6_Click    'save picture
    File.Delete(dir, filename)
    Dim Out As OutputStream
    Out = File.OpenOutput(File.DirRootExternal, "test.png", False)
    cvsDrawing.Bitmap.WriteToStream(Out, 100, "PNG")
    Out.Flush
    Out.Close
End Sub
 
Upvote 0

sorex

Expert
Licensed User
Longtime User
also notice that your android device and maybe your windows picture viewer might still show the holes as black or grey
but when opening it in a decent tool you will see that it is transparent.
 
Upvote 0

LucianoB

Member
Licensed User
Longtime User
sorex, your last answer is really interesting. In fact I tried to open the resulting picture with my windows picture viewer (I didn't do it until now) and the holes are white instead of black (like in the android device). I want to thank also ilan for his help. ilan's idea is also an interesting approach but I have 2 panels and two canvas. will try to find the way to copy the panels images to the imageview and save it.
 
Upvote 0

sorex

Expert
Licensed User
Longtime User
you only need 1 panel and 1 imageview that's linked to a canvas.

you detect movement on the panel and draw to the imageview via canvas.

you used 2 because you didn't want to show the holes but just a circle I guess?

you could draw the circles to a seperate overlaying panel aswell then you will keep the image and have the circles on top of it.
 
Upvote 0

LucianoB

Member
Licensed User
Longtime User
I used 2 panels and 2 canvas because on one of them the radius of the circle is drew in blue color and then removed when you leave the finger from the panel, on the second one the red circle is drew with the final radius.
 
Upvote 0
Top