美文网首页小技巧AndroidAndroid
Android图片尺寸与质量压缩你用对了吗?

Android图片尺寸与质量压缩你用对了吗?

作者: SnapKit | 来源:发表于2016-12-05 00:09 被阅读6286次

0x00-从图库中选择图片

这点不难,通过隐式意图跳转到图库,然后在onActivityResult中拿到返回结果
这里面需要注意以下几点:
1、选择图库中的照片在6.0之后个别手机需要权限,如华为;你会发现图库可以跳转进去,但是选中图片之后会报没有相关权限,这里主要是存储权限,华为手机比较特殊,需要去申请运行时权限。
2、onActivityResult中返回的是一个Uri,需要根据Uri翻查图片的真实路径,在Android4.4之后对图库做了调整,需要通过不同的方式进行查询;正常情况下Uri是以content开头但是有一种情况是特例,比如小米云相册(这个现在不知道是否已经统一),返回的Uri是file开头的,需要单独处理。代码如下:

Intent intent = new Intent(Intent.ACTION_PICK, null);
intent.setDataAndType(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, "image/*");
startActivityForResult(intent, REQUEST_CODE_NATIVE_PHOTO);```

public static String getPhotoPath(Context context, Uri uri) {
String filePath = "";
if (uri != null) {
Log.d(TAG, uri.toString());
String scheme = uri.getScheme();
if (TextUtils.equals("content", scheme)) {// android 4.4以上版本处理方式
if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.KITKAT
&& DocumentsContract.isDocumentUri(context, uri)) {
String wholeID = DocumentsContract.getDocumentId(uri);
String id = wholeID.split(":")[1];
String[] column = { MediaStore.Images.Media.DATA };
String sel = MediaStore.Images.Media._ID + "=?";
Cursor cursor = context.getContentResolver().query(MediaStore.Images.Media.EXTERNAL_CONTENT_URI,
column, sel, new String[] { id }, null);
if (cursor != null && cursor.moveToFirst()) {
int columnIndex = cursor.getColumnIndex(column[0]);
filePath = cursor.getString(columnIndex);
cursor.close();
}
} else {// android 4.4以下版本处理方式
String[] filePathColumn = { MediaStore.Images.Media.DATA };
Cursor cursor = context.getContentResolver().query(uri, filePathColumn, null, null, null);
if (cursor != null && cursor.moveToFirst()) {
int columnIndex = cursor.getColumnIndex(filePathColumn[0]);
filePath = cursor.getString(columnIndex);
Log.d(TAG, "filePath" + filePath);
cursor.close();
}
}
} else if (TextUtils.equals("file", scheme)) {// 小米云相册处理方式
filePath = uri.getPath();
}

    }
    return filePath;
}```

0x01-尺寸压缩之inSampleSize

这个都知道是为了防止加载图片时内存溢出,需要先计算采样率,然后再去加载图片这里要说的也有两点:
1、inSampleSize只能是2的次方,如计算结果是7会按4进行压缩,计算结果是15会按8进行压缩。
2、存在两种算法:
算法一:图片长与目标长比,图片宽与目标宽比,取最大值(不过也有人取最小值,怕压缩的太多吗?取最小值会遇到的问题举个例子,满屏加载长截图的时候,图片宽与屏幕宽为1:1,这样inSampleSize就为1,没有压缩那么很容易就内存溢出了),不管怎么都欠妥;因为如果手机是横屏拍摄,或者是拍摄的全景图,那么图片宽与目标宽的比例会很增大,这样压缩的比例会偏大。

public static int calculateInSampleSize(BitmapFactory.Options options, int reqWidth, int reqHeight) {
        final int width = options.outWidth;
        final int height = options.outHeight;
        int inSampleSize = 1;

        if (height > reqHeight || width > reqWidth) {
            //计算图片高度和我们需要高度的最接近比例值
            final int heightRatio = Math.round((float) height / (float) reqHeight);
            //宽度比例值
            final int widthRatio = Math.round((float) width / (float) reqWidth);
            //取比例值中的较大值作为inSampleSize
            inSampleSize = heightRatio > widthRatio ? heightRatio : widthRatio;
        }

        return inSampleSize;
    }

算法二:取目标长宽的最大值来计算,这样会减少过度的尺寸压缩,

public static int calculateInSampleSize(BitmapFactory.Options options, int reqWidth, int reqHeight) {
        final int width = options.outWidth;
        final int height = options.outHeight;
        int inSampleSize = 1;

        if (height > reqHeight || width > reqWidth) {
            //使用需要的宽高的最大值来计算比率
            final int suitedValue = reqHeight > reqWidth ? reqHeight : reqWidth;
            final int heightRatio = Math.round((float) height / (float) suitedValue);
            final int widthRatio = Math.round((float) width / (float) suitedValue);

            inSampleSize = heightRatio > widthRatio ? heightRatio : widthRatio;//用最大
        }

        return inSampleSize;
    }```
##0x02-质量压缩之quality
发现很多人有一个错误认识,本人曾经也不例外,就是误以为,这个比例是文件压缩前后大小的比值,因此会用目标大小/目前文件大小,来计算这个quality,其实这是错误的。因为这完全是两码事,比如压缩前是1.5M,目标大小是1M,好大概计算一下是60左右,压完了之后你可能会发现图片只有100多k;好像没有可以直接算出来这个比例的方法,常见的都是尝试式的算法,如从100开始,每次减少6,压缩一次比较一次,直到满足条件,当然这个可以自己调整。

ByteArrayOutputStream baos = new ByteArrayOutputStream();
int option = 100;
bitmap.compress(Bitmap.CompressFormat.JPEG, option, baos);
while (baos.toByteArray().length / 1024 > maxSize&&option>6) {
baos.reset();
option -= 6;
bitmap.compress(Bitmap.CompressFormat.JPEG, option, baos);
}```

0x03-图片的旋转角度之ExifInterface

图片的旋转角度在很多人做压缩的时候都会加上一笔,这个说实话我没有太多的研究,因为我用的手机不管怎么弄旋转角度都是0;如我们竖着拍照,图库里面的照片是竖着显示的;横着拍照,之后发现图库里面的照片是横着显示的(宽>高的形式展示),但是旋转角度都是0;然后我又把其中一张照片编辑一下 让它旋转一下保存,发现之后的旋转角度依然是0。可能是我的手机的问题,也可能是这个旋转角度会在个别手机上有体现。废话不多说贴上代码

private int getImageSpinAngle(String path) {
        int degree = 0;
        try {
            ExifInterface exifInterface = new ExifInterface(path);
            int orientation = exifInterface.getAttributeInt(ExifInterface.TAG_ORIENTATION,
                    ExifInterface.ORIENTATION_NORMAL);
            switch (orientation) {
                case ExifInterface.ORIENTATION_ROTATE_90:
                    degree = 90;
                    break;
                case ExifInterface.ORIENTATION_ROTATE_180:
                    degree = 180;
                    break;
                case ExifInterface.ORIENTATION_ROTATE_270:
                    degree = 270;
                    break;
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
        return degree;
    }```
##0x04-延伸
介绍一些github知名的压缩算法,luban算法
https://github.com/Curzibn/Luban
https://github.com/shaohui10086/AdvancedLuban
当然这都是从参数上的优化,star很多问题也很多,说明并非所有需求都适用,最重要的还是能够满足项目需求的算法才是最好的。

相关文章

  • Android图片尺寸与质量压缩你用对了吗?

    0x00-从图库中选择图片 这点不难,通过隐式意图跳转到图库,然后在onActivityResult中拿到返回结果...

  • [转]Bitmap的优化

    Bitmap的优化套路很简单,粗暴,就是让压缩。三种压缩方式: 对图片质量进行压缩 对图片尺寸进行压缩 使用lib...

  • iOS 图片压缩方法

    图片压缩可以通过两种方式实现,压缩图片质量和压缩图片尺寸。如果对图片清晰度有要求的,可以先压缩图片质量,在压缩图片...

  • 图片压缩---iOS笔记摘录

    方式一:压缩图片质量 方式二:压缩图片尺寸 工作使用

  • 图片压缩方法

    两种图片压缩方法 压缩图片质量(quality)、压缩图片尺寸(size) 压缩图片质量 或 前者可以控制压缩比例...

  • iOS 图片压缩方法

    两种图片压缩方法 两种图片压缩方法:压缩图片质量(Quality),压缩图片尺寸(Size)。 压缩图片质量 通过...

  • Android图片尺寸压缩和质量压缩

    遇到坑了,已解决。待研究~

  • iOS 图片压缩限制大小

    一、两种图片压缩方法 两种压缩图片的方法:压缩图片质量(Quality),压缩图片尺寸(Size)。 压缩图片质量...

  • iOS 图片压缩方法

    两种图片压缩方法 两种压缩图片的方法:压缩图片质量(Quality),压缩图片尺寸(Size)。 压缩图片质量 N...

  • iOS 图片压缩 压缩到指定大小 质量和尺寸压缩

    有时候一些功能需要上传规定大小的图片,所以我们要对图片进行压缩。 思路:图片质量压缩 + 图片尺寸压缩首先对图片进...

网友评论

    本文标题:Android图片尺寸与质量压缩你用对了吗?

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