Manage PowerPoint Paragraph in Python
Aspose.Slides provides all the interfaces and classes you need to work with PowerPoint texts, paragraphs, and portions in Python.
- Aspose.Slides provides the ITextFrame interface to allow you to add objects that represent a paragraph. An
ITextFame
object can have one or multiple paragraphs (each paragraph is created through a carriage return). - Aspose.Slides provides the IParagraph interface to allow you to add objects that represent portions. An
IParagraph
object can have one or multiple portions (collection of iPortions objects). - Aspose.Slides provides IPortion interface to allow you to add objects that represent texts and their formatting properties.
An IParagraph
object is capable of handling texts with different formatting properties through its underlying IPortion
objects.
Add Multiple Paragraph Containing Multiple Portions
These steps show you how to add a text frame containing 3 paragraphs and each paragraph containing 3 portions:
- Create an instance of the Presentation class.
- Access the relevant slide’s reference through its index.
- Add a Rectangle IAutoShape to the slide.
- Get the ITextFrame associated with the IAutoShape.
- Create two IParagraph objects and add them to the
IParagraphs
collection of the ITextFrame. - Create three IPortion objects for each new
IParagraph
(two Portion objects for default Paragraph) and add eachIPortion
object to the IPortion collection of eachIParagraph
. - Set some text for each portion.
- Apply your preferred formatting features to each portion using the formatting properties exposed by the
IPortion
object. - Save the modified presentation.
This Python code is an implementation of the steps for adding paragraphs containing portions:
import aspose.slides as slides
import aspose.pydrawing as draw
# Instantiate a Presentation class that represents a PPTX file
with slides.Presentation() as pres:
# Accessing first slide
slide = pres.slides[0]
# Add an AutoShape of Rectangle type
ashp = slide.shapes.add_auto_shape(slides.ShapeType.RECTANGLE, 50, 150, 300, 150)
# Access TextFrame of the AutoShape
tf = ashp.text_frame
# Create Paragraphs and Portions with different text formats
para0 = tf.paragraphs[0]
port01 = slides.Portion()
port02 = slides.Portion()
para0.portions.add(port01)
para0.portions.add(port02)
para1 = slides.Paragraph()
tf.paragraphs.add(para1)
port10 = slides.Portion()
port11 = slides.Portion()
port12 = slides.Portion()
para1.portions.add(port10)
para1.portions.add(port11)
para1.portions.add(port12)
para2 = slides.Paragraph()
tf.paragraphs.add(para2)
port20 = slides.Portion()
port21 = slides.Portion()
port22 = slides.Portion()
para2.portions.add(port20)
para2.portions.add(port21)
para2.portions.add(port22)
for i in range(3):
for j in range(3):
tf.paragraphs[i].portions[j].text = "Portion0" + str(j)
if j == 0:
tf.paragraphs[i].portions[j].portion_format.fill_format.fill_type = slides.FillType.SOLID
tf.paragraphs[i].portions[j].portion_format.fill_format.solid_fill_color.color = draw.Color.red
tf.paragraphs[i].portions[j].portion_format.font_bold = 1
tf.paragraphs[i].portions[j].portion_format.font_height = 15
elif j == 1:
tf.paragraphs[i].portions[j].portion_format.fill_format.fill_type = slides.FillType.SOLID
tf.paragraphs[i].portions[j].portion_format.fill_format.solid_fill_color.color = draw.Color.blue
tf.paragraphs[i].portions[j].portion_format.font_italic = 1
tf.paragraphs[i].portions[j].portion_format.font_height = 18
# Write PPTX to Disk
pres.save("multiParaPort_out.pptx", slides.export.SaveFormat.PPTX)
Manage Paragraph Bullets
Bullet lists help you to organize and present information quickly and efficiently. Bulleted paragraphs are always easier to read and understand.
- Create an instance of the Presentation class.
- Access the relevant slide’s reference through its index.
- Add an autoshape to the selected slide.
- Access the autoshape’s TextFrame.
- Remove the default paragraph in the
TextFrame
. - Create the first paragraph instance using the Paragraph class.
- Set the bullet
Type
for the paragraph toSymbol
and set the bullet character. - Set the paragraph
Text
. - Set the paragraph
Indent
for the bullet. - Set a color for the bullet.
- Set a height of the bullet.
- Add the new paragraph to the
TextFrame
paragraph collection. - Add the second paragraph and repeat the process given in steps 7 to 13.
- Save the presentation.
This Python code shows you how to add a paragraph bullet:
import aspose.slides as slides
import aspose.pydrawing as draw
# Creating a presenation instance
with slides.Presentation() as pres:
# Accessing the first slide
slide = pres.slides[0]
# Adding and accessing Autoshape
aShp = slide.shapes.add_auto_shape(slides.ShapeType.RECTANGLE, 200, 200, 400, 200)
# Accessing the text frame of created autoshape
txtFrm = aShp.text_frame
# Removing the default exisiting paragraph
txtFrm.paragraphs.remove_at(0)
# Creating a paragraph
para = slides.Paragraph()
# Setting paragraph bullet style and symbol
para.paragraph_format.bullet.type = slides.BulletType.SYMBOL
para.paragraph_format.bullet.char = chr(8226)
# Setting paragraph text
para.text = "Welcome to Aspose.Slides"
# Setting bullet indent
para.paragraph_format.indent = 25
# Setting bullet color
para.paragraph_format.bullet.color.color_type = slides.ColorType.RGB
para.paragraph_format.bullet.color.color = draw.Color.black
para.paragraph_format.bullet.is_bullet_hard_color = 1
# Setting bullet Height
para.paragraph_format.bullet.height = 100
# Adding Paragraph to text frame
txtFrm.paragraphs.add(para)
# Creating second paragraph
para2 = slides.Paragraph()
# Setting paragraph bullet type and style
para2.paragraph_format.bullet.type = slides.BulletType.NUMBERED
para2.paragraph_format.bullet.numbered_bullet_style = slides.NumberedBulletStyle.BULLET_CIRCLE_NUM_WDBLACK_PLAIN
# Adding paragraph text
para2.text = "This is numbered bullet"
# Setting bullet indent
para2.paragraph_format.indent = 25
para2.paragraph_format.bullet.color.color_type = slides.ColorType.RGB
para2.paragraph_format.bullet.color.color = draw.Color.black
para2.paragraph_format.bullet.is_bullet_hard_color = 1
# Setting bullet Height
para2.paragraph_format.bullet.height = 100
# Adding Paragraph to text frame
txtFrm.paragraphs.add(para2)
#Writing the presentation as a PPTX file
pres.save("bullet_out.pptx", slides.export.SaveFormat.PPTX)
Manage Picture Bullets
Bullet lists help you to organize and present information quickly and efficiently. Picture paragraphs are easy to read and understand.
- Create an instance of the Presentation class.
- Access the relevant slide’s reference through its index.
- Add an autoshape to the slide.
- Access the autoshape’s TextFrame.
- Remove the default paragraph in the
TextFrame
. - Create the first paragraph instance using the Paragraph class.
- Load the image in IPPImage.
- Set the bullet type to Picture and set the image.
- Set the Paragraph
Text
. - Set the Paragraph
Indent
for the bullet. - Set a color for the bullet.
- Set a height for the bullet.
- Add the new paragraph to the
TextFrame
paragraph collection. - Add the second paragraph and repeat the process based on the previous steps.
- Save the modified presentation.
This Python code shows you how to add and manage picture bullets:
import aspose.slides as slides
import aspose.pydrawing as draw
with slides.Presentation() as presentation:
# Accessing the first slide
slide = presentation.slides[0]
# Instantiate the image for bullets
image = draw.Bitmap(path + "bullets.png")
ippxImage = presentation.images.add_image(image)
# Adding and accessing Autoshape
autoShape = slide.shapes.add_auto_shape(slides.ShapeType.RECTANGLE, 200, 200, 400, 200)
# Accessing the text frame of created autoshape
textFrame = autoShape.text_frame
# Removing the default exisiting paragraph
textFrame.paragraphs.remove_at(0)
# Creating new paragraph
paragraph = slides.Paragraph()
paragraph.text = "Welcome to Aspose.Slides"
# Setting paragraph bullet style and image
paragraph.paragraph_format.bullet.type = slides.BulletType.PICTURE
paragraph.paragraph_format.bullet.picture.image = ippxImage
# Setting Bullet Height
paragraph.paragraph_format.bullet.height = 100
# Adding Paragraph to text frame
textFrame.paragraphs.add(paragraph)
# Writing the presentation as a PPTX file
presentation.save("ParagraphPictureBulletsPPTX_out.pptx", slides.export.SaveFormat.PPTX)
# Writing the presentation as a PPT file
presentation.save("ParagraphPictureBulletsPPT_out.ppt", slides.export.SaveFormat.PPT)
Manage Multilevel Bullets
Bullet lists help you to organize and present information quickly and efficiently. Multilevel bullets are easy to read and understand.
- Create an instance of the Presentation class.
- Access the relevant slide’s reference through its index.
- Add an autoshape in the new slide.
- Access the autoshape’s TextFrame.
- Remove the default paragraph in the
TextFrame
. - Create the first paragraph instance through the Paragraph class and set the depth to 0.
- Create the second paragraph instance through the
Paragraph
class and set the depth set to 1. - Create the third paragraph instance through the
Paragraph
class and set the depth set to 2. - Create the fourth paragraph instance through the
Paragraph
class and set the depth set to 3. - Add the new paragraphs to the
TextFrame
paragraph collection. - Save the modified presentation.
This Python code shows you how to add and manage multilevel bullets:
import aspose.slides as slides
import aspose.pydrawing as draw
# Creating a presenation instance
with slides.Presentation() as pres:
# Accessing the first slide
slide = pres.slides[0]
# Adding and accessing Autoshape
aShp = slide.shapes.add_auto_shape(slides.ShapeType.RECTANGLE, 200, 200, 400, 200)
# Accessing the text frame of created autoshape
text = aShp.add_text_frame("")
#clearing default paragraph
text.paragraphs.clear()
#Adding first paragraph
para1 = slides.Paragraph()
para1.text = "Content"
para1.paragraph_format.bullet.type = slides.BulletType.SYMBOL
para1.paragraph_format.bullet.char = chr(8226)
para1.paragraph_format.default_portion_format.fill_format.fill_type = slides.FillType.SOLID
para1.paragraph_format.default_portion_format.fill_format.solid_fill_color.color = draw.Color.black
#Setting bullet level
para1.paragraph_format.depth = 0
#Adding second paragraph
para2 = slides.Paragraph()
para2.text = "Second Level"
para2.paragraph_format.bullet.type = slides.BulletType.SYMBOL
para2.paragraph_format.bullet.char = '-'
para2.paragraph_format.default_portion_format.fill_format.fill_type = slides.FillType.SOLID
para2.paragraph_format.default_portion_format.fill_format.solid_fill_color.color = draw.Color.black
#Setting bullet level
para2.paragraph_format.depth = 1
#Adding third paragraph
para3 = slides.Paragraph()
para3.text = "Third Level"
para3.paragraph_format.bullet.type = slides.BulletType.SYMBOL
para3.paragraph_format.bullet.char = chr(8226)
para3.paragraph_format.default_portion_format.fill_format.fill_type = slides.FillType.SOLID
para3.paragraph_format.default_portion_format.fill_format.solid_fill_color.color = draw.Color.black
#Setting bullet level
para3.paragraph_format.depth = 2
#Adding fourth paragraph
para4 = slides.Paragraph()
para4.text = "Fourth Level"
para4.paragraph_format.bullet.type = slides.BulletType.SYMBOL
para4.paragraph_format.bullet.char = '-'
para4.paragraph_format.default_portion_format.fill_format.fill_type = slides.FillType.SOLID
para4.paragraph_format.default_portion_format.fill_format.solid_fill_color.color = draw.Color.black
#Setting bullet level
para4.paragraph_format.depth = 3
#Adding paragraphs to collection
text.paragraphs.add(para1)
text.paragraphs.add(para2)
text.paragraphs.add(para3)
text.paragraphs.add(para4)
#Writing the presentation as a PPTX file
pres.save("MultilevelBullet.pptx", slides.export.SaveFormat.PPTX)
Manage Paragraph with Custom Numbered List
The IBulletFormat interface provides the NumberedBulletStartWith
property and others that allow you to manage paragraphs with custom numbering or formatting.
- Create an instance of the Presentation class.
- Access the slide containing the paragraph.
- Add an autoshape to the slide.
- Access the autoshape TextFrame.
- Remove the default paragraph in the
TextFrame
. - Create the first paragraph instance through the Paragraph class and set
NumberedBulletStartWith
to 2. - Create the second paragraph instance through the
Paragraph
class and setNumberedBulletStartWith
to 3. - Create the third paragraph instance through the
Paragraph
class and setNumberedBulletStartWith
to 7. - Add the new paragraphs to the
TextFrame
paragraph collection. - Save the modified presentation.
This Python code shows you how to add and manage paragraphs with custom numbering or formatting:
import aspose.slides as slides
with slides.Presentation() as presentation:
shape = presentation.slides[0].shapes.add_auto_shape(slides.ShapeType.RECTANGLE, 200, 200, 400, 200)
# Accessing the text frame of created autoshape
textFrame = shape.text_frame
# Removing the default exisiting paragraph
textFrame.paragraphs.remove_at(0)
# First list
paragraph1 = slides.Paragraph()
paragraph1.text = "bullet 2"
paragraph1.paragraph_format.depth = 4
paragraph1.paragraph_format.bullet.numbered_bullet_start_with = 2
paragraph1.paragraph_format.bullet.type = slides.BulletType.NUMBERED
textFrame.paragraphs.add(paragraph1)
paragraph2 = slides.Paragraph()
paragraph2.text = "bullet 3"
paragraph2.paragraph_format.depth = 4
paragraph2.paragraph_format.bullet.numbered_bullet_start_with = 3
paragraph2.paragraph_format.bullet.type = slides.BulletType.NUMBERED
textFrame.paragraphs.add(paragraph2)
paragraph5 = slides.Paragraph()
paragraph5.text = "bullet 7"
paragraph5.paragraph_format.depth = 4
paragraph5.paragraph_format.bullet.numbered_bullet_start_with = 7
paragraph5.paragraph_format.bullet.type = slides.BulletType.NUMBERED
textFrame.paragraphs.add(paragraph5)
presentation.save("SetCustomBulletsNumber-slides.pptx", slides.export.SaveFormat.PPTX)
Set Paragraph Indent
- Create an instance of Presentation class.
- Access the relevant slide’s reference through its index.
- Add a rectangle autoshape to the slide.
- Add a TextFrame with three paragraphs to the rectangle autoshape.
- Hide the rectangle lines.
- Set the indent for each Paragraph through their BulletOffset property.
- Write the modified presentation as a PPT file.
This Python code shows you how to set a paragraph indent:
import aspose.slides as slides
# Instantiate Presentation Class
with slides.Presentation() as pres:
# Get first slide
sld = pres.slides[0]
# Add a Rectangle Shape
rect = sld.shapes.add_auto_shape(slides.ShapeType.RECTANGLE, 100, 100, 500, 150)
# Add TextFrame to the Rectangle
tf = rect.add_text_frame("This is first line \rThis is second line \rThis is third line")
# Set the text to fit the shape
tf.text_frame_format.autofit_type = slides.TextAutofitType.SHAPE
# Hide the lines of the Rectangle
rect.line_format.fill_format.fill_type = slides.FillType.SOLID
# Get first Paragraph in the TextFrame and set its Indent
para1 = tf.paragraphs[0]
# Setting paragraph bullet style and symbol
para1.paragraph_format.bullet.type = slides.BulletType.SYMBOL
para1.paragraph_format.bullet.char = chr(8226)
para1.paragraph_format.alignment = slides.TextAlignment.LEFT
para1.paragraph_format.depth = 2
para1.paragraph_format.indent = 30
# Get second Paragraph in the TextFrame and set its Indent
para2 = tf.paragraphs[1]
para2.paragraph_format.bullet.type = slides.BulletType.SYMBOL
para2.paragraph_format.bullet.char = chr(8226)
para2.paragraph_format.alignment = slides.TextAlignment.LEFT
para2.paragraph_format.depth = 2
para2.paragraph_format.indent = 40
# Get third Paragraph in the TextFrame and set its Indent
para3 = tf.paragraphs[2]
para3.paragraph_format.bullet.type = slides.BulletType.SYMBOL
para3.paragraph_format.bullet.char = chr(8226)
para3.paragraph_format.alignment = slides.TextAlignment.LEFT
para3.paragraph_format.depth = 2
para3.paragraph_format.indent = 50
#Write the Presentation to disk
pres.save("InOutDent_out.pptx", slides.export.SaveFormat.PPTX)
Set Hanging Indent for Paragraph
This Python code shows you how to set the hanging indent for a paragraph:
import aspose.slides as slides
with slides.Presentation() as pres:
auto_shape = pres.slides[0].shapes.add_auto_shape(slides.ShapeType.RECTANGLE, 50, 250, 550, 150)
para1 = slides.Paragraph()
para1.text = "Example"
para2 = slides.Paragraph()
para2.text = "Set Hanging Indent for Paragraph"
para3 = slides.Paragraph()
para3.text = "This C# code shows you how to set the hanging indent for a paragraph: "
para2.paragraph_format.margin_left = 10
para3.paragraph_format.margin_left = 20
paragraphs = auto_shape.text_frame.paragraphs
paragraphs.add(para1)
paragraphs.add(para2)
paragraphs.add(para3)
pres.save("pres.pptx", slides.export.SaveFormat.PPTX)
Manage End Paragraph Run Properties for Paragraph
- Create an instance of Presentation class.
- Get the reference for the slide containing the paragraph through its position.
- Add a rectangle autoshape to the slide.
- Add a TextFrame with two paragraphs to the Rectangle.
- Set the
FontHeight
and Font type for the paragraphs. - Set the End properties for the paragraphs.
- Write the modified presentation as a PPTX file.
This Python code shows you how to set the End properties for paragraphs in PowerPoint:
import aspose.slides as slides
with slides.Presentation("pres.pptx") as pres:
shape = pres.slides[0].shapes.add_auto_shape(slides.ShapeType.RECTANGLE, 10, 10, 200, 250)
para1 = slides.Paragraph()
para1.portions.add(slides.Portion("Sample text"))
para2 = slides.Paragraph()
para2.portions.add(slides.Portion("Sample text 2"))
endParagraphPortionFormat = slides.PortionFormat()
endParagraphPortionFormat.font_height = 48
endParagraphPortionFormat.latin_font = slides.FontData("Times New Roman")
para2.end_paragraph_portion_format = endParagraphPortionFormat
shape.text_frame.paragraphs.add(para1)
shape.text_frame.paragraphs.add(para2)
pres.save("pres.pptx", slides.export.SaveFormat.PPTX)
Import HTML Text into Paragraphs
Aspose.Slides provides enhanced support for importing HTML text into paragraphs.
- Create an instance of the Presentation class.
- Access the relevant slide’s reference through its index.
- Add an autoshape to the slide.
- Add and access
autoshape
ITextFrame. - Remove the default paragraph in the
ITextFrame
. - Read the source HTML file in a TextReader.
- Create the first paragraph instance through the Paragraph class.
- Add the HTML file content in the read TextReader to the TextFrame’s ParagraphCollection.
- Save the modified presentation.
This Python code is an implementation of the steps for importing HTML texts in paragraphs:
import aspose.slides as slides
# Create Empty presentation instance# Create Empty presentation instance
with slides.Presentation() as pres:
# Acesss the default first slide of presentation
slide = pres.slides[0]
# Adding the AutoShape to accomodate the HTML content
ashape = slide.shapes.add_auto_shape(slides.ShapeType.RECTANGLE, 10, 10, pres.slide_size.size.width - 20, pres.slide_size.size.height - 10)
ashape.fill_format.fill_type = slides.FillType.NO_FILL
# Adding text frame to the shape
ashape.add_text_frame("")
# Clearing all paragraphs in added text frame
ashape.text_frame.paragraphs.clear()
# Loading the HTML file using stream reader
with open(path + "file.html", "rt") as tr:
# Adding text from HTML stream reader in text frame
ashape.text_frame.paragraphs.add_from_html(tr.read())
# Saving Presentation
pres.save("output_out.pptx", slides.export.SaveFormat.PPTX)
Export Paragraphs Text to HTML
Aspose.Slides provides enhanced support for exporting texts (contained in paragraphs) to HTML.
- Create an instance of the Presentation class and load the desired presentation.
- Access the relevant slide’s reference through its index.
- Access the shape containing the text that will be exported to HTML.
- Access the shape TextFrame.
- Create an instance of
StreamWriter
and add the new HTML file. - Provide a starting index to StreamWriter and export your preferred paragraphs.
This Python code shows you how to export PowerPoint paragraph texts to HTML:
import aspose.slides as slides
# Load the presentation file
with slides.Presentation(path + "ExportingHTMLText.pptx") as pres:
# Acesss the default first slide of presentation
slide = pres.slides[0]
# Desired index
index = 0
# Accessing the added shape
ashape = slide.shapes[index]
with open("output_out.html", "w") as sw:
# Writing Paragraphs data to HTML by providing paragraph starting index, total paragraphs to be copied
sw.write(ashape.text_frame.paragraphs.export_to_html(0, ashape.text_frame.paragraphs.count, None))
Save a Paragraph as an Image
In this section, we will explore two examples that demonstrate how to save a text paragraph, represented by the Paragraph class, as an image. Both examples include obtaining the image of a shape containing the paragraph using the get_image
methods from the Shape class, calculating the bounds of the paragraph within the shape, and exporting it as a bitmap image. These approaches allow you to extract specific parts of the text from PowerPoint presentations and save them as separate images, which can be useful for further use in various scenarios.
Let’s assume we have a presentation file called sample.pptx with one slide, where the first shape is a text box containing three paragraphs.
Example 1
In this example, we obtain the second paragraph as an image. To do this, we extract the image of the shape from the first slide of the presentation and then calculate the bounds of the second paragraph in the shape’s text frame. The paragraph is then redrawn onto a new bitmap image, which is saved in PNG format. This method is especially useful when you need to save a specific paragraph as a separate image while preserving the exact dimensions and formatting of the text.
import aspose.slides as slides
import math
import io
from PIL import Image
with slides.Presentation("sample.pptx") as presentation:
first_shape = presentation.slides[0].shapes[0]
# Save the shape in memory as a bitmap.
with first_shape.get_image() as shape_image:
shape_image_stream = io.BytesIO()
shape_image.save(shape_image_stream, slides.ImageFormat.PNG)
# Create a shape bitmap from memory.
shape_image_stream.seek(0)
shape_bitmap = Image.open(shape_image_stream)
# Calculate the boundaries of the second paragraph.
second_paragraph = first_shape.text_frame.paragraphs[1]
paragraph_rectangle = second_paragraph.get_rect()
# Calculate the coordinates and size for the output image (minimum size - 1x1 pixel).
image_left = math.floor(paragraph_rectangle.x)
image_top = math.floor(paragraph_rectangle.y)
image_right = image_left + max(1, math.ceil(paragraph_rectangle.width))
image_bottom = image_top + max(1, math.ceil(paragraph_rectangle.height))
# Crop the shape bitmap to get the paragraph bitmap only.
paragraph_bitmap = shape_bitmap.crop((image_left, image_top, image_right, image_bottom))
paragraph_bitmap.save("paragraph.png")
The result:
Example 2
In this example, we extend the previous approach by adding scaling factors to the paragraph image. The shape is extracted from the presentation and saved as an image with a scaling factor of 2
. This allows for a higher resolution output when exporting the paragraph. The paragraph bounds are then calculated considering the scale. Scaling can be particularly useful when a more detailed image is needed, for example, for use in high-quality printed materials.
import aspose.slides as slides
import math
import io
from PIL import Image
image_scale_x = 2
image_scale_y = image_scale_x
with slides.Presentation("sample.pptx") as presentation:
first_shape = presentation.slides[0].shapes[0]
# Save the shape in memory as a bitmap.
with first_shape.get_image(slides.ShapeThumbnailBounds.SHAPE, image_scale_x, image_scale_y) as shape_image:
shape_image_stream = io.BytesIO()
shape_image.save(shape_image_stream, slides.ImageFormat.PNG)
# Create a shape bitmap from memory.
shape_image_stream.seek(0)
shape_bitmap = Image.open(shape_image_stream)
# Calculate the boundaries of the second paragraph.
second_paragraph = first_shape.text_frame.paragraphs[1]
paragraph_rectangle = second_paragraph.get_rect()
paragraph_rectangle.x *= image_scale_x
paragraph_rectangle.y *= image_scale_y
paragraph_rectangle.width *= image_scale_x
paragraph_rectangle.height *= image_scale_y
# Calculate the coordinates and size for the output image (minimum size - 1x1 pixel).
image_left = math.floor(paragraph_rectangle.x)
image_top = math.floor(paragraph_rectangle.y)
image_right = image_left + max(1, math.ceil(paragraph_rectangle.width))
image_bottom = image_top + max(1, math.ceil(paragraph_rectangle.height))
# Crop the shape bitmap to get the paragraph bitmap only.
paragraph_bitmap = shape_bitmap.crop((image_left, image_top, image_right, image_bottom))
paragraph_bitmap.save("paragraph.png")