互联网
arrayadapter(Android Bitmap史上最详细全解 - 原力计划)
Android Bitmap史上最详细全解 | 原力计划nerror="javascript:errorimg.call(this);">

责编 | 王晓曼

Bitmap的相关使用

Bitmap相关的使用主要有两种:

2.当做画布来使用 。

Bitmap的格式

第一:如何存储每个像素点?

1、存储格式

ARGB_4444:ARGB各用4位存储,1个像素点16位占2个字节;

  • RGB_565:只存储色值,不存储透明度,默认不透明,RGB分别占5,6,5位,一个像素点占用16位2个字节。

  • 注意以下三点即可:

    • 一般情况下用ARGB_8888格式存储Bitmap;
    • 假如对图片没有透明度要求,可以使用RGB_565,比ARGB_8888节省一半的内存开销。

    我们不妨来计算一下,如果一张和手机屏幕大小一样的Bitmap图片,采用ARGB_8888格式存储需要多大的内存!

    一张手机屏幕大小的 Bitmap 图片竟然要 24M ? 那就不奇怪我的 APP 为什么一直闪退了,只不过用 for 循环创 建了几十个用在滑动列表里面。

    Bitmap创建方法

    想要创建一个Bitmap有很多种方法,其中很多方法都要求传入一个Bitmap.Options,它是什么呢,有什么作用呢?

    介绍几个重要的成员变量:

    • inJustDecodeBounds:boolean类型,设为true时,无需要把图片加载入内存就可以获取图片的高度,宽度和图片的MIME类型。

    MIME通过options.outMineType获取。

    • inSampleSize:这个字段表示采样率,打个比方说,设置为4,则是从原本图片的四个像素中取一个像素作为结果返回。其余的都被丢弃。可见,采样率越大,图片越小,失真越严重。如何计算采样率呢?看一下这段代码你就会明白:
     public int getSampleSize(BitmapFactory.Options options , int dstWidth,int dstHeight){
    //dstWidth:表示目前ImageView的宽度
    //dstHeight:表示目标ImageView的高度
    //option中获取bitmap图片的信息
    int rawWidth = options.outWidth;
    int rawHeight = options.outHeight;
    int sampleSize=1;
    if(rawWidth>dstWidth||rawHeight>dstHeight){
    float ratioHeight = (float) (rawHeight/dstHeight);
    float ratioWidth = (float) (rawWidth/dstWidth);
    sampleSize = (int) Math.min(rawHeight, ratioWidth);
    }
    return sampleSize;
    }

    当屏幕分辨率与图片所在文件夹所对应的分辨率不同时,会进行缩放,缩放比例是屏幕分辨率/文件夹所对应的分辨率。

  • inScald :这个参数表示,在可以缩放时,是否对当前文件进行放缩,如果设置为 false 就不放缩。设置为 true,则会根据文件夹分辨率和屏幕分辨率进行动态缩放。

    关于 Options 就介绍这几个关键的字段,下面进入重头戏,创建Bitmap。

    BitmapFactory 提供了多种创建 bitmap 的静态方法:

    //从资源文件中通过id加载bitmap
    //Resources res:资源文件,可以context.getResources获得
    //id:资源文件的id,如R.drawable.xxx
    public static Bitmap decodeResources(Resources res,int id)
    //第二种只是第一种的重载方法,多了个Options参数
    public static Bitmap decodeResources(Resources res,int id,Options opt)
    //传入文件路径加载,比如加载sd卡中的文件
    //pathName:文件的全路径名
    public static Bitmap decodeFile(String pathName);
    public static Bitmap decodeFile(String pathName,Options opt);
    //从byte数组中加载
    //offset:对应data数组的起始下标
    //length:截取的data数组的长度
    public static Bitmap decodeByteArray(byte[] data,int offset , int length);
    public static Bitmap decodeByteArray(byte[] data,int offset , int length,Options opt);
    //从输入流中加载图片
    //InputStream is:输入流
    //Rect outPadding:用于返回矩形的内边距
    public static Bitmap decodeStream(InputStream is);
    public static Bitmap decodeStream(InputStream is,Rect outPadding,Options opt);
    //FileDescriptor :包含解码位图的数据文件的路径
    //通过该方式从路径加载bitmap比decodeFile更节省内存,原因不解释了。
    public static Bitmap decodeFileDescriptor(FileDescriptor fd);
    public static Bitmap decodeFileDescriptor(FileDescriptor fd,Rect outPadding,Options opt);

    3、Bitmap静态方法

    //width和height是长和宽单位px,config是存储格式
    static Bitmap createBitmap(int width , int height Bitmap.Config config)
    // 根据一幅图像创建一份一模一样的实例
    static Bitmap createBitmap(Bitmap bm)
    //截取一幅bitmap,起点是(x,y),width和height分别对应宽高
    static Bitmap createBitmap(Bitmap bm,int x,int y,int width,int height)
    //比上面的裁剪函数多了两个参数,Matrix:给裁剪后的图像添加矩阵 boolean filter:是否给图像添加滤波效果
    static Bitmap createBitmap(Bitmap bm,int x,int y,int width,int height,Matrix m,boolean filter);
    //用于缩放bitmap,dstWidth和dstHeight分别是目标宽高
    createScaledBitmap(Bitmap bm,int dstWidth,int dstHeight,boolean filter)

    加载图像可以使用BitmapFactory和Bitmap.create系列方法

  • 如果需要裁剪或者缩放图片,只能使用create系列函数

  • 常见函数

    getByteCount//获取bitmap的字节数

    2、综合案例演示

     String items = {"copy","extractAlpha 1","extractAlpha 2","bitmap大小","recycle","isRecycled"};
    ArrayAdapter<String> adapter = new ArrayAdapter<>(this, android.R.layout.simple_spinner_item,items);
    adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
    spinner.setAdapter(adapter);
    spinner.setonItemSelectedListener(new AdapterView.onItemSelectedListener {
    @Override
    public void onItemSelected(AdapterView<?> parent, View view, int position, long id) {
    switch (position){
    case 0:
    //copy
    Bitmap bm = BitmapFactory.decodeResource(getResources, R.drawable.photo);
    Bitmap copy = bm.copy(Bitmap.Config.ARGB_8888, true);
    imageView.setImageBitmap(copy);
    bm.recycle;
    break;
    case 1:
    //extractAlpha 不带参数
    Bitmap bp = BitmapFactory.decodeResource(getResources, R.drawable.photo);
    Bitmap alpha = bp.extractAlpha;
    imageView.setImageBitmap(alpha);
    bp.recycle;
    break;
    case 2:
    //extractAlpha 带参数
    Bitmap bp1 = BitmapFactory.decodeResource(getResources, R.drawable.photo);
    Paint paint = new Paint;
    BlurMaskFilter blurMaskFilter = new BlurMaskFilter(6, BlurMaskFilter.Blur.NORMAL);
    paint.setMaskFilter(blurMaskFilter);
    int offsetXY = new int[2];
    Bitmap alpha1 = bp1.extractAlpha(paint, offsetXY);
    imageView.setImageBitmap(alpha1);
    break;
    case 3:
    //获取bitmap大小
    Bitmap b = BitmapFactory.decodeResource(getResources, R.drawable.photo);
    Toast.makeText(getApplicationContext, "图片大小为:"+b.getByteCount+"字节", Toast.LENGTH_SHORT).show;
    break;
    case 4:
    //回收bitmap
    Bitmap b1 = BitmapFactory.decodeResource(getResources, R.drawable.photo);
    b1.recycle;
    if(b1.isRecycled){
    Toast.makeText(getApplicationContext, "已经被回收", Toast.LENGTH_SHORT).show;
    }
    //isRecycled判断是否被回收
    break;
    }

    }

    @Override
    public void onNothingSelected(AdapterView<?> parent) {

    }
    });
    Android Bitmap史上最详细全解 | 原力计划nerror="javascript:errorimg.call(this);">

    1、Bitmap与Canvas,View,Drawable的关系:

    • 我们自定义空间所显示的View也是通过Canvas中的Bitmap来显示的。

    • 2、使用Bitmap如何造成内存溢出的?

      3、怎么解决或者避免Bitmap内存溢出?

      • 我们可以对位图进行压缩,压缩手段有 PNG,JPEG,WEBP。
      • 在创建 Bitmap 时使用 try catch 步骤 OOM 异常,使程序更健壮,即使发生了 OOM 也不会闪退,造成不好的使用体验。

      (1)Drawable 转换成 Bitmap

      public static Bitmap drawableToBitmap(Drawable drawable) { 
      // 取 drawable 的长宽
      int w = drawable.getIntrinsicWidth;
      int h = drawable.getIntrinsicHeight;

      // 取 drawable 的颜色格式
      Bitmap.Config config = drawable.getOpacity != PixelFormat.OPAQUE ? Bitmap.Config.ARGB_8888
      : Bitmap.Config.RGB_565;
      // 建立对应 bitmap
      Bitmap bitmap = Bitmap.createBitmap(w, h, config);
      // 建立对应 bitmap 的画布
      Canvas canvas = new Canvas(bitmap);
      drawable.setBounds(0, 0, w, h);
      // 把 drawable 内容画到画布中
      drawable.draw(canvas);
      return bitmap;
      }

      小结

      版权声明:本文为CSDN博主「IF 」的原创文章,遵循CC4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。

      https://blog.csdn.net/weixin_43927892/article/details/106209563

      Linux 之父怒删工程师提交的补丁,称“太蠢了”网友:怼得好!

      性能超越最新序列推荐模型,华为诺亚方舟提出记忆增强的图神经网络

      稳定币经济:十大稳定币简史


      顶一下()     踩一下()
  • 热门推荐

    发表评论
    0评