一直想对之前做过的一款图片社交软件cos酱(类似in nice)的代码进行梳理,但是由于时间的关系拖到今天才开始这个工作。
在项目中,主要对照片裁剪、旋转、翻转(在之前的文章有提到过)、贴纸、滤镜、文字、边框、标签等功能。
涂抹马赛克
涂抹主要利用的是paint的setXfermode来进行图片的叠加
第一步 生成马赛克图片
private Bitmap getGridMosaic() { if (mImgBitmap == null) { return null; } int mImageWidth = mImgBitmap.getWidth(); int mImageHeight = mImgBitmap.getHeight(); Bitmap bitmap = Bitmap.createBitmap(mImageWidth, mImageHeight, Bitmap.Config.ARGB_8888); Canvas canvas = new Canvas(bitmap); int horCount = (int) Math.ceil(mImageWidth / (float) mGridWidth); int verCount = (int) Math.ceil(mImageHeight / (float) mGridWidth); Paint paint = new Paint(); paint.setAntiAlias(true); for (int horIndex = 0; horIndex < horCount; ++horIndex) { for (int verIndex = 0; verIndex < verCount; ++verIndex) { int l = mGridWidth * horIndex; int t = mGridWidth * verIndex; int r = l + mGridWidth; if (r > mImageWidth) { r = mImageWidth; } int b = t + mGridWidth; if (b > mImageHeight) { b = mImageHeight; } int color = mImgBitmap.getPixel(l, t); Rect rect = new Rect(l, t, r, b); paint.setColor(color); canvas.drawRect(rect, paint); } } canvas.save(); return bitmap; }
第二步 处理触摸事件
/** * 触摸事件 * @param event * @return */ public boolean dispatchTouchEvent(MotionEvent event) { super.dispatchTouchEvent(event); if(isTouchable){ int action = event.getAction(); int x = (int) event.getX(); int y = (int) event.getY(); onPathEvent(action, x, y); } return true;} /** * 触摸事件处理 * @param action * @param x * @param y */ private void onPathEvent(int action, int x, int y) { if (mImgBitmap == null) { return; } int mImageWidth = mImgBitmap.getWidth(); int mImageHeight = mImgBitmap.getHeight(); if (x < mImgDesRect.left || x > mImgDesRect.right || y < mImgDesRect.top || y > mImgDesRect.bottom) { return; } float ratio = (mImgDesRect.right - mImgDesRect.left)/ (float) mImageWidth; x = (int) ((x - mImgDesRect.left) / ratio); y = (int) ((y - mImgDesRect.top) / ratio); if (action == MotionEvent.ACTION_DOWN) { mErasePath = new Path(); mErasePath.moveTo(x, y); dp = new DrawPath(); dp.path = mErasePath; dp.paint = initErasePaint(); dp.isErase = isEraseMode; Log.e("tag", "mMosaic=====" + dp.paint.getStrokeWidth()); } else if (action == MotionEvent.ACTION_MOVE) { dp.path.lineTo(x, y); savePath.add(dp); updatePathMosaic(false,savePath); invalidate(); }else if(action == MotionEvent.ACTION_UP){ historyPath.add(dp); }}
第三步 绘制合成
/** * 是否绘制所有的路径, 当要撤销的时候就需要绘制所有的路径 * @param isDrawAll */ private void updatePathMosaic(boolean isDrawAll,ArrayList<DrawPath> listDrawPath) { if (mImgBitmap == null) { return ; } int mImageWidth = mImgBitmap.getWidth(); int mImageHeight = mImgBitmap.getHeight(); if (bmMosaicLayer != null) { bmMosaicLayer.recycle(); } bmMosaicLayer = Bitmap.createBitmap(mImageWidth, mImageHeight, Bitmap.Config.ARGB_8888); if(bmTouchLayer==null){ bmTouchLayer = Bitmap.createBitmap(mImageWidth, mImageHeight, Bitmap.Config.ARGB_8888); }// 先在bmTouchLayer上绘制出路径 Paint paint = new Paint(Paint.ANTI_ALIAS_FLAG); paint.setStyle(Paint.Style.STROKE); paint.setAntiAlias(true); paint.setStrokeJoin(Paint.Join.ROUND); paint.setStrokeCap(Paint.Cap.ROUND); paint.setPathEffect(new CornerPathEffect(10)); paint.setStrokeWidth(mErasePaintStrokeWidth); paint.setColor(Color.BLUE); Canvas canvas = new Canvas(bmTouchLayer);// 绘制路径操作 if(isDrawAll){ for(DrawPath db : listDrawPath){ if(db.isErase){ paint.setColor(Color.TRANSPARENT); paint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.CLEAR)); paint.setStrokeWidth(db.paint.getStrokeWidth()); }else{ paint.setColor(Color.BLUE); paint.setXfermode(null); paint.setStrokeWidth(db.paint.getStrokeWidth()); } canvas.drawPath(db.path, paint); } }else{ // 如果不是绘制所有,就只绘制最后一笔 DrawPath db = listDrawPath.get(listDrawPath.size()-1); if(db.isErase){ paint.setColor(Color.TRANSPARENT); paint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.CLEAR)); paint.setStrokeWidth(db.paint.getStrokeWidth()); }else{ paint.setColor(Color.BLUE); paint.setXfermode(null); paint.setStrokeWidth(db.paint.getStrokeWidth()); } canvas.drawPath(db.path, paint); } // 将幕布设置给bmMosaicLayer canvas.setBitmap(bmMosaicLayer); canvas.drawARGB(0, 0, 0, 0); // 将要绘制的 纯颜色or马赛克等图层绘制上去 canvas.drawBitmap(mEraseMaskBitmap, 0, 0, null); paint.reset(); paint.setAntiAlias(true); // 将bmTouchLayer和图层层叠 paint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.DST_IN)); canvas.drawBitmap(bmTouchLayer, 0, 0, paint); paint.setXfermode(null); canvas.save(); // bmTouchLayer.recycle(); }
网友评论