openseadragon-filters
v2.2.0
Published
A plugin that provides the capability to apply filters to images in OpenSeadragon.
Maintainers
Readme
OpenSeadragon Filters
A high-performance OpenSeadragon plugin that provides real-time image filtering capabilities using WebGL acceleration.
🎨 Live Demo | 📦 NPM Package
Features
- ⚡ WebGL-accelerated filtering for optimal performance
- 🎯 Multiple built-in filters: brightness, contrast, gamma, threshold, invert, greyscale
- 🔧 Customizable: create your own filters
- 🎭 Per-item filtering: apply different filters to different images (canvas mode)
- 🔄 Two rendering modes: tile-based (canvas) or viewport-based (WebGL overlay)
- 📦 TypeScript support: full type definitions included
- 🌐 Modern ESM/CJS: supports both module formats
Requirements
- OpenSeadragon 5.0+
- Node.js 20+ (for development)
Installation
npm install openseadragon-filtersor
yarn add openseadragon-filtersQuick Start
Canvas-Based Filtering (Tile-by-Tile)
import OpenSeadragon from 'openseadragon';
import { initializeFiltering, BRIGHTNESS } from 'openseadragon-filters';
const viewer = OpenSeadragon({
id: 'viewer',
tileSources: 'path/to/image.dzi'
});
const filterPlugin = initializeFiltering(viewer);
filterPlugin.setFilterOptions({
filters: {
processors: BRIGHTNESS(50)
}
});WebGL-Based Filtering (Viewport Overlay)
import OpenSeadragon from 'openseadragon';
import { initWebGLFiltering, BRIGHTNESS_WEBGL } from 'openseadragon-filters';
const viewer = OpenSeadragon({
id: 'viewer',
tileSources: 'path/to/image.dzi'
});
// Initialize after viewer is ready
viewer.addOnceHandler('open', () => {
const filterPlugin = initWebGLFiltering(viewer);
filterPlugin.setFilters([BRIGHTNESS_WEBGL(50)]);
});Usage
This plugin provides two filtering approaches:
1. Canvas-Based Filtering (Tile-by-Tile)
Filters each tile individually as it loads. Best for per-tile effects and compatibility.
Single Filter
import { initializeFiltering, BRIGHTNESS } from 'openseadragon-filters';
const filterPlugin = initializeFiltering(viewer);
filterPlugin.setFilterOptions({
filters: {
processors: BRIGHTNESS(50)
}
});Multiple Filters
Filters are applied in the order specified:
import { initializeFiltering, BRIGHTNESS, INVERT, CONTRAST } from 'openseadragon-filters';
filterPlugin.setFilterOptions({
filters: {
processors: [
BRIGHTNESS(-50),
CONTRAST(1.5),
INVERT()
]
}
});Per-Item Filtering
Apply different filters to specific images:
import { initializeFiltering, BRIGHTNESS, INVERT } from 'openseadragon-filters';
filterPlugin.setFilterOptions({
filters: [
{
items: viewer.world.getItemAt(0),
processors: [BRIGHTNESS(50)]
},
{
items: [viewer.world.getItemAt(1), viewer.world.getItemAt(2)],
processors: [INVERT()]
}
]
});Note: If the
itemsproperty is not specified, filters are applied to all items in the viewer.
Load Modes
The canvas-based plugin supports two rendering modes:
Async Mode (Default)
Tiles are progressively filtered as they load, preventing browser freezing:
filterPlugin.setFilterOptions({
filters: { processors: BRIGHTNESS(50) },
loadMode: 'async' // default
});Sync Mode
Filters are applied immediately for faster rendering with simple filters:
filterPlugin.setFilterOptions({
filters: { processors: BRIGHTNESS(50) },
loadMode: 'sync'
});Tip: Use sync mode for fast, synchronous filters. Use async mode for complex or slow filters to maintain UI responsiveness.
2. WebGL-Based Filtering (Viewport Overlay)
Applies filters to the entire viewport using WebGL. Best for real-time performance and viewport-level effects.
Important: Initialize WebGL filtering after the viewer is ready using the
openevent.
Basic Usage
import { initWebGLFiltering, BRIGHTNESS_WEBGL, CONTRAST_WEBGL } from 'openseadragon-filters';
viewer.addOnceHandler('open', () => {
const filterPlugin = initWebGLFiltering(viewer);
// Single filter
filterPlugin.setFilters([BRIGHTNESS_WEBGL(50)]);
// Multiple filters
filterPlugin.setFilters([
BRIGHTNESS_WEBGL(50),
CONTRAST_WEBGL(1.5)
]);
// Clear filters
filterPlugin.clearFilters();
});Custom WebGL Filters
import { convertToWebGLFilter } from 'openseadragon-filters';
const customShader = `
precision mediump float;
uniform sampler2D u_image;
uniform float u_intensity;
varying vec2 v_texCoord;
void main() {
vec4 color = texture2D(u_image, v_texCoord);
gl_FragColor = vec4(color.rgb * u_intensity, color.a);
}
`;
viewer.addOnceHandler('open', () => {
const filterPlugin = initWebGLFiltering(viewer);
const customFilter = convertToWebGLFilter('custom', customShader, { u_intensity: 1.5 });
filterPlugin.setFilters([customFilter]);
});Choosing Between Canvas and WebGL
| Feature | Canvas-Based | WebGL-Based | |---------|-------------|-------------| | Performance | Good for simple filters | Excellent for all filters | | Per-tile filtering | ✅ Yes | ❌ No (viewport only) | | Per-item filtering | ✅ Yes | ❌ No | | Custom filters | Canvas API | GLSL shaders | | Browser support | Universal | Requires WebGL | | Best for | Tile-specific effects, compatibility | Real-time performance, viewport effects |
Built-in Filters
Canvas Filters
Use with initializeFiltering():
BRIGHTNESS(adjustment)
Adjusts pixel intensity.
- Range: -255 to 255
- Effect: Negative values darken, positive values brighten
BRIGHTNESS(50) // Increase brightness
BRIGHTNESS(-50) // Decrease brightnessCONTRAST(adjustment)
Adjusts image contrast.
- Range: 0 to ∞ (typically 0-3)
- Effect: Values < 1 reduce contrast, values > 1 increase contrast
CONTRAST(1.5) // Increase contrast
CONTRAST(0.5) // Decrease contrastGAMMA(adjustment)
Applies gamma correction.
- Range: 0 to 5
- Effect: Values < 1 darken, values > 1 brighten
GAMMA(2.2) // Standard gamma correction
GAMMA(0.5) // Darken imageTHRESHOLDING(threshold)
Converts image to black and white based on threshold.
- Range: 0 to 255
- Effect: Pixels ≥ threshold become white, others become black
THRESHOLDING(128) // Standard thresholdGREYSCALE()
Converts image to greyscale.
GREYSCALE()INVERT()
Inverts all colors.
INVERT()WebGL Filters
Use with initWebGLFiltering(). Same parameters as canvas filters but with _WEBGL suffix:
import {
BRIGHTNESS_WEBGL,
CONTRAST_WEBGL,
GAMMA_WEBGL,
THRESHOLDING_WEBGL,
GREYSCALE_WEBGL,
INVERT_WEBGL
} from 'openseadragon-filters';
// Usage
filterPlugin.setFilters([
BRIGHTNESS_WEBGL(50),
CONTRAST_WEBGL(1.5),
GAMMA_WEBGL(2.2)
]);Custom Filters
Canvas Custom Filters
Create custom filters by implementing a function that processes canvas context:
function customFilter(context, callback) {
const imageData = context.getImageData(0, 0, context.canvas.width, context.canvas.height);
const pixels = imageData.data;
// Modify pixels (RGBA format)
for (let i = 0; i < pixels.length; i += 4) {
pixels[i] = 255 - pixels[i]; // Red
pixels[i + 1] = 255 - pixels[i + 1]; // Green
pixels[i + 2] = 255 - pixels[i + 2]; // Blue
// pixels[i + 3] is alpha
}
context.putImageData(imageData, 0, 0);
callback();
}
// Use the custom filter
filterPlugin.setFilterOptions({
filters: {
processors: customFilter
}
});Custom Filter Requirements
- Accept a CanvasRenderingContext2D as the first parameter
- Accept a callback function as the second parameter
- Call the callback when processing is complete
- Use
context.getImageData()to read pixels - Use
context.putImageData()to write modified pixels
API Reference
Canvas-Based API
initializeFiltering(viewer)
Initializes the filtering plugin for an OpenSeadragon viewer.
Parameters:
viewer(OpenSeadragon.Viewer): The OpenSeadragon viewer instance
Returns: FilterPlugin instance
filterPlugin.setFilterOptions(options)
Configures and applies filters.
Parameters:
options.filters(Object|Array): Filter configurationprocessors(Function|Array): Single filter or array of filtersitems(TiledImage|Array): Optional. Specific items to filter
options.loadMode(String): Optional. 'async' (default) or 'sync'
WebGL-Based API
initWebGLFiltering(viewer)
Initializes WebGL viewport filtering for an OpenSeadragon viewer.
Parameters:
viewer(OpenSeadragon.Viewer): The OpenSeadragon viewer instance
Returns: Object with methods:
setFilters(filters): Apply WebGL filtersclearFilters(): Remove all filtersdestroy(): Clean up resources
filterPlugin.setFilters(filters)
Applies WebGL filters to the viewport.
Parameters:
filters(Array): Array of WebGLFilterConfig objects
Example:
filterPlugin.setFilters([
BRIGHTNESS_WEBGL(50),
CONTRAST_WEBGL(1.5)
]);convertToWebGLFilter(name, shader, uniforms)
Creates a custom WebGL filter configuration.
Parameters:
name(String): Filter identifiershader(String): GLSL fragment shader sourceuniforms(Object): Shader uniform values
Returns: WebGLFilterConfig object
TypeScript Support
Full TypeScript definitions are included:
import OpenSeadragon from 'openseadragon';
import {
initializeFiltering,
initWebGLFiltering,
BRIGHTNESS,
BRIGHTNESS_WEBGL,
FilterPlugin
} from 'openseadragon-filters';
// Canvas-based
const viewer: OpenSeadragon.Viewer = OpenSeadragon({ id: 'viewer' });
const filterPlugin: FilterPlugin = initializeFiltering(viewer);
filterPlugin.setFilterOptions({
filters: {
processors: BRIGHTNESS(50)
}
});
// WebGL-based
viewer.addOnceHandler('open', () => {
const webglPlugin = initWebGLFiltering(viewer);
webglPlugin.setFilters([BRIGHTNESS_WEBGL(50)]);
});Known Limitations
Tile Edge Effects
The canvas-based plugin processes tiles independently and does not handle cross-tile boundaries. Kernel-based filters may produce visible artifacts at tile edges.
Development
Setup
git clone https://github.com/rssaini01/openseadragon-filters.git
cd openseadragon-filters
npm installBuild
npm run build # Build library
npm run dev # Start demo dev server
npm run build:demo # Build demo siteTesting
npm test # Run tests
npm run test:watch # Run tests in watch modeProject Structure
openseadragon-filters/
├── src/ # Source code
│ ├── index.ts # Main entry point
│ ├── predefined-filters.ts
│ └── webgl-*.ts # WebGL implementation
├── site/ # Demo application
├── tests/ # Test suite
└── dist/ # Built output
├── esm/ # ES modules
├── cjs/ # CommonJS
└── types/ # TypeScript definitionsContributing
Contributions are welcome! Please:
- Fork the repository
- Create a feature branch (
git checkout -b feature/amazing-feature) - Commit your changes (
git commit -m 'Add amazing feature') - Push to the branch (
git push origin feature/amazing-feature) - Open a Pull Request
Please ensure:
- Tests pass (
npm test) - Code follows existing style
- TypeScript types are updated
License
MIT © Ravi Shankar Saini
See LICENSE for details.
Acknowledgments
- Built for OpenSeadragon
- Inspired by image processing needs in digital libraries and archives
