Android Paint PorterDuff.Mode.CLEAR

2019-03-19 19:58发布

问题:

I'm working on application which is drawing on Canvas similar to Finger Paint demo from Android SDK. My problem is when I'm using PorterDuff.Mode.CLEAR. When drawing and Canvas and if I try to erase something, it's working fine. But if I try to save my image as PNG file the strokes of eraser are coloured black, and I'm not sure why is this happening. Here is an example what I'm doing :

@Override
    protected void onDraw(Canvas canvas) {
        canvas.drawColor(Color.WHITE);
        canvas.drawBitmap(mBitmap, 0, 0, mBitmapPaint);

        canvas.drawPath(mPath, mPaint);
    }

Eraser :

case ERASE_MENU_ID:
            mPaint.setXfermode(new PorterDuffXfermode(
                                                    PorterDuff.Mode.CLEAR));
            return true;

And how I'm saving the image :

            Calendar currentDate = Calendar.getInstance();
            SimpleDateFormat formatter= new SimpleDateFormat("yyyyMMMddHmmss");
            String dateNow = formatter.format(currentDate.getTime());
            File dir = new File(mImagePath);
            if(!dir.exists())
                dir.mkdirs();

            File file = new File(mImagePath + "/" + dateNow +".png");

            FileOutputStream fos;
            try {
                fos = new FileOutputStream(file);
                mBitmap.compress(Bitmap.CompressFormat.PNG, 100, fos);
                fos.close();
                Toast.makeText(getApplicationContext(), "File saved at \n"+mImagePath + "/" + dateNow +".png", Toast.LENGTH_LONG).show();
            } catch (FileNotFoundException e) {
                Log.e("Panel", "FileNotFoundException", e);
            } 
            catch (IOException e) {
                Log.e("Panel", "IOEception", e);
            }
            return true;

And here is an example of images :

here is what my canvas looks like before saving :

and here is the image after saving it on sd card :

回答1:

The problem with the fingerpaint code is that what you see is not the same that is compressed into the png. Look at onDraw(). First you draw the screen white. Then you add the Bitmap. Because you used Porter Duff Clear the erased part of the bitmap contains actually transparent black pixels (value 0x00000000). But because you have the white background these black pixels show as white.

To fix this either change your save code to do the same thing as the draw code

 try {
                    fos = new FileOutputStream(file);
                    Bitmap saveBitmap = Bitmap.createBitmap(mBitmap);
                    Canvas c = new Canvas(saveBitmap);
                    c.drawColor(0xFFFFFFFF);
                    c.drawBitmap(mBitmap,0,0,null);
                    saveBitmap.compress(Bitmap.CompressFormat.PNG, 100, fos);
                    saveBitmap.recycle();
...

or don't use PortDuff.Clear:

    case ERASE_MENU_ID:
        mPaint.setColor(Color.WHITE);