/** * White balance management module implementing temperature-based color adjustment. * * Implements white balance adjustment using temperature-based RGB channel scaling. * Provides non-linear temperature adjustment for natural color correction. * * Implements the following design patterns: * - Observer Pattern: state management and effect application * - Factory Pattern: UI initialization * - Strategy Pattern: temperature adjustment algorithm * - Command Pattern: state reset operations * * 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 * 3. Warmer temps (<6500K) increase red, decrease blue * 4. Cooler temps (>6500K) increase blue, decrease red * * Features: * - Temperature-based color adjustment * - Non-linear response curve * - Preserves green channel * - Real-time updates */ const BalanceManager = { // Private state _observers: new Set(), _slider: null, _value: null, /** * Initializes the balance manager and sets up UI controls */ init() { this._slider = document.getElementById('balance-slider'); this._value = document.getElementById('balance-value'); this._setupEventListeners(); }, _setupEventListeners() { this._slider.addEventListener('input', () => { const value = this._slider.value; this._value.textContent = `${value}K`; this._notifyObservers(); }); }, _notifyObservers() { this._observers.forEach(observer => observer(this.getCurrentBalance())); }, /** * Subscribes to balance 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); }, /** * Gets the current white balance temperature * @returns {number} Current temperature in Kelvin (2000K-10000K) */ getCurrentBalance() { return parseInt(this._slider.value); }, /** * Applies white balance adjustment to an image * And implements temperature-based RGB channel scaling with non-linear response * @param {ImageData} imageData - Source image data * @returns {ImageData} White balanced image data */ applyBalance(imageData) { const balance = this.getCurrentBalance(); if (!balance || balance === 6500) return imageData; // 6500K is neutral const data = imageData.data; const temperature = balance / 6500; // Convert to temperature ratio for (let i = 0; i < data.length; i += 4) { // Adjust red and blue channels based on temperature // Warmer (lower K) increases red, decreases blue // Cooler (higher K) increases blue, decreases red data[i] = Math.min(255, data[i] * (1 + (temperature - 1) * 0.2)); // Red data[i + 2] = Math.min(255, data[i + 2] * (1 + (1 - temperature) * 0.2)); // Blue } return imageData; }, /** * Resets balance effect to default state */ reset() { this._slider.value = 6500; this._value.textContent = '6500K'; this._notifyObservers(); } };