观心静

  博客园  :: 首页  :: 新随笔  :: 联系 :: 订阅 订阅  :: 管理

前言

  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

posted on 2020-08-26 17:43  观心静  阅读(1577)  评论(0编辑  收藏  举报