Android之高效加载大图的方法示例

加载大图到内存是一件令人头疼的事情。因为大图的原因,我们会在Crash报告中看到OOM(内存不足).Android的内存有限,这一点我们应该心里有数。

stackoverflow上有许多相关问题的回答,当你碰到oom时,可以直接跳过本文,粘贴复制答案即可。但是对于其他人来说,我想告诉你们一些加载大图的知识和原理。

加载Bitmap到内存

so easy.你所需要做的就是使用BitmapFactory解码你的图片。

Bitmap bitmap = BitmapFactory.decodeResource(getResources(), R.mipmap.hqimage);
imageView.setImageBitmap(bitmap);

看起来好像完事啦么?我要告诉你这里有个问题。让我们来看看解码后的图片占用的内存大小。

bitmap.getByteCount()可以返回图片的大小。其内存大小为 12262248 字节,等于 12.3MB .没错,你可能会有些疑惑。图片在磁盘上的大小为 3.5MB ,getByteCount()得出的结果却大于3.5MB。原因如下:

图片以JPG,PNG或者其他格式压缩后存储在计算机上。一旦你将图片加载到内存后,图片将不会呗压缩,而是占用所有像素所需的内存。

步骤

  • 不用加载图片到内存获取其尺寸
  • 通过图片尺寸计算缩放系数
  • 通过计算后值加载图片到内存

BitmapFactory.Options

这个类是个元数据提供器,我们可以通过这个类来完成第一步。

BitmapFactory.Options options = new BitmapFactory.Options();
options.inJustDecodeBounds = true;
BitmapFactory.decodeResource(getResources(), R.mipmap.hqimage, options);

我们传BitmapFactory.Options实例到BitmapFactory.decodeSource() 方法。我们将 inJustDecodeBounds 设置为 true .inJustDecodeBounds是什么意思呢?就是我们不用讲图片加载到内存中。我们只想得到关于图片的信息。我们可以通过这个信息计算缩放系数。

运行此段代码得到如下信息:

options.outHeight : 1126
options.outWidth : 2000
options.bitmap : null

减少图片大小(内存中)

现在该计算 inSampleSize 啦,等等,何为inSampleSize?inSampleSize是属于 BitmapFactory.Option这个类的一个缩放系数。

如果我们有一张1000 1000的图片,inSampleSize为2,解码后大小为500 500.

BitmapFactory.Options options = new BitmapFactory.Options();
options.inJustDecodeBounds = true;
options.inSampleSize = 3;
BitmapFactory.decodeResource(getResources(), R.mipmap.hqimage, options);

我们可以这样玩么?不行。因为我们不知道图片大小,如果是小图,图片将会变得更小,我们的用户只能看到一些像素而不是图片。有些图片将会缩放5倍,有些则为2倍。我们将缩放系数定义为一个常数。所以我们需要根据图片尺寸来计算。

计算inSampleSize的方法取决于你,我的意思就是根据你的需要来设计自己的算法。Android官方文档中,是基于2的幂次方来计算inSampleSize的。

options.inSampleSize = calculateInSampleSize(options, 500,500);
options.inJustDecodeBounds = false;
Bitmap smallBitmap = BitmapFactory.decodeResource(getResources(), R.mipmap.hqimage, options);

我们将inJustDecodeBounds变为false,以便获取bitmap.

现在,bitmap.getByteCount() 返回的大小为3.1MB。这个是内存大小。

图片的内存大小由12.3MB变为3.1MB,内存大小减少啦75%。

减少图片尺寸(磁盘上)

我们也可以减少图片在磁盘上的大小。我们可以通过Bitmap的compress方法来压缩图片。

让我们来看下不改边图片质量的尺寸大小,100表示质量不变

ByteArrayOutputStream bos = new ByteArrayOutputStream();
bitmap.compress(Bitmap.CompressFormat.JPEG, 100, bos);
byte[] bitmapdata = bos.toByteArray();

原图尺寸为1.6MB,改变图片质量后文件大小将发生何种变化?

bitmap.compress(Bitmap.CompressFormat.JPEG, 50, bos);

图片质量改为50,大小变成24.4KB

如果你想改变bitmap的质量,压缩格式必须为.JPEG ,PNG格式的图片质量是不会发生变化的。

文件大小由1.6MB变成啦24.4KB。

翻译自: Loading Large Bitmaps Efficiently in Android

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持我们。

(0)

相关推荐

  • Android高效加载大图、多图解决方案 有效避免程序OOM

    本篇文章主要内容来自于Android Doc,我翻译之后又做了些加工,英文好的朋友也可以直接去读原文. http://developer.android.com/training/displaying-bitmaps/index.html 高效加载大图片 我们在编写Android程序的时候经常要用到许多图片,不同图片总是会有不同的形状.不同的大小,但在大多数情况下,这些图片都会大于我们程序所需要的大小.比如说系统图片库里展示的图片大都是用手机摄像头拍出来的,这些图片的分辨率会比我们手机屏幕的分辨

  • Android开发实现ImageView加载摄像头拍摄的大图功能

    本文实例讲述了Android开发实现ImageView加载摄像头拍摄的大图功能.分享给大家供大家参考,具体如下: 这个方法是从官方demo中摘录的,在此记录学习. 权限 <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" /> <uses-feature android:name="android.hardware.camera2" android:re

  • Android 加载大图及多图避免程序出现OOM(OutOfMemory)异常

    Android 加载大图及多图避免程序出现OOM(OutOfMemory)异常 1.高效加载大图片 我们在编写Android程序的时候经常要用到许多图片,不同图片总是会有不同的形状.不同的大小,但在大多数情况下,这些图片都会大于我们程序所需要的大小.比如说系统图片库里展示的图片大都是用手机摄像头拍出来的,这些图片的分辨率会比我们手机屏幕的分辨率高得多.大家应该知道,我们编写的应用程序都是有一定内存限制的,程序占用了过高的内存就容易出现OOM(OutOfMemory)异常.我们可以通过下面的代码看

  • Android 加载大图、多图和LruCache缓存详细介绍

    我们在编写Android程序的时候经常要用到许多图片,不同图片总是会有不同的形状.不同的大小,但在大多数情况下,这些图片都会大于我们程序所需要的大小.比如说系统图片库里展示的图片大都是用手机摄像头拍出来的,这些图片的分辨率会比我们手机屏幕的分辨率高得多.大家应该知道,我们编写的应用程序都是有一定内存限制的,程序占用了过高的内存就容易出现OOM(OutOfMemory)异常.我们可以通过下面的代码看出每个应用程序最高可用内存是多少 int maxMemory = (int) (Runtime.ge

  • 在Android中高效的加载大图的方法示例

    将大图加载到内存中总是令人痛苦,因为我们经常会在应用的崩溃报告中看到OOM(Out Of Memory)的bug.大家都知道,Android系统的内存有限.我们必须牢记这一点. stackoverflow上有很多关于大图加载的问题,当你的应用程序遇到OOM的时候,你可以选择直接复制粘贴其中的答案来解决这个问题.因此,你完全可以略过本篇文章,但我想介绍一些加载大图的基础知识及其实际工作的原理. 我只想解释图片解码背后的逻辑.我建议你使用Picasso或Glide来加载图片.没有必要重新发明轮子.

  • Android 实现加载大图片的方法

    项目简介: 该项目为加载大图片 详细介绍: 对于超大的图片,如果不缩放的话,容易导致内存溢出.而经过处理后,无论多大的图片,都能够在手机屏幕上加载出来,不会导致内存溢出.当然,脸黑的除外 该应用涉及到的知识有: - 1.Bitmap的使用 - 2.Android手机中加载图片的原理 有的时候,我们加载一张不足1M的图片,尽管手机的堆内存有16M,仍然会导致内存溢出,why? 这就更计算机加载图片的原理有关了: 1).手机会解析图片的所有像素信息,把每个像素信息都存入到内存中 2).Android

  • 详解Android_性能优化之ViewPager加载成百上千高清大图oom解决方案

    一.背景 最近做项目需要用到选择图片上传,类似于微信.微博那样的图片选择器,ContentResolver读取本地图片资源并用RecyclerView+Glide加载图片显示就搞定列表的显示,这个没什么大问题,重点是,点击图片进入大图浏览,比如你相册有几百张图片,也就意味着在ViewPager中需要加载几百个view,况且手机拍出来的图片都是1-2千万左右像素的高清大图(笔者手机2千万像素 也就是拍照出来的照片3888*5152),大小也有5-7个兆,ViewPager滑动不了十几张就oom了,

  • Android实现网络加载图片点击大图后浏览可缩放

    本文实例为大家分享了Android九宫格图片展示的具体代码,供大家参考,具体内容如下 找了一些demo感觉没有自己想要的效果,于是借鉴一些改造一下并记录下来: 1.主Activity public class PictureViewFra extends Activity { private PicGallery gallery; // private ViewGroup tweetLayout; // 弹层 private boolean mTweetShow = false; // 弹层是否

  • Android之高效加载大图的方法示例

    加载大图到内存是一件令人头疼的事情.因为大图的原因,我们会在Crash报告中看到OOM(内存不足).Android的内存有限,这一点我们应该心里有数. stackoverflow上有许多相关问题的回答,当你碰到oom时,可以直接跳过本文,粘贴复制答案即可.但是对于其他人来说,我想告诉你们一些加载大图的知识和原理. 加载Bitmap到内存 so easy.你所需要做的就是使用BitmapFactory解码你的图片. Bitmap bitmap = BitmapFactory.decodeResou

  • Android开发之加载图片的方法

    本文实例讲述了Android开发之加载图片的方法.分享给大家供大家参考.具体分析如下: 加载网络上的图片需要在manifest中配置访问网络的权限,如下: <uses-permission android:name="android.permission.INTERNET" /> 如果不配置这个权限的话,会报错:unknown host exception. package com.example.loadimgfromweb; import java.io.InputSt

  • Android实现滑动加载数据的方法

    本文实例讲述了Android实现滑动加载数据的方法.分享给大家供大家参考.具体实现方法如下: EndLessActivity.java如下: package com.ScrollListView; import Android.app.ListActivity; import Android.os.Bundle; import Android.view.Gravity; import Android.view.View; import Android.view.ViewGroup; import

  • Android开发中Listview动态加载数据的方法示例

    本文实例讲述了Android开发中Listview动态加载数据的方法.分享给大家供大家参考,具体如下: 最近在研究网络数据加载的问题,比如我有几百,甚至上千条数据,这些数据如果一次性全部加载到arraylist,然后再加载到Listview中.我们必然会去单独开线程来做,这样造成的结果就是会出现等待时间很长,用户体验非常不好.我的想法是动态加载数据,第一次加载十条,然后往下面滑动的时候再追加十条,再往下面滑动的时候再去追加,这样大大减少了用户等待的时间,同时给处理数据留下了时间.网上看到了这样一

  • Android开发之底图局部加载移动的方法示例

    本文实例讲述了Android开发之底图局部加载移动的方法.分享给大家供大家参考,具体如下: public class MapMgr { public static MapMgr mapMgr = null; private int map_num = 28; private int b_x = 0; private int b_y = 0; private int width = 0; private int height = 0; private Bitmap bmpView = null;

  • Android实现自定义加载框的代码示例

    App在与服务器进行网络交互的时候,需要有一个提示的加载框,如图: 此时我们可以自定义一个加载中的对话框,代码如下: public class LoadingDialog extends Dialog { private static final int CHANGE_TITLE_WHAT = 1; private static final int CHNAGE_TITLE_DELAYMILLIS = 300; private static final int MAX_SUFFIX_NUMBER

  • JS简单实现滑动加载数据的方法示例

    本文实例讲述了JS简单实现滑动加载数据的方法.分享给大家供大家参考,具体如下: //滑动 function getScrollTop() { var scrollTop = 0; if (document.documentElement && document.documentElement.scrollTop) { scrollTop = document.documentElement.scrollTop; }else if (document.body) { scrollTop =

  • jQuery实现滚动到底部时自动加载更多的方法示例

    本文实例讲述了jQuery实现滚动到底部时自动加载更多的方法.分享给大家供大家参考,具体如下: 这里利用AJAX,实现滚动到底加载数据功能: <!DOCTYPE html> <html xmlns="http://www.w3.org/1999/xhtml"> <head runat="server"> <meta http-equiv="Content-Type" content="text/

随机推荐