import { Kernel, KernelCategory, PaddingMode } from '@/types' export type { KernelCategory } from '@/types' export const KERNEL_CATEGORIES: { value: KernelCategory; label: string; description: string }[] = [ { value: 'blur', label: 'Blur', description: 'Smoothing and noise reduction filters' }, { value: 'sharpen', label: 'Sharpen', description: 'Enhance edges and details' }, { value: 'edge', label: 'Edge Detection', description: 'Find boundaries and contours' }, { value: 'emboss', label: 'Emboss', description: '3D relief and depth effects' }, { value: 'other', label: 'Special Effects', description: 'Creative and artistic filters' }, { value: 'custom', label: 'Custom', description: 'User-defined kernels' }, ] export const PREDEFINED_KERNELS: Kernel[] = [ // Blur Kernels { id: 'box-blur-3x3', name: 'Box Blur 3×3', category: 'blur', matrix: [ [1, 1, 1], [1, 1, 1], [1, 1, 1], ], size: 3, normalize: true, description: 'Simple averaging blur. Each pixel becomes the average of its 3×3 neighborhood.', formula: '1/9 × Σ neighborhood', reference: 'https://en.wikipedia.org/wiki/Box_blur', }, { id: 'box-blur-5x5', name: 'Box Blur 5×5', category: 'blur', matrix: [ [1, 1, 1, 1, 1], [1, 1, 1, 1, 1], [1, 1, 1, 1, 1], [1, 1, 1, 1, 1], [1, 1, 1, 1, 1], ], size: 5, normalize: true, description: 'Larger box blur for stronger smoothing effect.', formula: '1/25 × Σ neighborhood', }, { id: 'gaussian-blur-3x3', name: 'Gaussian Blur 3×3', category: 'blur', matrix: [ [1, 2, 1], [2, 4, 2], [1, 2, 1], ], size: 3, normalize: true, description: 'Gaussian-weighted blur. Preserves edges better than box blur while reducing noise.', formula: '1/16 × G(x,y) where G is Gaussian function', reference: 'https://en.wikipedia.org/wiki/Gaussian_blur', }, { id: 'gaussian-blur-5x5', name: 'Gaussian Blur 5×5', category: 'blur', matrix: [ [1, 4, 6, 4, 1], [4, 16, 24, 16, 4], [6, 24, 36, 24, 6], [4, 16, 24, 16, 4], [1, 4, 6, 4, 1], ], size: 5, normalize: true, description: 'Larger Gaussian kernel for stronger blur with better frequency response.', formula: '1/256 × G(x,y) where G is Gaussian function', }, // Sharpen Kernels { id: 'sharpen', name: 'Sharpen', category: 'sharpen', matrix: [ [0, -1, 0], [-1, 5, -1], [0, -1, 0], ], size: 3, normalize: false, description: 'Enhances edges by subtracting blurred version from original (unsharp masking).', formula: '5×center - Σ(neighbors)', reference: 'https://en.wikipedia.org/wiki/Unsharp_masking', }, { id: 'sharpen-strong', name: 'Strong Sharpen', category: 'sharpen', matrix: [ [-1, -1, -1], [-1, 9, -1], [-1, -1, -1], ], size: 3, normalize: false, description: 'More aggressive sharpening with stronger edge enhancement.', formula: '9×center - Σ(all neighbors)', }, { id: 'unsharp-mask', name: 'Unsharp Mask 5×5', category: 'sharpen', matrix: [ [-1, -4, -6, -4, -1], [-4, -16, -24, -16, -4], [-6, -24, 476, -24, -6], [-4, -16, -24, -16, -4], [-1, -4, -6, -4, -1], ], size: 5, normalize: false, description: 'Classic unsharp mask: original - blurred. Large kernel for broad edge enhancement.', formula: 'Original - GaussianBlur(original)', }, // Edge Detection Kernels { id: 'sobel-x', name: 'Sobel X (Horizontal Edges)', category: 'edge', matrix: [ [-1, 0, 1], [-2, 0, 2], [-1, 0, 1], ], size: 3, normalize: false, description: 'Detects vertical edges (horizontal gradients). Highlights left-right transitions.', formula: 'Gx = ∂I/∂x', reference: 'https://en.wikipedia.org/wiki/Sobel_operator', }, { id: 'sobel-y', name: 'Sobel Y (Vertical Edges)', category: 'edge', matrix: [ [-1, -2, -1], [0, 0, 0], [1, 2, 1], ], size: 3, normalize: false, description: 'Detects horizontal edges (vertical gradients). Highlights top-bottom transitions.', formula: 'Gy = ∂I/∂y', }, { id: 'sobel-combined', name: 'Sobel Combined (Magnitude)', category: 'edge', matrix: [ [-1, -2, -1], [0, 0, 0], [1, 2, 1], ], size: 3, normalize: false, description: 'Combined Sobel magnitude: √(Gx² + Gy²). Shows all edges regardless of direction.', formula: '√(Gx² + Gy²)', }, { id: 'prewitt-x', name: 'Prewitt X', category: 'edge', matrix: [ [-1, 0, 1], [-1, 0, 1], [-1, 0, 1], ], size: 3, normalize: false, description: 'Similar to Sobel but with uniform weights. Faster but less noise-resistant.', formula: 'Gx = ∂I/∂x (uniform weights)', }, { id: 'prewitt-y', name: 'Prewitt Y', category: 'edge', matrix: [ [-1, -1, -1], [0, 0, 0], [1, 1, 1], ], size: 3, normalize: false, description: 'Prewitt vertical edge detector.', formula: 'Gy = ∂I/∂y (uniform weights)', }, { id: 'roberts-cross', name: 'Roberts Cross', category: 'edge', matrix: [ [1, 0], [0, -1], ], size: 2, normalize: false, description: 'Simple 2×2 diagonal edge detector. Very fast but noisy.', formula: 'Diagonal gradient approximation', }, { id: 'laplacian', name: 'Laplacian', category: 'edge', matrix: [ [0, 1, 0], [1, -4, 1], [0, 1, 0], ], size: 3, normalize: false, description: 'Second derivative operator. Detects edges at zero-crossings. Isotropic (rotation-invariant).', formula: '∇²I = ∂²I/∂x² + ∂²I/∂y²', reference: 'https://en.wikipedia.org/wiki/Discrete_Laplacian', }, { id: 'laplacian-diagonal', name: 'Laplacian (with Diagonals)', category: 'edge', matrix: [ [1, 1, 1], [1, -8, 1], [1, 1, 1], ], size: 3, normalize: false, description: 'Laplacian including diagonal neighbors. More isotropic response.', formula: '∇²I including diagonals', }, // Emboss Kernels { id: 'emboss', name: 'Emboss', category: 'emboss', matrix: [ [-2, -1, 0], [-1, 1, 1], [0, 1, 2], ], size: 3, normalize: false, description: 'Creates 3D relief effect. Light appears to come from top-left.', formula: 'Directional derivative at 45°', reference: 'https://en.wikipedia.org/wiki/Embossing_(image_processing)', }, { id: 'emboss-strong', name: 'Strong Emboss', category: 'emboss', matrix: [ [-3, -2, -1], [-2, 0, 2], [-1, 2, 3], ], size: 3, normalize: false, description: 'More pronounced embossing effect.', }, { id: 'emboss-bottom-right', name: 'Emboss (Bottom-Right Light)', category: 'emboss', matrix: [ [2, 1, 0], [1, 1, -1], [0, -1, -2], ], size: 3, normalize: false, description: 'Emboss with light source from bottom-right.', }, // Special Effects { id: 'motion-blur', name: 'Motion Blur (Horizontal)', category: 'other', matrix: [ [1, 0, 0, 0, 0], [0, 1, 0, 0, 0], [0, 0, 1, 0, 0], [0, 0, 0, 1, 0], [0, 0, 0, 0, 1], ], size: 5, normalize: true, description: 'Simulates horizontal camera motion. Diagonal line of 1s.', formula: 'Average along motion direction', }, { id: 'motion-blur-vertical', name: 'Motion Blur (Vertical)', category: 'other', matrix: [ [0, 0, 0, 0, 1], [0, 0, 0, 1, 0], [0, 0, 1, 0, 0], [0, 1, 0, 0, 0], [1, 0, 0, 0, 0], ], size: 5, normalize: true, description: 'Simulates vertical camera motion.', }, { id: 'outline', name: 'Outline', category: 'other', matrix: [ [-1, -1, -1], [-1, 8, -1], [-1, -1, -1], ], size: 3, normalize: false, description: 'Extracts outlines/edges. Similar to Laplacian but stronger center weight.', formula: '8×center - Σ(neighbors)', }, { id: 'ridge-detection', name: 'Ridge Detection', category: 'other', matrix: [ [-1, -1, -1], [-1, 8, -1], [-1, -1, -1], ], size: 3, normalize: false, description: 'Highlights ridges (bright lines on dark background).', }, { id: 'identity', name: 'Identity (No Change)', category: 'other', matrix: [ [0, 0, 0], [0, 1, 0], [0, 0, 0], ], size: 3, normalize: false, description: 'Returns the original image unchanged. Useful as baseline.', formula: 'I\' = I', }, ] export function getKernelById(id: string): Kernel | undefined { return PREDEFINED_KERNELS.find((k) => k.id === id) } export function getKernelsByCategory(category: KernelCategory): Kernel[] { return PREDEFINED_KERNELS.filter((k) => k.category === category) } export function normalizeKernel(matrix: number[][]): number[][] { const sum = matrix.flat().reduce((a, b) => a + b, 0) if (sum === 0) return matrix return matrix.map((row) => row.map((val) => val / sum)) } export function createCustomKernel( name: string, matrix: number[][], normalize: boolean, category: KernelCategory = 'custom', description = 'Custom user-defined kernel' ): Kernel { return { id: `custom-${Date.now()}`, name, category, matrix, size: matrix.length, normalize, description, } } export const PADDING_MODES: { value: PaddingMode; label: string; description: string }[] = [ { value: 'zero', label: 'Zero Padding', description: 'Fill outside with zeros (black)' }, { value: 'reflect', label: 'Reflect Padding', description: 'Mirror the image at boundaries' }, { value: 'replicate', label: 'Replicate Padding', description: 'Repeat edge pixels outward' }, { value: 'wrap', label: 'Wrap Padding', description: 'Tile the image (torus topology)' }, ]