android实现图片橡皮擦和快速染色功能
程序员文章站
2022-04-30 22:47:26
本文为大家分享了android实现图片橡皮擦和快速染色的具体代码,供大家参考,具体内容如下
源码地址:eraselmg
1.染色
...
本文为大家分享了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)); } }
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持。
上一篇: Android画板开发之基本画笔功能