2014-04-17 44 views
0

我想为我的Android照片编辑器应用添加模糊功能。到目前为止,我在Cpp中提供了以下代码以提高速度和效率。Android JNI镜头模糊

class JniBitmap 
{ 
    public: 
    uint32_t* _storedBitmapPixels; 
    AndroidBitmapInfo _bitmapInfo; 
    JniBitmap() 
    { 
     _storedBitmapPixels = NULL; 
    } 
}; 

JNIEXPORT void JNICALL Java_com_myapp_utils_NativeBitmapOperations_jniBlurBitmap(JNIEnv * env, jobject obj, jobject handle, uint32_t radius) 
{ 
    JniBitmap* jniBitmap = (JniBitmap*) env->GetDirectBufferAddress(handle); 
    if (jniBitmap->_storedBitmapPixels == NULL) return; 

    uint32_t width = jniBitmap->_bitmapInfo.width; 
    uint32_t height = jniBitmap->_bitmapInfo.height; 
    uint32_t* previousData = jniBitmap->_storedBitmapPixels; 
    uint32_t* newBitmapPixels = new uint32_t[width * height]; 

    // Array to hold totalRGB 
    uint8_t totalRGB[3]; 
    uint8_t Pixel_col[3]; 

    uint32_t Pixel_col; 
    int x, y, kx, ky; 
    uint8_t tmp; 

    for (y=0; y<height; y++) 
    { 
    for (x=0; x<width; x++) 
    { 
     // Colour value RGB 
     totalRGB[0] = 0.0; 
     totalRGB[1] = 0.0; 
     totalRGB[2] = 0.0; 

     for (ky=-radius; ky<=radius; ky++) 
     { 
     for (kx=-radius; kx<=radius; kx++) 
     { 
      // Each pixel position 
      pPixel_col = previousData[(y + ky) * width + x + kx]; 
      totalRBG[0] += (Pixel_col & 0xFF0000) >> 16; 
      totalRBG[1] += (Pixel_col & 0x00FF00) >> 8; 
      totalRBG[2] += Pixel_col & 0x0000FF; 
     } 
     } 


     tmp = (radius * 2 + 1) * (radius * 2 + 1); 
     totalRGB[0] += tmp; 
     totalRGB[1] += tmp; 
     totalRGB[2] += tmp; 
     pPixel_col = totalRGB[0] << 16 + totalRGB[1] << 8 + totalRGB[2]; 

     newBitmapPixels[y * width + x] = pPixel_col; 
    } 
    } 

    delete[] previousData; 
    jniBitmap->_storedBitmapPixels = newBitmapPixels; 
} 

我已经成功unsing最新Android NDK版本编译它。

在我的Android应用程序,我得到这个Java代码来调用本地方法:

private ByteBuffer handler = null; 

static 
{ 
    System.loadLibrary("JniBitmapOperationsLibrary"); 
} 

private native void jniBlurBitmap(ByteBuffer handler, final int radius); 

public void blurBitmap(final int radius) 
{ 
    if (handler == null) return; 
    jniBlurBitmap(handler, radius); 
} 

当我试图从我的应用程序中调用它,它提供了一个空白的画面。我做错了什么?

PS:我在我的JNI文件中也有一个裁剪和缩放方法,它们完美地工作。这可能是我的Blur algorithm的问题。

+0

你明白为什么图像是空白的?我遇到了同样的问题,我认为这都是因为像素基本转换为ARGB值(按位操作的“游戏”)。 –

+0

是的。更改'pPixel_col = totalRGB [0] << 16 + totalRGB [1] << 8 + totalRGB [2];'到'pPixel_col = totalRGB [0] << 16 | totalRGB [1] << 8 | totalRGB [2];' – Manitoba

+0

这是关于从RGB值到单一值的转换。你能告诉我如何做相反的事吗?我觉得我做错了什么。这是我做的一篇文章,我认为这是我的代码中的问题:http://stackoverflow.com/questions/23230047/trying-to-convert-bilinear-interpolation-code-from-java-to-cc -on-android –

回答

0

最后,我找到了最快的方法来做到这一点。起初,我制作了一个JNI脚本,但Android支持V8的方式显然更快(大约10次)。

  • 从目录SDK/build-tools/android-4.4.2/renderscript/lib/添加库.so文件。将renderscript-v8.jar复制到您的libs文件夹并将packaged内容复制到您的jni文件夹中。

  • 使用此代码

    public static Bitmap getBlurredBitmap(Context context, Bitmap bm, int radius) 
    { 
        if (bm == null) return null; 
    
        if (radius < 1) radius = 1; 
        if (radius > 25) radius = 25; 
    
        Bitmap outputBitmap = Bitmap.createBitmap(bm); 
    
        RenderScript rs = RenderScript.create(context); 
        ScriptIntrinsicBlur theIntrinsic = ScriptIntrinsicBlur.create(rs, Element.U8_4(rs)); 
        Allocation tmpIn = Allocation.createFromBitmap(rs, bm); 
        Allocation tmpOut = Allocation.createFromBitmap(rs, outputBitmap); 
        theIntrinsic.setRadius(radius); 
        theIntrinsic.setInput(tmpIn); 
        theIntrinsic.forEach(tmpOut); 
        tmpOut.copyTo(outputBitmap); 
    
        return outputBitmap; 
    } 
    
+0

这不是镜头模糊! – user65721