Here is my God damn solution which took me ages to figure out but works perfectly though you have to hardcode defaultwidth of the images and also direction of the text.
If text length is larger than defaultwidth, text will continue on the next line, so you will have multiline image of the text.
You can change the text direction. Currently it is rtl but ltr is commented out. Just switch the comment lines you will have left aligned text.
<%@ WebHandler Language="C#" Class="FontWriter" %>
using System;
using System.Web;
using System.Web.Caching;
using System.Drawing;
using System.IO;
using System.Drawing.Imaging;
using System.Drawing.Drawing2D;
using System.Drawing.Text;
using System.Collections.Generic;
using System.Linq;
using System.Web.UI;
public class FontWriter : IHttpHandler
{
private bool enableCache = false;
private TextRenderingHint textHint = TextRenderingHint.AntiAlias;
private int topOffset = 0;
private int bottomOffset = 0;
private int leftOffset = 0;
private int rightOffset = 0;
private string fontsPath = "";
private string defaultColor = "#00FF00";
private string defaultFontName = "Arial";
private string defaultBackgroundColor = "#ffffff";
private int defaultHeight = 20;
private Double defaultFontSize = 18.0F;
Color FontColor = Color.Blue;
Color BackColor = Color.White;
private int defaultWidth = 1000;
private Rectangle GetConstrainedTextHeight(string textToParse, ref string resultText)
{
int quoteAreaWidth = defaultWidth;
Bitmap bitmap = new Bitmap(100, quoteAreaWidth);
Graphics g = Graphics.FromImage(bitmap);
string fontName = HttpContext.Current.Request["font"] + "";
if (fontName == "" || fontName == "[font]")
fontName = defaultFontName;
Double fontSize = -1.0F;
if (!Double.TryParse((HttpContext.Current.Request["size"] + "" + "").Replace("px", ""), out fontSize))
{
fontSize = defaultFontSize;
}
Font font = new Font(fontName, (float)fontSize);
SizeF sz = g.MeasureString(textToParse, font);
if (sz.Width <= quoteAreaWidth)
{
resultText = textToParse;
g.Dispose();
bitmap.Dispose();
return new Rectangle(new Point(0, 0), new Size((int)sz.Width, (int)sz.Height));
}
resultText = "";
string[] words = textToParse.Trim().Split(' ');
string nextLine = "";
string word = "";
for (int i = 0; i < words.Length; i++)
{
word = words[i];
SizeF lineSize = g.MeasureString(nextLine + 1, font);
SizeF wordSize = g.MeasureString(" " + word, font);
if (lineSize.Width + wordSize.Width < quoteAreaWidth)
{
nextLine = string.Format("{0} {1}", nextLine, word);
if (i == words.Length - 1)
{
resultText += nextLine;
}
}
else
{
resultText += (nextLine + "\n");
nextLine = word;
if (i == words.Length - 1)
{
resultText += nextLine;
}
}
}
sz = g.MeasureString(resultText, font);
g.Dispose();
bitmap.Dispose();
return new Rectangle(new Point(0, 0), new Size((int)sz.Width, (int)sz.Height ));
}
public void ProcessRequest (HttpContext context) {
string text = context.Request["text"] + "";
Double fontSize = -1.0F;
if (!Double.TryParse((context.Request["size"] + ""+"").Replace("px",""), out fontSize))
{
fontSize = defaultFontSize;
}
int width = -1;
if (!Int32.TryParse( (context.Request["width"]+"").Replace("px",""), out width)) {
width = -1;
}
int height = -1;
if (!Int32.TryParse((context.Request["height"]+"").Replace("px",""), out height)) {
height = -1;
}
string fontName = context.Request["font"] + "";
if (fontName == "" || fontName == "[font]")
fontName = defaultFontName;
string foreColor = context.Request["color"] + ""; ;
if (foreColor == "" || foreColor == "[color]")
foreColor = defaultColor;
if (!foreColor.StartsWith("#"))
foreColor = "#" + foreColor;
string backColor = context.Request["bcolor"] + ""; ;
if (backColor == "" || backColor == "[bcolor]")
backColor = defaultBackgroundColor;
context.Trace.Write( String.Format("text: {0}; font:{1}; color:{2}; bgcolor:{3}; width:{4}; height:{5}; size:{6}", text, fontName, foreColor, backColor, width, height, fontSize) );
Bitmap bitmap = null;
string key = String.Format("FontWriter-{0}-{1}-{2}-{3}-{4}-{5}-{6}", text, fontName, foreColor, backColor, width, height, fontSize);
bitmap = context.Cache.Get(key) as Bitmap;
if (bitmap == null || !enableCache)
{
Font font = null;
FontFamily[] ff = FontFamily.Families;
bool hasFont = false;
foreach (FontFamily f in ff)
{
if (f.Name == fontName)
{
hasFont = true;
break;
}
}
context.Trace.Write("found font :" + hasFont.ToString());
if (hasFont)
{
font = new Font(fontName, (float)fontSize);
}
else
{
PrivateFontCollection pfc = new PrivateFontCollection();
if (fontsPath == "")
fontsPath = context.Request.PhysicalPath.Substring(0, context.Request.PhysicalPath.LastIndexOf(Path.DirectorySeparatorChar));
string fontPath = Path.Combine(fontsPath, fontName);
context.Trace.Write("looking for: " + fontPath);
if (File.Exists(fontPath))
{
pfc.AddFontFile(fontPath);
context.Trace.Write("added: " + fontPath);
}
if (pfc.Families.Length > 0)
{
context.Trace.Write("using loaded font");
font = new Font(pfc.Families[0], (float)fontSize);
}
else
{
font = new Font(defaultFontName, (float)fontSize);
}
}
string newQuoteText = "";
Rectangle quoteRect = GetConstrainedTextHeight(text, ref newQuoteText);
font = new Font(fontName, (float)fontSize);
bitmap = new Bitmap(quoteRect.Width, quoteRect.Height);
Graphics g = Graphics.FromImage(bitmap);
PointF point = new PointF(5.0F, 5.0F);
SolidBrush BrushForeColor = new SolidBrush(FontColor);
SolidBrush BrushBackColor = new SolidBrush(BackColor);
Pen BorderPen = new Pen(Color.Black);
g.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.AntiAlias;
g.TextRenderingHint = System.Drawing.Text.TextRenderingHint.ClearTypeGridFit;
g.Clear(Color.Transparent);
g.FillRectangle(BrushBackColor, quoteRect);
SolidBrush brush = new SolidBrush(ColorTranslator.FromHtml(foreColor));
if (backColor == "")
{
g.Clear(Color.Transparent);
}
else
{
try
{
g.Clear(ColorTranslator.FromHtml(backColor));
}
catch (Exception ex)
{
g.Clear(ColorTranslator.FromHtml(defaultBackgroundColor));
}
}
g.TextRenderingHint = textHint;
StringFormat format1 = new StringFormat();
format1.FormatFlags = StringFormatFlags.DirectionRightToLeft;
g.DrawString(newQuoteText, font, brush, quoteRect.Width, -bottomOffset, format1);
context.Cache.Add(key, bitmap, null, Cache.NoAbsoluteExpiration, new TimeSpan(0, 10, 0), CacheItemPriority.Normal, null);
}
context.Response.Clear();
if (backColor == "transparent")
{
MemoryStream io = new MemoryStream();
bitmap.Save(io, ImageFormat.Png);
context.Response.ContentType = "image/png";
context.Response.BinaryWrite(io.GetBuffer());
}
else
{
context.Response.ContentType = "image/jpg";
SaveAsJpeg(bitmap, context.Response.OutputStream, (long)100);
}
}
public bool IsReusable {
get {
return false;
}
}
void SaveAsJpeg(Image inputImage, Stream stream, long quality)
{
ImageCodecInfo codecEncoder = GetEncoder("image/jpeg");
EncoderParameters encoderParams = new EncoderParameters(1);
EncoderParameter qualityParam = new EncoderParameter(System.Drawing.Imaging.Encoder.Quality, quality);
encoderParams.Param[0] = qualityParam;
inputImage.Save(stream, codecEncoder, encoderParams);
}
ImageCodecInfo GetEncoder(string mimeType)
{
ImageCodecInfo[] codecs = ImageCodecInfo.GetImageEncoders();
foreach (ImageCodecInfo codec in codecs)
{
if (codec.MimeType == mimeType)
{
return codec;
}
}
return null;
}
}
Thanks to
Render Text On A Bitmap (and other stuff)[
^] and