diff options
author | elioat <elioat@tilde.institute> | 2025-04-06 13:33:14 -0400 |
---|---|---|
committer | elioat <elioat@tilde.institute> | 2025-04-06 13:33:14 -0400 |
commit | e0e75864e0d9981236bd50e2febdd0edd95019ea (patch) | |
tree | 8714af06fd451c659d8bc97626a23b718278d7d5 | |
parent | 473754434bed0310cab510bc2dd2b408c928f702 (diff) | |
download | tour-e0e75864e0d9981236bd50e2febdd0edd95019ea.tar.gz |
*
-rw-r--r-- | js/leibovitz/balance.js | 21 | ||||
-rw-r--r-- | js/leibovitz/blur.js | 32 | ||||
-rw-r--r-- | js/leibovitz/color.js | 24 | ||||
-rw-r--r-- | js/leibovitz/contrast.js | 16 | ||||
-rw-r--r-- | js/leibovitz/dither.js | 36 | ||||
-rw-r--r-- | js/leibovitz/leibovitz.js | 76 |
6 files changed, 52 insertions, 153 deletions
diff --git a/js/leibovitz/balance.js b/js/leibovitz/balance.js index b489a62..aeff62e 100644 --- a/js/leibovitz/balance.js +++ b/js/leibovitz/balance.js @@ -1,18 +1,15 @@ /** - * @fileoverview White balance management module implementing temperature-based color adjustment. + * White balance management module implementing temperature-based color adjustment. * - * @description * Implements white balance adjustment using temperature-based RGB channel scaling. * Provides non-linear temperature adjustment for natural color correction. * - * @architecture * Implements the following design patterns: - * - Observer Pattern: For state management and effect application - * - Factory Pattern: For UI initialization - * - Strategy Pattern: For temperature adjustment algorithm - * - Command Pattern: For state reset operations + * - Observer Pattern: state management and effect application + * - Factory Pattern: UI initialization + * - Strategy Pattern: temperature adjustment algorithm + * - Command Pattern: state reset operations * - * @algorithm * White balance adjustment process: * 1. Convert temperature to ratio relative to neutral (6500K) * 2. Apply non-linear scaling (0.2 factor) to red and blue channels @@ -34,7 +31,6 @@ const BalanceManager = { /** * Initializes the balance manager and sets up UI controls - * Implements the Factory pattern for UI initialization */ init() { this._slider = document.getElementById('balance-slider'); @@ -42,10 +38,6 @@ const BalanceManager = { this._setupEventListeners(); }, - /** - * Sets up event listeners for UI controls - * Implements the Observer pattern for state changes - */ _setupEventListeners() { this._slider.addEventListener('input', () => { const value = this._slider.value; @@ -78,7 +70,7 @@ const BalanceManager = { /** * Applies white balance adjustment to an image - * Implements temperature-based RGB channel scaling with non-linear response + * And implements temperature-based RGB channel scaling with non-linear response * @param {ImageData} imageData - Source image data * @returns {ImageData} White balanced image data */ @@ -102,7 +94,6 @@ const BalanceManager = { /** * Resets balance effect to default state - * Implements the Command pattern for state reset */ reset() { this._slider.value = 6500; diff --git a/js/leibovitz/blur.js b/js/leibovitz/blur.js index 001246b..bc6cddf 100644 --- a/js/leibovitz/blur.js +++ b/js/leibovitz/blur.js @@ -1,18 +1,15 @@ /** - * @fileoverview Blur management module implementing optimized box blur algorithm. + * Blur management module implementing optimized box blur algorithm. * - * @description * Implements a two-pass box blur algorithm with boundary optimization. * Uses block-based processing for improved performance on large images. * - * @architecture * Implements the following design patterns: - * - Observer Pattern: For state management and effect application - * - Factory Pattern: For UI initialization - * - Strategy Pattern: For blur algorithm implementation - * - Command Pattern: For state reset operations + * - Observer Pattern: state management and effect application + * - Factory Pattern: UI initialization + * - Strategy Pattern: blur algorithm implementation + * - Command Pattern: state reset operations * - * @algorithm * The blur implementation uses a two-pass approach: * 1. Horizontal pass: Applies blur along rows * 2. Vertical pass: Applies blur along columns @@ -31,20 +28,12 @@ const BlurManager = { _slider: null, _value: null, - /** - * Initializes the blur manager and sets up UI controls - * Implements the Factory pattern for UI initialization - */ init() { this._slider = document.getElementById('blur-slider'); this._value = document.getElementById('blur-value'); this._setupEventListeners(); }, - /** - * Sets up event listeners for UI controls - * Implements the Observer pattern for state changes - */ _setupEventListeners() { this._slider.addEventListener('input', () => { const value = this._slider.value; @@ -74,8 +63,8 @@ const BlurManager = { /** * Applies optimized box blur to an image - * Implements two-pass blur with content-aware boundary detection - * Uses separate horizontal and vertical passes for performance + * And implements two-pass blur with content-aware boundary detection + * Uses separate horizontal and vertical passes, which is more performant * @param {ImageData} imageData - Source image data * @param {number} radius - Blur radius * @returns {ImageData} Blurred image data @@ -112,14 +101,12 @@ const BlurManager = { maxX = Math.min(width - 1, maxX + radius); maxY = Math.min(height - 1, maxY + radius); - // Optimized box blur implementation // First pass: horizontal blur for (let y = minY; y <= maxY; y++) { for (let x = minX; x <= maxX; x++) { let r = 0, g = 0, b = 0, a = 0; let count = 0; - // Calculate horizontal blur for this pixel for (let dx = -radius; dx <= radius; dx++) { const nx = x + dx; if (nx >= 0 && nx < width) { @@ -147,7 +134,6 @@ const BlurManager = { let r = 0, g = 0, b = 0, a = 0; let count = 0; - // Calculate vertical blur for this pixel for (let dy = -radius; dy <= radius; dy++) { const ny = y + dy; if (ny >= 0 && ny < height) { @@ -172,10 +158,6 @@ const BlurManager = { return imageData; }, - /** - * Resets blur effect to default state - * Implements the Command pattern for state reset - */ reset() { this._currentBlur = 0; this._slider.value = 0; diff --git a/js/leibovitz/color.js b/js/leibovitz/color.js index b26229b..78f4ebc 100644 --- a/js/leibovitz/color.js +++ b/js/leibovitz/color.js @@ -1,18 +1,15 @@ /** - * @fileoverview Color tint management module implementing HSL-based color manipulation. + * Color tint management module implementing HSL-based color manipulation. * - * @description * Implements color tinting using HSL color space transformation with circular interpolation. * Features noise reduction and smooth blending for high-quality results. * - * @architecture * Implements the following design patterns: - * - Observer Pattern: For state management and effect application - * - Factory Pattern: For UI initialization - * - Strategy Pattern: For color manipulation algorithms - * - Command Pattern: For state reset operations + * - Observer Pattern: state management and effect application + * - Factory Pattern: UI initialization + * - Strategy Pattern: color manipulation algorithms + * - Command Pattern: state reset operations * - * @algorithm * Color manipulation process: * 1. Convert RGB to HSL color space * 2. Apply circular interpolation for hue blending @@ -33,18 +30,10 @@ const ColorManager = { _observers: new Set(), _colorInput: null, - /** - * Initializes the color manager and sets up UI controls - * Implements the Factory pattern for UI initialization - */ init() { this._setupEventListeners(); }, - /** - * Sets up event listeners for UI controls - * Implements the Observer pattern for state changes - */ _setupEventListeners() { this._colorInput = document.getElementById('color-tint'); this._colorInput.addEventListener('input', (e) => { @@ -95,7 +84,6 @@ const ColorManager = { /** * Applies color tint to an image using HSL color space - * Implements circular interpolation for hue blending * Uses noise reduction and smooth blending for quality * @param {ImageData} imageData - Source image data * @param {string} color - Hex color value @@ -120,7 +108,7 @@ const ColorManager = { const [h, s, l] = this._rgbToHsl(r, g, b); // Blend the tint color with the original color - // This creates a more natural LUT effect + // This tries to create a more natural LUT effect const blendFactor = 0.15; // Reduced from 0.3 to 0.15 for smoother effect // Smooth blending for hue (circular interpolation) diff --git a/js/leibovitz/contrast.js b/js/leibovitz/contrast.js index b34f205..c2b1a28 100644 --- a/js/leibovitz/contrast.js +++ b/js/leibovitz/contrast.js @@ -1,18 +1,15 @@ /** - * @fileoverview Contrast management module implementing linear contrast adjustment. + * Contrast management module implementing linear contrast adjustment. * - * @description * Implements contrast adjustment using a linear scaling algorithm. * Provides real-time contrast control with immediate visual feedback. * - * @architecture * Implements the following design patterns: - * - Observer Pattern: For state management and effect application - * - Factory Pattern: For UI initialization - * - Strategy Pattern: For contrast adjustment algorithm - * - Command Pattern: For state reset operations + * - Observer Pattern: state management and effect application + * - Factory Pattern: UI initialization + * - Strategy Pattern: contrast adjustment algorithm + * - Command Pattern: state reset operations * - * @algorithm * Contrast adjustment process: * 1. Calculate contrast factor using formula: (259 * (contrast + 255)) / (255 * (259 - contrast)) * 2. Apply linear scaling to each color channel @@ -33,7 +30,6 @@ const ContrastManager = { /** * Initializes the contrast manager and sets up UI controls - * Implements the Factory pattern for UI initialization */ init() { this._setupEventListeners(); @@ -41,7 +37,6 @@ const ContrastManager = { /** * Sets up event listeners for UI controls - * Implements the Observer pattern for state changes */ _setupEventListeners() { this._slider = document.getElementById('contrast-slider'); @@ -96,7 +91,6 @@ const ContrastManager = { /** * Resets contrast effect to default state - * Implements the Command pattern for state reset */ reset() { this._currentContrast = 1.0; diff --git a/js/leibovitz/dither.js b/js/leibovitz/dither.js index 66d6287..e74f1be 100644 --- a/js/leibovitz/dither.js +++ b/js/leibovitz/dither.js @@ -1,25 +1,22 @@ /** - * @fileoverview Dithering management module implementing multiple dithering algorithms. + * Dithering management module implementing multiple dithering algorithms. * - * @description - * Implements various dithering algorithms with block-based processing for performance. + * Implements a couple dithering algorithms with block-based processing. + * Block-based processing is faster, and has better performance. * Supports multiple dithering patterns with configurable block sizes. * - * @architecture * Implements the following design patterns: - * - Observer Pattern: For state management and effect application - * - Factory Pattern: For UI initialization - * - Strategy Pattern: For dithering algorithm selection - * - Command Pattern: For state reset operations + * - Observer Pattern: state management and effect application + * - Factory Pattern: UI initialization + * - Strategy Pattern: dithering algorithm selection + * - Command Pattern: state reset operations * - * @algorithm * Supported dithering algorithms: * - Floyd-Steinberg: Error diffusion with standard distribution pattern * - Ordered: Matrix-based threshold dithering * - Atkinson: Error diffusion with 1/8 error distribution * - Bayer: Pattern-based threshold dithering * - * @colorLevels * Each color channel (Red, Green, Blue) has 4 possible values: * - 0 -> Black/None * - 85 -> Low @@ -43,17 +40,12 @@ const DitherManager = { /** * Initializes the dither manager and sets up UI controls - * Implements the Factory pattern for UI initialization */ init() { this._setupEventListeners(); this._pixelSizeControl = document.getElementById('pixel-size-control'); }, - /** - * Sets up event listeners for UI controls - * Implements the Observer pattern for state changes - */ _setupEventListeners() { this._modeSelect = document.getElementById('dither-select'); this._modeSelect.addEventListener('change', (e) => { @@ -64,7 +56,7 @@ const DitherManager = { this._notifyObservers(); }); - // Only add the event listener if the element exists + // Only add the event listener if the element actually exists const blockSizeSlider = document.getElementById('block-size-slider'); if (blockSizeSlider) { blockSizeSlider.addEventListener('input', (e) => { @@ -97,7 +89,6 @@ const DitherManager = { /** * Applies selected dithering algorithm to image data - * Implements the Strategy pattern for algorithm selection * @param {ImageData} imageData - Source image data * @param {string} mode - Selected dithering algorithm * @returns {ImageData} Processed image data @@ -125,7 +116,6 @@ const DitherManager = { /** * Quantizes a value to create chunkier output - * Implements the Strategy pattern for quantization * @param {number} value - Input value * @param {number} levels - Number of quantization levels * @returns {number} Quantized value @@ -137,7 +127,6 @@ const DitherManager = { /** * Applies Floyd-Steinberg dithering algorithm - * Implements error diffusion with block-based processing * Uses a 4x4 error distribution pattern for smoother results * @param {Uint8ClampedArray} data - Image data * @param {number} width - Image width @@ -150,7 +139,7 @@ const DitherManager = { const levels = 4; const blockSize = this.currentBlockSize; - // Process in blocks for performance + // Process in blocks, block by block for (let y = 0; y < height; y += blockSize) { for (let x = 0; x < width; x += blockSize) { // Calculate block average @@ -227,8 +216,8 @@ const DitherManager = { /** * Applies ordered dithering using a Bayer matrix - * Implements threshold-based dithering with block processing - * Uses a 4x4 Bayer matrix pattern for structured dithering + * And implements threshold-based dithering with block processing + * Also uses a 4x4 Bayer matrix pattern for structured dithering * @param {Uint8ClampedArray} data - Image data * @param {number} width - Image width * @param {number} height - Image height @@ -293,7 +282,6 @@ const DitherManager = { /** * Applies Atkinson dithering algorithm - * Implements error diffusion with block-based processing * @param {Uint8ClampedArray} data - Image data * @param {number} width - Image width * @param {number} height - Image height @@ -368,7 +356,6 @@ const DitherManager = { /** * Applies Bayer dithering algorithm - * Implements threshold-based dithering with block processing * @param {Uint8ClampedArray} data - Image data * @param {number} width - Image width * @param {number} height - Image height @@ -378,7 +365,6 @@ const DitherManager = { const newData = new Uint8ClampedArray(data); const blockSize = this.currentBlockSize; - // 4x4 Bayer matrix for pattern generation const bayerMatrix = [ [ 0, 8, 2, 10], [12, 4, 14, 6 ], diff --git a/js/leibovitz/leibovitz.js b/js/leibovitz/leibovitz.js index d118c70..5cd6f2d 100644 --- a/js/leibovitz/leibovitz.js +++ b/js/leibovitz/leibovitz.js @@ -1,32 +1,26 @@ /** - * @fileoverview Main application entry point for a web-based camera application. - * - * @description + * Start here. * * Susan Sontag: * > The camera makes everyone a tourist in other people's reality, * > and eventually in one's own. * - * A functional architecture implementing image processing effects with real-time camera preview. - * Uses multiple design patterns for robust state management and effect application: - * - Observer Pattern: For state management and effect application across modules - * - State Pattern: For mode management (camera/edit) - * - Factory Pattern: For UI initialization and media device creation - * - Strategy Pattern: For algorithm selection in effect application - * - Command Pattern: For canvas operations and state reset - * - Chain of Responsibility: For sequential effect application + * Uses multiple design patterns for state management and applying effects: + * - Observer Pattern: state management and effect application across modules + * - State Pattern: mode management (camera/edit) + * - Factory Pattern: UI initialization and media device creation + * - Strategy Pattern: algorithm selection when applying an effect + * - Command Pattern: canvas operations and state reset + * - Chain of Responsibility: sequential effect application * * - * @architecture - * The application is structured into separate manager modules for each effect: + * Separate manager modules for each effect: * - ColorManager: HSL-based color manipulation - * - DitherManager: Multiple dithering algorithms - * - ContrastManager: Linear contrast adjustment - * - BlurManager: Optimized box blur - * - BalanceManager: Temperature-based color adjustment + * - DitherManager: multiple dithering algorithms + * - ContrastManager: linear contrast adjustment + * - BlurManager: optimized box blur + * - BalanceManager: temperature-based color adjustment * - * Each manager implements the Observer pattern for state changes and the Strategy pattern - * for effect application algorithms. * */ @@ -48,7 +42,7 @@ let track = null; let isEditMode = false; let originalImage = null; // Store the original image for edit mode -// Initialize managers - each implements the Observer pattern for state changes +// Initialize managers ColorManager.init(); DitherManager.init(); ContrastManager.init(); @@ -57,7 +51,6 @@ BalanceManager.init(); /** * Updates visibility of controls based on camera/edit mode state - * Uses the State pattern to manage UI visibility */ function updateSliderControlsVisibility() { const settingsContainer = document.getElementById('settings-container'); @@ -72,7 +65,6 @@ function updateSliderControlsVisibility() { /** * Updates canvas dimensions while maintaining aspect ratio - * Implements the Strategy pattern for different aspect ratio calculations */ function updateCanvasSize() { const container = document.querySelector('.preview-container'); @@ -96,7 +88,6 @@ function updateCanvasSize() { } } -// Observer pattern: Listen for window resize events window.addEventListener('resize', () => { if (cameraOn || isEditMode) { updateCanvasSize(); @@ -108,10 +99,6 @@ window.addEventListener('resize', () => { updateCanvasSize(); -/** - * Clears the canvas and resets its state - * Implements the Command pattern for canvas operations - */ function clearCanvas() { const container = document.querySelector('.preview-container'); const containerWidth = container.clientWidth; @@ -157,6 +144,7 @@ function startCamera() { const settings = track.getSettings(); // Feature detection for focus control + // Relatively untested because I don't have a device with focus control if ('focusDistance' in settings) { focusControl.style.display = 'flex'; focusSlider.disabled = false; @@ -198,7 +186,6 @@ function startCamera() { /** * Stops camera stream and resets UI state - * Implements the Command pattern for cleanup operations */ function stopCamera() { if (stream) { @@ -218,7 +205,6 @@ function stopCamera() { /** * Loads and displays an image file - * Implements the Factory pattern for image creation * Uses aspect ratio preservation strategy for responsive display */ function loadImage(file) { @@ -268,8 +254,7 @@ function loadImage(file) { } /** - * Applies all effects in sequence using the Chain of Responsibility pattern - * Each effect is applied using the Strategy pattern for algorithm selection + * Sequentially applies all effects to the original image */ function applyEffects() { ctx.clearRect(0, 0, canvas.width, canvas.height); @@ -283,7 +268,6 @@ function applyEffects() { /** * Draws video feed maintaining aspect ratio - * Implements the Strategy pattern for aspect ratio handling */ function drawVideoProportional() { ctx.clearRect(0, 0, canvas.width, canvas.height); @@ -307,9 +291,6 @@ function drawVideoProportional() { ctx.drawImage(video, offsetX, offsetY, drawWidth, drawHeight); } -/** - * Applies color tint effect using the Strategy pattern - */ function applyColorTint() { const currentColor = ColorManager.getCurrentColor(); if (!currentColor) return; @@ -319,18 +300,12 @@ function applyColorTint() { ctx.putImageData(tintedImageData, 0, 0); } -/** - * Applies white balance effect using the Strategy pattern - */ function applyBalance() { const imageData = ctx.getImageData(0, 0, canvas.width, canvas.height); const balancedImageData = BalanceManager.applyBalance(imageData); ctx.putImageData(balancedImageData, 0, 0); } -/** - * Applies contrast effect using the Strategy pattern - */ function applyContrast() { const currentContrast = ContrastManager.getCurrentContrast(); if (!currentContrast || currentContrast === 1.0) return; @@ -340,9 +315,6 @@ function applyContrast() { ctx.putImageData(contrastedImageData, 0, 0); } -/** - * Applies dithering effect using the Strategy pattern - */ function applyDither() { const currentMode = DitherManager.getCurrentMode(); if (!currentMode || currentMode === 'none') return; @@ -352,9 +324,7 @@ function applyDither() { ctx.putImageData(ditheredImageData, 0, 0); } -/** - * Applies blur effect using the Strategy pattern - */ + function applyBlur() { const currentBlur = BlurManager.getCurrentBlur(); if (!currentBlur) return; @@ -366,7 +336,6 @@ function applyBlur() { /** * Captures the current canvas state with effects - * Implements the Command pattern for image capture */ captureButton.addEventListener('click', () => { const currentColor = ColorManager.getCurrentColor(); @@ -391,9 +360,6 @@ captureButton.addEventListener('click', () => { link.click(); }); -/** - * Toggles camera state using the State pattern - */ toggleCameraButton.addEventListener('click', () => { cameraOn = !cameraOn; if (cameraOn) { @@ -405,9 +371,6 @@ toggleCameraButton.addEventListener('click', () => { } }); -/** - * Handles image upload using the Factory pattern - */ editImageButton.addEventListener('click', () => { if (!cameraOn) { imageInput.click(); @@ -423,7 +386,6 @@ imageInput.addEventListener('change', (e) => { /** * Service Worker registration for offline functionality - * Implements the Service Worker pattern for PWA support */ if ('serviceWorker' in navigator) { window.addEventListener('load', () => { @@ -438,9 +400,6 @@ if ('serviceWorker' in navigator) { ColorManager._setupEventListeners(); -/** - * Resets all effects using the Command pattern - */ function resetEffects() { if (isEditMode && originalImage) { applyEffects(); @@ -449,7 +408,6 @@ function resetEffects() { /** * Reset handlers for each effect manager - * Implements the Command pattern for state reset */ BlurManager.reset = function() { this._currentBlur = 0; |