Skip to content

Commit c197ab0

Browse files
authored
Merge pull request #211 from ImagingDataCommons/feat/gamma-correction
feat: Add gamma correction / PS
2 parents 64a1098 + 83be283 commit c197ab0

File tree

1 file changed

+23
-6
lines changed

1 file changed

+23
-6
lines changed

src/color.js

Lines changed: 23 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -364,26 +364,43 @@ class PaletteColorLookupTable {
364364
]
365365
const maxInput = Math.max(...maxValues)
366366
const maxOutput = 255
367+
368+
// Apply gamma correction to compensate for display gamma (brightens mid-tones)
369+
// When a linear intensity value i (0 to 1) is looked up, we actually want to look up
370+
// the color at position i^gamma where gamma = 1/2.2 ≈ 0.4545
371+
// This pre-brightens the colors for mid-tones
372+
const gammaInverse = 1.0 / 2.2 // ≈ 0.4545
373+
367374
if (this[_attrs].bitsPerEntry === 16 && maxInput > 255) {
368375
/*
369376
* Only palettes with 256 entries and 8 bit per entry are supported for
370377
* display. Therefore, data need to rescaled and resampled.
371378
*/
372379
const n = 256
373-
const step = this[_attrs].numberOfEntries / n
374380
this[_attrs].data = new Array(n)
375381
for (let i = 0; i < n; i++) {
376-
const j = i * step
382+
// Apply gamma correction: for palette position i, look up the color
383+
// that would be at the gamma-corrected position
384+
const normalizedPos = i / (n - 1)
385+
const gammaCorrectedPos = Math.pow(normalizedPos, gammaInverse)
386+
const lutIndex = Math.round(gammaCorrectedPos * (this[_attrs].numberOfEntries - 1))
387+
377388
this[_attrs].data[i] = [
378-
Math.round(rescale(redLUT[j], 0, maxInput, 0, maxOutput)),
379-
Math.round(rescale(greenLUT[j], 0, maxInput, 0, maxOutput)),
380-
Math.round(rescale(blueLUT[j], 0, maxInput, 0, maxOutput))
389+
Math.round(rescale(redLUT[lutIndex], 0, maxInput, 0, maxOutput)),
390+
Math.round(rescale(greenLUT[lutIndex], 0, maxInput, 0, maxOutput)),
391+
Math.round(rescale(blueLUT[lutIndex], 0, maxInput, 0, maxOutput))
381392
]
382393
}
383394
} else {
384395
this[_attrs].data = new Array(this[_attrs].numberOfEntries)
385396
for (let i = 0; i < this[_attrs].numberOfEntries; i++) {
386-
this[_attrs].data[i] = [redLUT[i], greenLUT[i], blueLUT[i]]
397+
// Apply gamma correction: for palette position i, look up the color
398+
// that would be at the gamma-corrected position
399+
const normalizedPos = i / (this[_attrs].numberOfEntries - 1)
400+
const gammaCorrectedPos = Math.pow(normalizedPos, gammaInverse)
401+
const lutIndex = Math.round(gammaCorrectedPos * (this[_attrs].numberOfEntries - 1))
402+
403+
this[_attrs].data[i] = [redLUT[lutIndex], greenLUT[lutIndex], blueLUT[lutIndex]]
387404
}
388405
}
389406
}

0 commit comments

Comments
 (0)