I'm passing an allocation created from Bitmap into rs file,
and inside the script I'm trying to copy the allocation to a new one using the rsAllocationCopy2DRange function, but I get force close when I'm trying to run the app.
Can someone please explain how to use the function correctly, and what exactly are the arguments it gets.
I looked in the reference site: http://developer.android.com/reference/renderscript/rs__allocation_8rsh.html#a7f7e2369b3ed7d7db31729b6db7ba07e
but I still don't know what are the dstMip and dstFace and how to get them.
Edit: I want to implement sobel operator, and in the implementation I need to use negative values after convolution with kernel, which is not possible using the build in allocation created from Bitmap and build in convove3x3, because the allocation is using uchar4. So I thought to implement convolution inside separate script so I can use the negative before it stored back to allocation. And I want to be able to pass only one allocation and kernel matrix, and inside the script I want to create new output allocation from the input allocation, and make the convolution on it and than copy the result back to the input allocation. I don't want to create the output allocation outside the script, in the java code, I want the entire process to be as transparent as possible, without the need to add objects that are unknown to the user.
Related
Lets say that I have an allocation where I want to change the value at cell x_0,y_0.Is there a way to either make a call that sets or gets the value of a cell or to run a kernel function that only runs for one cell?
You should probably use rsSetElementAt_uchar4() or whatever data type it is that you are setting. http://developer.android.com/guide/topics/renderscript/reference/rs_allocation_data.html#android_rs:rsSetElementAt is a guide for this.
Alternatively, you can do a single cell kernel call via Script.LaunchOptions (which should have a nice reflected interface in your ScriptC_* files).
http://developer.android.com/reference/android/renderscript/Script.LaunchOptions.html and http://developer.android.com/reference/android/renderscript/Script.html#forEach(int, android.renderscript.Allocation, android.renderscript.Allocation, android.renderscript.FieldPacker, android.renderscript.Script.LaunchOptions)
I want to combine two Renderscript scripts into a scriptGroup. The first one is the ScriptIntrinsicBlur. Based on the blurred U8 allocation as input the second script calculates two things: gradient and gradient-direction. The latter is the formal out-Allocation of the second kernel. The first one is a global allocation filled via rsSetElementAt_float(). Now, I find this second allocation is returned empty after execution of the scriptGroup.
Question: Is my assumption correct that with a scriptGroup you cannot use script globals - or at least not change them via rsSetElementAt_(...)?
UPDATE: I realized that the performance gain by using U8 both as output of the ScriptIntrinsicBlur and as input of the proprietary kernel is already more than satisfactory, even in a simple sequential set-up of both scripts. This is primarily because it avoids to copyTo the ScriptIntrinsicBlur's out-Allocation first into a Java-array before passing it as a separate input-allocation to the 2nd kernel.
Before, I used U8_4 (i.e. Bitmap equivalent) as output of ScriptIntrinsicBlur, and then converted it to a one-dimensional greyscale int[] array, before passing it as in-Allocation to the proprietary kernel... Now I convert to greyscale byte[] (i.e. U8) already before entering the allocation into ScriptIntrinsicBlur and use U8 also as input for the 2nd kernel.
This is what I realize again and again when working with RS: it is really worth to simplify data flows to the extent possible, the speed gains are fantastic. (maybe I will check the Scriptgroup question at a later stage, as for now I am happy with the result).
There should be no issue with using a script global like this. It's not as efficient as the output allocation, but is possible. You mentioned the out allocation is empty, what are you seeing in the script global?
On Android, I'm using Base64.decode() method. It has several variants, but all of them decode the given base64 input into a newly created byte array.
Since I need to call this a lot with big inputs, it allocates a lot of memory and causes frequent GC.
So I'm wondering if there is a way to pass an existing byte array to the method, or alternative techniques, so that it puts the result inside the existing byte array and avoid allocating memory for a new one.
That would be similar to the use of options.inBitmap in BitmapFactory when creating a bitmap in order to reuse an existing bitmap.
Thanks for your help
I wrote the code to create bitmap from a given byte array. Below is the sample code:
Bitmap bm = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888);
bitmap.copyPixelsFromBuffer(ByteBuffer.wrap(imgData));
However, it takes around 15-20 ms. Similarly, there might be other operation which can consume time in an android application. In adb logcat, I see GC_ALLOC_FREE....paused 14ms, growing heap size etc etc.
My question: Is there a way to pre-allocate memory in android applications so it can avoid GC being invoked so many time? I searched online and I got to know that usually game apps do it for performance optimization, however, could't find an example on how to do it.
EDIT:
As per the below suggestion, I have 'bm' as the member variable and create ByteBuffer object.
Bitmap bm = bm.createBitmap(width, height, Bitmap.Config.ARGB_8888);
ByteBuffer bb = ByteBuffer.allocate(<length>);
Then the below code keep getting invoked over and over again:
bitmap.copyPixelFromBuffer(bb.put(data));
However, it gave me the same result and I still see GC_FOR_ALLOC freed...paused 15 ms.
Also, the above code of line gets invoked in a listener method and it gets the 'data' as an argument.
The edited code was actually right, however, I was generating some byte array in other part of my code which was making GC work hard.
#CommansWare: your response pointed me to the right direction. Thanks.
Why don't you create your bitmap using BitmapFactory.decodeByteArray? Then it does everything automagically for you. Also you can check out the extended version of that method that allows you to set the width and height (and other parameters) ahead of time.
Background
I'm new to renderscript, and I would like to try some experiments with it (but small ones and not the complex ones we find in the SDK), so I thought of an exercise to try out, which is based on a previous question of mine (using NDK).
What I want to do
In short, I would like to pass a bitmap data to renderscript, and then I would like it to copy the data to another bitmap that has the dimensions opposite to the previous one, so that the second bitmap would be a rotation of the first one.
For illustration:
From this bitmap (width:2 , height:4):
01
23
45
67
I would like it to rotate (counter clock-wise of 90 degrees) to:
1357
0246
The problem
I've noticed that when I try to change the signature of the root function, Eclipse gives me errors about it.
Even making new functions creates new errors. I've even tried the same code written on Google's blog (here ), but I couldn't find out how he got to create the functions he used, and how come I can't change the filter function to have the input and output bitmap arrays.
What can I do in order to customize the parameters I send to renderscript, and use the data inside it?
Is it ok not to use "filter" or "root" functions (API 11 and above)? What can I do in order to have more flexibility about what I can do there?
You are asking a bunch of separate questions here, so I will answer them in order.
1) You want to rotate a non-square bitmap. Unfortunately, the bitmap model for Renderscript won't allow you to do this easily. The reason for this is that that input and output allocations must have the same shape (i.e. same number of dimensions and values of those dimensions, even if the Types are different). In order to get the effect you want, you should use a root function that only has an output allocation of the new shape (i.e. input columns X input rows). You can create an rs_allocation global variable for holding your input bitmap (which you can then create/bind on the Java side). The kernel then merely needs to set the output cell to the result of rsGetElementAt(globalInAlloc, y, x).
2) If you are using API 11, you can't adjust the signature of the root() function (you can pass NULL allocations as input, output on the Java side if you are not using them). You also can't create more than 1 kernel per source file on these older API levels, so you are forced to only have a single "root()" function. If you want to use more kernels per source file, consider targeting a higher API level.