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程序设计有所帮助。