Skip to content

Commit 22ded4a

Browse files
committed
[new feature] OverlayImage processor
processor that adds an image over the original image. Added in overlay.py test added in test_processor.py
1 parent 9b9e334 commit 22ded4a

File tree

4 files changed

+54
-1
lines changed

4 files changed

+54
-1
lines changed

pilkit/processors/overlay.py

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,3 +21,30 @@ def process(self, img):
2121
mask = Image.new('RGBA', original.size, (0,0,0,int((1.0 - self.overlay_opacity)*255)))
2222
img = Image.composite(original, overlay, mask).convert('RGB')
2323
return img
24+
25+
26+
class ImageOverlay(object):
27+
"""
28+
Overlay an image (i.e watermark) with a given opacity over the original image.
29+
"""
30+
31+
def __init__(self, overlay_img, position=(0,0)):
32+
"""
33+
:param overlay_img: PIL `Image` instance to overlay on the original image
34+
:param position: coordinate (x,y) of the top left corner of the overlay image on the original image.
35+
"""
36+
self.overlay_img=overlay_img
37+
self.position=position
38+
39+
def process(self, img):
40+
#create the mask (image of same dimension as the original, with the overlay at the right location, with the given opacity)
41+
mask = Image.new("RGBA",(img.width, img.height),(0,0,0,0)) #transparent image with the same dimensions as original image
42+
mask.paste(self.overlay_img, (self.position[0], self.position[1])) #put the overlay image at the computed location
43+
44+
#render the picture overlayed
45+
if img.mode != "RGBA" :
46+
tmp = Image.alpha_composite(img.convert("RGBA"), mask) #apply the overlay (both images need to be in "RGBA" mode with alpha_composite())
47+
img = tmp.convert(img.mode) #convert back to the original mode
48+
else :
49+
img = Image.alpha_composite(img, mask)
50+
return img
78.7 KB
Loading
78.5 KB
Loading

tests/test_processors.py

Lines changed: 27 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55
from pilkit.lib import Image, ImageDraw, ImageColor
66
from pilkit.processors import (Resize, ResizeToFill, ResizeToFit, SmartCrop,
77
SmartResize, MakeOpaque, ColorOverlay, Convert,
8-
GaussianBlur)
8+
GaussianBlur, ImageOverlay)
99
from pilkit.processors.resize import Thumbnail
1010
from .utils import create_image, compare_images, get_image_file
1111

@@ -56,6 +56,32 @@ def test_coloroverlay():
5656
img = ColorOverlay(color, overlay_opacity=1.0).process(img)
5757
assert img.getpixel((0,0)) == (204, 0, 0)
5858

59+
def test_imageoverlay():
60+
"""
61+
Test ImageOverlay processor
62+
"""
63+
#test with RGBA mode background image
64+
background_img_rgba = Image.open(get_image_file("reference.png")).convert("RGBA")
65+
overlay_img_rgba = Image.open(get_image_file("image_with_transparency.png"))
66+
result_1 = background_img_rgba
67+
result_1 = ImageOverlay(overlay_img_rgba, (56,156)).process(result_1) #the overlay is completely inside the background image
68+
result_1 = ImageOverlay(overlay_img_rgba, (-30,-10)).process(result_1) #the overlay top left corner is in the void
69+
result_1 = ImageOverlay(overlay_img_rgba, (199,36)).process(result_1) #the overlay bottom right corner is in the void
70+
expected_result_1 = Image.open(get_image_file("ImageOverlay_expected_result.png")).convert("RGBA") #This image have been generated with gimp
71+
assert compare_images(result_1, expected_result_1) #overlay are positioned as expected
72+
assert result_1.mode == "RGBA" #the mode of the result is the same as the original
73+
74+
#test with RGB mode background image
75+
background_img_rgb = Image.open(get_image_file("reference.png")).convert("RGB")
76+
result_2 = background_img_rgb
77+
result_2 = ImageOverlay(overlay_img_rgba, (56,156)).process(result_2) #the overlay is completely inside the background image
78+
result_2 = ImageOverlay(overlay_img_rgba, (-30,-10)).process(result_2) #the overlay top left corner is in the void
79+
result_2 = ImageOverlay(overlay_img_rgba, (199,36)).process(result_2) #the overlay bottom right corner is in the void
80+
expected_result_2 = Image.open(get_image_file("ImageOverlay_expected_result.png")).convert("RGB") #This image have been generated with gimp
81+
assert compare_images(result_2, expected_result_2) #overlay are positioned as expected
82+
assert result_2.mode == "RGB" #the mode of the result is the same as the original
83+
84+
5985
def test_convert():
6086
img = Image.new('RGBA', (200, 100))
6187

0 commit comments

Comments
 (0)