.. _Basic/CreateAnnotation: 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 :class:`~Draft.AnnotationInfo` object as is, the text image will use the default values: :attr:`PointSize`: 32 :attr:`FontType`: SourceSansPro-Regular :attr:`Padding`: 0.0 :attr:`Color`: white :attr:`BackgroundColor`: transparent :attr:`DrawShadow`: false :attr:`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 :attr:`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 :meth:`~Draft.Image.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 (:attr:`Color`), background (:attr:`BackgroundColor`), and shadow (:attr:`ShadowColor`) can be changed by creating a new :class:`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 :class:`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 :attr:`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 :meth:`~Draft.Image.CreateAnnotation` to create an image containing the text we want, in this case, "My ball!!!". :meth:`~Draft.Image.CreateAnnotation` saves the annotation as an image, which we can then composite over our photo using one of the three composite methods: :meth:`~Draft.Image.Composite`, :meth:`~Draft.Image.CompositeWithAnchor`, and :meth:`~Draft.Image.CompositeWithPositionAndAnchor`. In this case, we have chosen to use :meth:`~Draft.Image.CompositeWithPositionAndAnchor`. After the call to :meth:`~Draft.Image.CreateAnnotation`, we have our photo in the variable ``img``, and the text in the variable textImg. :meth:`~Draft.Image.CompositeWithPositionAndAnchor` is an instance method, meaning that we call it on an :class:`~Draft.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; :const:`Draft.Anchor.South` indicates that the anchor point corresponds to the bottom center of ``textImg``, and :const:`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 :ref:`Basic/CompositeTwoImages`. For more information on the ``import`` statement, :meth:`~Draft.Image.ReadFromFile`, and :meth:`~Draft.Image.WriteToFile`, see the :ref:`Basic/CreateAnImage` section of this cookbook.