*Note there is workaround needed to avoid running your processes out of memory when using this, please see my post int his thread: http://www.b4x.com/android/forum/threads/bitmaps-subs-and-garbage-collection.37660/
*
I was searching for a higher performance method of analyzing images (real-time), and stubled on the fairly new feature of android (4.2 and later only I believe) - RenderScript Intrinsics
http://android-developers.blogspot.com/2013/08/renderscript-intrinsics.html
Performance in release mode:
Gaussian Blur (7 pixels) 640x480:
RSImageProcessingLibrary: 16 seconds
RenderScript GuassianBlur: 100 ms
I have only tested this on Android 4.2.2 on Boundary Devices nitrogen6x (imx6), it will not work on my API17 emulator (get random colored noise as output bitmap), I think it requires a hardware GPU. Requires Reflection library.
I may update this post with more Intrinsic functions and turn it into a complete class if I need them in my project (I may end up using the 3x3 and 5x5 convolutions as well for example)
Here is code to do a 5x5 convolution:
It is called like so:
Where
bitmapOut bitmapIn are Bitmap
You can find more info about kernels to use to achieve filter effects @
http://en.wikipedia.org/wiki/Kernel_(image_processing)
http://docs.gimp.org/en/plug-in-convmatrix.html
From my testing 5x5 convolution takes about the same time as gaussian blur on hardware with GPU support. So a 512x512 image takes about 10 ms to process on hardware made in the past two years. It allows for emboss/sharpen/edge detect type filters. Getting fancy you can do the "oil painting" filters and such from photoshop by stacking convolutions.
In the future this would probably be easier to do with inline java rather than reflection.
*
I was searching for a higher performance method of analyzing images (real-time), and stubled on the fairly new feature of android (4.2 and later only I believe) - RenderScript Intrinsics
http://android-developers.blogspot.com/2013/08/renderscript-intrinsics.html
Performance in release mode:
Gaussian Blur (7 pixels) 640x480:
RSImageProcessingLibrary: 16 seconds
RenderScript GuassianBlur: 100 ms
I have only tested this on Android 4.2.2 on Boundary Devices nitrogen6x (imx6), it will not work on my API17 emulator (get random colored noise as output bitmap), I think it requires a hardware GPU. Requires Reflection library.
I may update this post with more Intrinsic functions and turn it into a complete class if I need them in my project (I may end up using the 3x3 and 5x5 convolutions as well for example)
B4X:
Public Sub GaussianBlur(bm As Bitmap, radius As Float) As Bitmap
Dim Obj1 As Reflector
Dim time As Long
time = DateTime.Now
Dim args(1) As Object
Dim types(1) As String
'RenderScript rs = RenderScript.create(getApplicationContext());
Dim rs As Reflector
args(0) = Obj1.GetContext
types(0) = "android.content.Context"
rs.Target = Obj1.RunStaticMethod("android.renderscript.RenderScript","create", args, types)
'Element.U8_4(rs)
Dim oU8 As Reflector
args(0) = rs.Target
types(0) = "android.renderscript.RenderScript"
oU8.Target = Obj1.RunStaticMethod("android.renderscript.Element","U8_4", args, types)
' ScriptIntrinsicBlur theIntrinsic = ScriptIntrinsicBlur
'.create(rs, Element.U8_4(rs));
Dim theIntrinsic As Reflector
Dim args2(2) As Object
Dim types2(2) As String
args2(0) = rs.Target
types2(0) = "android.renderscript.RenderScript"
args2(1) = oU8.Target
types2(1) = "android.renderscript.Element"
theIntrinsic.Target = Obj1.RunStaticMethod("android.renderscript.ScriptIntrinsicBlur","create", args2, types2)
'Allocation tmpIn = Allocation.createFromBitmap(rs, bm);
'Dim bm As Bitmap
'bm = LoadBitmap(File.DirAssets, "reusedefault.bmp")
Dim tmpIn As Reflector
args2(0) = rs.Target
types2(0) = "android.renderscript.RenderScript"
args2(1) = bm
types2(1) = "android.graphics.Bitmap"
tmpIn.Target = Obj1.RunStaticMethod("android.renderscript.Allocation", "createFromBitmap", args2, types2)
'Allocation tmpOut = Allocation.createFromBitmap(rs, outputBitmap);
Dim outputBitmap As Bitmap
outputBitmap.InitializeMutable(bm.Width,bm.Height)
Dim tmpOut As Reflector
args2(0) = rs.Target
types2(0) = "android.renderscript.RenderScript"
args2(1) = outputBitmap
types2(1) = "android.graphics.Bitmap"
tmpOut.Target = Obj1.RunStaticMethod("android.renderscript.Allocation", "createFromBitmap", args2, types2)
'theIntrinsic.setRadius(25.f);
args(0) = radius
types(0) = "java.lang.float"
theIntrinsic.RunPublicmethod("setRadius",args,types)
'theIntrinsic.setInput(tmpIn);
args(0) = tmpIn.Target
types(0) = "android.renderscript.Allocation"
theIntrinsic.RunPublicmethod("setInput",args,types)
'theIntrinsic.forEach(tmpOut);
args(0) = tmpOut.Target
types(0) = "android.renderscript.Allocation"
theIntrinsic.RunPublicmethod("forEach",args,types)
'tmpOut.copyTo(outputBitmap);
args(0) = outputBitmap
types(0) = "android.graphics.Bitmap"
tmpOut.RunMethod4("copyTo",args, types)
Log("Blur took: " & (DateTime.Now - time) & " ms")
Return outputBitmap
End Sub
Here is code to do a 5x5 convolution:
B4X:
Public Sub Convolution5x5(bm As Bitmap, coeff() As Float) As Bitmap
Dim Obj1 As Reflector
Dim time As Long
time = DateTime.Now
Dim args(1) As Object
Dim types(1) As String
'Element.U8_4(rs)
Dim oU8 As Reflector
args(0) = rs.Target
types(0) = "android.renderscript.RenderScript"
oU8.Target = Obj1.RunStaticMethod("android.renderscript.Element","U8_4", args, types)
Dim theIntrinsic As Reflector
Dim args2(2) As Object
Dim types2(2) As String
args2(0) = rs.Target
types2(0) = "android.renderscript.RenderScript"
args2(1) = oU8.Target
types2(1) = "android.renderscript.Element"
theIntrinsic.Target = Obj1.RunStaticMethod("android.renderscript.ScriptIntrinsicConvolve5x5","create", args2, types2)
'Allocation tmpIn = Allocation.createFromBitmap(rs, bm);
'Dim bm As Bitmap
'bm = LoadBitmap(File.DirAssets, "reusedefault.bmp")
Dim tmpIn As Reflector
args2(0) = rs.Target
types2(0) = "android.renderscript.RenderScript"
args2(1) = bm
types2(1) = "android.graphics.Bitmap"
tmpIn.Target = Obj1.RunStaticMethod("android.renderscript.Allocation", "createFromBitmap", args2, types2)
'Allocation tmpOut = Allocation.createFromBitmap(rs, outputBitmap);
Dim outputBitmap As Bitmap
outputBitmap.InitializeMutable(bm.Width,bm.Height)
Dim tmpOut As Reflector
args2(0) = rs.Target
types2(0) = "android.renderscript.RenderScript"
args2(1) = outputBitmap
types2(1) = "android.graphics.Bitmap"
tmpOut.Target = Obj1.RunStaticMethod("android.renderscript.Allocation", "createFromBitmap", args2, types2)
'theIntrinsic.setCoefficients(float[]);
args(0) = coeff
'types(0) = "java.lang.float" this needs to be passed as "[F" for array of float, not primitive type
theIntrinsic.RunPublicmethod("setCoefficients",args,Array As String("[F"))
args(0) = tmpIn.Target
types(0) = "android.renderscript.Allocation"
theIntrinsic.RunPublicmethod("setInput",args,types)
args(0) = tmpOut.Target
types(0) = "android.renderscript.Allocation"
theIntrinsic.RunPublicmethod("forEach",args,types)
args(0) = outputBitmap
types(0) = "android.graphics.Bitmap"
tmpOut.RunMethod4("copyTo",args, types)
Log("Convolution took: " & (DateTime.Now - time) & " ms")
Return outputBitmap
End Sub
It is called like so:
B4X:
bitmapOut = Convolution5x5(bitmapIn,Array As Float( _
0,0,0,0,0, _
0,1,1,1,0, _
0,1,2,1,0, _
0,1,1,1,0, _
0,0,0,0,0 _
))
Where
bitmapOut bitmapIn are Bitmap
You can find more info about kernels to use to achieve filter effects @
http://en.wikipedia.org/wiki/Kernel_(image_processing)
http://docs.gimp.org/en/plug-in-convmatrix.html
From my testing 5x5 convolution takes about the same time as gaussian blur on hardware with GPU support. So a 512x512 image takes about 10 ms to process on hardware made in the past two years. It allows for emboss/sharpen/edge detect type filters. Getting fancy you can do the "oil painting" filters and such from photoshop by stacking convolutions.
In the future this would probably be easier to do with inline java rather than reflection.
Last edited: