I have no problem applying the ScriptIntrinsicConvolve3x3 (or 5x5) function for in- and output allocations being both U8_4. But if I want to apply the convolution to a gradient filter such as Sobel I need an output of type float (not U8_4), because I need to consider also the NEGATIVE output values. This question was raised here already 18 month ago but has not been answered yet. Any help is highly appreciated.
Ok, below you have all the important parts. It's been copied from a working code, hopefully I did not miss anything. Computing gradient magnitude in Java using out
and out2
allocations is left as an exercise for the reader. ;) Again, it would be much faster (and cleaner) to do it all in one Renderscript pass.
public class MainActivity {
private RenderScript mRS;
private Allocation mInAllocation;
Type.Builder TypeIn;
private void createScript(Bitmap mBitmapIn) {
mRS = RenderScript.create(this);
TypeIn = new Type.Builder(mRS, Element.F32_4(mRS));
mInAllocation = createFromBitmap_F32_4(mRS, mBitmapIn);
mScriptConvolve = ScriptIntrinsicConvolve3x3.create(mRS,
Element.F32_4(mRS));
}
private Allocation createFromBitmap_F32_4(RenderScript rs, Bitmap b)
{
int w = b.getWidth();
int h = b.getHeight();
int idx = 0;
Allocation atn = Allocation.createTyped(mRS, TypeIn.setX(w).setY(h).create());
float []temp = new float[w * h * 4];
for(int y = 0; y < h; y++)
for(int x = 0; x < w; x++)
{
int pix = b.getPixel(x, y);
temp[idx++] = 255.f;
temp[idx++] = (float)((pix >>> 16) & 0xff);
temp[idx++] = (float)((pix >>> 8) & 0xff);
temp[idx++] = (float)(pix & 0xff);
}
atn.copyFrom(temp);
return atn;
}
private void allocationToBitmap(Allocation atn, Bitmap bmp)
{
int w = bmp.getWidth();
int h = bmp.getHeight();
int idx = 0;
float []temp = new float[w * h * 4];
atn.copyTo(temp);
for(int y = 0; y < h; y++)
for(int x = 0; x < w; x++)
{
int a = 255; idx++;
int r = Math.min(255, Math.max(0, (int)temp[idx++]));
int g = Math.min(255, Math.max(0, (int)temp[idx++]));
int b = Math.min(255, Math.max(0, (int)temp[idx++]));
bmp.setPixel(x, y, (a << 24 | r << 16 | g << 8 | b));
}
}
private void performFilter(Allocation inAllocation,
Bitmap bitmapOut) {
Allocation out = Allocation.createTyped(mRS, TypeIn.create());
Allocation out2 = Allocation.createTyped(mRS, TypeIn.create());
// Emboss filter kernel
float coefficients[] = {-1, 0, 1, -2, 0, 2, -1, 0, 1};
float coefficients2[] = {-1, -2, -1, 0, 0, 0, 1, 2, 1};
mScriptConvolve.setCoefficients(coefficients);
mScriptConvolve.setInput(inAllocation);
mScriptConvolve.forEach(out); // Gx
mScriptConvolve.setCoefficients(coefficients2);
mScriptConvolve.setInput(inAllocation);
mScriptConvolve.forEach(out2); // Gy
allocationToBitmap(out2, bitmapOut);
}