1

I successfully get out the two images in my resources folder in my project like this.

string BackGroundImage = "background_image";
string ObjectImage = "object_image";

var TheBackGroundImage = BitmapFactory.DecodeResource(Resources, Resources.GetIdentifier(BackGroundImage, "drawable", PackageName));
var TheObjectImage = BitmapFactory.DecodeResource(Resources, Resources.GetIdentifier(ObjectImage, "mipmap", PackageName));

What i have done after is very the tricky part comes in and I do not know how to quite get it right. What i try to do is create a new Bitmap where the BackgroundImage is the base. Then i create a canvas with my second image (ObjectImage) that is the image that will be on top of the BackgroundImage and try to merge it all together.

Bitmap Result = Bitmap.CreateBitmap(TheBackGroundImage.Width, TheBackGroundImage.Height, TheBackGroundImage.GetConfig());
Canvas canvas = new Canvas(Result);
canvas.DrawBitmap(ObjectImage, new Matrix(), null);
canvas.DrawBitmap(ObjectImage, 79, 79, null);

This does not work as anticipated, is canvas the way to go or is there somethinig else i should look at?

If we look at my iOS solution then i do it like this:

            UIImage PhoneImage = UIImage.FromFile(PhonePath);
            UIImage IconImage = UIImage.FromFile(IconPath);
            UIImage ResultImage;

            CGSize PhoneSize = PhoneImage.Size;
            CGSize IconSize = IconImage.Size;

            UIGraphics.BeginImageContextWithOptions(IconSize, false, IconImage.CurrentScale); //UIGraphics.BeginImageContextWithOptions(IconSize, false, IconImage.CurrentScale);
            UIGraphics.BeginImageContext(PhoneSize);

            CGRect Frame = (new CoreGraphics.CGRect(25, 29.5, 79, 79));
            UIBezierPath RoundImageCorner = new UIBezierPath();
            RoundImageCorner = UIBezierPath.FromRoundedRect(Frame, cornerRadius: 15);

            PhoneImage.Draw(PhoneImage.AccessibilityActivationPoint);
            RoundImageCorner.AddClip();
            IconImage.Draw(Frame);

            UIColor.LightGray.SetStroke();
            RoundImageCorner.LineWidth = 2;
            RoundImageCorner.Stroke();

            ResultImage = UIGraphics.GetImageFromCurrentImageContext();
            UIGraphics.EndImageContext();

            var documentsDirectory = Environment.GetFolderPath(Environment.SpecialFolder.Personal);
            string jpgFilename = System.IO.Path.Combine(documentsDirectory, "app.png");

            NSData image = ResultImage.AsPNG();

And it works beautifully with a border around my second image as well.

How can i adjust my code to successfully merge two images together and position the second image preferably like a CGRect?

Carlos Rodrigez
  • 1,347
  • 1
  • 15
  • 32
  • `merge two images` What type of "merging" are you talking about; an alpha overlay? a RGBa combine, etc.. , .... Might be easier to understand what you are expecting by showing the iOS code you are using and possible a picture or two. – SushiHangover Mar 20 '18 at 19:36
  • @SushiHangover Updated the question with the full iOS code. With merging i mean putting two transparent pictures together and making one image together. – Carlos Rodrigez Mar 20 '18 at 19:55

1 Answers1

2

Try this:

public Bitmap mergeBitmap(Bitmap backBitmap, Bitmap frontBitmap)
{
    Bitmap bitmap = backBitmap.Copy(Bitmap.Config.Argb8888, true);
    Canvas canvas = new Canvas(bitmap);
    Rect baseRect = new Rect(0, 0, backBitmap.Width, backBitmap.Height);
    Rect frontRect = new Rect(0, 0, frontBitmap.Width, frontBitmap.Height);
    canvas.DrawBitmap(frontBitmap, frontRect, baseRect, null);
    return bitmap;
}

Update:

Here is the DrawBitmap method's introduce. I add annotations in the method.

    public Bitmap mergeBitmap(Bitmap backBitmap, Bitmap frontBitmap)
    {
        Bitmap bitmap = backBitmap.Copy(Bitmap.Config.Argb8888, true);
        Canvas canvas = new Canvas(bitmap);

        //this Rect will decide which part of your frontBitmap will be drawn,
        //(0,0,frontBitmap.Width, frontBitmap.Height) means that the whole of frontBitmap will be drawn,
        //(0,0,frontBitmap.Width/2, frontBitmap.Height/2) means that the half of frontBitmap will be drawn.
        Rect frontRect = new Rect(0, 0, frontBitmap.Width, frontBitmap.Height);

        //this Rect will decide where the frontBitmap will be drawn on the backBitmap,
        //(200, 200, 200+ frontBitmap.Width, 200+frontBitmap.Height) means that
        //the fontBitmap will drawn into the Rect which left is 200, top is 200, and its width and
        //height are your frontBitmap's width and height.
        //I suggest the baseRect's width and height should be your fontBitmap's width and height,
        //or, your fontBitmap will be stretched or shrunk.
        Rect baseRect = new Rect(200, 200, 200+ frontBitmap.Width, 200+frontBitmap.Height);

        canvas.DrawBitmap(frontBitmap, frontRect, baseRect, null);
        return bitmap;
    }
Robbit
  • 4,300
  • 1
  • 13
  • 29
  • Alright, so a Rect should then work the same way as a GCRect right? As an example `Rect frontRect = new Rect(0, 0, frontBitmap.Width, frontBitmap.Height);` would then be like this instead `new Rect( 25, 29.5, 79, 79);` – Carlos Rodrigez Mar 21 '18 at 08:31
  • @CarlosRodrigez, I am not familiar with Ios, if you want put frontBitmap on backBitmap, you can use [Canvas.drawBitmap](https://developer.android.com/reference/android/graphics/Canvas.html#drawBitmap(android.graphics.Bitmap, android.graphics.Rect, android.graphics.Rect, android.graphics.Paint)). And in this method, there is a paint parameter. You can use [setXfermode](https://developer.android.com/reference/android/graphics/Paint.html#setXfermode(android.graphics.Xfermode)) method to set [PorterDuffXfermode](https://developer.android.com/reference/android/graphics/PorterDuffXfermode.html) – Robbit Mar 21 '18 at 08:43
  • I find [this](https://stackoverflow.com/questions/23966272/android-mask-bitmap-on-canvas-gen-a-black-space?utm_medium=organic&utm_source=google_rich_qa&utm_campaign=google_rich_qa) for you. And [this](https://developer.android.com/reference/android/graphics/PorterDuff.Mode.html) is the different `PorterDuff.Mode`. – Robbit Mar 21 '18 at 08:44
  • @CarlosRodrigez, these link can't solve your problem? – Robbit Mar 21 '18 at 10:08
  • I am having trouble (thats not related to this question) saving the image locally and being able to see how it looks. – Carlos Rodrigez Mar 21 '18 at 10:16
  • I will save this for now, but i need to get back to it later today after i found out how to save the image and see it. I just created a new thread about just that – Carlos Rodrigez Mar 21 '18 at 11:53
  • If you don't root your phone, you can't see /data/data.... path. Why not load the file to your ImageView to check the picture? – Robbit Mar 21 '18 at 12:00
  • Ok i used ur answer now but the frontbitmap does not position itself correctly when i use same value as in the CGRect for ios – Carlos Rodrigez Mar 22 '18 at 08:47
  • Can you add a picture on Android and Ios? – Robbit Mar 22 '18 at 08:50
  • I cant see the frontimage. I only see the background image (backBitmap) when i run the code above – Carlos Rodrigez Mar 22 '18 at 15:36
  • Can you add an effect picture about Ios? So I can achieve the same thing on Android. Above code will put fontimage over the background image. – Robbit Mar 22 '18 at 15:38
  • https://imgur.com/a/X4Her Kinda like this. Backgroundimage is grey, frontimage is red – Carlos Rodrigez Mar 22 '18 at 15:42
  • Alright :) No worries. I will keep looking to see if i can get it to work too – Carlos Rodrigez Mar 22 '18 at 15:50
  • I did make progress :) It now works. I now look to add a border to the frontimage. Did a post with that here: https://stackoverflow.com/questions/49450063/how-to-add-border-to-a-rounded-bitmap-image-in-xamarin-android – Carlos Rodrigez Mar 23 '18 at 12:56