Bitmap总结

Bitmap绘图,旋转,缩放,平移,优化
(一)绘图
(1)绘图
它的两种方式:

1.通过BitmapFactory来找到Bitmap对象
eg.Bitmap bitmap=BitmapFactory.decodeResource(super.getResrouces,R.drawable.android_mldn)
 ·具体可以看附件中的两张图片

 
2.通过BitmapDrawable来找到Bitmap对象
eg.mBitmap = ((BitmapDrawable) getResources().getDrawable(R.drawable.pic)).getBitmap();

(2)在onDraw()方法中,绘制Bitmap
通过DrawBitmap方法
              // 第一个参数表示需要绘制的图像对象
  // 第二个参数表示截取图像上的区域
  // 第三个参数表示屏幕上显示的区域
  // 第四个参数表示画笔对象
canvas.DrawBitmap(mBitmap,new Rect(),new Rect(),mPaint);

(二)旋转,缩放,平移
操作步骤
(1)实例化Matrix
eg.Matrix matrix=new Matrix();
        ·它有三种操作分为:
         translate(平移),rotate(旋转),scale(缩放)和skew(倾斜
         除了tranaslate不可以指定中心点,其他的都可以

        ·操作方式分为:
        pre,矩阵前乘,是在之前插入一种变换,也是一种累加式的变换
        set,直接设置Matrix的值,每一次设置,都会清空之前所有的变换
        post,矩阵后乘,在之后变换,是一种累加式的变换

(2)初始化Matrix的值
    /* 重置mMatrix */
eg.   matrix.reset();

(3)进行旋转,缩放,平移等操作
 ·旋转
 /* 设置旋转 */
  // 第一个参数表示旋转的角度
  // 第二个参数表示旋转中心的x坐标
  // 第三个参数表好旋转中心的y坐标
 eg.  matrix.setRotate(30,150,20);
 ·平移
 /* 设置平移 */
  // 第一个参数表示移动到目标位置的x轴坐标
  // 第二个参数表示移动到目标位置的y轴坐标
 eg.matrix.setTranslate(10,10)

 ·缩放
       /* 设置缩放 */
  // 第一个参数表示移动到目标位置的x轴坐标
  // 第二个参数表示移动到目标位置的y轴坐标
 eg.matrix.postScale(Scale, Scale, 300, 300);

 ·倾斜
 /* 设置倾斜 */
  // 第一个参数表示倾斜的x轴的角度
  // 第二个参数表示倾斜的y轴的角度
  // 第三个参数表示倾斜的中心的x轴的坐标
  // 第四个参数表示倾斜的中心的y轴的坐标
 eg.smatrix.postSkew(0.2f, 0.2f, 100, 100);

(4)创建变换后的bitmap
      /* 按mMatrix得旋转构建新的Bitmap */
  // 第一个参数表示需要显示的图片对象(创建了一个用于显示图像的白纸,该参数表示白纸上要显示的内容)
  // 第二个表示图像在白纸(这里的mBitmap2)上的左上角顶点x坐标
  // 第三个表示图像在白纸(这里的mBitmap2)上的左上角顶点y坐标
  // 第四个参数和第五个参数表示要创建的Bitmap对象的宽度和高度(白纸的宽高)
  // 第五个参数表示Bitmap的矩阵状态(这张白纸的显示效果:平移、缩放、倾斜、旋转等状态)
  // 第六个参数表示是否设置过滤

 ·Bitmap mBitmap2 = Bitmap.createBitmap(mBitmap, 0, 0, mBitmapWidth,
   mBitmapHeight, mMatrix, true);
(5)绘制变换后的bitmap,

 ·canvas.drawBitmap(mBitmap2, 0, 0, null);

(6)第四,五步可以采用下面的方式替换
 
 ·canvas.drawBitmap(mBitmap, mMatrix, null);
 即不用单独建立一个bitmap,直接显示


(三)bitmap的优化
前言:
  android应用中,最耗内存的就是图片资源。android系统中,读取位图Bitmap时,分给虚拟机中的图片的堆栈大小事8M,如果超出了就回发生outofMemory异常。所以要对bitmap进行优化
(1)及时回收Bitmap的内存
   Bitmap的构造方法是私有的,是通过BitmapFactory类的各种静态方法实例化一个Bitmap。而生成Bitmap对象最终都是通过JNI调用方式是实现的。所以,加载Bitmap到内存里以后,包括两部分内存区域。简单的说,一部分是java部分,一部分是c部分
,这个Btiamap是java部分分配的,不用的时候系统会自动回收、但是那个对应的C可用的内存区域,虚拟机是不能直接调用的,需要调用底层的功能来释放。所以需要用recyle()方法来释放c部分的内存,这个recycle()方法里也的确是调用JNI方法。那么不调用recyle()内存是否会泄露呢?也不是的,android的进程如果被杀掉,那么内存就回释放,也包括c的内存部分
    android中,系统进程分为几个级别:系统不足的情况下,杀掉一些低优先级的进程,以提供给其他进程充足的内存空间。在实际开发项目中,有两种对退出程序的方式Process.killProcess(Process.myPid())杀死进程,还有就是用Activity.finish的方式关闭Activity
     一般情况下,我们可以在Activity的onStop()或者onDestroy()进行回收

    // 先判断是否已经回收
  if(bitmap != null && !bitmap.isRecycled()){
  // 回收并且置为null
  bitmap.recycle();//回收占用的内存

  bitmap = null;//置空Bitmap方法
  }
  System.gc();//调用系统回收器,不能立即回收,可以加快回收的的到来

(2)捕获异常
前言:
 通常在实例化Bitmap的时候,会对Bitmap进行OutofMemoryError的异常进行捕获
Bitmap bitmap = null;
  try {
  // 实例化Bitmap
  bitmap = BitmapFactory.decodeFile(path);
  } catch (OutOfMemoryError e) {  //注意此处是error,不是Exception
  //
  }
  if (bitmap == null) {
  // 如果实例化失败 返回默认的Bitmap对象
  return defaultBitmapMap;
  }

(3)缓存通用的Bitmap对象
  ·如果是同一张图片,就没有必要多次实例化,以节省内存(可以认为是缓存了Bitmap的对象)
  android的缓存技术分为:
  1.硬盘缓存
 比如,开发网络应用的过程中,可以将一些从网络上获取的数据保存到SD卡中,下次直接从SD卡读取,节省网络流量
  2.内存缓存
 比如应用程序需要使用到同一对象,也可以放到内存中缓存起来。

(4)压缩图片
eg.
public class BitmapUtils {

 public Bitmap optimizeBitmap(String filePath, int maxWidth, int maxHeight) {
  Bitmap result = null;
  // 创建一个Options图像配置对象
  BitmapFactory.Options options = new BitmapFactory.Options();
  // inJustDecodeBounds解码图像的模式;如果为true表示先获取图像原始宽高
  options.inJustDecodeBounds = true;
  // inJustDecodeBounds=true的模式下解码出来的图像为空,值得到图像的宽高
  result = BitmapFactory.decodeFile(filePath, options);
  int widthRatio = (int) Math.ceil(options.outWidth / maxWidth);
  int heightRatio = (int) Math.ceil(options.outHeight / maxHeight);
  if (widthRatio > 1 || heightRatio > 1) {
   if (widthRatio > heightRatio) {
    // inSampleSize主要是配置图像获取的比例,最终显示的比例为1/inSampleSize
    // ,注意inSampleSize必须大于1
    options.inSampleSize = widthRatio;
   } else {
    options.inSampleSize = heightRatio;
   }
  }
  // inJustDecodeBounds=false的模式下解码出来的图像才是正常可以显示的图像
  options.inJustDecodeBounds = false;
  result = BitmapFactory.decodeFile(filePath, options);
  return result;
 }

 /**
  * 将Bitmap对象存到sdcard中
  * @param bitmap
  * @param saveFileName
  */
 public static void saveBitmap(Bitmap bitmap, String saveFileName) {
  try {
   FileOutputStream out = new FileOutputStream(saveFileName);
   bitmap.compress(CompressFormat.JPEG, 80, out);
   out.flush();
   out.close();
  } catch (Exception e) {
   // TODO Auto-generated catch block
   e.printStackTrace();
  } 
 }
}

总结:
    如果程序的图片的来源都是程序包中的资源,或者是自己服务器上的图片,图片的大小是开发者可以调整的,那么一般来说,就只需要注意使用的图片不要过大,并且注意代码的质量,及时回收Bitmap对象,就能避免OutOfMemory异常的发生。

  如果程序的图片来自外界,这个时候就特别需要注意OutOfMemory的发生。一个是如果载入的图片比较大,就需要先缩小;另一个是一定要捕获异常,避免程序Crash。

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值