diff options
Diffstat (limited to 'js/leibovitz/contrast.js')
-rw-r--r-- | js/leibovitz/contrast.js | 100 |
1 files changed, 100 insertions, 0 deletions
diff --git a/js/leibovitz/contrast.js b/js/leibovitz/contrast.js new file mode 100644 index 0000000..c2b1a28 --- /dev/null +++ b/js/leibovitz/contrast.js @@ -0,0 +1,100 @@ +/** + * Contrast management module implementing linear contrast adjustment. + * + * Implements contrast adjustment using a linear scaling algorithm. + * Provides real-time contrast control with immediate visual feedback. + * + * Implements the following design patterns: + * - Observer Pattern: state management and effect application + * - Factory Pattern: UI initialization + * - Strategy Pattern: contrast adjustment algorithm + * - Command Pattern: state reset operations + * + * Contrast adjustment process: + * 1. Calculate contrast factor using formula: (259 * (contrast + 255)) / (255 * (259 - contrast)) + * 2. Apply linear scaling to each color channel + * 3. Maintain color balance while adjusting contrast + * + * Features: + * - Linear contrast adjustment + * - Per-channel processing + * - Real-time updates + * - Preserves color relationships + */ + +const ContrastManager = { + // Private state + _currentContrast: 1.0, // Default contrast (no change) + _observers: new Set(), + _slider: null, + + /** + * Initializes the contrast manager and sets up UI controls + */ + init() { + this._setupEventListeners(); + }, + + /** + * Sets up event listeners for UI controls + */ + _setupEventListeners() { + this._slider = document.getElementById('contrast-slider'); + this._slider.addEventListener('input', (e) => { + this._currentContrast = parseFloat(e.target.value); + document.getElementById('contrast-value').textContent = this._currentContrast; + this._notifyObservers(); + }); + }, + + _notifyObservers() { + this._observers.forEach(observer => observer(this._currentContrast)); + }, + + /** + * Subscribes to contrast state changes + * @param {Function} observer - Callback function for state changes + * @returns {Function} Unsubscribe function + */ + subscribe(observer) { + this._observers.add(observer); + return () => this._observers.delete(observer); + }, + + getCurrentContrast() { + return this._currentContrast; + }, + + /** + * Applies contrast adjustment to an image + * Implements linear contrast adjustment algorithm + * @param {ImageData} imageData - Source image data + * @param {number} contrast - Contrast value + * @returns {ImageData} Contrasted image data + */ + applyContrast(imageData, contrast) { + if (!contrast || contrast === 1.0) return imageData; + + const { data } = imageData; + const factor = (259 * (contrast + 255)) / (255 * (259 - contrast)); + + for (let i = 0; i < data.length; i += 4) { + // Apply contrast to each color channel + for (let c = 0; c < 3; c++) { + const pixel = data[i + c]; + data[i + c] = factor * (pixel - 128) + 128; + } + } + + return imageData; + }, + + /** + * Resets contrast effect to default state + */ + reset() { + this._currentContrast = 1.0; + this._slider.value = 0; // Reset slider to middle position + this._notifyObservers(); + } +}; \ No newline at end of file |