当前位置: 移动技术网 > 移动技术>移动开发>Android > android实现图片橡皮擦和快速染色功能

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

2019年07月31日  | 移动技术网移动技术  | 我要评论

本文为大家分享了android实现图片橡皮擦和快速染色的具体代码,供大家参考,具体内容如下

源码地址:eraselmg

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) {
  // 因为要将图片放大,所以要根据放大的尺寸重新创建bitmap
  bitmap 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();
 }
 
 @override
 protected 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() {
 @override
 public 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));
 
 } 
 
}

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持移动技术网。

如对本文有疑问, 点击进行留言回复!!

相关文章:

验证码:
移动技术网