I've been playing around implementing watermark processors for django-imagekit. There was an open request for an overlay processor (which is kind of the same thing), and I wanted to explore a bit more PIL and imagekit processors.
So far, I've created processors that take text and images to overlay in the base image. At the time, the code is available in a fork of imagekit.
Examples
Overlaying text
Using TextWatermark
we can overlay some text in the following manner
img = Image.open("drave_base.jpg")
title_mark = TextWatermark("Views from Drave",
font=("/Library/Fonts/Arial Bold.ttf", 16),
text_color="red",
position=(20,20),
opacity=1)
copy_mark = TextWatermark("Photo taken by myself. No copyright.",
font=("/Library/Fonts/Arial Bold.ttf", 16),
text_color="#ff0",
position=(-20,-20),
opacity=0.5)
img = title_mark.process(img)
img = copy_mark.process(img)
And the resulting img
would be
In TextWatermark
, all configuration is optional, except for the text to be
written.
You see, you can use names for text_color
or HTML color notation (or any
format supported by PIL.ImageColor). opacity
takes a float
ranging from 0
to 1
. The position
parameter
accepts tuples containing horizontal and vertical position values. The values
can be specified as strings (such as top
, left
, bottom
, right
and
center
), strings containing percentages (such as "25%"
) or integers. If the
percentages or integers are negative, they're measured form the bottom-right instad
of the top-left point.
The font
parameter may be a path to a TrueType font file or a tuple with a
path and a size. Unfortunely there's no font discovery: you have to specify
the full path to the font file.
Overlaying images
With ImageWatermark
we can overlay one image on another. We'll use the
landscape image with this star:
The watermark can be provided to the processor as a str
with the path to
the image, an Image
object or a storage (file
-like object).
Here's some sample code on how we could use this processor.
img = Image.open("drave_base.jpg")
# any of these could be used
watermark = "200-star.png"
watermark = Image.open("200-star.png")
watermark = open("200-star.png") # if you use a file-like object
# remember to close your file when done
scaled = ImageWatermark(watermark,
position=('center', 'center'),
scale=True,
opacity=0.2)
repeated = ImageWatermark(watermark,
position=('right', 'bottom'),
repeat=True,
opacity=0.2)
img_scaled = scaled.process(img)
img_repeated = repeated.process(img)
Would result in img_scaled
:
And img_repeated
:
For performance tuning, it's better to setup the watermark image to be used by path or storage object. Using an Image object will require the Image to be kept in memory forever (which may be a problem depending on the size and amount of images you'll be using). By default, the watermark will be cached using a weak reference, so the image processor doesn't need to constantly fetch it from storage and the image may be collected in case your process gets low on memory.
I hope this code can be of use to you. If you have any issues or requests, please send them through GitHub.