当使用洪水填充算法填充颜色后绘制线条时,填充颜色消失
Posted
技术标签:
【中文标题】当使用洪水填充算法填充颜色后绘制线条时,填充颜色消失【英文标题】:When line is draw after filling color using flood fill algorithm then filling color is gone 【发布时间】:2015-06-30 05:04:00 【问题描述】:我有画布绘图应用程序。我成功地完成了集成填充算法,通过手指绘制形状为手指绘制圆形和矩形区域填充颜色。我的问题是用手指为创建的形状填充颜色后,在画布上绘制线条时填充的颜色消失了。
public class DrawingView extends View
private final Paint mDefaultPaint;
private final Paint mFloodPaint = new Paint();
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);
/*mFloodPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
mFloodPaint.setStyle(Paint.Style.STROKE);
mFloodPaint.setStrokeJoin(Paint.Join.ROUND);
mFloodPaint.setStrokeCap(Paint.Cap.ROUND);
mFloodPaint.setStrokeWidth(40);
mFloodPaint.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();
// final int targetColor = mFloodPaint.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);*/
else if(isFill == false)
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:
if(isFill == false)
// mLayerCanvas.drawColor(0, PorterDuff.Mode.CLEAR);
for (int p = 0; p < pointerCount; p++)
final int id = MotionEventCompat.getPointerId(event, p);
mDrawOps.push(mCurrentOps.get(id));
mCurrentOps.remove(id);
updateLayer();
/* else
for (int p = 0; p < pointerCount; p++)
final int id = MotionEventCompat.getPointerId(event, p);
mDrawOps.push(mCurrentOps.get(id));
mCurrentOps.remove(id);
*/
//
break;
case MotionEvent.ACTION_CANCEL:
if(isFill == false)
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 fillShapeColor()
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 updateDLayer()
mLayerCanvas.drawColor(0, PorterDuff.Mode.CLEAR);
for (DrawOp drawOp : mDrawOps)
if (drawOp != null)
// drawOp.draw(new Canvas(mLayerBitmap));
drawOp.draw(mLayerCanvas);
invalidate();
*/
private void updateLayer()
/* isFill=false;
if(isFill==false)
mLayerCanvas.drawColor(0, PorterDuff.Mode.CLEAR);
else
System.out.println("Not using mLayerCanvas.drawColor()");
*/
// mLayerCanvas.drawColor(0, PorterDuff.Mode.CLEAR);
// this.getPaintStrokeWidth();
// this.getPaintMaskFilter();
/* if(isFill == false)
// this.getPaintOpacity();
mLayerCanvas.save();
// mLayerCanvas.drawColor(0, PorterDuff.Mode.CLEAR);
mLayerCanvas.restore();
*/
/*mDefaultPaint.setXfermode(new PorterDuffXfermode(Mode.CLEAR));
mLayerCanvas.drawPaint(mDefaultPaint);
mDefaultPaint.setXfermode(new PorterDuffXfermode(Mode.SRC));
mLayerCanvas.drawPaint(mDefaultPaint);*/
/* if(isFill==false)
mLayerCanvas.save();
mLayerCanvas.drawColor(0, PorterDuff.Mode.CLEAR);
mLayerCanvas.restore();
invalidate();
else
mLayerCanvas.save();
for (DrawOp drawOp : mDrawOps)
if (drawOp != null)
// drawOp.draw(new Canvas(mLayerBitmap));
drawOp.draw(mLayerCanvas);
mLayerCanvas.restore();
*/
/*DrawOp dr = new DrawOp(mDefaultPaint);
if(dr.getPath().isEmpty())
// isFill = true;
isFill = false;
else
isFill=true;
mLayerCanvas.drawColor(0, PorterDuff.Mode.CLEAR);
*/
if(isFill == false)
mLayerCanvas.drawColor(0, PorterDuff.Mode.CLEAR);
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;
/*int w = canvas.getWidth();
int h = canvas.getHeight();
canvas.drawRect(0,0,w,h, mDefaultPaint);*/
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);
// mFloodPaint.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));
// mFloodPaint.setColor(combineAlpha(mFloodPaint.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());
mFloodPaint.setXfermode(null);
mFloodPaint.setColor(combineAlpha(Color.parseColor(color),
mFloodPaint.getAlpha()));
public void setPaintColor(int color)
mDefaultPaint.setXfermode(null);
mDefaultPaint.setColor(combineAlpha(color, mDefaultPaint.getAlpha()));
mFloodPaint.setXfermode(null);
mFloodPaint.setColor(combineAlpha(color, mFloodPaint.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);
// mFloodPaint.setMaskFilter(filter);
/*public MaskFilter getPaintMaskFilter()
return mDefaultPaint.getMaskFilter();
*/
public void setPaintShader(BitmapShader shader)
mDefaultPaint.setShader(shader);
// mFloodPaint.setShader(shader);
public void setPaintColorFilter(ColorFilter colorFilter)
mDefaultPaint.setColorFilter(colorFilter);
// mFloodPaint.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;
public void setFillColor(boolean flag)
this.isFill = flag;
【问题讨论】:
【参考方案1】:更新您的 updateLayer() 方法,如下所示:
private void updateLayer()
/*if(isFill == false)
mCanvas.drawColor(0, PorterDuff.Mode.CLEAR);
*/
for (DrawOp drawOp : mDrawOps)
if (drawOp != null)
drawOp.draw(mCanvas);
invalidate();
【讨论】:
以上是关于当使用洪水填充算法填充颜色后绘制线条时,填充颜色消失的主要内容,如果未能解决你的问题,请参考以下文章
R语言使用ggplot2包使用geom_density()函数绘制密度图(自定义颜色填充线条色彩分组均值线)实战(density plot)