0

I´m trying to resize a drawable, with a scale which is only in rare times a value which could be stored as an integer. Currently i´m using this:

private BitmapDrawable getCustomMarker(float scale){
    Bitmap originalMarker = BitmapFactory.decodeResource(this.getResources(), R.drawable.zone);
    int width = originalMarker.getWidth();
    int height = originalMarker.getHeight();

    Matrix matrix = new Matrix();
    matrix.postScale(scale, scale);

    Bitmap bitmap = Bitmap.createBitmap(originalMarker, 0, 0, width, height, matrix, true);


    BitmapDrawable bm = new BitmapDrawable(bitmap);
    bm.setBounds(0,0,bitmap.getWidth(),bitmap.getHeight());
    return bm;  
}

but every now and then it throws an OutOfMemoryError.... Sometimes when i want to change the scale to something > 1, but also when i want to scale it down to something < 1.

06-22 13:51:41.700: E/dalvikvm-heap(15021): Out of memory on a 10035216-byte allocation.
06-22 13:51:41.700: I/dalvikvm(15021): "main" prio=5 tid=1 RUNNABLE
06-22 13:51:41.700: I/dalvikvm(15021):   | group="main" sCount=0 dsCount=0 obj=0x401c75a8 self=0x12690
06-22 13:51:41.700: I/dalvikvm(15021):   | sysTid=15021 nice=0 sched=0/0 cgrp=default handle=-1342909336
06-22 13:51:41.700: I/dalvikvm(15021):   | schedstat=( 12261804000 820393000 4881 ) utm=1121 stm=105 core=0
06-22 13:51:41.700: I/dalvikvm(15021):   at android.graphics.Bitmap.nativeCreate(Native Method)
06-22 13:51:41.700: I/dalvikvm(15021):   at android.graphics.Bitmap.createBitmap(Bitmap.java:604)
06-22 13:51:41.700: I/dalvikvm(15021):   at android.graphics.Bitmap.createBitmap(Bitmap.java:551)
06-22 13:51:41.700: I/dalvikvm(15021):   at android.graphics.Bitmap.createScaledBitmap(Bitmap.java:437)
06-22 13:51:41.700: I/dalvikvm(15021):   at m.p.Activitys.GeoFancingActivity.getCustomMarker(GeoFancingActivity.java:61)
06-22 13:51:41.700: I/dalvikvm(15021):   at m.p.Activitys.GeoFancingActivity.adjustFanceScale(GeoFancingActivity.java:254)
06-22 13:51:41.700: I/dalvikvm(15021):   at m.p.Activitys.GeoFancingActivity.dispatchTouchEvent(GeoFancingActivity.java:194)
06-22 13:51:41.700: I/dalvikvm(15021):   at com.android.internal.policy.impl.PhoneWindow$DecorView.dispatchTouchEvent(PhoneWindow.java:1835)
06-22 13:51:41.700: I/dalvikvm(15021):   at android.view.View.dispatchPointerEvent(View.java:4694)
06-22 13:51:41.700: I/dalvikvm(15021):   at android.view.ViewRoot.deliverPointerEvent(ViewRoot.java:2419)
06-22 13:51:41.700: I/dalvikvm(15021):   at android.view.ViewRoot.handleMessage(ViewRoot.java:2080)
06-22 13:51:41.700: I/dalvikvm(15021):   at android.os.Handler.dispatchMessage(Handler.java:99)
06-22 13:51:41.700: I/dalvikvm(15021):   at android.os.Looper.loop(Looper.java:132)
06-22 13:51:41.700: I/dalvikvm(15021):   at android.app.ActivityThread.main(ActivityThread.java:4126)
06-22 13:51:41.700: I/dalvikvm(15021):   at java.lang.reflect.Method.invokeNative(Native Method)
06-22 13:51:41.700: I/dalvikvm(15021):   at java.lang.reflect.Method.invoke(Method.java:491)
06-22 13:51:41.700: I/dalvikvm(15021):   at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:844)
06-22 13:51:41.700: I/dalvikvm(15021):   at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:602)
06-22 13:51:41.700: I/dalvikvm(15021):   at dalvik.system.NativeStart.main(Native Method)
06-22 13:51:41.700: D/AndroidRuntime(15021): Shutting down VM
06-22 13:51:41.700: W/dalvikvm(15021): threadid=1: thread exiting with uncaught exception (group=0x401c0760)
06-22 13:51:41.700: E/AndroidRuntime(15021): FATAL EXCEPTION: main
06-22 13:51:41.700: E/AndroidRuntime(15021): java.lang.OutOfMemoryError
06-22 13:51:41.700: E/AndroidRuntime(15021):    at android.graphics.Bitmap.nativeCreate(Native Method)
06-22 13:51:41.700: E/AndroidRuntime(15021):    at android.graphics.Bitmap.createBitmap(Bitmap.java:604)
06-22 13:51:41.700: E/AndroidRuntime(15021):    at android.graphics.Bitmap.createBitmap(Bitmap.java:551)
06-22 13:51:41.700: E/AndroidRuntime(15021):    at android.graphics.Bitmap.createScaledBitmap(Bitmap.java:437)
06-22 13:51:41.700: E/AndroidRuntime(15021):    at m.p.Activitys.GeoFancingActivity.getCustomMarker(GeoFancingActivity.java:61)
06-22 13:51:41.700: E/AndroidRuntime(15021):    at m.p.Activitys.GeoFancingActivity.adjustFanceScale(GeoFancingActivity.java:254)
06-22 13:51:41.700: E/AndroidRuntime(15021):    at m.p.Activitys.GeoFancingActivity.dispatchTouchEvent(GeoFancingActivity.java:194)
06-22 13:51:41.700: E/AndroidRuntime(15021):    at com.android.internal.policy.impl.PhoneWindow$DecorView.dispatchTouchEvent(PhoneWindow.java:1835)
06-22 13:51:41.700: E/AndroidRuntime(15021):    at android.view.View.dispatchPointerEvent(View.java:4694)
06-22 13:51:41.700: E/AndroidRuntime(15021):    at android.view.ViewRoot.deliverPointerEvent(ViewRoot.java:2419)
06-22 13:51:41.700: E/AndroidRuntime(15021):    at android.view.ViewRoot.handleMessage(ViewRoot.java:2080)

I also tried to use Bitmap.createScaledBitmap(), but it also creates this error.

Bitmap.createScaledBitmap(originalMarker, Math.round(originalMarker.getWidth() * scale), Math.round(originalMarker.getHeight() * scale), true)

I found that one can solve this problem by using the BitmapFactory instead of Bitmap. But the creation-methods of it support only scales with the datatype integer. But i need the scale as a float.

Do you have any suggestions how to solve this issue?

Community
  • 1
  • 1
CAA
  • 968
  • 10
  • 27
  • float? can't you just cast float to integer, see this link http://blog.androidquery.com/2011/05/down-sample-images-to-avoid-out-of.html – max4ever Jun 22 '12 at 12:38
  • argh >.< uhm, where am i casting from float to int? – CAA Jun 22 '12 at 12:45

1 Answers1

1

A bitmap is simply an array of color values, hence the size in bytes of a bitmap is the "size" of a pixel (which depends on the bitmap format) multiplied by width and by height, which must be integer values: the indices to access elements in an array are always integers, aren't they? And the size of an array is always an integer, of course. That's why you need to supply two integers to create a bitmap. Your second attempt is the right choice, you only need to compute the values for width and height such as they stay reasonably low. As far as I can tell, your app crashed in trying to allocate a 10MB image, which in fact is a very big one. If you need to load a huge background, maybe you'll have to split it in small chunks and loaded a tile at a time when needed.

Don't forget to call Bitmap.recycle() when you're done to free native memory, otherwise your app will likely crash.

Raffaele
  • 20,627
  • 6
  • 47
  • 86