图片在内存中的大小

Android.graphics.Bitmap类里有一个内部类Bitmap.Config类,在Bitmap类里createBitmap(intwidth, int height, Bitmap.Config config)方法里会用到,打开个这个类一看

枚举变量
public static final Bitmap.Config ALPHA_8
public static final Bitmap.Config ARGB_4444
public static final Bitmap.Config ARGB_8888
public static final Bitmap.Config RGB_565

说白了就ALPHA_8就是Alpha由8位组成
ARGB_4444就是由4个4位组成即16位,
ARGB_8888就是由4个8位组成即32位,
RGB_565就是R为5位,G为6位,B为5位共16位

由此可见:
ALPHA_8 代表8位Alpha位图
ARGB_4444 代表16位ARGB位图
ARGB_8888 代表32位ARGB位图
RGB_565 代表8位RGB位图

位图位数越高代表其可以存储的颜色信息越多,当然图像也就越逼真。

图片的分辨率是3776 * 2520,每一点又是由ARGB色组成,每个色素占4个Byte,所以这张图片加载到内存中需要消耗的内存为:
3776 * 2520 * 4byte = 38062080byte,会造成内存溢出,那么如何加载大图片呢?

如何加载大分辨率图片

有时候我们确实会需要加载一些大分辨率的图片,但是对于移动设备而言,哪怕加载能成功那么大的内存也是一种浪费(屏幕分辨率限制),所以就需要想办法把图片按照一定比率压缩,使分辨率降低,以至于又不需要耗费很大的堆内存空间,又可以最大的利用设备屏幕的分辨率来显示图片。这里就用到一个BitmapFactory.Options对象,下面来介绍它。
BitmapFactory.Options为BitmapFactory的一个内部类,它主要用于设定与存储BitmapFactory加载图片的一些信息。下面是Options中需要用到的属性:
inJustDecodeBounds:如果设置为true,将不把图片的像素数组加载到内存中,仅加载一些额外的数据到Options中。
outHeight:图片的高度。
outWidth:图片的宽度。
inSampleSize:如果设置,图片将依据此采样率进行加载,不能设置为小于1的数。例如设置为4,分辨率宽和高将为原来的1/4,这个时候整体所占内存将是原来的1/16。

示例代码:

 1 import android.os.Bundle;
 2 import android.os.Environment;
 3 import android.app.Activity;
 4 import android.graphics.Bitmap;
 5 import android.graphics.BitmapFactory;
 6 import android.graphics.BitmapFactory.Options;
 7 import android.view.Menu;
 8 import android.view.View;
 9 import android.view.WindowManager;
10 import android.widget.Button;
11 import android.widget.ImageView;
12 public class MainActivity extends Activity {
13     private Button btn_loadimage;
14     private ImageView iv_bigimage;
15      @Override
16     protected void onCreate(Bundle savedInstanceState) {
17         super.onCreate(savedInstanceState);
18         setContentView(R.layout.activity_main);
19          btn_loadimage = (Button) findViewById(R.id.btn_loadimage);
20         iv_bigimage = (ImageView) findViewById(R.id.iv_bigimage);
21          btn_loadimage.setOnClickListener(new View.OnClickListener() {
22              @Override
23             public void onClick(View v) {
24                 // Bitmap bitmap=BitmapFactory.decodeFile("/sdcard/a.jpg");
25                 // iv_bigimage.setImageBitmap(bitmap);
26                  BitmapFactory.Options opts = new Options();
27                 // 不读取像素数组到内存中,仅读取图片的信息
28                 opts.inJustDecodeBounds = true;
29                 BitmapFactory.decodeFile("/sdcard/a.jpg", opts);
30                 // 从Options中获取图片的分辨率
31                 int imageHeight = opts.outHeight;
32                 int imageWidth = opts.outWidth;
33                  // 获取Android屏幕的服务
34                 WindowManager wm = (WindowManager) getSystemService(WINDOW_SERVICE);
35                 // 获取屏幕的分辨率,getHeight()、getWidth已经被废弃掉了
36                 // 应该使用getSize(),但是这里为了向下兼容所以依然使用它们
37                 int windowHeight = wm.getDefaultDisplay().getHeight();
38                 int windowWidth = wm.getDefaultDisplay().getWidth();
39                  // 计算采样率
40                 int scaleX = imageWidth / windowWidth;
41                 int scaleY = imageHeight / windowHeight;
42                 int scale = 1;
43                 // 采样率依照最大的方向为准
44                 if (scaleX > scaleY && scaleY >= 1) {
45                     scale = scaleX;
46                 }
47                 if (scaleX < scaleY && scaleX >= 1) {
48                     scale = scaleY;
49                 }
50                  // false表示读取图片像素数组到内存中,依照设定的采样率
51                 opts.inJustDecodeBounds = false;
52                 // 采样率
53                 opts.inSampleSize = scale;
54                 Bitmap bitmap = BitmapFactory.decodeFile("/sdcard/a.jpg", opts);
55                 iv_bigimage.setImageBitmap(bitmap);
56              }
57         });
58     }
59 }
60   

 1 import android.os.Bundle;
 2 import android.os.Environment;
 3 import android.app.Activity;
 4 import android.graphics.Bitmap;
 5 import android.graphics.BitmapFactory;
 6 import android.graphics.BitmapFactory.Options;
 7 import android.view.Menu;
 8 import android.view.View;
 9 import android.view.WindowManager;
10 import android.widget.Button;
11 import android.widget.ImageView;
12 public class MainActivity extends Activity {
13     private Button btn_loadimage;
14     private ImageView iv_bigimage;
15      @Override
16     protected void onCreate(Bundle savedInstanceState) {
17         super.onCreate(savedInstanceState);
18         setContentView(R.layout.activity_main);
19          btn_loadimage = (Button) findViewById(R.id.btn_loadimage);
20         iv_bigimage = (ImageView) findViewById(R.id.iv_bigimage);
21          btn_loadimage.setOnClickListener(new View.OnClickListener() {
22              @Override
23             public void onClick(View v) {
24                 // Bitmap bitmap=BitmapFactory.decodeFile("/sdcard/a.jpg");
25                 // iv_bigimage.setImageBitmap(bitmap);
26                  BitmapFactory.Options opts = new Options();
27                 // 不读取像素数组到内存中,仅读取图片的信息
28                 opts.inJustDecodeBounds = true;
29                 BitmapFactory.decodeFile("/sdcard/a.jpg", opts);
30                 // 从Options中获取图片的分辨率
31                 int imageHeight = opts.outHeight;
32                 int imageWidth = opts.outWidth;
33                  // 获取Android屏幕的服务
34                 WindowManager wm = (WindowManager) getSystemService(WINDOW_SERVICE);
35                 // 获取屏幕的分辨率,getHeight()、getWidth已经被废弃掉了
36                 // 应该使用getSize(),但是这里为了向下兼容所以依然使用它们
37                 int windowHeight = wm.getDefaultDisplay().getHeight();
38                 int windowWidth = wm.getDefaultDisplay().getWidth();
39                  // 计算采样率
40                 int scaleX = imageWidth / windowWidth;
41                 int scaleY = imageHeight / windowHeight;
42                 int scale = 1;
43                 // 采样率依照最大的方向为准
44                 if (scaleX > scaleY && scaleY >= 1) {
45                     scale = scaleX;
46                 }
47                 if (scaleX < scaleY && scaleX >= 1) {
48                     scale = scaleY;
49                 }
50                  // false表示读取图片像素数组到内存中,依照设定的采样率
51                 opts.inJustDecodeBounds = false;
52                 // 采样率
53                 opts.inSampleSize = scale;
54                 Bitmap bitmap = BitmapFactory.decodeFile("/sdcard/a.jpg", opts);
55                 iv_bigimage.setImageBitmap(bitmap);
56              }
57         });
58     }
59 }
60   

加载缩略图

1. 使用inJustDecodeBounds,读bitmap的长和宽。
2. 根据bitmap的长款和目标缩略图的长和宽,计算出inSampleSize的大小。
3. 使用inSampleSize,载入一个大一点的缩略图A
4. 使用createScaseBitmap,将缩略图A,生成我们需要的缩略图B。
5. 回收缩略图A。

 需要注意的事情

createScaseBitmap如果原图和目标缩略图大小一致,那么不会生成一个新的bitmap直接返回bitmap,因此,回收的时候,要判断缩略图A是否就是缩略图B,如果说是的话,不要回收。

 1 /**
 2  * http://developer.android.com/training/displaying-bitmaps/load-bitmap.html
 3  */
 4 public class BitmapUtils {
 5     private static int calculateInSampleSize(BitmapFactory.Options options,
 6             int reqWidth, int reqHeight) {
 7         final int height = options.outHeight;
 8         final int width = options.outWidth;
 9         int inSampleSize = 1;
10         if (height > reqHeight || width > reqWidth) {
11             final int halfHeight = height / 2;
12             final int halfWidth = width / 2;
13             while ((halfHeight / inSampleSize) > reqHeight
14                     && (halfWidth / inSampleSize) > reqWidth) {
15                 inSampleSize *= 2;
16             }
17         }
18         return inSampleSize;
19     }
20
21     // 如果是放大图片,filter决定是否平滑,如果是缩小图片,filter无影响
22     private static Bitmap createScaleBitmap(Bitmap src, int dstWidth,
23             int dstHeight) {
24         Bitmap dst = Bitmap.createScaledBitmap(src, dstWidth, dstHeight, false);
25         if (src != dst) { // 如果没有缩放,那么不回收
26             src.recycle(); // 释放Bitmap的native像素数组
27         }
28         return dst;
29     }
30
31     // 从Resources中加载图片
32     public static Bitmap decodeSampledBitmapFromResource(Resources res,
33             int resId, int reqWidth, int reqHeight) {
34         final BitmapFactory.Options options = new BitmapFactory.Options();
35         options.inJustDecodeBounds = true;
36         BitmapFactory.decodeResource(res, resId, options); // 读取图片长款
37         options.inSampleSize = calculateInSampleSize(options, reqWidth,
38                 reqHeight); // 计算inSampleSize
39         options.inJustDecodeBounds = false;
40         Bitmap src = BitmapFactory.decodeResource(res, resId, options); // 载入一个稍大的缩略图
41         return createScaleBitmap(src, reqWidth, reqHeight); // 进一步得到目标大小的缩略图
42     }
43
44     // 从sd卡上加载图片
45     public static Bitmap decodeSampledBitmapFromFd(String pathName,
46             int reqWidth, int reqHeight) {
47         final BitmapFactory.Options options = new BitmapFactory.Options();
48         options.inJustDecodeBounds = true;
49         BitmapFactory.decodeFile(pathName, options);
50         options.inSampleSize = calculateInSampleSize(options, reqWidth, reqHeight);
51         options.inJustDecodeBounds = false;
52         Bitmap src = BitmapFactory.decodeFile(pathName, options);
53         return createScaleBitmap(src, reqWidth, reqHeight);
54     }
55 }

 1 /**
 2  * http://developer.android.com/training/displaying-bitmaps/load-bitmap.html
 3  */
 4 public class BitmapUtils {
 5     private static int calculateInSampleSize(BitmapFactory.Options options,
 6             int reqWidth, int reqHeight) {
 7         final int height = options.outHeight;
 8         final int width = options.outWidth;
 9         int inSampleSize = 1;
10         if (height > reqHeight || width > reqWidth) {
11             final int halfHeight = height / 2;
12             final int halfWidth = width / 2;
13             while ((halfHeight / inSampleSize) > reqHeight
14                     && (halfWidth / inSampleSize) > reqWidth) {
15                 inSampleSize *= 2;
16             }
17         }
18         return inSampleSize;
19     }
20
21     // 如果是放大图片,filter决定是否平滑,如果是缩小图片,filter无影响
22     private static Bitmap createScaleBitmap(Bitmap src, int dstWidth,
23             int dstHeight) {
24         Bitmap dst = Bitmap.createScaledBitmap(src, dstWidth, dstHeight, false);
25         if (src != dst) { // 如果没有缩放,那么不回收
26             src.recycle(); // 释放Bitmap的native像素数组
27         }
28         return dst;
29     }
30
31     // 从Resources中加载图片
32     public static Bitmap decodeSampledBitmapFromResource(Resources res,
33             int resId, int reqWidth, int reqHeight) {
34         final BitmapFactory.Options options = new BitmapFactory.Options();
35         options.inJustDecodeBounds = true;
36         BitmapFactory.decodeResource(res, resId, options); // 读取图片长款
37         options.inSampleSize = calculateInSampleSize(options, reqWidth,
38                 reqHeight); // 计算inSampleSize
39         options.inJustDecodeBounds = false;
40         Bitmap src = BitmapFactory.decodeResource(res, resId, options); // 载入一个稍大的缩略图
41         return createScaleBitmap(src, reqWidth, reqHeight); // 进一步得到目标大小的缩略图
42     }
43
44     // 从sd卡上加载图片
45     public static Bitmap decodeSampledBitmapFromFd(String pathName,
46             int reqWidth, int reqHeight) {
47         final BitmapFactory.Options options = new BitmapFactory.Options();
48         options.inJustDecodeBounds = true;
49         BitmapFactory.decodeFile(pathName, options);
50         options.inSampleSize = calculateInSampleSize(options, reqWidth, reqHeight);
51         options.inJustDecodeBounds = false;
52         Bitmap src = BitmapFactory.decodeFile(pathName, options);
53         return createScaleBitmap(src, reqWidth, reqHeight);
54     }
55 }

时间: 2024-11-10 14:04:52

图片在内存中的大小的相关文章

关于Android应用中图片占用内存浅谈

从事过移动端应用开发的童鞋应该都清楚,内存是非常宝贵的资源.如果能很好的利用有限的内存,对应用性能的提升会有很大的帮助.在实际应用开发中图片内存占整个应用非常大的比重,我们只有了解图片是如何加载到内存中,才能更好的优化图片所占的内存. 那么对于图片在Android应用中的使用进行探讨一下. 图片所占内存大小=内存中图片高 * 内存中图片宽 * 每个像素所占字节数   1,那么图片的物理高宽和加载到内存中的高宽是否是一样的呢? 在应用中关于图片的加载一般分为两种情况,其加载到内存中的大小也是不一样

Android内存中的图片

图片在内存中的大小 Android.graphics.Bitmap类里有一个内部类Bitmap.Config类,在Bitmap类里createBitmap(intwidth, int height, Bitmap.Config config)方法里会用到,打开个这个类一看 枚举变量public static final Bitmap.Config ALPHA_8public static final Bitmap.Config ARGB_4444public static final Bitma

降低图片的内存消耗

我们知道产生OOM的原因是内存的使用量持续增长,直到超过了内存使用上限.每部手机对应用程序的内存上限在出厂时就已经是固定的了,所以我们需要尽量控制内存的使用量不要超过这个内存阀值,才能避免OOM.具体的做法就是去减少对象对内存的消耗.而今天要讨论的主要是减少图片对内存的消耗,因为图片消耗内存比较大,大多数应用程序都会有大量图片的加载,产生OOM往往也会发生在加载大量图片的时候.所以对图片占用内存的管理优化是很有必要的.但要记住的一点是,在内存的持续增长中,图片确实是其中一个很重量级的角色,但不是

转载__Android--加载大分辨率图片到内存

http://www.cnblogs.com/plokmju/p/android_LoadBigImage.html#3084005 前言 在使用ImageView显示图片的时候,直接加载一个图片资源到内存中,经常会出现内存溢出的错误,这是因为有些图片的分辨率比较高,把它直接加载到内存中之后,会导致堆内存溢出的问题.这篇博客就来讲解一下Android的堆内存以及如何在Android应用中加载一个高分辨率的图片.关于ImageView不熟悉的朋友,可以看看之前的博客:Android--ImageV

(四十二)、加载大分辨率图片到内存

有些图片的分辨率比较高,把它直接加载到手机内存中之后,会导致堆内存溢出的问题,下面就讲解一下Android的堆内存以及如何在Android应用中加载一个高分辨率的图片的方法. 1  还原堆内存溢出的错误首先来还原一下堆内存溢出的错误.首先在SD卡上放一张照片,分辨率为(3776 X 2520),大小为3.88MB,是我自己用相机拍的一张照片.应用的布局很简单,一个Button一个ImageView,然后按照常规的方式,使用BitmapFactory加载一张照片并使用一个ImageView展示.代

SQL Server 内存中OLTP内部机制概述(三)

----------------------------我是分割线------------------------------- 本文翻译自微软白皮书<SQL Server In-Memory OLTP Internals Overview>:http://technet.microsoft.com/en-us/library/dn720242.aspx 译者水平有限,如有翻译不当之处,欢迎指正. ----------------------------我是分割线---------------

知道内存中一个图片的指针IntPtr大小,转换成图片显示

//nSize 为总长度//pImageData 为总数据//nImageSize //一个图片的长度 byte[] _bytes = new byte[nImageSize];// //IntPtr infosIntptr = Marshal.AllocHGlobal(pImageData); Marshal.Copy(pImageData, _bytes, 0, nImageSize);//复制 PtrMoveSize(ref pImageData, nImageSize);//丛总内存中去

Android下将图片加载到内存中

Android的系统的标准默认每个应用程序分配的内存是16M.所以来说是非常宝贵的,在创建应用的时候要尽可能的去节省内存,但是在加载一些大的文件的时候,比如图片是相当耗内存的,一个1.3M的图片,分辨率是2560X1920(宽X高)图片当加载到手机内存的时候就会请求19M的一块内存,这是远远超出了系统自带的内存空间,这时候应用程序就会挂掉,所以我们要进行图片的缩放处理,下面我就来带大家创建一个用来图片缩放的应用: 应用效果图如下: 核心代码的实现: package com.examp.loadp

win7(旗舰版)下,OleLoadPicture 加载内存中的图片(MagickGetImageBlob),返回值 &lt; 0

昨天去三哥家,想把拍好的照片缩小一下,我用很久前写的一个软件进行缩小,然后进行一次效果预览,这个时候弹出: Call OleLoadPicture Fail - loadPictureFromMW 奇怪,这个图片批量处理软件我一直在用,在 xp系统下从来没出现过这样的提示,为什么在 win7下无法正常进行图片的效果预览? 更让我接受不了的是,从来没有用户或朋友向我反应这个问题,难道他们都不用 win7? 今天下午问了一个朋友借了台win7的笔记本,通过一下午的测试,解决了这个问题. 之前的代码思