Android裁剪图像实现方法示例
本文实例讲述了Android裁剪图像实现方法。分享给大家供大家参考,具体如下:
packagecom.xiaoma.piccut.demo; importjava.io.File; importandroid.app.Activity; importandroid.app.AlertDialog; importandroid.content.DialogInterface; importandroid.content.Intent; importandroid.graphics.Bitmap; importandroid.graphics.drawable.BitmapDrawable; importandroid.graphics.drawable.Drawable; importandroid.net.Uri; importandroid.os.Bundle; importandroid.os.Environment; importandroid.provider.MediaStore; importandroid.view.View; importandroid.view.View.OnClickListener; importandroid.widget.Button; importandroid.widget.ImageButton; importandroid.widget.ImageView; /** *@Title:PicCutDemoActivity.java *@Packagecom.xiaoma.piccut.demo *@Description:图片裁剪功能测试 *@authorXiaoMa */ publicclassPicCutDemoActivityextendsActivityimplementsOnClickListener{ privateImageButtonib=null; privateImageViewiv=null; privateButtonbtn=null; privateStringtp=null; /**Calledwhentheactivityisfirstcreated.*/ @Override publicvoidonCreate(BundlesavedInstanceState){ super.onCreate(savedInstanceState); setContentView(R.layout.main); //初始化 init(); } /** *初始化方法实现 */ privatevoidinit(){ ib=(ImageButton)findViewById(R.id.imageButton1); iv=(ImageView)findViewById(R.id.imageView1); btn=(Button)findViewById(R.id.button1); ib.setOnClickListener(this); iv.setOnClickListener(this); btn.setOnClickListener(this); } /** *控件点击事件实现 * *因为有朋友问不同控件的背景图裁剪怎么实现, *我就在这个地方用了三个控件,只为了自己记录学习 *大家觉得没用的可以跳过啦 */ @Override publicvoidonClick(Viewv){ switch(v.getId()){ caseR.id.imageButton1: ShowPickDialog(); break; caseR.id.imageView1: ShowPickDialog(); break; caseR.id.button1: ShowPickDialog(); break; default: break; } } /** *选择提示对话框 */ privatevoidShowPickDialog(){ newAlertDialog.Builder(this) .setTitle("设置头像...") .setNegativeButton("相册",newDialogInterface.OnClickListener(){ publicvoidonClick(DialogInterfacedialog,intwhich){ dialog.dismiss(); /** *刚开始,我自己也不知道ACTION_PICK是干嘛的,后来直接看Intent源码, *可以发现里面很多东西,Intent是个很强大的东西,大家一定仔细阅读下 */ Intentintent=newIntent(Intent.ACTION_PICK,null); /** *下面这句话,与其它方式写是一样的效果,如果: *intent.setData(MediaStore.Images.Media.EXTERNAL_CONTENT_URI); *intent.setType(""image/*");设置数据类型 *如果朋友们要限制上传到服务器的图片类型时可以直接写如:"image/jpeg、image/png等的类型" *这个地方小马有个疑问,希望高手解答下:就是这个数据URI与类型为什么要分两种形式来写呀?有什么区别? */ intent.setDataAndType( MediaStore.Images.Media.EXTERNAL_CONTENT_URI, "image/*"); startActivityForResult(intent,1); } }) .setPositiveButton("拍照",newDialogInterface.OnClickListener(){ publicvoidonClick(DialogInterfacedialog,intwhichButton){ dialog.dismiss(); /** *下面这句还是老样子,调用快速拍照功能,至于为什么叫快速拍照,大家可以参考如下官方 *文档,you_sdk_path/docs/guide/topics/media/camera.html *我刚看的时候因为太长就认真看,其实是错的,这个里面有用的太多了,所以大家不要认为 *官方文档太长了就不看了,其实是错的,这个地方小马也错了,必须改正 */ Intentintent=newIntent( MediaStore.ACTION_IMAGE_CAPTURE); //下面这句指定调用相机拍照后的照片存储的路径 intent.putExtra(MediaStore.EXTRA_OUTPUT,Uri .fromFile(newFile(Environment .getExternalStorageDirectory(), "xiaoma.jpg"))); startActivityForResult(intent,2); } }).show(); } @Override protectedvoidonActivityResult(intrequestCode,intresultCode,Intentdata){ switch(requestCode){ //如果是直接从相册获取 case1: startPhotoZoom(data.getData()); break; //如果是调用相机拍照时 case2: Filetemp=newFile(Environment.getExternalStorageDirectory() +"/xiaoma.jpg"); startPhotoZoom(Uri.fromFile(temp)); break; //取得裁剪后的图片 case3: /** *非空判断大家一定要验证,如果不验证的话, *在剪裁之后如果发现不满意,要重新裁剪,丢弃 *当前功能时,会报NullException,小马只 *在这个地方加下,大家可以根据不同情况在合适的 *地方做判断处理类似情况 * */ if(data!=null){ setPicToView(data); } break; default: break; } super.onActivityResult(requestCode,resultCode,data); } /** *裁剪图片方法实现 *@paramuri */ publicvoidstartPhotoZoom(Uriuri){ /* *至于下面这个Intent的ACTION是怎么知道的,大家可以看下自己路径下的如下网页 *yourself_sdk_path/docs/reference/android/content/Intent.html *直接在里面Ctrl+F搜:CROP,之前小马没仔细看过,其实安卓系统早已经有自带图片裁剪功能, *是直接调本地库的,小马不懂CC++这个不做详细了解去了,有轮子就用轮子,不再研究轮子是怎么 *制做的了...吼吼 */ Intentintent=newIntent("com.android.camera.action.CROP"); intent.setDataAndType(uri,"image/*"); //下面这个crop=true是设置在开启的Intent中设置显示的VIEW可裁剪 intent.putExtra("crop","true"); //aspectXaspectY是宽高的比例 intent.putExtra("aspectX",1); intent.putExtra("aspectY",1); //outputXoutputY是裁剪图片宽高 intent.putExtra("outputX",150); intent.putExtra("outputY",150); intent.putExtra("return-data",true); startActivityForResult(intent,3); } /** *保存裁剪之后的图片数据 *@parampicdata */ privatevoidsetPicToView(Intentpicdata){ Bundleextras=picdata.getExtras(); if(extras!=null){ Bitmapphoto=extras.getParcelable("data"); Drawabledrawable=newBitmapDrawable(photo); /** *下面注释的方法是将裁剪之后的图片以Base64Coder的字符方式上 *传到服务器,QQ头像上传采用的方法跟这个类似 */ /*ByteArrayOutputStreamstream=newByteArrayOutputStream(); photo.compress(Bitmap.CompressFormat.JPEG,60,stream); byte[]b=stream.toByteArray(); //将图片流以字符串形式存储下来 tp=newString(Base64Coder.encodeLines(b)); 这个地方大家可以写下给服务器上传图片的实现,直接把tp直接上传就可以了, 服务器处理的方法是服务器那边的事了,吼吼 如果下载到的服务器的数据还是以Base64Coder的形式的话,可以用以下方式转换 为我们可以用的图片类型就OK啦...吼吼 BitmapdBitmap=BitmapFactory.decodeFile(tp); Drawabledrawable=newBitmapDrawable(dBitmap); */ ib.setBackgroundDrawable(drawable); iv.setBackgroundDrawable(drawable); } } }
下裁剪中用到的类,大家详细看下头注释:
packagecom.xiaoma.piccut.demo; /** *下面这些注释是下载这个类的时候本来就有的,本来要删除的,但看了下竟然是license,吼吼, *好东西,留在注释里,以备不时之用,大家有需要加license的可以到下面的网址找哦 */ //EPL,EclipsePublicLicense,V1.0orlater,http://www.eclipse.org/legal //LGPL,GNULesserGeneralPublicLicense,V2.1orlater,http://www.gnu.org/licenses/lgpl.html //GPL,GNUGeneralPublicLicense,V2orlater,http://www.gnu.org/licenses/gpl.html //AL,ApacheLicense,V2.0orlater,http://www.apache.org/licenses //BSD,BSDLicense,http://www.opensource.org/licenses/bsd-license.php /** *ABase64encoder/decoder. * *<p> *ThisclassisusedtoencodeanddecodedatainBase64formatasdescribedinRFC1521. * *<p> *Projecthomepage:www.source-code.biz/base64coder/java *Author:Christiand'Heureuse,InventecInformatikAG,Zurich,Switzerland<br> *Multi-licensed:EPL/LGPL/GPL/AL/BSD. */ /** *这个类在上面注释的网址中有,大家可以自行下载下,也可以直接用这个, *公开的Base64Coder类(不用深究它是怎么实现的, *还是那句话,有轮子直接用轮子),好用的要死人了... *小马也很无耻的引用了这个网址下的东东,吼吼... *@Title:Base64Coder.java *@Packagecom.xiaoma.piccut.demo *@Description:TODO *@authorXiaoMa */ publicclassBase64Coder{ //Thelineseparatorstringoftheoperatingsystem. privatestaticfinalStringsystemLineSeparator=System.getProperty("line.separator"); //Mappingtablefrom6-bitnibblestoBase64characters. privatestaticchar[]map1=newchar[64]; static{ inti=0; for(charc='A';c<='Z';c++)map1[i++]=c; for(charc='a';c<='z';c++)map1[i++]=c; for(charc='0';c<='9';c++)map1[i++]=c; map1[i++]='+';map1[i++]='/';} //MappingtablefromBase64charactersto6-bitnibbles. privatestaticbyte[]map2=newbyte[128]; static{ for(inti=0;i<map2.length;i++)map2[i]=-1; for(inti=0;i<64;i++)map2[map1[i]]=(byte)i;} /** *EncodesastringintoBase64format. *Noblanksorlinebreaksareinserted. *@paramsAStringtobeencoded. *@returnAStringcontainingtheBase64encodeddata. */ publicstaticStringencodeString(Strings){ returnnewString(encode(s.getBytes()));} /** *EncodesabytearrayintoBase64formatandbreakstheoutputintolinesof76characters. *Thismethodiscompatiblewithsun.misc.BASE64Encoder.encodeBuffer(byte[]). *@paraminAnarraycontainingthedatabytestobeencoded. *@returnAStringcontainingtheBase64encodeddata,brokenintolines. */ publicstaticStringencodeLines(byte[]in){ returnencodeLines(in,0,in.length,76,systemLineSeparator);} /** *EncodesabytearrayintoBase64formatandbreakstheoutputintolines. *@paraminAnarraycontainingthedatabytestobeencoded. *@paramiOffOffsetofthefirstbytein<code>in</code>tobeprocessed. *@paramiLenNumberofbytestobeprocessedin<code>in</code>,startingat<code>iOff</code>. *@paramlineLenLinelengthfortheoutputdata.Shouldbeamultipleof4. *@paramlineSeparatorThelineseparatortobeusedtoseparatetheoutputlines. *@returnAStringcontainingtheBase64encodeddata,brokenintolines. */ publicstaticStringencodeLines(byte[]in,intiOff,intiLen,intlineLen,StringlineSeparator){ intblockLen=(lineLen*3)/4; if(blockLen<=0)thrownewIllegalArgumentException(); intlines=(iLen+blockLen-1)/blockLen; intbufLen=((iLen+2)/3)*4+lines*lineSeparator.length(); StringBuilderbuf=newStringBuilder(bufLen); intip=0; while(ip<iLen){ intl=Math.min(iLen-ip,blockLen); buf.append(encode(in,iOff+ip,l)); buf.append(lineSeparator); ip+=l;} returnbuf.toString();} /** *EncodesabytearrayintoBase64format. *Noblanksorlinebreaksareinsertedintheoutput. *@paraminAnarraycontainingthedatabytestobeencoded. *@returnAcharacterarraycontainingtheBase64encodeddata. */ publicstaticchar[]encode(byte[]in){ returnencode(in,0,in.length);} /** *EncodesabytearrayintoBase64format. *Noblanksorlinebreaksareinsertedintheoutput. *@paraminAnarraycontainingthedatabytestobeencoded. *@paramiLenNumberofbytestoprocessin<code>in</code>. *@returnAcharacterarraycontainingtheBase64encodeddata. */ publicstaticchar[]encode(byte[]in,intiLen){ returnencode(in,0,iLen);} /** *EncodesabytearrayintoBase64format. *Noblanksorlinebreaksareinsertedintheoutput. *@paraminAnarraycontainingthedatabytestobeencoded. *@paramiOffOffsetofthefirstbytein<code>in</code>tobeprocessed. *@paramiLenNumberofbytestoprocessin<code>in</code>,startingat<code>iOff</code>. *@returnAcharacterarraycontainingtheBase64encodeddata. */ publicstaticchar[]encode(byte[]in,intiOff,intiLen){ intoDataLen=(iLen*4+2)/3;//outputlengthwithoutpadding intoLen=((iLen+2)/3)*4;//outputlengthincludingpadding char[]out=newchar[oLen]; intip=iOff; intiEnd=iOff+iLen; intop=0; while(ip<iEnd){ inti0=in[ip++]&0xff; inti1=ip<iEnd?in[ip++]&0xff:0; inti2=ip<iEnd?in[ip++]&0xff:0; into0=i0>>>2; into1=((i0&3)<<4)|(i1>>>4); into2=((i1&0xf)<<2)|(i2>>>6); into3=i2&0x3F; out[op++]=map1[o0]; out[op++]=map1[o1]; out[op]=op<oDataLen?map1[o2]:'=';op++; out[op]=op<oDataLen?map1[o3]:'=';op++;} returnout;} /** *DecodesastringfromBase64format. *NoblanksorlinebreaksareallowedwithintheBase64encodedinputdata. *@paramsABase64Stringtobedecoded. *@returnAStringcontainingthedecodeddata. *@throwsIllegalArgumentExceptionIftheinputisnotvalidBase64encodeddata. */ publicstaticStringdecodeString(Strings){ returnnewString(decode(s));} /** *DecodesabytearrayfromBase64formatandignoreslineseparators,tabsandblanks. *CR,LF,TabandSpacecharactersareignoredintheinputdata. *Thismethodiscompatiblewith<code>sun.misc.BASE64Decoder.decodeBuffer(String)</code>. *@paramsABase64Stringtobedecoded. *@returnAnarraycontainingthedecodeddatabytes. *@throwsIllegalArgumentExceptionIftheinputisnotvalidBase64encodeddata. */ publicstaticbyte[]decodeLines(Strings){ char[]buf=newchar[s.length()+3]; intp=0; for(intip=0;ip<s.length();ip++){ charc=s.charAt(ip); if(c!=''&&c!='\r'&&c!='\n'&&c!='\t') buf[p++]=c;} while((p%4)!=0) buf[p++]='0'; returndecode(buf,0,p);} /** *DecodesabytearrayfromBase64format. *NoblanksorlinebreaksareallowedwithintheBase64encodedinputdata. *@paramsABase64Stringtobedecoded. *@returnAnarraycontainingthedecodeddatabytes. *@throwsIllegalArgumentExceptionIftheinputisnotvalidBase64encodeddata. */ publicstaticbyte[]decode(Strings){ returndecode(s.toCharArray());} /** *DecodesabytearrayfromBase64format. *NoblanksorlinebreaksareallowedwithintheBase64encodedinputdata. *@paraminAcharacterarraycontainingtheBase64encodeddata. *@returnAnarraycontainingthedecodeddatabytes. *@throwsIllegalArgumentExceptionIftheinputisnotvalidBase64encodeddata. */ publicstaticbyte[]decode(char[]in){ returndecode(in,0,in.length);} /** *DecodesabytearrayfromBase64format. *NoblanksorlinebreaksareallowedwithintheBase64encodedinputdata. *@paraminAcharacterarraycontainingtheBase64encodeddata. *@paramiOffOffsetofthefirstcharacterin<code>in</code>tobeprocessed. *@paramiLenNumberofcharacterstoprocessin<code>in</code>,startingat<code>iOff</code>. *@returnAnarraycontainingthedecodeddatabytes. *@throwsIllegalArgumentExceptionIftheinputisnotvalidBase64encodeddata. */ publicstaticbyte[]decode(char[]in,intiOff,intiLen){ if(iLen%4!=0)thrownewIllegalArgumentException("LengthofBase64encodedinputstringisnotamultipleof4."); while(iLen>0&&in[iOff+iLen-1]=='=')iLen--; intoLen=(iLen*3)/4; byte[]out=newbyte[oLen]; intip=iOff; intiEnd=iOff+iLen; intop=0; while(ip<iEnd){ inti0=in[ip++]; inti1=in[ip++]; inti2=ip<iEnd?in[ip++]:'A'; inti3=ip<iEnd?in[ip++]:'A'; if(i0>127||i1>127||i2>127||i3>127) thrownewIllegalArgumentException("IllegalcharacterinBase64encodeddata."); intb0=map2[i0]; intb1=map2[i1]; intb2=map2[i2]; intb3=map2[i3]; if(b0<0||b1<0||b2<0||b3<0) thrownewIllegalArgumentException("IllegalcharacterinBase64encodeddata."); into0=(b0<<2)|(b1>>>4); into1=((b1&0xf)<<4)|(b2>>>2); into2=((b2&3)<<6)|b3; out[op++]=(byte)o0; if(op<oLen)out[op++]=(byte)o1; if(op<oLen)out[op++]=(byte)o2;} returnout;} //Dummyconstructor. privateBase64Coder(){} }//endclassBase64Coder
更多关于Android相关内容感兴趣的读者可查看本站专题:《Android图形与图像处理技巧总结》、《Android开发入门与进阶教程》、《Android调试技巧与常见问题解决方法汇总》、《Android多媒体操作技巧汇总(音频,视频,录音等)》、《Android基本组件用法总结》、《Android视图View技巧总结》、《Android布局layout技巧总结》及《Android控件用法总结》
希望本文所述对大家Android程序设计有所帮助。