Android上图片涉及到的要点:html
颜色空间-YUV与RGBjava
图片格式及其文件头ios
exif :使用开源库Android-Exif-Extended或者support包里的ExifInterface. 建议前者,内部时直接读文件头,没有api的限制.git
Android-Exif-Extended示例:
public native static boolean nativeCompress(Bitmap bitmap,int quality,String outPath);
public static boolean compressOringinal(String srcPath,int quality,String outPath){
Bitmap bitmap = BitmapFactory.decodeFile(srcPath);
boolean success = nativeCompress(bitmap,quality,outPath);//libjpeg压缩
if(success){
ExifInterface exif = new ExifInterface();
try {
exif.readExif( srcPath, ExifInterface.Options.OPTION_ALL );
exif.writeExif( outPath );//所有exif信息拷到新文件那儿去
} catch (IOException e) {
e.printStackTrace();
}finally {
return true;
}
}
return success;
}
复制代码
camera api是Android兼容性问题最大的地方,没有之一.因此,不要做死去用原生的,或者本身从头开始写一套. 直接用开源的.github
固然,原生api的使用仍是要掌握的,有几个比较好的博客供参考:api
Android相机开发系列:很全面数组
Android多媒体之Camera的相关操做:至关于一个概述
注意点:
注意兼容性:
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须要加上读和写权限. 若是没有写权限,部分4.4如下手机会crash:
```
intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
intent.addFlags(Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
或者这种实现:
List<ResolveInfo> resInfoList = context.getPackageManager().queryIntentActivities(intent, PackageManager.MATCH_DEFAULT_ONLY);
for (ResolveInfo resolveInfo : resInfoList) {
String packageName = resolveInfo.activityInfo.packageName;
context.grantUriPermission(packageName, uri, Intent.FLAG_GRANT_WRITE_URI_PERMISSION | Intent.FLAG_GRANT_READ_URI_PERMISSION);
}
```
复制代码
抄官方demo谁都会,但后果就是致使容易跟第三方库内部实现冲突. 这里的重点在于与其余已内部实现Uri兼容性的第三方库的兼容:
//官方demo:原封不动搬过来,就可能会有跟第三方库冲突.由于别人通常也是原封不动搬过来的
<provider
android:name="android.support.v4.content.FileProvider"
android:authorities="${applicationId}.fileProvider"
android:exported="false"
android:grantUriPermissions="true">
<meta-data
android:name="android.support.FILE_PROVIDER_PATHS"
android:resource="@xml/file_paths"/>
</provider>
//正确示范:
<provider
android:name="org.devio.takephoto.permission.TFileProvider"//name要本身继承v4里的fileprovider
android:authorities="${applicationId}.takephoto.fileprovider"//本身附加字符串,后面要提供解析方法
android:grantUriPermissions="true"
android:exported="false">
<meta-data
android:name="android.support.FILE_PROVIDER_PATHS"
android:resource="@xml/file_paths_takephoto" />//记得加后缀.尤为做为库提供时,防止被同名覆盖.
</provider>
//xml里:
<paths>
<!--外置SD卡-->
<root-path
path=""
name="camera_photos" />
//若是是库,通常只提供上面一个就够了,下面的由app本身的module去提供.
<!--Context.getFilesDir()-->
<files-path
name="files"
path=""/>
<!--Context.getCacheDir()-->
<cache-path
name="cache"
path=""/>
<!--Environment.getExternalStorageDirectory()-->
<external-path
name="external"
path=""/>
<!--Context.getExternalFilesDir(null)-->
<external-files-path
name="external_file_path"
path=""/>
<!--Context.getExternalCacheDir()--> <!--直到support-v4:25.0.0才支持-->
<external-cache-path
name="external_cache_path"
path=""/>
</paths>
//而后提供解析这个uri的方式(sd卡):
public static String parseOwnUri(Context context, Uri uri) {
if (uri == null) {
return null;
}
String path;
if (TextUtils.equals(uri.getAuthority(), context.getPackageName() + ".takephoto.fileprovider") {
path = new File(uri.getPath().replace("camera_photos/", "")).getAbsolutePath();
} else {
path = uri.getPath();
}
return path;
}
复制代码
本质上仍是由于从7.0开始强制执行sctrickmode,也能够写代码让它不执行:只是不建议这样作罢了.
/过滤URI检查
StrictMode.VmPolicy.Builder builder = new StrictMode.VmPolicy.Builder();
StrictMode.setVmPolicy(builder.build());
复制代码
能够调用系统intent去图库里选一张图,可是不一样手机的图库选择千差万别,返回的uri依据手机厂商和版本的不一样而状况不一样,有的是contentprovider形式,有的是file uri形式,Android 7.0以上如下还不一致. 另外,系统intent不支持多选. 搞来搞去,不如本身查media center数据库,本身作ui. 基本上成熟的app都是经过这种形式实现,网上开源库也一大把.
有系统intent,可是不一样手机千差万别,大多数不好劲.果断用开源的. 开源库中,ucrop秒杀其余裁剪库: github.com/Yalantis/uC…
固然,也仍有不足之处: 选择区域后裁剪该区域,不是基于原图来裁,而是基于界面上预览图来裁剪,因此会自带压缩效果.
对于手机图片来讲,80%质量和100%质量并没有肉眼可见的明显区别,而文件大小相差近一倍.彻底没有必要设为100%的质量,而若是是相机拍摄的原图而非进行尺寸压缩后的图,70%的质量已经足够.
因此,通常来讲: 通过尺寸压缩的图,可设置质量80%. 原图大小,可将质量设置为70%. 二者均可用下面的libjpeg来压缩.
Bitmap.compress->skia->libjpeg->file,file->libjpeg->skia->bitmap 全部的问题均可以从这里找到答案.
参考:www.voidcn.com/article/p-w…
彩蛋: 本身写的图片压缩工具app
结合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
示例: 78re52.com1.z0.glb.clouddn.com/resource/go…
代码示例:QiniuUtils
普通图片: fresco/glide. 通常是本身封装一层,便于切换,以及作一些全局性的处理. ImageLoader
对fresco/glide/picasso的优缺点的讨论:mPaaS 3.0 多媒体组件发布 | 支付宝百亿级图片组件 XMedia 锤炼之路(图片缓存篇)
大图: 分区域解码 subsampling-scale-image-view