private static ProcessImageResult processImage(PipelineContext ctx, Stream ostm) { var frame = (WicImageFrame)ctx.ImageContainer.GetFrame(ctx.Settings.FrameIndex); ctx.AddFrameDisposer(); ctx.ImageFrame = frame; ctx.Source = frame.Source; MagicTransforms.AddGifFrameBuffer(ctx); ctx.FinalizeSettings(); WicTransforms.AddColorProfileReader(ctx); WicTransforms.AddNativeScaler(ctx); WicTransforms.AddExifFlipRotator(ctx); WicTransforms.AddCropper(ctx); WicTransforms.AddPixelFormatConverter(ctx); WicTransforms.AddHybridScaler(ctx); WicTransforms.AddScaler(ctx); WicTransforms.AddColorspaceConverter(ctx); MagicTransforms.AddMatte(ctx); MagicTransforms.AddPad(ctx); WicTransforms.AddIndexedColorConverter(ctx); using var enc = new WicImageEncoder(ctx.Settings.SaveFormat, ostm); using var frm = new WicImageEncoderFrame(ctx, enc); frm.WriteSource(ctx); enc.Commit(); return(new ProcessImageResult(ctx.UsedSettings, ctx.Stats)); }
private static ProcessImageResult processImage(WicDecoder dec, WicProcessingContext ctx, Stream ostm) { var frm = new WicFrameReader(ctx); WicTransforms.AddMetadataReader(ctx); ctx.FinalizeSettings(); WicTransforms.AddNativeScaler(ctx); WicTransforms.AddExifRotator(ctx); WicTransforms.AddConditionalCache(ctx); WicTransforms.AddCropper(ctx); WicTransforms.AddPixelFormatConverter(ctx); WicTransforms.AddScaler(ctx); WicTransforms.AddColorspaceConverter(ctx); MagicTransforms.AddMatte(ctx); MagicTransforms.AddPad(ctx); WicTransforms.AddIndexedColorConverter(ctx); var enc = new WicEncoder(ctx, ostm.AsIStream()); enc.WriteSource(ctx); return(new ProcessImageResult { Settings = ctx.UsedSettings, Stats = ctx.Stats }); }
internal ProcessingPipeline(WicProcessingContext ctx) { Context = ctx; source = new Lazy <IPixelSource>(() => { MagicTransforms.AddExternalFormatConverter(Context); WicTransforms.AddPixelFormatConverter(Context, false); return(Context.Source.AsIPixelSource()); }); }
#pragma warning restore 1573 internal static ProcessImageResult WriteOutput(PipelineContext ctx, Stream ostm) { MagicTransforms.AddExternalFormatConverter(ctx); WicTransforms.AddIndexedColorConverter(ctx); var enc = new WicEncoder(ctx, ostm.AsIStream()); enc.WriteSource(ctx); return(new ProcessImageResult(ctx.UsedSettings, ctx.Stats)); }
private static ProcessImageResult executePipeline(WicProcessingContext ctx, Stream ostm) { MagicTransforms.AddExternalFormatConverter(ctx); WicTransforms.AddIndexedColorConverter(ctx); var enc = new WicEncoder(ctx, ostm.AsIStream()); enc.WriteSource(ctx); return(new ProcessImageResult { Settings = ctx.UsedSettings, Stats = ctx.Stats }); }
/// <summary>Adds a new transform filter to the pipeline. Because a filter may alter dimensions or pixel format of an image, filters may not be added once the <see cref="PixelSource" /> has been retrieved.</summary> /// <param name="transform">The <see cref="IPixelTransform" /> that implements the filter.</param> public void AddTransform(IPixelTransform transform) { if (source.IsValueCreated) { throw new NotSupportedException("A Transform cannot be added once the Pipeline Source is materialized"); } if (transform is IPixelTransformInternal tint) { tint.Init(Context); return; } MagicTransforms.AddExternalFormatConverter(Context); transform.Init(Context.Source.AsIPixelSource()); Context.Source = transform.AsPixelSource(); }
private static void buildPipeline(WicProcessingContext ctx, bool outputPlanar = true) { var frm = new WicFrameReader(ctx, EnablePlanarPipeline); WicTransforms.AddMetadataReader(ctx); ctx.FinalizeSettings(); ctx.Settings.UnsharpMask = ctx.UsedSettings.UnsharpMask; ctx.Settings.JpegQuality = ctx.UsedSettings.JpegQuality; ctx.Settings.JpegSubsampleMode = ctx.UsedSettings.JpegSubsampleMode; if (ctx.DecoderFrame.SupportsPlanarPipeline) { bool savePlanar = outputPlanar && ctx.Settings.SaveFormat == FileFormat.Jpeg && ctx.Settings.InnerRect == ctx.Settings.OuterRect && ctx.SourceColorContext is null; WicTransforms.AddExifRotator(ctx); WicTransforms.AddPlanarCache(ctx); MagicTransforms.AddHighQualityScaler(ctx); MagicTransforms.AddUnsharpMask(ctx); MagicTransforms.AddExternalFormatConverter(ctx); ctx.SwitchPlanarSource(WicPlane.Chroma); if (savePlanar) { var subsample = ctx.Settings.JpegSubsampleMode; if (subsample == ChromaSubsampleMode.Subsample420) { ctx.Settings.InnerRect.Height = (int)Math.Ceiling(ctx.Settings.InnerRect.Height / 2d); } if (subsample == ChromaSubsampleMode.Subsample420 || subsample == ChromaSubsampleMode.Subsample422) { ctx.Settings.InnerRect.Width = (int)Math.Ceiling(ctx.Settings.InnerRect.Width / 2d); } } MagicTransforms.AddHighQualityScaler(ctx); MagicTransforms.AddExternalFormatConverter(ctx); ctx.SwitchPlanarSource(WicPlane.Luma); if (!savePlanar) { WicTransforms.AddPlanarConverter(ctx); MagicTransforms.AddColorspaceConverter(ctx); MagicTransforms.AddPad(ctx); } } else { WicTransforms.AddNativeScaler(ctx); WicTransforms.AddExifRotator(ctx); WicTransforms.AddConditionalCache(ctx); WicTransforms.AddCropper(ctx); MagicTransforms.AddHighQualityScaler(ctx, true); WicTransforms.AddPixelFormatConverter(ctx); WicTransforms.AddScaler(ctx, true); MagicTransforms.AddHighQualityScaler(ctx); MagicTransforms.AddColorspaceConverter(ctx); MagicTransforms.AddMatte(ctx); MagicTransforms.AddUnsharpMask(ctx); MagicTransforms.AddPad(ctx); } }
unsafe public void WriteAnimatedGif(PipelineContext ctx) { var cnt = ctx.ImageContainer as WicGifContainer ?? throw new NotSupportedException("Source must be a GIF"); using (var decmeta = ComHandle.Wrap(cnt.WicDecoder.GetMetadataQueryReader())) using (var encmeta = ComHandle.Wrap(WicEncoder.GetMetadataQueryWriter())) { if (decmeta.ComObject.TryGetMetadataByName(Wic.Metadata.Gif.AppExtension, out var appext)) { encmeta.ComObject.SetMetadataByName(Wic.Metadata.Gif.AppExtension, appext); } if (decmeta.ComObject.TryGetMetadataByName(Wic.Metadata.Gif.AppExtensionData, out var appdata)) { encmeta.ComObject.SetMetadataByName(Wic.Metadata.Gif.AppExtensionData, appdata); } if (decmeta.ComObject.TryGetMetadataByName(Wic.Metadata.Gif.PixelAspectRatio, out var aspect)) { encmeta.ComObject.SetMetadataByName(Wic.Metadata.Gif.PixelAspectRatio, aspect); } } using var buffer = new FrameBufferSource(ctx.Source.Width, ctx.Source.Height, ctx.Source.Format); var bspan = buffer.Span; var lastSource = ctx.Source; var wicBuffer = buffer.AsIWICBitmapSource(); var anictx = cnt.AnimationContext ??= new GifAnimationContext(); for (int i = 0; i < ctx.ImageContainer.FrameCount; i++) { if (i > 0) { ctx.Settings.FrameIndex = i; ctx.ImageFrame.Dispose(); ctx.ImageFrame = ctx.ImageContainer.GetFrame(ctx.Settings.FrameIndex); if (ctx.ImageFrame is WicImageFrame wicFrame) { ctx.Source = wicFrame.WicSource.AsPixelSource(nameof(IWICBitmapFrameDecode), true); } else { ctx.Source = ctx.ImageFrame.PixelSource.AsPixelSource(); } MagicTransforms.AddGifFrameBuffer(ctx, false); if (lastSource is ChainedPixelSource chain) { chain.ReInit(ctx.Source); ctx.Source = chain; } } fixed(byte *pbuff = bspan) { ctx.Source.CopyPixels(ctx.Source.Area, buffer.Stride, bspan.Length, (IntPtr)pbuff); var curFormat = ctx.Source.Format; var newFormat = PixelFormat.Indexed8Bpp; bool alpha = curFormat.AlphaRepresentation != PixelAlphaRepresentation.None; using var pal = ComHandle.Wrap(Wic.Factory.CreatePalette()); pal.ComObject.InitializeFromBitmap(wicBuffer, 256u, alpha); ctx.WicContext.DestPalette = pal.ComObject; using var conv = ComHandle.Wrap(Wic.Factory.CreateFormatConverter()); conv.ComObject.Initialize(wicBuffer, newFormat.FormatGuid, WICBitmapDitherType.WICBitmapDitherTypeErrorDiffusion, pal.ComObject, 10.0, WICBitmapPaletteType.WICBitmapPaletteTypeCustom); ctx.Source = conv.ComObject.AsPixelSource($"{nameof(IWICFormatConverter)}: {curFormat.Name}->{newFormat.Name}", false); using var frm = new WicImageEncoderFrame(ctx, this); var srcmeta = ((WicImageFrame)ctx.ImageFrame).WicMetadataReader !; using (var frmmeta = ComHandle.Wrap(frm.WicEncoderFrame.GetMetadataQueryWriter())) { var disp = srcmeta.TryGetMetadataByName(Wic.Metadata.Gif.FrameDisposal, out var fdisp) && (byte)fdisp.Value ! == (byte)GifDisposalMethod.RestoreBackground ? GifDisposalMethod.RestoreBackground : GifDisposalMethod.Undefined; frmmeta.ComObject.SetMetadataByName(Wic.Metadata.Gif.FrameDisposal, new PropVariant((byte)disp)); if (srcmeta.TryGetMetadataByName(Wic.Metadata.Gif.FrameDelay, out var delay)) { frmmeta.ComObject.SetMetadataByName(Wic.Metadata.Gif.FrameDelay, delay); } if (alpha) { frmmeta.ComObject.SetMetadataByName(Wic.Metadata.Gif.TransparencyFlag, new PropVariant(true)); frmmeta.ComObject.SetMetadataByName(Wic.Metadata.Gif.TransparentColorIndex, new PropVariant((byte)(pal.ComObject.GetColorCount() - 1))); } } frm.WriteSource(ctx); } } }
private static void buildPipeline(PipelineContext ctx, bool outputPlanar = true) { ctx.ImageFrame = ctx.ImageContainer.GetFrame(ctx.Settings.FrameIndex); bool processPlanar = false; var wicFrame = ctx.ImageFrame as WicImageFrame; if (wicFrame != null) { processPlanar = EnablePlanarPipeline && wicFrame.SupportsPlanarProcessing && ctx.Settings.Interpolation.WeightingFunction.Support >= 0.5; bool profilingPassThrough = processPlanar || (wicFrame.SupportsNativeScale && ctx.Settings.HybridScaleRatio > 1); ctx.Source = wicFrame.WicSource.AsPixelSource(nameof(IWICBitmapFrameDecode), !profilingPassThrough); } else if (ctx.ImageFrame is IYccImageFrame planarFrame) { processPlanar = true; outputPlanar = outputPlanar && planarFrame.IsFullRange && planarFrame.RgbYccMatrix.IsRouglyEqualTo(YccMatrix.Rec601); ctx.PlanarContext = new PipelineContext.PlanarPipelineContext(planarFrame.PixelSource.AsPixelSource(), planarFrame.PixelSourceCb.AsPixelSource(), planarFrame.PixelSourceCr.AsPixelSource()); ctx.Source = ctx.PlanarContext.SourceY; } MagicTransforms.AddColorProfileReader(ctx); ctx.FinalizeSettings(); ctx.Settings.UnsharpMask = ctx.UsedSettings.UnsharpMask; ctx.Settings.JpegQuality = ctx.UsedSettings.JpegQuality; ctx.Settings.JpegSubsampleMode = ctx.UsedSettings.JpegSubsampleMode; var subsample = ctx.Settings.JpegSubsampleMode; if (processPlanar) { if (wicFrame != null && !ctx.Settings.AutoCrop && ctx.Settings.HybridScaleRatio == 1) { var orCrop = PixelArea.FromGdiRect(ctx.Settings.Crop).DeOrient(ctx.Orientation, ctx.Source.Width, ctx.Source.Height); if (wicFrame.ChromaSubsampling.IsSubsampledX() && ((orCrop.X & 1) != 0 || (orCrop.Width & 1) != 0)) { processPlanar = false; } if (wicFrame.ChromaSubsampling.IsSubsampledY() && ((orCrop.Y & 1) != 0 || (orCrop.Height & 1) != 0)) { processPlanar = false; } } if (ctx.Settings.SaveFormat == FileFormat.Jpeg && ctx.Orientation.SwapsDimensions()) { if (subsample.IsSubsampledX() && (ctx.Settings.InnerSize.Width & 1) != 0) { outputPlanar = false; } if (subsample.IsSubsampledY() && (ctx.Settings.InnerSize.Height & 1) != 0) { outputPlanar = false; } } } if (processPlanar) { bool savePlanar = outputPlanar && ctx.Settings.SaveFormat == FileFormat.Jpeg && ctx.Settings.OuterSize == ctx.Settings.InnerSize && ctx.DestColorProfile == ctx.SourceColorProfile; if (wicFrame != null) { WicTransforms.AddPlanarCache(ctx); } MagicTransforms.AddPlanarCropper(ctx); MagicTransforms.AddPlanarHybridScaler(ctx); MagicTransforms.AddPlanarHighQualityScaler(ctx, savePlanar ? subsample : ChromaSubsampleMode.Subsample444); MagicTransforms.AddUnsharpMask(ctx); if (savePlanar) { MagicTransforms.AddPlanarExifFlipRotator(ctx); MagicTransforms.AddPlanarExternalFormatConverter(ctx); } else { MagicTransforms.AddPlanarConverter(ctx); MagicTransforms.AddColorspaceConverter(ctx); MagicTransforms.AddExifFlipRotator(ctx); MagicTransforms.AddPad(ctx); } } else { WicTransforms.AddNativeScaler(ctx); MagicTransforms.AddCropper(ctx); MagicTransforms.AddHybridScaler(ctx); WicTransforms.AddPixelFormatConverter(ctx); MagicTransforms.AddHybridScaler(ctx); MagicTransforms.AddHighQualityScaler(ctx); MagicTransforms.AddColorspaceConverter(ctx); MagicTransforms.AddMatte(ctx); MagicTransforms.AddUnsharpMask(ctx); MagicTransforms.AddExifFlipRotator(ctx); MagicTransforms.AddPad(ctx); } }