如何使用画布在ImageView上绘制不受缩放或缩放影响的线条?

问题描述

我通过执行以下操作在ImageView上绘制线条:

    Bitmap imageBitmap = ((BitmapDrawable) imageView.getDrawable()).getBitmap();
    Bitmap duplicateBitmap = Bitmap.createBitmap(imageBitmap.getWidth(),imageBitmap.getHeight(),Bitmap.Config.RGB_565);

    Canvas targetCanvas = new Canvas(duplicateBitmap);
    targetCanvas.drawBitmap(imageBitmap,null);
    Paint paint = new Paint();
    paint.setColor(Color.RED);
    paint.setstrokeWidth(3f);
    targetCanvas.drawLine(0f,100f,imageBitmap.getWidth(),paint);
    imageView.setimageDrawable(new BitmapDrawable(getResources(),duplicateBitmap));

未放大时看起来还可以。

但是当我放大时,线条变粗了。 (这是预期的行为)

现在,如何在图像视图上绘制线条,以使用户放大时线条的粗细不受影响?

P.S:我先尝试“放大”图像,然后在图像上绘制线条。 (点击按钮或其他方式)。但这没有用,线仍然很粗。

我还发现,当图像分辨率较低时,绘制的线条会更粗。因此,我认为在图像上绘图也与图像分辨率有关。

我当时想用高分辨率画布遮盖ImageView,但这会降低内存效率。另外,我对如何真正实现这一点一无所知。

我以某种方式相信this question的答案可以解决我的问题。

解决方法

正确的方法是使用View画布动态渲染线条,而不是渲染到位图本身。

实现失败的原因是,如果直接将栅格渲染到位图中,则实际上是在更改位图像素,因此从逻辑上讲,如果缩放位图,则栅格像素也将缩放,如所有的位图+网格都变成了同一张图片

解决方案可以是使用任何现成的缩放图像视图小部件。您会在GitHub中找到很多东西,例如:

ZoomImageView

然后,您有2个选项,可以扩展小部件以创建自己的子类,或直接在小部件代码中执行实现。由您决定。

在这两种情况下,您都需要覆盖其 onDraw 回调,并在 super.onDraw(canvas)调用之后立即执行网格绘制。 无需创建新的位图或新的画布实例。使用方法的画布执行绘制。

Error: disk: duplicate SCSI unit_number 0

请注意,避免在onDraw方法内部创建新对象,例如Paint实例等,因为onDraw可以在短时间内多次调用。无论如何,皮棉应该警告您。切勿在诸如onDraw,onMeasure等方法中创建新的对象实例,因为此类情况始终要预先缓存/重用它们。

一种更简单的选择,是扩展视图并创建一个新的专用网格视图小部件,该窗口小部件与实际的“缩放图像视图”无关。执行相同的操作,因此,也要覆盖上面示例中的 onDraw 方法,并如图所示渲染网格。然后,将这个新的View放在布局设计中,恰好在Zoom Image View控件的顶部,以确保两个控件具有相同的指标。

,

使用此TouchImageView库进行缩放,并通过OnTouchImageViewListenerisZoomed()检测缩放。如果已缩放,请使用缩放区域重新绘制画布。这是代码:

touchImageView.setOnTouchImageViewListener(() -> {
    if (touchImageView.isZoomed()){
        //gets the zoomed area
        Bitmap result = Bitmap.createBitmap(touchImageView.getWidth(),touchImageView.getHeight(),Bitmap.Config.RGB_565);
        Canvas c = new Canvas(result);
        touchImageView.draw(c);
    }
});