120
⚫ LVL 05 — SENIOR DEVELOPERSESSION 120DAY 120

AUTO-ENHANCE ENGINE

🏢 IMPLEMENTATION — PHASE 1
Senior Ownership | Backend Engine

Design doc approved. Time to build. Implement the image analysis engine: scan every pixel, compute histogram statistics, calculate optimal correction parameters. Then unit test every function. The algorithm is the brain of auto-enhance.
CONCEPTS.UNLOCKED
📊
Histogram Analysis
Count how many pixels exist at each brightness level (0-255). A dark image has pixels clustered left. A bright image: right. A flat image: narrow range. The histogram reveals what corrections are needed.
💡
Brightness Correction
Mean brightness should be ~128 (middle of 0-255). Below 100 → image is dark, lift it. Above 180 → overexposed, pull down. The suggested adjustment shifts the mean toward the target.
📐
Contrast Analysis
Full contrast uses the entire 0-255 range. Range = max - min brightness. Below 100 → flat/hazy, stretch the range. Above 230 → already punchy, leave it. Contrast multiplier adjusts the spread.
🎨
Saturation Detection
Convert to HSL and measure the S channel. Low mean saturation → washed out, boost. High → oversaturated, pull back. Skip saturation for grayscale images (detected by near-zero variance).
🧪
Unit Testing Analysis
Test with known images: pure black, pure white, 50% gray, known histograms. If input = all black pixels, brightness mean = 0, suggested adjustment = +50. Deterministic math → deterministic tests.
HANDS-ON.TASKS
01
Image Analysis Types
// lib/enhance/types.ts interface ImageAnalysis { brightness: { mean: number; histogram: number[]; // 256 buckets suggested: number; // adjustment }; contrast: { range: number; stdDev: number; suggested: number; // multiplier }; saturation: { mean: number; isGrayscale: boolean; suggested: number; // adjustment }; sharpness: { score: number; // 0-100 suggested: number; // amount }; } interface EnhancementParams { brightness: number; // -50 to +50 contrast: number; // 0.5 to 2.0 saturation: number; // -50 to +50 sharpness: number; // 0 to 100 }
02
Core Analysis Engine
// lib/enhance/analyze.ts function analyzeImage( imageData: ImageData ): ImageAnalysis { const pixels = imageData.data; const pixelCount = pixels.length / 4; let totalBrightness = 0; let minBrightness = 255; let maxBrightness = 0; const histogram = new Array(256) .fill(0); let totalSaturation = 0; let satValues: number[] = []; for (let i = 0; i < pixels.length; i += 4) { const r = pixels[i]; const g = pixels[i + 1]; const b = pixels[i + 2]; // Brightness (luminance) const bright = Math.round( 0.299 * r + 0.587 * g + 0.114 * b); totalBrightness += bright; minBrightness = Math.min(minBrightness, bright); maxBrightness = Math.max(maxBrightness, bright); histogram[bright]++; // Saturation (from HSL) const max = Math.max(r, g, b); const min = Math.min(r, g, b); const l = (max + min) / 2 / 255; const sat = max === min ? 0 : l < 0.5 ? (max - min) / (max + min) : (max - min) / (510 - max - min); totalSaturation += sat; satValues.push(sat); } const meanBright = totalBrightness / pixelCount; const contrastRange = maxBrightness - minBrightness; const meanSat = totalSaturation / pixelCount; // Saturation variance → detect B&W const satVariance = variance( satValues); const isGrayscale = satVariance < 0.01; return { brightness: { mean: meanBright, histogram, suggested: suggestBrightness(meanBright), }, contrast: { range: contrastRange, stdDev: stdDev(histogram), suggested: suggestContrast(contrastRange), }, saturation: { mean: meanSat, isGrayscale, suggested: isGrayscale ? 0 : suggestSaturation(meanSat), }, sharpness: { score: estimateSharpness( imageData), suggested: 0, // MVP: skip }, }; }
03
Suggestion Functions
// lib/enhance/suggestions.ts function suggestBrightness( mean: number ): number { const target = 128; const diff = target - mean; // Gentle correction: 30% of diff // Clamped to safe range return clamp( Math.round(diff * 0.3), -40, 40 ); } function suggestContrast( range: number ): number { if (range < 80) return 1.4; // very flat → boost if (range < 150) return 1.2; // somewhat flat if (range > 240) return 0.9; // too punchy → reduce return 1.0; // good range } function suggestSaturation( mean: number ): number { if (mean < 0.15) return 20; // washed out → boost if (mean < 0.25) return 10; // slightly dull if (mean > 0.7) return -15; // oversaturated return 0; // looks good } function clamp( val: number, min: number, max: number ) { return Math.min(max, Math.max(min, val)); }
04
Unit Tests
// __tests__/enhance.test.ts import { describe, it, expect } from 'vitest'; function createTestImage( r: number, g: number, b: number, size = 100 ): ImageData { const data = new Uint8ClampedArray(size * size * 4); for (let i = 0; i < data.length; i += 4) { data[i] = r; data[i+1] = g; data[i+2] = b; data[i+3] = 255; } return new ImageData(data, size, size); } describe('analyzeImage', () => { it('detects dark image', () => { const img = createTestImage( 30, 30, 30); const result = analyzeImage(img); expect(result.brightness.mean) .toBeCloseTo(30); expect(result.brightness.suggested) .toBeGreaterThan(0); }); it('detects bright image', () => { const img = createTestImage( 230, 230, 230); const result = analyzeImage(img); expect(result.brightness.suggested) .toBeLessThan(0); }); it('detects grayscale', () => { const img = createTestImage( 128, 128, 128); const result = analyzeImage(img); expect(result.saturation.isGrayscale) .toBe(true); expect(result.saturation.suggested) .toBe(0); }); it('suggests no change for good image', () => { const img = createTestImage( 128, 100, 80); const result = analyzeImage(img); expect(Math.abs( result.brightness.suggested)) .toBeLessThan(10); }); });
05
Analytics Endpoint
// Record enhancement for analytics app.post('/api/enhance/analytics', requireAuth, async (req, res) => { const { imageId, analysis, userAdjustments, applied } = req.body; await db.collection('enhancements') .insertOne({ imageId, userId: req.user.id, analysis, applied: applied ? userAdjustments : null, userAdjusted: applied && !deepEqual( analysis.suggested, userAdjustments), timestamp: new Date(), }); res.json({ recorded: true }); });
06
Close the Ticket
git switch -c feature/auto-enhance-engine git add src/lib/enhance/ src/__tests__/ git commit -m "Add image analysis engine + unit tests" git push origin feature/auto-enhance-engine # PR → Review → Merge ✅
CS.DEEP-DIVE

Image histograms reveal everything about a photo's exposure.

A histogram is a frequency distribution of pixel brightness values (0-255). Professional photographers check histograms to judge exposure quality.

// Reading histograms:

Dark image (underexposed)
▓▓▓▓▓▓▒░░░░░░░░░░░░░░░░░
Pixels clustered LEFT (0-80)
Fix: shift right (+ brightness)

Bright image (overexposed)
░░░░░░░░░░░░░░░░░░▒▓▓▓▓▓
Pixels clustered RIGHT (180-255)
Fix: shift left (- brightness)

Low contrast (flat/hazy)
░░░░░░░░▒▓▓▓▓▓▒░░░░░░░░░
Narrow range in the middle
Fix: stretch to fill 0-255

Good exposure
░▒▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▒░
Full range, gentle bell curve
Fix: minimal or none

// Auto-enhance = "fix the histogram"
// Same as Photoshop's Auto Levels.
"Analysis Lab"
[A]Visualize the histogram: draw a 256×100 canvas showing the brightness distribution. Overlay the suggested correction. Show this in the UI so users understand what auto-enhance is doing and why.
[B]Add edge-case handling: test with a 1×1 pixel image, an all-black image, an all-white image, and a very large 8K image. Verify the analysis engine handles all gracefully without crashing or suggesting absurd values.
[C]Research: histogram equalization (auto-levels). Instead of suggesting a single brightness shift, redistribute ALL pixel values to fill the full 0-255 range evenly. Implement it and compare results to your linear correction.
REF.MATERIAL
ARTICLE
Wikipedia
Histograms in image processing: brightness distribution, exposure analysis, and histogram-based corrections. The mathematical foundation.
HISTOGRAMTHEORYESSENTIAL
VIDEO
Computerphile
Brightness, contrast, and histogram equalization explained visually. The algorithms behind auto-enhance in professional software.
IMAGEALGORITHMS
ARTICLE
Vitest Team
The Vite-native testing framework: fast, TypeScript-first, Jest-compatible API. What we use for unit testing the analysis engine.
TESTINGOFFICIAL
ARTICLE
MDN Web Docs
The ImageData API: pixel arrays, width, height, and working with raw RGBA data. The foundation for image analysis in the browser.
CANVASOFFICIAL
ARTICLE
Wikipedia
How to extract saturation from RGB: the HSL conversion formula. Used by the analysis engine to detect washed-out or oversaturated images.
COLORMATH
// LEAVE EXCITED BECAUSE
The analysis engine scans every pixel: brightness histogram, contrast range, saturation level. Suggestion functions calculate optimal corrections. Unit tests pass. The brain of auto-enhance is built and tested. Tomorrow: the UI.