ArtistAPhoto Documentation
Complete documentation for the ArtistAPhoto image editing SDK.
Getting Started
ArtistAPhoto is a powerful browser-based image editing SDK that provides a complete toolkit for image manipulation. With support for filters, adjustments, transformations, text overlays, shapes, and full undo/redo functionality, it's designed to integrate seamlessly into any web application.
Key Features
- 10 Professional Filters - Grayscale, sepia, blur, sharpen, vintage, invert, vignette, posterize, pixelate, edge detection
- 5 Image Adjustments - Brightness, contrast, saturation, exposure, temperature
- Transformations - Crop, resize with quality control
- Overlays - Text with full styling, shapes (rectangles, ellipses)
- Non-destructive Editing - Original image preserved, full undo/redo
- High Performance - Web Workers for heavy operations
- TypeScript Ready - Full type definitions included
- Multiple Export Formats - JPEG, PNG, WebP
Quick Example
import { ArtistAPhoto } from 'artistaphoto';
// Load an image
const editor = await ArtistAPhoto.fromFile(file);
// Apply edits
editor
.crop({ x: 50, y: 50, width: 400, height: 400 })
.filter('vintage', 0.8)
.brightness(10)
.resize(800, 600);
// Download result
await editor.download('edited-photo.jpg', 'image/jpeg', 0.9);Installation
npm
npm install artistaphotoyarn
yarn add artistaphotopnpm
pnpm add artistaphotoCDN (Browser)
<script src="https://unpkg.com/artistaphoto/dist/index.global.js"></script>
<script>
const { ArtistAPhoto } = window.artistaphoto;
</script>ES Module Import
import { ArtistAPhoto } from 'artistaphoto';CommonJS
const { ArtistAPhoto } = require('artistaphoto');Licensing
ArtistAPhoto is a commercial SDK with a free trial mode.
Trial Mode (No License)
Without a license key, the SDK operates in trial mode:
| Feature | Trial Mode |
|---|---|
| All editing features | Available |
| Preview (toCanvas) | No watermark |
| Export (toBlob, toDataURL, download) | With watermark |
Activating Your License
import { ArtistAPhoto, LicenseError } from 'artistaphoto';
async function activateLicense() {
try {
const licenseInfo = await ArtistAPhoto.setLicenseKey('YOUR-LICENSE-KEY');
console.log('License activated!', licenseInfo);
} catch (error) {
if (error instanceof LicenseError) {
console.error('License error:', error.code, error.message);
}
}
}License Methods
| Method | Description |
|---|---|
| setLicenseKey(key) | Activate a license key |
| isLicenseValid() | Check if license is valid |
| getLicenseInfo() | Get license details |
| clearLicense() | Deactivate license (returns to trial) |
| refreshLicense() | Force re-validation |
Core Concepts
Fluent API
ArtistAPhoto uses a fluent (chainable) API pattern. Most methods return this, allowing you to chain operations:
editor
.crop({ x: 0, y: 0, width: 500, height: 500 })
.filter('grayscale')
.brightness(20)
.resize(400, 400);Non-Destructive Editing
All edits are stored as operations in a queue. The original image is never modified, allowing you to:
- Undo/redo any operation
- Reset to the original image at any time
- Preview changes before exporting
Operation Queue
Operations are applied in order when you call preview(), toCanvas(), toBlob(), toDataURL(), or download().
// Operations are queued, not immediately applied
editor.brightness(20); // Queued
editor.contrast(10); // Queued
// Operations applied when rendering
const canvas = await editor.preview();Loading Images
ArtistAPhoto provides multiple ways to load images.
From URL
const editor = await ArtistAPhoto.fromUrl('https://example.com/image.jpg');Note: The image URL must be CORS-enabled or same-origin.
From File Input
const fileInput = document.getElementById('fileInput');
fileInput.addEventListener('change', async (e) => {
const file = e.target.files[0];
const editor = await ArtistAPhoto.fromFile(file);
});From Canvas Element
const canvas = document.getElementById('myCanvas');
const editor = await ArtistAPhoto.fromCanvas(canvas);From Image Element
const img = document.getElementById('myImage');
const editor = await ArtistAPhoto.fromImageElement(img);Transformations
Crop
Extract a rectangular region from the image.
editor.crop({
x: number, // Left position (required)
y: number, // Top position (required)
width: number, // Crop width (required)
height: number // Crop height (required)
});
// Example: Crop a 300x300 region starting at position (50, 50)
editor.crop({ x: 50, y: 50, width: 300, height: 300 });Resize
Scale the image to new dimensions.
editor.resize(
width: number, // Target width (required)
height: number, // Target height (required)
options?: {
quality?: 'low' | 'medium' | 'high', // Default: 'medium'
maintainAspectRatio?: boolean // Default: false
}
);
// Examples
editor.resize(800, 600);
// High-quality resize maintaining aspect ratio
editor.resize(800, 600, {
quality: 'high',
maintainAspectRatio: true
});Quality Levels
| Quality | Description |
|---|---|
| low | Fastest, suitable for thumbnails |
| medium | Balanced quality and speed |
| high | Best quality, uses multi-step algorithm |
Filters
Apply visual filters to the image. All filters accept an intensity parameter (0 to 1).
editor.filter(type: FilterType, intensity?: number);Available Filters
| Filter | Description | Default Intensity |
|---|---|---|
| grayscale | Convert to black and white | 1.0 |
| sepia | Warm, vintage brown tones | 1.0 |
| blur | Gaussian blur effect | 1.0 |
| sharpen | Enhance edges and details | 1.0 |
| vintage | Retro look with vignette | 1.0 |
| invert | Negative/inverted colors | 1.0 |
| vignette | Darkened edges | 1.0 |
| posterize | Reduce color levels | 1.0 |
| pixelate | Pixelated/mosaic effect | 1.0 |
| edgeDetection | Sobel edge detection | 1.0 |
Examples
// Full intensity grayscale
editor.filter('grayscale');
// 50% sepia effect
editor.filter('sepia', 0.5);
// Light blur
editor.filter('blur', 0.3);
// Combine multiple filters
editor
.filter('vintage', 0.7)
.filter('vignette', 0.5);Adjustments
Fine-tune image properties. All adjustments accept values from -100 to 100.
Brightness
editor.brightness(value: number); // -100 to 100| Value | Effect |
|---|---|
| -100 | Completely dark |
| 0 | No change |
| 100 | Completely bright |
Contrast
editor.contrast(value: number); // -100 to 100Saturation
editor.saturation(value: number); // -100 to 100Exposure
editor.exposure(value: number); // -100 to 100Temperature
editor.temperature(value: number); // -100 to 100Combined Example
// Portrait enhancement
editor
.brightness(5)
.contrast(10)
.saturation(-5)
.temperature(10);Text & Shapes
Adding Text
Add text overlays with full styling options.
editor.addText({
// Required
text: string,
x: number,
y: number,
// Optional styling
fontSize?: number, // Default: 24
fontFamily?: string, // Default: 'Arial'
color?: string, // Default: '#000000'
bold?: boolean, // Default: false
italic?: boolean, // Default: false
align?: 'left' | 'center' | 'right',
rotation?: number, // Rotation in degrees
// Optional stroke (outline)
stroke?: { color: string, width: number },
// Optional shadow
shadow?: { color: string, blur: number, offsetX: number, offsetY: number }
});Text Examples
// Simple text
editor.addText({ text: 'Hello World', x: 100, y: 100 });
// Styled text
editor.addText({
text: 'ArtistAPhoto',
x: 200,
y: 150,
fontSize: 48,
fontFamily: 'Georgia',
color: '#FF0000',
bold: true,
italic: true
});
// Text with stroke and shadow
editor.addText({
text: 'WATERMARK',
x: 300,
y: 200,
fontSize: 36,
color: '#FFFFFF',
stroke: { color: '#000000', width: 2 },
shadow: { color: 'rgba(0, 0, 0, 0.5)', blur: 4, offsetX: 2, offsetY: 2 }
});Adding Shapes
editor.addShape({
type: 'rectangle' | 'ellipse',
x: number,
y: number,
width: number,
height: number,
fill?: string, // Fill color
rotation?: number, // Rotation in degrees
stroke?: { color: string, width: number }
});Shape Examples
// Filled rectangle
editor.addShape({
type: 'rectangle',
x: 50, y: 50,
width: 200, height: 100,
fill: '#FF0000'
});
// Circle (ellipse with equal width/height)
editor.addShape({
type: 'ellipse',
x: 150, y: 150,
width: 100, height: 100,
fill: '#00FF00'
});
// Rectangle with stroke only
editor.addShape({
type: 'rectangle',
x: 100, y: 100,
width: 150, height: 80,
stroke: { color: '#0000FF', width: 3 }
});Undo/Redo
ArtistAPhoto maintains a complete history of operations, allowing full undo/redo support.
// Undo last operation
editor.undo();
// Redo previously undone operation
editor.redo();
// Check availability
if (editor.canUndo()) {
editor.undo();
}
if (editor.canRedo()) {
editor.redo();
}
// Reset to original image
editor.reset();
// Get operation history
const history = editor.getHistory();Exporting
Export the edited image in various formats.
Preview (Canvas)
const canvas = await editor.preview();
document.body.appendChild(canvas);Note: Preview never includes watermark, even in trial mode.
To Blob
const blob = await editor.toBlob(
format?: 'image/jpeg' | 'image/png' | 'image/webp',
quality?: number // 0-1 for JPEG/WebP
);
// Upload example
const formData = new FormData();
formData.append('image', blob, 'edited.jpg');
await fetch('/upload', { method: 'POST', body: formData });To Data URL
const dataURL = await editor.toDataURL('image/jpeg', 0.9);
document.getElementById('result').src = dataURL;Download
// Download as JPEG with 90% quality
await editor.download('my-photo.jpg', 'image/jpeg', 0.9);
// Download as PNG (lossless)
await editor.download('my-photo.png', 'image/png');
// Download as WebP with 85% quality
await editor.download('my-photo.webp', 'image/webp', 0.85);Format Comparison
| Format | Compression | Transparency | Best For |
|---|---|---|---|
| JPEG | Lossy | No | Photos |
| PNG | Lossless | Yes | Graphics, screenshots |
| WebP | Both | Yes | Web (smaller files) |
Error Handling
ArtistAPhoto provides specific error types for different failure scenarios.
import {
ArtistAPhoto,
LicenseError,
ImageLoadError,
InvalidCropError,
InvalidDimensionsError
} from 'artistaphoto';
async function editImage(file) {
try {
await ArtistAPhoto.setLicenseKey(process.env.LICENSE_KEY);
const editor = await ArtistAPhoto.fromFile(file);
editor.filter('vintage').brightness(10);
return await editor.toBlob('image/jpeg', 0.9);
} catch (error) {
if (error instanceof LicenseError) {
console.error('License problem:', error.code);
} else if (error instanceof ImageLoadError) {
console.error('Could not load image');
} else {
console.error('Unexpected error:', error);
}
}
}License Error Codes
| Code | Description |
|---|---|
| INVALID_KEY | License key not found or invalid format |
| LICENSE_EXPIRED | License has expired |
| LICENSE_REVOKED | License was revoked |
| LICENSE_DISABLED | License was disabled |
| NO_LICENSE | No license key set (when calling refresh) |
TypeScript
ArtistAPhoto is written in TypeScript and includes full type definitions.
Importing Types
import {
ArtistAPhoto,
LicenseError,
ImageLoadError,
InvalidCropError,
InvalidDimensionsError,
FilterType,
ExportFormat,
CropOptions,
ResizeOptions,
TextOptions,
ShapeOptions,
LicenseInfo,
LicenseConfig
} from 'artistaphoto';Type Definitions
type FilterType =
| 'grayscale' | 'sepia' | 'blur' | 'sharpen' | 'vintage'
| 'invert' | 'vignette' | 'posterize' | 'pixelate' | 'edgeDetection';
type ExportFormat = 'image/jpeg' | 'image/png' | 'image/webp';
interface CropOptions {
x: number;
y: number;
width: number;
height: number;
}
interface ResizeOptions {
quality?: 'low' | 'medium' | 'high';
maintainAspectRatio?: boolean;
}Performance
ArtistAPhoto is optimized for performance in browser environments.
Web Workers
Heavy operations automatically use Web Workers to avoid blocking the main thread:
- Blur filter
- Sharpen filter
- Edge detection filter
- Pixelate filter
Best Practices
// 1. Process at display size, not original size
editor
.resize(1200, 900)
.filter('blur', 0.5); // Much faster on smaller image
// 2. Chain operations before rendering
editor
.brightness(10)
.contrast(5)
.filter('vintage');
const result = await editor.toBlob();
// 3. Use appropriate quality settings
// Thumbnails: low quality resize, high compression
editor.resize(200, 200, { quality: 'low' });
await editor.toBlob('image/jpeg', 0.6);Browser Support
Supported Browsers
| Browser | Version |
|---|---|
| Chrome | Last 2 versions |
| Edge | Last 2 versions |
| Firefox | Last 2 versions |
| Safari | Last 2 versions |
Required APIs
- Canvas API
- ES2020
- Fetch API (for URL loading)
- Blob API (for export)
FAQ
Can I use ArtistAPhoto without a license?
Yes! The SDK works fully without a license. The only limitation is that exported images will have a watermark. This is perfect for evaluation, testing, and development.
How does the watermark look?
The watermark displays "ArtistAPhoto - UNLICENSED" in a diagonal pattern across the entire image. It's semi-transparent (30% opacity) gray text.
Does ArtistAPhoto modify the original image?
No. ArtistAPhoto uses non-destructive editing. The original image is preserved, and all edits are stored as operations. You can always call reset() to return to the original.
How large images can ArtistAPhoto handle?
This depends on the browser and device memory. Generally up to 4000x4000 pixels works well on desktop, and up to 2000x2000 pixels on mobile devices.
Troubleshooting
Image won't load from URL
Problem: ImageLoadError when loading from URL.
Solutions:
- Check if the URL is accessible
- Verify CORS headers on the server
- Try loading from same origin
- Use fromFile() instead with a file input
Export quality is poor
Solutions:
- Use higher quality setting: toBlob('image/jpeg', 0.95)
- Use PNG for lossless: toBlob('image/png')
- Avoid multiple resize operations
- Use quality: 'high' for resize
Watermark appears even with license
Solutions:
- Verify isLicenseValid() returns true
- Ensure setLicenseKey() completed successfully before export
- Check getLicenseInfo() for expiration
- Try refreshLicense() to update cached license
Support
- Documentation: You're reading it!
- Issues: GitHub Issues
- Purchase: polar.sh/artistaphoto
Last updated: January 2025