2005.11.28 07:55 PM

Generate Dynamic Text Images with ASP.NET

I got a comment from Sumit Gupta on an earlier Sparklines post (version 2.2, the one that added transparency) describing, as best I can tell, some difficulty with using my code to dynamically generate transparent images containing arbitrarily specified text:

I use your code to generate the Image on the fly . My application is simple. It consist of Textbox and a button, Once I write a Text in textbox and click Button it should generate the Image of it..

I try to make the Transparent Image using Imageformat.Png and save it , But this code works fine on mozilla but not in IE.
so, I use your code to make Transparent GIF, First i write the code in VB.Net It works fine and Make Images that have transparent Background, but soon it start crashing my application, as some Images Leave there reference in memory, So I try to rewrite it in C# (also I copy paste your function) for the Same, But now it doesn't Make the Transparent Image at all,

Do you have any idea ..Please help me

This appears to be the same Sumit Gupta who left a similar question on an ASP.net forum with a link to the above post.

I don't really have time to review Mr. Gupta's code to figure out what the problem might be, so I decided to just write some code to see for myself what's involved with doing this, thinking perhaps something in my experience would aid Mr. Gupta. I took my IHttpHandler-based spark.ashx code, stripped the non-relevant stuff from it, and added a single function to generate an image based on some text and font characteristics supplied in the querystring. I then pounded out a quick form for entering the querystring parameters and started testing.

Seems to work fine. Certainly hasn't crashed my servers, yet. Feel free to try it out yourself using the form below.


Text:
Family:
Color:
Size: (pixels)
Bold   Italic   Underline


I surrounded the IMG element with a dashed border so you can see that the generated image is no bigger than required to support the specified text. What little gap there is around the text, and sometimes there's not enough on the right side depending on the font size specified, is the result of size coordinates returned by the Graphics type's MeasureString method.

Also, I placed the IMG element in a padded TD with a beige background so you can see that the image is indeed transparent (I was using a DIV, but IE wouldn't size it correctly relative to the IMG's dynamic height). As I mentioned in some later posts, the transparency logic in my Sparklines generator was a bit naïve and I've since come up with a better approach. Unfortunately, I don't have time to implement it here, so text graphics generated with non-solid font colors will suffer some due to the use of white as the transparency color.

Things to consider adding:

  • A text padding parameter.
  • A non-transparent background-color.
  • Drop shadows.
  • Rotation and/or bending.

You can modify and deploy the source on your own server, or you can just use my service. Please note, though, that I've included some text length and font size limits in my copy of text.ashx in order to avoid overloading my servers. Also, I make no guarantees regarding the availability, responsiveness, or correctness of my service.

Anyhow, Sumit Gupta, I hope something here helps. Good luck!


Comments

Excellent example....
I am able to use your form and submit some japanese characters, and it works great, but when I tried to do it locally it does not seem to work. Do you happen to have a guess why?

Brian | 2005.12.21 01:29 PM

Hi Brian,

By "not works locally", do you mean it runs but won't do the Japanese characters or that it won't run at all?

Assuming you mean the former, it might be the difference in operating sytems. My ASHX is hosted on Windows Server 2003. Are you trying it locally on Windows XP?

ewbi.develops | 2005.12.21 02:42 PM

Sorry I should have been more clear, I am running 2003 locally, and it does run, it just displays the "boxes" rather than the text. I have tried various fonts, etc... I am submiting it on the querystring, is there another way that you are submiting the text?

Brian | 2005.12.23 08:17 AM

Hi Brian,

One more clarification: Are you trying to run a local copy of the ASHX in your own IIS virtual directory, or are you only talking about running the HTML/Javascript locally calling my ASHX?

ewbi.develops | 2005.12.23 11:57 AM

This works for me perfectly in ie however not so good in mozilla. It just shows a small square like when the browser can't find the image.

Any ideas?

Steve | 2006.04.28 04:19 AM

Hi Steve,

That's the first of heard of an issue. Have you tried browsing to the service directly? Here's a simple URL:

http://www.ewbi.com/ewbi.develop/text/text.ashx?text=Hello%20world%21

Let me know whether this shows you a "Hello World" graphic. If it does, there's probably something incompatible in the JavaScript I'm using on this page to dynamically change the image's src attribute.

ewbi.develops | 2006.04.28 06:22 AM

Yeh, that works fine in both ie and firefox. Something in the javascript then!?

Steven | 2006.04.29 04:14 AM

Steve, when you said "mozilla" in your first comment, did you mean FireFox, Navigator, or some other Mozilla derivative? I assumed one of the latter, as I'm using FireFox (have been since before 1.0), and I've never had a problem with the JavaScript on this page. If you did mean FireFox, what version?

ewbi.develops | 2006.04.29 08:02 AM

Sorry about the confusion. I meant firefox ver 1.0.7. The form on this page doesn't show an image when you post it. Strange, I had a quick look into the javascript but with no luck.

Steve | 2006.04.30 11:45 AM

Interesting, Steve. I think I started using FireFox with v1.0.8 or 9, so it's possible 1.0.7 doesn't support dynamic changes to an IMG element's src attribute (I haven't got 1.0.7 around anymore to see for myself). Luckily, though, you can still get text image's by addressing the service directly using a parameterized querystring. Thanks for bringing this to my attention.

ewbi.develops | 2006.04.30 11:57 AM

I've just downloaded the new version of firefox 1.5.0.2 and it is doing exactly the same. Surely they didn't start supporting dynamic changes to an img and then stop again. I wonder what is going on?

Steve | 2006.05.01 05:18 AM

Steve, I'm using FireFox 1.5.0.2 and not having any problem seeing the generated graphic. Are you running any add-ins that might be interfering with the code, like Adblock, or modified any of the JavaScript settings?

ewbi.develops | 2006.05.01 09:31 AM

I m trying 2 make an asp.net page similar to hotmail sign up form. Im that page, v use an image text, to verify the user. i m trying 2 do the same. Here i've generated the dynamic text on image but been able 2 uise any other property of form. please sort out my problem. My code is
Imports System.Drawing.Imaging
Public Class DynamicText
Inherits System.Web.UI.Page

#Region " Web Form Designer Generated Code "

'This call is required by the Web Form Designer.
Private Sub InitializeComponent()

End Sub

'NOTE: The following placeholder declaration is required by the Web Form Designer.
'Do not delete or move it.
Private designerPlaceholderDeclaration As System.Object

Private Sub Page_Init(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Init
'CODEGEN: This method call is required by the Web Form Designer
'Do not modify it using the code editor.
InitializeComponent()
End Sub

#End Region

Function GetRandomChar() As String
Dim RandomLetter As Integer
Dim str As String
Dim Index As Integer
Randomize(Timer)
'Get Random Letters
RandomLetter = Int(Rnd() * 26) + 65
str = str & Chr(RandomLetter)
Return str
End Function

Function GetRandomConsonant() As String
Dim RandomLetter As Integer
Dim str As String
Dim Index As Integer
Randomize(Timer)
'Get Random Letters
RandomLetter = Int(Rnd() * 10)
str = str & (RandomLetter)
Return str
End Function

Function GetRandomFont() As String
Dim RandomVowel As Integer
RandomVowel = Int(Rnd() * 6)
Select Case RandomVowel
Case 0
GetRandomFont = "Algerian"
Case 1
GetRandomFont = "Batang"
Case 2
GetRandomFont = "Bodoni MT Poster Compressed"
Case 3
GetRandomFont = "Lucida Calligraphy"
Case 4
GetRandomFont = "Informal Roman"
Case 5
GetRandomFont = "Viner Hand ITC"
End Select
End Function

Private Sub Page_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
'Put user code to initialize the page here
If Page.IsPostBack = False Then
Dim oBitmap As Bitmap = New Bitmap(240, 30)
Dim oaxis As System.Drawing.Image
Dim oGraphic As Graphics = Graphics.FromImage(oBitmap)
Dim oFont As System.Drawing.Font
Dim oColor As System.Drawing.Color
Dim oBrush As New SolidBrush(Color.Red)
Dim oBrushWrite As New SolidBrush(Color.White)
Dim ThePassword As String
Dim str01, str02 As String
Dim Index, j As Integer
Dim selection As Integer
j = 0
For Index = 1 To 8
selection = Int(Rnd() * 2)
If selection = 0 Then
str01 = GetRandomConsonant()
ThePassword = ThePassword & str01
Else
str01 = GetRandomChar()
ThePassword = ThePassword & str01
End If
oGraphic.FillRectangle(oBrush, j, 0, 30, 30)
str02 = GetRandomFont()
oFont = New Font(str02, 16, FontStyle.Bold)
oGraphic.DrawString(str01, oFont, Brushes.White, j + 3, 3)
j = j + 30
Next
Response.ContentType = "image/GIF"
oBitmap.Save(Response.OutputStream, ImageFormat.Gif)
oFont.Dispose()
oGraphic.Dispose()
oBitmap.Dispose()
End If
End Sub
End Class

Shariq | 2006.06.29 11:37 PM

Hi Shariq,

If I understand what you're asking (forgive me if I've missed the point), you're wondering how you are supposed to utilize the graphic content that your page code above generates. The thing is, you can't take advantage of it in that page. That page (assuming it works, I haven't run it) essentially sends graphic content in response to HTTP requests. To take advantage of that content you need another page that references the page above as the source for an IMG tag. For instance, if the page above has the name MyGraphic.aspx, then you need another page (ASPX, HTML, etc.) that serves HTML like this ("[]" used to represent angle brackets):

[html]
[body]
Here's the dynamically generated graphic:
[img src="MyPage.aspx"]
[/body]
[/html]

Hope that helps. Good luck.

ewbi.develops | 2006.06.30 10:37 AM

I have been working with graphics a long time and I have readed your blog with pleasure. Great work.

The problem with measurestring is wellknown, and I can't find a solution to get hold of this.
The problem occures when I uses many rows with different sizes. It's look like the rows with bigger sizes dont "push" the row under.

If you look at www.tinon.se/test.bmp you will see this problem. If anyone has a solution, please let me know.

Robert | 2006.07.23 04:35 AM

Hi Robert,

Thanks for the note. I'm not familiar with the issue you describe, but hopefully someone can offer some help (I don't get a lot of traffic, though). Have you checked out the new .NET 2.0 System.Windows.Forms.TextRenderer class?

http://msdn.microsoft.com/msdnmag/issues/06/03/TextRendering/

Good luck.

ewbi.develops | 2006.07.24 10:22 AM

I have a html table where each row has a image to be rendered. I have the System.Drawing.Image objects (These are Gif images) which i need to put in the table rows. I ma using C#/ASP.Net How do I do this?

ameya kogje | 2006.08.10 12:54 AM

Ameya,

I'm not ignoring you, I just haven't had time to respond. I think the question you're asking is similar to the question from Shariq above. In your case, it sounds like you need a page (or IHttpHandler-derived class) to serve the images you're holding to another page (the one with the table). Please take a look at my response to Shariq and let me know if you need more info.

Good luck.

ewbi.develops | 2006.08.11 04:58 PM

Here is another happy user with your explanation and code. I am using it to create a gif-file from another gif-file contaning a button image where I dynamically add a text to.
The unwanted effect I am facing now is that the color of resulting gif-file is not as "solid" as on the original gif-file. It now contains slightly darker dots on regular distances.
I understand the gif converter needs to do some magic with the colors to make the image fit the limited capabilities of the gif specification, but: the original image is a gif-file (created with a graphics editor) with a smooth, one solid color surface. Even when I don't touch the image (no text added) and save it directly using your routine it gets uglyfied with these ghost spots. (pff, hard to explain, would be much easier if I could just show you the original en resulting image).
Do you have an answer to this challenging question?

Johan | 2007.01.02 05:07 PM

Johan,

So sorry for the very late reply. I've spent the last week trying to catch up on blog comments, and only happened to stumble onto yours by chance. I don't even recall getting a notice of your comment.

Anyhow, I assume you've moved way beyond this now, but on the off-chance you haven't, I was wondering if you were allowing the GIF to pass through the transparency logic as well? If so, I can see how that might screw up the image's color palette. If I get a chance, I'll try running the code using an existing solid-colored GIF to see what happens.

Good luck.

ewbi.develops | 2007.04.27 04:57 PM

Hi,

I was wondering...can this Handler can take a multi-line text value?

Manish | 2007.11.01 01:14 PM

Hi Manish,

Yes it does, but you can't submit one using the single-line text box above (I suppose that's something I should change someday). If you send properly URL-encoded new-line characters in your text, they will be preserved in the output. Here's an example:

http://www.ewbi.com/ewbi.develop/text/text.ashx?text=Hello%0Aworld%21

The "%0A" is ASCII character 10, representing a new line.

ewbi.develops | 2007.11.01 01:47 PM

Thanks, this helps...I am in the middle of a project where I generate a multi-line image with different sized fonts...which will probably involve some stiching together of seperate text generated images...

Manish | 2007.11.01 03:30 PM

Hi,

I tried a slight modification to the code which is giving me the dreaded "red x". I wanted to modify the g.DrawString call to use the StringFormat argument.

I added the following 4 lines:
StringFormat sf = new StringFormat();
sf.FormatFlags = StringFormatFlags.DirectionRightToLeft;
sf.Alignment = StringAlignment.Near;
sf.LineAlignment = StringAlignment.Center;

and modified the g.DrawString to:
g.DrawString(text, font, br, 0, 0,sf);

any thoughts?

Manish | 2007.11.01 03:54 PM

My only thought is that there might be a problem drawing into the Graphics object that was based on a Bitmap that was sized to the text without consideration for the string placement dictated by the StringFormat.

If you figure it out, please come back and let us know. Good luck.

ewbi.develops | 2007.11.01 04:19 PM

is there another way to change the text to be right justified?

Manish | 2007.11.01 05:58 PM

Oh sorry, Manish, I wasn't paying attention. I believe the problem stems from the fact that your DrawString call is not providing a rectangle within which to draw the string, according to your StringFormat options, but is instead being instructed to draw the string at 0, 0 within the underlying bitmap. In order to do right-justified text drawing, you'll have to draw within something presumably bigger than the text - else how would you know that it is right justified in the first place?

My text drawing service only produces a bitmap big enough to hold the text, so except for a little gap on the right/left (which I add to the total size) there's no room within which to justify the text anyhow. However, if you did want to justify it within that gap, you could do this:

StringFormat sf = (StringFormat) StringFormat.GenericTypographic.Clone();
sf.Alignment = StringAlignment.Far;
using (SolidBrush br = new SolidBrush(fontColor)) {
g.DrawString(text, font, br, new Rectangle(new Point(0, 0), new Size((int) size.Width, (int) size.Height)), sf);
}

Ultimately, though, you'll have to create a bigger bounding bitmap in the first place. Let me know if this doesn't make sense. Good luck.

ewbi.develops | 2007.11.01 06:35 PM

Finally got it to work!! (Will post code soon)...

I have one more question, mainly on deployment...What are the security settings that you use?

Manish | 2007.11.19 03:16 PM

Glad to hear you got it working the way you wanted. In terms of security, I'm afraid you'll have to be a little more specific - are you talking about CAS restrictions?

ewbi.develops | 2007.11.19 03:58 PM

Well I am running the handler on Windows 2000 IIS. I have a form where the user enters the text for the image, which then transmits the text to another aspx page that uses the handler and sets the ImageURL for the ASP:Image objects and loads the page. I was wondering what IIS permissions you set for this (read, write, execute)

Manish | 2007.11.19 05:32 PM

Ah, now I understand. Unfortunately, I have no idea what this is set to on my hosted server - I just pushed the page to a subdirectory of the root and that was sufficient. I don't think, though, that any IIS-level permissions (i.e., the read, write, execute, etc. permissions you referenced) are required (or at least they don't impact on whether or not a particular user, authenticated or not, can execute your .ASPX/.ASHX/etc. resources), as long as the site has the proper ASP.NET resource mappings. Here's a little backgrounder on the subject:

http://blogs.msdn.com/david.wang/archive/2005/08/20/Why-can-I-upload-a-file-without-IIS-Write-Permission.aspx

Good luck!

ewbi.develops | 2007.11.19 05:53 PM

Question: I want to show you the modifications I made to the handler, should I email them to you or just post them here?

Manish | 2007.11.22 01:59 AM

If they're short (one or two lines each) and few, here will work, but there's no formatting features here, so longer and/or indented text can be problematic. In that case, just send it to the email address at the bottom of the left column and I'll take a look after the Thanksgiving Holiday. Thanks.

ewbi.develops | 2007.11.22 08:25 AM

Hi there.
I copy spark.ashx code and tried to generate image but I did not get any idea to pass parameter to the ashx handler.Can any body tell how to pass text content to the ashx.?
I tried code but i got an error in this line
try
{
data[dataIndex + 1] = int.Parse((string)dataRaw[rawIndex]);
}
That input string was not in current format
Can any body solve my problem?

Imrankhan | 2007.12.27 09:49 PM

Thank you.

مهرگان طراحي وب نرم افزار آموزش | 2008.04.13 12:06 AM

Imrankhan, sorry - just saw your comment. On the off chance you still need help, please write back and let me know.

ewbi.develops | 2008.04.13 09:46 PM

Simple and Smart Example.
Btw, how to write text on image, and merge to the New Image with text inside..?

Sofyan Hadi | 2008.05.28 09:13 PM

Sofyan Hadi,

I'm afraid I don't have time to investigate this myself right now, but it seems like this would be a fairly easy thing to do using one of the other Bitmap class constructors that takes an image Stream, an Image object, or image file name String. The code provided with this post simply constructs a new empty Bitmap object using the dimension-based constructor, but I think it could have as easily used an existing image.

ewbi.develops | 2008.05.29 09:47 AM

I have install visual Std 2005 in my PC, how can install MSDN in my PC?

smita dixit | 2008.08.30 02:04 AM

Hi, and thank you for this post. I do have a question on whether or not it is possible to use this ashx technique to create a dynamic image without needing a hidded tage in the markup. In other words, when you click the "Generate Image" button, can an node be created and appended to the DOM and then have that newly created have it's src set to the ashx file, all without postback? I cannot seem to get my decribed scenario working. I would like to do it this way for a variety of reason, the main being that I don't really wish to limit the number of images my users may be creating. Any ideas?

Steve | 2008.09.25 02:51 PM

meh. hidded = hidden; tage = tag; all other bad grammer = I am a moron.

Steve | 2008.09.25 02:52 PM

Hi Steve,

No worries on the spelling - I'm guilty of much worse. :)

The answer to your question is "Yes". And, believe it or not, the form above doesn't do a postback, it simply uses client-side JavaScript to update the src property of an existing IMG element. However, to better illustrate what it is that you're asking, I modified the form to include another button, "Add as IMG Element", which when pressed creates a new IMG element with the proper src property and inserts it into the DOM.

Hope that answers your question. Good luck!

ewbi.develops | 2008.09.29 08:18 PM

Thank you very much for posting this article. I’ve found it very helpful but I can’t get past the issue about ‘non-solid font colors will suffer some due to the use of white as the transparency color’. Is there any way you could point me in the right direction?

Chad Boettcher | 2008.10.17 10:01 AM

Hi Chad,

Sorry for the slow response, TypePad has stopped delivering comment notices to me for some reason. I'm not sure in what direction you'd like to be pointed - do you mean toward a solution to the naïve transparency implementation in this code that results in whites in the font color being made transparent?

ewbi.develops | 2008.10.21 07:00 PM

Anybody for the .NET version?
(Made some minor adjustments, and added Caching!)
Thanks for the code, excellent!
---------------------------------------------------


Option Explicit On
Option Strict On

Imports System
Imports System.IO
Imports System.Net
Imports System.Web
Imports System.Drawing
Imports System.Drawing.Imaging
Imports System.Drawing.Text
Imports System.Runtime.InteropServices

Public Class imgOverlay : Implements IHttpHandler

' Thanks to: http://ewbi.blogs.com/develops/2005/11/aspnet_dynamic_.html !

Const VERSION As String = "1.0"

Private Function PlotText(ByVal text As String) As MemoryStream

Try
Dim fontFamily As String = GetArg("family", "Verdana")
Dim fontSize As Single = Single.Parse(GetArg("size", "18")) ' assumed to be pixels
Dim fontBold As Boolean = Boolean.Parse(GetArg("bold", "False"))
Dim fontItalic As Boolean = Boolean.Parse(GetArg("italic", "False"))
Dim fontUnderline As Boolean = Boolean.Parse(GetArg("underline", "False"))
Dim fontColor As Color = GetColor(GetArg("color", "Black"))

'arbitrary limits to avoid killing my servers; feel free to change in your own implementation
If (text.Length > 100) Then text = text.Substring(0, 100)
If (fontSize > 400) Then fontSize = 400

'need a bitmap and graphics object in order to measure the text to determine the height and width
'of the actual bitmap and graphics objects.
Dim size As SizeF = New SizeF(1, 1)
Dim font As Font = Nothing

Try
Using bitmap1 As Bitmap = New Bitmap(1, 1)
Using g As Graphics = Graphics.FromImage(bitmap1)
g.TextRenderingHint = TextRenderingHint.AntiAlias
Dim fontStyle As FontStyle = fontStyle.Regular

If fontBold Then fontStyle = fontStyle.Bold
If fontItalic Then fontStyle = fontStyle.Italic
If fontUnderline Then fontStyle = fontStyle.Underline

font = New Font(fontFamily, fontSize, fontStyle, GraphicsUnit.Pixel)

'could get fancy here with StringFormat options
size = g.MeasureString(text, font)

End Using
End Using

Using bitmap2 As Bitmap = New Bitmap(Convert.ToInt32(size.Width), Convert.ToInt32(size.Height), PixelFormat.Format32bppArgb)
Using g As Graphics = Graphics.FromImage(bitmap2)

Using br As SolidBrush = New SolidBrush(Color.White)
g.FillRectangle(br, 0, 0, bitmap2.Width, bitmap2.Height)
End Using

Using br As SolidBrush = New SolidBrush(fontColor)
g.DrawString(text, font, br, 0, 0)
End Using

Dim m As MemoryStream = New MemoryStream
bitmap2.Save(m, ImageFormat.Gif)
Return MakeTransparent(m)
End Using
End Using

Catch ex As Exception

Finally
If Not IsDBNull(font) And font IsNot Nothing Then
font.Dispose()
End If

End Try

Catch ex As Exception
Return PlotError()

End Try

End Function

Function PlotError() As MemoryStream
Dim m As MemoryStream = New MemoryStream
Using bitmap As Bitmap = New Bitmap(100, 100, PixelFormat.Format32bppArgb)
Using g As Graphics = Graphics.FromImage(bitmap)
Using br As SolidBrush = New SolidBrush(Color.White)
g.FillRectangle(Brushes.Brown, 0, 0, bitmap.Width, bitmap.Height)
End Using
Using p As Pen = New Pen(Color.Red)
g.DrawLine(p, 0, 0, bitmap.Width, bitmap.Height)
g.DrawLine(p, 0, bitmap.Height, bitmap.Width, 0)
End Using
bitmap.Save(m, ImageFormat.Gif)
End Using
End Using
Return MakeTransparent(m)
End Function

Sub ok()
SetResponse(HttpStatusCode.OK, "Ok")
End Sub

Overloads Sub errorr()
errorr(HttpStatusCode.BadRequest, "Bad Request")
End Sub

Overloads Sub errorr(ByVal statusCode As HttpStatusCode, ByVal statusDescription As String)
SetResponse(statusCode, statusDescription)
_response.BinaryWrite(PlotError().ToArray())
_response.End()
End Sub

Dim _request As Web.HttpRequest
Dim _response As Web.HttpResponse

Public Sub ProcessRequest(ByVal context As System.Web.HttpContext) Implements System.Web.IHttpHandler.ProcessRequest

_request = context.Request
_response = context.Response

If (_request.RequestType <> "GET") And (_request.RequestType <> "HEAD") Then
errorr(HttpStatusCode.MethodNotAllowed, "Method Not Allowed")
End If

Dim text As String = GetArg("text", DateTime.Now.ToLongDateString)
If String.IsNullOrEmpty(text) Then
errorr()
Else
ok()
_response.BinaryWrite(PlotText(text).ToArray())
End If

End Sub

Public ReadOnly Property IsReusable() As Boolean Implements System.Web.IHttpHandler.IsReusable
Get
Return False
End Get
End Property

'/ --------------------------------------------------------------------

Function GetArg(ByVal argName As String, ByVal argDefault As String) As String
If _request Is Nothing Then
Return argDefault
Else
Dim arg As String = Convert.ToString(_request.QueryString(argName))
If Not String.IsNullOrEmpty(arg) Then
Return arg
Else
Return argDefault
End If
End If
End Function

Sub SetResponse(ByVal statusCode As HttpStatusCode, ByVal statusDescription As String)

'caching / expiration
Const EXPIRES_AFTER_DAYS As Integer = 7
_response.Cache.SetCacheability(HttpCacheability.ServerAndPrivate)
_response.Cache.VaryByParams("family;size;bold;italic;underline;color") = True
_response.Cache.SetMaxAge(New TimeSpan(EXPIRES_AFTER_DAYS, 0, 0, 0)) ' preferred way to set expiration in HTTP1.1
_response.Cache.SetExpires(DateTime.Now.AddDays(EXPIRES_AFTER_DAYS))
_response.Cache.SetValidUntilExpires(True)

_response.ContentType = "image/gif"
_response.StatusCode = Convert.ToInt32(statusCode)
_response.StatusDescription = statusDescription
_response.AddHeader("ETag", (Convert.ToString((_request.QueryString.ToString() & VERSION)).GetHashCode().ToString()))
_response.Flush()
End Sub

Function Redimm(ByVal origArray As Array, ByVal newSize As Integer) As Array
Dim t As Type = origArray.GetType().GetElementType()
Dim newArray As Array = Array.CreateInstance(t, newSize)
Array.Copy(origArray, 0, newArray, 0, Math.Min(origArray.Length, newSize))
Return newArray
End Function

Function GetColor(ByVal strColor As String) As Color
If strColor.StartsWith("#") Then
Return Color.FromArgb(IntFromHexRgbPart(strColor, RgbPart.RgbPartRed), _
IntFromHexRgbPart(strColor, RgbPart.RgbPathGreen), _
IntFromHexRgbPart(strColor, RgbPart.RgbPartBlue))
Else
Return Color.FromName(strColor)
End If
End Function

Enum RgbPart
RgbPartRed
RgbPathGreen
RgbPartBlue
End Enum

Function IntFromHexRgbPart(ByVal hexRgb As String, ByVal part As RgbPart) As Integer
If String.IsNullOrEmpty(hexRgb) Or Not hexRgb.StartsWith("#") Then
Return 0
End If
Try
Select Case part
Case RgbPart.RgbPartRed
If (hexRgb.Length < 3) Then Return 0
Return IntFromHex(hexRgb.Substring(1, 2))
Case RgbPart.RgbPathGreen
If (hexRgb.Length < 5) Then Return 0
Return IntFromHex(hexRgb.Substring(3, 2))
Case RgbPart.RgbPartBlue
If (hexRgb.Length < 7) Then Return 0
Return IntFromHex(hexRgb.Substring(5, 2))
Case Else
Return 0
End Select
Catch ex As Exception
Return 0
End Try
End Function

Function IntFromHex(ByVal hex As String) As Integer
Return Convert.ToInt32(Byte.Parse(hex, Globalization.NumberStyles.HexNumber))
End Function

Function MakeTransparent(ByVal origBitmapMemoryStream As MemoryStream) As MemoryStream
Dim transparentColor As Color = GetColor("White")
Dim transparentArgb As Integer = transparentColor.ToArgb()
Using origBitmap As Bitmap = New Bitmap(origBitmapMemoryStream)
Using newBitmap As Bitmap = New Bitmap(origBitmap.Width, origBitmap.Height, origBitmap.PixelFormat)
Dim origPalette As ColorPalette = origBitmap.Palette
Dim newPalette As ColorPalette = newBitmap.Palette
Dim index As Integer = 0
Dim transparentIndex As Integer = -1
For Each origColor As Color In origPalette.Entries
newPalette.Entries(index) = Color.FromArgb(255, origColor)
If (origColor.ToArgb() = transparentArgb) Then transparentIndex = index
index += 1
Next
If transparentIndex = -1 Then
Return origBitmapMemoryStream
End If

newPalette.Entries(transparentIndex) = Color.FromArgb(0, transparentColor)
newBitmap.Palette = newPalette
Dim rect As Rectangle = New Rectangle(0, 0, origBitmap.Width, origBitmap.Height)
Dim origBitmapData As BitmapData = origBitmap.LockBits(rect, ImageLockMode.ReadOnly, origBitmap.PixelFormat)
Dim newBitmapData As BitmapData = newBitmap.LockBits(rect, ImageLockMode.WriteOnly, newBitmap.PixelFormat)

For y As Integer = 0 To origBitmap.Height - 1
For x As Integer = 0 To origBitmap.Width - 1
Dim origBitmapByte As Byte = Marshal.ReadByte(origBitmapData.Scan0, origBitmapData.Stride * y + x)
Marshal.WriteByte(newBitmapData.Scan0, newBitmapData.Stride * y + x, origBitmapByte)
Next
Next

newBitmap.UnlockBits(newBitmapData)
origBitmap.UnlockBits(origBitmapData)
Dim m As MemoryStream = New MemoryStream()
newBitmap.Save(m, ImageFormat.Gif)
Return m

End Using
End Using
End Function

End Class

Steven V | 2008.11.18 08:15 AM

VB.NET that is.... ;)

Steven V | 2008.11.18 08:15 AM

Steven, finally got your comment published! Thanks so much for sharing this - I'm sure some VB.NET folks will be very grateful! (Sorry TypePad's crappy comment system ate your indents, but Visual Studio will fix that up for folks real quick!)

ewbi | 2008.11.26 08:34 PM

Hi,


this code very useful..

Thanking you

Anbazhagan | 2010.02.19 02:11 AM

Thank you! I'd love to see a drop shadow option added.

Drew | 2011.06.14 03:34 PM

Me too! ;)

Sigh. I sure wish I had the time to come back and update this old thing with all the graphics library changes since .NET 2.0. Enjoy!

ewbi.develops | 2011.06.14 04:57 PM


TrackBack

TrackBack URL:  http://www.typepad.com/services/trackback/6a00d8341c7bd453ef00d8346ef94a53ef

Listed below are links to weblogs that reference Generate Dynamic Text Images with ASP.NET: