This tutorial will walk you through the process of developing a class for the generation of Memes.
We'll come back to the UI later, but next we will create a class whose responsibility it will be to make Memes.
Drawing
namespace in ASP.NET, so add the following using statements at the top of the file:
using System.Drawing;
using System.Drawing.Drawing2D;
private Image sourceImage;
Note that an image in the Drawing namespace differs from the one in System.Web.UI
(which you would might reference from inside a web form's class, and which reprents a HTML img element). We will make use of both in this project!public MemeGenerator(Image image)
{
this.sourceImage = image;
}
A shortcut to creating a constructor in Visual Studio is to type 'ctor' and then press the tab key twice.
public Image Generate(string topLine, string bottomLine)
{
}
Image memeImage = sourceImage.Clone() as Image;
Graphics textGraphics = Graphics.FromImage(memeImage);
textGraphics.CompositingQuality = CompositingQuality.HighQuality;
textGraphics.SmoothingMode = SmoothingMode.HighQuality;
textGraphics.InterpolationMode = InterpolationMode.HighQualityBicubic;
float fontSize = 10.0f; //default starting font size - will be adjusted to fit image
Font font = new Font(FontFamily.GenericSansSerif, fontSize, FontStyle.Bold);
private RectangleF estimateSizeOfString(string text, Font font)
{
GraphicsPath path = new GraphicsPath();
path.AddString(text, font.FontFamily, (int)font.Style, font.Size, new Point(0, 0), new StringFormat());
return path.GetBounds();
}
Generate
method, and add the following lines of code which will find the higher of the estimated sizes of each string:RectangleF topSize = estimateSizeOfString(topLine, font);
RectangleF bottomSize = estimateSizeOfString(bottomLine, font);
float textWidthAtTenEm = Math.Max(topSize.Width, bottomSize.Width);
(You may wonder why we didnt just measure the longest string. Whilst this would work in most cases, for most font faces, the size of the individual characters varies (consider the width of a lowercase 'i' compared to an uppercase 'W'). Because of this, the longest string won't always be the longest line of text graphically)float scale = memeImage.Width / textWidthAtTenEm;
fontSize *= scale * 0.98f;
font = new Font(font.FontFamily, fontSize, font.Style);
private GraphicsPath textPathWithVerticalOffSet(string text, Font font, int topOffset = 0)
{
}
StringFormat centreFormat = new StringFormat();
centreFormat.Alignment = StringAlignment.Center;
Point renderPoint = new Point(sourceImage.Width / 2, topOffset);
GraphicsPath path = new GraphicsPath();
path.AddString(text, font.FontFamily, (int)font.Style, font.Size, renderPoint, centreFormat);
return path;
Pen thickPen = new Pen(Brushes.Black, 3.0f);
topOffset
parameter is only used when getting the path for the bottom line of text. The outline of the text is drawn in black and it is filled with white, so it stands out on any image: GraphicsPath topPath = textPathWithVerticalOffSet(topLine, font);
textGraphics.DrawPath(thickPen, topPath);
textGraphics.FillPath(Brushes.White, topPath);
float bottomOffset = sourceImage.Height - (fontSize * 1.2f);
GraphicsPath bottomPath = textPathWithVerticalOffSet(bottomLine, font, (int)bottomOffset);
textGraphics.DrawPath(thickPen, bottomPath);
textGraphics.FillPath(Brushes.White, bottomPath);
textGraphics.Dispose();
return memeImage;
When the user adds the text to the fields, chooses an image and pressed the button, a few things need to happen:
System.Drawing.Image
)System.Web.Ui.WebControls.Image
) has various properties set, so that it points to the image file, is set to the correct dimensions, and has alternate text (based on the text the user entered)protected void SubmitButton_Click(object sender, EventArgs e)
{
Byte[] file = ImageUploader.FileBytes;
MemoryStream str = new MemoryStream(file);
System.Drawing.Image image = System.Drawing.Image.FromStream(str);
MemeGenerator memeGen = new MemeGenerator(image);
System.Drawing.Image memeImage = memeGen.Generate(txtTopLine.Text,txtBottomLine.Text);
String guid = Guid.NewGuid().ToString();
memeImage.Save(Server.MapPath("~/Memes/"+guid+".jpg"),System.Drawing.Imaging.ImageFormat.Jpeg);
MemeImage.ImageUrl = "memes/"+guid+".jpg";
MemeImage.AlternateText = txtTopLine.Text + ": " + txtBottomLine.Text;
MemeImage.Attributes.Add("width", memeImage.Width.ToString());
MemeImage.Attributes.Add("height", memeImage.Height.ToString());
}
You can Try out a completed version of the meme generator here