public WicGammaCompress(WicTransform prev) : base(prev) { var fmt = Source.GetPixelFormat(); var conv = (WicGammaFormatConverter)null; if (fmt == Consts.GUID_WICPixelFormat64bppBGRA) { conv = new WicGammaFormatConverter(Source, Consts.GUID_WICPixelFormat32bppBGRA); } else if (fmt == Consts.GUID_WICPixelFormat48bppBGR) { conv = new WicGammaFormatConverter(Source, Consts.GUID_WICPixelFormat24bppBGR); } else if (fmt == Consts.GUID_WICPixelFormat16bppGray) { conv = new WicGammaFormatConverter(Source, Context.SupportsPlanar ? Consts.GUID_WICPixelFormat8bppY : Consts.GUID_WICPixelFormat8bppGray); } if (conv == null) { return; } Source = conv; Context.PixelFormat = Source.GetPixelFormat(); }
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()]; }
public WicGammaExpand(WicTransform prev) : base(prev) { if (Context.Settings.BlendingMode != GammaMode.Linear) { return; } var fmt = Source.GetPixelFormat(); var conv = (WicLinearFormatConverter)null; if (fmt == Consts.GUID_WICPixelFormat32bppBGRA) { conv = new WicLinearFormatConverter(Source, Consts.GUID_WICPixelFormat64bppBGRA); } else if (fmt == Consts.GUID_WICPixelFormat24bppBGR) { conv = new WicLinearFormatConverter(Source, Consts.GUID_WICPixelFormat48bppBGR); } else if (fmt == Consts.GUID_WICPixelFormat8bppGray || fmt == Consts.GUID_WICPixelFormat8bppY) { conv = new WicLinearFormatConverter(Source, Consts.GUID_WICPixelFormat16bppGray); } if (conv == null) { return; } Source = conv; Context.PixelFormat = Source.GetPixelFormat(); }
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()]; }
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(); }
public WicConvertFromCustomPixelFormat(WicTransform prev) : base(prev) { var ifmt = Source.GetPixelFormat(); var ofmt = ifmt; if (ifmt == Consts.GUID_WICPixelFormat32bppGrayFloat || 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.Bgr96BppFloat.FormatGuid || ifmt == PixelFormat.Bgr96BppLinearFloat.FormatGuid || ifmt == PixelFormat.Bgr48BppLinearUQ15.FormatGuid) { ofmt = Consts.GUID_WICPixelFormat24bppBGR; } else if (ifmt == PixelFormat.Pbgra128BppFloat.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; } Source = conv = new WicCustomPixelFormatConverter(Source, ofmt); Context.PixelFormat = PixelFormat.Cache[Source.GetPixelFormat()]; }
public WicMatteTransform(WicTransform prev) : base(prev) { if (Context.Settings.MatteColor.IsEmpty || (Context.PixelFormat != Consts.GUID_WICPixelFormat32bppBGRA && Context.PixelFormat != Consts.GUID_WICPixelFormat64bppBGRA)) { return; } var mat = new WicMatte(Source, Context.Settings.MatteColor); Source = mat; }
public void WriteSource(WicTransform prevY, WicTransform prevCbCr) { var oformat = Consts.GUID_WICPixelFormat24bppBGR; Frame.SetPixelFormat(ref oformat); PlanarFrame.WriteSource(new IWICBitmapSource[] { prevY.Source, prevCbCr.Source }, 2, null); Frame.Commit(); Encoder.Commit(); }
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 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 WicUnsharpMask(WicTransform prev) : base(prev) { var ss = Context.Settings.UnsharpMask; if (ss.Radius <= 0 || ss.Amount <= 0) { return; } var mapx = KernelMap.MakeBlurMap(Context.Width, ss.Radius); var mapy = KernelMap.MakeBlurMap(Context.Height, ss.Radius); Source = new WicUnsharpMask8bpc(Source, mapx, mapy, ss); }
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; }
public WicMatteTransform(WicTransform prev) : base(prev) { if (Context.PixelFormat == PixelFormat.Pbgra128BppFloat) { Source = conv = new WicCustomPixelFormatConverter(Source, Consts.GUID_WICPixelFormat32bppBGRA); Context.PixelFormat = PixelFormat.Cache[Source.GetPixelFormat()]; } if (Context.Settings.MatteColor.IsEmpty || Context.PixelFormat.ColorRepresentation != PixelColorRepresentation.Bgr || Context.PixelFormat.AlphaRepresentation == PixelAlphaRepresentation.None) { return; } Source = new WicMatte(Source, Context.Settings.MatteColor); }
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; }
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 WicUnsharpMask(WicTransform prev) : base(prev) { var ss = Context.Settings.UnsharpMask; if (ss.Radius <= 0d || ss.Amount <= 0) { return; } var fmt = PixelFormat.Cache[Source.GetPixelFormat()]; mapx = KernelMap <int> .MakeBlurMap(Context.Width, ss.Radius, 1u, fmt.AlphaRepresentation != PixelAlphaRepresentation.None); mapy = KernelMap <int> .MakeBlurMap(Context.Height, ss.Radius, 1u, fmt.AlphaRepresentation != PixelAlphaRepresentation.None); Source = source = new WicUnsharpMask <byte, int>(Source, mapx, mapy, ss); }
public static void ProcessImage(WicTransform prev, WicProcessingContext ctx, Stream ostm) { bool savePlanar = ctx.Settings.SaveFormat == FileFormat.Jpeg && ctx.SourceColorContext == null; using (var rot = new WicExifRotator(prev)) using (var pln = new WicPlanarCache(rot)) using (var ply = new WicPlanarSplitter(pln, WicPlane.Luma)) using (var lll = new WicConvertToCustomPixelFormat(ply)) using (var mmm = new WicHighQualityScaler(lll)) using (var ggg = new WicConvertFromCustomPixelFormat(mmm)) using (var sss = new WicUnsharpMask(ggg)) using (var enc = new WicEncoder(ostm.AsIStream(), ctx)) using (var plc = new WicPlanarSplitter(pln, WicPlane.Chroma)) { if (savePlanar) { var subsample = ctx.Settings.JpegSubsampleMode; if (subsample == ChromaSubsampleMode.Subsample420) { ctx.Settings.Height = (int)Math.Ceiling(ctx.Settings.Height / 2d); } if (subsample == ChromaSubsampleMode.Subsample420 || subsample == ChromaSubsampleMode.Subsample422) { ctx.Settings.Width = (int)Math.Ceiling(ctx.Settings.Width / 2d); } using (var fff = new WicConvertToCustomPixelFormat(plc)) using (var res = new WicHighQualityScaler(fff)) using (var bbb = new WicConvertFromCustomPixelFormat(res)) using (var pen = new WicPlanarEncoder(enc)) pen.WriteSource(sss, bbb); } else { using (var fff = new WicConvertToCustomPixelFormat(plc)) using (var res = new WicHighQualityScaler(fff)) using (var bbb = new WicConvertFromCustomPixelFormat(res)) using (var con = new WicPlanarConverter(sss, bbb)) using (var pal = new WicPaletizer(con)) enc.WriteSource(pal); } } }
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 WicHighQualityScaler(WicTransform prev) : base(prev) { uint width = (uint)Context.Settings.Width, height = (uint)Context.Settings.Height; var interpolatorx = width == Context.Width ? InterpolationSettings.NearestNeighbor : Context.Settings.Interpolation; var interpolatory = height == Context.Height ? InterpolationSettings.NearestNeighbor : Context.Settings.Interpolation; var mapx = KernelMap.MakeScaleMap(Context.Width, width, interpolatorx); var mapy = KernelMap.MakeScaleMap(Context.Height, height, interpolatory); if (Context.Settings.BlendingMode == GammaMode.Linear) { Source = new WicConvolution16bpc(Source, mapx, mapy); } else { Source = new WicConvolution8bpc(Source, mapx, mapy); } Source.GetSize(out Context.Width, out Context.Height); }
public WicHighQualityScaler(WicTransform prev) : base(prev) { uint width = (uint)Context.Settings.Width, height = (uint)Context.Settings.Height; var interpolatorx = width == Context.Width ? InterpolationSettings.NearestNeighbor : Context.Settings.Interpolation; var interpolatory = height == Context.Height ? InterpolationSettings.NearestNeighbor : Context.Settings.Interpolation; var fmt = PixelFormat.Cache[Source.GetPixelFormat()]; if (fmt.NumericRepresentation == PixelNumericRepresentation.Float) { var mx = KernelMap <float> .MakeScaleMap(Context.Width, width, fmt.ColorChannelCount, fmt.AlphaRepresentation != PixelAlphaRepresentation.None, true, interpolatorx); var my = KernelMap <float> .MakeScaleMap(Context.Height, height, fmt.ColorChannelCount, fmt.AlphaRepresentation != PixelAlphaRepresentation.None, true, interpolatory); source = new WicConvolution <float, float>(Source, mx, my); mapx = mx; mapy = my; } else { var mx = KernelMap <int> .MakeScaleMap(Context.Width, width, 1, fmt.AlphaRepresentation == PixelAlphaRepresentation.Unassociated, false, interpolatorx); var my = KernelMap <int> .MakeScaleMap(Context.Height, height, 1, fmt.AlphaRepresentation == PixelAlphaRepresentation.Unassociated, false, interpolatory); if (fmt.NumericRepresentation == PixelNumericRepresentation.Fixed) { source = new WicConvolution <ushort, int>(Source, mx, my); } else { source = new WicConvolution <byte, int>(Source, mx, my); } mapx = mx; mapy = my; } Source = source; Source.GetSize(out Context.Width, out 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); }
public WicPlanarCache(WicTransform prev) : base(prev) { if (!(prev.Source is IWICPlanarBitmapSourceTransform)) { throw new NotSupportedException("Transform chain doesn't support planar mode. Only JPEG Decoder, Rotator, Scaler, and ColorSpaceConverter are allowed"); } var trans = (IWICPlanarBitmapSourceTransform)prev.Source; double rat = Context.Settings.HybridScaleRatio.Clamp(1d, 8d); Context.Width = (uint)Math.Ceiling(Context.Width / rat); Context.Height = (uint)Math.Ceiling(Context.Height / rat); // Although generally the last scan has the least significant bit(s) of the luma plane and skipping it could be very beneficial performance-wise, there is no guarantee of scan order. Might be able to do something with more decoder support. //var prog = Frame as IWICProgressiveLevelControl; //if (prog != null) //{ // uint levels = prog.GetLevelCount(); // uint level = (uint)Math.Ceiling(levels / rat) + (Context.Settings.HybridMode == HybridScaleMode.FavorQuality || Context.Settings.HybridMode == HybridScaleMode.Off ? (uint)Math.Ceiling(levels / 8d) : 0u); // prog.SetCurrentLevel(Math.Min(level, levels - (Context.Settings.ScaleRatio >= 2d && levels > 7u ? 2u : 1u))); //} var fmts = new Guid[] { Consts.GUID_WICPixelFormat8bppY, Consts.GUID_WICPixelFormat16bppCbCr }; var desc = new WICBitmapPlaneDescription[2]; if (!trans.DoesSupportTransform(ref Context.Width, ref Context.Height, Context.TransformOptions, WICPlanarOptions.WICPlanarOptionsDefault, fmts, desc, 2)) { throw new NotSupportedException("Requested planar transform not supported"); } var crop = new WICRect { X = Context.Settings.Crop.X, Y = Context.Settings.Crop.Y, Width = Context.Settings.Crop.Width, Height = Context.Settings.Crop.Height }; cacheSource = new WicPlanarCacheSource(trans, desc[0], desc[1], crop, Context.TransformOptions, Context.Width, Context.Height, rat, Context.NeedsCache); SourceY = cacheSource.GetPlane(WicPlane.Luma); SourceCbCr = cacheSource.GetPlane(WicPlane.Chroma); }
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 WicPlanarCache(WicTransform prev) : base(prev) { Contract.Requires <NotSupportedException>(prev.Source is IWICPlanarBitmapSourceTransform, "Transform chain doesn't support planar mode. Only JPEG Decoder, Rotator, Scaler, and ColorSpaceConverter are allowed"); var trans = (IWICPlanarBitmapSourceTransform)prev.Source; double rat = Context.Settings.HybridScaleRatio.Clamp(1d, 8d); Context.Width = (uint)Math.Ceiling(Context.Width / rat); Context.Height = (uint)Math.Ceiling(Context.Height / rat); var prog = Frame as IWICProgressiveLevelControl; if (prog != null) // TODO needs work { uint levels = prog.GetLevelCount(); uint level = (uint)Math.Ceiling(levels / rat) + (Context.Settings.HybridMode == HybridScaleMode.FavorQuality || Context.Settings.HybridMode == HybridScaleMode.Off ? (uint)Math.Ceiling(levels / 8d) : 0u); prog.SetCurrentLevel(Math.Min(level, levels - (Context.Settings.ScaleRatio >= 2d && levels > 7u ? 2u : 1u))); } var fmts = new Guid[] { Consts.GUID_WICPixelFormat8bppY, Consts.GUID_WICPixelFormat16bppCbCr }; var desc = new WICBitmapPlaneDescription[2]; if (!trans.DoesSupportTransform(ref Context.Width, ref Context.Height, Context.TransformOptions, WICPlanarOptions.WICPlanarOptionsPreserveSubsampling, fmts, desc, 2)) { throw new NotSupportedException("Planar Transform not supported"); } var crop = new WICRect() { X = Context.Settings.Crop.X, Y = Context.Settings.Crop.Y, Width = Context.Settings.Crop.Width, Height = Context.Settings.Crop.Height }; var source = new WicPlanarCacheSource(trans, desc[0], desc[1], crop, Context.TransformOptions, Context.Width, Context.Height, rat); SourceY = source.GetPlane(WicPlane.Luma); SourceCbCr = source.GetPlane(WicPlane.Chroma); }
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; }
public WicTransform(WicTransform prev) { Context = prev.Context; Frame = prev.Frame; Source = prev.Source; }
public WicConvertToCustomPixelFormat(WicTransform prev) : base(prev) { var ifmt = Source.GetPixelFormat(); var ofmt = ifmt; bool linear = Context.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; } Source = conv = new WicCustomPixelFormatConverter(Source, ofmt); Context.PixelFormat = PixelFormat.Cache[Source.GetPixelFormat()]; }
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; }