0

I am using the FingerPaintCanvasView from this xamarin sample.

I am working with 2 layers. The first layer is an ImageView i want to draw on. The second layer is the PaintCanvasView to draw.

  <RelativeLayout
    android:layout_height="match_parent"
    android:layout_width="match_parent">
    <ImageView
      android:id="@+id/markImageImageView"
      android:layout_height="wrap_content"
      android:layout_width="wrap_content"/>
    <fingerpaint.FingerPaintCanvasView
      android:id="@+id/canvasMarkMeta"
      android:layout_width="wrap_content"
      android:layout_height="wrap_content" />
  </RelativeLayout>

The canvas has a transparent background and the layout params of both views are set programmatically. This way the marking works fine.

enter image description here

Now the question is, how can I merge this imageview with the marking canvas with as little as possible quality loss to an singel file (bitmap or imageFile in FileSystem).

Let me explain why I mentiond the quality loss: For example the image in the background has a size of 1920x1080 from the devices camera. The display only has 1280x800 pixel. Since I can't fit the image in the display, I need to display a scaled down version AND the marking happens on this scaled down version.

EDIT:

@Joe LV:

This is your demo without any changes deployed on my devices:

Lenovo Yoga 3, Android 6.0.1 enter image description here

Huawei Honor 8, Android 7.0 enter image description here

I will try an Android 8 Emulator soon.

Pixel 2XL, Android 8.1 enter image description here

So this method does not Work for API <= 24 :-( (API 25 and 26 not tested)

markImageImageView just holds an image that I load from the device storage (can be any image) canvasMarkMeta is the FingerPaintCanvas from the linked template which the holds the drawn lines.

Aiko West
  • 791
  • 1
  • 10
  • 30
  • You need use `PorterDuff.Mode` to merge the two pictures. Can you show the codes about how did you handle the two pictures? You can read [this](https://stackoverflow.com/questions/8280027/what-does-porterduff-mode-mean-in-android-graphics-what-does-it-do), if this is what you want, I can provide a demo about how to merge two picture to a picture as answer for you. – Robbit May 04 '18 at 12:02
  • I would be very glad to see some demo code how to merge two picture into one. As soon as i am back at my solution i will show the code which handles my two pictures (could be monday 07.05.18) – Aiko West May 04 '18 at 12:18

1 Answers1

2

Below is the code, I have add comments in it:

   public class MainActivity : Activity
    {
        private Rect mSrcRect, mDestRect;
        protected override void OnCreate(Bundle savedInstanceState)
        {
            base.OnCreate(savedInstanceState);

            // Set our view from the "main" layout resource
            SetContentView(Resource.Layout.Main);
            //your background picture ---markImageImageView
            Bitmap background = BitmapFactory.DecodeResource(Resources, Resource.Drawable.pause);
            //your foreground picture ---FingerPaintCanvasView
            Bitmap foreground = BitmapFactory.DecodeResource(Resources, Resource.Drawable.play);

            Paint p = new Paint();
            p.SetXfermode(new PorterDuffXfermode(PorterDuff.Mode.SrcOver));

            //use background to create a canvas
            Bitmap workingBitmap = Bitmap.CreateBitmap(background);
            Bitmap mutableBitmap = workingBitmap.Copy(Bitmap.Config.Argb8888, true);
            Canvas c = new Canvas(mutableBitmap);

            int mBWith = background.Width;
            int mBHeight = background.Height;

            int mFWith = foreground.Width;
            int mFHeight = foreground.Height;
            mSrcRect = new Rect(0, 0, mBWith, mBHeight);
            mDestRect = new Rect(0, 0, mFWith, mFHeight);

            //draw foreground on the backaground, then they will be single bitmap
            c.DrawBitmap(foreground, mSrcRect, mDestRect, p);
            ImageView imageView = FindViewById<ImageView>(Resource.Id.iv);
            imageView.SetImageBitmap(mutableBitmap);
        }
    }

And I have provide the demo on github.

Update:

Change Bitmap.Config.Argb4444 to Bitmap.Config.Argb8888.

Community
  • 1
  • 1
Robbit
  • 4,300
  • 1
  • 13
  • 29
  • 1
    Thanks for the answer Joe. If I run your demo on my device, I am just seeing the pause button displayed, not a merged Image of the play & pause button. The same behavior, when apply this code in my solution ... – Aiko West May 07 '18 at 06:57
  • 1
    Hi, on my device(Google pixel 8.1), I can see the play button is over the pause button. If it is possible, could you please provide a demo? Or can you provide the pictures, `markImageImageView` and `canvasMarkMeta`, you can save them as file, and attach them into your question. – Robbit May 07 '18 at 07:08