android - 在 android 中使用 FloodFill 后 Canvas 手指绘图不透明度增加

标签 android android-canvas flood-fill

我有 Canvas 绘图应用程序。我成功地集成了用于手指绘制圆形和矩形区域填充颜色的 floodfill 算法。我的问题是当我使用模糊蒙版画笔效果并使用手指通过模糊蒙版画笔绘制时,在手指绘图圆上填充颜色后,整个模糊蒙版画笔绘图被一次又一次地重新绘制。这是我的代码:

public class DrawingView extends View {
    private final Paint mDefaultPaint;
    Bitmap mBitmap;
    float x, y;
    ProgressDialog pd;
    LinearLayout drawing_layout;
    private Canvas mLayerCanvas = new Canvas();
    private Bitmap mLayerBitmap;
    final Point p1 = new Point();
    private Stack<DrawOp> mDrawOps = new Stack<>();
    private Stack<DrawOp> mUndoOps = new Stack<>();

    boolean isFill = false;
    private SparseArray<DrawOp> mCurrentOps = new SparseArray<>(0);

    public DrawingView(Context context) {
        this(context, null, 0);

    }

    public DrawingView(Context context, AttributeSet attrs) {
        this(context, attrs, 0);
    }

    public DrawingView(Context context, AttributeSet attrs, int defStyle) {
        super(context, attrs, defStyle);

        mDefaultPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
        mDefaultPaint.setStyle(Paint.Style.STROKE);
        mDefaultPaint.setStrokeJoin(Paint.Join.ROUND);
        mDefaultPaint.setStrokeCap(Paint.Cap.ROUND);
        mDefaultPaint.setStrokeWidth(40);
        mDefaultPaint.setColor(Color.GREEN);

        setFocusable(true);
        setFocusableInTouchMode(true);
        setBackgroundColor(Color.WHITE);

        setLayerType(LAYER_TYPE_SOFTWARE, null);
        setSaveEnabled(true);
    }

    @Override
    public boolean onTouchEvent(@NonNull MotionEvent event) {
        final int pointerCount = MotionEventCompat.getPointerCount(event);

        switch (MotionEventCompat.getActionMasked(event)) {
        case MotionEvent.ACTION_DOWN: {
            if (isFill == true) {

                int xx = (int) event.getX();
                int yy = (int) event.getY();
                Point pp = new Point(xx, yy);

                /*Point pp = new Point();
                pp.x = (int) event.getX();
                pp.y = (int) event.getY();*/

                final int sourceColor = mLayerBitmap.getPixel(xx, yy);
                final int targetColor = mDefaultPaint.getColor();

                new TheTask(mLayerBitmap, pp, sourceColor, targetColor)
                        .execute();

//              JniBitmap.floodFill(mLayerBitmap, xx, yy, sourceColor,targetColor);

/*              FloodFill f = new FloodFill();
                f.floodFill(mLayerBitmap, pp, sourceColor, targetColor);*/

            }
            for (int p = 0; p < pointerCount; p++) {
                final int id = MotionEventCompat.getPointerId(event, p);
                DrawOp current = new DrawOp(mDefaultPaint);
                current.getPath().moveTo(event.getX(), event.getY());
                mCurrentOps.put(id, current);
            }
        }
            break;

        case MotionEvent.ACTION_MOVE: {

                if (isFill == false) {

                final int id = MotionEventCompat.getPointerId(event, 0);
                DrawOp current = mCurrentOps.get(id);
                final int historySize = event.getHistorySize();
                for (int h = 0; h < historySize; h++) {
                    x = event.getHistoricalX(h);
                    y = event.getHistoricalY(h);
                    current.getPath().lineTo(x, y);
                }
                x = MotionEventCompat.getX(event, 0);
                y = MotionEventCompat.getY(event, 0);
                current.getPath().lineTo(x, y);
            }
        }
            break;

        case MotionEvent.ACTION_UP: {
            for (int p = 0; p < pointerCount; p++) {
                final int id = MotionEventCompat.getPointerId(event, p);
                mDrawOps.push(mCurrentOps.get(id));
                mCurrentOps.remove(id);
            }
            updateLayer();
        }
            break;

        case MotionEvent.ACTION_CANCEL: {
            for (int p = 0; p < pointerCount; p++) {
                mCurrentOps.remove(MotionEventCompat.getPointerId(event, p));
            }
            updateLayer();
        }
            break;

        default:
            return false;
        }

        invalidate();
        return true;
    }

    class TheTask extends AsyncTask<Void, Integer, Void> {

        Bitmap bmp;
        Point pt;
        int replacementColor, targetColor;

        public TheTask(Bitmap bm, Point p, int sc, int tc) {
//          this.bmp = bm;
            mLayerBitmap = bm;
            pd = new ProgressDialog(getContext());
            this.pt = p;
            this.replacementColor = tc;
            this.targetColor = sc;
            pd.setMessage("Filling....");
            pd.show();
        }

        @Override
        protected void onPreExecute() {
        }

        @Override
        protected void onProgressUpdate(Integer... values) {
        }

        @Override
        protected Void doInBackground(Void... params) {
            FloodFill f = new FloodFill();
//           mLayerBitmap = f.floodFill(bmp, pt, targetColor, replacementColor);
            f.floodFill(mLayerBitmap, pt, targetColor, replacementColor);

//          New Commented Algorithm
//          f.FloodFill(mLayerBitmap, pt, targetColor, replacementColor);
            return null;
        }

        @Override
        protected void onPostExecute(Void result) {
            pd.dismiss();
            invalidate();
            isFill = false;
        }
    }

    public void fillShapeColor(Bitmap mBitmap2) {
        isFill = true;
    }

    public void setDrawing() {
        isFill = false;
    }

    @Override
    protected void onSizeChanged(int w, int h, int oldW, int oldH) {
        super.onSizeChanged(w, h, oldW, oldH);
        mLayerBitmap = Bitmap.createBitmap(w, h, Bitmap.Config.ARGB_8888);
        mLayerCanvas.setBitmap(mLayerBitmap);
        updateLayer();
    }

    private void updateLayer() {


        for (DrawOp drawOp : mDrawOps) {
            if (drawOp != null) {
//              drawOp.draw(new Canvas(mLayerBitmap));
                drawOp.draw(mLayerCanvas);
            }
        }
        invalidate();
    }

    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);

        if (isInEditMode()) {
            return;
        }
        canvas.drawBitmap(mLayerBitmap, 0, 0, null);

        for (int i = 0; i < mCurrentOps.size(); i++) {
            DrawOp current = mCurrentOps.valueAt(i);
            if (current != null) {
                current.draw(canvas);
            }
        }
    }

    public void operationClear() {
        mDrawOps.clear();
        mUndoOps.clear();
        mCurrentOps.clear();
        // To Clear Whole Canvas
        mLayerCanvas.drawColor(0, PorterDuff.Mode.CLEAR);
        updateLayer();
    }

    public void operationUndo() {
        if (mDrawOps.size() > 0) {
            mUndoOps.push(mDrawOps.pop());
            updateLayer();
        }
    }

    public void operationRedo() {
        if (mUndoOps.size() > 0) {
            mDrawOps.push(mUndoOps.pop());
            updateLayer();
        }
    }

    public void setPaintStrokeWidth(float widthPx) {
        mDefaultPaint.setStrokeWidth(widthPx);
    }

    /*public float getPaintStrokeWidth(){
        return mDefaultPaint.getStrokeWidth();

    }*/

    public void setPaintOpacity(int percent) {
        int alphaValue = (int) Math.round(percent * (255.0 / 100.0));
        mDefaultPaint.setColor(combineAlpha(mDefaultPaint.getColor(),
                alphaValue));
    }

    /*public int getPaintOpacity(){
        this.setPaintOpacity(50);
        return mDefaultPaint.getColor();
    }*/

    public void setPaintColor(String color) {
        mDefaultPaint.setXfermode(null);
        mDefaultPaint.setColor(combineAlpha(Color.parseColor(color),
                mDefaultPaint.getAlpha()));
//      mDefaultPaint.setColor(mDefaultPaint.getAlpha());
    }

    public void setPaintColor(int color) {
        mDefaultPaint.setXfermode(null);
        mDefaultPaint.setColor(combineAlpha(color, mDefaultPaint.getAlpha()));
    }

//  New Created
    public void setEraser(int color){
//      mDefaultPaint.setAlpha(0xFF);
        mDefaultPaint.setColor(color);
        mDefaultPaint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.CLEAR));
    }

    public void setPaintMaskFilter(MaskFilter filter) {
        mDefaultPaint.setMaskFilter(filter);
    }

    /*public MaskFilter getPaintMaskFilter(){
        return mDefaultPaint.getMaskFilter();

    }*/

    public void setPaintShader(BitmapShader shader) {
        mDefaultPaint.setShader(shader);
    }

    public void setPaintColorFilter(ColorFilter colorFilter) {
        mDefaultPaint.setColorFilter(colorFilter);
    }

    private static int combineAlpha(int color, int alpha) {
        return (color & 0x00FFFFFF) | ((alpha & 0xFF) << 24);
    }

    private static class DrawOp {
        private final Paint mPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
        private final Path mPath = new Path();

        public DrawOp(Paint paint) {
            reset(paint);
        }

        void reset(Paint paint) {
            mPath.reset();
            update(paint);
        }

        void update(Paint paint) {
            mPaint.set(paint);
        }

        void draw(Canvas canvas) {
            canvas.drawPath(mPath, mPaint);
        }

        public Path getPath() {
            return mPath;
        }
    }
}

最佳答案

经过大量研究后,我喜欢上了我的问题并加以改正。下面是我的代码。

    if (isFloodFill) {
        if (mZoomMode) {
            return false;
        } else {

            final Point p = new Point();
            float[] mTmpPoint1 = new float[2];

            mTmpPoint1[0] = event.getX() - mPanX;
            mTmpPoint1[1] = event.getY() - mPanY;

            mZoomMatrixInv.mapPoints(mTmpPoint1);

            p.x = (int) (mTmpPoint1[0]);
            p.y = (int) (mTmpPoint1[1]);

            System.out.println("--plotX mTmpPoint0: touch:" + p.x);
            System.out.println("--plotY mTmpPoint0: touch:" + p.y);

            this.mBitmap = getBitmap();
            if (this.mBitmap != null) {

                if(p.x > mBitmap.getWidth() || p.y > mBitmap.getHeight())
                {
                    return false;
                }
                else
                {
                    if(p.x >= 0 && p.y >= 0)
                    {
                        this.color = this.mBitmap.getPixel(p.x, p.y);   
                    }
                    else
                    {
                        return false;
                    }
                }
            }
            try {
                // isFilling = false;
                new FloodFillAlgo().execute(p);
                return false;
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    }

关于android - 在 android 中使用 FloodFill 后 Canvas 手指绘图不透明度增加,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/31068481/

相关文章:

java - 边界填充算法..java中的Stackoverflow错误

android 中的 java.lang.NoClassDefFoundError

android - Android ImageView 上的减法滤镜(从图像或 View 对象中切出羽毛状椭圆)

java - 将图像转换为二维数组仅获取左上象限

c++ flood fill图像递归算法错误

algorithm - 用矩形填充二维形状

android - 如何创建自己的资源名称?

android - 在 Android list 中使用 largeheap 是一个好习惯吗?

android - 网格渲染问题 libgdx

android - 围绕其中心旋转自定义图像