Skip to main content

Fast, friendly image processing for web apps and SaaS

Project description

nitro-image

Fast, friendly image processing for Python web apps and SaaS.

from nitro_img import Image

Image("photo.jpg").resize(800).webp(quality=80).save("photo.webp")

Install

pip install nitro-image

Optional extras:

pip install nitro-image[url]   # Load images from URLs (httpx)
pip install nitro-image[avif]  # AVIF format support
pip install nitro-image[blur]  # BlurHash generation
pip install nitro-image[all]   # Everything

Claude Code Skill

Add NitroImage as a skill in Claude Code for AI-assisted image manipulation:

npx skills add nitrosh/nitro-image

Why nitro-image?

With Pillow alone:

from PIL import Image

img = Image.open("photo.jpg")
img = img.convert("RGB")
width, height = img.size
new_height = int(height * (800 / width))
img = img.resize((800, new_height), Image.LANCZOS)
img.save("photo.webp", "WEBP", quality=80)

With nitro-image:

from nitro_img import Image

Image("photo.jpg").resize(800).webp(quality=80).save("photo.webp")

nitro-image wraps Pillow with a chainable API and lazy execution pipeline. Operations queue up and only run when you call an output method like .save() or .to_bytes().

Features

Resize and crop

Image("photo.jpg").resize(800).save("resized.jpg")
Image("photo.jpg").thumbnail(200).save("thumb.jpg")
Image("photo.jpg").cover(400, 400).save("square.jpg")
Image("photo.jpg").contain(400, 400).save("contained.jpg")
Image("photo.jpg").crop(100, 100, 500, 400).save("cropped.jpg")

Format conversion

Image("photo.jpg").webp(quality=80).save("photo.webp")
Image("photo.jpg").png().save("photo.png")
Image("photo.jpg").jpeg(quality=90).save("photo.jpg")
Image("photo.jpg").auto_format().save("photo.webp")  # picks best format

Adjustments and effects

Image("photo.jpg").brightness(1.2).contrast(1.1).save("enhanced.jpg")
Image("photo.jpg").sharpen(1.5).save("sharp.jpg")
Image("photo.jpg").blur(2.0).save("blurred.jpg")
Image("photo.jpg").grayscale().save("gray.jpg")
Image("photo.jpg").sepia().save("sepia.jpg")
Image("photo.jpg").rounded_corners(20).png().save("rounded.png")

Watermark and text overlay

Image("photo.jpg").watermark("logo.png", position="bottom-right", opacity=0.5).save("watermarked.jpg")
Image("photo.jpg").text_overlay("Sample", font_size=48).save("labeled.jpg")

Responsive images

widths = Image("photo.jpg").responsive([400, 800, 1200, 1600])
# Returns {400: bytes, 800: bytes, 1200: bytes, 1600: bytes}

Image("photo.jpg").save_responsive("output/{width}w.webp", [400, 800, 1200])
# Saves output/400w.webp, output/800w.webp, output/1200w.webp

Placeholders

Image("photo.jpg").lqip()           # Low-quality base64 data URI
Image("photo.jpg").dominant_color()  # "#3a6b8c"
Image("photo.jpg").color_palette(5)  # ["#3a6b8c", "#d4a574", ...]
Image("photo.jpg").svg_placeholder() # SVG with dominant color
Image("photo.jpg").blurhash()        # "LKO2:N%2Tw=w]~RBVZRi..."

Optimization

Image("photo.jpg").optimize(target_kb=200).save("optimized.jpg")

Presets

from nitro_img import Image

Image("photo.jpg").preset.thumbnail()     # 300px thumbnail
Image("photo.jpg").preset.avatar()        # 128px circle crop
Image("photo.jpg").preset.og_image()      # 1200x630 social card
Image("photo.jpg").preset.banner()        # 1920x400 banner

Image.preset.avatar_placeholder("SN")     # Initials avatar image

Batch processing

from nitro_img import BatchImage

BatchImage("photos/*.jpg").resize(800).webp().save("output/{name}.webp")
BatchImage("photos/*.jpg").resize(800).jpeg().save("output/{name}.jpg", parallel=True)

Web framework responses

# Django
return Image("photo.jpg").resize(400).webp().to_django_response()

# Flask
return Image("photo.jpg").resize(400).webp().to_flask_response()

# FastAPI
return Image("photo.jpg").resize(400).webp().to_fastapi_response()

Loading from anywhere

Image("photo.jpg")                          # File path
Image.from_bytes(raw_bytes)                 # Bytes
Image.from_base64(b64_string)              # Base64 string
Image.from_url("https://example.com/img")  # URL (requires httpx)
Image.from_file(file_object)               # File-like object

Output options

img = Image("photo.jpg").resize(400).webp()

img.save("output.webp")      # Save to file
img.to_bytes()                # Get raw bytes
img.to_base64()               # Base64 encoded string
img.to_data_uri()             # data:image/webp;base64,...
img.to_response()             # {"body": bytes, "content_type": str, "content_length": int}

Chain everything

All operations are chainable and lazily evaluated:

(
    Image("photo.jpg")
    .resize(800)
    .brightness(1.1)
    .contrast(1.05)
    .sharpen(1.2)
    .sepia()
    .rounded_corners(10)
    .png(optimize=True)
    .save("final.png")
)

Configuration

from nitro_img import config

config.update(
    jpeg_quality=85,
    webp_quality=80,
    png_optimize=True,
    max_width=4096,
    max_height=4096,
)

Requirements

  • Python 3.10+
  • Pillow 10.0+

Ecosystem

License

This project is licensed under the BSD 3-Clause License. See the LICENSE file for details.

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

nitro_image-1.0.0.tar.gz (34.8 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

nitro_image-1.0.0-py3-none-any.whl (28.2 kB view details)

Uploaded Python 3

File details

Details for the file nitro_image-1.0.0.tar.gz.

File metadata

  • Download URL: nitro_image-1.0.0.tar.gz
  • Upload date:
  • Size: 34.8 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.1.0 CPython/3.13.7

File hashes

Hashes for nitro_image-1.0.0.tar.gz
Algorithm Hash digest
SHA256 bcdef4ab2647ae1c4d1ceefe7e03afbc3ee62b241c265fbca0fb0d1cee8221fa
MD5 a6c45dbb000f13ea72c604c3f2690fd2
BLAKE2b-256 8585dfaa74c6283fd636ca18fda91229775bcd2b50911965ba6a9c4e349e7df6

See more details on using hashes here.

File details

Details for the file nitro_image-1.0.0-py3-none-any.whl.

File metadata

  • Download URL: nitro_image-1.0.0-py3-none-any.whl
  • Upload date:
  • Size: 28.2 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.1.0 CPython/3.13.7

File hashes

Hashes for nitro_image-1.0.0-py3-none-any.whl
Algorithm Hash digest
SHA256 b9a800d5f25fc334afbece814bdfdc367b158e7bc3ad41a652fbd95363686d71
MD5 70bdda22345cb117aedf7786fc9d1fed
BLAKE2b-256 98874a33f203ea7bc1a2c691e87a360e925602005865e2e899dfe71a44847e98

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page