TA Toolbox Home / Tool Tutorial

Color Space Conversion: Linear, sRGB, and Gamma Correction Tutorial

2026-08-24

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

  1. Open the image, go to "Edit" > "Color Settings".
  2. In "Working Spaces", set RGB to sRGB or a custom linear profile.
  3. To convert the image, use "Edit" > "Convert to Profile" and choose the target color space.
  4. Manual Gamma Adjustment

    • Use "Image" > "Adjustments" > "Levels" or "Curves", adjust mid-tones to gamma 2.2 (brighten) or 1/2.2 (darken).

    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

    • **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.

    Notes

    • **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.

    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.