Exemple #1
0
        public WicDecoder(byte[] inBuffer, WicProcessingContext ctx)
        {
            var stm = AddRef(Wic.CreateStream());

            stm.InitializeFromMemory(inBuffer, (uint)inBuffer.Length);
            init(checkDecoder(() => Wic.CreateDecoderFromStream(stm, null, WICDecodeOptions.WICDecodeMetadataCacheOnDemand)), ctx);
        }
        public WicPixelFormatConverter(WicTransform prev) : base(prev)
        {
            var newFormat = Consts.GUID_WICPixelFormat24bppBGR;

            if (Context.HasAlpha)
            {
                newFormat = Context.PixelFormat.FormatGuid == Consts.GUID_WICPixelFormat32bppPBGRA ? Consts.GUID_WICPixelFormat32bppPBGRA : Consts.GUID_WICPixelFormat32bppBGRA;
            }
            else if (Context.IsGreyscale)
            {
                newFormat = Consts.GUID_WICPixelFormat8bppGray;
            }
            else if (Context.PixelFormat.ColorRepresentation == PixelColorRepresentation.Cmyk)
            {
                newFormat = Consts.GUID_WICPixelFormat32bppCMYK;
            }

            if (Context.PixelFormat.FormatGuid == newFormat)
            {
                return;
            }

            var conv = AddRef(Wic.CreateFormatConverter());

            if (!conv.CanConvert(Context.PixelFormat.FormatGuid, newFormat))
            {
                throw new NotSupportedException("Can't convert to destination pixel format");
            }

            conv.Initialize(Source, newFormat, WICBitmapDitherType.WICBitmapDitherTypeNone, null, 0.0, WICBitmapPaletteType.WICBitmapPaletteTypeCustom);
            Source = conv;
            Context.PixelFormat = PixelFormat.Cache[Source.GetPixelFormat()];
        }
Exemple #3
0
        public WicDecoder(Stream inFile, WicProcessingContext ctx)
        {
            var stm = AddRef(Wic.CreateStream());

            stm.InitializeFromIStream(inFile.AsIStream());
            init(checkDecoder(() => Wic.CreateDecoderFromStream(stm, null, WICDecodeOptions.WICDecodeMetadataCacheOnDemand)), ctx);
        }
        public WicPaletizer(WicTransform prev, uint colors = 256u) : base(prev)
        {
            var newFormat = Consts.GUID_WICPixelFormat8bppIndexed;

            if (!Context.Settings.IndexedColor || Context.PixelFormat.FormatGuid == newFormat || Context.IsGreyscale)
            {
                return;
            }

            var conv = AddRef(Wic.CreateFormatConverter());

            if (!conv.CanConvert(Context.PixelFormat.FormatGuid, newFormat))
            {
                throw new NotSupportedException("Can't convert to destination pixel format");
            }

            var bmp = AddRef(Wic.CreateBitmapFromSource(Source, WICBitmapCreateCacheOption.WICBitmapCacheOnDemand));

            var pal = AddRef(Wic.CreatePalette());

            pal.InitializeFromBitmap(bmp, colors, false);
            Context.DestPalette = pal;

            conv.Initialize(bmp, newFormat, WICBitmapDitherType.WICBitmapDitherTypeErrorDiffusion, pal, 10.0, WICBitmapPaletteType.WICBitmapPaletteTypeCustom);
            Source = conv;
            Context.PixelFormat = PixelFormat.Cache[Source.GetPixelFormat()];
        }
Exemple #5
0
        public void WriteSource(WicTransform prev)
        {
            var src = prev.Source;

            var iformat = src.GetPixelFormat();
            var oformat = iformat;

            Frame.SetPixelFormat(ref oformat);
            if (oformat != iformat)
            {
                var pal = default(IWICPalette);
                var ptt = WICBitmapPaletteType.WICBitmapPaletteTypeCustom;
                if (PixelFormat.Cache[oformat].NumericRepresentation == PixelNumericRepresentation.Indexed)
                {
                    pal = AddRef(Wic.CreatePalette());
                    pal.InitializePredefined(WICBitmapPaletteType.WICBitmapPaletteTypeFixedGray256, false);
                    ptt = WICBitmapPaletteType.WICBitmapPaletteTypeFixedGray256;
                }

                var conv = AddRef(Wic.CreateFormatConverter());
                conv.Initialize(src, oformat, WICBitmapDitherType.WICBitmapDitherTypeNone, pal, 0.0, ptt);
                src = conv;
            }

            Frame.WriteSource(src, null);

            Frame.Commit();
            Encoder.Commit();
        }
        private static IWICColorContext getDefaultColorProfile(Guid pixelFormat)
        {
            var pfi = Wic.CreateComponentInfo(pixelFormat) as IWICPixelFormatInfo;
            var cc  = pfi.GetColorContext();

            Marshal.ReleaseComObject(pfi);
            return(cc);
        }
Exemple #7
0
        public WicColorspaceConverter(WicTransform prev) : base(prev)
        {
            if (Context.SourceColorContext == null)
            {
                return;
            }

            var trans = AddRef(Wic.CreateColorTransform());

            trans.Initialize(Source, Context.SourceColorContext, Context.DestColorContext, Context.IsCmyk ? Context.HasAlpha ? Consts.GUID_WICPixelFormat32bppBGRA : Consts.GUID_WICPixelFormat24bppBGR : Context.PixelFormat);

            Source = trans;
        }
        public WicColorspaceConverter(WicTransform prev) : base(prev)
        {
            if (Context.SourceColorContext == null)
            {
                return;
            }

            var trans = AddRef(Wic.CreateColorTransform());

            trans.Initialize(Source, Context.SourceColorContext, Context.DestColorContext, Context.PixelFormat.FormatGuid);

            Source = trans;
        }
        public WicCmykConverter(WicTransform prev) : base(prev)
        {
            if (Context.PixelFormat.ColorRepresentation != PixelColorRepresentation.Cmyk)
            {
                return;
            }

            var trans = AddRef(Wic.CreateColorTransform());

            trans.Initialize(Source, Context.SourceColorContext, Context.DestColorContext, Context.PixelFormat.AlphaRepresentation != PixelAlphaRepresentation.None ? Consts.GUID_WICPixelFormat32bppBGRA : Consts.GUID_WICPixelFormat24bppBGR);

            Source = trans;
            Context.SourceColorContext = null;
        }
        protected WicBitmapSourceBase(IWICBitmapSource source)
        {
            Source = source;

            Source.GetSize(out Width, out Height);
            Format = Source.GetPixelFormat();

            var pfi = AddRef(Wic.CreateComponentInfo(Format)) as IWICPixelFormatInfo;

            Channels = pfi.GetChannelCount();
            Bpp      = pfi.GetBitsPerPixel() / 8u;
            Release(pfi);

            Stride = Width * Bpp + 3u & ~3u;
        }
        public WicExifRotator(WicTransform prev) : base(prev)
        {
            if (Context.TransformOptions == WICBitmapTransformOptions.WICBitmapTransformRotate0)
            {
                return;
            }

            var rotator = AddRef(Wic.CreateBitmapFlipRotator());

            rotator.Initialize(Source, Context.TransformOptions);

            Source = rotator;
            Source.GetSize(out Context.Width, out Context.Height);
            Context.NeedsCache = Context.TransformOptions != WICBitmapTransformOptions.WICBitmapTransformFlipHorizontal;
        }
        public WicConditionalCache(WicTransform prev) : base(prev)
        {
            if (!Context.NeedsCache)
            {
                return;
            }

            var crop = Context.Settings.Crop;
            var bmp  = AddRef(Wic.CreateBitmapFromSourceRect(Source, (uint)crop.X, (uint)crop.Y, (uint)crop.Width, (uint)crop.Height));

            Source = bmp;
            Source.GetSize(out Context.Width, out Context.Height);
            Context.Settings.Crop = new Rectangle(0, 0, (int)Context.Width, (int)Context.Height);
            Context.NeedsCache    = false;
        }
Exemple #13
0
        public WicPlanarConverter(WicTransform prevY, WicTransform prevCbCr) : base(prevY)
        {
            var cfmt  = Consts.GUID_WICPixelFormat24bppBGR;
            var conv  = AddRef(Wic.CreateFormatConverter());
            var pconv = conv as IWICPlanarFormatConverter;

            pconv.Initialize(new IWICBitmapSource[] { prevY.Source, prevCbCr.Source }, 2, cfmt, WICBitmapDitherType.WICBitmapDitherTypeNone, null, 0.0, WICBitmapPaletteType.WICBitmapPaletteTypeCustom);
            Source = pconv;

            if (Context.SourceColorContext != null)
            {
                var trans = AddRef(Wic.CreateColorTransform());
                trans.Initialize(Source, Context.SourceColorContext, Context.DestColorContext, cfmt);
                Source = trans;
            }
        }
        public WicCropper(WicTransform prev) : base(prev)
        {
            var crop = Context.Settings.Crop;

            if (crop == Rectangle.FromLTRB(0, 0, (int)Context.Width, (int)Context.Height))
            {
                return;
            }

            var cropper = AddRef(Wic.CreateBitmapClipper());

            cropper.Initialize(Source, new WICRect {
                X = crop.X, Y = crop.Y, Width = crop.Width, Height = crop.Height
            });

            Source = cropper;
            Source.GetSize(out Context.Width, out Context.Height);
        }
        public WicScaler(WicTransform prev, bool hybrid = false) : base(prev)
        {
            if (Context.Settings.Width == Context.Width && Context.Settings.Height == Context.Height)
            {
                return;
            }

            double rat = Context.Settings.HybridScaleRatio;

            if (hybrid && rat == 1d)
            {
                return;
            }

            if (Source is IWICBitmapSourceTransform)
            {
                // null crop to disable IWICBitmapSourceTransform scaling
                var clip = AddRef(Wic.CreateBitmapClipper());
                clip.Initialize(Source, new WICRect {
                    X = 0, Y = 0, Width = (int)Context.Width, Height = (int)Context.Height
                });

                Source = clip;
            }

            uint ow   = hybrid ? (uint)Math.Ceiling(Context.Width / rat) : (uint)Context.Settings.Width;
            uint oh   = hybrid ? (uint)Math.Ceiling(Context.Height / rat) : (uint)Context.Settings.Height;
            var  mode = hybrid ? WICBitmapInterpolationMode.WICBitmapInterpolationModeFant :
                        Context.Settings.Interpolation.WeightingFunction.Support <0.1 ? WICBitmapInterpolationMode.WICBitmapInterpolationModeNearestNeighbor :
                                                                                  Context.Settings.Interpolation.WeightingFunction.Support> 1.0 ? Context.Settings.ScaleRatio < 1.0 ? WICBitmapInterpolationMode.WICBitmapInterpolationModeCubic : WICBitmapInterpolationMode.WICBitmapInterpolationModeHighQualityCubic :
                        WICBitmapInterpolationMode.WICBitmapInterpolationModeFant;

            var scaler = AddRef(Wic.CreateBitmapScaler());

            scaler.Initialize(Source, ow, oh, mode);

            Source = scaler;
            Source.GetSize(out Context.Width, out Context.Height);

            if (hybrid)
            {
                Context.Settings.Crop = new Rectangle(0, 0, (int)Context.Width, (int)Context.Height);
            }
        }
        public WicNativeScaler(WicTransform prev) : base(prev)
        {
            double rat = Context.Settings.HybridScaleRatio;

            if (rat == 1d)
            {
                return;
            }

            var trans = Source as IWICBitmapSourceTransform;

            if (trans == null)
            {
                return;
            }

            uint ow = Context.Width, oh = Context.Height;
            uint cw = (uint)Math.Ceiling(ow / rat), ch = (uint)Math.Ceiling(oh / rat);

            trans.GetClosestSize(ref cw, ref ch);

            if (cw == ow && ch == oh)
            {
                return;
            }

            double wrat = (double)ow / cw, hrat = (double)oh / ch;

            var crop = Context.Settings.Crop;

            Context.Settings.Crop = new Rectangle((int)Math.Floor(crop.X / wrat), (int)Math.Floor(crop.Y / hrat), (int)Math.Ceiling(crop.Width / wrat), (int)Math.Ceiling(crop.Height / hrat));

            var scaler = AddRef(Wic.CreateBitmapScaler());

            scaler.Initialize(Source, cw, ch, WICBitmapInterpolationMode.WICBitmapInterpolationModeFant);

            Source = scaler;
            Source.GetSize(out Context.Width, out Context.Height);
        }
Exemple #17
0
        public void WriteSource(WicTransform prev)
        {
            var src = prev.Source;

            var iformat = src.GetPixelFormat();
            var oformat = iformat;

            Frame.SetPixelFormat(ref oformat);
            if (oformat != iformat)
            {
                // TODO grey -> indexed support
                //var pal = AddRef(Wic.CreatePalette());
                //pal.InitializePredefined(WICBitmapPaletteType.WICBitmapPaletteTypeFixedGray256, false);
                var conv = AddRef(Wic.CreateFormatConverter());
                conv.Initialize(src, oformat, WICBitmapDitherType.WICBitmapDitherTypeNone, null, 0.0, WICBitmapPaletteType.WICBitmapPaletteTypeCustom);
                src = conv;
            }

            Frame.WriteSource(src, null);

            Frame.Commit();
            Encoder.Commit();
        }
        public WicMetadataReader(WicTransform prev, bool basicOnly = false) : base(prev)
        {
            if (Context.PixelFormat.NumericRepresentation == PixelNumericRepresentation.Indexed)
            {
                var pal = AddRef(Wic.CreatePalette());
                Frame.CopyPalette(pal);

                Context.HasAlpha    = pal.HasAlpha();
                Context.IsGreyscale = pal.IsGrayscale();
            }
            else
            {
                Context.HasAlpha    = Context.PixelFormat.AlphaRepresentation != PixelAlphaRepresentation.None;
                Context.IsGreyscale = Context.PixelFormat.ColorRepresentation == PixelColorRepresentation.Grey;
            }

#if NET46
            if (Frame.TryGetMetadataQueryReader(out var metareader))
            {
                AddRef(metareader);

                // Exif orientation
                if (metareader.TryGetMetadataByName("System.Photo.Orientation", out var ovar))
                {
                    ushort orientation = 1;
                    if (ovar.UnmanagedType == VarEnum.VT_UI2)
                    {
                        orientation = (ushort)ovar.Value;
                    }

                    var opt = WICBitmapTransformOptions.WICBitmapTransformRotate0;
                    if (orientation == 3 || orientation == 4)
                    {
                        opt = WICBitmapTransformOptions.WICBitmapTransformRotate180;
                    }
                    else if (orientation == 6 || orientation == 7)
                    {
                        opt = WICBitmapTransformOptions.WICBitmapTransformRotate90;
                    }
                    else if (orientation == 5 || orientation == 8)
                    {
                        opt = WICBitmapTransformOptions.WICBitmapTransformRotate270;
                    }

                    if (orientation == 2 || orientation == 4 || orientation == 5 || orientation == 7)
                    {
                        opt |= WICBitmapTransformOptions.WICBitmapTransformFlipHorizontal;
                    }

                    Context.TransformOptions = opt;
                }

                if (basicOnly)
                {
                    return;
                }

                // other requested properties
                var propdic = new Dictionary <string, PropVariant>();
                foreach (string prop in Context.Settings.MetadataNames ?? Enumerable.Empty <string>())
                {
                    if (metareader.TryGetMetadataByName(prop, out var pvar) && pvar.Value != null)
                    {
                        propdic[prop] = pvar;
                    }
                }

                Context.Metadata = propdic;
            }
#endif

            // ICC profiles
            //http://ninedegreesbelow.com/photography/embedded-color-space-information.html
            uint ccc      = Frame.GetColorContextCount();
            var  profiles = new IWICColorContext[ccc];
            var  profile  = default(IWICColorContext);

            if (ccc > 0)
            {
                for (int i = 0; i < ccc; i++)
                {
                    profiles[i] = AddRef(Wic.CreateColorContext());
                }

                Frame.GetColorContexts(ccc, profiles);
            }

            foreach (var cc in profiles)
            {
                var cct = cc.GetType();
                if (cct == WICColorContextType.WICColorContextProfile)
                {
                    uint ccs = cc.GetProfileBytes(0, null);
                    var  ccb = ArrayPool <byte> .Shared.Rent((int)ccs);

                    cc.GetProfileBytes(ccs, ccb);

                    var cp = new ColorProfileInfo(new ArraySegment <byte>(ccb, 0, (int)ccs));
                    ArrayPool <byte> .Shared.Return(ccb);

                    // match only color profiles that match our intended use. if we have a standard sRGB profile, don't save it; we don't need to convert
                    if (cp.IsValid && ((cp.IsDisplayRgb && !cp.IsStandardSrgb) || (cp.IsCmyk && Context.PixelFormat.ColorRepresentation == PixelColorRepresentation.Cmyk) /* || (Context.IsGreyscale && cp.DataColorSpace == "GRAY") */))
                    {
                        profile = cc;
                        break;
                    }
                }
                else if (cct == WICColorContextType.WICColorContextExifColorSpace && cc.GetExifColorSpace() == ExifColorSpace.AdobeRGB)
                {
                    profile = cc;
                    break;
                }
            }

            Context.SourceColorContext = profile ?? (Context.PixelFormat.ColorRepresentation == PixelColorRepresentation.Cmyk ? cmykProfile.Value : null);
            Context.DestColorContext   = srgbProfile.Value;
        }
Exemple #19
0
        public WicMetadataReader(WicTransform prev, bool basicOnly = false) : base(prev)
        {
            var pfi = AddRef(Wic.CreateComponentInfo(Context.PixelFormat)) as IWICPixelFormatInfo2;

            if (pfi.GetNumericRepresentation() == WICPixelFormatNumericRepresentation.WICPixelFormatNumericRepresentationIndexed)
            {
                var pal = AddRef(Wic.CreatePalette());
                Frame.CopyPalette(pal);

                Context.HasAlpha    = pal.HasAlpha();
                Context.IsGreyscale = pal.IsGrayscale();
            }
            else
            {
                uint chans = pfi.GetChannelCount();
                bool trans = pfi.SupportsTransparency();
                Context.HasAlpha    = trans;
                Context.IsGreyscale = chans == 1u;
                Context.IsCmyk      = (chans == 4u && !trans) || (chans == 5u && trans);
            }

            var metareader = Frame.GetMetadataQueryReaderNoThrow();

            if (metareader != null)
            {
                AddRef(metareader);
                // Exif orientation
                if (metareader.HasMetadataName("System.Photo.Orientation"))
                {
                    ushort orientation = 1;
                    var    ovar        = new PropVariant();
                    metareader.GetMetadataByName("System.Photo.Orientation", ovar);
                    if (ovar.UnmanagedType == VarEnum.VT_UI2)
                    {
                        orientation = (ushort)ovar.Value;
                    }

                    var opt = WICBitmapTransformOptions.WICBitmapTransformRotate0;
                    if (orientation == 3 || orientation == 4)
                    {
                        opt = WICBitmapTransformOptions.WICBitmapTransformRotate180;
                    }
                    else if (orientation == 6 || orientation == 7)
                    {
                        opt = WICBitmapTransformOptions.WICBitmapTransformRotate90;
                    }
                    else if (orientation == 5 || orientation == 8)
                    {
                        opt = WICBitmapTransformOptions.WICBitmapTransformRotate270;
                    }

                    if (orientation == 2 || orientation == 4 || orientation == 5 || orientation == 7)
                    {
                        opt |= WICBitmapTransformOptions.WICBitmapTransformFlipHorizontal;
                    }

                    Context.TransformOptions = opt;
                }

                if (basicOnly)
                {
                    return;
                }

                // other requested properties
                var propdic = new Dictionary <string, PropVariant>();
                foreach (string prop in Context.Settings.MetadataNames ?? Enumerable.Empty <string>())
                {
                    if (metareader.HasMetadataName(prop))
                    {
                        var pvar = new PropVariant();
                        metareader.GetMetadataByName(prop, pvar);
                        if (pvar.Value != null)
                        {
                            propdic[prop] = pvar;
                        }
                    }
                }

                Context.Metadata = propdic;
            }

            // ICC profiles
            //http://ninedegreesbelow.com/photography/embedded-color-space-information.html
            uint ccc      = Frame.GetColorContextCount();
            var  profiles = new IWICColorContext[ccc];
            var  profile  = (IWICColorContext)null;

            if (ccc > 0)
            {
                for (int i = 0; i < ccc; i++)
                {
                    profiles[i] = AddRef(Wic.CreateColorContext());
                }

                Frame.GetColorContexts(ccc, profiles);
            }

            foreach (var cc in profiles)
            {
                var cct = cc.GetType();
                if (cct == WICColorContextType.WICColorContextProfile)
                {
                    uint ccs = cc.GetProfileBytes(0, null);
                    var  ccb = new byte[ccs];
                    cc.GetProfileBytes(ccs, ccb);

                    // match only color profiles that match our intended use. if we have a standard sRGB profile, don't save it; we don't need to convert
                    var cp = new ColorProfileInfo(ccb);
                    if (cp.IsValid && ((cp.IsDisplayRgb && !cp.IsStandardSrgb) || (Context.IsCmyk && cp.IsCmyk) /* || (Context.IsGreyscale && cp.DataColorSpace == "GRAY") */))
                    {
                        profile = cc;
                        break;
                    }
                }
                else if (cct == WICColorContextType.WICColorContextExifColorSpace && cc.GetExifColorSpace() == ExifColorSpace.AdobeRGB)
                {
                    profile = cc;
                    break;
                }
            }

            Context.SourceColorContext = profile ?? (Context.IsCmyk ? cmykProfile.Value : null);
            Context.DestColorContext   = srgbProfile.Value;
        }
Exemple #20
0
 public WicDecoder(string fileName, WicProcessingContext ctx)
 {
     init(checkDecoder(() => Wic.CreateDecoderFromFilename(fileName, null, GenericAccessRights.GENERIC_READ, WICDecodeOptions.WICDecodeMetadataCacheOnDemand)), ctx);
 }
Exemple #21
0
        public WicEncoder(IStream stm, WicProcessingContext ctx)
        {
            var frame = (IWICBitmapFrameEncode)null;

            if (ctx.Settings.SaveFormat == FileFormat.Jpeg)
            {
                Encoder = AddRef(Wic.CreateEncoder(Consts.GUID_ContainerFormatJpeg, null));
                Encoder.Initialize(stm, WICBitmapEncoderCacheOption.WICBitmapEncoderNoCache);

                var bag = (IPropertyBag2)null;
                Encoder.CreateNewFrame(out frame, ref bag);
                AddRef(frame);
                AddRef(bag);

                if (ctx.Settings.JpegSubsampleMode != ChromaSubsampleMode.Default)
                {
                    var props = new PROPBAG2[] { new PROPBAG2 {
                                                     pstrName = "ImageQuality"
                                                 }, new PROPBAG2 {
                                                     pstrName = "JpegYCrCbSubsampling"
                                                 } };
                    bag.Write(2, props, new object[] { ctx.Settings.JpegQuality / 100f, (byte)ctx.Settings.JpegSubsampleMode });
                }
                else
                {
                    var props = new PROPBAG2[] { new PROPBAG2 {
                                                     pstrName = "ImageQuality"
                                                 } };
                    bag.Write(1, props, new object[] { ctx.Settings.JpegQuality / 100f });
                }

                frame.Initialize(bag);
            }
            else if (ctx.Settings.SaveFormat == FileFormat.Gif)
            {
                Encoder = AddRef(Wic.CreateEncoder(Consts.GUID_ContainerFormatGif, null));
                Encoder.Initialize(stm, WICBitmapEncoderCacheOption.WICBitmapEncoderNoCache);
                Encoder.SetPalette(ctx.DestPalette);

                Encoder.CreateNewFrame(out frame, null);
                AddRef(frame);

                frame.Initialize(null);
            }
            else if (ctx.Settings.SaveFormat == FileFormat.Bmp)
            {
                Encoder = AddRef(Wic.CreateEncoder(Consts.GUID_ContainerFormatBmp, null));
                Encoder.Initialize(stm, WICBitmapEncoderCacheOption.WICBitmapEncoderNoCache);

                var bag = (IPropertyBag2)null;
                Encoder.CreateNewFrame(out frame, ref bag);
                AddRef(frame);
                AddRef(bag);

                var props = new PROPBAG2[] { new PROPBAG2 {
                                                 pstrName = "EnableV5Header32bppBGRA"
                                             } };
                bag.Write(1, props, new object[] { ctx.PixelFormat == Consts.GUID_WICPixelFormat32bppBGRA });

                frame.Initialize(bag);
            }
            else if (ctx.Settings.SaveFormat == FileFormat.Tiff)
            {
                Encoder = AddRef(Wic.CreateEncoder(Consts.GUID_ContainerFormatTiff, null));
                Encoder.Initialize(stm, WICBitmapEncoderCacheOption.WICBitmapEncoderNoCache);

                var bag = (IPropertyBag2)null;
                Encoder.CreateNewFrame(out frame, ref bag);
                AddRef(frame);
                AddRef(bag);

                var props = new PROPBAG2[] { new PROPBAG2 {
                                                 pstrName = "TiffCompressionMethod"
                                             } };
                bag.Write(1, props, new object[] { (byte)WICTiffCompressionOption.WICTiffCompressionNone });

                frame.Initialize(bag);
            }
            else
            {
                Encoder = AddRef(Wic.CreateEncoder(Consts.GUID_ContainerFormatPng, null));
                Encoder.Initialize(stm, WICBitmapEncoderCacheOption.WICBitmapEncoderNoCache);

                Encoder.CreateNewFrame(out frame, null);
                AddRef(frame);

                frame.Initialize(null);
            }

            frame.SetResolution(96d, 96d);
            frame.SetSize(ctx.Width, ctx.Height);

            if (ctx.Settings.IndexedColor && ctx.PixelFormat == Consts.GUID_WICPixelFormat8bppIndexed)
            {
                frame.SetPalette(ctx.DestPalette);
            }

            if (ctx.Metadata?.Count > 0)
            {
                var metawriter = frame.GetMetadataQueryWriterNoThrow();
                if (metawriter != null)
                {
                    AddRef(metawriter);
                    foreach (var nv in ctx.Metadata)
                    {
                        metawriter.SetMetadataByNameNoThrow(nv.Key, nv.Value);
                    }
                }
            }

            // TODO setting
            //if (ctx.DestColorContext != null)
            //	frame.SetColorContexts(1, new IWICColorContext[] { ctx.DestColorContext });

            Frame = frame;
        }