about summary refs log tree commit diff stats
path: root/js/leibovitz/contrast.js
diff options
context:
space:
mode:
Diffstat (limited to 'js/leibovitz/contrast.js')
-rw-r--r--js/leibovitz/contrast.js100
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