P3 Image Delivery Guide 2025 — Safe fallback to sRGB with real‑device verification

Published: Sep 20, 2025 · Reading time: 3 min · By Unified Image Tools Editorial

Recent devices support P3 more often, but non‑P3 still exists. To avoid breakage, decide how to offer P3 alongside an sRGB fallback.

This article is a minimal, practical approach to “use P3 without causing surprises”: ICC embedding, tagged JPEG/AVIF, HTML/Next examples, and CI diff checks.

Related: Color Management and ICC — sRGB/Display-P3/CMYK Handoff 2025 / Correct Color Management & ICC Profile Strategy 2025 — A Practical Guide for Stable Web Image Color

Export basics

  • Always embed ICC for P3 assets
  • Keep an sRGB version (double‑delivery in key spots is fine)
  • Do processing in one colorspace; avoid multi‑stage conversions

ICC handling

  • P3: Embed Display P3 (D65 / 2°). Treat gamma close to sRGB tone curve.
  • sRGB: Embed the profile explicitly (untagged is fragile and environment‑dependent)

Format/codec tips

  • Photo: AVIF/JPEG XL (when available) > WebP > JPEG. Confirm ICC retention.
  • UI/illustrations: PNG/SVG. P3 benefits are limited; validate against palette shifts.
  • The priority is “P3 vs sRGB look remains consistent enough” — avoid oversaturated or skin‑tone shifts.

Delivery patterns

  1. Use Srcset Generator to compose type + srcset
  2. Switch P3/sRGB by media query or MIME. If detection is tricky, limit P3 to hero/product only.
  3. Add screenshot diffs in CI to detect accidental changes.

HTML pattern

<picture>
  <source type="image/avif" srcset="hero-p3.avif" media="(color-gamut: p3)">
  <source type="image/avif" srcset="hero-srgb.avif">
  <img src="hero-srgb.jpg" width="1200" height="800" alt="hero" />
</picture>

(color-gamut: p3) approximates wide‑gamut capability. It’s not perfect; prefer using P3 only for important elements.

Next.js example

<picture>
  <source srcSet={p3Avif} type="image/avif" media="(color-gamut: p3)" />
  <source srcSet={srgbAvif} type="image/avif" />
  <img src={srgbJpg} width={1200} height={800} alt="hero" />
</picture>

With Next/Image, use unoptimized or ensure color‑managed transforms; some optimizers strip ICC. In such cases, hand‑crafted <picture> can be safer.

Verification

  • Compare on a P3‑capable device and an sRGB‑limited device
  • Check gradients and saturation/clip behavior

What to look for on real devices

  • Skin‑tone red/yellow bias shifts
  • Brand color over‑saturation (P3 shouldn’t look “painted”)
  • Gradient banding from mishandled gamma/quantization

CI diff (idea)

// Pseudo: compare two screenshots in Lab ΔE
import { diffDE2000 } from 'some-color-lib';

function meanDeltaE(imgA: Uint8ClampedArray, imgB: Uint8ClampedArray): number {
  // ...convert RGB→Lab and average ΔE...
  return 1.8; // example
}

if (meanDeltaE(p3Shot, srgbShot) > 3.0) {
  throw new Error('Color diff too large: please review P3 conversion');
}

FAQ

  • Q: Can browsers be forced into P3? A: Not reliably. Embed ICC and verify on hardware instead.
  • Q: My JPEG loses ICC. A: Some tools drop ICC at conversion. Use --icc or “preserve metadata” options, then verify with exiftool -icc_profile -G1.
  • Q: Isn’t double‑delivery heavy? A: Limit P3 to high‑impact areas (hero/product). Keep the rest sRGB.

Summary

Don’t try to “go wide everywhere.” Use P3 where it matters and keep the sRGB fallback solid.


Appendix: mini pipeline (example)

# Start from sRGB master, convert to P3, and embed ICC
magick in_srgb.jpg -colorspace DisplayP3 -profile DisplayP3.icc out_p3.jpg

# Convert to AVIF, keep ICC
avifenc --icc out_p3.jpg out_p3.avif

# sRGB fallback
magick out_p3.jpg -colorspace sRGB -profile sRGB.icc out_srgb.jpg

Extra checks

# ICC presence
exiftool -icc_profile -G1 out_p3.jpg out_p3.avif out_srgb.jpg

# Quick tag read
exiftool -ColorSpace -ProfileDescription out_p3.jpg

Related Articles