RenderScript incorrectly controls kernel output

I'm trying to use Android RenderScript to render a translucent circle behind an image, but when I return a value from the RenderScript kernel, everything happens very badly.

This is my core:

#pragma version(1) #pragma rs java_package_name(be.abyx.aurora) // We don't need very high precision floating points #pragma rs_fp_relaxed // Center position of the circle int centerX = 0; int centerY = 0; // Radius of the circle int radius = 0; // Destination colour of the background can be set here. float destinationR; float destinationG; float destinationB; float destinationA; static int square(int input) { return input * input; } uchar4 RS_KERNEL circleRender(uchar4 in, uint32_t x, uint32_t y) { //Convert input uchar4 to float4 float4 f4 = rsUnpackColor8888(in); // Check if the current coordinates fall inside the circle if (square(x - centerX) + square(y - centerY) < square(radius)) { // Check if current position is transparent, we then need to add the background!) if (f4.a == 0) { uchar4 temp = rsPackColorTo8888(0.686f, 0.686f, 0.686f, 0.561f); return temp; } } return rsPackColorTo8888(f4); } 

The rsPackColorTo8888() function rsPackColorTo8888() accepts 4 floats with a value from 0.0 to 1.0. The resulting ARGB color is then determined by calculating 255 times each float value. Thus, these floats correspond to the color R = 0.686 * 255 = 175, G = 0.686 * 255 = 175, B = 0.686 * 255 = 175 and A = 0.561 * 255 = 143.

The rsPackColorTo8888() function works correctly, but when the found uchar4 value uchar4 returned from the kernel, something really strange happens. The values โ€‹โ€‹of R, G, and B change respectively to Red * Alpha = 56, Green * Alpha = 56, and Blue * Alpha = 56, where Alpha is 0.561. This means that no value of R, G and B can be greater than A = 0.561 * 255.

Manually setting output instead of using rsPackColorTo8888() gives the exact same behavior. I mean, the following code gives the same result, which in turn proves that rsPackColorTo8888() not a problem:

 if (square(x - centerX) + square(y - centerY) < square(radius)) { // Check if current position is transparent, we then need to add the background!) if (f4.a == 0) { uchar4 temp; temp[0] = 175; temp[1] = 175; temp[2] = 175; temp[3] = 143; return temp; } } 

This is the Java code from which the script is called:

 @Override public Bitmap renderParallel(Bitmap input, int backgroundColour, int padding) { ResizeUtility resizeUtility = new ResizeUtility(); // We want to end up with a square Bitmap with some padding applied to it, so we use the // the length of the largest dimension (width or height) as the width of our square. int dimension = resizeUtility.getLargestDimension(input.getWidth(), input.getHeight()) + 2 * padding; Bitmap output = resizeUtility.createSquareBitmapWithPadding(input, padding); output.setHasAlpha(true); RenderScript rs = RenderScript.create(this.context); Allocation inputAlloc = Allocation.createFromBitmap(rs, output); Type t = inputAlloc.getType(); Allocation outputAlloc = Allocation.createTyped(rs, t); ScriptC_circle_render circleRenderer = new ScriptC_circle_render(rs); circleRenderer.set_centerX(dimension / 2); circleRenderer.set_centerY(dimension / 2); circleRenderer.set_radius(dimension / 2); circleRenderer.set_destinationA(((float) Color.alpha(backgroundColour)) / 255.0f); circleRenderer.set_destinationR(((float) Color.red(backgroundColour)) / 255.0f); circleRenderer.set_destinationG(((float) Color.green(backgroundColour)) / 255.0f); circleRenderer.set_destinationB(((float) Color.blue(backgroundColour)) / 255.0f); circleRenderer.forEach_circleRender(inputAlloc, outputAlloc); outputAlloc.copyTo(output); inputAlloc.destroy(); outputAlloc.destroy(); circleRenderer.destroy(); rs.destroy(); return output; } 

If alpha is set to 255 (or 1.0 as a float), the returned color values โ€‹โ€‹(inside the applicationโ€™s Java code) are correct.

Am I doing something wrong, or is it really a mistake somewhere in the RenderScript implementation?

Note. I tested and verified this behavior on Oneplus 3T (Android 7.1.1), Nexus 5 (Android 7.1.2), Android emulator versions 7.1.2 and 6.0

+7
android renderscript
source share
1 answer

Instead of passing values โ€‹โ€‹with type:

 uchar4 temp = rsPackColorTo8888(0.686f, 0.686f, 0.686f, 0.561f); 

Trying to create float4 and pass this.

 float4 newFloat4 = { 0.686, 0.686, 0.686, 0.561 }; uchar4 temp = rsPackColorTo8888(newFloat4); 
0
source share

All Articles