android开发游记:CROP 大图片裁剪原理分析

最近项目中需要加入裁剪图片的功能,图片的来源包括相机拍照和相册手动选择,使用了系统自带的裁图功能Crop,但是实际使用中却发生了一些意想不到的问题:

  • 裁剪后返回的data为null
  • 裁剪后返回的图片严重失真

这里总结一下出现问题的原因和解决方案:

调用系统裁剪组件的需要设置一些intent参数,通常如下:

Intent intent = new Intent(Intent.ACTION_GET_CONTENT, null);
intent.setType("image/*");
intent.putExtra("crop", "true");
intent.putExtra("aspectX", 2);
intent.putExtra("aspectY", 1);
intent.putExtra("outputX", 400);
intent.putExtra("outputY", 400);
intent.putExtra("scale", true);
intent.putExtra("return-data", true);
intent.putExtra("outputFormat",Bitmap.CompressFormat.JPEG.toString());
intent.putExtra("noFaceDetection", true);
startActivityForResult(intent, 1);

上面的
intent.putExtra("return-data", true);
指定了是否返回数据
-如果设置为true,则在返回的data中能拿到返回的bitmap数据
-如果设置为false,则不会返回data,相应的会返回给玩家一个uri,这个uri关联了一张外存设备中的一张图片,就是裁剪后的图片

然而google为什么要这样设计看起来多此一举的功能呢,直接返回data不就好了吗?
这样做的主要原因是因为activity间的参数传递大小受到严格限制,这主要是考虑到手机执行性能,所以做了这样的设计。如果你裁剪的只是一张小图片,那么ok,设置return-data为true,直接从返回的data中取出bitmap就行了,如果你返回的是一张大图,那么久萎了,你会发现如果你的
intent.putExtra("outputX", 400);
intent.putExtra("outputY", 400);
这2个参数设置过大,你收到的返回bitmap将会是一个缩略图!
google这样做是为了保证系统流畅运行,这样想想也算合理。

那么,如何裁剪大图片呢?
只有把return-data设置为false
然后设置一个uri用于保存图片到外存设备

Intent intent = new Intent(Intent.ACTION_GET_CONTENT, null);
intent.setType("image/*");
intent.putExtra("crop", "true");
intent.putExtra("aspectX", 2);
intent.putExtra("aspectY", 1);
intent.putExtra("outputX", 400);
intent.putExtra("outputY", 400);
intent.putExtra("scale", true);
intent.putExtra("return-data", false);
intent.putExtra(MediaStore.EXTRA_OUTPUT, uri);
intent.putExtra("outputFormat",Bitmap.CompressFormat.JPEG.toString());
intent.putExtra("noFaceDetection", true);
startActivityForResult(intent, 1);

然后在 onActivityResult 这样处理:

switch (requestCode) {
case 1:
    if(uri != null){
        Bitmap bitmap = null;
        try {
            bitmap = BitmapFactory.decodeStream(getContentResolver().openInputStream(uri));
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        }
        imageView.setImageBitmap(bitmap);
    }
    break;
}

这样就解决的裁剪大图的问题

然而,你会发现调用系统裁剪组件会消耗大量的内存,有时候会杀死你应用的进程,导致你不得不做好应用的被杀恢复工作,在一些低端机上裁图组件根本打不开,或者直接崩溃;而且返回大图过大,而你仅仅是想要一张能看得清楚字的图就ok了,比如说营业许可证证件照,你并不希望图片过于高清占用太大的内存空间,或者上传产生过多的流量,使你不得不再次压缩图片。总之你会发现这些处理工作过于麻烦。这样你就需要使用自定义的裁图组件。

我调查发现市面上主流的应用如qq微信等,都没有使用系统裁图,而是自己编写了一个裁图组件来解决这些问题。
下一章我就分享一下如何自定义裁剪图片功能组件

你可能感兴趣的:(android,图片裁剪,crop)