项目新需求中,有这个功能,所以各种百度搜索,最后写出了一个demo,分享给大家。
在demo中,有两个需要注意的地方,其他的都很简单啦
(1)高仿微信裁切图片,我使用的是鸿洋哥哥的demo,http://blog.csdn.net/lmj623565791/article/details/39761281
(2)拍照,获取原图,我看到了他的博客,http://892848153.iteye.com/blog/1851869,解决了这个问题
谢谢上面的两位哦
功能的一个流程:
我最后需要实现的是把,裁切出来的图片上传到服务器,demo中没有实现啊。。。
现在开始上代码啦,嘻嘻
1.MainActivity.java
MainActivity类中,
package com.example.picturecuttingdemos;
import java.io.ByteArrayOutputStream;
import java.io.File;
import android.app.AlertDialog;
import android.content.ContentResolver;
import android.content.DialogInterface;
import android.content.Intent;
import android.content.res.Configuration;
import android.graphics.Bitmap;
import android.net.Uri;
import android.os.Bundle;
import android.os.Environment;
import android.os.Handler;
import android.provider.MediaStore;
import android.support.v7.app.ActionBarActivity;
import android.view.Menu;
import android.view.MenuItem;
import com.example.picturecuttingdemos.view.ClipImageLayout;
public class MainActivity extends ActionBarActivity {
private Bitmap mBitmap;
private String capturePath = null;
private String out_file_path;
private ClipImageLayout mClipImageLayout;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mClipImageLayout = (ClipImageLayout) findViewById(R.id.clip_image);
showAlertDialog();
}
@Override
public boolean onCreateOptionsMenu(Menu menu) {
super.onCreateOptionsMenu(menu);
getMenuInflater().inflate(R.menu.main, menu);
return true;
}
@Override
public boolean onOptionsItemSelected(MenuItem item) {
if(item.getItemId() == R.id.action_settings){
getClip();
}
return super.onOptionsItemSelected(item);
}
@Override
public void onConfigurationChanged(Configuration newConfig) {
super.onConfigurationChanged(newConfig);
}
/**
* 裁切图片
*/
private void getClip(){
Bitmap bitmap = mClipImageLayout.clip();
ByteArrayOutputStream baos = new ByteArrayOutputStream();
bitmap.compress(Bitmap.CompressFormat.JPEG, 100, baos);
byte[] datas = baos.toByteArray();
Intent intent = new Intent(MainActivity.this, ShowImageActivity.class);
intent.putExtra("bitmap", datas);
startActivity(intent);
}
/**
* 创建对话框
*/
private void showAlertDialog() {
new AlertDialog.Builder(MainActivity.this).setTitle("上传头像")
.setMessage("选择获取头像的方式")
.setNegativeButton("拍照", new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
getPhotograph();
}
})
.setPositiveButton("图库", new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
getAlbum();
}
}).create().show();
}
/**
* 从相册获取图片
*/
private void getAlbum() {
Intent intent = new Intent();
/* 开启Pictures画面Type设定为image */
intent.setType("image/*");
/* 使用Intent.ACTION_GET_CONTENT这个Action */
intent.setAction(Intent.ACTION_GET_CONTENT);
/* 取得相片后返回本画面 */
startActivityForResult(intent, 1);
}
/**
* 从拍照
*/
private void getPhotograph() {
Intent intent = new Intent();
intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
out_file_path = getExternalStorePath()
+ "/PictureCutting/image";
File dir = new File(out_file_path);
if (!dir.exists()) {
dir.mkdirs();
}
capturePath = "PictureCutting"
+ System.currentTimeMillis() + ".jpg";
File f = new File(dir, capturePath);
Uri u = Uri.fromFile(f);
intent.putExtra(MediaStore.Images.Media.ORIENTATION, 0);
intent.putExtra(MediaStore.EXTRA_OUTPUT, u);
intent.putExtra(MediaStore.EXTRA_VIDEO_QUALITY, 1);
startActivityForResult(intent, 2);
}
private Handler mHandler = new Handler() {
public void handleMessage(android.os.Message msg) {
switch (msg.what) {
case 1:
mClipImageLayout.setBitmap(mBitmap);
break;
default:
break;
}
};
};
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
switch (requestCode) {
case 1:
chooseFromAlbum(resultCode, data);
break;
default:
photoGraph(resultCode, data);
break;
}
}
/**
* 从相册选照片。
*
* @param resultCode
* @param data
*/
private void chooseFromAlbum(int resultCode, Intent data) {
if (resultCode == MainActivity.RESULT_OK) {
Uri uri = data.getData();
ContentResolver cr = MainActivity.this.getContentResolver();
ConsultImageUtil consultImageUtil = new ConsultImageUtil(uri, cr);
try {
mBitmap = consultImageUtil.getBmp(uri, cr);
mHandler.sendEmptyMessage(1);
} catch (Exception e) {
e.printStackTrace();
}
}
}
/**
* 用手机拍照。
*
* @param resultCode
* @param data
*/
private void photoGraph(int resultCode, Intent data) {
File f = new File(out_file_path + "/" + capturePath);
try {
Uri u = Uri.parse(MediaStore.Images.Media.insertImage(
getContentResolver(), f.getAbsolutePath(), null, null));
ContentResolver cr = MainActivity.this.getContentResolver();
ConsultImageUtil consultImageUtil = new ConsultImageUtil(u, cr);
mBitmap = consultImageUtil.getBmp(u, cr);
} catch (Exception e) {
e.printStackTrace();
}
mHandler.sendEmptyMessage(1);
}
/**
* /sdcard
*
* @return
*/
public static String getExternalStorePath() {
if (isExistExternalStore()) {
return Environment.getExternalStorageDirectory().getAbsolutePath();
}
return null;
}
/**
* 是否有外存卡
*
* @return
*/
public static boolean isExistExternalStore() {
if (Environment.getExternalStorageState().equals(
Environment.MEDIA_MOUNTED)) {
return true;
} else {
return false;
}
}
}
2.ConsultImageUtil.java
这个类,是对图片进行的处理
package com.example.picturecuttingdemos;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.HttpURLConnection;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.Calendar;
import java.util.Locale;
import android.annotation.SuppressLint;
import android.content.ContentResolver;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.net.Uri;
import android.text.TextUtils;
import android.text.format.DateFormat;
@SuppressLint("NewApi")
public class ConsultImageUtil {
String path;
Uri uri;
ContentResolver cr;
Bitmap bmp;
byte[] bmpBytes;// comBmp 压缩后的图片数组
private String id = "";
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
/**
* 通过图片所在路径创建图像工具类。
*
* @param path
*/
public ConsultImageUtil(String path) {
this.path = path;
}
public ConsultImageUtil(Uri uri, ContentResolver cr) {
this.uri = uri;
this.cr = cr;
}
public ConsultImageUtil(Bitmap bmp) {
this.bmp = bmp;
}
private Bitmap image;
/**
* android中,存放图片的内存最大为8M
*/
private final int EDGE = 8;
/**
* 自定义大小。图片超过2M,则压缩。
*/
private int customSize = 0;
public int getCustomSize() {
return customSize;
}
public void setCustomSize(int customSize) {
this.customSize = customSize;
}
/**
* 通过路径获得Bitmap
*
* @param path
* @return
* @throws Exception
*/
public Bitmap getBmp(Uri uri, ContentResolver cr) throws Exception {
InputStream in = cr.openInputStream(uri);
if (isUseable(in.available())) {
return BitmapFactory.decodeStream(in);
} else {
BitmapFactory.Options opt = new BitmapFactory.Options();
opt.inSampleSize = 4;
return BitmapFactory.decodeStream(in, null, opt);
}
}
/**
* 判断图片是否过大
*
* @param len
* @return
*/
private boolean isUseable(double len) {
if (customSize == 0) {
if (len >= EDGE)
return false;
else
return true;
} else {
if (len >= customSize)
return false;
else
return true;
}
}
/**
* 通过路径获得Bitmap
*
* @param path
* @return
*/
private Bitmap getBmp(String path) {
if (isUseable(path)) {
return BitmapFactory.decodeFile(path);
} else {
BitmapFactory.Options opt = new BitmapFactory.Options();
opt.inSampleSize = 4;
return BitmapFactory.decodeFile(path, opt);
}
}
/**
* 判断图片是否过大
*
* @param path
* @return 不能用返回false(即图片过大)
*/
private boolean isUseable(String path) {
long fLen = new File(path).length();
double m = fLen / 1024 / 1024;
return isUseable(m);
}
private boolean check() throws Exception {
if (path != null) {
image = getBmp(path);
return true;
}
if (bmp != null) {
image = bmp;
return true;
}
if (uri != null) {
image = getBmp(uri, cr);
return true;
}
return false;
}
/**
* 压缩图片
*
* @param image
* 压缩前的图片
* @return 压缩后的图片
* @throws Exception
*/
public Bitmap compression() throws Exception {
if (!check())
throw new Exception("图片不能用");
ByteArrayOutputStream baos = new ByteArrayOutputStream();
image.compress(Bitmap.CompressFormat.JPEG, 100, baos);
if (baos.toByteArray().length / 1024 > 1024) {// 判断如果图片大于1M,进行压缩避免在生成图片(BitmapFactory.decodeStream)时溢出
baos.reset();// 重置baos即清空baos
image.compress(Bitmap.CompressFormat.JPEG, 50, baos);// 这里压缩50%,把压缩后的数据存放到baos中
}
ByteArrayInputStream isBm = new ByteArrayInputStream(baos.toByteArray());
BitmapFactory.Options newOpts = new BitmapFactory.Options();
// 开始读入图片,此时把options.inJustDecodeBounds 设回true了
newOpts.inJustDecodeBounds = true;
Bitmap bitmap = BitmapFactory.decodeStream(isBm, null, newOpts);
newOpts.inJustDecodeBounds = false;
int w = newOpts.outWidth;
int h = newOpts.outHeight;
// 现在主流手机比较多是800*480分辨率,所以高和宽我们设置为
float hh = 800f;// 这里设置高度为800f
float ww = 480f;// 这里设置宽度为480f
// 缩放比。由于是固定比例缩放,只用高或者宽其中一个数据进行计算即可
int be = 1;// be=1表示不缩放
if (w > h && w > ww) {// 如果宽度大的话根据宽度固定大小缩放
be = (int) (newOpts.outWidth / ww);
} else if (w < h && h > hh) {// 如果高度高的话根据宽度固定大小缩放
be = (int) (newOpts.outHeight / hh);
}
if (be <= 0)
be = 1;
newOpts.inSampleSize = be;// 设置缩放比例
// 重新读入图片,注意此时已经把options.inJustDecodeBounds 设回false了
isBm = new ByteArrayInputStream(baos.toByteArray());
bitmap = BitmapFactory.decodeStream(isBm, null, newOpts);
return compressImage(bitmap);// 压缩好比例大小后再进行质量压缩
}
private Bitmap compressImage(Bitmap image) {
ByteArrayOutputStream baos = new ByteArrayOutputStream();
image.compress(Bitmap.CompressFormat.JPEG, 100, baos);// 质量压缩方法,这里100表示不压缩,把压缩后的数据存放到baos中
bmpBytes = baos.toByteArray();
int options = 100;
while (baos.toByteArray().length / 1024 > 100) { // 循环判断如果压缩后图片是否大于100kb,大于继续压缩
baos.reset();// 重置baos即清空baos
image.compress(Bitmap.CompressFormat.JPEG, options, baos);// 这里压缩options%,把压缩后的数据存放到baos中
options -= 10;// 每次都减少10
}
ByteArrayInputStream isBm = new ByteArrayInputStream(baos.toByteArray());// 把压缩后的数据baos存放到ByteArrayInputStream中
Bitmap bitmap = BitmapFactory.decodeStream(isBm, null, null);// 把ByteArrayInputStream数据生成图片
return bitmap;
}
public Bitmap getBitmap() {
if (bmpBytes != null) {
return BitmapFactory.decodeByteArray(bmpBytes, 0, bmpBytes.length);
}
return null;
}
public void saveCompression(String filePath) throws Exception {
if (filePath != null || TextUtils.isEmpty(filePath))
throw new Exception("还未实现");
String name = DateFormat.format("yyyyMMdd_hhmmss",
Calendar.getInstance(Locale.CHINA))
+ ".jpg";
FileOutputStream b = null;
File file = new File("/sdcard/Image/1/");
file.mkdirs();// 创建文件夹
String fileName = "/sdcard/Image/1/" + name;
try {
b = new FileOutputStream(fileName);
Bitmap bitmap = compression();
bitmap.compress(Bitmap.CompressFormat.JPEG, 50, b);// 把数据写入文件
} catch (Exception e) {
e.printStackTrace();
} finally {
try {
b.flush();
b.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
public int getImgSize(String path) {
File f = new File(path);
long fLen = f.length();
return longToInt(fLen);
}
private int longToInt(long fLen) {
long m = fLen / 1024 / 1024;
return Integer.valueOf(String.valueOf(m));
}
// public static void setImg(String url,)
/**
* 从服务器取图片 http://bbs.3gstdy.com
*
* @param url
* @return
*/
public static Bitmap getHttpBitmap(String url) {
URL myFileUrl = null;
Bitmap bitmap = null;
try {
myFileUrl = new URL(url);
} catch (MalformedURLException e) {
e.printStackTrace();
}
try {
HttpURLConnection conn = (HttpURLConnection) myFileUrl
.openConnection();
conn.setConnectTimeout(5000);
conn.setDoInput(true);
conn.connect();
InputStream is = conn.getInputStream();
bitmap = BitmapFactory.decodeStream(is);
is.close();
} catch (Exception e) {
e.printStackTrace();
}
return bitmap;
}
}
O(∩_∩)O哈哈~,是不是很简单啦。。。
如果想看裁切是怎么实现的,请看鸿洋的博客,路径上面有。
如果想看拍照怎么获取原图,请点击上面的路径。。。
我对ClipImageLayout进行了一点修改,给大家看一下吧
3.ClipImageLayout.java
package com.example.picturecuttingdemos.view;
import android.content.Context;
import android.content.res.TypedArray;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.drawable.BitmapDrawable;
import android.util.AttributeSet;
import android.util.TypedValue;
import android.widget.RelativeLayout;
import com.example.picturecuttingdemos.R;
/**
* http://blog.csdn.net/lmj623565791/article/details/39761281
*
* @author zhy
*
*/
public class ClipImageLayout extends RelativeLayout {
private ClipZoomImageView mZoomImageView;
private ClipImageBorderView mClipImageView;
private Bitmap mBitmap;
/**
* 这里测试,直接写死了大小,真正使用过程中,可以提取为自定义属性
*/
private int mHorizontalPadding = 20;
public ClipImageLayout(Context context, AttributeSet attrs) {
super(context, attrs);
mZoomImageView = new ClipZoomImageView(context);
mClipImageView = new ClipImageBorderView(context);
android.view.ViewGroup.LayoutParams lp = new LayoutParams(
android.view.ViewGroup.LayoutParams.MATCH_PARENT,
android.view.ViewGroup.LayoutParams.MATCH_PARENT);
this.addView(mZoomImageView, lp);
this.addView(mClipImageView, lp);
TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.ClipImageLayout);
mHorizontalPadding = (int) a.getDimension(R.styleable.ClipImageLayout_HorizontalPadding, 20);
a.recycle();
// 计算padding的px
mHorizontalPadding = (int) TypedValue.applyDimension(
TypedValue.COMPLEX_UNIT_DIP, mHorizontalPadding, getResources()
.getDisplayMetrics());
mZoomImageView.setHorizontalPadding(mHorizontalPadding);
mClipImageView.setHorizontalPadding(mHorizontalPadding);
}
/**
* 对外公布设置边距的方法,单位为dp
*
* @param mHorizontalPadding
*/
public void setHorizontalPadding(int mHorizontalPadding) {
this.mHorizontalPadding = mHorizontalPadding;
}
/**
* 裁切图片
*
* @return
*/
public Bitmap clip() {
return mZoomImageView.clip();
}
/**
* 设置图片
* @param b
*/
public void setBitmap(Bitmap b){
mBitmap = b;
setImageBitmap(b);
invalidate();
}
private void setImageBitmap(Bitmap b) {
mZoomImageView.setImageDrawable(new BitmapDrawable(getResources(), b));
}
}
主要是定义了一个自定义属性,以及将Bitmap位图,从MainActivity从传过来,来进行处理。
4.attrs.xml
<?xml version="1.0" encoding="utf-8"?>
<resources>
<declare-styleable name="ClipImageLayout">
<attr name="HorizontalPadding" format="dimension" />
</declare-styleable>
</resources>
5.activity_main.xml
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
xmlns:clip="http://schemas.android.com/apk/res/com.example.picturecuttingdemos"
android:layout_width="match_parent"
android:layout_height="match_parent" >
<com.example.picturecuttingdemos.view.ClipImageLayout
android:id="@+id/clip_image"
android:layout_width="match_parent"
android:layout_height="match_parent"
clip:HorizontalPadding="10dp" />
</RelativeLayout>
行了,结束,如果需要源码的,请点击http://download.csdn.net/detail/u010947098/8932619