您好,登錄后才能下訂單哦!
本文為大家分享了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)); } }
以上就是本文的全部內容,希望對大家的學習有所幫助,也希望大家多多支持億速云。
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。