Create Text Annotation

Problem

You wish to add some text, “My ball!!!”, to your image, ‘Patches with ball.jpg’.

Solution

import Draft

img = Draft.Image.ReadFromFile( 'Patches with ball.jpg' )

textInfo = Draft.AnnotationInfo()
textImage = Draft.Image.CreateAnnotation( "My ball!!!", textInfo )

anchor = Draft.Anchor.South
compOp = Draft.CompositeOperator.OverCompositeOp
img.CompositeWithPositionAndAnchor( textImage, 0.5, 0.1, anchor, compOp )

img.WriteToFile( 'Patches with ball (annotated).jpg' )

Discussion

There are three steps to adding text in this solution: getting the annotation information, creating an image that contains the text, and adding the text image to the photo.

The annotation information stores the properties, such as font, point size, colour, and more. If we use the AnnotationInfo object as is, the text image will use the default values:

PointSize: 32

FontType: SourceSansPro-Regular

Padding: 0.0

Color: white

BackgroundColor: transparent

DrawShadow: false

ShadowColor: black

However, we can also customize any of the above settings.

PointSize:

The point size is measured in pixels. If your image resolution is 72 ppi, the default point size will give you text that is nearly half an inch tall. However, if your image resolution is, say, 300 ppi, the text will only be a tenth of an inch tall. To make sure the text is the height you want it, be sure to set the point size after creating the annotation info, but before using it to create the text image:

text_height_inches = 0.5
ppi = 300
textInfo.PointSize = int( text_height_inches * ppi )

Since PointSize expects an integer, we need to use the int() function to convert text_height_inches * ppi from floating point to an integer.

FontType:

The font type specifies both which font, and which style (bold, italic, etc) to use for the text. The default font is set to Adobe’s Source Sans Pro (regular) font. However, you can use any font contained in your type.xml file, or any font not in type.xml as long as you specify the full path to the font file:

textInfo.FontType = 'Times-New-Roman-Bold'  # Using the name field value from type.xml

or:

textInfo.FontType = r'C:\Windows\Fonts\timesbi.ttf'  # Specifying location of glyphs

Troubleshooting: If you get an error message when trying to use the default font, make sure the MAGICK_FONT_PATH environment variable is set to the Draft subdirectory containing SourceSansPro-Regular.otf.

Padding:

Padding specifies how much empty space to leave around the text in the image that is created using CreateAnnotation(). The padding is multiplied by the point size to get the measurement in pixels, so a padding of 1.0 with the default point size gives 32 pixels of space around the text.

Color:

The colors of the text (Color), background (BackgroundColor), and shadow (ShadowColor) can be changed by creating a new Draft.ColorRGBA object and performing the appropriate assignment. For example, to make the text dark red:

textInfo.Color = Draft.ColorRGBA( 0.5, 0.0, 0.0, 1.0)

The four parameters to Draft.ColorRGBA are the values to use for red, green, blue, and alpha, in that order. Values for these channels are normally in the range 0.0 to 1.0.

DrawShadow:

A shadow will be drawn for the text if DrawShadow is set to true:

textInfo.DrawShadow = True

Adding some of our customizations to the simple solution, we get:

import Draft

img = Draft.Image.ReadFromFile( 'Patches with ball.jpg' )

textInfo = Draft.AnnotationInfo()
text_height_inches = 0.5
ppi = 300
textInfo.PointSize = int( text_height_inches * ppi )
textInfo.FontType = 'Times-New-Roman-Bold-Italic'       # Using 'name' from type.xml
textInfo.Color = Draft.ColorRGBA( 0.5, 0.0, 0.0, 1.0)
textInfo.DrawShadow = True

textImage = Draft.Image.CreateAnnotation( "My ball!!!", textInfo )
anchor = Draft.Anchor.South
compOp = Draft.CompositeOperator.OverCompositeOp
img.CompositeWithPositionAndAnchor( textImage, 0.5, 0.1, anchor, compOp )

img.WriteToFile( 'Patches with ball (annotated).jpg' )

After the annotation information is set how we want it, we can use it in the call to CreateAnnotation() to create an image containing the text we want, in this case, “My ball!!!”. CreateAnnotation() saves the annotation as an image, which we can then composite over our photo using one of the three composite methods: Composite(), CompositeWithAnchor(), and CompositeWithPositionAndAnchor(). In this case, we have chosen to use CompositeWithPositionAndAnchor().

After the call to CreateAnnotation(), we have our photo in the variable img, and the text in the variable textImg. CompositeWithPositionAndAnchor() is an instance method, meaning that we call it on an Image instance, in this case, img. The photo in img will be modified, which is why we do not need to assign a return value to another variable. The second image, textImg, is passed as an argument to the method. The remaining arguments specify how we wish the second image to be composited with the first: 0.5 and 0.1 specify that we want the anchor point to be located half way across img, and 10% up from the bottom; Draft.Anchor.South indicates that the anchor point corresponds to the bottom center of textImg, and Draft.CompositeOperator.OverCompositeOp indicates to place textImg over img. Since the background of textImg is transparent by default, we will be able to see our photograph wherever there is neither text nor shadow.

See Also

For more information on the other two composite methods and the various composite operations, see the section Composite Two Images.

For more information on the import statement, ReadFromFile(), and WriteToFile(), see the Creating an Image section of this Cookbook.