'bitmap merge different amount of images together every time c#

When i run the program, i get a different amount of images(from 20 all the way up to 2000) and i would like to merge all of these images into one image which would preferably be a square. This is the code i have for getting the file images(the images are in URL format)

int ximg = 1;
int totalImgs = richTextBox1.Lines.Count();
while (ximg < totalImgs)
{
    System.Net.WebRequest request = System.Net.WebRequest.Create(richTextBox1.Lines[ximg]);
    System.Net.WebResponse response = request.GetResponse();
    System.IO.Stream responseStream =
    response.GetResponseStream();
    Bitmap image = new Bitmap(responseStream);

    List<Image> fileList = new List<Image>();
    fileList.Add(image);
    ximg++;
}

Also every single image has a title in a different richtextbox which i would like to know if it is possible to add a title under the image (richtextbox1.lines[1] (image) = richtextbox2.lines[1] (title)). Is it possible to add a picture as a background picture when merging(to the square image I want to generate)? Is it possible to add a border on every single image picture and merge them with the border? How can the code calculate when its time to change line and start adding images in the next row?

I've tried this code, but it works only if you know the amount of images you want to merge.

Bitmap bitmap = new Bitmap(image1.Width + image2.Width, Math.Max(image1.Height, image2.Height));
using (Graphics g = Graphics.FromImage(bitmap))
{
    g.DrawImage(image1, 0, 0);
    g.DrawImage(image2, image1.Width, 0);
}
bitmap.Save("merged.bmp");

I would do it with photoshop but when there are 2000 images to merge together, I just do not have the time.

Is there any way to accomplish such task? Any references would be appreciated!

I have mentioned it above :) !



Solution 1:[1]

This solution will create a mosaic of the images from left to right, top to bottom. It does not do anything to maximize the available space. It also assumes that you have a max width and height for the finished image, since it's not realistic to support an arbitrary size.

// where we store the finished mosaic
var mosaic = new Bitmap(maxWidth, maxHeight);

// track the location where we are drawing each image
var imageCorner = new Point(0,0);

// track the height of the current row
var currentRowHeight = 0;

// track the width and height of the mosaic as it grows.
var mosaicWidth = 0;
var mosaicHeight = 0;

using (var g = Graphics.FromImage(bitmap))
{
    var borderPen = new Pen(Brushes.Black) { Width = 2 };
    var labelFont = new Font("Arial", 10);
    var labelBrush = new SolidBrush(Color.Black);

    foreach (var image in imageList)
    {
        if (imageCorner.X + image.Width > maxWidth)
        {
            // if adding the image to the current row would make it too wide,
            // move to the next row by resetting X to zero and adding the 
            // height of the tallest image to Y

            imageCorner.X = 0;
            imageCorner.Y += currentRowHeight;
   
            // since this is a new row, it's current height is zero
            currentRowHeight = 0;
        }

        // if adding this image would put us past the 
        // height of the image, then we're out of room.
        if (imageCorner.Y + image.Height > maxHeight)
        {
             // this skips images if there's no room for them in
             // the mosaic, you may want to do something different
             Trace.WriteLine($"Image is {image.Height} pixels tall, but only {maxHeight - mosaicHeight} pixels available.");
             continue;
        }

        // draw the image
        g.DrawImage(image, imageCorner);

        // draw the border 
        g.DrawRectangle(borderPen, 
                        imageCorner.X, imageCorner.Y, 
                        image.Width, image.Height) 

        // draw the label
        g.DrawText("Image Label", labelBrush, imageCorner.X, imageCorner.Y)

        // now that we've drawn the image, we need to shift to the right
        imageCorner.X += image.Width;
        
        // row height is the height of the tallest image so far in this row
        currentRowHeight = Math.Max(image.Height, currentRowHeight);

        // track the total height of the mosaic
        mosaicHeight = imageCorner.Y + currentRowHeight;

        // mosaic width is just the widest row in the mosaic
        mosaicWidth = Math.Max(imageCorner.X, widthOfWidestRow);
    }
}

// trim off the parts of the mosaic we didn't fill
mosaic = mosaic.Clone(new Rectangle(0, 0, mosaicWidth, mosaicHeight);

mosaic.Save("merged.bmp");

If you wanted to minimize wasted space, you could sort your list of images in different ways, or calculate ahead of time what a good width and height for the mosaic would be.

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1