5

I have a canvas on which I draw lines:

//see code upd

I need to make the pipette tool which will take color from my canvas. How may I make it?


Code upd:

private static class DrawView extends View 
{
        ...
        public DrawView(Context context) {
            super(context);
            setFocusable(true);

            mBitmap = Bitmap.createBitmap(640, 860, Bitmap.Config.ARGB_8888);
            mCanvas = new Canvas(mBitmap);
            mPath = new Path();
            mBitmapPaint = new Paint(Paint.DITHER_FLAG);

            this.setDrawingCacheEnabled(true);
        }

        @Override
        protected void onDraw(Canvas canvas) {
            canvas.drawColor(0xFFAAAAAA);
            canvas.drawBitmap(mBitmap, 0, 0, mBitmapPaint);
            canvas.drawPath(mPath, mPaint);
        }
        private void touch_up()
        {
            if(!drBool) //is true when I click pipette button
            {
                ...
                mCanvas.drawPath(mPath, mPaint); // lines draw
                mPath.reset();
            }else{
                this.buildDrawingCache();
                cBitmap = this.getDrawingCache(true);
                if(cBitmap != null)
                {
                    int clr = cBitmap.getPixel((int)x, (int)y);
                    Log.v("pixel", Integer.toHexString(clr));
                    mPaint.setColor(clr);
                }else{
                    Log.v("pixel", "null");
                }
            }
            drBool = false;
        }
    }

I see only "pixel"-"ffaaaaaa", or if I use mCanvas.drawColor(Color.GRAY) "pixel"-"ff888888"

Loktar
  • 34,764
  • 7
  • 90
  • 104
Leo
  • 3,003
  • 5
  • 38
  • 61

2 Answers2

14

A canvas is nothing more than a container which holds drawing calls to manipulate a bitmap. So there is no concept of "taking colour from a canvas".

Instead, you should examine the pixels of the bitmap of the view, which you can get with getDrawingCache.

In your views' constructor:

this.setDrawingCacheEnabled(true);

When you want the colour of a pixel:

this.buildDrawingCache();
this.getDrawingCache(true).getPixel(x,y);

This is very inefficient if you are calling it many times in which case, you might want to add a bitmap field and use getDrawingCache() to set it in ondraw().

private Bitmap bitmap;

...

onDraw()

  ...

  bitmap = this.getDrawingCache(true);

Then use bitmap.getPixel(x,y);

Simon
  • 14,407
  • 8
  • 46
  • 61
  • This code works correctly only for drawColor, but he doesn't see the colors created by drawPath – Leo Nov 25 '12 at 14:22
  • It must work! getPixel does exactly that. It gets the pixel at x,y directly from the bitmap (i.e. from the byte array which stores the bitmap) and is what you see on screen. When the drawPath method renders to the bitmap, it ultimately draws pixels so at this level (getPixel) there is no difference between any of the drawing calls. I suspect that the maths for x and y is probably wrong. – Simon Jan 22 '13 at 08:08
1

Above answer returns me blank bitmap. This is my solution

@Override
protected void onDraw(Canvas canvas) {
    ...
    bitmapUpdated = true;
}

And then for getting bitmap

public Bitmap getBitmapImage() {
    if (bitmapUpdated) {
        this.buildDrawingCache();
        bitmapImage = Bitmap.createBitmap(this.getDrawingCache());
        this.destroyDrawingCache();
    }
    return bitmapImage;
}

This works fine for me, without excessive overhead.

Perhaps better solution would be to override invalidate() and onDraw() so it uses your canvas, that is linked with your bitmap

Bitmap b = Bitmap.createBitmap(v.getWidth(), v.getHeight(), Bitmap.Config.ARGB_8888);
Canvas c = new Canvas(b);
v.draw(c);
return b;
Jonzi
  • 141
  • 1
  • 2
  • 13
  • This works fine! I tried to obtain a color from a bitmap I've drawn, and it does return the correct value, however, after applying a filter, it did not (well, it still returned the original color). Your solution does the job. – Danny E.K. van der Kolk Nov 16 '20 at 16:20