Android 图像裁剪功用完成详解(相似QQ自定义头像裁剪)-Android-优质IT资源分享社区

admin
管理员
管理员
  • UID1
  • 粉丝26
  • 关注4
  • 发帖数581
  • 社区居民
  • 忠实会员
  • 原创写手
阅读:165回复:0

 Android 图像裁剪功用完成详解(相似QQ自定义头像裁剪)

楼主#
更多 发布于:2016-05-22 14:55


近来有看到有兄弟在评论QQ头像的裁剪上载是怎样完成的,吼吼,小马也没做过,好奇之下学习下,发现曾经项目中有类型的功用,联系官方文档里边的解说,就非常好玩了,周末,急急忙忙写的,记载在博客里,期望能与咱们交流学习,也恳请高手能答复小马在代码注释中提出的疑问,不论有没有人答复,小马先谢谢了,相同的,先看下效果图(效果图小马不解说了,直接流水写下去,小马是直接在模拟器里写的,能在真机上运用,由于很简略),再看代码是怎样完成的:
一:主规划界面

二:点击控件触发事情后效果图

三:摄影完以后效果图

四:裁剪界面效果图

五:点击相册后回来的图像效果图

六:裁剪完从相册PICK的保存后的效果图

下面直接来看下主操控类代码,如下:
package com.xiaoma.piccut.demo;import
java.io.File;import android.app.Activity;import android.app.AlertDialog;import
android.content.DialogInterface;import android.content.Intent;import
android.graphics.Bitmap;import android.graphics.drawable.BitmapDrawable;import
android.graphics.drawable.Drawable;import android.net.Uri;import
android.os.Bundle;import android.os.Environment;import
android.provider.MediaStore;import android.view.View;import
android.view.View.OnClickListener;import android.widget.Button;import
android.widget.ImageButton;import android.widget.ImageView;     /**       *
@Title: PicCutDemoActivity.java       * @Package com.xiaoma.piccut.demo       *
@Description: 图像裁剪功用测验       * @author XiaoMa       */     public class
PicCutDemoActivity extends Activity implements OnClickListener {        
 private ImageButton ib = null;          private ImageView iv = null;        
 private Button btn = null;          private String tp = null;          /**
Called when the activity is first created. */          @Override          public
void onCreate(Bundle savedInstanceState) {              
super.onCreate(savedInstanceState);               setContentView(R.layout.main);
              //初始化               init();          }          /**            *
初始化办法完成            */          private void init() {                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          public void onClick(View
v) {               switch (v.getId()) {               case R.id.imageButton1:  
                 ShowPickDialog();                    break;               case
R.id.imageView1:                    ShowPickDialog();                    break;
              case R.id.button1:                    ShowPickDialog();          
         break;               default:                    break;          }    
}     /**       * 选择提示对话框       */     private void ShowPickDialog() { new
AlertDialog.Builder(this)                  .setTitle("设置头像...")                
 .setNegativeButton("相册", new DialogInterface.OnClickListener() {          
 public void onClick(DialogInterface dialog, int which) {                
dialog.dismiss();                 /**                   *
刚开始,我自个也不知道ACTION_PICK是干嘛的,后来直接看Intent源码,                   *
能够发现里边许多东西,Intent是个很强大的东西,咱们一定细心阅读下                   */                 Intent
intent = new Intent(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("摄影", new
DialogInterface.OnClickListener() {             public void
onClick(DialogInterface dialog, int whichButton) {                
 dialog.dismiss();                  /**                    *
下面这句仍是老样子,调用迅速摄影功用,至于为何叫迅速摄影,咱们能够参考如下官方                    *
文档,you_sdk_path/docs/guide/topics/media/camera.html                    *
我刚看的时分由于太长就细心看,其实是错的,这个里边有用的太多了,所以咱们不要以为                    *
官方文档太长了就不看了,其实是错的,这个当地小马也错了,有必要改正                    */                  Intent
intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);                
 //下面这句指定调用相机摄影后的相片存储的途径                
 intent.putExtra(MediaStore.EXTRA_OUTPUT, Uri.fromFile(new
File(Environment.getExternalStorageDirectory(), "xiaoma.jpg")));                
 startActivityForResult(intent, 2);              }      }).show();}    
 @Override      protected void onActivityResult(int requestCode, int resultCode,
Intent data) {            switch (requestCode) {            // 假如是直接从相册获取      
     case 1:                 startPhotoZoom(data.getData());                
break;            // 假如是调用相机摄影时            case 2:                 File temp =
new File(Environment.getExternalStorageDirectory() + "/xiaoma.jpg");            
    startPhotoZoom(Uri.fromFile(temp));                 break;            //
获得裁剪后的图像            case 3:                 /**                   *
非空判别咱们一定要验证,假如不验证的话,                   * 在取舍以后假如发现不满意,要从头裁剪,丢掉                  
* 当时功用时,会报NullException,小马只                   * 在这个当地加下,咱们能够依据不相同状况在适宜的        
          * 当地做判别处理相似状况                   *                   */                
if(data != null){                        setPicToView(data);                 }  
               break;           default:                  break;          }    
     super.onActivityResult(requestCode, resultCode, data);    }    /**      *
裁剪图像办法完成      * @param uri      */    public void startPhotoZoom(Uri uri) {    
    /*          * 至于下面这个Intent的ACTION是怎样知道的,咱们能够看下自个途径下的如下页面          *
yourself_sdk_path/docs/reference/android/content/Intent.html          *
直接在里边Ctrl+F搜:CROP ,之前小马没细心看过,其实安卓体系早已经有自带图像裁剪功用,          * 是直接调本地库的,小马不懂C C++
 这个不做具体了解去了,有轮子就用轮子,不再研讨轮子是怎样          * 制做的了...吼吼          */         Intent
intent = new Intent("com.android.camera.action.CROP");        
intent.setDataAndType(uri, "image/*");        
//下面这个crop=true是设置在开启的Intent中设置显示的VIEW可裁剪         intent.putExtra("crop",
"true");         // aspectX aspectY 是宽高的份额         intent.putExtra("aspectX",
1);         intent.putExtra("aspectY", 1);         // outputX outputY 是裁剪图像宽高  
      intent.putExtra("outputX", 150);         intent.putExtra("outputY", 150);
        intent.putExtra("return-data", true);        
startActivityForResult(intent, 3);    }    /**      * 保存裁剪以后的图像数据      * @param
picdata      */    private void setPicToView(Intent picdata) {          Bundle
extras = picdata.getExtras();          if (extras != null) {              
 Bitmap photo = extras.getParcelable("data");                Drawable drawable =
new BitmapDrawable(photo);                /**                  *
下面注释的办法是将裁剪以后的图像以Base64Coder的字符办法上                  * 传到服务器,QQ头像上载选用的办法跟这个相似    
             */                /*ByteArrayOutputStream stream = new
ByteArrayOutputStream();                
 photo.compress(Bitmap.CompressFormat.JPEG, 60, stream);                  byte[]
b = stream.toByteArray();                  // 将图像流以字符串办法存储下来                  tp
= new String(Base64Coder.encodeLines(b));                
 这个当地咱们能够写下给服务器上载图像的完成,直接把tp直接上载就能够了,                  服务器处理的办法是服务器那儿的事了,吼吼    
             假如下载到的服务器的数据仍是以Base64Coder的办法的话,能够用以下办法转换为咱们能够用的图像类型就OK啦...        
         Bitmap dBitmap = BitmapFactory.decodeFile(tp);                
 Drawable drawable = new BitmapDrawable(dBitmap);                  */          
       ib.setBackgroundDrawable(drawable);                
 iv.setBackgroundDrawable(drawable);           }     }}
下面来看下裁剪中用到的类,咱们具体看下头注释:
package com.xiaoma.piccut.demo;/***
下面这些注释是下载这个类的时分正本就有的,正本要删去的,但看了下竟然是license,吼吼,*
好东西,留在注释里,以备不时之用,咱们有需求加license的能够到下面的网址找哦*///EPL, Eclipse Public License, V1.0
or later, http://www.eclipse.org/legal//LGPL, GNU Lesser General Public License,
V2.1 or later, http://www.gnu.org/licenses/lgpl.html//GPL, GNU General Public
License, V2 or later, http://www.gnu.org/licenses/gpl.html//AL, Apache License,
V2.0 or later, http://www.apache.org/licenses//BSD, BSD License,
http://www.opensource.org/licenses/bsd-license.php/*** A Base64
encoder/decoder.**
* This class is used to encode and decode data in
Base64 format as described in RFC 1521.**
* Project home page: www.source-code.biz/base64coder/java
* Author: Christian d'Heureuse, Inventec Informatik AG,
Zurich, Switzerland
* Multi-licensed: EPL / LGPL /
GPL / AL / BSD.*//*** 这个类在上面注释的网址中有,咱们能够自行下载下,也能够直接用这个,*
揭露的Base64Coder类(不必深究它是怎样完成的,* 仍是那句话,有轮子直接用轮子),好用的要死人了...*
小马也很无耻的引用了这个网址下的东东,吼吼...* @Title: Base64Coder.java* @Package
com.xiaoma.piccut.demo* @Description: TODO* @author XiaoMa*/public class
Base64Coder {     //The line separator string of the operating system.    
private static final String systemLineSeparator =
System.getProperty("line.separator");     //Mapping table from 6-bit nibbles to
Base64 characters.     private static char[]    map1 = new char[64];        
 static {               int i=0;               for (char c='A'; c<='Z'; c++)
map1[i++] = c;               for (char c='a'; c<='z'; c++) map1[i++] = c;    
          for (char c='0'; c<='9'; c++) map1[i++] = c;              
map1[i++] = '+'; map1[i++] = '/'; }          //Mapping table from Base64
characters to 6-bit nibbles.          private static byte[]    map2 = new
byte[128];          static {               for (int i=0; i<map2.length; i++)
map2 = -1;               for (int i=0; i<64; i++) map2[map1] = (byte)i;
}          /**            * Encodes a string into Base64 format.            * No
blanks or line breaks are inserted.            * @param s  A String to be
encoded.            * @return   A String containing the Base64 encoded data.    
       */         public static String encodeString (String s) {            
 return new String(encode(s.getBytes())); }         /**           * Encodes a
byte array into Base 64 format and breaks the output into lines of 76
characters.           * This method is compatible with sun.misc.BASE64Encoder.encodeBuffer(byte[]).           * @param in
 An array containing the data bytes to be encoded.           * @return    A
String containing the Base64 encoded data, broken into lines.           */      
  public static String encodeLines (byte[] in) {              return
encodeLines(in, 0, in.length, 76, systemLineSeparator); }         /**          
* Encodes a byte array into Base 64 format and breaks the output into lines.    
      * @param in            An array containing the data bytes to be encoded.  
        * @param iOff          Offset of the first byte in in to be
processed.           * @param iLen          Number of bytes to be processed in in, starting at iOff.           * @param lineLen      
Line length for the output data. Should be a multiple of 4.           * @param
lineSeparator The line separator to be used to separate the output lines.      
    * @return              A String containing the Base64 encoded data, broken
into lines.           */         public static String encodeLines (byte[] in,
int iOff, int iLen, int lineLen, String lineSeparator) {              int
blockLen = (lineLen*3) / 4;              if (blockLen <= 0) throw new
IllegalArgumentException();                    int lines = (iLen+blockLen-1) /
blockLen;              int bufLen = ((iLen+2)/3)*4 +
lines*lineSeparator.length();              StringBuilder buf = new
StringBuilder(bufLen);              int ip = 0;              while (ip <
iLen) {                    int l = Math.min(iLen-ip, blockLen);                
   buf.append (encode(in, iOff+ip, l));                    buf.append
(lineSeparator);                    ip += l; }              return
buf.toString(); }         /**           * Encodes a byte array into Base64
format.           * No blanks or line breaks are inserted in the output.        
  * @param in  An array containing the data bytes to be encoded.           *
@return    A character array containing the Base64 encoded data.           */  
     public static char[] encode (byte[] in) {             return encode(in, 0,
in.length); }        /**          * Encodes a byte array into Base64 format.    
     * No blanks or line breaks are inserted in the output.          * @param in
   An array containing the data bytes to be encoded.          * @param iLen
 Number of bytes to process in in.          * @return      A
character array containing the Base64 encoded data.          */        public
static char[] encode (byte[] in, int iLen) {             return encode(in, 0,
iLen); }        /**          * Encodes a byte array into Base64 format.        
 * No blanks or line breaks are inserted in the output.          * @param in  
 An array containing the data bytes to be encoded.          * @param iOff
 Offset of the first byte in in to be processed.          * @param
iLen  Number of bytes to process in in, starting at iOff.          * @return      A character array containing the
Base64 encoded data.          */        public static char[] encode (byte[] in,
int iOff, int iLen) {             int oDataLen = (iLen*4+2)/3;       // output
length without padding             int oLen = ((iLen+2)/3)*4;         // output
length including padding             char[] out = new char[oLen];            
int ip = iOff;             int iEnd = iOff + iLen;             int op = 0;      
      while (ip < iEnd) {                  int i0 = in[ip++] & 0xff;    
             int i1 = ip < iEnd ? in[ip++] & 0xff : 0;                
 int i2 = ip < iEnd ? in[ip++] & 0xff : 0;                  int o0 = i0
>>> 2;                  int o1 = ((i0 &   3) << 4) | (i1
>>> 4);                  int o2 = ((i1 & 0xf) << 2) | (i2
>>> 6);                  int o3 = i2 & 0x3F;                
 out[op++] = map1[o0];                  out[op++] = map1[o1];                
 out[op] = op < oDataLen ? map1[o2] : '='; op++;                  out[op] =
op < oDataLen ? map1[o3] : '='; op++; }                  return out; }      
 /**          * Decodes a string from Base64 format.          * No blanks or
line breaks are allowed within the Base64 encoded input data.          * @param
s  A Base64 String to be decoded.          * @return   A String containing the
decoded data.          * @throws   IllegalArgumentException If the input is not
valid Base64 encoded data.          */       public static String decodeString
(String s) {            return new String(decode(s)); }       /**         *
Decodes a byte array from Base64 format and ignores line separators, tabs and
blanks.         * CR, LF, Tab and Space characters are ignored in the input
data.         * This method is compatible with sun.misc.BASE64Decoder.decodeBuffer(String).         * @param s  A
Base64 String to be decoded.         * @return   An array containing the decoded
data bytes.         * @throws   IllegalArgumentException If the input is not
valid Base64 encoded data.         */       public static byte[] decodeLines
(String s) {            char[] buf = new char[s.length()+3];            int p =
0;            for (int ip = 0; ip < s.length(); ip++) {                 char
c = s.charAt(ip);                 if (c != ' ' && c != '\r' && c
!= '\n' && c != '\t')                     buf[p++] = c; }          
 while ((p % 4) != 0)                  buf[p++] = '0';            return
decode(buf, 0, p); }        /**          * Decodes a byte array from Base64
format.          * No blanks or line breaks are allowed within the Base64
encoded input data.          * @param s  A Base64 String to be decoded.        
 * @return   An array containing the decoded data bytes.          * @throws  
IllegalArgumentException If the input is not valid Base64 encoded data.        
 */        public static byte[] decode (String s) {             return
decode(s.toCharArray()); }        /**          * Decodes a byte array from
Base64 format.          * No blanks or line breaks are allowed within the Base64
encoded input data.          * @param in  A character array containing the
Base64 encoded data.          * @return    An array containing the decoded data
bytes.          * @throws    IllegalArgumentException If the input is not valid
Base64 encoded data.          */        public static byte[] decode (char[] in)
{             return decode(in, 0, in.length); }        /**          * Decodes a
byte array from Base64 format.          * No blanks or line breaks are allowed
within the Base64 encoded input data.          * @param in    A character array
containing the Base64 encoded data.          * @param iOff  Offset of the first
character in in to be processed.          * @param iLen  Number of
characters to process in in, starting at iOff.        
 * @return      An array containing the decoded data bytes.          * @throws  
   IllegalArgumentException If the input is not valid Base64 encoded data.      
   */        public static byte[] decode (char[] in, int iOff, int iLen) {      
      if (iLen%4 != 0) throw new IllegalArgumentException ("Length of Base64
encoded input string is not a multiple of 4.");             while (iLen > 0
&& in[iOff+iLen-1] == '=') iLen--;             int oLen = (iLen*3) / 4;
            byte[] out = new byte[oLen];             int ip = iOff;            
int iEnd = iOff + iLen;             int op = 0;             while (ip < iEnd)
{                 int i0 = in[ip++];                 int i1 = in[ip++];        
        int i2 = ip < iEnd ? in[ip++] : 'A';                 int i3 = ip <
iEnd ? in[ip++] : 'A';                 if (i0 > 127 || i1 > 127 || i2 >
127 || i3 > 127)                        throw new IllegalArgumentException
("Illegal character in Base64 encoded data.");                 int b0 =
map2[i0];                 int b1 = map2[i1];                 int b2 = map2[i2];
                int b3 = map2[i3];                 if (b0 < 0 || b1 < 0 ||
b2 < 0 || b3 < 0)                         throw new
IllegalArgumentException ("Illegal character in Base64 encoded data.");        
        int o0 = ( b0       <<2) b1="">>>4);                 int
o1 = ((b1 & 0xf)<<4) b2="">>>2);                 int o2 =
((b2 &   3)<<6) |  b3;                 out[op++] = (byte)o0;          
      if (op<oLen) out[op++] = (byte)o1;                 if (op<oLen)
out[op++] = (byte)o2; }       return out; }       //Dummy constructor.      
private Base64Coder() {}} // end class Base64Coder
最终,小马还把小DEMO源码放在附件里边,有需求的兄弟能够下载下来,一起交流学习,也恳请高人答复下小马在文章注释中提出的疑问,谢谢,文章是小马急急忙忙在家写的,在网吧发的,晕…不是我有多用功,这边下雨,厌烦下雨,下雨我就抑郁,来网吧玩的,顺带发下文章,吼吼,该玩的时分死命的玩,该作业的时分死命的作业,年轻时张狂,老了不懊悔,吼吼,加油加油!咱们作业,也留意身体健康,嘿嘿,你懂的,不解说…哈哈








[font=Tahoma  ]

优质IT资源分享社区为你提供此文。
站有大量优质android教程视频,资料等资源,包含android基础教程,高级进阶教程等等,教程视频资源涵盖传智播客,极客学院,达内,北大青鸟,猎豹网校等等IT职业培训机构的培训教学视频,价值巨大。欢迎点击下方链接查看。

android教程视频
优质IT资源分享社区(www.itziyuan.top)
一个免费,自由,开放,共享,平等,互助的优质IT资源分享网站。
专注免费分享各大IT培训机构最新培训教学视频,为你的IT学习助力!

!!!回帖受限制请看点击这里!!!
!!!资源失效请在此版块发帖说明!!!

[PS:按 CTRL+D收藏本站网址~]

——“优质IT资源分享社区”管理员专用签名~

本版相似帖子

游客