A Python library built on top of Pillow to easily edit/modify images.
pip install easy-pilRequires Python 3.11 or higher.
from easy_pil import Editor, Canvas
canvas = Canvas(width=500, height=500)
editor = Editor(canvas)
editor.text((10, 10), "Hello World")
editor.show() # or .save("output.png")Apply 38+ effects using the unified effect() method with Effect classes:
from easy_pil import Editor, load_image
from easy_pil import Vignette, Glow, Gradient, Blur, Sepia, PixelSort
editor = Editor(load_image("image.jpg"))
# Single effect
editor.effect(Vignette(radius=120, feather=60))
# Chain multiple effects
editor.effect(Blur(amount=2)).effect(Sepia()).save("out.png")| Category | Effects |
|---|---|
| Blur & Filters | Blur (box/gaussian), Contour, Emboss, EdgeEnhance, Sharpen, Smooth, Pixelate |
| Color | Grayscale, Sepia, Invert, Posterize, Solarize, Threshold, Duotone |
| Overlay | ColorOverlay, Gradient, Vignette, Noise, Scanlines, Halftone, Dither |
| Lighting | Glow, Bloom, Neon, EdgeGlow |
| Shadow | DropShadow |
| Distort | Ripple, Vortex, Glitch, PixelSort, Kaleidoscope |
| Artistic | OilPaint, TiltShift, Sketch, Cartoon, Thermal |
| Region | PixelateRegion |
Each Effect class has configurable parameters — see the API Reference for details.
from easy_pil import Editor, Font, Text
editor = Editor("image.jpg")
# Simple text
editor.text((10, 10), "Hello", font=Font.poppins(size=32), color="white")
# Rich text with mixed colors/fonts
editor.rich_text((10, 50), [
Text("Hello", Font.poppins(size=32), "red"),
Text("World", Font.poppins(size=24), "blue"),
])
# Auto-wrapping text box
editor.text_box((10, 100), "Long text that wraps automatically...",
font=Font.poppins(size=20), max_width=400)
# Text with drop shadow
editor.text_shadow((200, 300), "Hello", font=Font.poppins(size=40),
shadow_color="black", shadow_offset=(3, 3))
# Auto-fit text to width (accepts Font, FreeTypeFont, or path string)
font = editor.fit_text("Title", max_width=300, font=Font.poppins(size=40))
editor.text((10, 10), "Title", font=font)
# Centered text (no position — auto-centers on image)
editor.centered_text("Centered", font=Font.poppins(size=30))editor.rectangle((10, 10), width=100, height=50, fill="red")
editor.ellipse((150, 10), width=80, height=80, outline="blue", stroke_width=3)
editor.bar((10, 70), width=200, height=20, fill="green")
editor.rounded_bar((10, 100), width=200, height=20, fill="purple", radius=10)
editor.polygon([(300, 10), (350, 50), (250, 50)], fill="orange")
editor.arc((10, 150), width=100, height=100, start=0, rotation=180, fill="pink", stroke_width=3)
editor.line((10, 300), (200, 350), width=4, fill="black")
editor.donut((300, 300), inner_radius=30, outer_radius=60, fill="teal")editor.resize((400, 400))
editor.rotate(45, expand=True)
editor.crop((50, 50, 200, 200))
editor.flip(horizontal=True)
editor.thumbnail((200, 200))
editor.contrast(1.5)
editor.brightness(1.2)
editor.saturation(0.8)
editor.invert()
editor.blur(mode="gaussian", amount=5)editor.blend(other_image, alpha=0.5)
editor.paste(overlay, position=(50, 50))
editor.mask(mask_image, invert=False)
editor.compose([img1, img2, img3], direction="vertical", align="center")
editor.rounded_corners(radius=20)
editor.circle_image()
editor.add_border(width=5, color="black")editor = Editor.open("image.png")
editor.save("output.png")
editor.show()
editor.to_bytes(fmt="PNG") # -> bytes
# Context manager — auto-closes image on exit
with Editor("image.png") as e:
e.resize((400, 400)).save("thumb.png")from easy_pil import load_image_async
img = await load_image_async("https://example.com/image.png")from easy_pil import GifEditor
with GifEditor("animation.gif") as gif:
gif.rotate(90)
gif.save("rotated.gif")