android图片橡皮擦功能和快速染色

源码github地址:https://github.com/zhouguangfu09/EraseImg.git

1.染色

     关于染色部分,可以分别设置调整画笔的大小和画笔的透明度,画笔已经设置了模糊效果。画笔的特效可以调整下面一行代码:



2.橡皮擦

  橡皮擦的实现用了两个canvas,一个临时的,一个是作用在ImageTouchView上显示的,代码里面有注释,这里不再详细介绍。

3.功能展示:

原图:


画笔设置界面:


(1)画笔大小为32,透明度为255(不透明)。如下图:


(2)画笔大小为32,透明度为10,如下图:


融合的效果跟画笔的透明度有关系,也跟背景图片的相应区域颜色有关,所以透明度的值自行调整得出满意效果。

(3)擦除

擦除前图像:


部分擦除后:

 

4.Bitmap处理相关的类BitmapUtils:

package com.jiangjie.utils;import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import android.content.Context;
import android.content.res.Resources;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.graphics.Matrix;
import android.graphics.Paint;
import android.graphics.Rect;
import android.graphics.Bitmap.Config;
public class BitmapUtils {/*** 缩放图片*/public static void bitmapScale(Bitmap baseBitmap, Paint paint, float x, float y) {// 因为要将图片放大,所以要根据放大的尺寸重新创建BitmapBitmap scaleBitmap = Bitmap.createBitmap((int) (baseBitmap.getWidth() * x),(int) (baseBitmap.getHeight() * y), baseBitmap.getConfig());Canvas canvas = new Canvas(scaleBitmap);// 初始化Matrix对象Matrix matrix = new Matrix();// 根据传入的参数设置缩放比例matrix.setScale(x, y);// 根据缩放比例,把图片draw到Canvas上canvas.drawBitmap(baseBitmap, matrix,paint);}/*** 图片旋转*/public static void bitmapRotate(Bitmap baseBitmap, Paint paint,float degrees) {// 创建一个和原图一样大小的图片Bitmap afterBitmap = Bitmap.createBitmap(baseBitmap.getWidth(),baseBitmap.getHeight(), baseBitmap.getConfig());Canvas canvas = new Canvas(afterBitmap);Matrix matrix = new Matrix();// 根据原图的中心位置旋转matrix.setRotate(degrees, baseBitmap.getWidth() / 2,baseBitmap.getHeight() / 2);canvas.drawBitmap(baseBitmap, matrix, paint);}/*** 图片移动*/public static void bitmapTranslate(Bitmap baseBitmap, Paint paint, float dx, float dy) {// 需要根据移动的距离来创建图片的拷贝图大小Bitmap afterBitmap = Bitmap.createBitmap((int) (baseBitmap.getWidth() + dx),(int) (baseBitmap.getHeight() + dy), baseBitmap.getConfig());Canvas canvas = new Canvas(afterBitmap);Matrix matrix = new Matrix();// 设置移动的距离matrix.setTranslate(dx, dy);canvas.drawBitmap(baseBitmap, matrix, paint);}/*** 倾斜图片*/public static void bitmapSkew(Bitmap baseBitmap, Paint paint, float dx, float dy) {// 根据图片的倾斜比例,计算变换后图片的大小,Bitmap afterBitmap = Bitmap.createBitmap(baseBitmap.getWidth()+ (int) (baseBitmap.getWidth() * dx), baseBitmap.getHeight()+ (int) (baseBitmap.getHeight() * dy), baseBitmap.getConfig());Canvas canvas = new Canvas(afterBitmap);Matrix matrix = new Matrix();// 设置图片倾斜的比例matrix.setSkew(dx, dy);canvas.drawBitmap(baseBitmap, matrix, paint);}public static Bitmap decodeFromResource(Context context, int id) {Resources res = context.getResources();Bitmap bitmap = BitmapFactory.decodeResource(res,id).copy(Bitmap.Config.ARGB_8888, true);return bitmap;}   /*** 保存图片到SD卡*/public static void saveToSdCard(String path, Bitmap bitmap) {if (null != bitmap && null != path && !path.equalsIgnoreCase("")) {try {File file = new File(path);FileOutputStream outputStream = null;//创建文件,并写入内容outputStream = new FileOutputStream(new File(path), true);bitmap.compress(Bitmap.CompressFormat.PNG, 30, outputStream);outputStream.flush();outputStream.close();} catch (FileNotFoundException e) {e.printStackTrace();} catch (IOException e) {e.printStackTrace();}}}/*** 复制bitmap*/public static Bitmap duplicateBitmap(Bitmap bmpSrc, int width, int height) {if (null == bmpSrc) {return null;}int bmpSrcWidth = bmpSrc.getWidth();int bmpSrcHeight = bmpSrc.getHeight();Bitmap bmpDest = Bitmap.createBitmap(width, height, Config.ARGB_8888);if (null != bmpDest) {Canvas canvas = new Canvas(bmpDest);Rect viewRect = new Rect();final Rect rect = new Rect(0, 0, bmpSrcWidth, bmpSrcHeight);if (bmpSrcWidth <= width && bmpSrcHeight <= height) {viewRect.set(rect);} else if (bmpSrcHeight > height && bmpSrcWidth <= width) {viewRect.set(0, 0, bmpSrcWidth, height);} else if (bmpSrcHeight <= height && bmpSrcWidth > width) {viewRect.set(0, 0, width, bmpSrcWidth);} else if (bmpSrcHeight > height && bmpSrcWidth > width) {viewRect.set(0, 0, width, height);}canvas.drawBitmap(bmpSrc, rect, viewRect, null);}return bmpDest;}/*** 复制bitmap*/public static Bitmap duplicateBitmap(Bitmap bmpSrc) {if (null == bmpSrc) {return null;}int bmpSrcWidth = bmpSrc.getWidth();int bmpSrcHeight = bmpSrc.getHeight();Bitmap bmpDest = Bitmap.createBitmap(bmpSrcWidth, bmpSrcHeight,Config.ARGB_8888);if (null != bmpDest) {Canvas canvas = new Canvas(bmpDest);final Rect rect = new Rect(0, 0, bmpSrcWidth, bmpSrcHeight);canvas.drawBitmap(bmpSrc, rect, rect, null);}return bmpDest;}/*** bitmap转字节码*/public static byte[] bitampToByteArray(Bitmap bitmap) {byte[] array = null;try {if (null != bitmap) {ByteArrayOutputStream os = new ByteArrayOutputStream();bitmap.compress(Bitmap.CompressFormat.PNG, 100, os);array = os.toByteArray();os.close();}} catch (IOException e) {e.printStackTrace();}return array;}/*** 字节码转bitmap*/public static Bitmap byteArrayToBitmap(byte[] array) {if (null == array) {return null;}return BitmapFactory.decodeByteArray(array, 0, array.length);}}


5。图像旋转,缩放,橡皮擦和染色功能如下:

package com.jiangjie.ps;import com.jiangjie.utils.PaintConstants;import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.Bitmap.Config;
import android.graphics.BlurMaskFilter;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Matrix;
import android.graphics.Paint;
import android.graphics.Path;
import android.graphics.PointF;
import android.graphics.PorterDuff.Mode;
import android.graphics.PorterDuffXfermode;
import android.graphics.RectF;
import android.graphics.drawable.BitmapDrawable;
import android.util.AttributeSet;
import android.util.DisplayMetrics;
import android.util.FloatMath;
import android.util.Log;
import android.view.MotionEvent;
import android.view.View;
import android.widget.ImageView;public class ImageTouchView extends ImageView{public Matrix matrix = new Matrix();Matrix savedMatrix = new Matrix();/** 屏幕的分辨率*/private DisplayMetrics dm;/** 当前模式*/int mode = PaintConstants.MODE.NONE;/** 存储float类型的x,y值,就是你点下的坐标的X和Y*/PointF prev = new PointF();PointF curPosition = new PointF();PointF mid = new PointF();float dist = 1f;float oldRotation = 0;  float oldDistX = 1f;float oldDistY = 1f;/**位图对象*/private Bitmap bitmap = null;private Paint paint;private Context context;private Path path;private Path tempPath;//定义一个内存中的图片,该图片将作为缓冲区Bitmap cacheBitmap = null;//定义cacheBitmap上的Canvas对象Canvas cacheCanvas = null;private Paint cachePaint = null;private String TAG = "APP";int x = 0;  int y = 0;  public ImageTouchView(Context context) {super(context);}public ImageTouchView(Context context, AttributeSet attrs) {super(context, attrs);this.context = context;Log.i(TAG, "ImageTouchView(Context context, AttributeSet attrs)=>");setupView();}@Overrideprotected void onDraw(Canvas canvas) {				super.onDraw(canvas);if(mode == PaintConstants.MODE.COLORING){canvas.drawPath(tempPath, paint);}}public void setupView(){//获取屏幕分辨率,需要根据分辨率来使用图片居中dm = getContext().getResources().getDisplayMetrics();//根据MyImageView来获取bitmap对象BitmapDrawable bd = (BitmapDrawable)this.getDrawable();if(bd != null){bitmap = bd.getBitmap();//			bitmap = setBitmapAlpha(bitmap, 100);center(true, true);}	setCoverBitmap(bitmap);this.setImageMatrix(matrix);this.setOnTouchListener(new OnTouchListener() {@Overridepublic boolean onTouch(View v, MotionEvent event) {Matrix matrixTemp = new Matrix();matrixTemp.set(matrix);//view的触摸坐标的转换matrixTemp.invert(matrixTemp);Log.i(TAG, "Touch screen.");switch (event.getAction() & MotionEvent.ACTION_MASK) {// 主点按下case MotionEvent.ACTION_DOWN:savedMatrix.set(matrix);prev.set(event.getX(), event.getY());float[] pointPrevInit = new float[]{prev.x, prev.y};matrixTemp.mapPoints(pointPrevInit);path.moveTo(pointPrevInit[0], pointPrevInit[1]);tempPath.moveTo(event.getX(), event.getY());mode = PaintConstants.MODE.DRAG;Log.i(TAG, "ACTION_DOWN=>.");break;// 副点按下case MotionEvent.ACTION_POINTER_DOWN:dist = spacing(event);oldRotation = rotation(event);  oldDistX = spacingX(event);oldDistY = spacingY(event);// 如果连续两点距离大于10,则判定为多点模式if (spacing(event) > 10f) {savedMatrix.set(matrix);midPoint(mid, event);mode = PaintConstants.MODE.ZOOM;}break;case MotionEvent.ACTION_UP:Log.i(TAG, "ACTION_UP=>.");if(mode == PaintConstants.MODE.COLORING){cachePaint.setColor(PaintConstants.PEN_COLOR);cachePaint.setStrokeWidth(PaintConstants.PEN_SIZE);cachePaint.setAlpha(PaintConstants.TRANSPARENT);  cachePaint.setMaskFilter(new BlurMaskFilter(5, PaintConstants.BLUR_TYPE));cacheCanvas.drawPath(path, cachePaint);path.reset();tempPath.reset();}break;case MotionEvent.ACTION_POINTER_UP:mode = PaintConstants.MODE.NONE;break;case MotionEvent.ACTION_MOVE:if(!PaintConstants.SELECTOR.KEEP_IMAGE){if (mode == PaintConstants.MODE.DRAG) {matrix.set(savedMatrix);matrix.postTranslate(event.getX() - prev.x, event.getY() - prev.y);} else if (mode == PaintConstants.MODE.ZOOM) {float rotation = (rotation(event) - oldRotation)/2;  float newDistX = spacingX(event);float newDistY = spacingY(event); float scaleX = newDistX-oldDistX;float scaleY = newDistY-oldDistY;float newDist = spacing(event);if (newDist > 10f) {matrix.set(savedMatrix);float tScale = newDist / dist;tScale = tScale>1?1+((tScale-1)/2):1-(1-tScale)/2;if(PaintConstants.SELECTOR.KEEP_SCALE){matrix.postScale(tScale, tScale, mid.x, mid.y);// 縮放  }else{if(Math.abs(scaleX)>=Math.abs(scaleY)){matrix.postScale(tScale, 1, mid.x, mid.y);// 縮放  }else{matrix.postScale(1, tScale, mid.x, mid.y);// 縮放}}if(PaintConstants.SELECTOR.HAIR_RURN)matrix.postRotate(rotation, mid.x, mid.y);// 旋轉 }}}else{float[] pointPrev = new float[]{prev.x, prev.y};float[] pointStop= new float[]{event.getX(), event.getY()};//view的触摸坐标的转换matrixTemp.mapPoints(pointPrev);matrixTemp.mapPoints(pointStop);	if(PaintConstants.SELECTOR.COLORING){//染色功能mode = PaintConstants.MODE.COLORING;paint.reset();paint = new Paint(Paint.DITHER_FLAG);paint.setColor(Color.RED);//设置画笔风格paint.setStyle(Paint.Style.STROKE);paint.setStrokeWidth(1);//反锯齿paint.setAntiAlias(true);paint.setDither(true);				paint.setColor(PaintConstants.PEN_COLOR);paint.setStrokeWidth(PaintConstants.PEN_SIZE);path.quadTo(pointPrev[0],pointPrev[1],pointStop[0],pointStop[1]);tempPath.quadTo(prev.x, prev.y,event.getX(), event.getY());// 更新开始点的位置prev.set(event.getX(), event.getY());ImageTouchView.this.setImageBitmap(cacheBitmap); }else if(PaintConstants.SELECTOR.ERASE){//橡皮擦功能mode = PaintConstants.MODE.ERASE;paint.reset();paint.setColor(Color.TRANSPARENT);paint.setAntiAlias(false);paint.setStyle(Paint.Style.STROKE);paint.setStrokeWidth(16);paint.setStrokeJoin(Paint.Join.ROUND);paint.setStrokeCap(Paint.Cap.ROUND);paint.setAlpha(0);   paint.setXfermode(new PorterDuffXfermode(Mode.DST_IN));paint.setStrokeWidth(PaintConstants.ERASE_SIZE);prev.set(event.getX(), event.getY());cacheCanvas.drawLine(pointPrev[0],pointPrev[1],pointStop[0],pointStop[1], paint);ImageTouchView.this.setImageBitmap(cacheBitmap); }}}ImageTouchView.this.setImageMatrix(matrix);invalidate();return true;}});}/*** 横向、纵向居中*/protected void center(boolean horizontal, boolean vertical) {RectF rect = new RectF(0, 0, bitmap.getWidth(), bitmap.getHeight());float height = rect.height();float width = rect.width();float deltaX = 0, deltaY = 0;if (vertical) {// 图片小于屏幕大小,则居中显示。大于屏幕,上方留空则往上移,下方留空则往下移int screenHeight = dm.heightPixels;if (height < screenHeight) {deltaY = (screenHeight - height) / 2 - rect.top;} else if (rect.top > 0) {deltaY = -rect.top;} else if (rect.bottom < screenHeight) {deltaY = this.getHeight() - rect.bottom;}}if (horizontal) {int screenWidth = dm.widthPixels;if (width < screenWidth) {deltaX = (screenWidth - width) / 2 - rect.left;} else if (rect.left > 0) {deltaX = -rect.left;} else if (rect.right < screenWidth) {deltaX = screenWidth - rect.right;}}matrix.postTranslate(deltaX, deltaY);} private float spacingX(MotionEvent event) {  float x = event.getX(0) - event.getX(1);  return x;}   private float spacingY(MotionEvent event) {  float y = event.getY(0) - event.getY(1);  return y; }      // 取旋转角度  private float rotation(MotionEvent event) {  double delta_x = (event.getX(0) - event.getX(1));  double delta_y = (event.getY(0) - event.getY(1));  double radians = Math.atan2(delta_y, delta_x);  return (float) Math.toDegrees(radians);  }  /*** 两点的距离*/private float spacing(MotionEvent event) {float x = event.getX(0) - event.getX(1);float y = event.getY(0) - event.getY(1);return FloatMath.sqrt(x * x + y * y);}/*** 两点的中点*/private void midPoint(PointF point, MotionEvent event) {float x = event.getX(0) + event.getX(1);float y = event.getY(0) + event.getY(1);point.set(x / 2, y / 2);}/** *  * @param bm * @note set cover bitmap , which  overlay on background.  */  private void setCoverBitmap(Bitmap bitmap) {  // setting paint  paint = new Paint();  cacheBitmap = Bitmap.createBitmap(bitmap.getWidth(), bitmap.getHeight(), Config.ARGB_8888);  cacheCanvas = new Canvas();cacheCanvas.setBitmap(cacheBitmap);cacheCanvas.drawBitmap( bitmap, 0, 0, null);  path = new Path();tempPath = new Path();//设置画笔的颜色cachePaint = new Paint();//设置画笔风格cachePaint.setStyle(Paint.Style.STROKE);//反锯齿cachePaint.setAntiAlias(true);cachePaint.setStrokeJoin(Paint.Join.ROUND);cachePaint.setStrokeCap(Paint.Cap.ROUND);cachePaint.setXfermode(new PorterDuffXfermode(Mode.SRC_ATOP));//设置画笔模糊效果cachePaint.setMaskFilter(new BlurMaskFilter(5, PaintConstants.BLUR_TYPE));} }


 


本文来自互联网用户投稿,文章观点仅代表作者本人,不代表本站立场,不承担相关法律责任。如若转载,请注明出处。 如若内容造成侵权/违法违规/事实不符,请点击【内容举报】进行投诉反馈!

相关文章

立即
投稿

微信公众账号

微信扫一扫加关注

返回
顶部