npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

photeryx

v0.1.5

Published

Fast Rust + WebAssembly image processing for the browser.

Readme

Photeryx

High-performance Rust + WebAssembly image processing for modern web applications.

npm version npm downloads license GitHub issues Node version WebAssembly


🚀 Overview

Photeryx is a fast, lightweight image processing pipeline powered by Rust + WebAssembly, designed for browsers and modern frontend apps. It supports loading multiple images, transforming them, and exporting them in various formats, all locally without backend services.

This makes it ideal for:

  • Image editors
  • Upload preprocessors
  • Offline-first web apps
  • High-performance React / Vue / Svelte applications

✨ Core Features

  • Written in Rust, compiled to WebAssembly
  • Manage multiple images in memory at once
  • Load images from:
    • File
    • URL
    • ArrayBuffer
  • Transformations:
    • Rotate
    • Crop
    • Resize
    • Filters (brightness, contrast, blur, sharpen, etc.)
  • Export formats:
    • JPEG
    • PNG
    • WebP
  • Export as:
    • Uint8Array
    • Blob
    • Base64 data: URL
  • Duplicate detection across loaded images (returns Photo[][])
  • Manual memory control: free images when you’re done
  • Zero network dependency

📦 Installation

npm install photeryx

🧱 TypeScript API Overview

export interface RotationConfig {
  degrees: number;
}

export interface CropConfig {
  x: number;
  y: number;
  width: number;
  height: number;
}

export interface ResizeConfig {
  max_width: number;
  max_height: number;
  mode: "fit" | "exact" | "fill";
}

export interface SharpenConfig {
  radius: number;
  threshold: number;
}

export interface FilterConfig {
  grayscale?: boolean;
  invert?: boolean;
  sharpen?: SharpenConfig | null;
  brightness?: number | null;
  contrast?: number | null;
  blur?: number | null;
}

export type ExportConfig =
  | {
      format: "jpeg";
      quality: number;
    }
  | {
      format: "png";
    }
  | {
      format: "webp";
    };

export interface ImageConfig {
  rotation?: RotationConfig | null;
  crop?: CropConfig | null;
  resize?: ResizeConfig | null;
  filters?: FilterConfig | null;
  export: ExportConfig;
}

export declare class Photo {
  #private;
  constructor(manager: Photeryx, id: number);
  get id(): number;
  exportAsBytes(config: ImageConfig): Promise<Uint8Array>;
  exportAsBlob(config: ImageConfig): Promise<Blob>;
  exportAsDataUrl(config: ImageConfig): Promise<string>;
  free(): void;
  _unsafeFreeWithoutDetach(): void;
}

export declare class Photeryx {
  #private;
  get photos(): readonly Photo[];
  addFromFile(file: File): Promise<Photo>;
  addFromUrl(url: string): Promise<Photo>;
  addFromArrayBuffer(buffer: ArrayBuffer): Promise<Photo>;
  exportAllAsBytes(config: ImageConfig): Promise<Uint8Array[]>;
  exportAllAsBlobs(config: ImageConfig): Promise<Blob[]>;
  exportAllAsDataUrls(config: ImageConfig): Promise<string[]>;
  findDuplicates(threshold?: number): Promise<Photo[][]>;
  freeAll(): void;
  _detach(photo: Photo): void;
}

export default Photeryx;

🖼 Using Photeryx

1) Import & Initialize

import Photeryx, { type ImageConfig } from "photeryx";

const ph = new Photeryx();

2) Load Images

const photo1 = await ph.addFromFile(fileInput.files[0]);
const photo2 = await ph.addFromUrl("https://example.com/image.jpg");

// Or from ArrayBuffer
const buffer = await someFetchOrFileApi();
const photo3 = await ph.addFromArrayBuffer(buffer);

3) Configure Processing

const config: ImageConfig = {
  rotation: { degrees: 90 },
  crop: { x: 0, y: 0, width: 800, height: 600 },
  resize: { max_width: 1200, max_height: 1200, mode: "fit" },
  filters: {
    grayscale: false,
    sharpen: { radius: 2, threshold: 1 },
    brightness: 10,
    contrast: 20,
    blur: 1,
  },
  export: { format: "jpeg", quality: 85 },
};

4) Export Options (single image)

// Uint8Array
const bytes = await photo1.exportAsBytes(config);

// Blob
const blob = await photo1.exportAsBlob(config);

// Base64 string (data URL)
const base64 = await photo1.exportAsDataUrl(config);

// If you need a File instance:
const file = new File([blob], "output.jpeg", { type: "image/jpeg" });

5) Export All Loaded Images

// As Uint8Array[]
const allBytes = await ph.exportAllAsBytes(config);

// As Blob[]
const allBlobs = await ph.exportAllAsBlobs(config);

// As data URLs
const allDataUrls = await ph.exportAllAsDataUrls(config);

6) Duplicate Detection

findDuplicates compares all loaded photos and returns groups of Photo instances that are considered duplicates or very similar.

// Optionally pass a threshold (implementation-defined, e.g. 0–100)
const groups = await ph.findDuplicates(90);

// Example shape:
// [
//   [Photo, Photo],       // first duplicate group
//   [Photo, Photo, Photo] // second duplicate group
// ]

for (const group of groups) {
  console.log("Duplicate group:");
  for (const photo of group) {
    console.log("  Photo id:", photo.id);
  }
}

You can still access the flat list of currently loaded photos through ph.photos.

7) Memory Management

Photeryx gives you full control over WebAssembly memory:

photo1.free(); // Free one image
ph.freeAll(); // Free all images

⚠️ After .free() or .freeAll(), freed objects can no longer be used.


🧪 Browser Requirements

| Feature | Support | | --------------------------- | -------- | | WebAssembly | Required | | ES6 Modules | Required | | Offscreen Canvas (optional) | Optional |


📚 Full API Reference

Class: Photeryx

| Member / Method | Description | | ----------------------------- | ------------------------------------------------------------ | | photos: readonly Photo[] | Readonly list of currently loaded photos | | addFromFile(file) | Load an image from a File | | addFromUrl(url) | Fetch and load image from a URL | | addFromArrayBuffer(buffer) | Load image from raw ArrayBuffer | | exportAllAsBytes(config) | Export all loaded images as Uint8Array[] | | exportAllAsBlobs(config) | Export all loaded images as Blob[] | | exportAllAsDataUrls(config) | Export all loaded images as Base64 data URLs (string[]) | | findDuplicates(threshold?) | Find duplicate/similar images, returns groups of Photo[][] | | freeAll() | Free all images from WebAssembly memory |

Class: Photo

| Member / Method | Description | | ------------------------- | ---------------------------------- | | id: number | Stable numeric ID for this photo | | exportAsBytes(config) | Export as Uint8Array | | exportAsBlob(config) | Export as Blob | | exportAsDataUrl(config) | Export as Base64 data URL string | | free() | Free memory of this image |


📄 License

Apache-2.0 © Mehran Taslimi


🔗 Repository

https://github.com/mehranTaslimi/photeryx