2015-07-12 54 views
0

我正在KitKat(4.4)中开发一个应用程序,并且最近在我的设备(5.1)上闪动了棒棒糖。我的RenderScript代码似乎已经“破损”了。我的意思是它编译得很好,但是当我启动应用程序时,它并没有做它应该做的事情。我用它来并行执行边缘检测,但它没有做任何事情。以前在KitKat上我可以看到边缘。现在它呈现相机看到的东西,没有效果,没有边缘检测。RenderScript停止在Android Lollilop中工作

这里是我的应用程序清单:

<?xml version="1.0" encoding="utf-8"?> 
<manifest xmlns:android="http://schemas.android.com/apk/res/android" 
    package="foo.bar" 
    android:versionCode="1" 
    android:versionName="1.0" > 

    <uses-sdk android:minSdkVersion="9" /> 

    <uses-feature android:name="android.hardware.camera" /> 

    <uses-permission android:name="android.permission.CAMERA" /> 
    <uses-permission android:name="android.hardware.camera.autofocus" /> 
    <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" /> 
    <!--uses-permission android:name="android.permission.INTERNET" /> 
    <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" /--> 

    <application 
     android:icon="@drawable/ic_launcher" 
     android:label="@string/app_name" > 
     <activity 
      android:label="@string/app_name" 
      android:name=".LiveCameraActivity" 
      android:screenOrientation="sensorLandscape" > 
      <intent-filter > 
       <action android:name="android.intent.action.MAIN" /> 

       <category android:name="android.intent.category.LAUNCHER" /> 
      </intent-filter> 
     </activity> 
    </application> 

</manifest> 

这里是我的应用程序gradle这个build.gradle文件:

apply plugin: 'com.android.application' 

android { 
    compileSdkVersion 19 
    buildToolsVersion '19.1.0' 

    defaultConfig { 
     applicationId "foo.bar" 
     minSdkVersion 15 
     targetSdkVersion 19 
     versionCode 1 
     versionName "1.0" 

     renderscriptTargetApi 19 
     renderscriptSupportModeEnabled true //not applicable for rs targetapi 21+ 
    } 
    buildTypes { 
     release { 
      minifyEnabled false 
      proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' 
     } 
    } 
} 

或多或少这是我打电话给我的renderScript代码:

我将所有我的renderscript(.rs)文件放在main下的rs文件夹下。

而且在Java中:

bmp = mTextureView.getBitmap(); 
bmpCopy = bmp.copy(bmp.getConfig(),true); //create a copy of the original 
bitmapProcessor.processBmpEdgeDetect(bmp, bmpCopy); //I think this is where it breaks 
mImageView.setImageBitmap(bmpCopy); // render result 

现在bitmapProcessor.processBmpEdgeDetect()有这样的:

renderScriptEdgeDetectWrapper = new RenderScriptEdgeDetectWrapper(ctx); 
renderScriptAvgOperWrapper.setInAllocation(bmp); 
renderScriptAvgOperWrapper.setOutAllocation(bmpCopy); 
renderScriptAvgOperWrapper.setScriptWidth(bmp.getWidth()-1); 
renderScriptAvgOperWrapper.setScriptHeight(bmp.getHeight()-1); 
renderScriptAvgOperWrapper.forEach_root(); 

而且我renderScriptAvgOperWrapper基本上是这样的:

public class RenderScriptEdgeDetectWrapper { 

    private Allocation inAllocation; 
    private Allocation outAllocation; 
    private RenderScript rs; 
    private ScriptC_edgedetect edgeDetectScript; 
    private Context ctx; 


    public RenderScriptEdgeDetectWrapper(Context context){ 
     ctx = context; 
     rs = RenderScript.create(ctx); 
     edgeDetectScript = new ScriptC_edgedetect(rs, ctx.getResources(), R.raw.edgedetect); 
    }; 

    public void setInAllocation(Bitmap bmp){ 
     inAllocation = Allocation.createFromBitmap(rs,bmp); 
     edgeDetectScript.set_inPixels(inAllocation); 
    }; 

    public void setOutAllocation(Bitmap bmp){ 
     outAllocation = Allocation.createFromBitmap(rs,bmp); 
    }; 

    public void setScriptWidth(int scriptWidth) { 
     edgeDetectScript.set_width(scriptWidth); 
    } 

    public void setScriptHeight(int scriptHeight) { 
     edgeDetectScript.set_height(scriptHeight); 
    } 

    public void forEach_root(){ 
     edgeDetectScript.forEach_root(inAllocation,outAllocation); 
    } 
} 

这只是一个简单的包装。

最后我的renderScript edgedetect.rs文件是这样的:

#pragma version(1) 
#pragma rs java_package_name(foo.bar) 

rs_allocation inPixels; 
int height; 
int width; 

void root(const uchar4 *in, uchar4 *out, uint32_t x, uint32_t y) { 
    float3 pixel = convert_float4(in[0]).rgb; 

    if(x==0 || x==width || y==0 || y==height){ 
     pixel.r = 0; 
     pixel.g = 191; 
     pixel.b = 255; 
    }else{ //do image processing here 

     float3 pixelNH = convert_float4(rsGetElementAt_uchar4(inPixels, x+1, y)).rgb; 
     float3 pixelNV = convert_float4(rsGetElementAt_uchar4(inPixels, x, y+1)).rgb; 

     int grayAvg = (pixel.r + pixel.g + pixel.b)/3; 
     int grayAvgNH = (pixelNH.r + pixelNH.g + pixelNH.b)/3; 
     int grayAvgNV = (pixelNV.r + pixelNV.g + pixelNV.b)/3; 

     int edgeOperatorValue = 2*grayAvg - grayAvgNH - grayAvgNV; 

     if(edgeOperatorValue < 0){ 
      edgeOperatorValue = -1 * edgeOperatorValue; 
     }; 

     pixel.r = edgeOperatorValue; 
     pixel.g = edgeOperatorValue; 
     pixel.b = edgeOperatorValue; 
    }; 

    out->xyz = convert_uchar3(pixel); 
} 

现在我不明白为什么这个代码在奇巧工作得很好,但在棒棒糖完全失败。如果你能指导什么是错的,那会很好。谢谢。

回答

1

当您使用renderScriptAvgOperWrapper调用forEach时,实际上并不会将生成的输出Allocation复制回您正在绘制的位图中。您需要在forEach之后执行明确的“Allocation.copyTo(Bitmap)”操作。分配应该是您刚刚编写的输出分配,而位图是您想要绘制的分配。

+0

为什么在kitkat中工作?... –

+0

如果发生零复制(即共享后备缓冲区),它可以工作。在那种情况下,copyTo()将不会执行任何操作。如果它不是零拷贝(即USAGE_SHARED),则必须copyTo()才能更新缓冲区。 –