mcpField
I
image-processing

image-processing

github.com/claude-dev-suiteDevelopment4642 installsUpdated 2d ago
Repository

About image-processing

A practical image-processing reference with examples for Sharp in Node.js, Cloudinary and Python Pillow. It covers common upload transformations and validation, responsive images, and production practices rather than providing a standalone processing service.

Key features

  1. 01Resize and convert images with Sharp
  2. 02Validate uploads with Express and multer
  3. 03Process images with Python Pillow
  4. 04Use Cloudinary for managed image handling
  5. 05Guidance on responsive image delivery
  6. 06Production checklist and anti-patterns

Use cases

  1. 01Generate multiple image sizes during upload
  2. 02Validate file type and size before processing
  3. 03Convert uploads to WebP or AVIF
  4. 04Plan background processing and CDN delivery

Install

Copy the command and run it in a terminal.

$npx skills add https://github.com/claude-dev-suite/claude-dev-suite --skill image-processing

After installing, type/image-processingin Claude Code to confirm it loaded.

Details

From the project README

Image Processing

Sharp (Node.js — recommended)

import sharp from 'sharp';

// Resize and convert
async function processUpload(input: Buffer, filename: string) {
  const variants = await Promise.all([
    sharp(input).resize(1200, 1200, { fit: 'inside', withoutEnlargement: true })
      .webp({ quality: 80 }).toBuffer(),
    sharp(input).resize(400, 400, { fit: 'cover' })
      .webp({ quality: 75 }).toBuffer(),
    sharp(input).resize(100, 100, { fit: 'cover' })
      .webp({ quality: 70 }).toBuffer(),
  ]);

  return {
    original: { buffer: variants[0], key: `images/${filename}.webp` },
    medium: { buffer: variants[1], key: `images/${filename}-400.webp` },
    thumb: { buffer: variants[2], key: `images/${filename}-100.webp` },
  };
}
Express Upload Pipeline
import multer from 'multer';

const upload = multer({ limits: { fileSize: 10 * 1024 * 1024 } }); // 10MB

app.post('/api/images', upload.single('image'), async (req, res) => {
  // Validate image type
  const metadata = await sharp(req.file!.buffer).metadata();
  if (!['jpeg', 'png', 'webp'].includes(metadata.format!)) {
    return res.status(400).json({ error: 'Invalid image format' });
  }

  const variants = await processUpload(req.file!.buffer, uuid());

  // Upload to S3
  await Promise.all(Object.values(variants).map((v) =>
    s3.putObject({ Bucket: BUCKET, Key: v.key, Body: v.buffer, ContentType: 'image/webp' })
  ));

  res.json({ url: `${CDN_URL}/${variants.original.key}` });
});

Cloudinary (managed service)

import { v2 as cloudinary } from 'cloudinary';

cloudinary.config({
  cloud_name: process.env.CLOUDINARY_CLOUD,
  api_key: process.env.CLOUDINARY_KEY,
  api_secret: process.env.CLOUDINARY_SECRET,
});

// Upload with auto-optimization
const result = await cloudinary.uploader.upload(filePath, {
  folder: 'products',
  transformation: [
    { width: 1200, height: 1200, crop: 'limit' },
    { quality: 'auto', fetch_format: 'auto' },
  ],
});

// URL-based transformations
const thumbUrl = cloudinary.url(result.public_id, {
  width: 200, height: 200, crop: 'fill', gravity: 'face',
  quality: 'auto', format: 'webp',
});

Python (Pillow)

from PIL import Image
from io import BytesIO

def process_image(data: bytes, max_size: int = 1200) -> bytes:
    img = Image.open(BytesIO(data))
    img.thumbnail((max_size, max_size), Image.Resampling.LANCZOS)

    if img.mode in ('RGBA', 'P'):
        img = img.convert('RGB')

    output = BytesIO()
    img.save(output, format='WEBP', quality=80)
    return output.getvalue()

Responsive Images (HTML)

<picture>
  <source srcset="/images/hero-400.webp 400w, /images/hero-800.webp 800w, /images/hero-1200.webp 1200w"
          sizes="(max-width: 600px) 400px, (max-width: 1024px) 800px, 1200px"
          type="image/webp" />
  <img src="/images/hero-800.jpg" alt="Hero image" loading="lazy" decoding="async" />
</picture>

Anti-Patterns

Anti-PatternFix
Processing in request handlerProcess in background job queue
Storing only original sizeGenerate multiple sizes on upload
No format conversionConvert to WebP/AVIF for smaller size
No file size validationValidate before processing
Serving images from app serverUse CDN or cloud storage

Production Checklist

  • Image processing in background queue
  • Multiple sizes generated (thumb, medium, full)
  • WebP/AVIF conversion for modern browsers
  • CDN for serving images
  • File type and size validation
  • Metadata stripping for privacy

Comments

Markdown supported