Android应用程序在renderscript代码中崩溃

时间:2015-07-29 09:53:18

标签: android renderscript

这是我实现BoxBlur的renderscript代码:

#pragma version(1)
#pragma rs java_package_name(com.karthik.imgproc)

rs_allocation pixelAlloc;
rs_allocation indices;
uint width;
uint height;
int radius;

void root(const uint *v_in, uchar4 *v_out) {
    uint row = *v_in >> 16 & 0xffff;
    uint col = *v_in & 0xffff;
    uint sumR = 0;
    uint sumG = 0;
    uint sumB = 0;
    int yr = 0;
    int xr = 0;
    for(yr = -radius; yr <= radius; yr++){
        for(xr = -radius; xr <= radius; xr++){
            int a = row + xr;
            int b = col + yr;
            if(a < 0 || b < 0)
                continue;
            uchar4 p = rsGetElementAt_uchar4(pixelAlloc, a, b);
            sumR = sumR + p.r;
            sumG = sumG + p.g;
            sumB = sumB + p.b;
        }
    }
    uint divisor = ((radius * 2) + 1) * ((radius * 2) + 1);
    float R = sumR / divisor;
    float G = sumG / divisor;
    float B = sumB / divisor;

    float A = rsGetElementAt_uchar4(pixelAlloc, row, col).a;
    if(R > 255)
        R = 255;
    if(R < 0)
        R = 0;
    if(G > 255)
        G = 255;
    if(G < 0)
        G = 0;
    if(B > 255)
        B = 255;
    if(B < 0)
        B = 0;
    R = R/255;
    G = G/255;
    B = B/255;
    A = A/255;
    *v_out = rsPackColorTo8888(R,G,B,A);
}

这是启动renderscript代码执行的java代码

private void convolve(final Bitmap srcBmp, int radius){
    int width = srcBmp.getWidth();
    int height = srcBmp.getHeight();
    Allocation inPixels = Allocation.createFromBitmap(mRs, srcBmp, Allocation.MipmapControl.MIPMAP_NONE, Allocation.USAGE_SHARED);
    inPixels.copyFrom(srcBmp);
    ScriptC_convolve script = new ScriptC_convolve(mRs);
    script.set_width(width);
    script.set_height(height);
    script.set_radius(radius);
    script.set_pixelAlloc(inPixels);

    Allocation in = Allocation.createTyped(mRs, Type.createXY(mRs, Element.U32(mRs), srcBmp.getWidth(), srcBmp.getHeight()), Allocation.USAGE_SCRIPT);
    int pixelIndices[] = new int[srcBmp.getWidth() * srcBmp.getHeight()];
    int i = 0;
    for(int col=0; col<width; col++){
        for(int row=0; row<height; row++, i++){
            pixelIndices[i] = (row << 16) | col ;
        }
    }
    in.copy2DRangeFrom(0, 0, srcBmp.getWidth(), srcBmp.getHeight(), pixelIndices);
    final Bitmap dstBitmap = Bitmap.createBitmap(srcBmp.getWidth(), srcBmp.getHeight(), srcBmp.getConfig());
    Allocation out = Allocation.createTyped(mRs, inPixels.getType(), Allocation.USAGE_SHARED);
    script.forEach_root(in, out);
    out.copyTo(dstBitmap);
   ((ImageView)findViewById(R.id.dstImgView)).setImageDrawable(new BitmapDrawable(getResources(), dstBitmap));
    script.destroy();
}

问题是应用程序每次都有以下日志崩溃:

F/libc    (28885): Fatal signal 7 (SIGBUS), code 2, fault addr 0xa3369000 in tid 28922 (imageprocessing)
F/libc    (28885): Fatal signal 7 (SIGBUS), code 2, fault addr 0xa3369820 in tid 28920 (imageprocessing)
F/libc    (28885): Fatal signal 7 (SIGBUS), code 2, fault addr 0xa336da20 in tid 28921 (imageprocessing)
I/DEBUG   (15097): *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** ***
I/DEBUG   (15097): Build fingerprint: 'motorola/falcon_asia_ds/falcon_umtsds:5.0.2/LXB22.46-28/30:user/release-keys'
I/DEBUG   (15097): Revision: 'p3c0'
I/DEBUG   (15097): ABI: 'arm'
I/DEBUG   (15097): pid: 28885, tid: 28922, name: imageprocessing  >>> imageeffect.kpbird.com.imageprocessing <<<
I/DEBUG   (15097): signal 7 (SIGBUS), code 2 (BUS_ADRERR), fault addr 0xa3369000
I/DEBUG   (15097):     r0 00000001  r1 a320f020  r2 000001f7  r3 a2c27000
I/DEBUG   (15097):     r4 00159fe0  r5 00000b00  r6 00000000  r7 000000b7
I/DEBUG   (15097):     r8 00000000  r9 00000000  sl 00000001  fp 000000b8
I/DEBUG   (15097):     ip 00000000  sp a682dc94  lr ffffffff  pc a2c230fc  cpsr 200f0010
I/DEBUG   (15097):
I/DEBUG   (15097): backtrace:
I/DEBUG   (15097):     #00 pc 000000fc  /dev/kgsl-3d0
I/DEBUG   (15097):     #01 pc fffffffd  <unknown>
I/DEBUG   (15097):
I/DEBUG   (15097): Tombstone written to: /data/tombstones/tombstone_07
E/        (15097): tid 28920 does not exist in pid 28885. ignoring debug request
E/        (15097): tid 28921 does not exist in pid 28885. ignoring debug request
I/BootReceiver(  988): Copying /data/tombstones/tombstone_07 to DropBox (SYSTEM_TOMBSTONE)
W/ActivityManager(  988):   Force finishing activity imageeffect.kpbird.com.imageprocessing/com.karthik.imgproc.MainActivity
I/WindowState(  988): WIN DEATH: Window{18f03389 u0 imageeffect.kpbird.com.imageprocessing/com.karthik.imgproc.MainActivity}

我不明白应用程序崩溃的原因。但对于非常小的图像说25x25分辨率,它的工作正常。这里有趣的观察是我评论出来的时候 * v_out = rsPackColorTo8888(R,G,B,A)在renderscript代码中,应用程序没有崩溃当然不会显示任何内容。我的问题是为什么它会在rsPackColorTo8888(R,G,B,A)崩溃?我实施的方式有什么问题。为什么它适用于非常小的图像?对于大多数图像应用程序崩溃。

2 个答案:

答案 0 :(得分:2)

此代码存在许多问题。建议:

  • 检查上限(if(a < 0 || b < 0)仅检查下限),
  • 不要将int除以int并期望浮点精度结果(float R = sumR / divisor;
  • 使用clamp()而不是检查RGB值对0和255,
  • 使用矢量类型而不是单独处理R,G和B组件。

第一个问题可能导致崩溃。第二个 - 介绍视觉工件。其余的东西减慢了。

答案 1 :(得分:0)

@Laubzega

感谢您的线索!最后我得到了解决方案除了你的第一点,即检查上限,我还应该更改java中的代码以正确发送(x,y)像素位置,如下所示:

for(int y=0; y < height; y++){
    for(int x=0; x < width; x++, i++){
        pixelIndices[i] = (x << 16) | y ;
    }
}

现在应用程序正常运行而没有任何崩溃!!