• Skip to primary navigation
  • Skip to main content
  • Skip to primary sidebar
  • Skip to footer

The Coding Couple

Pair programming is a lifetime commitment.

  • Home
  • Categories
    • Arduino
    • JavaScript
    • Python
    • Raspberry Pi
  • About Us
    • Privacy Policy
  • Contact

How to watermark images with Python and Pillow (PIL)

July 9, 2016 by Ashley

I am a DIY blogger, and the most tedious part of the job is editing the images. I am constantly repeating the following steps:

  1. Resize the image
  2. Add a text watermark
  3. Compress the image

I wanted to automate the process. There are good solutions out there for automating image manipulation, but it has been a few years since I last wrote a meaningful piece of Python code. I saw this as an excellent way to dust off my Python skill and learn a bit about programmatic image manipulation.

Related:

  • Counting Pixels by Color with Python and Pillow

Pillow, the friendly PIL fork

Pillow is an active fork of PIL, the Python Imaging Library.  With Pillow, you can programmatically edit image files in Python.  To get started with Pillow, install the binary with pip:

pip install Pillow

The core component of the Python Imaging Library is the Image module.  With Image, you can open and save images, create new images, resize images and read the image metadata.

from PIL import Image 
image = Image.open('cats.png') 
print(image.size, image.format) 
# (350, 250) PNG 

ImageDraw and ImageFont

In addition to Image, the ImageDraw and ImageFont modules are necessary to watermark an image.  The ImageDraw module adds functionality for drawing 2D graphics onto new or existing images.  The ImageFont module is used for loading bitmap, TrueType and OpenType font files.

To draw text onto an image, get a drawing context from ImageDraw.Draw.  The drawing context has a text method that will draw a string at the given position.  To determine the size of the text, call the textsize method and it will return a tuple containing the text’s width and height.

from PIL import Image, ImageDraw, ImageFont 

image = Image.open('cats.png') 
width, height = image.size 

draw = ImageDraw.Draw(image) 
text = "A watermark"

font = ImageFont.truetype('arial.ttf', 12)
textwidth, textheight = draw.textsize(text, font)

# calculate the x,y coordinates of the text 
margin = 5 
x = width - textwidth - margin 
y = height - textheight - margin 

# draw watermark in the bottom right corner 
draw.text((x, y), text, font=font) 
image.save('cats.png')

In addition to watermarking the images, my script had the requirement of resizing and compressing the images. The Image class has a resize method that takes a tuple containing values for width and height.  To compress the images, I used the Tinify API.

marker.py

The first version my Python image manipulation script is complete.  There are a couple things that I would like to tweak, but in it’s current form the script already saves me a lot of time and effort!

CLICK HERE to check out some of our other posts!

FIND US ONLINE!

  • Instagram: @thecodingcouple
  • Twitter: @thecodingcouple
  • GitHub: @thecodingcouple

Related Posts

  • Fractions in Python | Today I LearnedFractions in Python | Today I Learned
  • Avoid using mutable values as default parameter values in Python (Today I Learned)Avoid using mutable values as default parameter values in Python (Today I Learned)
  • Counting Pixels in the Browser with the HTML5 Canvas and the ImageData objectCounting Pixels in the Browser with the HTML5 Canvas and the ImageData object
  • Pokémon Color Picker | A web app built with HTML/CSS + JavaScriptPokémon Color Picker | A web app built with HTML/CSS + JavaScript
  • AdaBox 005: Break for Pi | Adafruit Subscription BoxAdaBox 005: Break for Pi | Adafruit Subscription Box
  • Getting started with Phaser and ES2015Getting started with Phaser and ES2015

Filed Under: Python Tagged With: automation, image manipulation, pil, pillow, python, python imaging library, script, tinify, tinypng, watermark

Previous Post: « Creation Crate Month 2: An Arduino Powered Memory Game
Next Post: Getting started with Phaser and ES2015 »

Reader Interactions

Comments

  1. Dave Beck says

    July 11, 2016 at 9:28 pm

    This is very cool and could save me a lot of time. I’m heading over to github to check it out. Thanks Ashley!

Primary Sidebar

Social Media

  • GitHub
  • Instagram
  • Twitter
  • YouTube

Recent Posts

  • Pokémon Color Picker | A web app built with HTML/CSS + JavaScript
  • Pokéball Single DIV CSS Drawing | Tutorial
  • Error: [🍍]: “getActivePinia()” was called but there was no active Pinia
  • Trijam #261 Game Jam Diary: One Wrong Move
  • Using WSL on Corporate VPN

Recent Comments

  • Lizzy on Creation Crate Month 2: An Arduino Powered Memory Game
  • Ashley Grenon on Creation Crate Month 2: An Arduino Powered Memory Game
  • Lizzy on Creation Crate Month 2: An Arduino Powered Memory Game
  • kelly on Creation Crate Month 2: An Arduino Powered Memory Game
  • Ashley on Creation Crate Month 3: An Arduino Powered Distance Detector

Follow us on Instagram!

This error message is only visible to WordPress admins

Error: No feed found.

Please go to the Instagram Feed settings page to create a feed.

Categories

  • Arduino
  • Conferences
  • Debugging
  • Game Jams
  • HTML and CSS
  • JavaScript
  • Programming Languages
  • Python
  • Raspberry Pi
  • Today I Learned

Archives

  • May 2024
  • April 2024
  • March 2024
  • May 2022
  • December 2021
  • May 2021
  • March 2020
  • January 2020
  • December 2019
  • November 2019
  • October 2019
  • June 2019
  • April 2019
  • September 2017
  • April 2017
  • August 2016
  • July 2016
  • June 2016
  • May 2016
  • April 2016
  • March 2016
  • April 2015
  • January 2015

Tags

adafruit arduino brackets c# code smell codestock coding standards conventions creation crate debugging developer devspace electronics es6 es2015 game development game jam gotcha hackathon hoisting html html5 javascript led naming conventions nintendo phaser pluralsight pokemon programmer python raspberry pi retro retropie scope self improvement single div single div drawing subscription box TIL today I learned troubleshooting vue vuejs windbg

Footer

About Us

We are the Coding Couple.  Two people who met in college and decided they wanted to pair program for the rest of their ...

Read More »

Most Recent Posts

Pokémon Color Picker | A web app built with HTML/CSS + JavaScript

Pokéball Single DIV CSS Drawing | Tutorial

Error: [🍍]: “getActivePinia()” was called but there was no active Pinia

Trijam #261 Game Jam Diary: One Wrong Move

Social Media

  • GitHub
  • Instagram
  • Twitter
  • YouTube

Copyright Notice

© The Coding Couple, 2015 – 2023. Excerpts and links may be used, provided that full and clear credit is given to The Coding Couple with appropriate and specific direction to the original content.

Copyright © 2025 · Foodie Pro Theme by Shay Bocks · Built on the Genesis Framework · Powered by WordPress