我試圖使用Android的RenderScript在圖像後面渲染半透明的圓,但從RenderScript內核返回值時事情變得非常錯誤。RenderScript錯誤地操作內核的輸出
這是我的內核:
#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);
}
現在,rsPackColorTo8888()
功能需要4個與漂浮在0.0和1.0之間的值。然後通過計算每個浮點值255次來找到生成的ARGB顏色。所以給定的浮點數對應顏色R = 0.686 * 255 = 175,G = 0.686 * 255 = 175,B = 0.686 * 255 = 175和A = 0.561 * 255 = 143。
rsPackColorTo8888()
函數本身工作正常,但是當發現從內核返回的值uchar4
時,會發生一些非常奇怪的事情。 R,G和B值分別變爲Red * Alpha = 56,Green * Alpha = 56和Blue * Alpha = 56,其中Alpha爲0.561。這意味着R,G和B的值不可能比A = 0.561 * 255大。
手動設置輸出,而不是使用rsPackColorTo8888()
會產生完全相同的行爲。我的意思是下面的代碼產生完全相同的結果,這反過來證明,證明rsPackColorTo8888()
不是問題:
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;
}
}
這是Java代碼從腳本被稱爲:
@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;
}
當alpha設置爲255(或1.0,如float),返回的顏色值(在我的應用程序的Java代碼中)是正確的。
我做錯了什麼,或者這真的是在RenderScript實現中的某個地方?
注:我已經檢查並在萬普拉斯3T(安卓7.1.1),是Nexus 5(安卓7.1.2),Android的模擬器版本7.1.2和6.0
你能分享你的java代碼和你正在測試的設備嗎? – sakridge
@sakridge謝謝你的回覆!我已將用於測試的Java代碼和設備添加到我的帖子中。 –
我不確定,但也許'fa.a == 0'比較結果爲false,因爲'fa.a'是浮動的。如果您更改爲'in.a == 0',它是否會產生相同的輸出? –