How to merge multiple images into one with C#

Due to a requirement we needed to layer multiple images into one image. This needed to be faster and efficient plus we didn’t want to use any third party software as that would increase maintenance. Through some fun research and testing I found a neat and effective method to get the outcome required by only using C#.NET 4.6.

So the simple result was to use the C# class ‘Graphics’ to collect the images as Bitmaps and layer them, then produce a single resulting Bitmap.

As you can see from below, we first create the instance of the end Bitmap by create a new type with the width and height of the resulting image passed in. Using that Bitmap we create an instance of the Graphics, which we use in our loop of each image. For each of the images, they are added to the graphic with the starting X/Y co-ordinates of 0.

This solution solves the requirement I had as they all needed to be layered from the starting point of the top left corner, but you could also get imaginative with the settings to place the layers in different places, or even with the Bitmaps width you could create a full length banner.

// merge images
var bitmap = new Bitmap(width, height);
using (var g = Graphics.FromImage(bitmap)) {
foreach (var image in enumerable)     {      
g.DrawImage(image, 0, 0);
    }
}

This is of course handy and simple, so I thought to share and help I would create a full class to handle the processing. With the class below you do not need to create an instance as it is static, so that it can be used as a tool like it is.

You can find the full code on my Github at https://github.com/PureRandom/CSharpImageMerger

The aim of this class which can be expanded, is to layer an array of images into one. You can do this by passing an array of links, of bitmaps or a single folder directory.

When you pass the array of links, you also have the option of providing proxy settings depending what your security is like. It then uses an inside method to loop each link to attempt to download it and return them in a bitmap list.

private static List ConvertUrlsToBitmaps(List imageUrls, WebProxy proxy = null) {
    List bitmapList = new List();
    // Loop URLs
    foreach (string imgUrl in imageUrls)
    {
      try
      {
        WebClient wc = new WebClient();
        // If proxy setting then set
        if (proxy != null)
        wc.Proxy = proxy;
        // Download image
        byte[] bytes = wc.DownloadData(imgUrl);
        MemoryStream ms = new MemoryStream(bytes);
        Image img = Image.FromStream(ms);
        bitmapList.Add((Bitmap)img);
      }
      catch (Exception ex)
      {
        Console.Write(ex.Message);
      }
      }
    return bitmapList;
}

When you pass the array of bitmaps it is the same as the above, but it doesn’t have to download anything.

Finally the file system method can be used by passing the folder directory you wish it to search, then the image extension type. So if you was looking to merge all png’s in the directory ‘src/images/png’, then that is what you pass.

private static List ConvertUrlsToBitmaps(string folderPath, ImageFormat imageFormat)
{
    List bitmapList = new List();
    List imagesFromFolder = Directory.GetFiles(folderPath, "*." + imageFormat, SearchOption.AllDirectories).ToList();
    // Loop Files
    foreach (string imgPath in imagesFromFolder)
    {
      try
      {
        var bmp = (Bitmap) Image.FromFile(imgPath);
        bitmapList.Add(bmp);
      }
      catch (Exception ex)
    {
      Console.Write(ex.Message);
      }
      }
    return bitmapList;
}

With all of these it then uses the common method to loop each item in the array of bitmaps for find the biggest width and height, so the images don’t over or under run the results size. As explained above, each bitmap is looped through to merge the images to the top left of the result Bitmap to create the final image.

private static Bitmap Merge(IEnumerable images)
{
  var enumerable = images as IList ?? images.ToList();
  var width = 0;
  var height = 0;
  // Get max width and height of the image
  foreach (var image in enumerable)
  {
    width = image.Width > width ? image.Width : width;
    height = image.Height > height ? image.Height : height;
  }
  // merge images
  var bitmap = new Bitmap(width, height);
  using (var g = Graphics.FromImage(bitmap))
  {
    foreach (var image in enumerable) {
      g.DrawImage(image, 0, 0);
    }
  }
  return bitmap;
}

Feel free to comment, expand and share this code to help others.

https://github.com/PureRandom/CSharpImageMerger

Published by Chris Pateman - PR Coder

A Digital Technical Lead, constantly learning and sharing the knowledge journey.

3 thoughts on “How to merge multiple images into one with C#

  1. It does not work for me. I have multiple images which needs to be merged one by one vertically, and also it should be resize as per the larger height and width of one of the images. Please help

    Like

Leave a message please

This site uses Akismet to reduce spam. Learn how your comment data is processed.