0

I have a function that take a bitmap, two colors and return a BitmapDrawable :

// Theme function
    static public BitmapDrawable pFilter(Bitmap bitmap, int backgroundColor, int foregroundColor)
{

    Bitmap bitmapCopy = Bitmap.createBitmap(bitmap, 0, 0, bitmap.getWidth(), bitmap.getHeight(), null, true);

    int[] pixels = new int[bitmapCopy.getByteCount()]; 

    bitmapCopy.getPixels(pixels, 0, bitmapCopy.getWidth(), 0, 0, bitmapCopy.getWidth(), bitmapCopy.getHeight());

    // Call native function

    bitmapCopy.setPixels(pixels, 0, bitmapCopy.getWidth(), 0, 0, bitmapCopy.getWidth(), bitmapCopy.getHeight());

    BitmapDrawable finalDrawable = new BitmapDrawable(Application.getAppContext().getResources(), bitmapCopy);

    return finalDrawable;
}

// Custom Imageview
public class CustomImageView extends ImageView 
{

private BitmapDrawable sourceImage;

private CustomTheme theme;

// [...]

private void refreshImageView()
{

  super.setImageDrawable(theme.pFilter(sourceImage.getBitmap(), theme.backgroundColor, theme.foregroundColor));

}

My problem is that after about 80 calls to this function (with 10px*10px bitmaps), I get a OutOfMemory exception on this line :

int[] pixels = new int[bitmapCopy.getByteCount()]; 

Thanks.

Florian Mac Langlade
  • 1,863
  • 7
  • 28
  • 57

2 Answers2

0

after calling the pFilter(??); call bitmap.recycle(); on the orignal bitmap

hepizoj
  • 243
  • 4
  • 9
  • I get an error : java.lang.IllegalArgumentException: Cannot draw recycled bitmaps – Florian Mac Langlade Mar 28 '14 at 10:02
  • the original bitmap is still displayed on the imageView right? try to replace it with something else before calling recycle. – hepizoj Mar 28 '14 at 10:11
  • Yes, take a look of my code : BitmapDrawable finalDrawable = new BitmapDrawable(Application.getAppContext().getResources(), bitmapCopy); – Florian Mac Langlade Mar 28 '14 at 10:12
  • My theme class don't know my ImageView... So, when and where must I call the recyle ? In the CustomImgeView's finalize ? – Florian Mac Langlade Mar 28 '14 at 10:19
  • Bitmap oldBitmap = sourceImage.getBitmap(); sourceImage=theme.pFilter(oldBitmap); super.setImageDrawable(theme.pFilter(oldBitmap, theme.backgroundColor, theme.foregroundColor)); postDelayed(new Runnable() { @Override public void run() { oldBitmap.recycle(); } }, 20); – hepizoj Mar 28 '14 at 10:25
  • The sourceBitmap is never cleared ? And why are you using a delay ? – Florian Mac Langlade Mar 28 '14 at 10:34
  • Recycle do nothing, System.gc too. I've also try to use WeakReference : do nothing. In the DDMS view I can see my object, never cleared... – Florian Mac Langlade Mar 31 '14 at 09:24
0

The error was in my JNI call, not in Android :

(*env)->ReleaseIntArrayElements(env, pixels, nativePixels, JNI_COMMIT);

JNI_COMMIT : copy back the content but do not free the elems buffer

The solution is to use 0 instead of JNI_COMMIT :

(*env)->ReleaseIntArrayElements(env, pixels, nativePixels, 0);
Florian Mac Langlade
  • 1,863
  • 7
  • 28
  • 57