Question

I want to add a blur feature to my Android photo editor app. So far, I've made the following code in Cpp to improve speed and efficiency.

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;
}

I've compiled it with success unsing the latest Android NDK version.

In my Android application, I got this Java code to call the native method:

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);
}

When I try to call it from my application it gives a blank picture. Did I make something wrong ?

PS: I also have a crop and scale method in my JNI files and they work perfectly. It might be an issue with my Blur algorithm.

Was it helpful?

Solution

Finally, I found the fastest way to do that. At first, I made a JNI script but the Android Support V8 way is clearly faster (About 10 times).

  • Add the library AND the .so files from the directory SDK/build-tools/android-4.4.2/renderscript/lib/. Copy renderscript-v8.jar to your libs folder and the packaged content to your jni folder.

  • Use this code

    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;
    }
    
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top