B4A Library ABExtDrawing 1.0

ABExtDrawing 1.7

ABExtDrawing is a wrapper around the Android Drawing classes.

14/08/2012: Updated to version 1.7

Bugfixes and additional functions for blurring and masks.

16/02/2012: Updated to version 1.1

It makes it possible to access all the drawing functions of the Canvas. It is like the B4A canvas, but you can also use all Paints.

Several sub objects are also included:
ABPaint: a wrapper for thePaint class
ABMatrix: a wrapper for the Matrix class
ABRegion: a wrapper for the Region class
ABColorMatrix: a wrapper for the ColorMatrix class
ABCamera: a wrapper for the Camera class [NEW version 1.1]
ABRgbFunctions: several functions to manipulate RGB values

Also two extended classes
ABRectF: a wrapper around the RectF class. B4A contains the Rect class, but to use some of the functions of this library I needed the float version of Rect.
ABPath: a full wrapper for the Path class. B4A contains the Path class but only exposes LineTo. ABPath exposes all functions (like addArc, addOval, etc...)

This lib is to big to list all functions, but a lot of them are used in the attached demo. It is a B4A translation of the Thermometer project on Mind The Robot

Therm.png


How to use this library:

The main object is ABExtDrawing. You pass the B4A canvas to each function:
B4X:
Sub Globals
        Dim ExDraw As ABExtDrawing
        Dim MyCanvas As Canvas
        Dim Panel1 as Panel
end Sub

Sub Activity_Create(FirstTime As Boolean)
        If FirstTime Then
      Activity.LoadLayout("2")
      MyCanvas.Initialize(Panel1)   
   End If
        drawRim(MyCanvas)
End Sub

Sub drawRim(Canv As Canvas)
   ' first, draw the metallic body
   ExDraw.drawOval(Canv, rimRect, rimPaint)
   ' now the outer rim circle
   ExDraw.drawOval(Canv, rimRect, rimCirclePaint)
End Sub

The fun part is you can create all kind of Paints:
B4X:
        ' the linear gradient Is a Bit skewed For realism
   rimPaint.Initialize
   rimPaint.SetFlags(rimPaint.flag_ANTI_ALIAS_FLAG)
   rimPaint.SetLinearGradient2(1,0.40, 0.0, 0.60, 1.0, Colors.RGB(0xf0, 0xf5, 0xf0),Colors.RGB(0x30, 0x31, 0x30),rimPaint.ShaderTileMode_CLAMP)   
   rimPaint.DoShaderSingle(1)

   rimCirclePaint.Initialize
   rimCirclePaint.SetAntiAlias(True)
   rimCirclePaint.SetStyle(rimCirclePaint.Style_STROKE)
   rimCirclePaint.SetColor(Colors.ARGB(0x4f, 0x33, 0x36, 0x33))
   rimCirclePaint.SetStrokeWidth(0.005)

or make extended Paths:
B4X:
        handPath.Initialize
   handPath.moveTo(0.5, 0.5 + 0.2)
   handPath.lineTo(0.5 - 0.010, 0.5 + 0.2 - 0.007)
   handPath.lineTo(0.5 - 0.002, 0.5 - 0.32)
   handPath.lineTo(0.5 + 0.002, 0.5 - 0.32)
   handPath.lineTo(0.5 + 0.010, 0.5 + 0.2 - 0.007)
   handPath.lineTo(0.5, 0.5 + 0.2)
   handPath.addCircle(0.5, 0.5, 0.025, handPath.Direction_CW)

You can also use the Save and Restore functions of the canvas:
B4X:
Sub drawScale(Canv As Canvas)
   ExDraw.drawOval(Canv, scaleRect, ScalePaint)

   ExDraw.save2(Canv, ExDraw.MATRIX_SAVE_FLAG)
   Dim i As Int
   Dim y1 As Float
   Dim y2 As Float
   Dim value As Int
   Dim valueString As String
   For i = 0 To totalNicks
      y1 = scaleRect.top
      y2 = y1 - 0.020
         
      ExDraw.drawLine(Canv, 0.5, y1, 0.5, y2, ScalePaint)
         
      If (i Mod 5 = 0) Then
         value = nickToDegree(i)
         If (value >= minDegrees AND value <= maxDegrees) Then
            valueString = value
            ExDraw.drawText(Canv, valueString, 0.5, y2 - 0.015, ScalePaint)
         End If
      End If
         
      ExDraw.rotate2(Canv, degreesPerNick, 0.5, 0.5)
   Next
   ExDraw.restore(Canv)
End Sub

For more information on what is possible, look into the Android documentation

There is a new article on the Camera class (see the AB3DCamera project) that shows you how to make a 3D list with ABExtDrawing 1.1. The article can be found at Alwaysbusy's Corner. The project is also attached to this post.

3DCamera.png
 

Attachments

  • ABExtDrawing - Demo.zip
    168 KB · Views: 3,013
  • AB3DCamera.zip
    265.4 KB · Views: 2,344
  • ABExtDrawing 1.7.zip
    51.6 KB · Views: 3,121
Last edited:

alwaysbusy

Expert
Licensed User
Longtime User
Yes, I'm reading on the net that it is still a problem and SetLinearText does not fix this in 5 anymore. Seems the only workaround for the moment is scaling up:

In java it's solved like this:

final float magnifier = 100f;

// Scale the canvas
canvas.save();
canvas.scale(1f / magnifier, 1f / magnifier);

// increase the font size
mDegreeMarkingsPaint.setTextSize(originalTextSize * magnifier);

canvas.drawText(value, x*magnifier, y*magnifier,mDegreeMarkingsPaint);

//canvas.drawTextOnPath(value, textPath, 0.0f, 0.0f, mDegreeMarkingsPaint);

// bring everything back to normal
canvas.restore();

Should be possible with the existing lib.
 

alwaysbusy

Expert
Licensed User
Longtime User
I'm not currently working in B4A (other project, other language) but it should be something like this:

Dim magnifier As Double = 100
Dim OriginalTextSize As Double = 20

myExDraw.save(tmpCanv)
myExDraw.scale(tmpCanv, 1/magnifier, 1/magnifier)

' hovever the paint is build
Dim mDegreeMarkingsPaint As ABPaint
mDegreeMarkingsPaint.Initialize
mDegreeMarkingsPaint.setDither(True)
mDegreeMarkingsPaint.setAntiAlias(True)
mDegreeMarkingsPaint.SetTextSize(OriginalTextSize * magnifier)

myExDraw.drawText(tmpCanv, "mytext", x * magnifier, y * magnifier, mDegreeMarkingsPaint)

myExDraw.restore(tmpCanv)
 

peacemaker

Expert
Licensed User
Longtime User
Hi,
Please, suggest a sub how to get 16 x 16 pixels Bitmap from any size source Bitmap.
Stratching for getting a picture hash.


I have found sub to get it https://www.b4x.com/android/forum/threads/wish-createscaledbitmap-core-function.21439/#content, but
B4X:
Sub GrayScale(bmp As Bitmap) As Bitmap
    Dim bmpGrayscale As Bitmap
    'bmpGrayscale.InitializeMutable(bmp.Width, bmp.height)
    bmpGrayscale.InitializeMutable(16dip, 16dip)
    Dim c As Canvas
    c.Initialize2(bmpGrayscale)

    Dim paint As ABPaint
    paint.Initialize

    Dim mat As ABColorMatrix
    mat.Initialize
    mat.SetSaturation(0)

    paint.SetColorMatrixColorFilter2(mat)
    Dim ExDraw As ABExtDrawing
    ExDraw.drawBitmap2(c, bmp, 0, 0, paint)
    Return bmpGrayscale
End Sub
drawBitmap2 is declared to scale the picture to the Canvas BMP that is 16 x 16 :-(
but not scaled into 16 x 16.
 
Last edited:

alwaysbusy

Expert
Licensed User
Longtime User
I don't think DrawBitmap2 scales the dimensions, only the density.

To scale you can use DrawBitmap4 with a matrix. Maybe it has to be done in two steps (first grayscale, then scale)

Something in the lines of (not tested):

B4X:
Dim bmpGrayscale As Bitmap
bmpGrayscale.InitializeMutable(16dip, 16dip)
Dim c As Canvas
c.Initialize2(bmpGrayscale)

Dim paint As ABPaint
paint.Initialize
paint.setDither(True)
paint.setAntiAlias(True)
paint.setFilterBitmap(True)

Dim mat As ABColorMatrix
mat.Initialize
mat.SetSaturation(0)
paint.SetColorMatrixColorFilter2(mat)

Dim innerScale As Float
innerScale = bmpGrayscale.width/bmp.width
Dim matrix As ABMatrix
matrix.postScale(innerScale, innerScale)

Dim ExDraw AsABExtDrawing
exDraw.drawBitmap4(c, bmp, matrix, paint)  

Return bmpGrayscale
 

TheMightySwe

Active Member
Licensed User
Longtime User
Hi, all,

has anyone made any cool resizeable buttons using this libray and feel like share some code??
 

Troberg

Well-Known Member
Licensed User
Longtime User
Really nice lib, although a bit overwhelming in its powerfulness.

I have a very distinct problem, and I can't find the apropriate methods to do it. My problem:

I have to bitmaps, one is an icon with an alpha channel (actually, the only thing I'm interested in is the alpha channel), the other is a background color/gradient. I want to combine these, so that I get an icon with the same transparency as the icon, but all the nontransparent pixels are replaced by the corresponding pixels from the other bitmap. In other words, the alpha channel works as a cookie cutter on the color bitmap.

To do this, I plan to use Porter-Duff modes, using:

Source: The color bitmap
Dest: The alpha icon
Porter-Duff mode: In

Now, I can find constants for PorterDuffMode in ABExtDrawing, but I can't find the right method to apply them.

I want to achieve something like (conceptually only, just to clarify, not exactly):

B4X:
Dim ABExtDraw as ABExtDrawing
BitmapResult=ABExtDraw.DrawPorterDuff(BitmapSource, BitmapDest, ABExtDraw.PorterDuffMode_IN)

How to do this?
 

alwaysbusy

Expert
Licensed User
Longtime User
Try this. (For some reason Drawbitmap2() does not work, so use DrawBitmap())

B4X:
Public Sub BuildBitmap(iPicture As Bitmap, iPicture2 As Bitmap) As Bitmap
   Dim exDraw As ABExtDrawing
   
   Dim xBuildPicture As Bitmap
   Dim xBuildCanvas As Canvas
     
   xBuildPicture.InitializeMutable(iPicture.Width, iPicture.Height)
   xBuildCanvas.Initialize2(xBuildPicture)
       
   Dim paint As ABPaint
   paint.Initialize
   paint.setDither(True)
   paint.setAntiAlias(True)
   paint.setFilterBitmap(True)   
   
   Dim d As Rect
   d.Initialize(0,0,iPicture.Width, iPicture.Height)
     
   exDraw.drawBitmap(xBuildCanvas, iPicture, Null, d, paint)
   
   paint.SetPorterDuffXfermode(paint.PorterDuffMode_SRC_IN)
   exDraw.drawBitmap(xBuildCanvas, iPicture2, Null, d, paint)
   
   Return xBuildPicture
End Sub
 

NeoTechni

Well-Known Member
Licensed User
Longtime User
Do you know how I would make an image mask?
Ie: the alpha level of each pixel of a bitmap I draw I controlled by the shade of grey of a second bitmap. Black = 255, white = 0
 

Troberg

Well-Known Member
Licensed User
Longtime User
Found one minor hickup, and fixed it. The background and mask were swapped in the last few lines. Fixed code below, hope someone has use for it!

B4X:
Private Sub BuildBitmap(Back As Bitmap, Mask As Bitmap) As Bitmap
  Dim exDraw As ABExtDrawing
  Dim xBuildPicture As Bitmap
  Dim xBuildCanvas As Canvas

  xBuildPicture.InitializeMutable(Back.Width, Back.Height)
  xBuildCanvas.Initialize2(xBuildPicture)

  Dim paint As ABPaint
  paint.Initialize
  paint.setDither(True)
  paint.setAntiAlias(True)
  paint.setFilterBitmap(True)
 
  Dim d As Rect
  d.Initialize(0,0,Back.Width, Back.Height)
   
  exDraw.drawBitmap(xBuildCanvas, Mask, Null, d, paint)
  
  paint.SetPorterDuffXfermode(paint.PorterDuffMode_SRC_IN)
  exDraw.drawBitmap(xBuildCanvas, Back, Null, d, paint)
 
  Return xBuildPicture
End Sub

Once again, thanks for the help!
 

Elton Leung

Member
Licensed User
Longtime User
The 3Dcamera sample shows the possibility to create sudo 3d object with 2 transforming trapezoid shape bitmaps, I am impressed. I just wonder is the ABExtDrawing library can also transform triangle shape bitmap or shape with 4 sides. I like to create a warping effect similar to below picture. I know Pixel by Pixel plotting is possible, but it will be very slow.

I need a function that can change a square bitmap into any shape with the input of just 4 corners.

image%20distortion.jpg
 

sultan87

Active Member
Licensed User
Longtime User
hello,
very nice
I created an app to manage a thermostat via SIM card
I took your abex drawing demo
but it does not show me the full figures as your example
how to position the needle on a precise value
values are in degrees Celsius or Fahrenheit
best regards
 

sultan87

Active Member
Licensed User
Longtime User
hello,
very nice
I created an app to manage a thermostat via SIM card
I took your abex drawing demo
how to position the needle on a precise value
best regards
 

Turbo3

Active Member
Licensed User
Longtime User
Any chance of getting the example code in the first post updated to work on Android 5.x by updating it with the code fragments in post #44?

It is not clear to me how you integrate the lines in post #44 into the example code. Has anyone done it and gotten it to display the all the scale digits rather than only the last digit?

Or is there a better way to get this working on Android 5?
 

NeoTechni

Well-Known Member
Licensed User
Longtime User
How do I use path operations like RegionOp_DIFFERENCE? ie: I'd like to use it to subtract an oval path from a rect path
 

NeoTechni

Well-Known Member
Licensed User
Longtime User
I'm using drawpoly to draw parts of an image distorted, but for some reason it draws the entire image instead of the part I defined as the source. Is there a way to limit it to just the source dimensions so I don't have to use a clippath?
 

NeoTechni

Well-Known Member
Licensed User
Longtime User
Now I need RegionOp_INTERSECT.

B4X:
Sub OpPath(Path1 As Path, Path2 As Path, Op As Int) As Path
   Dim Operation As String
   Select Case Op
     Case -1:    Operation = "DIFFERENCE"
     Case 0:    Operation = "INTERSECT"
     Case 1:    Operation = "REVERSE_DIFFERENCE"     
     Case 2:    Operation = "UNION"'merge 2 paths together
     Case 3:    Operation = "XOR"
   End Select
  Dim jo As JavaObject = Path1, success As Boolean = jo.RunMethod("op", Array(Path2, Operation))
   Return Path1   
End Sub

This does 2 normal paths, but one of the paths I need are a handpath, and it won't work with this code
 
Top