Example #1
0
        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);
        }
Example #2
0
        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;
        }
Example #3
0
        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));
        }
Example #4
0
        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));
        }
Example #5
0
        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));
        }
Example #6
0
        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;
        }