通过触摸输入在位图上绘制透明线

发布于 2024-09-11 11:22:50 字数 3630 浏览 1 评论 0原文

我正在开发 Android 的绘图应用程序。现在我想实现一个橡皮擦,以允许通过使用触摸输入来擦除加载的位图的一部分,并使位图沿着手指的路径透明。

应用程序 Steamy 窗口(适用于 Android)。 Steamy Window 模拟雾化窗口,用户可以通过触摸输入擦除部分雾气。

有什么建议我可以如何实现该功能吗?

更新:我已在下面发布了当前代码中最重要的部分。我对它不太满意,原因如下:

  1. 绘图速度相当缓慢。这里我可以改进什么?

  2. 我正在寻找一种使用 alpha 蒙版的方法来设置像素的像素透明度/alpha,因为我想模拟画笔。有什么建议可以实现这一点吗?

        public DrawView(Context context, String imageName) {

        super(context);

        // Get the overlay image and its dimensions
        Bitmap overlayImageOriginal = BitmapFactory.decodeResource(
                getResources(), R.drawable.overlay);
        width = overlayImageOriginal.getWidth();
        height = overlayImageOriginal.getHeight();

        // Get a copy of the overlay image and recycle the original
        overlayImage = overlayImageOriginal.copy(Config.ARGB_8888, true);
        overlayImageOriginal.recycle();

        // Get background image of this level
        int resId = getResources().getIdentifier(imageName, "drawable",
                "com.xxx");
        backgroundImage = BitmapFactory.decodeResource(getResources(), resId);

        // Copy pixels
        overlayImagePixels = new int[width * height];
        overlayImage.getPixels(overlayImagePixels, 0, width, 0, 0, width,
                height);

        getHolder().addCallback(this);
        _thread = new DrawThread(getHolder(), this);
        setFocusable(true);
    }

    @Override
    public boolean onTouchEvent(MotionEvent event) {
        synchronized (_thread.getSurfaceHolder()) {
            switch (event.getAction()) {
            case MotionEvent.ACTION_DOWN:
                touchStart(event.getX(), event.getY());
                return true;
            case MotionEvent.ACTION_MOVE:
                touchMove(event.getX(), event.getY());
                return true;
            case MotionEvent.ACTION_UP:
                touchStop();
                return true;
            }
            return false;
        }
    }

    @Override
    public void onDraw(Canvas canvas) {
       // draw the image to guess
       canvas.drawBitmap(backgroundImage, 0, 0, null);
       // apply user input to the overlay-image
       setRegionTransparency((int) mTouchX, (int) mTouchY, 20, 0);
       // draw the overlay-image (hiding the image to guess)
       canvas.drawBitmap(overlayImage, 0, 0, null);
    }


    /**
     * 
     * @param posX
     * @param posY
     * @param radius
     * @param alpha - 0: full transparent, 255: full opaque
     */
    private void setRegionTransparency(int posX, int posY, int radius, int alpha) {
        int left = posX - radius;
        int right = posX + radius;
        int top = posY - radius;
        int bottom = posY + radius;
        int color = 0;

        // onDraw() is called before any user input
        // -> assume 0/0 as invalid arguments
        if (posX == 0 && posY == 0) {
              return;
        }

        // TODO currently only rectangular area is supported
        // but we need circular
        // we should use a pre-made alpha mask with smoothed edges
        // we should take into account: pressure and/or duration of touch

        for (int y = top; y = 0 && y = 0 && x = TOUCH_TOLERANCE || dy >= TOUCH_TOLERANCE) {
            mPath.quadTo(mTouchX, mTouchY, (x + mTouchX) / 2, (y + mTouchY) / 2);
            mTouchX = x;
            mTouchY = y;
        }
    }
}


I am working on a paint application for Android. Now I want to implement an eraser to allow erasing parts of a loaded bitmap by using touch input and making the bitmap transparent along the finger's path.

A very good example of what I try to achieve is shown in the application Steamy Window for Android. Steamy Window simulates a fogged window, where a user can wipe parts of the fog via touch input.

Any suggestions how I could implement the feature?

UPDATE: I have posted the most important sections of my current code below. I am not really happy with it for the following reasons:

  1. Drawing is quite sluggish. What can I improve here?

  2. I am looking for a way to use an alpha mask in order to set the pixel transparency/alpha of the pixels as I want to simulate a paint brush. Any suggestions how this could be achieved?

        public DrawView(Context context, String imageName) {

        super(context);

        // Get the overlay image and its dimensions
        Bitmap overlayImageOriginal = BitmapFactory.decodeResource(
                getResources(), R.drawable.overlay);
        width = overlayImageOriginal.getWidth();
        height = overlayImageOriginal.getHeight();

        // Get a copy of the overlay image and recycle the original
        overlayImage = overlayImageOriginal.copy(Config.ARGB_8888, true);
        overlayImageOriginal.recycle();

        // Get background image of this level
        int resId = getResources().getIdentifier(imageName, "drawable",
                "com.xxx");
        backgroundImage = BitmapFactory.decodeResource(getResources(), resId);

        // Copy pixels
        overlayImagePixels = new int[width * height];
        overlayImage.getPixels(overlayImagePixels, 0, width, 0, 0, width,
                height);

        getHolder().addCallback(this);
        _thread = new DrawThread(getHolder(), this);
        setFocusable(true);
    }

    @Override
    public boolean onTouchEvent(MotionEvent event) {
        synchronized (_thread.getSurfaceHolder()) {
            switch (event.getAction()) {
            case MotionEvent.ACTION_DOWN:
                touchStart(event.getX(), event.getY());
                return true;
            case MotionEvent.ACTION_MOVE:
                touchMove(event.getX(), event.getY());
                return true;
            case MotionEvent.ACTION_UP:
                touchStop();
                return true;
            }
            return false;
        }
    }

    @Override
    public void onDraw(Canvas canvas) {
       // draw the image to guess
       canvas.drawBitmap(backgroundImage, 0, 0, null);
       // apply user input to the overlay-image
       setRegionTransparency((int) mTouchX, (int) mTouchY, 20, 0);
       // draw the overlay-image (hiding the image to guess)
       canvas.drawBitmap(overlayImage, 0, 0, null);
    }


    /**
     * 
     * @param posX
     * @param posY
     * @param radius
     * @param alpha - 0: full transparent, 255: full opaque
     */
    private void setRegionTransparency(int posX, int posY, int radius, int alpha) {
        int left = posX - radius;
        int right = posX + radius;
        int top = posY - radius;
        int bottom = posY + radius;
        int color = 0;

        // onDraw() is called before any user input
        // -> assume 0/0 as invalid arguments
        if (posX == 0 && posY == 0) {
              return;
        }

        // TODO currently only rectangular area is supported
        // but we need circular
        // we should use a pre-made alpha mask with smoothed edges
        // we should take into account: pressure and/or duration of touch

        for (int y = top; y = 0 && y = 0 && x = TOUCH_TOLERANCE || dy >= TOUCH_TOLERANCE) {
            mPath.quadTo(mTouchX, mTouchY, (x + mTouchX) / 2, (y + mTouchY) / 2);
            mTouchX = x;
            mTouchY = y;
        }
    }
}


如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文