GetSubBitmap

nicholas.jj.taylor

Member
Licensed User
Longtime User
I need to get a sub-bitmap from an existing bitmap i.e.

I have Bitmap1 which is 200x200 dimensions.

Now, I want to store a new Bitmap2 that is a grab of Bitmap1 Left=50,Top=50,Width=100,Height=100

Can anyone suggest a proper way to do this as I'm stuck.

Here is my code so far...

A code module:..
B4X:
Sub GetBitmap(VwSource As View) As Bitmap
   Dim StrMethod As String = "Sub GetBitmap(VwSource As View) As Bitmap"
   Dim BmpResult As Bitmap = Null
   Try      
      Dim BmpView As Bitmap
      BmpView = GetSubBitmap(VwSource, VwSource.Width, VwSource.Height)
      
      BmpResult = BmpView
      
   Catch
      CdException.Show(StrClass, StrMethod, LastException)
   End Try
   Return BmpResult
End Sub

Sub PasteBitmap(ImgTarget As ImageView, BmpSource As Bitmap, IntXOffset As Int, IntYOffset As Int)
   Dim StrMethod As String = "Sub PasteBitmap(ImgTarget As ImageView, BmpSource As Bitmap, IntXOffset As Int, IntYOffset As Int)"
   Try
      Dim CnvImgTarget As Canvas
      CnvImgTarget.Initialize(ImgTarget)
          
      Dim Rct As Rect
      
      Dim BmpImgTarget As Bitmap
      BmpImgTarget = GetBitmap(ImgTarget)
      
      Rct.Initialize(0, 0, BmpImgTarget.Width, BmpImgTarget.Height)
       CnvImgTarget.DrawBitmap(BmpImgTarget, Null, Rct)
      
      Rct.Initialize(IntXOffset, IntYOffset, BmpSource.Width+IntXOffset, BmpSource.Height+IntYOffset)
       CnvImgTarget.DrawBitmap(BmpSource, Null, Rct)
      
       ImgTarget.Invalidate

   Catch
      CdException.Show(StrClass, StrMethod, LastException)
   End Try
End Sub

Sub GetSubBitmap(VwSource As View, IntMaxWidth As Int, IntMaxHeight As Int) As Bitmap
   Dim StrMethod As String = "Sub GetSubBitmap(VwSource As View, IntMaxWidth As Int, IntMaxHeight As Int) As Bitmap"
   Dim BmpResult As Bitmap = Null
   Try
      Dim Bmp As Bitmap
      
      Dim IntWidth As Int
      If VwSource.Width > IntMaxWidth Then
         IntWidth = IntMaxWidth
         
      Else
         IntWidth = VwSource.Width
      
      End If
      
      Dim IntHeight As Int
      If VwSource.Height > IntMaxHeight Then
         IntHeight = IntMaxHeight
         
      Else
         IntHeight = VwSource.Height
      
      End If
      
      Bmp.InitializeMutable(IntWidth, IntHeight)
      
      Dim Cnv As Canvas
      Cnv.Initialize2(Bmp)
      
      Dim Rfl As Reflector
      Rfl.Target = Cnv
      
      Dim AryObjectRef(1) As Object 
      AryObjectRef = Array As Object (Rfl.GetField("canvas"))
      
      Dim AryObjectTypeRef(1) As String
      AryObjectTypeRef = Array As String ("android.graphics.Canvas")
      
      Dim RftView As Reflector
      RftView.Target = VwSource
      
      RftView.RunMethod4("draw", AryObjectRef, AryObjectTypeRef)
      
      BmpResult = Bmp
   
   Catch
      CdException.Show(StrClass, StrMethod, LastException)
   End Try
   Return BmpResult
End Sub

and a couple of functions that I put in the Activity class due to the method used.

B4X:
#Region Screenshot

   Sub GetJoinedBitmap(BmpFirst As Bitmap, BmpSecond As Bitmap) As Bitmap
      Dim StrMethod As String = "Sub GetJoinedBitmap(BmpFirst As Bitmap, BmpSecond As Bitmap) As Bitmap"
      Dim BmpResult As Bitmap = Null
      Try
         Dim IntWidth As Int
         If BmpFirst.Width > BmpSecond.Width Then
            IntWidth = BmpFirst.width
         
         Else
            IntWidth = BmpSecond.width
         
         End If
               
         Dim IntHeight As Int
         IntHeight = BmpFirst.Height + BmpSecond.Height
         
         Dim ImgTemp As ImageView
         ImgTemp.Initialize("ImgTemp")
          Activity.AddView(ImgTemp, 0, 0, IntWidth, IntHeight)
         
         CdScreenShot.PasteBitmap(ImgTemp, BmpFirst, 0, 0)
         
         CdScreenShot.PasteBitmap(ImgTemp, BmpSecond, 0, BmpFirst.Height)   
         
         Dim BmpJoined As Bitmap
         BmpJoined = CdScreenShot.GetBitmap(ImgTemp)
         
         ImgTemp.RemoveView
         
         BmpResult = BmpJoined
         
      Catch
         CdException.Show(StrClass, StrMethod, LastException)
      End Try
      Return BmpResult
   End Sub
   
   Sub GetSubBitmap(VwSource As View, IntLeft As Int, IntTop As Int, IntWidth As Int, IntHeight As Int) As Bitmap
      Dim StrMethod As String = "Sub GetSubBitmap(VwSource As View, IntLeft As Int, IntTop As Int, IntWidth As Int, IntHeight As Int) As Bitmap"
      Dim BmpResult As Bitmap = Null
      Try
         Dim ImgTemp As ImageView
         ImgTemp.Initialize("ImgTemp")
          Activity.AddView(ImgTemp, 0, 0, IntWidth, IntHeight)
         
         Dim BmpSource As Bitmap
         BmpSource = CdScreenShot.GetBitmap(VwSource)
         
         CdScreenShot.PasteBitmap(ImgTemp, BmpSource, 0 - IntLeft, 0 - IntTop)
         
         Dim BmpSubBitmap As Bitmap
         BmpSubBitmap = CdScreenShot.GetBitmap(ImgTemp)
         
         ImgTemp.RemoveView
         
         BmpResult = BmpSubBitmap
      
      Catch
         CdException.Show(StrClass, StrMethod, LastException)
      End Try
      Return BmpResult
   End Sub
   
#End Region

It is my approach that I think is the problem.

PS. CdException.Show(StrClass, StrMethod, LastException) simply displays an exception into the log along with the method and class that threw it.

B4X:
Sub Show(StrClass As String, StrMethod As String, Ex As Exception)
   LogColor("Exception: " & Ex.Message & " - Class: " & StrClass & " - Method: " & StrMethod, Colors.Magenta)
   
End Sub
 
Last edited:

derez

Expert
Licensed User
Longtime User
I think what you are looking for is very simple, qouted from canvas documentation:
DrawBitmap (Bitmap1 As android.graphics.Bitmap, SrcRect As android.graphics.Rect, DestRect As android.graphics.Rect)

Draws a bitmap.
SrcRect - The subset of the bitmap that will be drawn. If Null then the complete bitmap will be drawn.
DestRect - The rectangle that the bitmap will be drawn to.

Example:
Dim Bitmap1 As Bitmap
Bitmap1.Initialize(File.DirAssets, "X.jpg")
Dim DestRect As Rect
DestRect.Initialize(10dip, 10dip, 10dip + 100dip, 10dip + 100dip)
Canvas1.DrawBitmap(Bitmap1, Null, DestRect) 'draws the bitmap to the destination rectangle.

Dim SrcRect As Rect
SrcRect.Initialize(0, 0, Bitmap1.Width / 2, Bitmap1.Height) 'the left half of the bitmap.
DestRect.Top = 200dip
DestRect.Bottom = 200dip + 100dip
Canvas1.DrawBitmap(Bitmap1, SrcRect, DestRect) 'draws half of the bitmap.
Activity.Invalidate
 
Upvote 0

nicholas.jj.taylor

Member
Licensed User
Longtime User
Thanks. I absolutely did not find the concept simple or the objects easy to use.

However, after some good old-fashioned elbow-grease, I did manage to make some nice functions that work really nicely, and they are:

B4X:
Sub GetBitmapFromView(VwSource As View) As Bitmap
   Dim StrMethod As String = "Sub GetBitmapFromView(VwSource As View) As Bitmap"
   Dim BmpResult As Bitmap = Null
   Try
      Dim Bmp As Bitmap
      
      Dim IntWidth As Int
      
         IntWidth = VwSource.Width
      
      Dim IntHeight As Int
         IntHeight = VwSource.Height
      
      Bmp.InitializeMutable(IntWidth, IntHeight)
      
      Dim Cnv As Canvas
      Cnv.Initialize2(Bmp)
      
      Dim Rfl As Reflector
      Rfl.Target = Cnv
      
      Dim AryObjectRef(1) As Object 
      AryObjectRef = Array As Object (Rfl.GetField("canvas"))
      
      Dim AryObjectTypeRef(1) As String
      AryObjectTypeRef = Array As String ("android.graphics.Canvas")
      
      Dim RftView As Reflector
      RftView.Target = VwSource
      
      RftView.RunMethod4("draw", AryObjectRef, AryObjectTypeRef)
      
      BmpResult = Bmp
   
   Catch
      CdException.Show(StrClass, StrMethod, LastException)
   End Try
   Return BmpResult
End Sub

Sub PasteBitmap(ImgTarget As ImageView, BmpSource As Bitmap, IntXOffset As Int, IntYOffset As Int)
   Dim StrMethod As String = "Sub PasteBitmap(ImgTarget As ImageView, BmpSource As Bitmap, IntXOffset As Int, IntYOffset As Int)"
   Try
      Dim CnvImgTarget As Canvas
      CnvImgTarget.Initialize(ImgTarget)
          
      Dim Rct As Rect
      
      Dim BmpImgTarget As Bitmap
      BmpImgTarget = GetBitmapFromView(ImgTarget)
      
      Rct.Initialize(0, 0, BmpImgTarget.Width, BmpImgTarget.Height)
       CnvImgTarget.DrawBitmap(BmpImgTarget, Null, Rct)
      
      Rct.Initialize(IntXOffset, IntYOffset, BmpSource.Width+IntXOffset, BmpSource.Height+IntYOffset)
       CnvImgTarget.DrawBitmap(BmpSource, Null, Rct)
      
       ImgTarget.Invalidate

   Catch
      CdException.Show(StrClass, StrMethod, LastException)
   End Try
End Sub

Sub GetJoinedBitmap(BmpFirst As Bitmap, BmpSecond As Bitmap) As Bitmap
   Dim StrMethod As String = "Sub GetJoinedBitmap(BmpFirst As Bitmap, BmpSecond As Bitmap) As Bitmap"
   Dim BmpResult As Bitmap = Null
   Try
      Dim IntWidth As Int
      If BmpFirst.Width > BmpSecond.Width Then
         IntWidth = BmpFirst.width
      
      Else
         IntWidth = BmpSecond.width
      
      End If
            
      Dim IntHeight As Int
      IntHeight = BmpFirst.Height + BmpSecond.Height
      
      Dim BmpTarget As Bitmap
      BmpTarget.InitializeMutable(IntWidth, IntHeight)
            
      Dim CnvBitmap As Canvas
      CnvBitmap.Initialize2(BmpTarget)
      
      Dim IntTempHeight As Int
      IntTempHeight = BmpFirst.height
      
      Dim RctBmpFirstDestination As Rect
      RctBmpFirstDestination.Initialize(0, 0, BmpFirst.width, BmpFirst.height)
               
      Dim RctBmpFirstSource As Rect
      RctBmpFirstSource.Initialize(0, 0, BmpFirst.width, BmpFirst.height)
      
      CnvBitmap.DrawBitmap(BmpFirst, RctBmpFirstSource, RctBmpFirstDestination) 
      
      
      Dim RctBmpSecondDestination As Rect
      RctBmpSecondDestination.Initialize(0, BmpFirst.height, IntWidth, BmpFirst.height + BmpSecond.height)
      
      Dim RctBmpSecond As Rect
      RctBmpSecond.Initialize(0, 0, BmpSecond.width, BmpSecond.height)
      
      CnvBitmap.DrawBitmap(BmpSecond, RctBmpSecond, RctBmpSecondDestination) 
      
      
      BmpResult = BmpTarget
      
   Catch
      CdException.Show(StrClass, StrMethod, LastException)
   End Try
   Return BmpResult
End Sub

Sub GetSubBitmap(BmpSource As Bitmap, IntLeft As Int, IntTop As Int, IntWidth As Int, IntHeight As Int) As Bitmap
   Dim StrMethod As String = "Sub GetSubBitmap(BmpSource As Bitmap, IntLeft As Int, IntTop As Int, IntWidth As Int, IntHeight As Int) As Bitmap"
   Dim BmpResult As Bitmap
   Try         
      Dim RctDestination As Rect
      RctDestination.Initialize(0, 0, IntWidth - IntLeft, IntHeight - IntTop)
      
      Dim RctSource As Rect
      RctSource.Initialize(IntLeft, IntTop, IntWidth, IntHeight)
            
      Dim BmpTarget As Bitmap
      BmpTarget.InitializeMutable(IntWidth - IntLeft, IntHeight - IntTop)
            
      Dim CnvBitmap As Canvas
      CnvBitmap.Initialize2(BmpTarget)
               
      CnvBitmap.DrawBitmap(BmpSource, RctSource, RctDestination) 
               
      BmpResult = BmpTarget
      
   Catch
      CdException.Show(StrClass, StrMethod, LastException)
   End Try
   Return BmpResult
End Sub

I have them in a code module. I'm a bit pressed for time now, but I will revisit this and clean up the code a bit later.


Kind regards,
Nick
 
Upvote 0

nicholas.jj.taylor

Member
Licensed User
Longtime User
Getting a bitmap from a scrollview is subtly different:

B4X:
Sub GetBitmapFromScrollView(ScrSource As ScrollView) As Bitmap
   Dim StrMethod As String = "Sub GetBitmapFromScrollView(ScrSource As ScrollView) As Bitmap"
   Dim BmpResult As Bitmap = Null
   Try      
      Dim IntWidth As Int
      IntWidth = ScrSource.Width
      
      Dim IntHeight As Int
      IntHeight = ScrSource.Panel.Height
      
      Dim Bmp As Bitmap
      Bmp.InitializeMutable(IntWidth, IntHeight)
      
      Dim Cnv As Canvas
      Cnv.Initialize2(Bmp)
      
      Dim Rfl As Reflector
      Rfl.Target = Cnv
      
      Dim AryObjectRef(1) As Object 
      AryObjectRef = Array As Object (Rfl.GetField("canvas"))
      
      Dim AryObjectTypeRef(1) As String
      AryObjectTypeRef = Array As String ("android.graphics.Canvas")
      
      Dim RftView As Reflector
      RftView.Target = ScrSource
      
      RftView.RunMethod4("draw", AryObjectRef, AryObjectTypeRef)
      
      BmpResult = Bmp
   
   Catch
      CdException.Show(StrClass, StrMethod, LastException)
   End Try
   Return BmpResult
End Sub
 
Upvote 0
Top