拍照,相册获取图片,高仿微信裁切图片

项目新需求中,有这个功能,所以各种百度搜索,最后写出了一个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






评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值