What Is Gamma?

Gamma describes the relationship between the input signal (what your software specifies) and the output luminance (what the screen displays). It's not a 1:1 relationship.

V_out = V_inγ
Standard gamma (γ) = 2.2 for sRGB displays

If you send a 50% gray pixel to your display, it doesn't output 50% brightness. With gamma 2.2, it outputs only about 22% brightness. This is intentional—human vision is more sensitive to dark tones, so gamma "expands" the dark range.

The Lookup Table (LUT)

Rather than computing a power function for every pixel, displays use a 256-entry lookup table. Think of it as a conversion chart:

              256-ENTRY GAMMA LOOKUP TABLE
═══════════════════════════════════════════════════

  Input Index →  Output Value
  ─────────────────────────────────────────────────
       0      →   0.000  (black)
      32      →   0.012
      64      →   0.050
      96      →   0.116
     128      →   0.216  (mid-gray input ≠ mid output!)
     160      →   0.349
     192      →   0.521
     224      →   0.737
     255      →   1.000  (white)

  Each RGB channel has its own 256-value table
  Total: 256 × 3 = 768 values control your screen

macOS CoreGraphics API

Tap Zap uses two essential CoreGraphics functions:

// Capture the current gamma state CGGetDisplayTransferByTable( displayID, // Which screen 256, // Table size &redTable, // 256 floats for red &greenTable, // 256 floats for green &blueTable, // 256 floats for blue &actualCount // Returns actual count ) // Apply a new gamma table CGSetDisplayTransferByTable( displayID, 256, modifiedRed, modifiedGreen, modifiedBlue )
Key Insight

Each table entry is a CGGammaValue (Float) from 0.0 to 1.0. By scaling all values down, we darken the screen without touching the backlight.

Dimming via Gamma Scaling

To dim the screen to 50%, Tap Zap multiplies every LUT value by 0.5:

          GAMMA TABLE MODIFICATION
═══════════════════════════════════════════════════

  ORIGINAL (captured at startup):
  Index:   0    64   128   192   255
  Value: 0.00  0.05  0.22  0.52  1.00

  MODIFIED (brightness = 50%):
  Index:   0    64   128   192   255
  Value: 0.00  0.025 0.11  0.26  0.50
                ↑
           All values × 0.5

  Result: Maximum possible output is now 0.50
          Screen appears 50% dimmer
          Backlight unchanged → NO FLICKER

Per-Channel Control

Tap Zap applies different multipliers to each channel for color temperature:

          COLOR TEMPERATURE VIA CHANNEL SCALING
═══════════════════════════════════════════════════

  NEUTRAL (6500K):    R × 1.00    G × 1.00    B × 1.00
  
  WARM (4000K):       R × 1.00    G × 1.00    B × 0.50
                                              ↑
                                         Blue reduced

  DEEP WARM (2000K):  R × 1.00    G × 0.50    B × 0.00
                                    ↑          ↑
                               Green reduced  Blue gone

  Combined with brightness factor:
  final_value = original × brightness × color_factor

Why Tables Instead of Formulas?

Power Function

  • Must compute V^γ for each pixel
  • Billions of operations per frame
  • Only simple curves possible

Lookup Table

  • Just one array lookup per channel
  • 768 values, applied by GPU
  • Any arbitrary curve possible

The Full Pipeline

              PIXEL → SCREEN PIPELINE
═══════════════════════════════════════════════════

  ┌──────────────┐
  │ Application  │  Sends RGB value (128, 64, 200)
  └──────┬───────┘
         ↓
  ┌──────────────┐
  │  Gamma LUT   │  R: table[128] → 0.11 (dimmed)
  │   (Tap Zap)  │  G: table[64]  → 0.025
  │              │  B: table[200] → 0.38
  └──────┬───────┘
         ↓
  ┌──────────────┐
  │     GPU      │  Renders with modified values
  └──────┬───────┘
         ↓
  ┌──────────────┐
  │   Display    │  Shows dimmed, warm pixel
  │  (100% PWM)  │  Backlight at full power
  └──────────────┘

From 768 Numbers to Zero Flicker

Tap Zap captures your display's gamma on launch, then scales those values in real-time as you adjust brightness and color temperature—all while your backlight stays at 100%.

256 × 3 = Complete control over your screen

T Toggle TOC Esc Scroll to top D Deep dark