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()]; }
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()]; }
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); }
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; }
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); }
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; }
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 WicDecoder(string fileName, WicProcessingContext ctx) { init(checkDecoder(() => Wic.CreateDecoderFromFilename(fileName, null, GenericAccessRights.GENERIC_READ, WICDecodeOptions.WICDecodeMetadataCacheOnDemand)), ctx); }
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; }