private WicColorProfile getColorProfile() { var guid = default(Guid); HRESULT.Check(WicSource->GetPixelFormat(&guid)); var fmt = PixelFormat.FromGuid(guid); uint ccc; if (FAILED(WicFrame->GetColorContexts(0, null, &ccc)) || ccc == 0) { return(WicColorProfile.GetDefaultFor(fmt)); } var profiles = stackalloc IWICColorContext *[(int)ccc]; for (int i = 0; i < (int)ccc; i++) { HRESULT.Check(Wic.Factory->CreateColorContext(&profiles[i])); } HRESULT.Check(WicFrame->GetColorContexts(ccc, profiles, &ccc)); var match = matchProfile(new Span <IntPtr>(profiles, (int)ccc), fmt); for (int i = 0; i < (int)ccc; i++) { profiles[i]->Release(); } return(match); }
public static void AddColorProfileReader(PipelineContext ctx) { if (ctx.ImageFrame is not WicImageFrame wicFrame || ctx.Settings.ColorProfileMode == ColorProfileMode.Ignore) { return; } ctx.WicContext.SourceColorContext = WicColorProfile.GetSourceProfile(wicFrame.ColorProfileSource, ctx.Settings.ColorProfileMode).WicColorContext; ctx.WicContext.DestColorContext = WicColorProfile.GetDestProfile(wicFrame.ColorProfileSource, ctx.Settings.ColorProfileMode).WicColorContext; }
private WicColorProfile matchProfile(ReadOnlySpan <IntPtr> profiles, PixelFormat fmt) { var buff = (Span <byte>) stackalloc byte[8]; foreach (var pcc in profiles) { var cc = (IWICColorContext *)pcc; var cct = default(WICColorContextType); HRESULT.Check(cc->GetType(&cct)); if (cct == WICColorContextType.WICColorContextProfile) { uint cb; HRESULT.Check(cc->GetProfileBytes(0, null, &cb)); // Don't try to read giant profiles. 4MiB should be enough, and more might indicate corrupt metadata. if (cb > 1024 * 1024 * 4) { continue; } var cpi = WicColorProfile.GetProfileFromContext(cc, cb); if (cpi.IsValid && cpi.IsCompatibleWith(fmt)) { return(new WicColorProfile(new ComPtr <IWICColorContext>(cc), cpi, true)); } } else if (cct == WICColorContextType.WICColorContextExifColorSpace && WicMetadataReader is not null) { // Although WIC defines the non-standard AdobeRGB ExifColorSpace value, most software (including Adobe's) only supports the Uncalibrated/InteropIndex=R03 convention. // http://ninedegreesbelow.com/photography/embedded-color-space-information.html uint ecs; HRESULT.Check(cc->GetExifColorSpace(&ecs)); if (ecs == (uint)ExifColorSpace.AdobeRGB) { return(WicColorProfile.AdobeRgb.Value); } if (ecs == (uint)ExifColorSpace.Uncalibrated) { var r03 = (ReadOnlySpan <byte>)(new[] { (byte)'R', (byte)'0', (byte)'3' }); var meta = ComPtr <IWICMetadataQueryReader> .Wrap(WicMetadataReader); if (meta.GetValueOrDefault(Container.ContainerFormat == FileFormat.Jpeg ? Wic.Metadata.InteropIndexJpeg : Wic.Metadata.InteropIndexExif, buff).SequenceEqual(r03)) { return(WicColorProfile.AdobeRgb.Value); } } } } return(WicColorProfile.GetDefaultFor(fmt)); }
private WicColorProfile matchProfile(ReadOnlySpan <IWICColorContext> profiles, PixelFormat fmt) { foreach (var cc in profiles) { var cct = cc.GetType(); if (cct == WICColorContextType.WICColorContextProfile) { uint cb = cc.GetProfileBytes(0, null); // Don't try to read giant profiles. 4MiB should be enough, and more might indicate corrupt metadata. if (cb > 1024 * 1024 * 4) { continue; } var cpi = WicColorProfile.GetProfileFromContext(cc, cb); if (cpi.IsValid && cpi.IsCompatibleWith(fmt)) { return(new WicColorProfile(cc, cpi)); } } else if (cct == WICColorContextType.WICColorContextExifColorSpace && WicMetadataReader is not null) { // Although WIC defines the non-standard AdobeRGB ExifColorSpace value, most software (including Adobe's) only supports the Uncalibrated/InteropIndex=R03 convention. // http://ninedegreesbelow.com/photography/embedded-color-space-information.html var ecs = cc.GetExifColorSpace(); if ( ecs == ExifColorSpace.AdobeRGB || ( ecs == ExifColorSpace.Uncalibrated && WicMetadataReader.GetValueOrDefault <string>(Container.ContainerFormat == FileFormat.Jpeg ? Wic.Metadata.InteropIndexJpeg : Wic.Metadata.InteropIndexExif) == "R03") ) { return(WicColorProfile.AdobeRgb.Value); } } } return(WicColorProfile.GetDefaultFor(fmt)); }
private WicColorProfile getColorProfile() { var fmt = PixelFormat.FromGuid(WicSource.GetPixelFormat()); uint ccc = WicFrame.GetColorContextCount(); if (ccc == 0) { return(WicColorProfile.GetDefaultFor(fmt)); } var profiles = ArrayPool <IWICColorContext> .Shared.Rent((int)ccc); for (int i = 0; i < (int)ccc; i++) { profiles[i] = comHandles.AddRef(Wic.Factory.CreateColorContext()); } WicFrame.GetColorContexts(ccc, profiles); var match = matchProfile(profiles.AsSpan(0, (int)ccc), fmt); ArrayPool <IWICColorContext> .Shared.Return(profiles); return(match ?? WicColorProfile.GetDefaultFor(fmt)); }
public static void AddColorProfileReader(PipelineContext ctx) { if (!(ctx.ImageFrame is WicImageFrame wicFrame)) { return; } ctx.WicContext.SourceColorContext = wicFrame.ColorProfileSource.WicColorContext; ctx.WicContext.DestColorContext = ctx.Settings.ColorProfileMode <= ColorProfileMode.NormalizeAndEmbed ? WicColorProfile.GetDefaultFor(ctx.Source.Format).WicColorContext : ctx.WicContext.SourceColorContext; }