image-js
Version:
Image processing and manipulation in JavaScript
71 lines (64 loc) • 1.84 kB
text/typescript
import { match } from 'ts-pattern';
import type { BitDepth, Image } from '../Image.js';
import {
PREWITT_X,
PREWITT_Y,
SCHARR_X,
SCHARR_Y,
SOBEL_X,
SOBEL_Y,
} from '../utils/constants/kernels.js';
import type { BorderType } from '../utils/interpolateBorder.js';
export const DerivativeFilter = {
SOBEL: 'sobel',
SCHARR: 'scharr',
PREWITT: 'prewitt',
// todo: handle even sized kernels to implement Roberts' filter
// for 2x2 matrices, the current pixel corresponds to the top-left
// ROBERTS = 'roberts',
} as const;
export type DerivativeFilter =
(typeof DerivativeFilter)[keyof typeof DerivativeFilter];
export interface DerivativeFilterOptions {
/**
* Algorithm to use for the derivative filter.
* @default `SOBEL`
*/
filter?: DerivativeFilter;
/**
* Specify how the borders should be handled.
* @default `'replicate'`
*/
borderType?: BorderType;
/**
* Value of the border if BorderType is 'constant'.
* @default `0`
*/
borderValue?: number;
/**
* Specify the bit depth of the resulting image.
* @default `image.bitDepth`
*/
bitDepth?: BitDepth;
}
/**
* Apply a derivative filter to an image.
* @param image - Image to process.
* @param options - Derivative filter options.
* @returns The processed image.
*/
export function derivativeFilter(
image: Image,
options: DerivativeFilterOptions = {},
): Image {
const { filter = 'sobel' } = options;
const kernels = match<
DerivativeFilter,
{ kernelX: number[][]; kernelY: number[][] }
>(filter)
.with('sobel', () => ({ kernelX: SOBEL_X, kernelY: SOBEL_Y }))
.with('scharr', () => ({ kernelX: SCHARR_X, kernelY: SCHARR_Y }))
.with('prewitt', () => ({ kernelX: PREWITT_X, kernelY: PREWITT_Y }))
.exhaustive();
return image.gradientFilter({ ...kernels, ...options });
}