Here's a couple of methods from a captcha generator we use that might steer you in the right direction:
internal static void DrawPhrase(
this Graphics graphics,
int width,
int height,
string phrase)
{
graphics.FillRectangle(
Brushes.White,
0,
0,
width,
height);
using (var gp = new GraphicsPath())
{
gp.AddString(phrase,
FontFamily.GenericMonospace,
(int)FontStyle.Bold,
33f,
new Point(0,
0),
StringFormat.GenericTypographic);
using (var gpp = gp.Deform(width, height))
{
var bounds = gpp.GetBounds();
var matrix = new Matrix();
var x = (width - bounds.Width) / 2 - bounds.Left;
var y = (height - bounds.Height) / 2 - bounds.Top;
matrix.Translate(x,
y);
gpp.Transform(matrix);
graphics.FillPath(Brushes.Black,
gpp);
}
}
graphics.Flush();
}
internal static GraphicsPath Deform(
this GraphicsPath path,
int width,
int height)
{
var WarpFactor = 4;
var xAmp = WarpFactor * width / 300d;
var yAmp = WarpFactor * height / 50d;
var xFreq = 2d * Math.PI / width;
var yFreq = 2d * Math.PI / height;
var deformed = new PointF[path.PathPoints.Length];
var xSeed = rng.NextDouble() * 2 * Math.PI;
var ySeed = rng.NextDouble() * 2 * Math.PI;
var i = 0;
foreach (var original in path.PathPoints)
{
var val = xFreq * original.X + yFreq * original.Y;
var xOffset = (int)(xAmp * Math.Sin(val + xSeed));
var yOffset = (int)(yAmp * Math.Sin(val + ySeed));
deformed[i++] = new PointF(original.X + xOffset,
original.Y + yOffset);
}
return new GraphicsPath(deformed,
path.PathTypes);
}