Point operators transform each pixel independently — the output at (x,y) depends only on the input at (x,y). Brightness, contrast, and gamma correction all follow this pattern and compose efficiently via lookup tables.
Image processing operators are functions that take one or more input images and produce an output image. They divide into two families: point operators, where the output pixel value depends only on the corresponding input pixel, and neighbourhood operators, where the output depends on a region of pixels. Point operators are the simplest and most computationally efficient class.
Formally, a point operator maps each pixel independently: g(x,y) = T(f(x,y)), where f is the input image, g is the output, and T is the transformation function applied to each pixel value at coordinate (x,y). Because each pixel is processed in isolation, point operators are trivially parallelisable — every pixel on a GPU can be transformed simultaneously.
Brightness shifts all pixel values by a constant: g(x,y) = f(x,y) + β. Adding a positive value makes the image lighter; subtracting makes it darker. Values are clamped to [0, 255] for 8-bit images.
Contrast scales pixel values around a midpoint (typically 128): g(x,y) = α × (f(x,y) − 128) + 128. α > 1 stretches the dynamic range (more contrast); α < 1 compresses it. The two operations combine as g = α·f + β, which is the standard linear contrast/brightness formula used in most image editors.
Brightness affects all pixels equally — a dark object stays dark relative to a bright one. Contrast changes the separation between dark and bright regions. Together they give you full control over the linear mapping from input to output intensities: g = α·f + β where α is the gain (contrast) and β is the bias (brightness).
Gamma correction is a non-linear point operator: g(x,y) = (f(x,y)/255)^γ × 255. It models the non-linear response of display devices. CRT monitors and most digital displays do not reproduce intensity linearly — a gamma of ~2.2 is typical. Gamma correction compensates by applying the inverse non-linearity before display.
For γ < 1 (e.g., 0.5), the output is brighter than the input — the transform lifts dark tones. For γ > 1 (e.g., 2.0), the output is darker — the transform compresses bright tones. An s-curve can be implemented by composing two gamma operations with different midpoints.
Lifts shadow detail. Used to correct underexposed images or display images on dim screens. Dark pixels get boosted more than bright ones.
Compresses highlights. Used for overexposed images or to make colours appear richer. Bright pixels are pushed down more than dark ones.
Any point operator can be precomputed into a Lookup Table (LUT): a 256-entry array where LUT[v] holds the transformed value for input intensity v. Applying the operator then becomes a single array index per pixel — far cheaper than evaluating the formula for every pixel.
LUTs also enable composition: applying brightness then contrast is equivalent to constructing a combined LUT that merges both transforms. OpenCV stores LUTs as uint8 arrays and applies them with a single vectorised pass. This is why even complex colour-grading pipelines can run in real time.
The histogram shows the distribution of pixel intensities. After a brightness increase, the histogram shifts right. After a contrast increase, it spreads out. After gamma < 1, it skews toward higher values. Understanding the histogram helps diagnose whether a point operation is doing what you intend.
Say the answer out loud before revealing — recalling is what makes it stick. Next: Image Noise: Types, Models and Denoising →
What is a point operator and how does it differ from a neighbourhood operator?
What is the general formula for combined brightness and contrast adjustment?
What does gamma correction do and when is γ < 1 used?
Why are Lookup Tables (LUTs) used for point operators?