36

I have a requirement wherein I need to merge two different png/jpeg images resulting into a single image using C#.Net. There will be a particular location defined on the source image wherein I need to insert another image. Can anybody suggest some links ?

Anil C
  • 1,045
  • 3
  • 16
  • 38
  • 1
    I was looking for the same things and found this. http://stackoverflow.com/questions/465172/merging-two-images-in-c-net/465195#465195 – ddaaggeett Mar 25 '15 at 21:20

5 Answers5

45

This method merge two images one in the top of the other you can modify the code to meet for your needs:

    public static Bitmap MergeTwoImages(Image firstImage, Image secondImage)
    {
        if (firstImage == null)
        {
            throw new ArgumentNullException("firstImage");
        }

        if (secondImage == null)
        {
            throw new ArgumentNullException("secondImage");
        }

        int outputImageWidth = firstImage.Width > secondImage.Width ? firstImage.Width : secondImage.Width;

        int outputImageHeight = firstImage.Height + secondImage.Height + 1;

        Bitmap outputImage = new Bitmap(outputImageWidth, outputImageHeight, System.Drawing.Imaging.PixelFormat.Format32bppArgb);

        using (Graphics graphics = Graphics.FromImage(outputImage))
        {
            graphics.DrawImage(firstImage, new Rectangle(new Point(), firstImage.Size),
                new Rectangle(new Point(), firstImage.Size), GraphicsUnit.Pixel);
            graphics.DrawImage(secondImage, new Rectangle(new Point(0, firstImage.Height + 1), secondImage.Size),
                new Rectangle(new Point(), secondImage.Size), GraphicsUnit.Pixel);
        }

        return outputImage;
    }
Jalal Said
  • 15,906
  • 7
  • 45
  • 68
  • why Format32bppArgb? – Toolkit Feb 15 '17 at 11:08
  • @Toolkit: As far as I remember when you use the constructor overload with two arguments only `(width, height)`it will create a`24bit` version which is `Format24bppRgb` . and so will lose the alpha channel info of the original images if it includes one, hence the `Format32bppArgb`. Though, I believe it would be more convenient if you get the appropriate format from the original images instead of the inline `Format32bppArgb` thing... – Jalal Said Feb 21 '17 at 14:33
  • It works nice, but i think there is no need to add 1 pixel in height between two images – Milad Dastan Zand Jul 12 '19 at 08:21
17

After all this, I found a new easier method try this ..

It can join multiple photos together:

public static System.Drawing.Bitmap CombineBitmap(string[] files)
{
    //read all images into memory
    List<System.Drawing.Bitmap> images = new List<System.Drawing.Bitmap>();
    System.Drawing.Bitmap finalImage = null;

    try
    {
        int width = 0;
        int height = 0;

        foreach (string image in files)
        {
            //create a Bitmap from the file and add it to the list
            System.Drawing.Bitmap bitmap = new System.Drawing.Bitmap(image);

            //update the size of the final bitmap
            width += bitmap.Width;
            height = bitmap.Height > height ? bitmap.Height : height;

            images.Add(bitmap);
        }

        //create a bitmap to hold the combined image
        finalImage = new System.Drawing.Bitmap(width, height);

        //get a graphics object from the image so we can draw on it
        using (System.Drawing.Graphics g = System.Drawing.Graphics.FromImage(finalImage))
        {
            //set background color
            g.Clear(System.Drawing.Color.Black);

            //go through each image and draw it on the final image
            int offset = 0;
            foreach (System.Drawing.Bitmap image in images)
            {
                g.DrawImage(image,
                  new System.Drawing.Rectangle(offset, 0, image.Width, image.Height));
                offset += image.Width;
            }
        }

        return finalImage;
    }
    catch (Exception)
    {
        if (finalImage != null)
            finalImage.Dispose();
        //throw ex;
        throw;
    }
    finally
    {
        //clean up memory
        foreach (System.Drawing.Bitmap image in images)
        {
            image.Dispose();
        }
    }
}
TheSoftwareJedi
  • 34,421
  • 21
  • 109
  • 151
Anant Dabhi
  • 10,864
  • 3
  • 31
  • 49
  • 4
    Awesome, thanks for the code - but never "throw ex" - always just "throw". You're resetting the stack and making it impossible to debug otherwise! – TheSoftwareJedi Nov 25 '15 at 03:52
  • This code generates me a final image with the double of the width than the original (height remains ok) – Pablo Costa Apr 10 '17 at 18:29
  • @PabloCosta Yes, If you see above code `height = bitmap.Height > height ? bitmap.Height : height;` height of newly created image will be maximum of all images. – Anant Dabhi Apr 13 '17 at 06:05
6
        String jpg1 = @"c:\images.jpeg";
        String jpg2 = @"c:\images2.jpeg";
        String jpg3 = @"c:\image3.jpg";

        Image img1 = Image.FromFile(jpg1);
        Image img2 = Image.FromFile(jpg2);

        int width = img1.Width + img2.Width;
        int height = Math.Max(img1.Height, img2.Height);

        Bitmap img3 = new Bitmap(width, height);
        Graphics g = Graphics.FromImage(img3);

        g.Clear(Color.Black);
        g.DrawImage(img1, new Point(0, 0));
        g.DrawImage(img2, new Point(img1.Width, 0));

        g.Dispose();
        img1.Dispose();
        img2.Dispose();

        img3.Save(jpg3, System.Drawing.Imaging.ImageFormat.Jpeg);
        img3.Dispose();
Deepak Sharma
  • 223
  • 2
  • 3
  • I tried something similar following your method. I set a larger width and when I draw the images, a gray region will be displayed. How can I change that region into white or other solid color of my preference? – Pablo Gonzalez Jan 05 '18 at 06:04
6

Disclaimer: I work at Atalasoft

Our DotImage Photo SDK (which is free) can do this.

To open an image

 AtalaImage botImage = new AtalaImage("bottomImage.png");
 AtalaImage topImage = new AtalaImage("topImage.png");

To overlay one on top of another

 Point pos = new Point(0,0); // or whatever you need
 OverlayCommand cmd = new OverlayCommand(topImage, pos);
 ImageResults res = cmd.Apply(botImage);

If you need the resulting image to be a different size, look at the CanvasCommand. You could also create an AtalaImage of the size you need, then overlay each image onto it.

To save

 botImage.Save("newImage.png", new PngEncoder(), null);
Lou Franco
  • 87,846
  • 14
  • 132
  • 192
1
private void Merge _Click(object sender, EventArgs e)
{
}
DirectoryInfo directory=new DirectoryInfo("D:\\Images");
if(directory!=null)
{
    FileInfo[]files = directory.GetFiles();
    MergeImages(Image);
}

private void MergeImages(FileInfo[] Image)
{
    //change the location to store the final image.
    string FImage= @"D:\\Images\\FImage.jpg";
    List imageHeights = new List();
    int nIndex = 0;
    int width = 0;
    foreach (FileInfo file in files)
    {
        Image img = Image.FromFile(file.FullName);
        imageHeights.Add(img.Height);
        width += img.Width;
        img.Dispose();
    }
    imageHeights.Sort();
    int height = imageHeights[imageHeights.Count - 1];
    Bitmap NewImg = new Bitmap(width, height);
    Graphics Gr= Graphics.FromImage(NewImg);
    Gr.Clear(SystemColors.AppWorkspace);
    foreach (FileInfo file in files)
    {
        Image img = Image.FromFile(file.FullName);
        if (nIndex == 0)
        {
            Gr.DrawImage(img, new Point(0, 0));
            nIndex++;
            width = img.Width;
        }
        else
        {
            Gr.DrawImage(img, new Point(width, 0));
            width += img.Width;
        }
            img.Dispose();
    }
    Gr.Dispose();
    NewImg .Save(FImage, System.Drawing.Imaging.ImageFormat.Jpeg);
    NewImg .Dispose();
    imageLocation.Image = Image.FromFile(FImage);
}
Code
  • 679
  • 5
  • 9