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 void moveToFrame(int index) { ctx.Settings.FrameIndex = index; ctx.ImageFrame.Dispose(); ctx.ImageFrame = ctx.ImageContainer.GetFrame(index); if (ctx.ImageFrame is WicImageFrame wicFrame) { ctx.Source = ComPtr <IWICBitmapSource> .Wrap(wicFrame.WicSource).AsPixelSource(null, nameof(IWICBitmapFrameDecode), false); } else { ctx.Source = ctx.ImageFrame.PixelSource.AsPixelSource(); } MagicTransforms.AddGifFrameBuffer(ctx, false); if (lastSource is ChainedPixelSource chain && chain.Passthrough) { chain.ReInit(ctx.Source); ctx.Source = chain; } }