Android裁剪图像实现方法示例
程序员文章站
2024-03-07 15:41:27
本文实例讲述了android裁剪图像实现方法。分享给大家供大家参考,具体如下:
package com.xiaoma.piccut.demo;
import j...
本文实例讲述了android裁剪图像实现方法。分享给大家供大家参考,具体如下:
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. * * <p> * this class is used to encode and decode data in base64 format as described in rfc 1521. * * <p> * project home page: www.source-code.biz/base64coder/java * author: christian d'heureuse, inventec informatik ag, zurich, switzerland<br> * 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[i] = -1; for (int i=0; i<64; i++) map2[map1[i]] = (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 <code>in</code> to be processed. * @param ilen number of bytes to be processed in <code>in</code>, starting at <code>ioff</code>. * @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 <code>in</code>. * @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 <code>in</code> to be processed. * @param ilen number of bytes to process in <code>in</code>, starting at <code>ioff</code>. * @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 <code>sun.misc.base64decoder.decodebuffer(string)</code>. * @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 <code>in</code> to be processed. * @param ilen number of characters to process in <code>in</code>, starting at <code>ioff</code>. * @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
更多关于android相关内容感兴趣的读者可查看本站专题:《android图形与图像处理技巧总结》、《android开发入门与进阶教程》、《android调试技巧与常见问题解决方法汇总》、《android多媒体操作技巧汇总(音频,视频,录音等)》、《android基本组件用法总结》、《android视图view技巧总结》、《android布局layout技巧总结》及《android控件用法总结》
希望本文所述对大家android程序设计有所帮助。