Create Mock Watermarked Image Bytes in Python Without PIL

Builds a mock image-like byte stream with an embedded watermark using only stdlib modules, for testing pipelines without PIL.

Easy Python 3.9+ Aug 9, 2026 Automation & scripting 13 views 0 copies

Python code

27 lines
Python 3.9+
from io import BytesIO
import zlib
import struct


def create_watermarked_bytes(width: int, height: int, watermark: bytes) -> bytes:
    """Create a mock image-like byte stream with a watermark (no PIL)."""
    header = struct.pack("<2I", width, height)
    payload = watermark * max(1, (width * height // max(1, len(watermark))))
    payload = payload[: width * height]
    compressed = zlib.compress(payload)
    size = struct.pack("<I", len(compressed))
    return header + size + compressed


if __name__ == "__main__":
    wm = b"WM" * 16
    raw = create_watermarked_bytes(16, 16, wm)
    b = BytesIO(raw)

    w, h = struct.unpack("<2I", b.read(8))
    comp_len = struct.unpack("<I", b.read(4))[0]
    data = zlib.decompress(b.read(comp_len))

    assert len(data) == w * h
    assert data[:32] == wm[:32]
    print(f"OK: {w}x{h}, {len(data)} bytes, watermark verified")

Output

stdout
OK: 16x16, 256 bytes, watermark verified

How it works

The function creates a binary structure: an 8-byte header carrying width and height, a 4-byte payload length, and zlib-compressed payload bytes. The payload repeats the watermark pattern to fill the exact pixel area (width times height bytes). Decompression verifies the payload length and the watermark appears at the start. Using BytesIO simulates reading from a file-like object, which mirrors real streaming scenarios.

Common mistakes

  • Packing arguments in the wrong endianness or order
  • Forgetting to compress or decompress the payload consistently
  • Not truncating the repeated watermark to the exact required length

Variations

  1. Use a list of pixel tuples to build a richer mock image format
  2. Write the result to a temp file with pathlib instead of BytesIO

Real-world use cases

  • Unit testing image upload handlers without loading heavyweight imaging libraries into the test environment.
  • Stubbing watermark detection logic in CI pipelines where deterministic binary fixtures speed up regression runs.
  • Validating storage and retrieval of binary blobs in backend services with predictable, synthetic data.

Sponsored

Run this sample

Open the browser IDE to tweak the example and see results without installing anything.

Open editor

More from Automation & scripting

Related tutorials and quizzes for this topic.