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:
Here is the source code for entering some parameters, which could obviously come from some other source:
View source image
Matte and overlay some text:
Import Img X
Import Img Y
... 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 colorg.Clear(Color.LightGray);//Overlay fontFont textFont = new Font("Verdana", 9.0f, FontStyle.Bold | FontStyle.Underline);Brush fontBrush = Brushes.Black;//Scales the image down to matte itg.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));//StreamnewImage.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#.
Remember Me
a@href@title, strike
Powered by: newtelligence dasBlog 2.0.7226.0
Disclaimer The opinions expressed herein are my own personal opinions and do not represent my employer's view in any way.
© Copyright 2010, Damon Payne
E-mail