• Android开发 Bitmap图像处理详解


    前言

      Bitmap开发涉及到方方面面,比如裁剪图片,压缩图片,镜像图片,旋转图片,各种转存图片等等,是必需掌握Android开发技巧,Android开发提供了2个类来实现这些需求,Bitmap类与BitmapFactory类。此博客会持续更新各种实际需求。

    将Res位图资源转成Bitmap

    请注意,使用这个方法会出现Bitmap为null的问题。这个问题可能是因为资源id异常引起的。特别是你使用了分module形式构建的app

    Bitmap bitmap = BitmapFactory.decodeResource(getResources(), R.mipmap.ic_launcher);

    将指定文件转成Bitmap

    Bitmap bitmap = BitmapFactory.decodeFile(getContext().getExternalCacheDir() + File.separator + "demo1.png");

    将Drawable矢量图资源转成Bitmap

        public static Bitmap getBitmapFromDrawable(Context context, @DrawableRes int drawableId) {
            Drawable drawable = ContextCompat.getDrawable(context, drawableId);
            if (drawable instanceof BitmapDrawable) {
                return ((BitmapDrawable) drawable).getBitmap();
            } else if (drawable instanceof VectorDrawable || drawable instanceof VectorDrawableCompat) {
                Bitmap bitmap = Bitmap.createBitmap(drawable.getIntrinsicWidth(), drawable.getIntrinsicHeight(), Bitmap.Config.ARGB_8888);
                Canvas canvas = new Canvas(bitmap);
                drawable.setBounds(0, 0, canvas.getWidth(), canvas.getHeight());
                drawable.draw(canvas);
                return bitmap;
            } else {
                throw new IllegalArgumentException("unsupported drawable type");
            }
        }

    将Uri转成Bitmap

        @Override
        public void onActivityResult(int requestCode, int resultCode, @Nullable Intent data) {
            super.onActivityResult(requestCode, resultCode, data);
            //相册选择图片
            if (requestCode == GALLERY_RESULT_CODE && resultCode == RESULT_OK) {
                final Uri uri = data.getData();
                try (InputStream inputStream = getActivity().getApplicationContext().getContentResolver().openInputStream(uri)) {
                    Bitmap bitmap = BitmapFactory.decodeStream(inputStream);//得到bitmap
                } catch (FileNotFoundException e) {
                    e.printStackTrace();
                } catch (IOException e) {
                    e.printStackTrace();
                }
                return;
            }
        }

    将Bitmap输出成文件 

               Bitmap bitmap = BitmapFactory.decodeFile(getContext().getExternalCacheDir() + File.separator + "demo1.png");
                    File file = new File(getContext().getExternalCacheDir(), "demo.jpg");
                    try (FileOutputStream fileOutputStream = new FileOutputStream(file)) {
                        //参数1:输出的图片格式 参数2:输出图片的压缩质量(范围值为0-100) 参数3:输出流
                        bitmap.compress(Bitmap.CompressFormat.JPEG, 90, fileOutputStream);
                    } catch (FileNotFoundException e) {
                        e.printStackTrace();
                    } catch (IOException e) {
                        e.printStackTrace();
                    }

    镜像垂直翻转

            Bitmap bitmap = BitmapFactory.decodeResource(getResources(), R.mipmap.ic_launcher);
            Matrix matrix = new Matrix();
            matrix.postScale(1, -1);   //镜像垂直翻转
            Bitmap changBitmap = Bitmap.createBitmap(bitmap, 0, 0, bitmap.getWidth(), bitmap.getHeight(), matrix, false);

    镜像水平翻转

            Bitmap bitmap = BitmapFactory.decodeResource(getResources(), R.mipmap.ic_launcher);
            Matrix matrix = new Matrix();
            matrix.postScale(-1, 1);   //镜像水平翻转
            Bitmap changBitmap = Bitmap.createBitmap(bitmap, 0, 0, bitmap.getWidth(), bitmap.getHeight(), matrix, false);
            mBinding.weatherIcon.setImageBitmap(changBitmap);

    旋转图片

            Bitmap bitmap = BitmapFactory.decodeResource(getResources(), R.mipmap.ic_launcher);
            Matrix matrix = new Matrix();
            matrix.postRotate(-90);  //旋转-90度
            Bitmap changBitmap = Bitmap.createBitmap(bitmap, 0, 0, bitmap.getWidth(), bitmap.getHeight(), matrix, false);
            mBinding.weatherIcon.setImageBitmap(changBitmap);

    压缩图片质量,降低图片存储大小

    原理其实很简单就是利用compress方法,一点一点的降低图片质量,最后压缩到需要的目标存储大小

        /**
         * 压缩图片
         * @param bitmap bitmap图片 压缩
         * @param targetKB 目标压缩大小
         * @return
         */
        private Bitmap compressImage(Bitmap bitmap, int targetKB){
            Bitmap outBitmap = null;
            ByteArrayInputStream bais = null;
            ByteArrayOutputStream baos = null;
            try {
                baos = new ByteArrayOutputStream();
                int quality = 80;
                bitmap.compress(Bitmap.CompressFormat.JPEG, quality, baos);
                while ((baos.toByteArray().length/1024) > targetKB){
                    quality = quality-10;
                    baos.reset();
                    bitmap.compress(Bitmap.CompressFormat.JPEG,quality,baos);
                }
                bais = new ByteArrayInputStream(baos.toByteArray());
                outBitmap = BitmapFactory.decodeStream(bais);
                bais.close();
                baos.close();
            } catch (Exception e) {
                e.printStackTrace();
                onError(e);
            } finally {
                try {
                    bais.close();
                    baos.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
    
            }
            return outBitmap;
    
        }

    压缩图片尺寸

    原理是利用BitmapFactory.decodeStream方法,传入options,以降幂的方式等比例的压缩到目标尺寸,关键是options.inSampleSize = be;这个属性的配置

    /**
         * 尺寸压缩
         * @param bitmap
         */
        private Bitmap sizeCompres(Bitmap bitmap,float targetWidth,float targetHeight){
            Bitmap handleBitmap = null;
            try {
                ByteArrayOutputStream baos = new ByteArrayOutputStream();
                bitmap.compress(Bitmap.CompressFormat.JPEG,100,baos);
                // 判断如果图片大于1M,进行压缩避免在生成图片(BitmapFactory.decodeStream)时溢出
                if (baos.toByteArray().length / 1024 > 1024) {
                    baos.reset();// 重置baos即清空baos
                    bitmap.compress(Bitmap.CompressFormat.JPEG, 50, baos);// 这里压缩50%,把压缩后的数据存放到baos中
                }
                ByteArrayInputStream bais = new ByteArrayInputStream(baos.toByteArray());
                BitmapFactory.Options options = new BitmapFactory.Options();
                options.inJustDecodeBounds = true;
                BitmapFactory.decodeStream(bais,null,options);
                options.inJustDecodeBounds = false;
                int imageWidth = options.outWidth;
                int imageHeight = options.outHeight;
                int be = 1;
                if (imageWidth>imageHeight && imageWidth>targetWidth){
                    be = Math.round(imageWidth/targetWidth);
    
                }else if (imageHeight>imageWidth && imageHeight>targetHeight){
                    be = Math.round(imageHeight/targetHeight);
                }
                if (be <= 1){
                    be =1;//如果小于1等于1就不需要压缩直接返回
                }
                options.inSampleSize = be;
                bais = new ByteArrayInputStream(baos.toByteArray());//bais运行到这里可能已经清空了,所以需要再次添加
                handleBitmap = BitmapFactory.decodeStream(bais,null,options);
                bais.close();
                baos.close();
            } catch (Exception e) {
                e.printStackTrace();
            }
            return handleBitmap;
    
        }

    获取图片的角度属性与将图片角度属性设置回去

    获取图片的角度属性很重要,这里说明下,因为我们在压缩或者读取图片成Bitmap后在保存到文件里会丢失图片的角度,这样下次在查看这张图片的时候极有可能是倒的图片

    try {
                ExifInterface exifInterface = new ExifInterface(inpPath);//获取图片角度
                mDegrees = exifInterface.getAttributeInt(ExifInterface.TAG_ORIENTATION, -1);
                int angle = exifInterface.getAttributeInt(ExifInterface.TAG_ORIENTATION, -1);
                switch (angle){
                    case ExifInterface.ORIENTATION_ROTATE_270:
                        mDegrees = 270;
    
                        break;
                    case ExifInterface.ORIENTATION_ROTATE_180:
                        mDegrees = 180;
    
                        break;
                    case ExifInterface.ORIENTATION_ROTATE_90:
                        mDegrees = 90;
    
                        break;
                    default:
                        mDegrees = 0;
                        break;
                }
            } catch (IOException e) {
                e.printStackTrace();
            }

     将图片角度设置回去

             Matrix matrix = new Matrix();
                matrix.setRotate(mDegrees, bitmap.getWidth(), bitmap.getHeight());
                Bitmap finishBitmap = Bitmap.createBitmap(finishBitmap, 0, 0, bitmap.getWidth(), bitmap.getHeight(), matrix,true);

    End

  • 相关阅读:
    判断大小写数字个数,取交集和并集
    软件工程总结
    正则表达式(邮箱)
    今天距离你生日的天数
    字符数量,查回文
    解决一个表单中的两个或者多个按钮提交到不同的页面中问题
    jsp前台输入框不输入值,后台怎么取出整型?
    第十次作业
    CMD命令行
    Kali渗透安卓手机
  • 原文地址:https://www.cnblogs.com/guanxinjing/p/13566480.html
Copyright © 2020-2023  润新知