概述
Android上图片涉及到的要点:
- 自定义相机拍照
- 调用系统相机拍照
- 图片选择
- 裁剪
- 压缩
- 上传
- 服务端处理与下载
- 显示与内存-普通图与超大图
- 文件夹管理
- 内置图片管理与包大小
自定义相机拍照
camera api是Android兼容性问题最大的地方,没有之一.所以,不要作死去用原生的,或者自己从头开始写一套. 直接用开源的.
注意点:
- preview和takepicture两套不同的操作,不同的supportedSize.
- takepicture的自拍镜像问题
- 图像矩阵横屏90°.方向旋转可以用纯java数组转换,也可以用opencv 的api,或者renderscript,或者利用bitmap中转.
- 最终图像质量:如果对图片质量(清晰度,亮度)有所要求,可以使用preview的api来采集多帧,取评价最高的一帧作为最终的结果. 评价标准方面,可以基于opencv开发一套对清晰度和亮度判断的算法. 更牛的就是多帧合成,顶级实践就是谷歌,华为,小米的超级夜景算法.
调用系统相机拍照
注意兼容性:
- 构建intent时指定文件保存位置,避免有些机型拿不到默认存储位置的返回
- Uri 在7.0以上系统的兼容
- 8.0以上系统,即使是调用系统相机拍照,也需要请求权限,否则crash
Intent takeIntent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
Uri photoUri = getMediaFileUri(TYPE_TAKE_PHOTO);
takeIntent.putExtra(MediaStore.EXTRA_OUTPUT, photoUri);
startActivityForResult(takeIntent, CODE_TAKE_PHOTO);
复制代码
图片选择
可以调用系统intent去图库里选一张图,但是不同手机的图库选择千差万别,返回的uri依据手机厂商和版本的不同而情况不同,有的是contentprovider形式,有的是file uri形式,Android 7.0以上以下还不一致. 另外,系统intent不支持多选. 搞来搞去,不如自己查media center数据库,自己做ui. 基本上成熟的app都是通过这种形式实现,网上开源库也一大把.
图片裁剪
有系统intent,但是不同手机千差万别,大多数很差劲.果断用开源的. 开源库中,ucrop秒杀其他裁剪库: github.com/Yalantis/uC…
图片压缩
- 尺寸压缩与质量压缩:
- Android skia库的bug: 多次压缩的图片发绿问题
- libjpeg-turbo库在Android上的压缩优化
- 模仿微信压缩效果的库: Luban
拍照/图片选择-图片裁剪-压缩 的整合
结合app业务的二次封装技巧: 透明fragment接收onactivityResult,达到最终静态方法+回调的一行代码调用的效果:
TakePhotoUtil.startPickOne(fragmentActivity, isForCamera, new TakeOnePhotoListener() {
@Override
public void onSuccess(String usableFilePath) {
showImg(usableFilePath);
}
@Override
public void onFail(String filePath, String msg) {
MyToast.errorBigL(msg);
//toTakePhotoMode();
}
@Override
public void onCancel() {
// toTakePhotoMode();
}
});
复制代码
ps. 透明fragment的封装技巧参考: RxPermissionsFragment
图片上传
- 控制图片源,尽量小
- 多图并发,结合rxjava
- 顶层封装,api友好
服务端处理与下载
- CDN缓存
- 提供服务端处理能力:resize,裁剪,模糊.七牛和阿里云的图片存储服务均提供了此类功能.客户端通过url后添加参数,获得比原图小的图片,节省流量. 78re52.com1.z0.glb.clouddn.com/resource/go… 示例:QiniuUtils
客户端显示
- 普通图片: fresco/glide. 自己封装一层,便于切换
- 大图: 分区域解码 subsampling-scale-image-view
文件夹管理
- 项目中提供统一的获取方法,删除方法
- cache使用的注意事项:存储不足时会被系统优先清空
内置图片管理与包大小
- tinypng/tinyjpg先压缩一遍
- 用不到透明通道的png统一转换成jpg
- 大一些的图,可以放到服务端,首次进入app时下载到files文件夹.