A mapping project I've recently been working on needed to have coloured, numbered pins to correspond to the numbered items shown in the list below the map, e.g.
I wanted the images to be created dynamically, as the numbers could reach into the hundreds, and I didn't fancy spending several days with Photoshop. I started with empty pin images (red, green, blue and black).
To improve performance, I decided to write the image to disk once I'd generated it, which I could just return in future calls. I also wanted to cache the image path, so I wouldn't have to access the disk to see if the image had been created already.
I added an ImageController class, and an Index action that took the colour as a string and the number as an integer:
public ActionResult Index(string colour, int number)
This would correspond to the url http://domain.com/image/green/23.png. I put the png extension so everything would know it was a png file. So after checking that an existing image for the colour and number didn't exist, one needed to be generated. I've not used the graphics classes in .NET before, so I was super excited about it. The first step was to load the correctly coloured image:using (var stream = new FileStream(imageRoot + colour + ".png") {
image = Image.FromStream(stream);
}
Now to draw the number on top of the image:var g = Graphics.FromImage(image);
g.TextRenderingHint = TextRenderingHint.AntiAlias;
var stringFormat = new StringFormat
{
Alignment = StringAlignment.Center,
LineAlignment = StringAlignment.Center
};
g.DrawString(
number.ToString(),
SystemFonts.DefaultFont,
Brushes.Black,
new RectangleF(0f, 0f, image.Width, 33f),
stringFormat);
This is just setting up the text style, defining a rectangle in the right place, then drawing the string into the rectangle. (I still can't help thinking of Speedos.) Then it was a simple case of saving the image for next time and returning it as aFilePathResult
:image.Save(imagePath, ImageFormat.Png);
return File(imageUrl, "image/png");
Sample Code :
Imports System.Web Imports System.Web.Services Imports System.IO Imports System.Drawing.Text Imports System.Drawing Imports SHAPI.SHSafeNull Public Class NumeredMarker Implements System.Web.IHttpHandler Sub ProcessRequest(ByVal context As HttpContext) Implements IHttpHandler.ProcessRequest Try Dim tmpImg As System.Drawing.Image Dim color As String = GetString(context.Request("color")) Dim bgimagepath As String = "" Select Case Color.ToUpper Case "B" bgimagepath = context.Server.MapPath("~/MarkerImages/BlueMarker.png") Case "G" bgimagepath = context.Server.MapPath("~/MarkerImages/GreenMarker.png") End Select Dim stream As New FileStream(bgimagepath, FileMode.Open, FileAccess.Read, FileShare.ReadWrite) tmpImg = Image.FromStream(stream) stream.Dispose() stream.Close() Dim number As Long = GetString(context.Request("No")) Dim g = Graphics.FromImage(tmpImg) Dim stringFormat = New StringFormat() With {.Alignment = StringAlignment.Center, .LineAlignment = StringAlignment.Center} g.DrawString(number.ToString(), New Font("Times New Roman", 9, FontStyle.Bold, GraphicsUnit.Point), Brushes.White, New RectangleF(0.0F, 0.0F, tmpImg.Width, 23.0F), stringFormat) context.Response.ContentType = "image/png" Dim ms As New MemoryStream() tmpImg.Save(ms, Imaging.ImageFormat.Png) context.Response.OutputStream.Write(ms.ToArray(), 0, CInt(ms.Length)) Catch ex As Exception End Try End Sub ReadOnly Property IsReusable() As Boolean Implements IHttpHandler.IsReusable Get Return False End Get End Property End Class
No comments:
Post a Comment