Drawing Images using Graphics
Drawing Images using Graphics
With the Aspose.Imaging library you can draw simple shapes like lines, rectangles and circles, as well as complex shapes like polygons, curves, arcs and Bezier shapes. Aspose.Imaging library creates such shapes using Graphics class that resides in the aspose.imaging namespace. Graphics objects are responsible for performing different drawing operations on an image, thus changing the image’s surface. The Graphics class uses a variety of helper objects to enhance the shapes:
- Pens, to draw lines, outline shapes, or render other geometric representations.
- Brushes, to define how areas are filled in.
- Fonts, to define the shape of characters of text.
Drawing with the Graphics Class
Below is a code example demonstrating the use of the Graphics class. The example source code has been split into several parts to keep it simple and easy to follow. Step by step, the examples show how to:
- Create an image.
- Create and initialize a Graphics object.
- Clear the surface.
- Draw an ellipse.
- Draw a filled polygon and save the image.
Programming Samples
Creating an Image
Start by creating an image using any of the methods described in Creating Files.
Create and Initialize a Graphics Object
Then create and initialize a Graphics object by passing the Image object to its constructor.
Clear the Surface
Clear the Graphics surface by calling the Graphics class clear method and pass a color as a parameter. This method fills the Graphics surface with the color passed in as argument.
Draw an Ellipse
You may notice that the Graphics class has exposed plenty of methods to draw and fill shapes. You’ll find get the complete list of methods in the Aspose.Imaging for Python via .NET API Reference. There are several overloaded versions of the draw_ellipse method exposed by the Graphics class. All these methods accept a Pen object as its first argument. The later parameters are passed to define the bounding rectangle around the ellipse. For the sake of this example, use the version accepting a Rectangle object as the second parameter to draw an ellipse using the Pen object in your desired color.
Draw a Filled Polygon
Next, draw a polygon using the LinearGradientBrush and an array of points. The Graphics class has exposed several overloaded versions of the fill_polygon() method. All of these accept a Brush object as its first argument, defining the characteristics of the fill. The second parameter is an array of points. Please note that every two consecutive points in the array specify a side of the polygon.
import aspose.pycore as aspycore | |
from aspose.imaging import Image, Graphics, Rectangle, Point, Color, Point | |
from aspose.imaging.brushes import SolidBrush | |
from aspose.imaging.fileformats.bmp import * | |
import os | |
if 'TEMPLATE_DIR' in os.environ: | |
templates_folder = os.environ['TEMPLATE_DIR'] | |
else: | |
templates_folder = r"C:\Users\USER\Downloads\templates" | |
delete_output = 'SAVE_OUTPUT' not in os.environ | |
data_dir = templates_folder | |
with Image.load(os.path.join(data_dir, "template.bmp")) as image: | |
# Create and initialize an instance of Graphics class | |
graphic = Graphics(image) | |
graphic.fill_rectangle(SolidBrush(Color.green), Rectangle(0, 0, 100, 100)) | |
graphic.fill_polygon_by_point(SolidBrush(Color.green), [Point(0, 0), Point(100, 100), Point(10, 10)]) | |
image.save(os.path.join(data_dir, "result.bmp")) | |
if delete_output: | |
os.remove(os.path.join(data_dir, "result.bmp")) |
Measure string using Aspose.Graphics
Aspose.Imaging Graphics supports method to measure string. Here the sample code for it is provided.
import aspose.pycore as aspycore | |
from aspose.imaging import Image, Graphics, Font, Color, StringFormat, SizeF, PointF | |
from aspose.imaging.brushes import SolidBrush | |
import os | |
if 'TEMPLATE_DIR' in os.environ: | |
templates_folder = os.environ['TEMPLATE_DIR'] | |
else: | |
templates_folder = r"C:\Users\USER\Downloads\templates" | |
delete_output = 'SAVE_OUTPUT' not in os.environ | |
data_dir = templates_folder | |
# Creates an instance of FileStream | |
with Image.load(os.path.join(data_dir, "template.bmp")) as image: | |
# Create and initialize an instance of Graphics class | |
graphic = Graphics(image) | |
graphic.draw_string("Test", Font("Arial", 10.0), SolidBrush(Color.black), PointF(0.0, 0.0)) | |
size = graphic.measure_string("Test", Font("Arial", 10.0), SizeF(100.0, 100.0), StringFormat.generic_default) | |
image.save(os.path.join(data_dir, "result.bmp")) | |
if delete_output: | |
os.remove(os.path.join(data_dir, "result.bmp")) |
Drawing Images using Graphics : Complete Source
from aspose.imaging import Image, Graphics, Color, Pen, Rectangle, Point | |
from aspose.imaging.brushes import LinearGradientBrush | |
from aspose.imaging.imageoptions import BmpOptions | |
from aspose.imaging.sources import FileCreateSource | |
import os | |
if 'TEMPLATE_DIR' in os.environ: | |
templates_folder = os.environ['TEMPLATE_DIR'] | |
else: | |
templates_folder = r"C:\Users\USER\Downloads\templates" | |
delete_output = 'SAVE_OUTPUT' not in os.environ | |
data_dir = templates_folder | |
# Create an instance of BmpOptions and set its various properties | |
with BmpOptions() as image_options: | |
image_options.bits_per_pixel = 24 | |
# Create an instance of FileCreateSource and assign it to Source property | |
image_options.source = FileCreateSource(os.path.join(data_dir, "result.bmp"), False) | |
with Image.create(image_options, 500, 500) as image: | |
graphics = Graphics(image) | |
# Clear the image surface with white color and Create and initialize a Pen object with blue color | |
graphics.clear(Color.white) | |
pen = Pen(Color.blue) | |
# Draw Ellipse by defining the bounding rectangle of width 150 and height 100 also Draw a polygon using the LinearGradientBrush | |
graphics.draw_ellipse(pen, Rectangle(10, 10, 150, 100)) | |
with LinearGradientBrush(image.bounds, Color.red, Color.white, 45.0) as linear_gradient_brush: | |
graphics.fill_polygon_by_point(linear_gradient_brush, [Point(200, 200), Point(400, 200), Point(250, 350)]) | |
image.save() | |
if delete_output: | |
os.remove(os.path.join(data_dir, "result.bmp")) |
All classes that implement enter and exit methods and access unmanaged resources are instantiated in a with statement to ensure that they are disposed of correctly.
Drawing Text on images using Graphics
Using Aspose.Imaging you can easily draw text on image with text alignment using Graphics.
import aspose.pycore as aspycore | |
from aspose.imaging import Image, Graphics, Color, Pen, RectangleF, Point, SizeF, \ | |
StringFormat, StringAlignment, StringFormatFlags, Font | |
from aspose.imaging.brushes import SolidBrush | |
from aspose.imaging.imageoptions import PngOptions | |
from aspose.imaging.sources import FileCreateSource | |
import os | |
if 'TEMPLATE_DIR' in os.environ: | |
templates_folder = os.environ['TEMPLATE_DIR'] | |
else: | |
templates_folder = r"C:\Users\USER\Downloads\templates" | |
delete_output = 'SAVE_OUTPUT' not in os.environ | |
data_dir = templates_folder | |
def run(): | |
alignments = ["Left", "Center", "Right"] | |
for alignment in alignments: | |
draw_string(templates_folder, alignment) | |
def draw_string(base_folder, align): | |
output_file_name = os.path.join(data_dir, "result.png") | |
font_names = ["Arial", "Times New Roman", "Bookman Old Style", "Calibri", "Comic Sans MS", "Courier New", "Microsoft Sans Serif", "Tahoma", "Verdana", "Proxima Nova Rg"] | |
font_sizes = [10.0, 22.0, 50.0, 100.0] | |
width = 3000 | |
height = 3500 | |
# Create an instance of PngOptions and set its various properties | |
with PngOptions() as png_options: | |
# Set the Source for PngOptions | |
png_options.source = FileCreateSource(output_file_name, False) | |
# Create an instance of Image | |
with Image.create(png_options, width, height) as image: | |
# Create and initialize an instance of Graphics class | |
graphics = Graphics(image) | |
# Clear Graphics surface | |
graphics.clear(Color.white) | |
# Create a SolidBrush object and set its various properties | |
brush = SolidBrush() | |
brush.color = Color.black | |
x = 10 | |
line_x = 0 | |
y = 10 | |
w = width - 20 | |
pen = Pen(Color.red, 1.0) | |
alignment = StringAlignment.NEAR | |
if align == "Left": | |
line_x = round(x, 0) | |
elif align == "Center": | |
alignment = StringAlignment.CENTER | |
line_x = round(x + w / 2.0, 0) | |
elif align == "Right": | |
alignment = StringAlignment.FAR | |
line_x = round(x + w) | |
string_format = StringFormat(StringFormatFlags.EXACT_ALIGNMENT) | |
string_format.alignment = alignment | |
for font_name in font_names: | |
for font_size in font_sizes: | |
font = Font(font_name, font_size) | |
text = "This is font: {0}, size:{1}".format(font_name, font_size) | |
s = graphics.measure_string(text, font, SizeF.empty, None) | |
graphics.draw_string(text, font, brush, RectangleF(float(x), float(y), float(w), float(s.height)), string_format) | |
y += s.height | |
graphics.draw_line(pen, Point(round(x), round(y)), Point(round(x + w), round(y))) | |
graphics.draw_line(pen, Point(round(line_x), 0), Point(round(line_x), round(y))) | |
# save all changes. | |
image.save() | |
if delete_output: | |
os.remove(os.path.join(data_dir, "result.png")) | |
run() |
Memory Strategy optimization
Graphics operations can be proceeded using memory strategy optimization - ie limiting memory buffer size for operation.
from aspose.imaging import Image, Graphics, Color, Pen, Rectangle, Point | |
from aspose.imaging.brushes import LinearGradientBrush | |
from aspose.imaging.imageoptions import PngOptions | |
from aspose.imaging.sources import FileCreateSource | |
import os | |
if 'TEMPLATE_DIR' in os.environ: | |
templates_folder = os.environ['TEMPLATE_DIR'] | |
else: | |
templates_folder = r"C:\Users\USER\Downloads\templates" | |
delete_output = 'SAVE_OUTPUT' not in os.environ | |
data_dir = templates_folder | |
image_size = 2000 | |
with PngOptions() as create_options: | |
create_options.source = FileCreateSource(os.path.join(data_dir, "result.png"), False) | |
create_options.buffer_size_hint = 30 | |
with Image.create(create_options, image_size, image_size) as image: | |
graphics = Graphics(image) | |
# You can use any graphic operations here, all of them will be performed within the established memory limit | |
# For example: | |
graphics.clear(Color.light_sky_blue) | |
graphics.draw_line(Pen(Color.red, 3.0), 0, 0, image.width, image.height) | |
image.save() | |
if delete_output: | |
os.remove(os.path.join(data_dir, "result.png")) | |
# A large number of graphic operations are also supported: | |
operation_area_size = 10 | |
with PngOptions() as create_options: | |
create_options.source = FileCreateSource(os.path.join(data_dir, "result_2.png"), False) | |
create_options.buffer_size_hint = 30 | |
with Image.create(create_options, image_size, image_size) as image: | |
graphics = Graphics(image) | |
graphics.begin_update() | |
graphics.clear(Color.light_sky_blue) | |
for column in range(image_size // operation_area_size): | |
for row in range(image_size // operation_area_size): | |
x = column * operation_area_size | |
y = row * operation_area_size | |
is_reversed = (column + row) % 2 != 0 | |
if (is_reversed): | |
graphics.draw_line( | |
Pen(Color.red), | |
x + operation_area_size - 2, | |
y, | |
x, | |
y + operation_area_size); | |
else: | |
graphics.draw_line( | |
Pen(Color.red), | |
x, | |
y, | |
x + operation_area_size - 2, | |
y + operation_area_size); | |
# About 40k operations will be applied here, while they do not take up too much memory | |
# (since they are already unloaded into the external file, and will be loaded from there one at a time) | |
graphics.end_update() | |
image.save() | |
if delete_output: | |
os.remove(os.path.join(data_dir, "result_2.png")) |