奇怪的内存不足的问题,同时加载图像为位图对象 [英] Strange out of memory issue while loading an image to a Bitmap object

查看:359
本文介绍了奇怪的内存不足的问题,同时加载图像为位图对象的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个列表视图每行的一对夫妇的图像按钮。当您单击列表行,它推出了新的活动。我不得不打造,因为一个问题相机的布局我自己的选项卡。这被推出了成果的活动是一张地图。如果我点击我的按钮启动图像preVIEW(加载图像关闭SD卡)的活动回到列表视图活动结果处理应用程序返回到重新启动我的新的活动比的图像而已窗口小部件。

在列表中查看图像preVIEW正在做与鼠标和 ListAdapter 。这使得它pretty的简单,但我不知道我怎么可以把调整后的图像(即更小的位大小不是像素的SRC在飞行的图像按钮。所以,我只是调整了来到了手机的图像摄像头。

问题是,我得到一个内存不足的错误当它试图回去,然后重新启动第二届活动。

**有没有一种方法,我可以很容易地生成列表适配器按行,在那里我可以在飞行中(逐位)调整排?这将是preferable,因为我还需要进行一些更改,每行中的小部件/元素的属性,因为我无法选择一排,因为焦点问题触摸屏。 (我可以使用滚球)。

**我知道我可以做一个带外调整大小和保存我的形象,但是这并不是我真正想做的事情,但有些样品$ C $下,这将是很好的。

当我关闭它好起来的工作列表视图中的图像。

FYI:这就是我是如何做的:

 的String []从=新的String [] {DBHelper.KEY_BUSINESSNAME,
                               DBHelper.KEY_ADDRESS,
                               DBHelper.KEY_CITY,
                               DBHelper.KEY_GPSLONG,
                               DBHelper.KEY_GPSLAT,
                               DBHelper.KEY_IMAGEFILENAME +};
INT []到=新INT [] {R.id.businessname,
                       R.id.address,
                       R.id.city,
                       R.id.gpslong,
                       R.id.gpslat,
                       R.id.imagefilename};
注释=新SimpleCursorAdapter(这一点,R.layout.notes_row,C,从,到);
setListAdapter(票据);
 

其中, R.id.imagefilename 按钮画面

下面是我的LogCat中:


  5月1日至25日:05:49.877:ERROR / dalvikvm堆(3896):6291456字节外部分配太大,此过程。
5月1号至25日:05:49.877:ERROR /(3896):虚拟机不会让我们分配6291456字节
5月1号至25日:05:49.877:ERROR / AndroidRuntime(3896):未捕获的处理程序:螺纹主力退出,由于未捕获的异常
5月1号至25日:05:49.917:ERROR / AndroidRuntime(3896):java.lang.OutOfMemoryError:位图大小超过VM预算
5月1号至25日:05:49.917:ERROR / AndroidRuntime(3896):在android.graphics.BitmapFactory.nativeDe codeStream(本机方法)
5月1号至25日:05:49.917:ERROR / AndroidRuntime(3896):在android.graphics.BitmapFactory.de codeStream(BitmapFactory.java:304)
5月1号至25日:05:49.917:ERROR / AndroidRuntime(3896):在android.graphics.BitmapFactory.de codeFILE(BitmapFactory.java:149)
5月1号至25日:05:49.917:ERROR / AndroidRuntime(3896):在android.graphics.BitmapFactory.de codeFILE(BitmapFactory.java:174)
5月1号至25日:05:49.917:ERROR / AndroidRuntime(3896):在android.graphics.drawable.Drawable.createFromPath(Drawable.java:729)
5月1号至25日:05:49.917:ERROR / AndroidRuntime(3896):在android.widget.ImageView.resolveUri(ImageView.java:484)
5月1号至25日:05:49.917:ERROR / AndroidRuntime(3896):在android.widget.ImageView.setImageURI(ImageView.java:281)
5月1号至25日:05:49.917:ERROR / AndroidRuntime(3896):在android.widget.SimpleCursorAdapter.setViewImage(SimpleCursorAdapter.java:183)
5月1号至25日:05:49.917:ERROR / AndroidRuntime(3896):在android.widget.SimpleCursorAdapter.bindView(SimpleCursorAdapter.java:129)
5月1号至25日:05:49.917:ERROR / AndroidRuntime(3896):在android.widget.CursorAdapter.getView(CursorAdapter.java:150)
5月1号至25日:05:49.917:ERROR / AndroidRuntime(3896):在android.widget.AbsListView.obtainView(AbsListView.java:1057)
5月1号至25日:05:49.917:ERROR / AndroidRuntime(3896):在android.widget.ListView.makeAndAddView(ListView.java:1616)
5月1号至25日:05:49.917:ERROR / AndroidRuntime(3896):在android.widget.ListView.fillSpecific(ListView.java:1177)
5月1号至25日:05:49.917:ERROR / AndroidRuntime(3896):在android.widget.ListView.layoutChildren(ListView.java:1454)
5月1号至25日:05:49.917:ERROR / AndroidRuntime(3896):在android.widget.AbsListView.onLayout(AbsListView.java:937)
5月1号至25日:05:49.917:ERROR / AndroidRuntime(3896):在android.view.View.layout(View.java:5611)
5月1号至25日:05:49.917:ERROR / AndroidRuntime(3896):在android.widget.LinearLayout.setChildFrame(LinearLayout.java:1119)
5月1号至25日:05:49.917:ERROR / AndroidRuntime(3896):在android.widget.LinearLayout.layoutHorizo​​ntal(LinearLayout.java:1108)
5月1号至25日:05:49.917:ERROR / AndroidRuntime(3896):在android.widget.LinearLayout.onLayout(LinearLayout.java:922)
5月1号至25日:05:49.917:ERROR / AndroidRuntime(3896):在android.view.View.layout(View.java:5611)
5月1号至25日:05:49.917:ERROR / AndroidRuntime(3896):在android.widget.FrameLayout.onLayout(FrameLayout.java:294)
5月1号至25日:05:49.917:ERROR / AndroidRuntime(3896):在android.view.View.layout(View.java:5611)
5月1号至25日:05:49.917:ERROR / AndroidRuntime(3896):在android.widget.LinearLayout.setChildFrame(LinearLayout.java:1119)
5月1号至25日:05:49.917:ERROR / AndroidRuntime(3896):在android.widget.LinearLayout.layoutVertical(LinearLayout.java:999)
5月1号至25日:05:49.917:ERROR / AndroidRuntime(3896):在android.widget.LinearLayout.onLayout(LinearLayout.java:920)
5月1号至25日:05:49.917:ERROR / AndroidRuntime(3896):在android.view.View.layout(View.java:5611)
5月1号至25日:05:49.917:ERROR / AndroidRuntime(3896):在android.widget.FrameLayout.onLayout(FrameLayout.java:294)
5月1号至25日:05:49.917:ERROR / AndroidRuntime(3896):在android.view.View.layout(View.java:5611)
5月1号至25日:05:49.917:ERROR / AndroidRuntime(3896):在android.view.ViewRoot.performTraversals(ViewRoot.java:771)
5月1号至25日:05:49.917:ERROR / AndroidRuntime(3896):在android.view.ViewRoot.handleMessage(ViewRoot.java:1103)
5月1号至25日:05:49.917:ERROR / AndroidRuntime(3896):在android.os.Handler.dispatchMessage(Handler.java:88)
5月1号至25日:05:49.917:ERROR / AndroidRuntime(3896):在android.os.Looper.loop(Looper.java:123)
5月1号至25日:05:49.917:ERROR / AndroidRuntime(3896):在android.app.ActivityThread.main(ActivityThread.java:3742)
5月1号至25日:05:49.917:ERROR / AndroidRuntime(3896):在java.lang.reflect.Method.invokeNative(本机方法)
5月1号至25日:05:49.917:ERROR / AndroidRuntime(3896):在java.lang.reflect.Method.invoke(Method.java:515)
5月1号至25日:05:49.917:ERROR / AndroidRuntime(3896):在com.android.internal.os.ZygoteInit $ MethodAndArgsCaller.run(ZygoteInit.java:739)
5月1号至25日:05:49.917:ERROR / AndroidRuntime(3896):在com.android.internal.os.ZygoteInit.main(ZygoteInit.java:497)
5月1号至25日:05:49.917:ERROR / AndroidRuntime(3896):在dalvik.system.NativeStart.main(本机方法)
5月1号至25日:10:01.127:ERROR / AndroidRuntime(3943):错误:线程附加失败
 


我还显示图像时,有一个新的错误:

  01-25 22:13:18.594:DEBUG / Skia的(4204):XXXXXXXXXXX JPEG错误20不正确的呼叫状态%D JPEG库
01-25 22:13:18.604:信息/的System.out(4204):resolveUri没有坏的位图网址:
01-25 22:13:18.694:ERROR / dalvikvm堆(4204):6291456字节外部分配太大,此过程。
01-25 22:13:18.694:ERROR /(4204):虚拟机不会让我们分配6291456字节
01-25 22:13:18.694:DEBUG / Skia的(4204):xxxxxxxxxxxxxxxxxxxx allocPixelRef失败
 

解决方案

Android的培训类,< A HREF =htt​​p://developer.android.com/training/displaying-bitmaps/index.html>显示位图的高效,提供了一些伟大的信息的理解和处理异常 java.lang.OutOfMemoryError:位图大小超过VM预算装载位图时


读取位图尺寸和类型

BitmapFactory 类提供了多种解码方式(德codeByteArray()德codeFILE()去创建一个位图codeResource()等) 从各种来源。您可根据您的影像数据源的最合适的德code方法。这些方法试图分配内存构造位图,因此可以很容易地导致内存不足例外。每种类型的德code方法,让您指定通过 BitmapFactory.Options 类解码选项的其他签名。在 inJustDe codeBounds 属性设置为同时解码避免了内存分配,返回为位图对象,但设置 outWidth outHeight outMimeType 。这种技术可以让你读取图像数据的尺寸和类型之前,位图的建设(和内存分配)。

  BitmapFactory.Options选项=新BitmapFactory.Options();
options.inJustDe codeBounds = TRUE;
BitmapFactory.de codeResource(getResources(),R.id.myimage,期权);
INT imageHeight = options.outHeight;
INT ImageWidth等= options.outWidth;
字符串IMAGETYPE = options.outMimeType;
 

要避免 java.lang.OutOfMemory 异常,检查一个位图的尺寸进行解码之前,除非你绝对信任的来源为你提供predictably大小舒适地可用的存储器内适合的图像数据。


加载一个缩小版到内存

现在,图像尺寸是已知的,它们可以被用来决定是否完整图像应该被装入存储器,或者如果一个子采样版本应加载代替。这里有一些因素需要考虑:

    加载完整的图像在内存中的
  • 在估计内存使用情况。
  • 的内存,你愿意承诺加载这一形象给您的应用程序的任何其它存储量的要求。
  • 目标的ImageView或UI组件的尺寸,该图像将被装入。
  • 在屏幕大小以及当前设备的密度。

例如,它不值得载入1024×768像素的图片到内存中,如果它最终将在显示在128x96像素的缩略图的ImageView

要告诉德codeR子采样图像,装载的缩小版到​​内存中,设置 inSampleSize BitmapFactory.Options 对象。例如,2048×1536分辨率的图像是德codeD与 inSampleSize 4产生大约512x384的位图。加载此到内存使用0.75MB,而不是12MB的完整映像(假设 ARGB_8888 的位图配置)。这里的一个方法来计算一个样本大小值是两个基于目标宽度和高度的功率:

 公共静态INT calculateInSampleSize(
        BitmapFactory.Options选项,INT reqWidth,诠释reqHeight){
    //原始高度和宽度的图像
    最终诠释身高= options.outHeight;
    最终诠释宽度= options.outWidth;
    INT inSampleSize = 1;

    如果(高度&GT; reqHeight ||宽度GT; reqWidth){

        最终诠释halfHeight =身高/ 2;
        最终诠释半宽度=宽度/ 2;

        //计算最大inSampleSize值是2的幂,并保持这两个
        //高度和宽度小于所需的高度和宽度。
        而((halfHeight / inSampleSize)&GT; reqHeight
                &功放;&安培; (半角/ inSampleSize)&GT; reqWidth){
            inSampleSize * = 2;
        }
    }

    返回inSampleSize;
}
 

  

注意:两个值的功率计算,因为去codeR使用   通过下舍入到最接近的2的幂,具体根据最终值    inSampleSize 文档。

要使用此方法,第一代code与 inJustDe codeBounds 设置为,通过传递的选项,然后C再次使用新的 inSampleSize 价值去$ C $和 inJustDe codeBounds 集以

 公共静态位图德codeSampledBitmapFromResource(资源RES,INT渣油,
    INT reqWidth,诠释reqHeight){

    //第一代code与inJustDe codeBounds = true来检查尺寸
    最后BitmapFactory.Options选项=新BitmapFactory.Options();
    options.inJustDe codeBounds = TRUE;
    BitmapFactory.de codeResource(RES,渣油,期权);

    //计算inSampleSize
    options.inSampleSize = calculateInSampleSize(选项,reqWidth,reqHeight);

    与inSampleSize集//德code位图
    options.inJustDe codeBounds = FALSE;
    返回BitmapFactory.de codeResource(RES,渣油,期权);
}
 

此方法可以很容易地加载任意大尺寸的位图转换为的ImageView 显示一个100×100像素的缩略图,如下面的示例code:

  mImageView.setImageBitmap(
    德codeSampledBitmapFromResource(getResources(),R.id.myimage,100,100));
 

您可以按照类似的过程去其他来源的code位图,根据需要替换相应的 BitmapFactory.de code * 方法。

I have a list view with a couple of image buttons on each row. When you click the list row, it launches a new activity. I have had to build my own tabs because of an issue with the camera layout. The activity that gets launched for result is a map. If I click on my button to launch the image preview (load an image off the SD card) the application returns from the activity back to the listview activity to the result handler to relaunch my new activity which is nothing more than an image widget.

The image preview on the list view is being done with the cursor and ListAdapter. This makes it pretty simple, but I am not sure how I can put a resized image (I.e. Smaller bit size not pixel as the src for the image button on the fly. So I just resized the image that came off the phone camera.

The issue is that I get an out of memory error when it tries to go back and re-launch the 2nd activity.

** Is there a way I can build the list adapter easily row by row, where I can resize on the fly (bit wise)? This would be preferable as I also need to make some changes to the properties of the widgets/elements in each row as I am unable to select a row with touch screen because of focus issue. (I can use roller ball.)

** I know I can do an out of band resize and save of my image, but that is not really what I want to do, but some sample code for that would be nice.

As soon as I disabled the image on the list view it worked fine again.

FYI: This is how I was doing it:

String[] from = new String[] { DBHelper.KEY_BUSINESSNAME,
                               DBHelper.KEY_ADDRESS,
                               DBHelper.KEY_CITY,
                               DBHelper.KEY_GPSLONG,
                               DBHelper.KEY_GPSLAT,
                               DBHelper.KEY_IMAGEFILENAME  + ""};
int[] to = new int[] { R.id.businessname,
                       R.id.address,
                       R.id.city,
                       R.id.gpslong,
                       R.id.gpslat,
                       R.id.imagefilename };
notes = new SimpleCursorAdapter(this, R.layout.notes_row, c, from, to);
setListAdapter(notes);

Where R.id.imagefilename is a ButtonImage.

Here is my LogCat:


01-25 05:05:49.877: ERROR/dalvikvm-heap(3896): 6291456-byte external allocation too large for this process.
01-25 05:05:49.877: ERROR/(3896): VM wont let us allocate 6291456 bytes
01-25 05:05:49.877: ERROR/AndroidRuntime(3896): Uncaught handler: thread main exiting due to uncaught exception
01-25 05:05:49.917: ERROR/AndroidRuntime(3896): java.lang.OutOfMemoryError: bitmap size exceeds VM budget
01-25 05:05:49.917: ERROR/AndroidRuntime(3896):     at android.graphics.BitmapFactory.nativeDecodeStream(Native Method)
01-25 05:05:49.917: ERROR/AndroidRuntime(3896):     at android.graphics.BitmapFactory.decodeStream(BitmapFactory.java:304)
01-25 05:05:49.917: ERROR/AndroidRuntime(3896):     at android.graphics.BitmapFactory.decodeFile(BitmapFactory.java:149)
01-25 05:05:49.917: ERROR/AndroidRuntime(3896):     at android.graphics.BitmapFactory.decodeFile(BitmapFactory.java:174)
01-25 05:05:49.917: ERROR/AndroidRuntime(3896):     at android.graphics.drawable.Drawable.createFromPath(Drawable.java:729)
01-25 05:05:49.917: ERROR/AndroidRuntime(3896):     at android.widget.ImageView.resolveUri(ImageView.java:484)
01-25 05:05:49.917: ERROR/AndroidRuntime(3896):     at android.widget.ImageView.setImageURI(ImageView.java:281)
01-25 05:05:49.917: ERROR/AndroidRuntime(3896):     at android.widget.SimpleCursorAdapter.setViewImage(SimpleCursorAdapter.java:183)
01-25 05:05:49.917: ERROR/AndroidRuntime(3896):     at android.widget.SimpleCursorAdapter.bindView(SimpleCursorAdapter.java:129)
01-25 05:05:49.917: ERROR/AndroidRuntime(3896):     at android.widget.CursorAdapter.getView(CursorAdapter.java:150)
01-25 05:05:49.917: ERROR/AndroidRuntime(3896):     at android.widget.AbsListView.obtainView(AbsListView.java:1057)
01-25 05:05:49.917: ERROR/AndroidRuntime(3896):     at android.widget.ListView.makeAndAddView(ListView.java:1616)
01-25 05:05:49.917: ERROR/AndroidRuntime(3896):     at android.widget.ListView.fillSpecific(ListView.java:1177)
01-25 05:05:49.917: ERROR/AndroidRuntime(3896):     at android.widget.ListView.layoutChildren(ListView.java:1454)
01-25 05:05:49.917: ERROR/AndroidRuntime(3896):     at android.widget.AbsListView.onLayout(AbsListView.java:937)
01-25 05:05:49.917: ERROR/AndroidRuntime(3896):     at android.view.View.layout(View.java:5611)
01-25 05:05:49.917: ERROR/AndroidRuntime(3896):     at android.widget.LinearLayout.setChildFrame(LinearLayout.java:1119)
01-25 05:05:49.917: ERROR/AndroidRuntime(3896):     at android.widget.LinearLayout.layoutHorizontal(LinearLayout.java:1108)
01-25 05:05:49.917: ERROR/AndroidRuntime(3896):     at android.widget.LinearLayout.onLayout(LinearLayout.java:922)
01-25 05:05:49.917: ERROR/AndroidRuntime(3896):     at android.view.View.layout(View.java:5611)
01-25 05:05:49.917: ERROR/AndroidRuntime(3896):     at android.widget.FrameLayout.onLayout(FrameLayout.java:294)
01-25 05:05:49.917: ERROR/AndroidRuntime(3896):     at android.view.View.layout(View.java:5611)
01-25 05:05:49.917: ERROR/AndroidRuntime(3896):     at android.widget.LinearLayout.setChildFrame(LinearLayout.java:1119)
01-25 05:05:49.917: ERROR/AndroidRuntime(3896):     at android.widget.LinearLayout.layoutVertical(LinearLayout.java:999)
01-25 05:05:49.917: ERROR/AndroidRuntime(3896):     at android.widget.LinearLayout.onLayout(LinearLayout.java:920)
01-25 05:05:49.917: ERROR/AndroidRuntime(3896):     at android.view.View.layout(View.java:5611)
01-25 05:05:49.917: ERROR/AndroidRuntime(3896):     at android.widget.FrameLayout.onLayout(FrameLayout.java:294)
01-25 05:05:49.917: ERROR/AndroidRuntime(3896):     at android.view.View.layout(View.java:5611)
01-25 05:05:49.917: ERROR/AndroidRuntime(3896):     at android.view.ViewRoot.performTraversals(ViewRoot.java:771)
01-25 05:05:49.917: ERROR/AndroidRuntime(3896):     at android.view.ViewRoot.handleMessage(ViewRoot.java:1103)
01-25 05:05:49.917: ERROR/AndroidRuntime(3896):     at android.os.Handler.dispatchMessage(Handler.java:88)
01-25 05:05:49.917: ERROR/AndroidRuntime(3896):     at android.os.Looper.loop(Looper.java:123)
01-25 05:05:49.917: ERROR/AndroidRuntime(3896):     at android.app.ActivityThread.main(ActivityThread.java:3742)
01-25 05:05:49.917: ERROR/AndroidRuntime(3896):     at java.lang.reflect.Method.invokeNative(Native Method)
01-25 05:05:49.917: ERROR/AndroidRuntime(3896):     at java.lang.reflect.Method.invoke(Method.java:515)
01-25 05:05:49.917: ERROR/AndroidRuntime(3896):     at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:739)
01-25 05:05:49.917: ERROR/AndroidRuntime(3896):     at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:497)
01-25 05:05:49.917: ERROR/AndroidRuntime(3896):     at dalvik.system.NativeStart.main(Native Method)
01-25 05:10:01.127: ERROR/AndroidRuntime(3943): ERROR: thread attach failed


I also have a new error when displaying an image:

01-25 22:13:18.594: DEBUG/skia(4204): xxxxxxxxxxx jpeg error 20 Improper call to JPEG library in state %d
01-25 22:13:18.604: INFO/System.out(4204): resolveUri failed on bad bitmap uri: 
01-25 22:13:18.694: ERROR/dalvikvm-heap(4204): 6291456-byte external allocation too large for this process.
01-25 22:13:18.694: ERROR/(4204): VM won't let us allocate 6291456 bytes
01-25 22:13:18.694: DEBUG/skia(4204): xxxxxxxxxxxxxxxxxxxx allocPixelRef failed

解决方案

The Android Training class, "Displaying Bitmaps Efficiently", offers some great information for understanding and dealing with the exception java.lang.OutOfMemoryError: bitmap size exceeds VM budget when loading Bitmaps.


Read Bitmap Dimensions and Type

The BitmapFactory class provides several decoding methods (decodeByteArray(), decodeFile(), decodeResource(), etc.) for creating a Bitmap from various sources. Choose the most appropriate decode method based on your image data source. These methods attempt to allocate memory for the constructed bitmap and therefore can easily result in an OutOfMemory exception. Each type of decode method has additional signatures that let you specify decoding options via the BitmapFactory.Options class. Setting the inJustDecodeBounds property to true while decoding avoids memory allocation, returning null for the bitmap object but setting outWidth, outHeight and outMimeType. This technique allows you to read the dimensions and type of the image data prior to construction (and memory allocation) of the bitmap.

BitmapFactory.Options options = new BitmapFactory.Options();
options.inJustDecodeBounds = true;
BitmapFactory.decodeResource(getResources(), R.id.myimage, options);
int imageHeight = options.outHeight;
int imageWidth = options.outWidth;
String imageType = options.outMimeType;

To avoid java.lang.OutOfMemory exceptions, check the dimensions of a bitmap before decoding it, unless you absolutely trust the source to provide you with predictably sized image data that comfortably fits within the available memory.


Load a scaled down version into Memory

Now that the image dimensions are known, they can be used to decide if the full image should be loaded into memory or if a subsampled version should be loaded instead. Here are some factors to consider:

  • Estimated memory usage of loading the full image in memory.
  • The amount of memory you are willing to commit to loading this image given any other memory requirements of your application.
  • Dimensions of the target ImageView or UI component that the image is to be loaded into.
  • Screen size and density of the current device.

For example, it’s not worth loading a 1024x768 pixel image into memory if it will eventually be displayed in a 128x96 pixel thumbnail in an ImageView.

To tell the decoder to subsample the image, loading a smaller version into memory, set inSampleSize to true in your BitmapFactory.Options object. For example, an image with resolution 2048x1536 that is decoded with an inSampleSize of 4 produces a bitmap of approximately 512x384. Loading this into memory uses 0.75MB rather than 12MB for the full image (assuming a bitmap configuration of ARGB_8888). Here’s a method to calculate a sample size value that is a power of two based on a target width and height:

public static int calculateInSampleSize(
        BitmapFactory.Options options, int reqWidth, int reqHeight) {
    // Raw height and width of image
    final int height = options.outHeight;
    final int width = options.outWidth;
    int inSampleSize = 1;

    if (height > reqHeight || width > reqWidth) {

        final int halfHeight = height / 2;
        final int halfWidth = width / 2;

        // Calculate the largest inSampleSize value that is a power of 2 and keeps both
        // height and width larger than the requested height and width.
        while ((halfHeight / inSampleSize) > reqHeight
                && (halfWidth / inSampleSize) > reqWidth) {
            inSampleSize *= 2;
        }
    }

    return inSampleSize;
}

Note: A power of two value is calculated because the decoder uses a final value by rounding down to the nearest power of two, as per the inSampleSize documentation.

To use this method, first decode with inJustDecodeBounds set to true, pass the options through and then decode again using the new inSampleSize value and inJustDecodeBounds set to false:

public static Bitmap decodeSampledBitmapFromResource(Resources res, int resId,
    int reqWidth, int reqHeight) {

    // First decode with inJustDecodeBounds=true to check dimensions
    final BitmapFactory.Options options = new BitmapFactory.Options();
    options.inJustDecodeBounds = true;
    BitmapFactory.decodeResource(res, resId, options);

    // Calculate inSampleSize
    options.inSampleSize = calculateInSampleSize(options, reqWidth, reqHeight);

    // Decode bitmap with inSampleSize set
    options.inJustDecodeBounds = false;
    return BitmapFactory.decodeResource(res, resId, options);
}

This method makes it easy to load a bitmap of arbitrarily large size into an ImageView that displays a 100x100 pixel thumbnail, as shown in the following example code:

mImageView.setImageBitmap(
    decodeSampledBitmapFromResource(getResources(), R.id.myimage, 100, 100));

You can follow a similar process to decode bitmaps from other sources, by substituting the appropriate BitmapFactory.decode* method as needed.

这篇关于奇怪的内存不足的问题,同时加载图像为位图对象的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆