Android - 使用泛洪填充时画布变黑

25

当我实现我的flood-fill类时,整个Bitmap都变成了黑色。显然这不是期望的效果。我看过以下帖子:

从这些帖子中我能看出我正在尝试他们提出的所有解决方案,但是还没有找到解决我的问题的方法。所以为了直接点,这里是代码和一些简要说明。

XML
我使用相对布局,并将两个ImageViews堆叠在一起。它们都有相同的图像,这创造了你可以在图像上绘制的幻觉。但实际上,你只是在一个透明的覆盖层上进行绘制。

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="horizontal" >

    ....

    <ImageView
        android:id="@+id/drawContainer2"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:layout_toRightOf="@id/imageMapperSurfaces"
        android:contentDescription="@string/image" />

    <ImageView
        android:id="@+id/drawContainer"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:layout_toRightOf="@id/imageMapperSurfaces"
        android:contentDescription="@string/image" />

   ...
</RelativeLayout>

画布(Canvas)
使用以下代码创建Canvas,确保设置图层类型正确。

public void setCanvas() {
    if(mFile != null && mFile.exists()) {
        mPictureBitmap = BitmapFactory.decodeFile(mFile.getAbsolutePath());
        mBitmap = Bitmap.createScaledBitmap(mPictureBitmap, mImageView.getWidth(), mImageView.getHeight(), false);
        mPictureBitmap = mBitmap.copy(Bitmap.Config.ARGB_8888, true);
        mBitmap = mPictureBitmap.copy(Bitmap.Config.ARGB_8888, true);
        mSceneBitmap = mBitmap.copy(Bitmap.Config.ARGB_8888, true);
        mBlurBitmap = blurImage(mPictureBitmap); 
        mCanvas = new Canvas(mBitmap);
        mImageView.setImageBitmap(mBitmap);
        mImageView2.setImageBitmap(mPictureBitmap);
        mBlur.setImageBitmap(mBlurBitmap);

        // failure to set these layer types correctly will result in a black canvas after drawing.
        mImageView.setLayerType(View.LAYER_TYPE_HARDWARE, null);
        mImageView2.setLayerType(View.LAYER_TYPE_HARDWARE, null);
        mImageView.bringToFront();
        mAllowedToDraw = true;

        setImageViewOnTouch();
    }
}

泛洪填充实现
我获取颜色,将我的参数传递给flood-fill对象,使用flood-fill方法,返回bitmap,最后将新的bitmap绘制到我的canvas上。

int targetColor = mSceneBitmap.getPixel((int) event.getX(), (int) event.getY());
FloodFill fill = new FloodFill(mBitmap, targetColor, Color.argb(100, 255, 0, 0));
fill.floodFill((int) event.getX(), (int) event.getY());
Bitmap bmp = fill.getImage();
mCanvas.drawBitmap(bmp, 0, 0, null);
mImageView.invalidate();

泛洪填充类
这是一个通用的泛洪填充算法。

public class FloodFill {
    protected Bitmap mImage = null;
    protected int[] mTolerance = new int[] { 0, 0, 0, 0 };
    protected int mWidth = 0;
    protected int mHeight = 0;
    protected int[] mPixels = null;
    protected int mFillColor = 0;
    protected int[] mStartColor = new int[] { 0, 0, 0, 0 };
    protected boolean[] mPixelsChecked;
    protected Queue<FloodFillRange> mRanges;

    public FloodFill(Bitmap img) {
        copyImage(img);
    }

    public FloodFill(Bitmap img, int targetColor, int newColor) {
        useImage(img);

        setFillColor(newColor);
        setTargetColor(targetColor);
    }

    public void setTargetColor(int targetColor) {
        mStartColor[0] = Color.red(targetColor);
        Log.v("Red", "" + mStartColor[0]);
        mStartColor[1] = Color.green(targetColor);
        Log.v("Green", "" + mStartColor[1]);
        mStartColor[2] = Color.blue(targetColor);
        Log.v("Blue", "" + mStartColor[2]);
        mStartColor[3] = Color.alpha(targetColor);
        Log.v("Alpha", "" + mStartColor[3]);
    }

    public int getFillColor() {
        return mFillColor;
    }

    public void setFillColor(int value) {
        mFillColor = value;
    }

    public int[] getTolerance() {
        return mTolerance;
    }

    public void setTolerance(int[] value) {
        mTolerance = value;
    }

    public void setTolerance(int value) {
        mTolerance = new int[] { value, value, value, value };
    }

    public Bitmap getImage() {
        return mImage;
    }

    public void copyImage(Bitmap img) {
        mWidth = img.getWidth();
        mHeight = img.getHeight();

        mImage = Bitmap.createBitmap(mWidth, mHeight, Bitmap.Config.ARGB_8888);
        Canvas canvas = new Canvas(mImage);
        canvas.drawBitmap(img, 0, 0, null);

        mPixels = new int[mWidth * mHeight];

        mImage.getPixels(mPixels, 0, mWidth, 0, 0, mWidth, mHeight);
    }

    public void useImage(Bitmap img) {
        mWidth = img.getWidth();
        mHeight = img.getHeight();
        mImage = img;

        mPixels = new int[mWidth * mHeight];

        mImage.getPixels(mPixels, 0, mWidth, 0, 0, mWidth, mHeight);
    }

    protected void prepare() {
        mPixelsChecked = new boolean[mPixels.length];
        mRanges = new LinkedList<FloodFillRange>();
    }

    public void floodFill(int x, int y) {
        // Setup
        prepare();

        if (mStartColor[0] == 0) {
            // ***Get starting color.
            int startPixel = mPixels[(mWidth * y) + x];
            mStartColor[0] = (startPixel >> 16) & 0xff;
            mStartColor[1] = (startPixel >> 8) & 0xff;
            mStartColor[2] = startPixel & 0xff;
        }

        LinearFill(x, y);
        FloodFillRange range;

        while (mRanges.size() > 0) {
            range = mRanges.remove();
            int downPxIdx = (mWidth * (range.Y + 1)) + range.startX;
            int upPxIdx = (mWidth * (range.Y - 1)) + range.startX;
            int upY = range.Y - 1;
            int downY = range.Y + 1;

            for (int i = range.startX; i <= range.endX; i++) {
                if (range.Y > 0 && (!mPixelsChecked[upPxIdx]) && CheckPixel(upPxIdx)) LinearFill(i, upY);
                if (range.Y < (mHeight - 1) && (!mPixelsChecked[downPxIdx]) && CheckPixel(downPxIdx)) LinearFill(i, downY);
                downPxIdx++;
                upPxIdx++;
            }
        }

        mImage.setPixels(mPixels, 0, mWidth, 0, 0, mWidth, mHeight);
    }

    protected void LinearFill(int x, int y) {
        int lFillLoc = x;
        int pxIdx = (mWidth * y) + x;

        while (true) {
            mPixels[pxIdx] = mFillColor;
            mPixelsChecked[pxIdx] = true;
            lFillLoc--;
            pxIdx--;

            if (lFillLoc < 0 || (mPixelsChecked[pxIdx]) || !CheckPixel(pxIdx)) {
                break;
            }
        }

        lFillLoc++;
        int rFillLoc = x; 

        pxIdx = (mWidth * y) + x;

        while (true) {
            mPixels[pxIdx] = mFillColor;
            mPixelsChecked[pxIdx] = true;

            rFillLoc++;
            pxIdx++;

            if (rFillLoc >= mWidth || mPixelsChecked[pxIdx] || !CheckPixel(pxIdx)) {
                break;
            }
        }

        rFillLoc--;

        FloodFillRange r = new FloodFillRange(lFillLoc, rFillLoc, y);

        mRanges.offer(r);
    }

    protected boolean CheckPixel(int px) {
        int red = (mPixels[px] >>> 16) & 0xff;
        int green = (mPixels[px] >>> 8) & 0xff;
        int blue = mPixels[px] & 0xff;
        int alpha = (Color.alpha(mPixels[px]));

        return (red >= (mStartColor[0] - mTolerance[0]) && red <= (mStartColor[0] + mTolerance[0])
                && green >= (mStartColor[1] - mTolerance[1]) && green <= (mStartColor[1] + mTolerance[1])
                && blue >= (mStartColor[2] - mTolerance[2]) && blue <= (mStartColor[2] + mTolerance[2])
                && alpha >= (mStartColor[3] - mTolerance[3]) && alpha <= (mStartColor[3] + mTolerance[3]));
    }

    protected class FloodFillRange {
        public int startX;
        public int endX;
        public int Y;

        public FloodFillRange(int startX, int endX, int y) {
            this.startX = startX;
            this.endX = endX;
            this.Y = y;
        }
    }
}

所以这就是问题的所有要素,但出于某些原因它们没有起作用。我感到很困惑,任何帮助都将不胜感激。谢谢!

2个回答

0

我认为你的代码行:

mCanvas.drawBitmap(bmp, 0, 0, null);

可能需要更像这样

mPaint = new Paint();    
mCanvas.drawBitmap(bmp, 0, 0, mPaint);

0

我不是很确定,但据我所知,我会尝试这些解决方案:

第一: 不要使用decodeFile,而是使用decodeInputStream 第二: 正如有人回答的那样,在显示视图时最好使用Paint() 第三: 我想问一下,为什么你需要那个填充算法?我认为它太卡了,看起来有点乱,为什么不创建一个新的缩放位图或类似于OpenGL效果的东西来完成它?因为这就是为什么有显卡的原因;


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接