TA Toolbox Home / Tool Tutorial
Color Space Conversion: Linear, sRGB, and Gamma Correction Tutorial
Introduction
Color space conversion is crucial in computer graphics. sRGB is the standard display color space with a non-linear gamma curve, while physical calculations are usually done in linear space. Correct conversion can avoid color shifts and lighting errors. This tutorial will guide you through conversion.
Understanding Basic Concepts
- **sRGB**: Standard Red Green Blue color space, widely used for displays and image files. Its values are gamma-encoded, approximately a power function of 2.2.
- **Linear Space**: Light intensity is proportional to the numeric value, used for physical rendering and lighting calculations.
- **Gamma Correction**: Converting linear values to sRGB for display, or vice versa.
Converting with Photoshop
Viewing and Assigning Color Spaces
- Open the image, go to "Edit" > "Color Settings".
- In "Working Spaces", set RGB to sRGB or a custom linear profile.
- To convert the image, use "Edit" > "Convert to Profile" and choose the target color space.
- Use "Image" > "Adjustments" > "Levels" or "Curves", adjust mid-tones to gamma 2.2 (brighten) or 1/2.2 (darken).
- **Texture Import**: In Unity or Unreal, mark textures as sRGB (color maps) or Linear (normal, roughness, etc.).
- **Rendering Pipeline**: Ensure lighting calculations in linear space, convert to sRGB before output.
- **Precision**: Use floating-point buffers for linear data to avoid 8-bit precision loss.
- **Consistency**: Manage color space uniformly across the project to avoid mixing.
- **Browsers**: Canvas and WebGL need correct color space handling.
Manual Gamma Adjustment
Converting with Python
Using Pillow and NumPy
Install libraries:
```bash
pip install Pillow numpy
```
Example conversion functions:
```python
import numpy as np
from PIL import Image
def srgb_to_linear(img):
arr = np.array(img, dtype=np.float32) / 255.0
mask = arr <= 0.04045
arr[mask] = arr[mask] / 12.92
arr[~mask] = ((arr[~mask] + 0.055) / 1.055) ** 2.4
return arr
def linear_to_srgb(arr):
mask = arr <= 0.0031308
arr[mask] = arr[mask] * 12.92
arr[~mask] = 1.055 * (arr[~mask] ** (1/2.4)) - 0.055
return (arr * 255).astype(np.uint8)
```
Converting with Shaders
In GLSL or HLSL, GPUs can automatically handle sRGB texture sampling, but manual conversion is also common.
GLSL Functions
```glsl
vec3 srgb_to_linear(vec3 c) {
return mix(c / 12.92, pow((c + 0.055) / 1.055, vec3(2.4)), step(0.04045, c));
}
vec3 linear_to_srgb(vec3 c) {
return mix(c * 12.92, 1.055 * pow(c, vec3(1.0/2.4)) - 0.055, step(0.0031308, c));
}
```
Using OpenCV
OpenCV typically assumes images are in BGR order and does not perform gamma correction by default. Use `cvtColor` with lookup tables.
Practical Applications
Notes
Summary
Mastering color space conversion is fundamental for graphics development. By setting image processing software correctly, using code conversion, or handling in shaders, you can ensure accurate colors.
FAQ
What is the difference between sRGB and linear space?
sRGB is gamma-encoded, matching human perception and storage efficiency; linear space values are proportional to light intensity, suitable for physical calculations.
How to determine if my image is sRGB or linear?
Color maps are usually sRGB, data maps (normal, roughness) are linear. Check image metadata or source software settings.
How to set texture color space in Unity?
In texture import settings, check sRGB for color maps, uncheck for data maps. Global color space can be configured in project settings.
Why do colors look too dark or bright in the engine?
Possible color space mismatch. Check the sRGB flag on textures and gamma settings of render output.
Do I need to consider color space conversion in web development?
Yes, Canvas and WebGL default to sRGB. If doing physical rendering, manually convert to linear space.