Last active
October 3, 2017 20:18
-
-
Save 5p4k/69c684f64188b92f19abff4fbfaab71b to your computer and use it in GitHub Desktop.
Gamma transfer and correction functions for sRGB.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# | |
# Copyright (C) 2017 Pietro Saccardi <lizardm4@gmail.com> | |
# | |
# This work is free. You can redistribute it and/or modify it under the | |
# terms of the Do What The Fuck You Want To Public License, Version 2, | |
# as published by Sam Hocevar. See http://www.wtfpl.net/ for more details. | |
# | |
# ---- | |
# | |
# Blend your RGB colors correctly! Convert them to a linear space first. | |
# https://www.youtube.com/watch?v=LKnqECcg6Gw (thanks MinutePhysics!) | |
# | |
from math import pow | |
_SRGB_A = 0.055 | |
_SRGB_G = 2.4 | |
_SRGB_S = 12.92 | |
_SRGB_DIR_THR = 0.0031308 | |
_SRGB_INV_THR = 0.04045 | |
def srgb_gamma_dir(c): | |
""" | |
The gamma transfer function for sRGB. This takes a linear RGB value and returns its storage representation (i.e. | |
performs gamma correction of the value). | |
:param c: A floating point value in the range [0., 1.] representing one of the R, G, B channels. | |
:return: A floating point value in the range [0., 1.], representing the gamma-corrected channel. | |
""" | |
return (1. + _SRGB_A) * pow(c, 1. / _SRGB_G) - _SRGB_A if c > _SRGB_DIR_THR else c * _SRGB_S | |
def srgb_gamma_inv(c): | |
""" | |
The inverse gamma transfer function for sRGB. This takes a stored RGB value and returns its linear representation | |
(i.e. not gamma-corrected). | |
:param c: A floating point value in the range [0., 1.] representing the gamma-corrected channel. | |
:return: A floating point value in the range [0., 1.], representing one of the R, G, B channels. | |
""" | |
return pow((c + _SRGB_A) / (1. + _SRGB_A), _SRGB_G) if c > _SRGB_INV_THR else c / _SRGB_S | |
# A lookup table for the function srgb_gamma_dir, evaluated on all the integers from 0 to 255 (included). | |
SRGB_GAMMA_DIR_TABLE = [int(0.5 + 255 * srgb_gamma_dir(i / 255)) for i in range(256)] | |
# A lookup table for the function srgb_gamma_inv, evaluated on all the integers from 0 to 255 (included). | |
SRGB_GAMMA_INV_TABLE = [int(0.5 + 255 * srgb_gamma_inv(i / 255)) for i in range(256)] | |
def srgb_to_linear_rgb(rgb): | |
""" | |
Convert sRGB values to linear RGB. Linear RGB values are suitable to be interpolated and blended linearly, because | |
they are not gamma-corrected. For more information, see https://en.wikipedia.org/wiki/SRGB. | |
:param rgb: A 3-tuple of R, G, B integers in the range 0..255. No check is performed on the input. | |
:return: A 3-tuple of linear R, G, B integers in the range 0..255. | |
""" | |
return SRGB_GAMMA_INV_TABLE[rgb[0]], SRGB_GAMMA_INV_TABLE[rgb[1]], SRGB_GAMMA_INV_TABLE[rgb[2]] | |
def linear_rgb_to_srgb(rgb): | |
""" | |
Convert linear RGB values to sRGB. sRGB values are gamma-corrected and are suitable for storage. This is the format | |
in which you get data from e.g. PIL. For more information, see https://en.wikipedia.org/wiki/SRGB. | |
:param rgb: A 3-tuple of linear R, G, B integers in the range 0..255. No check is performed on the input. | |
:return: A 3-tuple of sRGB R, G, B integers in the range 0..255. | |
""" | |
return SRGB_GAMMA_DIR_TABLE[rgb[0]], SRGB_GAMMA_DIR_TABLE[rgb[1]], SRGB_GAMMA_DIR_TABLE[rgb[2]] |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment