about summary refs log tree commit diff stats
path: root/js
diff options
context:
space:
mode:
Diffstat (limited to 'js')
-rw-r--r--js/leibovitz/balance.js96
-rw-r--r--js/leibovitz/blur.js43
-rw-r--r--js/leibovitz/color.js38
-rw-r--r--js/leibovitz/contrast.js27
-rw-r--r--js/leibovitz/dither.js53
-rw-r--r--js/leibovitz/leibovitz.js71
-rw-r--r--js/leibovitz/manifest.json9
-rw-r--r--js/pipe.js4
8 files changed, 194 insertions, 147 deletions
diff --git a/js/leibovitz/balance.js b/js/leibovitz/balance.js
index 73f60e8..aeff62e 100644
--- a/js/leibovitz/balance.js
+++ b/js/leibovitz/balance.js
@@ -1,53 +1,80 @@
 /**
- * White balance management module implementing temperature-based color adjustment
- * Uses the Observer pattern for state management and effect application
- * Implements a non-linear temperature adjustment algorithm with RGB channel scaling
- * Uses a static class pattern for state management
+ * 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
  */
 
-class BalanceManager {
+const BalanceManager = {
+    // Private state
+    _observers: new Set(),
+    _slider: null,
+    _value: null,
+
     /**
      * Initializes the balance manager and sets up UI controls
-     * Implements the Factory pattern for UI initialization
      */
-    static init() {
-        this.balanceSlider = document.getElementById('balance-slider');
-        this.balanceValue = document.getElementById('balance-value');
+    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()));
+    },
 
     /**
-     * Sets up event listeners for UI controls
-     * Implements the Observer pattern for state changes
+     * Subscribes to balance state changes
+     * @param {Function} observer - Callback function for state changes
+     * @returns {Function} Unsubscribe function
      */
-    static _setupEventListeners() {
-        this.balanceSlider.addEventListener('input', () => {
-            const value = this.balanceSlider.value;
-            this.balanceValue.textContent = `${value}K`;
-        });
-    }
+    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)
      */
-    static getCurrentBalance() {
-        return parseInt(this.balanceSlider.value);
-    }
+    getCurrentBalance() {
+        return parseInt(this._slider.value);
+    },
 
     /**
      * 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
-     * 
-     * Algorithm:
-     * 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
      */
-    static applyBalance(imageData) {
+    applyBalance(imageData) {
         const balance = this.getCurrentBalance();
         if (!balance || balance === 6500) return imageData; // 6500K is neutral
 
@@ -63,5 +90,14 @@ class BalanceManager {
         }
 
         return imageData;
+    },
+
+    /**
+     * Resets balance effect to default state
+     */
+    reset() {
+        this._slider.value = 6500;
+        this._value.textContent = '6500K';
+        this._notifyObservers();
     }
-} 
\ No newline at end of file
+}; 
\ No newline at end of file
diff --git a/js/leibovitz/blur.js b/js/leibovitz/blur.js
index 27fa480..bc6cddf 100644
--- a/js/leibovitz/blur.js
+++ b/js/leibovitz/blur.js
@@ -1,8 +1,24 @@
 /**
- * Blur management module implementing optimized box blur
- * Uses the Observer pattern for state management and effect application
- * Implements two-pass box blur algorithm with boundary detection
- * Uses content-aware optimization for performance
+ * Blur management module implementing optimized box blur algorithm.
+ * 
+ * Implements a two-pass box blur algorithm with boundary optimization.
+ * Uses block-based processing for improved performance on large images.
+ * 
+ * Implements the following design patterns:
+ * - Observer Pattern: state management and effect application
+ * - Factory Pattern: UI initialization
+ * - Strategy Pattern: blur algorithm implementation
+ * - Command Pattern: state reset operations
+ * 
+ * The blur implementation uses a two-pass approach:
+ * 1. Horizontal pass: Applies blur along rows
+ * 2. Vertical pass: Applies blur along columns
+ * 
+ * Features:
+ * - Boundary optimization for performance
+ * - Block-based processing
+ * - Two-pass implementation for better performance
+ * - Edge clamping to prevent artifacts
  */
 
 const BlurManager = {
@@ -12,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;
@@ -55,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
@@ -93,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) {
@@ -128,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) {
@@ -153,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 1438403..78f4ebc 100644
--- a/js/leibovitz/color.js
+++ b/js/leibovitz/color.js
@@ -1,8 +1,27 @@
 /**
- * Color tint management module implementing HSL-based color manipulation
- * Uses the Observer pattern for state management and effect application
- * Implements HSL color space transformation with circular interpolation
- * Uses noise reduction and smooth blending for quality
+ * Color tint management module implementing HSL-based color manipulation.
+ * 
+ * Implements color tinting using HSL color space transformation with circular interpolation.
+ * Features noise reduction and smooth blending for high-quality results.
+ * 
+ * Implements the following design patterns:
+ * - Observer Pattern: state management and effect application
+ * - Factory Pattern: UI initialization
+ * - Strategy Pattern: color manipulation algorithms
+ * - Command Pattern: state reset operations
+ * 
+ * Color manipulation process:
+ * 1. Convert RGB to HSL color space
+ * 2. Apply circular interpolation for hue blending
+ * 3. Smooth blending for saturation and lightness
+ * 4. Noise reduction through value rounding
+ * 5. Convert back to RGB color space
+ * 
+ * Features:
+ * - Circular interpolation for natural hue transitions
+ * - Noise reduction through value rounding
+ * - Smooth blending with quadratic easing
+ * - HSL color space for better color manipulation
  */
 
 const ColorManager = {
@@ -11,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) => {
@@ -73,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
@@ -98,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 01312ad..c2b1a28 100644
--- a/js/leibovitz/contrast.js
+++ b/js/leibovitz/contrast.js
@@ -1,7 +1,25 @@
 /**
- * Contrast management module implementing contrast adjustment
- * Uses the Observer pattern for state management and effect application
- * Implements linear contrast adjustment algorithm
+ * 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 = {
@@ -12,7 +30,6 @@ const ContrastManager = {
 
     /**
      * Initializes the contrast manager and sets up UI controls
-     * Implements the Factory pattern for UI initialization
      */
     init() {
         this._setupEventListeners();
@@ -20,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');
@@ -75,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 b011eca..e74f1be 100644
--- a/js/leibovitz/dither.js
+++ b/js/leibovitz/dither.js
@@ -1,15 +1,33 @@
 /**
- * Dithering management module implementing various dithering algorithms
- * Uses the Observer pattern for state management and effect application
- * Implements block-based processing for performance optimization
- * Uses the Strategy pattern for algorithm selection
+ * Dithering management module implementing multiple dithering algorithms.
+ * 
+ * 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.
+ * 
+ * Implements the following design patterns:
+ * - Observer Pattern: state management and effect application
+ * - Factory Pattern: UI initialization
+ * - Strategy Pattern: dithering algorithm selection
+ * - Command Pattern: state reset operations
+ * 
+ * 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
  * 
  * Each color channel (Red, Green, Blue) has 4 possible values:
- * 0   -> Black/None
- * 85  -> Low
- * 170 -> Medium
- * 255 -> Full
+ * - 0   -> Black/None
+ * - 85  -> Low
+ * - 170 -> Medium
+ * - 255 -> Full
  * 
+ * Features:
+ * - Block-based processing for performance
+ * - Multiple dithering algorithms
+ * - Configurable block sizes
+ * - Error diffusion patterns
  */
 
 const DitherManager = {
@@ -22,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) => {
@@ -43,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) => {
@@ -76,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
@@ -104,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
@@ -116,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
@@ -129,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
@@ -206,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
@@ -272,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
@@ -347,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
@@ -357,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 030e7d2..5cd6f2d 100644
--- a/js/leibovitz/leibovitz.js
+++ b/js/leibovitz/leibovitz.js
@@ -1,8 +1,27 @@
 /**
- * Main application entry point for the app.
- * Implements a functional architecture with separate managers for each effect.
- * Uses the Observer pattern for state management and effect application.
- * Implements the State pattern for mode management (camera/edit).
+ * Start here.
+ * 
+ * Susan Sontag:
+ * > The camera makes everyone a tourist in other people's reality, 
+ * > and eventually in one's own.
+ * 
+ * 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
+ * 
+ * 
+ * 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
+ * 
+ * 
  */
 
 const canvas = document.getElementById('canvas');
@@ -23,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();
@@ -32,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');
@@ -47,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');
@@ -71,7 +88,6 @@ function updateCanvasSize() {
     }
 }
 
-// Observer pattern: Listen for window resize events
 window.addEventListener('resize', () => {
     if (cameraOn || isEditMode) {
         updateCanvasSize();
@@ -83,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;
@@ -132,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;
@@ -173,7 +186,6 @@ function startCamera() {
 
 /**
  * Stops camera stream and resets UI state
- * Implements the Command pattern for cleanup operations
  */
 function stopCamera() {
     if (stream) {
@@ -193,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) {
@@ -243,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);
@@ -258,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);
@@ -282,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;
@@ -294,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;
@@ -315,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;
@@ -327,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;
@@ -341,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();
@@ -366,9 +360,6 @@ captureButton.addEventListener('click', () => {
     link.click();
 });
 
-/**
- * Toggles camera state using the State pattern
- */
 toggleCameraButton.addEventListener('click', () => {
     cameraOn = !cameraOn;
     if (cameraOn) {
@@ -380,9 +371,6 @@ toggleCameraButton.addEventListener('click', () => {
     }
 });
 
-/**
- * Handles image upload using the Factory pattern
- */
 editImageButton.addEventListener('click', () => {
     if (!cameraOn) {
         imageInput.click();
@@ -398,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', () => {
@@ -413,9 +400,6 @@ if ('serviceWorker' in navigator) {
 
 ColorManager._setupEventListeners();
 
-/**
- * Resets all effects using the Command pattern
- */
 function resetEffects() {
     if (isEditMode && originalImage) {
         applyEffects();
@@ -424,7 +408,6 @@ function resetEffects() {
 
 /**
  * Reset handlers for each effect manager
- * Implements the Command pattern for state reset
  */
 BlurManager.reset = function() {
     this._currentBlur = 0;
diff --git a/js/leibovitz/manifest.json b/js/leibovitz/manifest.json
index 03dc94f..1ddc0b2 100644
--- a/js/leibovitz/manifest.json
+++ b/js/leibovitz/manifest.json
@@ -50,15 +50,6 @@
    "type": "image/png"
   }
  ],
- "screenshots": [
-  {
-   "src": "screenshot1.png",
-   "sizes": "1080x1920",
-   "type": "image/png",
-   "platform": "narrow",
-   "label": "Leibovitz Camera App"
-  }
- ],
  "categories": ["photo", "camera", "art"],
  "prefer_related_applications": false,
  "shortcuts": [
diff --git a/js/pipe.js b/js/pipe.js
index 69ccae3..ace5fb9 100644
--- a/js/pipe.js
+++ b/js/pipe.js
@@ -1,2 +1,6 @@
 const pipe = (...args) => args.reduce((acc, el) => el(acc));
 
+/* alt implementation
+const pipe = (...fns) => (initialValue) =>
+  fns.reduce((acc, fn) => fn(acc), initialValue);
+*/
\ No newline at end of file