Image Automation with Python: Batch Resize, Compress and Watermark

Hong Kong SMEs running an online shop, Facebook or Instagram deal with piles of product photos every day: websites demand images that aren't too large (or pages load slowly and eat customers' mobile data), social media wants specific dimensions, and you still need a watermark to protect your originals. Resizing, compressing and watermarking each one by hand is fine for eight or ten — but a hundred?

This tutorial uses Python with a library called Pillow to process an entire folder of photos in a dozen lines of code. Even if you've never written code before, you can follow along.

Step 1: Install Pillow

First make sure Python is installed (if not, see our earlier beginner tutorial). Then open Command Prompt and install Pillow with:

pip install Pillow

When you see Successfully installed Pillow, you're ready.

Step 2: What does the script do?

This script does three things for you in one go:

  • Resize — shrinks anything wider than 1200 pixels (never upscales, so quality stays intact)
  • Compress — converts to JPEG and lowers quality, shrinking files dramatically so your site loads fast
  • Watermark — adds a line of text to the bottom-right corner to deter image theft

Step 3: Write the script

Create a new file called resize.py (Notepad is fine) and paste in the code below:

from PIL import Image, ImageDraw, ImageFont from pathlib import Path SRC = Path("photos") # Put your originals here OUT = Path("resized") # Output folder OUT.mkdir(exist_ok=True) MAX_W = 1200 # Max width in pixels QUALITY = 80 # JPEG quality (lower = smaller file) WATERMARK = "Sky World Biz" n = 0 for p in SRC.glob("*"): if p.suffix.lower() not in (".jpg", ".jpeg", ".png"): continue img = Image.open(p).convert("RGB") # 1) Resize: only shrink, never enlarge w, h = img.size if w > MAX_W: img = img.resize((MAX_W, int(h * MAX_W / w))) # 2) Add a watermark to the bottom-right corner draw = ImageDraw.Draw(img) font = ImageFont.load_default() bbox = draw.textbbox((0, 0), WATERMARK, font=font) tw, th = bbox[2] - bbox[0], bbox[3] - bbox[1] draw.text((img.width - tw - 10, img.height - th - 10), WATERMARK, fill=(255, 255, 255), font=font) # 3) Compress and save img.save(OUT / (p.stem + ".jpg"), "JPEG", quality=QUALITY, optimize=True) n += 1 print("Done! Processed", n, "photos")

Line by line

  • from PIL import Image, ImageDraw, ImageFont — loads Pillow's three core tools: opening images, drawing, and fonts.
  • SRC = Path("photos") — the source folder; put your photos here.
  • MAX_W = 1200 — the width cap. 1200px is plenty for web and social media.
  • QUALITY = 80 — JPEG quality from 1 (smallest) to 100 (sharpest). 80 is usually indistinguishable to the eye but far smaller.
  • SRC.glob("*") — lists every file in the folder, then p.suffix checks whether it's an image.
  • img.resize((MAX_W, int(h * MAX_W / w))) — shrinks proportionally so the aspect ratio never distorts.
  • draw.text(...) — draws the watermark bottom-right; the -10 leaves a 10-pixel margin.
  • img.save(..., quality=80, optimize=True) — saves compressed, and optimize squeezes the file a little more.

Step 4: Run it

In Command Prompt, navigate to where you saved resize.py and run:

python resize.py

Done! The resized folder now holds your processed photos, and your originals are untouched.

How to pick the quality setting

The QUALITY number is a balance between sharpness and file size. As a rule of thumb:

  • 90–100 — near-lossless; for photos you may print large
  • 75–85 — product and social-media images; visually identical but 60–70% smaller
  • 50–70 — thumbnails or previews only, not for display

Summary

Python Tutorial: With a dozen lines of code you've handed the repetitive resize-compress-watermark grunt work to the computer, freeing up time to focus on your business. Using the same idea, you can add automatic borders, batch format conversion — or combine it with our earlier scheduling tutorial to make it run every day on its own.