Skip to content

Instantly share code, notes, and snippets.

@shinyzhu
Created August 11, 2010 08:49
Show Gist options
  • Save shinyzhu/518701 to your computer and use it in GitHub Desktop.
Save shinyzhu/518701 to your computer and use it in GitHub Desktop.
using System;
using System.Collections.Generic;
using System.Drawing;
using System.Linq;
namespace SocialKit.ImageUtil
{
/// <summary>
/// Provides methods for combine images into a single one.
/// </summary>
public class ImageCombiner
{
/// <summary>
/// Combine some images into a single one.
/// </summary>
/// <param name="columnMaxCount">Max images in a row.</param>
/// <param name="images">Images to combine.</param>
/// <returns></returns>
public static Image Combine(int rowImagesMaxCount, params Image[] images)
{
if (images == null || images.Count() == 0)
return null;
if (rowImagesMaxCount < 1 || rowImagesMaxCount > images.Count())
rowImagesMaxCount = images.Count();
Image combinedImage = null;
try
{
//compute the size of combined image
var groupedImages = GroupImages(images, rowImagesMaxCount);
var lastRowCount = groupedImages.Min(g => g.Value.Count());
if (lastRowCount < rowImagesMaxCount)
{
//last row
var toAttachCount = rowImagesMaxCount - lastRowCount;
groupedImages.Last().Value.AddRange(images.Take(toAttachCount));
}
var width = groupedImages.Select(g => g.Value.Sum(img => img.Width)).Max();
var height = groupedImages.Select(g => g.Value.Max(img => img.Height)).Sum();
combinedImage = new Bitmap(width, height);
using (var g = Graphics.FromImage(combinedImage))
{
g.Clear(Color.White);
int xOffset = 0;
int yOffset = 0;
foreach (var rowImages in groupedImages)
{
var rowHeight = rowImages.Value.Max(i => i.Height);
foreach (var img in rowImages.Value)
{
g.DrawImage(img, new Rectangle(xOffset, yOffset, img.Width, img.Height));
xOffset += img.Width;
}
xOffset = 0;
yOffset += rowHeight;
}
}
return combinedImage;
}
catch (Exception)
{
if (combinedImage != null)
combinedImage.Dispose();
throw;
}
finally
{
foreach (var img in images)
{
img.Dispose();
}
}
}
static IDictionary<int, List<Image>> GroupImages(Image[] images, int rowMax)
{
var grouped = new Dictionary<int, List<Image>>();
if (images.Count() <= rowMax)
{
grouped.Add(0, images.ToList());
}
else
{
var groupCount = Math.Ceiling(((double)images.Count() / rowMax));
for (int i = 0; i < groupCount; i++)
{
grouped.Add(i, images.Skip(i * rowMax).Take(rowMax).ToList());
}
}
return grouped;
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment