We have a cool feature in our backend data hub we call Image Overlay. Basically given images of a vehicle we can do all sorts of transformations including overlaying text ("Buy this car!"), overlaying images ("GM Certified logo") scaling and matte-ing (shrinking the input image down to have a single color margin to draw text in) and support for various geometric primitives. Our implementation is one of the few in our industry and is probably far more complete, flexible, and better-er than the few competing implementations. Our backend uses some PERL stuff for this and I wondered if a .NET engine would be as fast or faster and how it would scale, given that the claim has been made that C# is 1:1 performance with C++ and despite my love of C# I found this claim questionable. So, supposing I have an input image which is assuredly not a car:

And a tiny screenshot of my most anticipated upcoming PS3 game, LAIR:

And I want to do a few operations in realtime in .NET:
- create a Matte
- scale the source image
- Add some text
- import the Dragon screenshot from LAIR
- Time the operation
Here is the source code for entering some parameters, which could obviously come from some other source:
<div>
<h3>Source Image:</h3>
<asp:HyperLink ID="_exampleLnk" runat="server" Target="_blank" NavigateUrl="~/sample.jpg">
View source image
</asp:HyperLink>
<br />
Matte and overlay some text:
<asp:TextBox ID="_overlayTxt" runat="server" Text="go MSFT!"></asp:TextBox>
<br />
Import Img X
<asp:TextBox runat="server" ID="_xTxt" Width="2em" Text="100"></asp:TextBox>
Import Img Y
<asp:TextBox runat="server" ID="_yTxt" Width="2em" Text="100"></asp:TextBox>
<asp:Button ID="_submitBtn" runat="server" Text="Lay it over" OnClick="_submitBtn_Click" />
<br />
<asp:Label ID="_resultTimeLbl" runat="server"></asp:Label>
<br />
<asp:Image ID="_resultImg" runat="server" />
</div>
... and the code behind....
protected void _submitBtn_Click(object sender, EventArgs e)
{
string getQuery = "Image.aspx?overlay={0}&x={1}&y={2}";
int x;
int y;
int.TryParse(_xTxt.Text, out x);
int.TryParse(_yTxt.Text, out y);
_resultImg.ImageUrl = string.Format(getQuery, _overlayTxt.Text, x, y);
}
... and the result...

So, on a Windows Server 2003 running ASP.Net 2.0, how much code does it take to generate this? Surprisingly little:
protected override void OnLoad(EventArgs e)
{
base.OnLoad(e);
bool high = true;
HighResTimer hpt = new HighResTimer();
hpt.Start();
System.Drawing.Imaging.ImageCodecInfo codecInfo;
System.Drawing.Imaging.EncoderParameters parms;
System.Drawing.Imaging.ImageCodecInfo[] infoz = System.Drawing.Imaging.ImageCodecInfo.GetImageEncoders();
codecInfo = infoz[1];
parms = new System.Drawing.Imaging.EncoderParameters(1);
parms.Param[0] = new System.Drawing.Imaging.EncoderParameter(System.Drawing.Imaging.Encoder.Quality, 100L);
string txt = Request["overlay"];
int x = int.Parse(Request["x"]);
int y = int.Parse(Request["y"]);
Response.ContentType = codecInfo.MimeType;
System.Drawing.Image newImage = new Bitmap(640, 480);
System.Drawing.Image srcImage = System.Drawing.Image.FromFile(Server.MapPath("~/sample.jpg"));
System.Drawing.Image lairImage = System.Drawing.Image.FromFile(Server.MapPath("~/lair.jpg"));
Graphics g = Graphics.FromImage(newImage);
//Interpolation mode, smoothing mode, CompositingQuality,PixellOffsetMode,etc.
if (high)
{
g.InterpolationMode = System.Drawing.Drawing2D.InterpolationMode.HighQualityBicubic;
g.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.HighQuality;
}
try
{
//Matte color
g.Clear(Color.LightGray);
//Overlay font
Font textFont = new Font("Verdana", 9.0f, FontStyle.Bold | FontStyle.Underline);
Brush fontBrush = Brushes.Black;
//Scales the image down to matte it
g.DrawImage(srcImage, new RectangleF(0, 0, 600, 440));
g.DrawImage(lairImage, new RectangleF(x, y, 150, 84));
g.DrawString(txt, textFont, fontBrush, new PointF(10, 441));
g.DrawString("Damon Certified used o-scope", textFont, Brushes.Red, new PointF(430, 370));
hpt.Stop();
g.DrawString("RenderTime=" + hpt.Duration.ToString("n4") + "seconds", textFont, fontBrush, new PointF(10, 455));
//Stream
newImage.Save(Response.OutputStream, codecInfo, parms);
}
finally
{
if (null != srcImage)
{
srcImage.Dispose();
}
if (null != lairImage)
{
lairImage.Dispose();
}
if (null != g)
{
g.Dispose();
}
if (null != parms) // Seems to want to save in BMP anyway with this code in
{
parms.Dispose();
}
}
}
And I'd say 6/100th of a second on my very slow server (its an Emachine's POS we confiscated from someone after a pr0n escapade) is pretty good performance. I have one bug in that it does not always save as a JPEG like I told it to but I'm sure a little research would clear that up. So there you have it, a simple bit of image watermarking code in C#.