An ICC profile describes how to interpret image colors. Convert to sRGB when your output needs sRGB pixel values, not just a different profile label.
dotnet add package RecursiveAI.OneImageRequires .NET 10 (net10.0); .NET 9 and earlier aren’t supported.
using OneImage; // Any image with an embedded ICC profile works. // p3.png is the sample in the zip. Image.Load("p3.png") .ConvertColor(ColorProfile.Srgb) .Save("srgb.png"); Console.WriteLine("Wrote srgb.png");
Wrote srgb.pngUnzip the example, then dotnet run.
The full program
The program creates a one-pixel RGB image with values 180, 100, 60, assigns Display P3, and saves it as p3.png. It then compares converting the pixel to sRGB with changing only its label. The generated sample is included in the zip.
using OneImage; Image original = Image.FromPixels<Rgb24>( new Rgb24[] { new(180, 100, 60) }, 1, 1); Image tagged = original.AssignProfile(ColorProfile.DisplayP3); tagged.Save("p3.png"); Image source = Image.Load("p3.png"); Image converted = source.ConvertColor(ColorProfile.Srgb); converted.Save("srgb.png"); Image relabeled = source.AssignProfile(ColorProfile.Srgb); relabeled.Save("relabeled.png"); foreach (string name in new[] { "p3.png", "srgb.png", "relabeled.png" }) { Image saved = Image.Load(name); Rgb24 pixel = saved.ToArray<Rgb24>()[0]; var profile = ColorProfile.FromIcc(saved.Metadata.IccProfile.Span); Console.WriteLine($"{name}: RGB {pixel.R},{pixel.G},{pixel.B}; {profile.Description}"); }
dotnet run prints:
p3.png: RGB 180,100,60; OneImage Display P3 srgb.png: RGB 193,95,49; sRGB relabeled.png: RGB 180,100,60; sRGB
Invalid or unsupported ICC data passed to ColorProfile.FromIcc throws ImageFormatException.
Variations
Choose the rendering intent explicitly. This uses perceptual intent without black-point compensation; the default is relative colorimetric with compensation enabled.
using OneImage; Image.Load("p3.png").ConvertColor( ColorProfile.Srgb, RenderingIntent.Perceptual, blackPointCompensation: false).Save("perceptual.png"); Console.WriteLine("Wrote perceptual.png");
Wrote perceptual.pngRelated recipes
The short answer
Call image.ConvertColor(ColorProfile.Srgb) to convert pixel values and embed the destination profile. AssignProfile(ColorProfile.Srgb) only changes the label. It is not an alternative way to convert an image whose pixels are in another color space.
The distinction is visible in the example: the Display P3 pixel starts at RGB 180, 100, 60. Conversion produces 193, 95, 49. Assignment leaves 180, 100, 60 untouched, but labels those unchanged numbers as sRGB. Both saved files carry an sRGB profile; only one has undergone pixel conversion.
How can I convert an image to sRGB?
Load the image, call ConvertColor, and save it in a format that carries an ICC profile, such as PNG. The snippet at the top does all three. Loading alone does not convert color: OneImage keeps the source values and embedded profile by default. Saving alone also does not make the image sRGB.
For a tagged source, the embedded ICC profile supplies the source interpretation. For an untagged source, first establish what color space the values actually represent. Assign the correct source profile only when you know that interpretation, then convert to the destination. Assigning Display P3 to an arbitrary file does not recover missing color information.
The full program deliberately makes an image with a known source interpretation. Its first assignment labels the test data; its later assignment to sRGB demonstrates the wrong operation for converting those data. The printed values come from reloading the saved files, so the comparison includes both pixel storage and profile metadata.
Is sRGB an ICC profile?
sRGB is a color space that can be described by ICC profiles. There is not just one sRGB profile file: the International Color Consortium’s sRGB profile registry lists v2, v4 preference, v4 appearance, and iccMAX profiles with different intended uses.
In OneImage, ColorProfile.Srgb supplies a built-in destination profile. You do not need to download a profile file for this recipe. For a custom profile, ColorProfile.FromIcc(bytes) accepts ICC v2/v4 matrix or LUT profiles. DeviceLink, named-color and iccMAX profiles are not supported. A file from the registry is therefore not automatically suitable merely because its name includes sRGB.
Should I convert to sRGB when exporting?
Convert when the receiving workflow calls for sRGB. Keep the original profile and values when the next step expects the original color space. Do not remove the source profile first and then expect conversion to know what those numbers meant.
OneImage defaults to relative colorimetric intent with black-point compensation on. The variation makes both choices explicit for a different intent. The ICC registry explains that media-relative intent maps the source medium white to the destination medium, while perceptual intent aims to preserve the look while re-optimizing colors for the reproduction medium. The result depends on the profiles and intent, so a profile label is not a guarantee that every original color remains representable.
For an untagged CMYK JPEG or TIFF, OneImage uses its built-in generic CMYK profile when converting to RGB. That is a fallback interpretation, not knowledge of the original printer profile. HDR PQ/HLG transfer functions and cICP tags are not interpreted. These behaviors are documented in the color guide.