在我的项目中,我采用15x15的随机颜色位图,并确定每个像素与其他像素的区别。
调用Distinct.start()时,出现以下错误:
A/libc(18416): Fatal signal 11 (SIGSEGV) at 0x00000038 (code=1), thread 18538 (AsyncTask #1)
从我能够找到的信号11可以看出我试图非法访问内存,但我无法找到它的位置。我甚至尝试从脚本中删除所有内容,除了结果的实例化并返回它。
distinct.rs:
#pragma version(1)
#pragma rs java_package_name(com.moffitj.horizon)
#pragma rs_fp_relaxed
rs_allocation image;
int imgSize;
int side;
float __attribute__((kernel)) root(float in, uint32_t x, uint32_t y){
//where we'll store the cumulative distance for the current pixel
float result = 0.0f;
//Pull the current pixel and unpack it's componants
const uchar4 current = *(const uchar4*)rsGetElementAt(image, (y * side) + x, 0);
float4 currentPixel = rsUnpackColor8888(current);
//find how distinct the current pixel is from all others (and self, to save a branch)
for(int i = 0; i < imgSize; i++){
//get the next pixel and uppack it
const uchar4 pixel = *(const uchar4*)rsGetElementAt(image, i, 0);
float4 unpackedPixel = rsUnpackColor8888(pixel);
//compare the distance between the two pixels
float4 temp = sqrt(pow(currentPixel - unpackedPixel,2));
//add the difference to the running total
result += (temp.w + temp.x + temp.y + temp.z);
}
result /= imgSize;
return result;
}
distinct.java:
public class Distinct {
private Allocation mBitmapAllocation;
private Allocation mReferenceAllocation;
private Allocation mResultAllocation;
private int mImgSize;
private int mNumBlocks;
private RenderScript mRS;
private Context mContext;
private ScriptC_distinct mScript;
private Bitmap mBitmap;
/**
*
* @param bitmap
* @throws IllegalArgumentException if the bitmap is not square or divisible by 64
*/
public Distinct(Bitmap bitmap, Context context) throws IllegalArgumentException {
mBitmap = bitmap;
mContext = context;
mImgSize = bitmap.getHeight() * bitmap.getWidth();
mRS = RenderScript.create(mContext);
mBitmapAllocation = Allocation.createFromBitmap(mRS, bitmap, Allocation.MipmapControl.MIPMAP_NONE, Allocation.USAGE_SCRIPT);
Type.Builder referenceBuilder = new Type.Builder(mRS, Element.F32(mRS));//Dummy data won't be used, just to get location once inside script
referenceBuilder.setX(bitmap.getWidth());
referenceBuilder.setY(bitmap.getHeight());
Type type = referenceBuilder.create();
mReferenceAllocation = Allocation.createTyped(mRS, type, Allocation.USAGE_SCRIPT);
Type.Builder resultBuilder = new Type.Builder(mRS, Element.F32(mRS));
resultBuilder.setX(bitmap.getWidth());
resultBuilder.setY(bitmap.getHeight());
Type resultType = resultBuilder.create();
mResultAllocation = Allocation.createTyped(mRS, resultType, Allocation.USAGE_SCRIPT);
/*Type.Builder imgTypeBuilder = new Type.Builder(mRS, Element.I32(mRS));
imgTypeBuilder.setX(mImgSize * mImgSize);
imgTypeBuilder.setY(1);
Type imgType = imgTypeBuilder.create();
mBitmapAllocation = Allocation.createTyped(mRS, imgType, Allocation.USAGE_SCRIPT);*/
mScript = new ScriptC_distinct(mRS, mContext.getResources(), R.raw.average);
mScript.set_image(mBitmapAllocation);
mScript.set_imgSize(mImgSize);
mScript.set_side(bitmap.getHeight());
}
public void start(){
mScript.forEach_root(mReferenceAllocation, mResultAllocation);
}
答案 0 :(得分:4)
您的错误来自:
rsGetElementAt(image, (y * side) + x, 0);
您假设位图的布局允许您以这种方式对其进行索引,但这实际上是未定义的行为。您应该为rsGetElementAt()的x和y部分使用适当的索引。我还建议你切换到性能更高的rsGetElementAt_uchar4()函数(对于所有的原始/矢量类型都存在这样的帮助器)。此函数将直接返回uchar4,因此无需转换指针并取消引用它。
我的另一个建议是尝试使用调试运行时来发现这些边界错误。只需将标志添加到上面的create()调用中:
RenderScript.create(mContext, RenderScript.ContextType.DEBUG);
错误/警告将显示在adb logcat下。