Title: Combine images in rows and columns in C#
I just finished my latest book WPF 3d, Three-Dimensional Graphics with WPF and C# and I wanted to combine images showing samples from the book into a single image. You can use a program such as MS Paint to do this manually, but it's a lot of work. I wrote this example to make it easier to combine images in this way.
Enter the following values.
- The source directory that contains the images that you want to combine
- The output file name
- The number of columns you want to use
- A margin (pixels) to add space between the images
- The background color (between the images)
You can click on the background color box to select a color.
After you enter the values, click Go to combine the images. The program gives each image the same amount of room. Each image's position is as wide as the widest image and as tall as the tallest image.
The following code shows how the program makes the combined image.
private void btnGo_Click(object sender, EventArgs e)
{
Cursor = Cursors.WaitCursor;
// Get the picture files in the source directory.
List<string> files = new List<string>();
foreach (string filename in
Directory.GetFiles(txtSourceDir.Text))
{
int pos = filename.LastIndexOf('.');
string extension = filename.Substring(pos).ToLower();
if ((extension == ".bmp") ||
(extension == ".jpg") ||
(extension == ".jpeg") ||
(extension == ".png") ||
(extension == ".tif") ||
(extension == ".tiff") ||
(extension == ".gif"))
files.Add(filename);
}
int num_images = files.Count;
if (num_images == 0)
{
Cursor = Cursors.Default;
MessageBox.Show("Selected 0 files");
return;
}
// Load the images.
Bitmap[] images = new Bitmap[files.Count];
for (int i = 0; i < num_images; i++)
images[i] = new Bitmap(files[i]);
// Find the largest width and height.
int max_wid = 0;
int max_hgt = 0;
for (int i = 0; i < num_images; i++)
{
if (max_wid < images[i].Width) max_wid = images[i].Width;
if (max_hgt < images[i].Height) max_hgt = images[i].Height;
}
// Make the result bitmap.
int margin = int.Parse(txtMargin.Text);
int num_cols = int.Parse(txtNumCols.Text);
int num_rows = (int)Math.Ceiling(num_images / (float)num_cols);
int wid = max_wid * num_cols + margin * (num_cols - 1);
int hgt = max_hgt * num_rows + margin * (num_rows - 1);
Bitmap bm = new Bitmap(wid, hgt);
// Place the images on it.
using (Graphics gr = Graphics.FromImage(bm))
{
gr.Clear(picBackground.BackColor);
int x = 0;
int y = 0;
for (int i = 0; i < num_images; i++)
{
gr.DrawImage(images[i], x, y);
x += max_wid + margin;
if (x >= wid)
{
y += max_hgt + margin;
x = 0;
}
}
}
// Save the result.
SaveImage(bm, txtOutputFile.Text);
Cursor = Cursors.Default;
MessageBox.Show("Done");
}
The program first uses Directory.GetFiles to list the files in the source directory. It checks each file's extension and saves the names of the image files.
Next, the program loops through the image file names and loads each file into a bitmap. It then loops through the bitmaps to find the largest width and height.
The program then calculates the number of rows and columns it needs to display the images and creates a new bitmap large enough to hold all of the images. It creates a Graphics object associated with the bitmap, and then loops through the images again. This time it copies each image into the next row/column position in the new bitmap.
After it finishes copying the images the program saves the result by calling the SaveImage method described in the post Save images with an appropriate format depending on the file name's extension in C#.
Download the example to experiment with it and to see additional details.
|