Click here to Skip to main content
Licence CPOL
First Posted 15 Jul 2003
Views 127,363
Bookmarked 48 times

Overlay Text To Fit on Any Image

By | 11 Aug 2004 | Article
Use of MeasureString and DrawString to produce text overlays on any image.

Introduction

Image manipulation in .NET is far simpler than it has been in the past - even VB users get to play with GDI+! This sample shows how to draw semi-transparent text onto an image so that it fills (at least most of) the image area.

New in v.1.2: the core overlay function has been ported to C#. When you run the code in the demo, it will alternate between using the original VB and the C# implementation (for lack of anything better to do).

Background

This sample is built around actual production code that I use to draw the program environment (e.g. Development, QA, etc.) onto the application's splash screen. It could also be used to "rubber stamp" an image, or whatever else you can dream up.

Using the code

The main code is in the function (VB):

Public Function Overlay(ByVal img As Image, ByVal OverlayText As String, _
  ByVal OverlayFont As Font, ByVal OverlayColor As Color, ByVal AddAlpha As Boolean, _
  ByVal AddShadow As Boolean, ByVal Position As Drawing.ContentAlignment, _
  ByVal PercentFill As Single) As Bitmap

OR (C#):

public static Bitmap TextOverlay( Image img,  
  string  OverlayText,  Font OverlayFont,  
  Color OverlayColor,  bool AddAlpha,  bool AddShadow,  
  System.Drawing.ContentAlignment Position,  float PercentFill) 
Where:
  • img is any loaded image reference,
  • OverlayText is the text to draw onto the image,
  • OverlayFont is the font to use (size will be calculated),
  • OverlayColor is the color to use,
  • AddAlpha enables transparency (amount is calculated),
  • AddShadow adds a drop shadow
  • Position sets the text position on the image
  • PercentFill sets the relative fill factor (0-100%)

The function returns a bitmap. The text will wrap (if necessary) and will fill approximately PercentFill of the image's area. When using transparency (alpha), the shorter the text, the greater the transparency.

Points of Interest

Pretty much all the work in the function is simply to determine the correct font size to use. This is done in several steps:

  1. Determine the area required to draw the text as a single line, using initial font size:
    The Code Project: Your Visual Studio .NET Homepage
  2. Estimate a scaling factor by comparing the text area to the image area * PercentFill (default = 80%):
    Scaling Factor = Square Root(80% Image Area / Text Area)
    = Square Root(51725 px2/ 3998 px2) = 3.6
  3. Scale the font by that factor, then measure the text to fit 90% (SQRT(80%)) of the image width, but allow the height to run over. This is necessary because MeasureString will leave off lines if there isn't enough room, and will return only the size used and not the size needed.
    The Code Project:
    Your Visual
    Studio .NET
    Homepage
    <-- Layout too tall for image
  4. Reduce the font size (if necessary) and remeasure until the width and height are within limits.
  5. Once the appropriate size is found, position the layout rectangle on the image and draw:
    The Code Project: Your Visual
    Studio .NET Homepage
    <-- Final layout

At first I was concerned about (in)efficiency, since the function must make an initial guess at the font size, then test to see how well it fits, and adjust until the text will actually fit on the given image. This is because you must measure the string with a specific font size, but the actual area required depends on how well (or not) the text can "flow" into the region -- wrapping to multiple lines when necessary. However, changing the font size often changes how the text wraps, thereby changing the overall area required to print it. In testing, however, I found that the "reduction loop" only rarely took two passes to fit the text, and often the initial estimate did not require adjusting -- especially for long, frequently breaking text (like a sentence). For those who like numbers, various stats are written to the Console when run from the IDE.

Areas of Improvement

  • It would be more interesting to draw the text at an angle (diagonally). Still looking for someone to tackle those calculations!

History

Changes in 1.1
  • Added Positioning and %Fill as suggested by Mike.
  • Added Text Rendering Hint as suggested by Thomas.

Changes in 1.2

  • Added Save As for cliven
  • Added Load from for Bariah
  • Added StringFormat.GenericTypographic to MeasureString( ) for more accurate measurements
  • Moved core function to separate assembly (for easy inclusion in your own solution), AAANNNDDDD
  • Ported core function to C# for all you "purists" out there.

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)

About the Author

GWSyZyGy

Team Leader

United States United States

Member



Sign Up to vote   Poor Excellent
Add a reason or comment to your vote: x
Votes of 3 or less require a comment

Comments and Discussions

 
You must Sign In to use this message board. (secure sign-in)
 
Search this forum  
 FAQ
    Noise  Layout  Per page   
  Refresh
GeneralCan't see text on the image Pinmemberbcodebox5:46 16 Mar '10  
GeneralRe: Can't see text on the image PinmemberGWSyZyGy4:37 18 Mar '10  
GeneralProblem with TIF image PinmemberMember 34054481:46 15 Feb '10  
GeneralOverlay a smaller image on a larger image Pinmemberarsal_shaikh19:23 4 Sep '08  
GeneralRe: Overlay a smaller image on a larger image PinmemberGWSyZyGy6:06 5 Sep '08  
GeneralCarriage Returns PinmemberMrTeQ4:27 23 Aug '07  
GeneralRe: Carriage Returns PinmemberGWSyZyGy6:01 5 Sep '08  
GeneralAnnotation. PinmemberRajesh Dabhi18:57 4 Jun '06  
GeneralRe: Annotation. PinmemberGWSyZyGy5:57 12 Jun '06  
GeneralOverlay outside the main Window Pinmemberffortier18:10 2 Dec '05  
NewsRe: Overlay outside the main Window PinmemberGWSyZyGy11:47 5 Dec '05  
GeneralThanks so much... PinmemberPaul Selormey23:44 28 Jan '05  
GeneralRe: Thanks so much... PinsussGWSyZyGy5:22 31 Jan '05  
Paul,
The Overlay method will use newlines if they are in the text sent. Just change the textbox in the demo to be multiline to test. If, however, you want the text to only break at your newlines, you need to add a flag to the following line:
strFormat.FormatFlags = StringFormatFlags.NoClip | StringFormatFlags.NoWrap; // add NoWrap to preserve layout.
 
You'll also need to widen the initial rectangle, or you can end up clipping (even with the NoClip flag).
 
Tabs, unfortunately, are not as easily supported. If the tabs are always at the beginning of a line (like paragraph indention), then you can just replace them with 3 or 4 spaces to simulate a tab.
 
What you're *supposed* to do is use the SetTabStops() method:
strFormat.SetTabStops(0F, new float[] {60F});
 
However, you may need to play with the values and maybe even base them off the calculated font size to get good results. In fact, until I added NoWrap, I couldn't get the tabs to show at all, and afterwards, the values I used didn't seem to have any effect. Confused | :confused: There's not a lot of info on SetTabStops().
 
HTH
GeneralRe: Thanks so much... PinmemberPaul Selormey5:52 31 Jan '05  
GeneralRe: Thanks so much... PinmemberTim McCurdy5:58 19 Sep '05  
Generalnice article! Pinmembervpas17:57 6 Jan '05  
GeneralNon Destructive Text Overlay Pinsussdavemc75914:56 16 Sep '04  
GeneralRe: Non Destructive Text Overlay PinsussGWSyZyGy4:53 17 Sep '04  
Generalload image PinsussBariah16:19 4 Aug '04  
GeneralRe: load image PinsussGWSyZyGy5:49 9 Aug '04  
GeneralThe Image is Dirty Pinmembercliven23:40 14 Jun '04  
GeneralRe: The Image is Dirty PinsussGWSyZyGy4:12 15 Jun '04  
GeneralRe: The Image is Dirty Pinmembercliven15:36 15 Jun '04  
GeneralAnti Alias Pinmemberfanell9:27 18 Sep '03  
GeneralNext step: add positioning! Pinmembernzmike12:53 23 Jul '03  

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.

Permalink | Advertise | Privacy | Mobile
Web04 | 2.5.120528.1 | Last Updated 12 Aug 2004
Article Copyright 2003 by GWSyZyGy
Everything else Copyright © CodeProject, 1999-2012
Terms of Use
Layout: fixed | fluid