zoukankan      html  css  js  c++  java
  • 图片在内存中的大小

    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 }
    复制代码
  • 相关阅读:
    人民币汇率
    世界金融危机史
    选题==》方法
    宏观经济学理论
    央行货币政策执行报告
    货币政策科普
    几个数据库使用记录 & DPD-GMM调整到通过检验
    OBOR数据处理
    stata几个常用命令
    个人闭包理解(结合代码)
  • 原文地址:https://www.cnblogs.com/android-blogs/p/4969403.html
Copyright © 2011-2022 走看看