美文网首页Android开发Android开发经验谈程序员
Android 图片压缩处理避免出现oom的方法

Android 图片压缩处理避免出现oom的方法

作者: 燊在锦官城 | 来源:发表于2017-09-11 11:44 被阅读489次

    1. 通过设置采样率压缩

    res资源图片压缩 decodeResource

         public static Bitmap decodeSampledBitmapFromResource(Resources res, int resId, int reqWidth, int reqHeight) {
            // First decode with inJustDecodeBounds=true to check dimensions
            final BitmapFactory.Options options = new BitmapFactory.Options();
            options.inJustDecodeBounds = true;
            BitmapFactory.decodeResource(res, resId, options);
    
            // Calculate inSampleSize
            options.inSampleSize = calculateInSampleSize(options, reqWidth, reqHeight);
    
            // Decode bitmap with inSampleSize set
            options.inJustDecodeBounds = false;
            return BitmapFactory.decodeResource(res, resId, options);
        }
    

    uri图片压缩 decodeStream

         public static Bitmap decodeSampledBitmapFromUri(Uri uri, int reqWidth, int reqHeight) {
            Bitmap bitmap = null;
            try {
            BitmapFactory.Options options = new BitmapFactory.Options();
            options.inJustDecodeBounds = true;
           BitmapFactory.decodeStream(getContentResolver().openInputStream(uri), null, options);
            options.inSampleSize = BitmapUtils.calculateInSampleSize(options,
                    UtilUnitConversion.dip2px(MyApplication.mContext, reqWidth), UtilUnitConversion.dip2px(MyApplication.mContext, reqHeight));
            options.inJustDecodeBounds = false;
    
            bitmap = BitmapFactory.decodeStream(getContentResolver().openInputStream(uri), null, options);
            } catch (Exception e) {
                e.printStackTrace();
            }
            return bitmap;
        }
    

    本地File url图片压缩

        public static Bitmap getloadlBitmap(String load_url, int width, int height) {
            Bitmap bitmap = null;
            if (!UtilText.isEmpty(load_url)) {
                File file = new File(load_url);
                if (file.exists()) {
                    FileInputStream fs = null;
                    try {
                        fs = new FileInputStream(file);
                    } catch (FileNotFoundException e) {
                        e.printStackTrace();
                    }
                    if (null != fs) {
                        try {
                            BitmapFactory.Options opts = new BitmapFactory.Options();
                            opts.inJustDecodeBounds = true;
                            BitmapFactory.decodeFileDescriptor(fs.getFD(), null, opts);
                            opts.inDither = false;
                            opts.inPurgeable = true;
                            opts.inInputShareable = true;
                            opts.inTempStorage = new byte[32 * 1024];
                            opts.inSampleSize = BitmapUtils.calculateInSampleSize(opts,
                                    UtilUnitConversion.dip2px(MyApplication.mContext, width), UtilUnitConversion.dip2px(MyApplication.mContext, height));
                            opts.inJustDecodeBounds = false;
    
                            bitmap = BitmapFactory.decodeFileDescriptor(fs.getFD(),
                                    null, opts);
                        } catch (IOException e) {
                            e.printStackTrace();
                        } finally {
                            if (null != fs) {
                                try {
                                    fs.close();
                                } catch (IOException e) {
                                    e.printStackTrace();
                                }
                            }
                        }
                    }
                }
            }
            return bitmap;
        }
    

    根据显示的图片大小进行SampleSize的计算

    public int calculateInSampleSize(BitmapFactory.Options options, int reqWidth, int reqHeight) {
            if (reqWidth == 0 || reqHeight == 0) {
                return 1;
            }
    
            // Raw height and width of image
            final int height = options.outHeight;
            final int width = options.outWidth;
            int inSampleSize = 1;
    
            if (height > reqHeight || width > reqWidth) {
                final int halfHeight = height / 2;
                final int halfWidth = width / 2;
    
                // Calculate the largest inSampleSize value that is a power of 2 and
                // keeps both height and width larger than the requested height and width.
                while ((halfHeight / inSampleSize) >= reqHeight && (halfWidth / inSampleSize) >= reqWidth) {
                    inSampleSize *= 2;
                }
            }
    
            return inSampleSize;
        }
    
    附:宽高dp值转px的工具类
        /**
         * dip 装换成 px
         * 
         * @作者 zhuofq
         * @创建时间   
         * @param context
         * @param dipValue
         * @return int
         */
        public static int dip2px(Context context, float dipValue) {
            int num = 0;
            if (context != null) {
                final float scale = context.getResources().getDisplayMetrics().density;
                num = (int) (dipValue * scale + 0.5f);
            }
            return num;
        }
    

    以上三种工具类的调用方式(设工具类名为UtilBitmap,ImageView宽高100dp):

    mImageView.setImageBitmap(UtilBitmap.decodeSampledBitmapFromResource(getResources(), R.id.myImage, 100, 100));
    
    Bitmap bitmap = UtilBitmap.decodeSampledBitmapFromUri(cropFileUri, 100, 100);
    
    mImageView.setImageBitmap(mContext, mImage,
                    UtilBitmap.getloadlBitmap(url, 100, 100),
                    R.drawable.ic_login_head, true);
    

    2. 质量压缩:指定图片缩小到xkb以下

        // 压缩到100kb以下
        int maxSize = 100 * 1024;
        public static Bitmap getBitmapByte(Bitmap oriBitmap, int maxSize) {
            ByteArrayOutputStream out = new ByteArrayOutputStream();
            oriBitmap.compress(Bitmap.CompressFormat.JPEG, 100, out);
    
            byte[] fileBytes = out.toByteArray();
    
            int be = (maxSize * 100) / fileBytes.length;
    
            if (be > 100) {
                be = 100;
            }
            out.reset();
            oriBitmap.compress(Bitmap.CompressFormat.JPEG, be, out);
            return oriBitmap;
        }
    

    3. 单纯获取图片宽高避免oom的办法

    itmapFactory.Options这个类,有一个字段叫做 inJustDecodeBounds 。SDK中对这个成员的说明是这样的:

    If set to true, the decoder will return null (no bitmap), but the out...

    也就是说,如果我们把它设为true,那么BitmapFactory.decodeFile(String path, Options opt)并不会真的返回一个Bitmap给你,它仅仅会把它的宽,高取回来给你,这样就不会占用太多的内存,也就不会那么频繁的发生OOM了。

        /**
         * 根据res获取Options,来获取宽高options.outWidth和options.outHeight
         * @param res
         * @param resId
         * @return
         */
        public static BitmapFactory.Options decodeOptionsFromResource(Resources res, int resId) {
            // First decode with inJustDecodeBounds=true to check dimensions
            final BitmapFactory.Options options = new BitmapFactory.Options();
            options.inJustDecodeBounds = true;
            BitmapFactory.decodeResource(res, resId, options);
            return options;
        }
    

    相关文章

      网友评论

        本文标题:Android 图片压缩处理避免出现oom的方法

        本文链接:https://www.haomeiwen.com/subject/emwxsxtx.html