图片涂鸦马赛克

之前写的项目了,因为有小伙伴问到处理后如何保存的问题我把方法加到代码里了。(最近项目时间紧未经测试>o 最近项目里用到了马赛克效果,就是对手指划过的区域打码。效果如下:

关于图片模糊其实我是采用偷懒的做法,先缩小后放大....,代码很少就不解释了。

布局中使用:

MosaicView代码:

package 你的包名;

import android.content.Context;

import android.graphics.Bitmap;

import android.graphics.Canvas;

import android.graphics.DiscretePathEffect;

import android.graphics.Matrix;

import android.graphics.Paint;

import android.graphics.Path;

import android.graphics.PorterDuff;

import android.graphics.PorterDuffXfermode;

import android.graphics.RectF;

import android.graphics.drawable.BitmapDrawable;

import android.graphics.drawable.Drawable;

import android.util.AttributeSet;

import android.view.MotionEvent;

import android.widget.ImageView;

import java.util.ArrayList;

/**

* Created on 2017/8/3.

*/

public class MosaicView extends ImageView {

private Bitmap mMosaicBmp;

private Paint mPaint;

private ArrayListmPaths;

private DrawPath mLastPath;

private RectF mBitmapRectF;

private PorterDuffXfermode mDuffXfermode;

private float tempX,tempY;

private final float mTargetWidth = 20.0f;

public MosaicView(Context context) {

super(context);

init();

}

public MosaicView(Context context, AttributeSet attrs) {

super(context, attrs);

init();

}

public MosaicView(Context context, AttributeSet attrs, int defStyleAttr) {

super(context, attrs, defStyleAttr);

init();

}

private void init() {

mPaint = new Paint();

mPaint.setAntiAlias(true);

mPaint.setDither(true);

mPaint.setStyle(Paint.Style.STROKE);//描边

mPaint.setTextAlign(Paint.Align.CENTER);//居中

mPaint.setStrokeCap(Paint.Cap.ROUND);//圆角

mPaint.setStrokeJoin(Paint.Join.ROUND);//拐点圆角

//正常效果

mPaint.setStrokeWidth(32);

// //抖动效果

// mPaint.setStrokeWidth(2f);

// mPaint.setPathEffect(new DiscretePathEffect(0.35f, 40));

//

mPaths = new ArrayList<>();

mBitmapRectF = new RectF();

//叠加效果

mDuffXfermode = new PorterDuffXfermode(PorterDuff.Mode.SRC_IN);

}

/**

* 清除操作

* */

public void clear() {

mPaths.clear();

invalidate();

}

/**

* 撤销

* */

public void undo() {

int size = mPaths.size();

if (size > 0) {

mPaths.remove(size-1);

invalidate();

}

}

private float mScale;

/**

* 获取处理后的图片

* */

public Bitmap getImageBitmap() {

Bitmap bitmap;

if ((getDrawable() instanceof BitmapDrawable)) {

BitmapDrawable drawable = (BitmapDrawable) getDrawable();

bitmap = drawable.getBitmap().copy(Bitmap.Config.ARGB_8888, true);

} else {

bitmap = Bitmap.createBitmap(getWidth(), getHeight(), Bitmap.Config.ARGB_8888);

}

int width = bitmap.getWidth();

mScale = (float) width / mMosaicBmp.getWidth();

Canvas canvas = new Canvas(bitmap);

canvas.save();

canvas.scale(mScale, mScale);

drawOnLayer(canvas);

canvas.restore();

return bitmap;

}

private int drawOnLayer(Canvas canvas) {

int canvasWidth = canvas.getWidth();

int canvasHeight = canvas.getHeight();

//新图层

int layerId;

layerId = canvas.saveLayer(0, 0, canvasWidth/mScale, canvasHeight/mScale, null, Canvas.ALL_SAVE_FLAG);

canvas.save();

canvas.translate(-mBitmapRectF.left, -mBitmapRectF.top);

for (DrawPath drawPath : mPaths) {

//滑过的区域

drawPath.draw(canvas);

}

mPaint.setXfermode(mDuffXfermode);//设置叠加模式

canvas.drawBitmap(mMosaicBmp, mBitmapRectF.left, mBitmapRectF.top, mPaint);//画出重叠区域

canvas.restore();

mPaint.setXfermode(null);

return layerId;

}

@Override

public void setImageDrawable(Drawable drawable) {

super.setImageDrawable(drawable);

if (drawable != null && drawable instanceof BitmapDrawable) {

scaleBitmap(((BitmapDrawable) drawable).getBitmap());

}

}

@Override

public void setImageBitmap(Bitmap bm) {

super.setImageBitmap(bm);

scaleBitmap(bm);

}

// 生成小图

private void scaleBitmap(Bitmap bm) {

int width = bm.getWidth();

float scale = mTargetWidth / width;

Matrix matrix = new Matrix();

matrix.postScale(scale, scale);

mMosaicBmp = Bitmap.createBitmap(bm, 0, 0, width, bm.getHeight(),

matrix, true);

}

/**

* 得到图片展示区域

*/

private RectF getBitmapRect() {

final Drawable drawable = getDrawable();

if (drawable == null) {

return new RectF();

}

// Get image matrix values and place them in an array.

final float[] matrixValues = new float[9];

getImageMatrix().getValues(matrixValues);

// Extract the scale and translation values from the matrix.

final float scaleX = matrixValues[Matrix.MSCALE_X];

final float scaleY = matrixValues[Matrix.MSCALE_Y];

final float transX = matrixValues[Matrix.MTRANS_X] + getPaddingLeft();

final float transY = matrixValues[Matrix.MTRANS_Y] + getPaddingTop();

// Get the width and height of the original bitmap.

final int drawableIntrinsicWidth = drawable.getIntrinsicWidth();

final int drawableIntrinsicHeight = drawable.getIntrinsicHeight();

// Calculate the dimensions as seen on screen.

final int drawableDisplayWidth = Math.round(drawableIntrinsicWidth * scaleX);

final int drawableDisplayHeight = Math.round(drawableIntrinsicHeight * scaleY);

// Get the Rect of the displayed image within the ImageView.

final float left = Math.max(transX, 0);

final float top = Math.max(transY, 0);

final float right = Math.min(left + drawableDisplayWidth, getWidth());

final float bottom = Math.min(top + drawableDisplayHeight, getHeight());

return new RectF(left, top, right, bottom);

}

@Override

protected void onLayout(boolean changed, int left, int top, int right, int bottom) {

super.onLayout(changed, left, top, right, bottom);

if (mMosaicBmp != null) {

mBitmapRectF = getBitmapRect();

Matrix mosaicMatrix = new Matrix();

mosaicMatrix.setTranslate(mBitmapRectF.left, mBitmapRectF.top);

float scaleX = (mBitmapRectF.right - mBitmapRectF.left) / mMosaicBmp.getWidth();

float scaleY = (mBitmapRectF.bottom - mBitmapRectF.top) / mMosaicBmp.getHeight();

mosaicMatrix.postScale(scaleX, scaleY);

// 生成整张模糊图片

mMosaicBmp = Bitmap.createBitmap(mMosaicBmp, 0, 0, mMosaicBmp.getWidth(), mMosaicBmp.getHeight(),

mosaicMatrix, true);

}

}

@Override

protected void onDraw(Canvas canvas) {

super.onDraw(canvas);

if(!mPaths.isEmpty()){

int canvasWidth = canvas.getWidth();

int canvasHeight = canvas.getHeight();

//新图层

int layerId = canvas.saveLayer(0, 0, canvasWidth, canvasHeight, null, Canvas.ALL_SAVE_FLAG);

canvas.clipRect(mBitmapRectF); //限定区域

for(DrawPath drawPath:mPaths){

//滑过的区域

drawPath.draw(canvas);

}

mPaint.setXfermode(mDuffXfermode);//设置叠加模式

canvas.drawBitmap(mMosaicBmp, mBitmapRectF.left, mBitmapRectF.top, mPaint);//画出重叠区域

mPaint.setXfermode(null);

canvas.restoreToCount(layerId);

}

}

@Override

public boolean onTouchEvent(MotionEvent event) {

switch (event.getAction()){

case MotionEvent.ACTION_DOWN:

float downX = event.getX();

float downY = event.getY();

mLastPath = new DrawPath();//每次手指下去都是一条新的路径

mLastPath.moveTo(downX,downY);

mPaths.add(mLastPath);

invalidate();

tempX = downX;

tempY = downY;

break;

case MotionEvent.ACTION_MOVE:

float moveX = event.getX();

float moveY = event.getY();

if (Math.abs(moveX - tempX) > 5 || Math.abs(moveY - tempY) > 5) {

mLastPath.quadTo(tempX,tempY,moveX,moveY);

invalidate();

}

tempX = moveX;

tempY = moveY;

break;

case MotionEvent.ACTION_UP:

mLastPath.up();

break;

}

return true;

}

/**

* 封装一条路径

*/

class DrawPath{

Path path;

float downX;

float downY;

boolean quaded;

DrawPath() {

path = new Path();

}

void moveTo(float x, float y) {

downX = x;

downY = y;

path.moveTo(x, y);

}

void quadTo(float x1, float y1, float x2, float y2) {

quaded = true;

path.quadTo(x1, y1, x2, y2);

}

void up() {

if (!quaded) {

//画点

path.lineTo(downX, downY+0.1f);

invalidate();

}

}

void draw(Canvas canvas) {

if(path!=null){

canvas.drawPath(path, mPaint);

}

}

}

}

安卓马赛克view_Android马赛克效果MosaicView相关推荐

  1. PS制作简单可爱马赛克像素画效果

    动作支持CC以上版本PS软件,动作陌鱼社区下载"照片做成马赛克像素装饰画效果PS动作"下面请看动作演示教程. 01.打开软件,载入动作. 02.把软件切换成英文,参考"怎 ...

  2. 程序员开源去马赛克软件,效果感人;黑客明码标价出售 FB 聊天信息

    (给技术最前线加星标,每天看技术热点) 转自:游民星空.开源中国.solidot.cnBeta.腾讯科技.快科技等 [技术资讯] 0.程序员开源去马赛克软件,效果感人 相信一提起马赛克这个东西,不少小 ...

  3. 安卓SurfaceView 实现下雨效果

    安卓SurfaceView 实现下雨效果 先来一张效果图 我的思路 下雨每个雨滴用一条线来实现,生成一条线,X轴坐标随机,Y轴不断增加,就形成了下雨的效果 1.首先定义mSurfaceView类,继承 ...

  4. android写qq动态界面,Android_Android仿QQ空间主页面的实现,今天模仿安卓QQ空间,效果如 - phpStudy...

    Android仿QQ空间主页面的实现 今天模仿安卓QQ空间,效果如下: 打开程序的启动画面和导航页面我就不做了,大家可以模仿微信的那个做一下,很简单.这次主要做一下主页面的实现,下面是主页面的布局: ...

  5. 安卓马赛克view_Android图形图像处理:马赛克(Mosaic)效果

    以图形图像界经典的实验例图Lenna为例,当手指在图片上滑过后,形成马赛克的: 写一个MosaicView继承自AppCompatImageView: package com.zhangphil; i ...

  6. Android马赛克效果MosaicView

    图片涂鸦马赛克 之前写的项目了,因为有小伙伴问到处理后如何保存的问题我把方法加到代码里了.(最近项目时间紧未经测试>o<) 最近项目里用到了马赛克效果,就是对手指划过的区域打码.效果如下: ...

  7. 安卓马赛克view_android 图片编辑(马赛克等功能实现)源码下载

    [实例简介]实现的基本功能如下: 1,图片编辑(图片添加,文字添加),实现图片编辑中的图片添加,旋转,缩放,删除:文字的添加,大小缩放,字体更换,颜色更换,删除: 2,基本滤镜实现与接口封装: 涂鸦( ...

  8. 计算机视觉:图片的马赛克、毛玻璃效果和图片的融合

    1.马赛克效果 马赛克的基本原理就是,用某一个区域的某一个像素点替代这个区域所有的像素点,从而导致图片出现模糊的效果,如下: import cv2# 马赛克效果 img = cv2.imread(fi ...

  9. 程序员开发去马赛克工具,效果感人

    给小视频女主角换脸的 deepfakes 2017 年 12 月下旬,有个对 ML(机器学习)感兴趣程序员火遍全网,他的网名是 deepfakes.他做什么好事/坏事火了? 他自学深度学习(Deep ...

最新文章

  1. 信息安全的一些东西,初步查询了解!
  2. numpy 学习笔记
  3. java int数列转字符串,鍥剧墖杞瓧绗︿覆
  4. Ecplise中怎样导入Maven项目
  5. 【黑金原创教程】【FPGA那些事儿-驱动篇I 】实验二十:SDRAM模块③ — 页读写 α...
  6. OpenCV将GIS数据加载到OpenCV容器中的实例(附完整代码)
  7. java求质数为什么%3ci 2_C语言程序设计部分习题及例题参考程序
  8. [译+改]最长回文子串(Longest Palindromic Substring) Part II
  9. MySql 使用规范推荐(转)
  10. python 3.5 format_python 3.5学习笔记(第四章)
  11. java使用bks双向认证_android客户端SSL单向双向认证
  12. 水声方位估计 - MUSIC算法
  13. linux服务器中安装SVN,linux服务器安装svn并上传项目
  14. 浅析城市综合管廊配电结构
  15. STM32 f103搭配LM386声音传感器实现简单音乐识别
  16. [UE4]打包运行时提示Plugin ‘‘ failed to load because module ‘‘ could not be found.缺少插件解决方法
  17. Linux解压缩时报错: Error is not recoverable: exiting now
  18. 为什么我们需要关注基于 EIP-3664 标准的可拆分,可组合的NFT?
  19. 就是计算机信息学竞赛,什么是信息学竞赛NOI?参加信息学竞赛有什么用?
  20. Java+MySQL基于Springboot+vue的汉服交流网站#毕业设计

热门文章

  1. sqlserver 存储过程 分页搜索查询
  2. iOS设计模式-适配器
  3. 第二章 TestNG环境搭建
  4. Scala初体验之:Map
  5. transmute[推荐小软件]
  6. html5手机常亮,vue开发的webapp中的手机物理返回键,以及屏幕常亮处理
  7. 前端调数据会经常用到的事件处理
  8. webpack Babel
  9. windows下创建vp9的VS版本
  10. getFullYear 方法