Android 图像选取 图片剪裁 照相选图 照相裁剪 大全 619更新.docx
- 文档编号:27739390
- 上传时间:2023-07-04
- 格式:DOCX
- 页数:20
- 大小:20.97KB
Android 图像选取 图片剪裁 照相选图 照相裁剪 大全 619更新.docx
《Android 图像选取 图片剪裁 照相选图 照相裁剪 大全 619更新.docx》由会员分享,可在线阅读,更多相关《Android 图像选取 图片剪裁 照相选图 照相裁剪 大全 619更新.docx(20页珍藏版)》请在冰豆网上搜索。
Android图像选取图片剪裁照相选图照相裁剪大全619更新
Android图像选取图片剪裁照相选图照相裁剪大全6-19更新
本篇讲的是使用“Intent.ACTION_PICK”来选取图片并进行剪裁加载的操作,包括以下两个功能
从本地相册读取图片进行剪裁
从照相机获取图片进行剪裁
注意:
本篇使用一个工具类PickUriUtils使Uri转换成文件路径,工具类在文章最后给出.本文的Bitmap对象没有进行回收和缓存,在真正的使用中是需要进行相关的操作的,由于这里是演示,就不做多余的处理了.
技术注意点
1.返回值区别
因为我们的选图是通过第三方的选图应用来操作的,所以他们之间可能会有些区别,我们要特别注意!
!
获取剪裁图片一般会有两个过程,第一步是获取图像,第二步是剪裁图像,每一步的返回数据会有以下的类型
返回ContextUri路径——同时携带Bitmap对象
返回文件Uri路径——同时携带Bitmap对象
仅仅返回Bitmap对象
携带Bitmap对象需要”return-data”为true的状态下,如果为false,在某些选图软件则什么东西都不会返回来,所以返回Bitmap对象是必须的,但我们可以选择性使用
2.文件解析异常
在某些图库裁剪之后生成的图像文件无法被BitmapFactory.decodeFile解析出来,但这个过程是没有异常产生的,这时候我们就只能使用到携带的Bitmap对象了.
3.选取&剪裁流程区别
在一些图库中,你选取完图像之后会启动自带的剪裁工具进行剪裁或启动第三方应用剪裁,这是最理想的状态.但有的图库选取完了之后不会启动任何剪裁界面,而且直接返回一个Uri路径,这时候我们就需要单独对返回的图像进行剪裁.
开始编码
主要的注意点说完了,下面我们就开始正式编码!
我们一个个功能来做.剩下的一些细小的注意点我们边写边说.
1.使用到的参数变量
//请求码
privatefinalintREQUEST_PERMISSION=300;
privatefinalintREQUEST_CAMERA=301;
privatefinalintREQUEST_LOCAL=302;
privatefinalintREQUEST_CUT=303;
//请求参数
//临时储存点1
privatefinalStringTEMPSAVE_PATH=Environment.getExternalStorageDirectory().getPath()+"/temp.jpg";
//临时储存点2
privatefinalStringTEMPSAVE_PATH2=Environment.getExternalStorageDirectory().getPath()+"/temp2.jpg";
//剪裁图像的长
privatefinalintPICTURE_WIDTH=200;
//剪裁图像的高
privatefinalintPICTURE_HEIGHT=200;
//用于显示的ImageView
ImageViewshower;
//用于储存得到的Bitmap对象
Bitmapbitmap;
2.从图库选择图像
请求Intent构建
/**
*启动图片选取界面
*/
privatevoidrequestPickFromLocal(){
//我们需要将选取到的图像
FiletempFile=newFile(TEMPSAVE_PATH);
try{
//创建临时文件
tempFile.createNewFile();
Intentintent=newIntent(Intent.ACTION_PICK,null);
//选取的是图像类型
intent.setType("image/*");
//请求剪裁(不一定有卵用)
intent.putExtra("crop","true");
//X轴剪裁比例,一般为1
intent.putExtra("aspectX",1);
//Y轴剪裁比例,一般为1
intent.putExtra("aspectY",1);
//X轴剪裁长度
intent.putExtra("outputX",PICTURE_WIDTH);
//Y轴剪裁长度
intent.putExtra("outputY",PICTURE_HEIGHT);
//是否将剪裁后的图像以Bitmap返回
intent.putExtra("return-data",true);
//是否允许缩放(不一定有卵用)
intent.putExtra("scale",true);
//文件输出格式(不一定有卵用)
intent.putExtra("outputFormat",Bitmap.CompressFormat.JPEG.toString());
//不进行脸部识别(不一定有卵用)
intent.putExtra("noFaceDetection",true);
//得到的文件对象存放的位置,以Uri路径
intent.putExtra(MediaStore.EXTRA_OUTPUT,Uri.fromFile(tempFile));
startActivityForResult(intent,REQUEST_LOCAL);
}catch(IOExceptione){
Toast.makeText(MainActivity.this,"无法创建临时文件",Toast.LENGTH_SHORT).show();
tempFile=null;
}
}
处理从图库操作后得到的数据
/**
*处理本地选取图片后的结果
*@paramintent返回的结果Intent
*@return0:
失败1:
成功2:
还需要进行剪裁处理
*/
privateinthandlePickFromLocal(Intentintent){
if(intent==null){
//Intent为空,则这次的请求失败
return0;
}elseif(intent.getData()!
=null){
//Intent携带有Uri路径,我们优先使用它
StringresultPath=PickUriUtils.getPath(MainActivity.this,intent.getData());
if(resultPath.equals(TEMPSAVE_PATH)){
//如果返回的路径和指定的临时路径相同,则说明图片已经剪裁过,否则没有
this.bitmap=BitmapFactory.decodeFile(TEMPSAVE_PATH);
if(this.bitmap==null){
//Uri读取失败,尝试通过Bitmap读取
if(intent.hasExtra("data")){
//如果存在数据,则读取,否则当作失败
this.bitmap=intent.getParcelableExtra("data");
if(this.bitmap!
=null){
//读取成功
return1;
}else{
//读取失败
return0;
}
}else{
//没有附带数据,操作失败
return0;
}
}else{
//Uri读取成功
return1;
}
}else{
//进行剪裁之前需要将图像复制到临时文件,否则会直接剪裁原始文件并保存,导致原始文件被修改
if(copyFile(resultPath,TEMPSAVE_PATH)){
cropImageFromURI(Uri.fromFile(newFile(TEMPSAVE_PATH)));
return2;
}else{
return0;
}
}
}elseif(intent.hasExtra("data")){
//如果Intent携带有Bitmap对象,我们则直接拿出使用
/**
*这个方式虽然直接,但是对内存使用并不友好,有可能得到的Bitmap对象很大
*但是有的图像软件裁剪后不会返回Uri数据,只会返回剪裁后的Bitmap对象
*
*比如:
快图浏览,OPPO自带图库
*/
this.bitmap=intent.getParcelableExtra("data");
return1;
}else{
return0;
}
}
3.单独剪裁图像
请求Intent构建
/**
*剪裁图像
*@paramuri图像Uri
*/
privatevoidcropImageFromURI(Uriuri){
//这里我们使用2号临时文件地址,因为可能需要剪裁的文件已经存在1号地址,如果使用同一个地址会导致剪裁失败
FiletempFile=newFile(TEMPSAVE_PATH2);
try{
tempFile.createNewFile();
Intentintent=newIntent("com.android.camera.action.CROP");
//传入的第一个参数是要剪裁的文件Uri路径
intent.setDataAndType(uri,"image/*");
intent.putExtra("crop","true");
intent.putExtra("aspectX",1);
intent.putExtra("aspectY",1);
intent.putExtra("return-data",true);
intent.putExtra("scale",true);
intent.putExtra("outputX",PICTURE_WIDTH);
intent.putExtra("outputY",PICTURE_HEIGHT);
//剪裁后输出到的位置
intent.putExtra(MediaStore.EXTRA_OUTPUT,Uri.fromFile(tempFile));
startActivityForResult(intent,REQUEST_CUT);
}catch(IOExceptione){
Toast.makeText(MainActivity.this,"无法创建临时文件",Toast.LENGTH_SHORT).show();
tempFile=null;
}
}
处理剪裁后的数据
/**
*处理剪裁后的数据
*@paramresultCode返回来的resultCode
*@paramintent返回来的intent
*@return执行结果
*/
privatebooleanhandleCropFromPic(intresultCode,Intentintent){
if(resultCode==0){
//图像裁剪失败
returnfalse;
}elseif(intent.getData()!
=null){
//返回来的是Uri路径,解析后直接加载即可,其文件路径为我们在请求Intent中设定的路径TEMPSAVE_PATH2
this.bitmap=BitmapFactory.decodeFile(TEMPSAVE_PATH2);
if(this.bitmap==null){
//Uri读取失败,尝试读取Bitmap对象
if(intent.hasExtra("data")){
//如果存在数据,则读取,否则当作失败
this.bitmap=intent.getParcelableExtra("data");
}else{
//不存在Bitmap数据,读取失败
returnfalse;
}
}
returnthis.bitmap!
=null&&!
this.bitmap.isRecycled();
}elseif(intent.hasExtra("data")){
//返回来的是Bitmap对象,直接加载即可
this.bitmap=intent.getParcelableExtra("data");
returnthis.bitmap!
=null&&!
this.bitmap.isRecycled();
}else{
//其他状态,为失败
returnfalse;
}
}
以上就是两大功能,获取图像&剪裁下面我们吧一些其他地方补完
4.获取数据以及剩余操作
@Override
protectedvoidonActivityResult(intrequestCode,intresultCode,Intentdata){
super.onActivityResult(requestCode,resultCode,data);
switch(requestCode){
//图像获取请求
caseREQUEST_LOCAL:
switch(handlePickFromLocal(data)){
//处理失败
case0:
Toast.makeText(MainActivity.this,"返回数据无效",Toast.LENGTH_SHORT).show();
break;
//处理成功,显示图像
case1:
onGotBitmap(this.bitmap);
break;
//还需要单独剪裁,内部已经处理,外部就不作处理了
case2:
default:
break;
}
break;
//单独图像剪裁请求
caseREQUEST_CUT:
if(!
handleCropFromPic(resultCode,data)){
Toast.makeText(MainActivity.this,"剪裁无效",Toast.LENGTH_SHORT).show();
}else{
//剪裁处理成功,显示图像
onGotBitmap(this.bitmap);
}
break;
//照相请求(我们最后再说这个)
caseREQUEST_CAMERA:
handlePickFromCamera();
break;
default:
Toast.makeText(MainActivity.this,"未定义操作",Toast.LENGTH_SHORT).show();
break;
}
}
显示图像
/**
*最终获取到图像的时候
*@parambitmap得到的Bitmap
*/
privatevoidonGotBitmap(Bitmapbitmap){
//显示Bitmap
shower.setImageBitmap(bitmap);
//清除临时文件
newFile(TEMPSAVE_PATH).delete();
newFile(TEMPSAVE_PATH2).delete();
}
复制文件方法
/**
*复制文件
*@paramsourcePosition源文件路径
*@paramtargetPosition目的地路径
*@return执行结果
*/
privatebooleancopyFile(StringsourcePosition,StringtargetPosition){
FilesourceFile=newFile(sourcePosition);
FiletargetFile=newFile(targetPosition);
targetFile.delete();
try{
targetFile.createNewFile();
InputStreaminputStream=newFileInputStream(sourceFile);
OutputStreamoutputStream=newFileOutputStream(targetFile);
byte[]buffer=newbyte[1024];
intlength;
while((length=inputStream.read(buffer))!
=-1){
outputStream.write(buffer,0,length);
}
inputStream.close();
outputStream.flush();
outputStream.close();
returntrue;
}catch(Exceptione){
Log.e("复制文件异常",""+e);
returnfalse;
}
}
5.照相图像处理
为啥我们最后再说这个,因为…这个东西没什么可以说的,因为它仅仅是获取图像之后单独进行剪裁而已
请求Intent构建
/**
*启动摄像头获取图像
*/
privatevoidrequestPickFromCamera(){
Intentintent=newIntent(MediaStore.ACTION_IMAGE_CAPTURE);
//将拍照得到的图像,存储在临时点1
intent.putExtra(MediaStore.EXTRA_OUTPUT,Uri.fromFile(newFile(TEMPSAVE_PATH)));
startActivityForResult(intent,REQUEST_CAMERA);
}
处理得到的数据
/**
*处理拍照后得到的数据
*/
privatevoidhandlePickFromCamera(){
/**
*拍照后得到照片对象会保存在我们请求中的指定路径内TEMPSAVE_PATH.
*如果设置了带数据返回"return-data"则会在Intent中返回一个Bitmap对象
*但一般非常不建议这么使用,因为一般这个Bitmap对象会很大
*/
FilesavedFile=newFile(TEMPSAVE_PATH);
if(savedFile.exists()&&savedFile.length()>0){
//如果得到的文件存在并且有效(长度大于0)我们就将这个对象进行剪裁
cropImageFromURI(Uri.fromFile(savedFile));
}else{
//文件无效,操作失败
Toast.makeText(MainActivity.this,"无效照片文件,请检查储存空间是否已满",Toast.LENGTH_SHORT).show();
}
}
6.结尾&工具类
代码复制粘贴即可使用
publicclassPickUriUtils{
/**
*GetafilepathfromaUri.ThiswillgetthethepathforStorageAccess
*FrameworkDocuments,aswellasthe_datafieldfortheMediaStoreand
*otherfile-basedContentProviders.
*
*@paramcontextThecontext.
*@paramuriTheUritoquery.
*@authorpaulburke
*/
publicstaticStringgetPath(finalContextcontext,finalUriuri){
//DocumentProvider
if(Build.VERSION.SDK_INT>=Build.VERSION_CODES.KITKAT&&DocumentsContract.isDocumentUri(context,uri)){
//ExternalSageProvider
if(isExternalStorageDocument(uri)){
finalStringdocId=DocumentsContract.getDocumentId(uri);
finalString[]split=docId.split(":
");
finalStringtype=split[0];
if("primary".equalsIgnoreCase(type)){
returnEnvironment.getExternalStorageDirectory()+"/"+split[1];
}
//TODOhandlenon-primaryvolumes
}
//DownloadsProvider
elseif(isDownloadsDocument(uri)){
finalStringid=DocumentsContract.getDocumentId(uri);
finalUricontentUri=ContentUris.withAppendedId(
Uri.parse("content:
//downloads/public_downloads"),Long.valueOf(id));
returngetDataColumn(context,contentUri,null,null);
}
//MediaProvider
elseif(isMediaDocument(uri)){
finalStringdocId=DocumentsContract.getDocumentId(uri);
finalString[]split=docId.split(":
");
finalString
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- Android 图像选取 图片剪裁 照相选图 照相裁剪 大全 619更新 图像 选取 图片 剪裁 照相 裁剪 619 更新