Hackathon #1: Composite Image

My company recently had a Hackathon day, where the IT dept. was split into teams and had one day to develop something amazing to present to a panel of judges.

Over the next couple of posts I’d like to just show some things that my team hacked together, as I found them quite interesting, if not amazingly applicable to a real-world app!

First up is a very quick hack I created to generate a composite image on the fly given several other images. Apologies that this is in vb.net and not C#, but I was forced to work within our legacy environment! Assumption: all images to composite are of the same dimensions

Here is a function to take an arraylist of image URLs, merge them, and return the byte array:

[vb]Public Function BuildMergedImage(ByVal imgsToMerge As ArrayList) As Byte()

‘build image array, loading each image from a stream into the image array
Dim imagesToMerge As ArrayList = New ArrayList
Dim webClient As System.Net.WebClient = New System.Net.WebClient()
Dim imgStream As Stream

For Each imgToMerge As String In imgsToMerge
imgStream = webClient.OpenRead(imgToMerge.ToString())
imagesToMerge.Add(System.Drawing.Image.FromStream(imgStream))
Next

‘get composite dimensions
Dim height As Integer = CType(imagesToMerge(0), System.Drawing.Image).Height
Dim width As Integer = (CType(imagesToMerge(0), System.Drawing.Image).Width * imagesToMerge.Count())

‘init composite image
Dim mergedImage As Bitmap = New Bitmap(width, height)
Dim g As Graphics = Graphics.FromImage(mergedImage)

‘create composite image
For i As Integer = 0 To (imagesToMerge.Count() – 1)
g.DrawImage(imagesToMerge(i), (CType(imagesToMerge(i), System.Drawing.Image).Width * i), 0)
Next

‘save merged image to mem stream
Dim imgMemStream As New System.IO.MemoryStream
mergedImage.Save(imgMemStream, ImageFormat.Jpeg)

‘convert stream to byte array
Dim bytes(imgMemStream.Length() – 1) As Byte
imgMemStream.Position = 0
imgMemStream.Read(bytes, 0, bytes.Length)
imgMemStream.Close()

‘return byte array
Return bytes
End Function[/vb]

Then to use this method, build up a string arraylist of image urls, pass it to a new function, and output the returned byte array to the response buffer (I used mine in the Page Load, hence the obligatory postback check):

[vb]If Not IsPostBack Then
Response.Buffer = True
Response.ContentType = "image/jpeg" ‘match to the imageformat in the composite image function
Response.BinaryWrite(BuildMergedImage(taggedImg))
End If[/vb]

You’ll need these at the top of your file to get it working though. I realise the “option strict off” is a horrid hack, but it was for a hackathon..

[vb]Option Strict Off

Imports System.IO
Imports System.Drawing.Imaging[/vb]

Bit random, I know, but I found it quite interesting. Have a go with something similar to (but hopefully cleaner than) this:

[vb]Dim imageArrayList As ArrayList = new ArrayList

For Each imageUrl As String In Request.QueryString("i").Split(CChar("-"))
If Not IsNothing(imageUrl) AndAlso Not String.IsNullOrEmpty(imageUrl) Then
imageArrayList.Add(imageUrl)
End If
Next

If Not IsPostBack Then
Response.Buffer = True
Response.ContentType = "image/jpeg" ‘match to the imageformat in the composite image function
Response.BinaryWrite(BuildMergedImage(imageArrayList))
End If[/vb]

Example usage (although in this example it’s not pulling the correct dimensions through, which is odd):

[vb]http://localhost/combinedimages.aspx?i=http://www.docdatastorage.co.uk/Live/flyfiftythree/ProductImages/savage_white_1_medium.jpg-http://www.docdatastorage.co.uk/Live/flyfiftythree/ProductImages/checkit_green_1_medium.jpg-http://www.docdatastorage.co.uk/Live/flyfiftythree/ProductImages/telemaniacs_navy_1_medium.jpg[/vb]