java - 如何使用浮点而不是整数缩放位图,而不出现内存不足错误?

标签 java android image-scaling

我正在尝试调整可绘制对象的大小,其比例仅在极少数情况下是可以存储为整数的值。目前我正在使用这个:

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

但它时不时地会抛出 OutOfMemoryError...有时当我想将比例更改为 > 1 时,但有时当我想将其缩小到 < 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)

我也尝试使用 Bitmap.createScaledBitmap(),但它也会产生此错误。

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

我发现可以通过使用BitmapFactory来解决这个问题而不是位图。但它的创建方法仅支持数据类型整数的缩放。但我需要将秤作为浮子。

您对如何解决这个问题有什么建议吗?

最佳答案

位图只是一个颜色值数组,因此位图的字节大小是像素的“大小”(取决于位图格式)乘以宽度和高度,这必须是整数值:访问数组中元素的索引始终是整数,不是吗?当然,数组的大小始终是整数。这就是为什么您需要提供两个整数来创建位图。您的第二次尝试是正确的选择,您只需要计算宽度和高度的值,例如它们保持相当低的值。据我所知,您的应用程序在尝试分配 10MB 图像时崩溃了,这实际上是一个非常大的图像。如果您需要加载巨大的背景,也许您必须将其分成小块,并在需要时一次加载一个图 block 。

释放 native 内存后,不要忘记调用 Bitmap.recycle(),否则您的应用可能会崩溃。

关于java - 如何使用浮点而不是整数缩放位图,而不出现内存不足错误?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/11155841/

相关文章:

java - 如何用 "@"替换所有空行?

java - 这个 sum() 究竟是如何工作的?

opencv - OpenCV 上的 resize 函数有什么问题?

java - 我的涉及 JFrame 的代码有什么问题

java - 在找到解决方案之前 BFS 队列为空

java - 从 tabhost 中删除选项卡会导致应用程序崩溃

android - 如何使用按钮实现自定义 ListView 行?

Android 录制方 block 视频并拼接

epub - ePub 封面的正确图像尺寸是多少?