android 裁剪涂抹区域并保存成图片

这篇博客主要想实现的功能是:1、用canvas实现自定义绘图,包括绘制资源图片和手势涂画    2、将手势涂抹过的区域(矩形)保存成一张图片。

一提到裁剪图片,就想到canvas里面的clipXXX接口。事实上,clipXXX接口并不能实现所谓”裁剪图片“的功能,只能指定一块区域显示绘画内容,超出区域的部分就会被裁剪掉(不显示)。

先简单说下原理:

1、新生成一个画布  canvas

2、为画布指定一个bitmap对象,用来保存自定义绘制过程中的图像

3、自定义绘图(画线、画路径、画什么的,这里就不提了),ondraw方法里面只将bitmap对象重新绘制下就ok了

4、最后,生成一个指定宽高的bitmap对象用来保存指定区域图像。(如何指定区域?那得看什么需求了,这里计算最后一次涂抹所占的矩形区域为指定区域)


自定义视图:

import java.io.File;
import java.io.FileOutputStream;

import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.Bitmap.Config;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Path;
import android.graphics.RectF;
import android.util.AttributeSet;
import android.util.Log;
import android.view.MotionEvent;
import android.view.View;

import com.example.test4_0.R;

/**
 * 
 * 作者:zg 创建时间:2014-8-3 上午11:18:43
 * 
 **/
public class TestDrawView extends View {
	private Paint mPaint;
	private Path mPath;
	boolean isMove;
	private float mX, mY;
	private static final float TOUCH_TOLERANCE = 4;
	private Canvas mCanvas;
	private Bitmap mDrawBitmap;
	private Bitmap mBmp;
	boolean isChange;
	private int windowHeight;
	private int windowWidth;

	public TestDrawView(Context context) {
		super(context);
		init();
	}

	public TestDrawView(Context context, AttributeSet attrs) {
		super(context, attrs);
		init();
	}

	public TestDrawView(Context context, AttributeSet attrs, int defStyle) {
		super(context, attrs, defStyle);
		init();
	}

	public void setWH(int w, int h) {
		windowHeight = h;
		windowWidth = w;
		mDrawBitmap = Bitmap.createBitmap(w, h, Config.ARGB_8888);
		mCanvas.setBitmap(mDrawBitmap);
		mCanvas.drawBitmap(mBmp, 0, 0, null);
	}

	private void init() {
		mBmp = BitmapFactory.decodeResource(getResources(),
				R.drawable.ic_launcher);
		mPath = new Path();
		mPaint = new Paint();
		mCanvas = new Canvas();
		mPaint.setAntiAlias(true);
		mPaint.setDither(true);
		mPaint.setColor(Color.BLACK);
		mPaint.setStyle(Paint.Style.STROKE);
		mPaint.setStrokeJoin(Paint.Join.ROUND);
		mPaint.setStrokeCap(Paint.Cap.ROUND);
		mPaint.setStrokeWidth(15);
	}

	@Override
	protected void onDraw(Canvas canvas) {
		super.onDraw(canvas);
		canvas.drawColor(Color.WHITE);
		canvas.drawBitmap(mDrawBitmap, 0, 0, null);

	}

	private void touch_start(float x, float y) {
		mPath.reset();
		mPath.moveTo(x, y);
		mX = x;
		mY = y;
		mCanvas.drawPath(mPath, mPaint);
	}

	private void touch_move(float x, float y) {
		float dx = Math.abs(x - mX);
		float dy = Math.abs(y - mY);
		if (dx >= TOUCH_TOLERANCE || dy >= TOUCH_TOLERANCE) {
			mPath.quadTo(mX, mY, (x + mX) / 2, (y + mY) / 2);
			mX = x;
			mY = y;
		}
		mCanvas.drawPath(mPath, mPaint);
	}

	private void touch_up() {
		mPath.lineTo(mX, mY);
		mCanvas.drawPath(mPath, mPaint);
		saveBitmap();
	}

	private void saveBitmap() {
		RectF rect = new RectF();
		mPath.computeBounds(rect, true);
		Log.i("info", "mPath.getWidth()=" + (rect.width()));
		Log.i("info", "mPath.getHeight()=" + (rect.height()));
		Bitmap bmp = Bitmap.createBitmap((int) rect.width(),
				(int) rect.height(), Config.ARGB_8888);
		Canvas canvas = new Canvas(bmp);
		// canvas.clipRect(rect);
		canvas.translate(-rect.left, -rect.top);
		canvas.drawColor(Color.WHITE);

		canvas.drawBitmap(mDrawBitmap, 0, 0, null);

		// canvas.drawBitmap(mBitmap, null, rect, null);
		// canvas.drawPath(mPath, mPaint);

		canvas.save(Canvas.ALL_SAVE_FLAG);
		canvas.restore();

		File file = new File("/sdcard/akai/");
		if (!file.exists())
			file.mkdirs();
		try {
			FileOutputStream fos = new FileOutputStream(file.getPath()
					+ "/4.png");
			bmp.compress(Bitmap.CompressFormat.PNG, 100, fos);
			fos.close();
			System.out.println("saveBmp is here");
		} catch (Exception e) {
			e.printStackTrace();
		}
	}

	@Override
	public boolean onTouchEvent(MotionEvent event) {
		isMove = false;
		isChange = false;
		float x = event.getX();
		float y = event.getY();
		switch (event.getAction()) {
		case MotionEvent.ACTION_DOWN:
			touch_start(x, y);

			invalidate();
			break;
		case MotionEvent.ACTION_MOVE:
			isMove = true;
			touch_move(x, y);
			invalidate();
			return true;
		case MotionEvent.ACTION_UP:
			touch_up();
			invalidate();
			break;
		}
		if (!isMove) {
			return true;
		}
		return super.onTouchEvent(event);
	}
}



activity:

import android.app.Activity;
import android.os.Bundle;

import com.example.test4_0.definedview.TestDrawView;

/**
 * 
 * 作者:zg 创建时间:2014-8-3 下午1:43:05
 * 
 **/
public class TestDrawSaveActivity extends Activity {
	private TestDrawView mView;

	@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.test_draw_save);
		mView = (TestDrawView) findViewById(R.id.test_save);
		int windowHeight = getWindowManager().getDefaultDisplay().getHeight();
		int windowWidth = getWindowManager().getDefaultDisplay().getWidth();
		// mView.setBgBitmap(BitmapFactory.decodeResource(getResources(),
		//	R.drawable.ic_launcher));
		mView.setWH(windowWidth,windowHeight);
	}

}


test_draw_save.xml

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical" >
<com.example.test4_0.definedview.TestDrawView
    android:id="@+id/test_save"
    android:layout_width="match_parent"
    android:layout_height="match_parent" />

</LinearLayout>

不要忘记写SD卡权限:

 <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />





  • 2
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值