PhotoView实现图片动态马赛克效果
【免费下载链接】PhotoView 项目地址: https://gitcode.com/gh_mirrors/pho/PhotoView
引言
你是否曾经需要在查看图片时,对敏感区域进行模糊处理?比如在分享截图时遮盖个人信息,或者在展示照片时保护隐私?使用PhotoView库,我们可以轻松实现这一功能,让用户通过简单的触摸操作,就能在图片上添加动态马赛克效果。本文将详细介绍如何基于PhotoView实现这一实用功能,读完你将学会:
- 集成PhotoView到Android项目
- 监听用户触摸事件获取马赛克区域
- 实现图片马赛克算法
- 在PhotoView中叠加马赛克图层
PhotoView基础
PhotoView是一个强大的Android图片查看库,支持缩放、平移、旋转等手势操作。其核心类包括:
- PhotoView:继承自AppCompatImageView,提供图片显示和手势交互功能
- PhotoViewAttacher:处理缩放、拖动等触摸事件的逻辑实现
要使用PhotoView,首先需要在布局文件中添加PhotoView控件,如示例项目中的sample/src/main/res/layout/activity_simple_sample.xml所示:
<com.github.chrisbanes.photoview.PhotoView
android:id="@+id/iv_photo"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:src="@drawable/wallpaper" />
然后在Activity中初始化并设置图片:
PhotoView mPhotoView = findViewById(R.id.iv_photo);
Drawable bitmap = ContextCompat.getDrawable(this, R.drawable.wallpaper);
mPhotoView.setImageDrawable(bitmap);
实现思路
动态马赛克效果的实现主要包括以下步骤:
- 监听用户触摸事件,记录需要打马赛克的区域
- 将屏幕坐标转换为图片实际坐标
- 对指定区域应用马赛克算法
- 在PhotoView上叠加显示马赛克效果
下面我们将逐步实现这些功能。
监听触摸事件
PhotoView提供了丰富的触摸事件监听接口,我们可以使用OnTouchListener来获取用户的触摸轨迹。首先创建一个自定义的马赛克触摸监听器:
public class MosaicTouchListener implements View.OnTouchListener {
private List<PointF> mosaicPoints = new ArrayList<>();
@Override
public boolean onTouch(View v, MotionEvent event) {
PhotoView photoView = (PhotoView) v;
Matrix inverseMatrix = new Matrix();
photoView.getImageMatrix().invert(inverseMatrix);
float[] touchPoint = new float[]{event.getX(), event.getY()};
inverseMatrix.mapPoints(touchPoint);
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
mosaicPoints.clear();
mosaicPoints.add(new PointF(touchPoint[0], touchPoint[1]));
break;
case MotionEvent.ACTION_MOVE:
mosaicPoints.add(new PointF(touchPoint[0], touchPoint[1]));
break;
case MotionEvent.ACTION_UP:
// 处理马赛克绘制
break;
}
return true;
}
}
这里需要注意的是,我们需要通过PhotoView的getImageMatrix()方法获取当前图片的矩阵变换,然后通过逆矩阵将屏幕坐标转换为图片实际坐标。
马赛克算法实现
马赛克效果的核心是将图片中指定区域的像素进行模糊处理。一种简单的实现方式是将图片分成小块,每块取平均颜色值:
public Bitmap applyMosaic(Bitmap sourceBitmap, List<PointF> points, int mosaicSize) {
Bitmap mosaicBitmap = sourceBitmap.copy(Bitmap.Config.ARGB_8888, true);
Canvas canvas = new Canvas(mosaicBitmap);
Paint paint = new Paint();
Path path = new Path();
if (!points.isEmpty()) {
path.moveTo(points.get(0).x, points.get(0).y);
for (int i = 1; i < points.size(); i++) {
path.lineTo(points.get(i).x, points.get(i).y);
}
// 创建马赛克路径的遮罩
Bitmap maskBitmap = Bitmap.createBitmap(sourceBitmap.getWidth(), sourceBitmap.getHeight(), Bitmap.Config.ARGB_8888);
Canvas maskCanvas = new Canvas(maskBitmap);
Paint maskPaint = new Paint();
maskPaint.setColor(Color.BLACK);
maskPaint.setStyle(Paint.Style.STROKE);
maskPaint.setStrokeWidth(mosaicSize * 2);
maskCanvas.drawPath(path, maskPaint);
// 应用马赛克算法
for (int x = 0; x < sourceBitmap.getWidth(); x += mosaicSize) {
for (int y = 0; y < sourceBitmap.getHeight(); y += mosaicSize) {
if (maskBitmap.getPixel(x, y) != 0) {
int pixelColor = sourceBitmap.getPixel(x, y);
paint.setColor(pixelColor);
canvas.drawRect(x, y, x + mosaicSize, y + mosaicSize, paint);
}
}
}
}
return mosaicBitmap;
}
自定义PhotoView实现叠加绘制
为了在PhotoView上叠加马赛克效果,我们需要自定义一个MosaicPhotoView,重写onDraw方法:
public class MosaicPhotoView extends PhotoView {
private Bitmap mosaicBitmap;
public MosaicPhotoView(Context context) {
super(context);
}
public MosaicPhotoView(Context context, AttributeSet attr) {
super(context, attr);
}
public MosaicPhotoView(Context context, AttributeSet attr, int defStyle) {
super(context, attr, defStyle);
}
public void setMosaicBitmap(Bitmap bitmap) {
mosaicBitmap = bitmap;
invalidate();
}
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
if (mosaicBitmap != null) {
canvas.drawBitmap(mosaicBitmap, getImageMatrix(), null);
}
}
}
整合实现
最后,我们将上述组件整合到Activity中:
public class MosaicSampleActivity extends AppCompatActivity {
private MosaicPhotoView mPhotoView;
private MosaicTouchListener mMosaicTouchListener;
private Bitmap originalBitmap;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_mosaic_sample);
mPhotoView = findViewById(R.id.iv_photo);
mMosaicTouchListener = new MosaicTouchListener();
mPhotoView.setOnTouchListener(mMosaicTouchListener);
// 加载原始图片
originalBitmap = BitmapFactory.decodeResource(getResources(), R.drawable.wallpaper);
mPhotoView.setImageBitmap(originalBitmap);
// 马赛克按钮点击事件
Button mosaicButton = findViewById(R.id.btn_apply_mosaic);
mosaicButton.setOnClickListener(v -> applyMosaicEffect());
}
private void applyMosaicEffect() {
Bitmap mosaicBitmap = applyMosaic(originalBitmap, mMosaicTouchListener.getMosaicPoints(), 20);
mPhotoView.setMosaicBitmap(mosaicBitmap);
}
}
效果展示
通过以上实现,我们可以在示例应用中看到如下效果:
用户可以通过触摸屏幕绘制需要打马赛克的区域,点击应用按钮后,指定区域将显示马赛克效果。
总结
本文介绍了如何基于PhotoView实现图片动态马赛克效果,主要包括:
- 利用PhotoView的矩阵变换实现坐标转换
- 通过触摸事件监听获取用户绘制区域
- 实现简单的马赛克算法
- 自定义PhotoView实现叠加绘制
这种实现方式不仅保留了PhotoView原有的缩放、平移等功能,还添加了实用的马赛克效果,可广泛应用于图片查看和编辑类应用中。
如果你想进一步优化,可以考虑:
- 添加马赛克大小调整功能
- 实现撤销/重做功能
- 优化马赛克算法性能
- 支持多种马赛克形状
完整代码可参考示例项目中的SimpleSampleActivity.java进行修改扩展。
【免费下载链接】PhotoView 项目地址: https://gitcode.com/gh_mirrors/pho/PhotoView
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考




