Text Halo Effect

You might imagine that creating the effect of an electric glow or halo around text would be nothing like drawing a soft shadow but the technique is exactly the same, just in a different place.

For the soft shadow effect I took advantage of the graphics interoplation mode used for bitmap drawing to create a fuzzy edge for text. When an image is enlarged, the interpolation mode decides how pixels will be combined with their neighbors and with the original. Low quality modes simply draw the pixel as a square but high quality modes such as HighQualityBilinear and HighQualityBicubic do considerable averaging and antialiasing of pixels. For the best effect I have found that the HighQualityBilinear mode is best.

The technique relies on drawing the text twice. Once to a shrunken bitmap which represents the halo, this will be expanded to full size using the interpolation mode of choice, and once at full size to create the actual text.  The bitmap which is used to create the halo must be of a specific size ratio to the original text.  In this case I have chosen a ratio of 1:5 so the halo text must be drawn at 1 fifth size. 

Here's how it works:

  1. create a new bitmap that is smaller than your original drawing area by some fixed ratio.  In this case 1/5th.

  2. create a GraphicsPath and had the desired text to it. 

  3. obtain a graphics object for the bitmap and create a matrix that shrinks all drawing output by the chosen ratio. 

  4. Fill the text path using the desired halo color and then, just for good measure, stroke the text path with a pen to provide a little bit of edge to the aura. 

  5. Set the interpolation mode in the destination graphics object to HighQualityBilinear and stretch the bitmap containing the halo using the chosen ratio again. 

  6. Finally, on the destination graphics object, fill the text path without changing the size.  This should register the text correctly with the fuzzy outline of the halo and produce the final effect. 

Using this method I created the effect shown in figure 1.

Figure 1. The text halo in action.

The code which produces this effect his shown in the following listings. 

C#

    private void Form1_Paint(object sender, System.Windows.Forms.PaintEventArgs e)

    {

      //Create a bitmap in a fixed ratio to the original drawing area.

      Bitmap bm=new Bitmap(this.ClientSize.Width/5, this.ClientSize.Height/5);

      //Create a GraphicsPath object. 

      GraphicsPath pth=new GraphicsPath();

      //Add the string in the chosen style. 

      pth.AddString("Text Halo",new FontFamily("Verdana"),(int)FontStyle.Regular,100,new Point(20,20),StringFormat.GenericTypographic);

      //Get the graphics object for the image. 

      Graphics g=Graphics.FromImage(bm);

      //Create a matrix that shrinks the drawing output by the fixed ratio. 

      Matrix mx=new Matrix(1.0f/5,0,0,1.0f/5,-(1.0f/5),-(1.0f/5));

      //Choose an appropriate smoothing mode for the halo. 

      g.SmoothingMode=SmoothingMode.AntiAlias;

      //Transform the graphics object so that the same half may be used for both halo and text output. 

      g.Transform=mx;

      //Using a suitable pen...

      Pen p=new Pen(Color.Yellow,3);

      //Draw around the outline of the path

      g.DrawPath(p,pth);

      //and then fill in for good measure. 

      g.FillPath(Brushes.Yellow,pth);

      //We no longer need this graphics object

      g.Dispose();

      //this just shifts the effect a little bit so that the edge isn't cut off in the demonstration

      e.Graphics.Transform=new Matrix(1,0,0,1,50,50);

      //setup the smoothing mode for path drawing

      e.Graphics.SmoothingMode=SmoothingMode.AntiAlias;

      //and the interpolation mode for the expansion of the halo bitmap

      e.Graphics.InterpolationMode=InterpolationMode.HighQualityBicubic;

      //expand the halo making the edges nice and fuzzy. 

      e.Graphics.DrawImage(bm,ClientRectangle,0,0,bm.Width,bm.Height,GraphicsUnit.Pixel);

      //Redraw the original text

      e.Graphics.FillPath(Brushes.Black,pth);

      //and you're done. 

      pth.Dispose();

    }

 

VB

    Private Sub Form1_Paint(sender As Object, e As System.Windows.Forms.PaintEventArgs) Handles MyBase.Paint

     'Create a bitmap in a fixed ratio to the original drawing area.

     Dim bm As New Bitmap(Me.ClientSize.Width / 5, Me.ClientSize.Height / 5)

     'Create a GraphicsPath object. 

     Dim pth As New GraphicsPath()

     'Add the string in the chosen style. 

     pth.AddString("Text Halo", New FontFamily("Verdana"), CInt(FontStyle.Regular), 100, New Point(20, 20), StringFormat.GenericTypographic)

     'Get the graphics object for the image. 

     Dim g As Graphics = Graphics.FromImage(bm)

     'Create a matrix that shrinks the drawing output by the fixed ratio. 

     Dim mx As New Matrix(1F / 5, 0, 0, 1F / 5, -(1F / 5), -(1F / 5))

     'Choose an appropriate smoothing mode for the halo. 

     g.SmoothingMode = SmoothingMode.AntiAlias

     'Transform the graphics object so that the same half may be used for both halo and text output. 

     g.Transform = mx

     'Using a suitable pen...

     Dim p As New Pen(Color.Yellow, 3)

     'Draw around the outline of the path

     g.DrawPath(p, pth)

     'and then fill in for good measure. 

     g.FillPath(Brushes.Yellow, pth)

     'We no longer need this graphics object

     g.Dispose()

     'this just shifts the effect a little bit so that the edge isn't cut off in the demonstration

     e.Graphics.Transform = New Matrix(1, 0, 0, 1, 50, 50)

     'setup the smoothing mode for path drawing

     e.Graphics.SmoothingMode = SmoothingMode.AntiAlias

     'and the interpolation mode for the expansion of the halo bitmap

     e.Graphics.InterpolationMode = InterpolationMode.HighQualityBicubic

     'expand the halo making the edges nice and fuzzy. 

     e.Graphics.DrawImage(bm, ClientRectangle, 0, 0, bm.Width, bm.Height, GraphicsUnit.Pixel)

     'Redraw the original text

     e.Graphics.FillPath(Brushes.Black, pth)

     'and you're done. 

     pth.Dispose()

    End Sub 'Form1_Paint

 

 

Return to the GDI+ FAQ.

Copyright Robert W. Powell 2004. All rights reserved.