Esempio n. 1
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);
        }
Esempio n. 2
0
        public static void AddHighQualityScaler(WicProcessingContext ctx)
        {
            uint width = (uint)ctx.Settings.Width, height = (uint)ctx.Settings.Height;
            var  fmt           = ctx.Source.Format;
            var  interpolator  = ctx.Settings.Interpolation.WeightingFunction.Support > 1d && fmt.ColorRepresentation == PixelColorRepresentation.Unspecified ? InterpolationSettings.Hermite : ctx.Settings.Interpolation;
            var  interpolatorx = width == ctx.Source.Width ? InterpolationSettings.NearestNeighbor : interpolator;
            var  interpolatory = height == ctx.Source.Height ? InterpolationSettings.NearestNeighbor : interpolator;

            if (fmt.NumericRepresentation == PixelNumericRepresentation.Float)
            {
                var mx = ctx.AddDispose(KernelMap <float> .MakeScaleMap(ctx.Source.Width, width, fmt.ColorChannelCount, fmt.AlphaRepresentation != PixelAlphaRepresentation.None, true, interpolatorx));
                var my = ctx.AddDispose(KernelMap <float> .MakeScaleMap(ctx.Source.Height, height, fmt.ChannelCount == 3 ? 4 : fmt.ColorChannelCount, fmt.AlphaRepresentation != PixelAlphaRepresentation.None, true, interpolatory));

                ctx.Source = ctx.AddDispose(new ConvolutionTransform <float, float>(ctx.Source, mx, my));
            }
            else
            {
                var mx = ctx.AddDispose(KernelMap <int> .MakeScaleMap(ctx.Source.Width, width, 1, fmt.AlphaRepresentation == PixelAlphaRepresentation.Unassociated, false, interpolatorx));
                var my = ctx.AddDispose(KernelMap <int> .MakeScaleMap(ctx.Source.Height, height, 1, fmt.AlphaRepresentation == PixelAlphaRepresentation.Unassociated, false, interpolatory));

                if (fmt.NumericRepresentation == PixelNumericRepresentation.Fixed)
                {
                    ctx.Source = ctx.AddDispose(new ConvolutionTransform <ushort, int>(ctx.Source, mx, my));
                }
                else
                {
                    ctx.Source = ctx.AddDispose(new ConvolutionTransform <byte, int>(ctx.Source, mx, my));
                }
            }
        }
Esempio n. 3
0
        public static void AddExternalFormatConverter(WicProcessingContext ctx)
        {
            var ifmt = ctx.Source.Format.FormatGuid;
            var ofmt = ifmt;

            if (ifmt == PixelFormat.Grey32BppFloat.FormatGuid || ifmt == PixelFormat.Grey32BppLinearFloat.FormatGuid || ifmt == PixelFormat.Grey16BppLinearUQ15.FormatGuid)
            {
                ofmt = Consts.GUID_WICPixelFormat8bppGray;
            }
            else if (ifmt == PixelFormat.Y32BppFloat.FormatGuid || ifmt == PixelFormat.Y32BppLinearFloat.FormatGuid || ifmt == PixelFormat.Y16BppLinearUQ15.FormatGuid)
            {
                ofmt = Consts.GUID_WICPixelFormat8bppY;
            }
            else if (ifmt == PixelFormat.Bgrx128BppFloat.FormatGuid || ifmt == PixelFormat.Bgrx128BppLinearFloat.FormatGuid || ifmt == PixelFormat.Bgr96BppFloat.FormatGuid || ifmt == PixelFormat.Bgr96BppLinearFloat.FormatGuid || ifmt == PixelFormat.Bgr48BppLinearUQ15.FormatGuid)
            {
                ofmt = Consts.GUID_WICPixelFormat24bppBGR;
            }
            else if (ifmt == PixelFormat.Pbgra128BppFloat.FormatGuid || ifmt == PixelFormat.Bgra128BppLinearFloat.FormatGuid || ifmt == PixelFormat.Pbgra128BppLinearFloat.FormatGuid || ifmt == PixelFormat.Bgra64BppLinearUQ15.FormatGuid || ifmt == PixelFormat.Pbgra64BppLinearUQ15.FormatGuid)
            {
                ofmt = Consts.GUID_WICPixelFormat32bppBGRA;
            }
            else if (ifmt == PixelFormat.CbCr64BppFloat.FormatGuid)
            {
                ofmt = Consts.GUID_WICPixelFormat16bppCbCr;
            }

            if (ofmt == ifmt)
            {
                return;
            }

            bool forceSrgb = (ifmt == PixelFormat.Y32BppLinearFloat.FormatGuid || ifmt == PixelFormat.Y16BppLinearUQ15.FormatGuid) && ctx.SourceColorProfile != ColorProfile.sRGB;

            ctx.Source = ctx.AddDispose(new FormatConversionTransform(ctx.Source, forceSrgb ? ColorProfile.sRGB : ctx.SourceColorProfile, forceSrgb ? ColorProfile.sRGB : ctx.DestColorProfile, ofmt));
        }
Esempio n. 4
0
 public WicDecoder(IPixelSource imgSource, WicProcessingContext ctx)
 {
     init(null, ctx);
     ContainerFormat = FileFormat.Unknown;
     FrameCount      = 1;
     ctx.Source      = imgSource.AsPixelSource();
 }
Esempio n. 5
0
        public static void AddUnsharpMask(WicProcessingContext ctx)
        {
            var ss = ctx.Settings.UnsharpMask;

            if (!ctx.Settings.Sharpen || ss.Radius <= 0d || ss.Amount <= 0)
            {
                return;
            }

            var fmt = ctx.Source.Format;

            if (fmt.NumericRepresentation == PixelNumericRepresentation.Float)
            {
                var mapx = ctx.AddDispose(KernelMap <float> .MakeBlurMap(ctx.Source.Width, ss.Radius, 1, false, true));
                var mapy = ctx.AddDispose(KernelMap <float> .MakeBlurMap(ctx.Source.Height, ss.Radius, 1, false, true));

                ctx.Source = ctx.AddDispose(new UnsharpMaskTransform <float, float>(ctx.Source, mapx, mapy, ss));
            }
            else
            {
                var mapx = ctx.AddDispose(KernelMap <int> .MakeBlurMap(ctx.Source.Width, ss.Radius, 1, false, false));
                var mapy = ctx.AddDispose(KernelMap <int> .MakeBlurMap(ctx.Source.Height, ss.Radius, 1, false, false));

                if (fmt.NumericRepresentation == PixelNumericRepresentation.Fixed)
                {
                    ctx.Source = ctx.AddDispose(new UnsharpMaskTransform <ushort, int>(ctx.Source, mapx, mapy, ss));
                }
                else
                {
                    ctx.Source = ctx.AddDispose(new UnsharpMaskTransform <byte, int>(ctx.Source, mapx, mapy, ss));
                }
            }
        }
Esempio n. 6
0
        public static void AddPlanarCache(WicProcessingContext ctx)
        {
            if (!(ctx.Source.WicSource is IWICPlanarBitmapSourceTransform trans))
            {
                throw new NotSupportedException("Transform chain doesn't support planar mode.  Only JPEG Decoder, Rotator, Scaler, and PixelFormatConverter are allowed");
            }

            double rat    = ctx.Settings.HybridScaleRatio.Clamp(1d, 8d);
            uint   width  = (uint)Math.Ceiling(ctx.Source.Width / rat);
            uint   height = (uint)Math.Ceiling(ctx.Source.Height / rat);

            var fmts = new[] { Consts.GUID_WICPixelFormat8bppY, Consts.GUID_WICPixelFormat16bppCbCr };
            var desc = new WICBitmapPlaneDescription[2];

            var opt = ctx.DecoderFrame.ExifOrientation.ToWicTransformOptions();

            if (!trans.DoesSupportTransform(ref width, ref height, opt, WICPlanarOptions.WICPlanarOptionsDefault, fmts, desc, 2))
            {
                throw new NotSupportedException("Requested planar transform not supported");
            }

            var cacheSource = ctx.AddDispose(new WicPlanarCache(trans, desc[0], desc[1], ctx.Settings.Crop.ToWicRect(), opt, width, height, rat));

            ctx.PlanarChromaSource = cacheSource.GetPlane(WicPlane.Chroma);
            ctx.PlanarLumaSource   = cacheSource.GetPlane(WicPlane.Luma);
            ctx.Source             = ctx.PlanarChromaSource;
            ctx.Source             = ctx.PlanarLumaSource;
        }
Esempio n. 7
0
        public WicDecoder(ArraySegment <byte> inBuffer, WicProcessingContext ctx)
        {
            var stm = ctx.AddRef(Wic.Factory.CreateStream());

            stm.InitializeFromMemory(inBuffer.Array, (uint)inBuffer.Count);
            init(checkDecoder(() => Wic.Factory.CreateDecoderFromStream(stm, null, WICDecodeOptions.WICDecodeMetadataCacheOnDemand)), ctx);
        }
Esempio n. 8
0
        public static void AddIndexedColorConverter(WicProcessingContext ctx)
        {
            var newFormat = Consts.GUID_WICPixelFormat8bppIndexed;

            if (!ctx.Settings.IndexedColor || ctx.Source.Format.NumericRepresentation == PixelNumericRepresentation.Indexed || ctx.Source.Format.ColorRepresentation == PixelColorRepresentation.Grey)
            {
                return;
            }

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

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

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

            ctx.Source = bmp.AsPixelSource(nameof(IWICBitmap));

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

            pal.InitializeFromBitmap(ctx.Source.WicSource, 256u, ctx.Source.Format.AlphaRepresentation != PixelAlphaRepresentation.None);
            ctx.DestPalette = pal;

            conv.Initialize(ctx.Source.WicSource, newFormat, WICBitmapDitherType.WICBitmapDitherTypeErrorDiffusion, pal, 10.0, WICBitmapPaletteType.WICBitmapPaletteTypeCustom);
            ctx.Source = conv.AsPixelSource(nameof(IWICFormatConverter), false);
        }
Esempio n. 9
0
        public static void AddScaler(WicProcessingContext ctx, bool hybrid = false)
        {
            double rat = ctx.Settings.HybridScaleRatio;

            if ((ctx.Settings.Width == ctx.Source.Width && ctx.Settings.Height == ctx.Source.Height) || (hybrid && rat == 1d))
            {
                return;
            }

            if (ctx.Source.WicSource is IWICBitmapSourceTransform)
            {
                ctx.Source = ctx.Source.WicSource.AsPixelSource(nameof(IWICBitmapFrameDecode));
            }

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

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

            scaler.Initialize(ctx.Source.WicSource, ow, oh, mode);
            ctx.Source = scaler.AsPixelSource(nameof(IWICBitmapScaler));

            if (hybrid)
            {
                ctx.Settings.Crop = new Rectangle(0, 0, (int)ctx.Source.Width, (int)ctx.Source.Height);
            }
        }
Esempio n. 10
0
        public static void AddInternalFormatConverter(WicProcessingContext ctx)
        {
            var  ifmt   = ctx.Source.Format.FormatGuid;
            var  ofmt   = ifmt;
            bool linear = ctx.Settings.BlendingMode == GammaMode.Linear;

            if (MagicImageProcessor.EnableSimd)
            {
                if (ifmt == Consts.GUID_WICPixelFormat8bppGray)
                {
                    ofmt = linear ? PixelFormat.Grey32BppLinearFloat.FormatGuid : Consts.GUID_WICPixelFormat32bppGrayFloat;
                }
                else if (ifmt == Consts.GUID_WICPixelFormat8bppY)
                {
                    ofmt = linear ? PixelFormat.Y32BppLinearFloat.FormatGuid : PixelFormat.Y32BppFloat.FormatGuid;
                }
                else if (ifmt == Consts.GUID_WICPixelFormat24bppBGR)
                {
                    ofmt = linear ? PixelFormat.Bgr96BppLinearFloat.FormatGuid : PixelFormat.Bgr96BppFloat.FormatGuid;
                }
                else if (ifmt == Consts.GUID_WICPixelFormat32bppBGRA || ifmt == Consts.GUID_WICPixelFormat32bppPBGRA)
                {
                    ofmt = linear ? PixelFormat.Pbgra128BppLinearFloat.FormatGuid : PixelFormat.Pbgra128BppFloat.FormatGuid;
                }
                else if (ifmt == Consts.GUID_WICPixelFormat16bppCbCr)
                {
                    ofmt = PixelFormat.CbCr64BppFloat.FormatGuid;
                }
            }
            else if (linear)
            {
                if (ifmt == Consts.GUID_WICPixelFormat8bppGray)
                {
                    ofmt = PixelFormat.Grey16BppLinearUQ15.FormatGuid;
                }
                else if (ifmt == Consts.GUID_WICPixelFormat8bppY)
                {
                    ofmt = PixelFormat.Y16BppLinearUQ15.FormatGuid;
                }
                else if (ifmt == Consts.GUID_WICPixelFormat24bppBGR)
                {
                    ofmt = PixelFormat.Bgr48BppLinearUQ15.FormatGuid;
                }
                else if (ifmt == Consts.GUID_WICPixelFormat32bppBGRA)
                {
                    ofmt = PixelFormat.Bgra64BppLinearUQ15.FormatGuid;
                }
                else if (ifmt == Consts.GUID_WICPixelFormat32bppPBGRA)
                {
                    ofmt = PixelFormat.Pbgra64BppLinearUQ15.FormatGuid;
                }
            }

            if (ofmt == ifmt)
            {
                return;
            }

            ctx.Source = ctx.AddDispose(new FormatConversionTransform(ctx.Source, ofmt));
        }
Esempio n. 11
0
        public static void AddColorspaceConverter(WicProcessingContext ctx)
        {
            if (ctx.SourceColorProfile == ctx.DestColorProfile)
            {
                if ((ctx.SourceColorProfile == ColorProfile.sRGB || ctx.SourceColorProfile == ColorProfile.sGrey) && ctx.SourceColorContext != null)
                {
                    AddExternalFormatConverter(ctx);
                    WicTransforms.AddColorspaceConverter(ctx);
                }

                return;
            }

            if (ctx.Source.Format.NumericRepresentation == PixelNumericRepresentation.Float && ctx.Source.Format.Colorspace != PixelColorspace.LinearRgb)
            {
                AddExternalFormatConverter(ctx);
            }

            AddInternalFormatConverter(ctx, forceLinear: true);

            if (ctx.Source.Format.ColorRepresentation != PixelColorRepresentation.Bgr)
            {
                return;
            }

            var matrix = ctx.SourceColorProfile.Matrix * ctx.DestColorProfile.InverseMatrix;

            if (matrix == default || matrix.IsIdentity)
            {
                return;
            }

            ctx.Source = new ColorMatrixTransformInternal(ctx.Source, matrix);
        }
Esempio n. 12
0
        private static void processImage(WicDecoder dec, WicProcessingContext ctx, Stream ostm)
        {
            using (var frm = new WicFrameReader(dec, ctx))
                using (var met = new WicMetadataReader(frm))
                {
                    if (!ctx.Settings.Normalized)
                    {
                        ctx.Settings.Fixup((int)ctx.Width, (int)ctx.Height, ctx.IsRotated90);
                    }

                    ctx.Settings.HybridMode = HybridScaleMode.Turbo;
                    //ctx.NeedsCache = true;

                    using (var qsc = new WicNativeScaler(met))
                        using (var rot = new WicExifRotator(qsc))
                            using (var cac = new WicConditionalCache(rot))
                                using (var crp = new WicCropper(cac))
                                    using (var pix = new WicPixelFormatConverter(crp))
                                        using (var cmy = new WicCmykConverter(pix))
                                            using (var res = new WicScaler(cmy))
                                                using (var csc = new WicColorspaceConverter(res))
                                                    using (var mat = new WicMatteTransform(csc))
                                                        using (var pal = new WicPaletizer(mat, 256))
                                                            using (var enc = new WicEncoder(ostm.AsIStream(), ctx))
                                                                enc.WriteSource(pal);
                }
        }
Esempio n. 13
0
        private void init(IWICBitmapDecoder dec, WicProcessingContext ctx)
        {
            Decoder = AddRef(dec);

            ctx.ContainerFormat     = dec.GetContainerFormat();
            ctx.ContainerFrameCount = dec.GetFrameCount();
        }
Esempio n. 14
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);
        }
Esempio n. 15
0
        public static void AddPlanarConverter(WicProcessingContext ctx)
        {
            var conv = ctx.AddRef(Wic.Factory.CreateFormatConverter()) as IWICPlanarFormatConverter;

            conv.Initialize(new[] { ctx.PlanarLumaSource.WicSource, ctx.PlanarChromaSource.WicSource }, 2, Consts.GUID_WICPixelFormat24bppBGR, WICBitmapDitherType.WICBitmapDitherTypeNone, null, 0.0, WICBitmapPaletteType.WICBitmapPaletteTypeCustom);
            ctx.Source             = conv.AsPixelSource(nameof(IWICPlanarFormatConverter));
            ctx.PlanarChromaSource = ctx.PlanarLumaSource = null;
        }
Esempio n. 16
0
        public static void AddPixelFormatConverter(WicProcessingContext ctx, bool allowPbgra = true)
        {
            var curFormat = ctx.Source.Format;

            if (curFormat.ColorRepresentation == PixelColorRepresentation.Cmyk)
            {
                //TODO WIC doesn't support proper CMYKA conversion with color profile
                if (curFormat.AlphaRepresentation == PixelAlphaRepresentation.None)
                {
                    // WIC doesn't support 16bpc CMYK conversion with color profile
                    if (curFormat.BitsPerPixel == 64)
                    {
                        ctx.Source = ctx.AddDispose(new FormatConversionTransformInternal(ctx.Source, null, null, Consts.GUID_WICPixelFormat32bppCMYK));
                    }

                    var trans = ctx.AddRef(Wic.Factory.CreateColorTransform());
                    if (trans.TryInitialize(ctx.Source.WicSource, ctx.SourceColorContext, ctx.DestColorContext, Consts.GUID_WICPixelFormat24bppBGR))
                    {
                        ctx.Source = trans.AsPixelSource(nameof(IWICColorTransform));
                        curFormat  = ctx.Source.Format;
                    }
                }

                ctx.SourceColorContext = null;
            }

            var newFormat = PixelFormat.Cache[Consts.GUID_WICPixelFormat24bppBGR];

            if (curFormat.AlphaRepresentation == PixelAlphaRepresentation.Associated && allowPbgra && ctx.Settings.BlendingMode != GammaMode.Linear && ctx.Settings.MatteColor.IsEmpty)
            {
                newFormat = PixelFormat.Cache[Consts.GUID_WICPixelFormat32bppPBGRA];
            }
            else if (curFormat.AlphaRepresentation != PixelAlphaRepresentation.None)
            {
                newFormat = PixelFormat.Cache[Consts.GUID_WICPixelFormat32bppBGRA];
            }
            else if (curFormat.ColorRepresentation == PixelColorRepresentation.Grey)
            {
                newFormat = PixelFormat.Cache[Consts.GUID_WICPixelFormat8bppGray];
            }

            if (curFormat.FormatGuid == newFormat.FormatGuid)
            {
                return;
            }

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

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

            conv.Initialize(ctx.Source.WicSource, newFormat.FormatGuid, WICBitmapDitherType.WICBitmapDitherTypeNone, null, 0.0, WICBitmapPaletteType.WICBitmapPaletteTypeCustom);
            ctx.Source = conv.AsPixelSource($"{nameof(IWICFormatConverter)}: {curFormat.Name}->{newFormat.Name}");
        }
Esempio n. 17
0
        internal ProcessingPipeline(WicProcessingContext ctx)
        {
            Context = ctx;
            source  = new Lazy <IPixelSource>(() => {
                MagicTransforms.AddExternalFormatConverter(Context);
                WicTransforms.AddPixelFormatConverter(Context, false);

                return(Context.Source.AsIPixelSource());
            });
        }
Esempio n. 18
0
        public static void ProcessImage(byte[] imgBuffer, Stream ostm, ProcessImageSettings s)
        {
            Contract.Requires <ArgumentNullException>(imgBuffer != null, nameof(imgBuffer));
            Contract.Requires <ArgumentNullException>(ostm != null, nameof(ostm));
            Contract.Requires <ArgumentException>(ostm.CanSeek && ostm.CanWrite, "Output Stream must allow Seek and Write");

            using (var ctx = new WicProcessingContext(s))
                using (var dec = new WicDecoder(imgBuffer, ctx))
                    processImage(dec, ctx, ostm);
        }
Esempio n. 19
0
        /// <summary>Constructs a new processing pipeline from which pixels can be retrieved.</summary>
        /// <param name="imgStream">A stream containing a supported input image container.</param>
        /// <param name="settings">The settings for this processing operation.</param>
        /// <returns>A <see cref="ProcessingPipeline" /> containing the <see cref="IPixelSource" />, settings used, and basic instrumentation for the pipeline.</returns>
        public static ProcessingPipeline BuildPipeline(Stream imgStream, ProcessImageSettings settings)
        {
            checkInStream(imgStream);

            var ctx = new WicProcessingContext(settings);
            var dec = new WicDecoder(imgStream, ctx);

            buildPipeline(ctx, false);
            return(new ProcessingPipeline(ctx));
        }
Esempio n. 20
0
        public ImageFileInfo(byte[] imgBuffer, DateTime lastModified)
        {
            Contract.Requires <ArgumentNullException>(imgBuffer != null, nameof(imgBuffer));

            using (var ctx = new WicProcessingContext(new ProcessImageSettings()))
                using (var dec = new WicDecoder(imgBuffer, ctx))
                    loadInfo(dec, ctx);

            FileSize = imgBuffer.Length;
            FileDate = lastModified;
        }
Esempio n. 21
0
        public WicEncoder(WicProcessingContext ctx, IStream stm)
        {
            Encoder = ctx.AddRef(Wic.Factory.CreateEncoder(formatMap.GetValueOrDefault(ctx.Settings.SaveFormat, () => Consts.GUID_ContainerFormatPng), null));
            Encoder.Initialize(stm, WICBitmapEncoderCacheOption.WICBitmapEncoderNoCache);

            var props = new Dictionary <string, object>();
            var bag   = default(IPropertyBag2);

            Encoder.CreateNewFrame(out var frame, ref bag);
            ctx.AddRef(frame);
            ctx.AddRef(bag);

            if (ctx.Settings.SaveFormat == FileFormat.Jpeg)
            {
                props.Add("ImageQuality", ctx.Settings.JpegQuality / 100f);
            }

            if (ctx.Settings.SaveFormat == FileFormat.Jpeg && ctx.Settings.JpegSubsampleMode != ChromaSubsampleMode.Default)
            {
                props.Add("JpegYCrCbSubsampling", (byte)ctx.Settings.JpegSubsampleMode);
            }

            if (ctx.Settings.SaveFormat == FileFormat.Tiff)
            {
                props.Add("TiffCompressionMethod", (byte)WICTiffCompressionOption.WICTiffCompressionNone);
            }

            if (ctx.Settings.SaveFormat == FileFormat.Bmp && ctx.Source.Format.AlphaRepresentation != PixelAlphaRepresentation.None)
            {
                props.Add("EnableV5Header32bppBGRA", true);
            }

            if (props.Count > 0)
            {
                bag.Write((uint)props.Count, props.Keys.Select(k => new PROPBAG2 {
                    pstrName = k
                }).ToArray(), props.Values.ToArray());
            }

            frame.Initialize(bag);
            frame.SetSize(ctx.Source.Width, ctx.Source.Height);
            frame.SetResolution(ctx.Settings.DpiX > 0d ? ctx.Settings.DpiX : ctx.DecoderFrame.DpiX, ctx.Settings.DpiY > 0d ? ctx.Settings.DpiY : ctx.DecoderFrame.DpiY);

            if (ctx.DecoderFrame.Metadata?.Count > 0 && frame.TryGetMetadataQueryWriter(out var metawriter))
            {
                ctx.AddRef(metawriter);
                foreach (var nv in ctx.DecoderFrame.Metadata)
                {
                    metawriter.TrySetMetadataByName(nv.Key, nv.Value);
                }
            }

            Frame = frame;
        }
Esempio n. 22
0
        public static void AddPad(WicProcessingContext ctx)
        {
            if (ctx.Settings.InnerRect == ctx.Settings.OuterRect)
            {
                return;
            }

            AddExternalFormatConverter(ctx);

            ctx.Source = new PadTransformInternal(ctx.Source, ctx.Settings.MatteColor, ctx.Settings.InnerRect, ctx.Settings.OuterRect);
        }
Esempio n. 23
0
        public static void AddCropper(WicProcessingContext ctx)
        {
            if (ctx.Settings.Crop == new Rectangle(0, 0, (int)ctx.Source.Width, (int)ctx.Source.Height))
            {
                return;
            }

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

            cropper.Initialize(ctx.Source.WicSource, ctx.Settings.Crop.ToWicRect());
            ctx.Source = cropper.AsPixelSource(nameof(IWICBitmapClipper));
        }
Esempio n. 24
0
        public static void AddExifRotator(WicProcessingContext ctx)
        {
            if (ctx.DecoderFrame.ExifOrientation == Orientation.Normal)
            {
                return;
            }

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

            rotator.Initialize(ctx.Source.WicSource, ctx.DecoderFrame.ExifOrientation.ToWicTransformOptions());
            ctx.Source = rotator.AsPixelSource(nameof(IWICBitmapFlipRotator), !ctx.DecoderFrame.SupportsPlanarPipeline && !ctx.DecoderFrame.SupportsNativeTransform);
        }
Esempio n. 25
0
        public static void ProcessImage(Stream istm, Stream ostm, ProcessImageSettings s)
        {
            Contract.Requires <ArgumentNullException>(istm != null, nameof(istm));
            Contract.Requires <ArgumentNullException>(ostm != null, nameof(ostm));
            Contract.Requires <ArgumentException>(istm.CanSeek && istm.CanRead, "Input Stream must allow Seek and Read");
            Contract.Requires <ArgumentException>(ostm.CanSeek && ostm.CanWrite, "Output Stream must allow Seek and Write");
            Contract.Assume(istm.Position < istm.Length, "Input Stream Position is at the end.  Did you forget to Seek?");

            using (var ctx = new WicProcessingContext(s))
                using (var dec = new WicDecoder(istm, ctx))
                    processImage(dec, ctx, ostm);
        }
Esempio n. 26
0
        /// <summary>All-in-one processing of an image according to the specified <paramref name="settings" />.</summary>
        /// <param name="imgStream">A stream containing a supported input image container.</param>
        /// <param name="outStream">The stream to which the output image will be written.</param>
        /// <param name="settings">The settings for this processing operation.</param>
        /// <returns>A <see cref="ProcessImageResult" /> containing the settings used and basic instrumentation for the pipeline.</returns>
        public static ProcessImageResult ProcessImage(Stream imgStream, Stream outStream, ProcessImageSettings settings)
        {
            checkInStream(imgStream);
            checkOutStream(outStream);

            using (var ctx = new WicProcessingContext(settings))
            {
                var dec = new WicDecoder(imgStream, ctx);
                buildPipeline(ctx);
                return(executePipeline(ctx, outStream));
            }
        }
Esempio n. 27
0
        private static ProcessImageResult executePipeline(WicProcessingContext ctx, Stream ostm)
        {
            WicTransforms.AddIndexedColorConverter(ctx);

            var enc = new WicEncoder(ctx, ostm.AsIStream());

            enc.WriteSource(ctx);

            return(new ProcessImageResult {
                Settings = ctx.UsedSettings, Stats = ctx.Stats
            });
        }
Esempio n. 28
0
        public static void AddColorspaceConverter(WicProcessingContext ctx)
        {
            if (ctx.SourceColorContext == null)
            {
                return;
            }

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

            trans.Initialize(ctx.Source.WicSource, ctx.SourceColorContext, ctx.DestColorContext, ctx.Source.Format.FormatGuid);
            ctx.Source = trans.AsPixelSource(nameof(IWICColorTransform));
        }
Esempio n. 29
0
        public static void AddPixelFormatConverter(WicProcessingContext ctx)
        {
            var oldFormat = ctx.Source.Format;

            if (oldFormat.ColorRepresentation == PixelColorRepresentation.Cmyk)
            {
                //TODO WIC doesn't support proper CMYKA conversion with color profile
                if (oldFormat.AlphaRepresentation == PixelAlphaRepresentation.None)
                {
                    // WIC doesn't support 16bpc CMYK conversion with color profile
                    if (oldFormat.BitsPerPixel == 64)
                    {
                        ctx.Source = new FormatConversionTransform(ctx.Source, Consts.GUID_WICPixelFormat32bppCMYK);
                    }

                    var trans = ctx.AddRef(Wic.Factory.CreateColorTransform());
                    if (trans.TryInitialize(ctx.Source.WicSource, ctx.SourceColorContext, ctx.DestColorContext, Consts.GUID_WICPixelFormat24bppBGR))
                    {
                        ctx.Source = trans.AsPixelSource(nameof(IWICColorTransform));
                        oldFormat  = ctx.Source.Format;
                    }
                }

                ctx.SourceColorContext = null;
            }

            var newFormat = Consts.GUID_WICPixelFormat24bppBGR;

            if (oldFormat.AlphaRepresentation != PixelAlphaRepresentation.None)
            {
                newFormat = oldFormat.AlphaRepresentation == PixelAlphaRepresentation.Associated ? Consts.GUID_WICPixelFormat32bppPBGRA : Consts.GUID_WICPixelFormat32bppBGRA;
            }
            else if (oldFormat.ColorRepresentation == PixelColorRepresentation.Grey)
            {
                newFormat = Consts.GUID_WICPixelFormat8bppGray;
            }

            if (oldFormat.FormatGuid == newFormat)
            {
                return;
            }

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

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

            conv.Initialize(ctx.Source.WicSource, newFormat, WICBitmapDitherType.WICBitmapDitherTypeNone, null, 0.0, WICBitmapPaletteType.WICBitmapPaletteTypeCustom);
            ctx.Source = conv.AsPixelSource(nameof(IWICFormatConverter));
        }
Esempio n. 30
0
        /// <summary>Constructs a new processing pipeline from which pixels can be retrieved.</summary>
        /// <param name="imgSource">A custom pixel source to use as input.</param>
        /// <param name="settings">The settings for this processing operation.</param>
        /// <returns>A <see cref="ProcessingPipeline" /> containing the <see cref="IPixelSource" />, settings used, and basic instrumentation for the pipeline.</returns>
        public static ProcessingPipeline BuildPipeline(IPixelSource imgSource, ProcessImageSettings settings)
        {
            if (imgSource is null)
            {
                throw new ArgumentNullException(nameof(imgSource));
            }

            var ctx = new WicProcessingContext(settings);
            var dec = new WicDecoder(imgSource, ctx);

            buildPipeline(ctx, false);
            return(new ProcessingPipeline(ctx));
        }