Skip to content

Repository files navigation

Pixtimize ⚡🖼️

Pixtimize is an open source image transform API compatible with the ImageKit API. Pixtimize is compatible with any S3 bucket service.

This is a Rust rewrite built on Axum for a fast, memory-safe web server.

Tools used

  • Rust and Axum as the web framework and runtime
  • AWS SDK for S3 to read source images and store transformed ones (any S3-compatible bucket)
  • Redis to store the cached image keys
  • libvips (via libvips-rs) for fast, low-memory image decoding, resizing, and encoding

How it works

For every request the server:

  1. Parses the transform string (from the path or the tr query param).
  2. Computes a cache key: sha256(image_path + transformations).
  3. Looks up the transformed image in the cache. On a GET hit the object is fetched from S3; on a HEAD hit the body is never downloaded — Redis stores {s3_key, size, content_type} and S3 HeadObject is used only for legacy markers that lack size.
  4. Otherwise it coalesces concurrent builds for the same cache key (in-process single-flight plus a Redis SET NX lock across instances), fetches the source from S3, applies the transform, stores the result in S3, records metadata in Redis, and returns it.

When CACHE_DELETE_CRON is set, a cron job periodically clears the cache (Redis markers and the matching S3 objects). Omit the variable to disable cleanup.

Transforms compatibility

Property name compatible comment
w fixed pixel values, and fractions in (0, 1) are treated as a percentage
h fixed pixel values, and fractions in (0, 1) are treated as a percentage
q quality of the image, default value is DEFAULT_QUALITY
f output format, default is DEFAULT_FORMAT; values: jpeg, jpg, png, webp

Limits (ImageKit-compatible)

Aligned with ImageKit transformation limits (free-plan values where adjustable):

Limit Value Behavior
Max image file size for processing 20 MB request rejected
Max image megapixels for processing 25 MP request rejected
Max transform dimensions (w / h) 65 535 px larger absolute values are ignored
Max WebP transform / output dimensions 16 383 px request rejected

Usage

You can transform an image by calling your URL like this (remember to encode the , as %2C in the query param):

https://yourdomain.com/image-example.png?tr=w-606,h-450,f-jpeg

or

https://yourdomain.com/tr:w-606,h-450,f-jpeg/image-example.png

Client usage with Unpic

Because Pixtimize speaks the ImageKit transform URL API, use it from the frontend with Unpic’s ImageKit provider — not a custom provider. Point Unpic at your Pixtimize base URL the same way you would point it at ImageKit.

See the Unpic ImageKit provider docs for options, operations (w, h, q, f, …), and other frameworks.

import { Image } from "@unpic/react";

export function ProductImage() {
  return (
    <Image
      src="https://your-pixtimize-host/image-example.png"
      width={800}
      height={600}
      alt="Example"
      operations={{
        imagekit: {
          // imagekit operations here (supported transforms: see below)
        },
      }}
    />
  );
}

The generated URLs work against Pixtimize for the transforms this server implements (see Transforms compatibility).

CDN

Serve Pixtimize behind a CDN so transformed images are cached at the edge and delivered closer to users. Point the CDN origin at your Pixtimize host and use the CDN hostname in client URLs (including Unpic src).

Partner

We recommend LightCDN. Sign up with referral code gl6hwdgy.

LightCDN

Configuration

Required environment variables:

  • S3_ENDPOINT: URL of the S3 bucket (default https://ams3.digitaloceanspaces.com)
  • S3_BUCKET: name of the S3 bucket
  • S3_ACCESS_KEY: access key id of the S3 bucket
  • S3_SECRET_KEY: secret key of the S3 bucket
  • REDIS_URL: Redis connection URL

Optional environment variables:

  • PORT: port to listen on (default 3000)
  • S3_REGION: S3 region (default ams3)
  • DEFAULT_QUALITY: default quality applied to optimize images (default 80)
  • DEFAULT_FORMAT: default output format (default webp)
  • CACHE_DELETE_CRON: optional cron schedule for cache cleanup (omit to disable). Example: 0 1 * * 1 (every Monday at 1am). Standard 5-field expressions are supported; a seconds field is optional.
  • CACHED_TIME: max-age (in seconds) advertised on served images (default 31536000, matching ImageKit’s 1-year CDN cache)

See .env.example for a template.

Commands

Prerequisites

Image processing is powered by native libvips, so it must be installed before building or running locally:

# macOS
brew install vips

# Debian / Ubuntu
sudo apt-get install -y libvips-dev

On Homebrew (or any non-standard prefix), point pkg-config at libvips so the build script can find it:

export PKG_CONFIG_PATH="$(brew --prefix vips)/lib/pkgconfig:$(brew --prefix)/lib/pkgconfig:$PKG_CONFIG_PATH"

Install the toolchain from rustup.rs, then:

# run in development
cargo run

# run the tests
cargo test

# build an optimized release binary
cargo build --release

Docker

docker build -t pixtimize .
docker run --rm -p 3000:3000 --env-file .env pixtimize

License

Licensed under the Apache License 2.0.

About

Pixtimize is an opensource image transform api compatible with imagekit API. Pixtimize is compatible with any S3 bucket service.

Resources

Stars

4 stars

Watchers

1 watching

Forks

Releases

Packages

Contributors

Languages