PhotoView实现图片动态马赛克效果

PhotoView实现图片动态马赛克效果

【免费下载链接】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);

实现思路

动态马赛克效果的实现主要包括以下步骤:

  1. 监听用户触摸事件,记录需要打马赛克的区域
  2. 将屏幕坐标转换为图片实际坐标
  3. 对指定区域应用马赛克算法
  4. 在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实现图片动态马赛克效果,主要包括:

  1. 利用PhotoView的矩阵变换实现坐标转换
  2. 通过触摸事件监听获取用户绘制区域
  3. 实现简单的马赛克算法
  4. 自定义PhotoView实现叠加绘制

这种实现方式不仅保留了PhotoView原有的缩放、平移等功能,还添加了实用的马赛克效果,可广泛应用于图片查看和编辑类应用中。

如果你想进一步优化,可以考虑:

  • 添加马赛克大小调整功能
  • 实现撤销/重做功能
  • 优化马赛克算法性能
  • 支持多种马赛克形状

完整代码可参考示例项目中的SimpleSampleActivity.java进行修改扩展。

【免费下载链接】PhotoView 【免费下载链接】PhotoView 项目地址: https://gitcode.com/gh_mirrors/pho/PhotoView

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值