/// <summary> /// Adds padding to a bitmap, optionally cropping it at the same time. /// </summary> /// <param name="s"></param> /// <param name="left"></param> /// <param name="top"></param> /// <param name="right"></param> /// <param name="bottom"></param> /// <param name="bgcolor"></param> /// <param name="crop"></param> public WicBitmapPadder(IWICBitmapSource s, int left, int top, int right, int bottom, byte[] bgcolor, WICRect crop) { this.s = s; this.left = left; this.right = right; this.bottom = bottom; this.top = top; this.bgcolor = bgcolor; this.crop = crop; Guid pf; s.GetPixelFormat(out pf); if (bgcolor.Length != ConversionUtils.BytesPerPixel(pf)) throw new ArgumentException("bgcolor length must match the format bytes per pixel"); }
public static SlimDX.Direct2D.Bitmap CreateBitmapFromWicBitmap(IWICBitmapSource source, BitmapProperties bitmapProperties, RenderTarget renderTarget) { var pBitmap = IntPtr.Zero; SlimDX.Direct2D.Bitmap bmp = null; var pRenderTarget = Marshal.GetObjectForIUnknown(renderTarget.ComPointer) as ID2D1RenderTarget; int hr = pRenderTarget.CreateBitmapFromWicBitmap(source, ref bitmapProperties, out pBitmap); if (hr != 0) goto cleanup; bmp = SlimDX.Direct2D.Bitmap.FromPointer(pBitmap); cleanup: Marshal.Release(pBitmap); Marshal.ReleaseComObject(pRenderTarget); return bmp; }
public extern IWICBitmap CreateBitmapFromSourceRect([In, MarshalAs(UnmanagedType.Interface)] IWICBitmapSource pIBitmapSource, [In] uint X, [In] uint Y, [In] uint Width, [In] uint Height);
public static bool TryGetPreview(this IWICBitmapDecoder dec, out IWICBitmapSource pvw) { int hr = ProxyFunctions.GetPreview(dec, out pvw); return(hr >= 0); }
public void GetThumbnail(out IWICBitmapSource ppIThumbnail) { Log.Trace("GetThumbnail called"); var guid = Guid.Empty; var pPreviewDecoder = RW2BitmapDecoder.GetImagingFactory().CreateDecoderFromStream( new StreamComWrapper(new MemoryStream(exif.Thumbnail)), ref guid, WICDecodeOptions.WICDecodeMetadataCacheOnDemand); IWICBitmapFrameDecode pPreviewFrame; pPreviewDecoder.GetFrame(0, out pPreviewFrame); ppIThumbnail = pPreviewFrame; Log.Trace("GetThumbnail finished"); }
public static IComObject <IWICBitmap> CreateBitmapFromSource(this IWICImagingFactory factory, IWICBitmapSource source, WICBitmapCreateCacheOption option = WICBitmapCreateCacheOption.WICBitmapNoCache) { if (factory == null) { throw new ArgumentNullException(nameof(factory)); } if (source == null) { throw new ArgumentNullException(nameof(source)); } factory.CreateBitmapFromSource(source, option, out var value).ThrowOnError(); return(new ComObject <IWICBitmap>(value)); }
internal static extern int CopyPixels(IWICBitmapSource bitmap, IntPtr rect, uint cbStride, uint cbBufferSize, IntPtr pvPixels);
public ArgbImage(IWICImagingFactory factory, IWICBitmapSource bitmapSource) : base(factory, bitmapSource, ArgbImage.WicImageFormat) { }
public static uint GetStride(IWICBitmapSource source) { uint w, h; source.GetSize(out w, out h); Guid format; source.GetPixelFormat(out format); uint dword = 4; uint stride = (uint)BytesPerPixel(format) * w; //1bpp, 2bpp, 4 bpp all take one byte? Not sure how to handle those. stride = ((stride + dword - 1) / dword) * dword; //Round up to multiple of 4. return stride; }
public WicLinearFormatConverter(IWICBitmapSource source, Guid dstFormat) : base(source, dstFormat) { }
public WicFormatConverterBase(IWICBitmapSource source, Guid dstFormat) : base(source) { OutFormat = dstFormat; LineBuff = new byte[Stride]; HasAlpha = Format == Consts.GUID_WICPixelFormat64bppBGRA || Format == Consts.GUID_WICPixelFormat32bppBGRA; }
public static (int Left, int Top, int Width, int Height, bool Alpha, bool FullScreen, GifDisposalMethod Disposal) GetGifFrameInfo(WicGifContainer cont, IWICBitmapSource frame, IWICMetadataQueryReader meta) { frame.GetSize(out uint width, out uint height); int left = 0, top = 0; var disp = ((GifDisposalMethod)meta.GetValueOrDefault <byte>(Wic.Metadata.Gif.FrameDisposal)).Clamp(); bool trans = meta.GetValueOrDefault <bool>(Wic.Metadata.Gif.TransparencyFlag); bool full = width == cont.ScreenWidth && height == cont.ScreenHeight; if (!full) { left = meta.GetValueOrDefault <ushort>(Wic.Metadata.Gif.FrameLeft); top = meta.GetValueOrDefault <ushort>(Wic.Metadata.Gif.FrameTop); } return(left, top, (int)width, (int)height, trans, full, disp); }
public void EncodeToStream(IWICComponentFactory factory, IWICBitmapSource data, Size imageSize, IStream outputStream) { //A list of COM objects to destroy List <object> com = new List <object>(); try { //Find the GUID of the destination format Guid guidEncoder = GetOutputFormatWicGuid(); //Find out the data's pixel format Guid pFormat = Guid.Empty; data.GetPixelFormat(out pFormat); //Create the encoder var encoder = factory.CreateEncoder(guidEncoder, null); com.Add(encoder); //And initialize it encoder.Initialize(outputStream, WICBitmapEncoderCacheOption.WICBitmapEncoderNoCache); // Create the output frame and property bag IWICBitmapFrameEncode outputFrame; var propertyBagArray = new IPropertyBag2[1]; encoder.CreateNewFrame(out outputFrame, propertyBagArray); //An array is used instead of an out parameter... I have no idea why com.Add(outputFrame); //The property bag is a COM object... var propBag = propertyBagArray[0]; com.Add(propBag); //Adjust encoder settings if it's a jpegs if (guidEncoder.Equals(Consts.GUID_ContainerFormatJpeg)) { //Jpeg //ImageQuality 0..1 //"JpegYCrCbSubsampling" WICJpegYCrCbSubsamplingOption. //Configure encoder settings (see http://msdn.microsoft.com/en-us/library/windows/desktop/ee719871(v=vs.85).aspx#encoderoptions) var qualityOption = new PROPBAG2[1]; qualityOption[0].pstrName = "ImageQuality"; propBag.Write(1, qualityOption, new object[] { ((float)Math.Max(0, Math.Min(100, Quality))) / 100 }); WICJpegYCrCbSubsamplingOption subsampling = WICJpegYCrCbSubsamplingOption.WICJpegYCrCbSubsamplingDefault; //411 NOT SUPPPORTED BY WIC - only by freeimage if ("420".Equals(Subsampling)) { subsampling = WICJpegYCrCbSubsamplingOption.WICJpegYCrCbSubsampling420; } if ("422".Equals(Subsampling)) { subsampling = WICJpegYCrCbSubsamplingOption.WICJpegYCrCbSubsampling422; } if ("444".Equals(Subsampling)) { subsampling = WICJpegYCrCbSubsamplingOption.WICJpegYCrCbSubsampling444; } if (subsampling != WICJpegYCrCbSubsamplingOption.WICJpegYCrCbSubsamplingDefault) { var samplingOption = new PROPBAG2[1]; samplingOption[0].pstrName = "JpegYCrCbSubsampling"; samplingOption[0].vt = VarEnum.VT_UI1; propBag.Write(1, samplingOption, new object[] { (byte)subsampling }); } } //PNG interlace if (guidEncoder.Equals(Consts.GUID_ContainerFormatPng)) { var interlaceOption = new PROPBAG2[1]; interlaceOption[0].pstrName = "InterlaceOption"; propBag.Write(1, interlaceOption, new object[] { Interlace ?? false }); } //Apply the property bag outputFrame.Initialize(propBag); //Convert the bitmap to the correct pixel format for encoding. //Jpeg: encodes as GUID_WICPixelFormat24bppBGR or GUID_WICPixelFormat8bppGray. //If the original pixel format has an alpha chanel, we need to specify a matte color. //UPDATE - IWICFormatConverter doesn't let you specify a matte color. Disabling code if (false && guidEncoder.Equals(Consts.GUID_ContainerFormatJpeg)) { ConversionUtils.HasAlphaAbility(pFormat); var conv = factory.CreateFormatConverter(); com.Add(conv); if (conv.CanConvert(pFormat, Consts.GUID_WICPixelFormat24bppBGR)) { /*dither, pIPalette, alphaThresholdPercent, and paletteTranslate are used to mitigate color loss when * converting to a reduced bit-depth format. For conversions that do not need these settings, the * following parameters values should be used: dither set to WICBitmapDitherTypeNone, pIPalette set to NULL, * alphaThresholdPercent set to 0.0f, and paletteTranslate set to WICBitmapPaletteTypeCustom.*/ conv.Initialize(data, Consts.GUID_WICPixelFormat24bppBGR, WICBitmapDitherType.WICBitmapDitherTypeNone, null, 0.0f, WICBitmapPaletteType.WICBitmapPaletteTypeCustom); data = conv; //Oops, we didn't do anything - there's no way to specify a matte color! } } //GIF encodes as GUID_WICPixelFormat8bppIndexed //If the current format is > 8bpp, quantization may be required, and we may need to manually build the palette with Median Cut. //PNG encodeds as EVERYTHING! Way too many formats supported. // If the user is specifying a colors setting, we need to // convert to GUID_WICPixelFormat8bppIndexed, GUID_WICPixelFormat4bppIndexed, GUID_WICPixelFormat2bppIndexed, or GUID_WICPixelFormat1bppIndexed if ((guidEncoder.Equals(Consts.GUID_ContainerFormatPng) && this.Colors != -1) || (guidEncoder.Equals(Consts.GUID_ContainerFormatGif))) { Guid target = Consts.GUID_WICPixelFormat8bppIndexed; int colors = this.Colors; if (colors > 0 && guidEncoder.Equals(Consts.GUID_ContainerFormatPng)) { if (colors <= 2) { target = Consts.GUID_WICPixelFormat1bppIndexed; } if (colors <= 4) { target = Consts.GUID_WICPixelFormat2bppIndexed; } if (colors <= 32) { target = Consts.GUID_WICPixelFormat4bppIndexed; } } if (colors < 0) { colors = 256; } if (colors < 2) { colors = 2; } if (colors > 256) { colors = 256; } var conv = factory.CreateFormatConverter(); com.Add(conv); if (conv.CanConvert(pFormat, target)) { var palette = factory.CreatePalette(); com.Add(palette); palette.InitializeFromBitmap(data, (uint)colors, true); /*dither, pIPalette, alphaThresholdPercent, and paletteTranslate are used to mitigate color loss when * converting to a reduced bit-depth format. For conversions that do not need these settings, the * following parameters values should be used: dither set to WICBitmapDitherTypeNone, pIPalette set to NULL, * alphaThresholdPercent set to 0.0f, and paletteTranslate set to WICBitmapPaletteTypeCustom.*/ conv.Initialize(data, target, this.Dither ? WICBitmapDitherType.WICBitmapDitherTypeErrorDiffusion : WICBitmapDitherType.WICBitmapDitherTypeNone, palette, 50.0f, WICBitmapPaletteType.WICBitmapPaletteTypeCustom); data = conv; } } //Get size uint fw, fh; data.GetSize(out fw, out fh); //Set destination frame size outputFrame.SetSize(fw, fh); // Write the data to the output frame outputFrame.WriteSource(data, null); outputFrame.Commit(); encoder.Commit(); } finally { //Manually cleanup all the com reference counts, aggressively while (com.Count > 0) { Marshal.ReleaseComObject(com[com.Count - 1]); //In reverse order, so no item is ever deleted out from under another. com.RemoveAt(com.Count - 1); } } }
public static IComObject <T> CreateBitmapFromWicBitmap <T>(this ID2D1DeviceContext context, IWICBitmapSource source, D2D1_BITMAP_PROPERTIES1?properties = null) where T : ID2D1Bitmap1 { if (context == null) { throw new ArgumentNullException(nameof(context)); } if (source == null) { throw new ArgumentNullException(nameof(source)); } using (var mem = properties.StructureToMemory()) { context.CreateBitmapFromWicBitmap(source, mem.Pointer, out ID2D1Bitmap1 bmp).ThrowOnError(); return(new ComObject <T>((T)bmp)); } }
public void GetThumbnail(out IWICBitmapSource ppIThumbnail) { Log.Trace("GetThumbnail called"); try { var guid = Guid.Empty; lock (this) { var pPreviewDecoder = GetImagingFactory().CreateDecoderFromStream( new StreamComWrapper(new MemoryStream(exif.Thumbnail)), ref guid, WICDecodeOptions.WICDecodeMetadataCacheOnDemand); IWICBitmapFrameDecode pPreviewFrame; pPreviewDecoder.GetFrame(0, out pPreviewFrame); ppIThumbnail = pPreviewFrame; } Log.Trace("GetThumbnail finished"); } catch (Exception e) { Log.Error("GetThumbnail failed: " + e); throw; } }
public void GetPreview(out IWICBitmapSource ppIBitmapSource) { Log.Trace("GetPreview called"); GetThumbnail(out ppIBitmapSource); }
public WicConvolution(IWICBitmapSource source, KernelMap <TWeight> mapx, KernelMap <TWeight> mapy, bool bufferSource = false) : base(source) { if (Format.FormatGuid == Consts.GUID_WICPixelFormat32bppPBGRA) { Processor = new Convolver4ChanByte(); } else if (Format.FormatGuid == Consts.GUID_WICPixelFormat32bppBGRA) { Processor = new ConvolverBgraByte(); } else if (Format.FormatGuid == Consts.GUID_WICPixelFormat24bppBGR) { Processor = new ConvolverBgrByte(); } else if (Format.FormatGuid == Consts.GUID_WICPixelFormat16bppCbCr) { Processor = new Convolver2ChanByte(); } else if (Format.FormatGuid == Consts.GUID_WICPixelFormat8bppGray || Format.FormatGuid == Consts.GUID_WICPixelFormat8bppY) { Processor = new Convolver1ChanByte(); } else if (Format == PixelFormat.Pbgra64BppLinearUQ15) { Processor = new Convolver4ChanUQ15(); } else if (Format == PixelFormat.Bgra64BppLinearUQ15) { Processor = new ConvolverBgraUQ15(); } else if (Format == PixelFormat.Bgr48BppLinearUQ15) { Processor = new ConvolverBgrUQ15(); } else if (Format == PixelFormat.Grey16BppLinearUQ15 || Format == PixelFormat.Y16BppLinearUQ15) { Processor = new Convolver1ChanUQ15(); } else if (Format == PixelFormat.Pbgra128BppLinearFloat || Format == PixelFormat.Pbgra128BppFloat) { Processor = new Convolver4ChanFloat(); } else if (Format == PixelFormat.Bgr96BppLinearFloat || Format == PixelFormat.Bgr96BppFloat) { Processor = new Convolver3ChanFloat(); } else if (Format == PixelFormat.CbCr64BppFloat) { Processor = new Convolver2ChanFloat(); } else if (Format == PixelFormat.Grey32BppLinearFloat || Format.FormatGuid == Consts.GUID_WICPixelFormat32bppGrayFloat || Format == PixelFormat.Y32BppLinearFloat || Format == PixelFormat.Y32BppFloat) { Processor = new Convolver1ChanFloat(); } else { throw new NotSupportedException("Unsupported pixel format"); } BufferSource = bufferSource; OutWidth = (uint)mapx.OutPixels; OutHeight = (uint)mapy.OutPixels; SourceRect = new WICRect { Width = (int)Width, Height = 1 }; XMap = mapx; YMap = mapy; IntBpp = Bpp / Unsafe.SizeOf <TPixel>() * Unsafe.SizeOf <TWeight>(); IntStride = mapy.Samples * IntBpp; IntStartLine = -mapy.Samples; int lineBuffLen = (bufferSource ? mapy.Samples : 1) * (int)Stride; int intBuffLen = mapx.OutPixels * IntStride; LineBuff = new ArraySegment <byte>(ArrayPool <byte> .Shared.Rent(lineBuffLen), 0, lineBuffLen); IntBuff = new ArraySegment <byte>(ArrayPool <byte> .Shared.Rent(intBuffLen), 0, intBuffLen); }
public WicCustomPixelFormatConverter(IWICBitmapSource source, Guid dstFormat) : base(source) { InFormat = PixelFormat.Cache[source.GetPixelFormat()]; OutFormat = PixelFormat.Cache[dstFormat]; LineBuff = ArrayPool <byte> .Shared.Rent((int)Stride); }
public static WICSize GetSize(this IWICBitmapSource bitmapSource) { bitmapSource.GetSize(out int width, out int height); return(new WICSize(width, height)); }
public void EncodeToStream(IWICComponentFactory factory, IWICBitmapSource data, IStream outputStream) { //A list of COM objects to destroy List <object> com = new List <object>(); try { //Find the GUID of the destination format Guid guidEncoder = Consts.GUID_ContainerFormatJpeg; //Find out the data's pixel format Guid pFormat = Guid.Empty; data.GetPixelFormat(out pFormat); //Create the encoder var encoder = factory.CreateEncoder(guidEncoder, null); com.Add(encoder); //And initialize it encoder.Initialize(outputStream, WICBitmapEncoderCacheOption.WICBitmapEncoderNoCache); // Create the output frame and property bag IWICBitmapFrameEncode outputFrame; var propertyBagArray = new IPropertyBag2[1]; encoder.CreateNewFrame(out outputFrame, propertyBagArray); //An array is used instead of an out parameter... I have no idea why com.Add(outputFrame); //The property bag is a COM object... var propBag = propertyBagArray[0]; com.Add(propBag); //Adjust encoder settings if it's a jpegs if (guidEncoder.Equals(Consts.GUID_ContainerFormatJpeg)) { //Configure encoder settings (see http://msdn.microsoft.com/en-us/library/windows/desktop/ee719871(v=vs.85).aspx#encoderoptions) var qualityOption = new PROPBAG2[1]; qualityOption[0].pstrName = "ImageQuality"; qualityOption[0].vt = VarEnum.VT_R4; object qualityValue = ((float)90) / 100; propBag.Write(1, qualityOption, new object[] { qualityValue }); } //Apply the property bag outputFrame.Initialize(propBag); //Get size uint fw, fh; data.GetSize(out fw, out fh); //Set destination frame size outputFrame.SetSize(fw, fh); // Write the data to the output frame outputFrame.WriteSource(data, null); outputFrame.Commit(); encoder.Commit(); } finally { //Manually cleanup all the com reference counts, aggressively while (com.Count > 0) { Marshal.ReleaseComObject(com[com.Count - 1]); //In reverse order, so no item is ever deleted out from under another. com.RemoveAt(com.Count - 1); } } }
public WicTransform(IWICBitmapFrameDecode frm, IWICBitmapSource src, WicProcessingContext ctx) { Frame = frm; Source = src; Context = ctx; }
public WicUnsharpMask16bpc(IWICBitmapSource source, KernelMap mapx, KernelMap mapy, UnsharpMaskSettings ss) : base(source, mapx, mapy, true) { sharpenSettings = ss; blurBuff = new ushort[Stride]; }
public void EncodeToStream(IWICComponentFactory factory, IWICBitmapSource data, Size imageSize, IStream outputStream) { //A list of COM objects to destroy List<object> com = new List<object>(); try { //Find the GUID of the destination format Guid guidEncoder = GetOutputFormatWicGuid(); //Find out the data's pixel format Guid pFormat = Guid.Empty; data.GetPixelFormat(out pFormat); //Create the encoder var encoder = factory.CreateEncoder(guidEncoder, null); com.Add(encoder); //And initialize it encoder.Initialize(outputStream, WICBitmapEncoderCacheOption.WICBitmapEncoderNoCache); // Create the output frame and property bag IWICBitmapFrameEncode outputFrame; var propertyBagArray = new IPropertyBag2[1]; encoder.CreateNewFrame(out outputFrame, propertyBagArray); //An array is used instead of an out parameter... I have no idea why com.Add(outputFrame); //The property bag is a COM object... var propBag = propertyBagArray[0]; com.Add(propBag); //Adjust encoder settings if it's a jpegs if (guidEncoder.Equals(Consts.GUID_ContainerFormatJpeg)) { //Jpeg //ImageQuality 0..1 //"JpegYCrCbSubsampling" WICJpegYCrCbSubsamplingOption. //Configure encoder settings (see http://msdn.microsoft.com/en-us/library/windows/desktop/ee719871(v=vs.85).aspx#encoderoptions) var qualityOption = new PROPBAG2[1]; qualityOption[0].pstrName = "ImageQuality"; propBag.Write(1, qualityOption, new object[] { ((float)Math.Max(0,Math.Min(100,Quality))) / 100 }); WICJpegYCrCbSubsamplingOption subsampling = WICJpegYCrCbSubsamplingOption.WICJpegYCrCbSubsamplingDefault; //411 NOT SUPPPORTED BY WIC - only by freeimage if ("420".Equals(Subsampling)) subsampling = WICJpegYCrCbSubsamplingOption.WICJpegYCrCbSubsampling420; if ("422".Equals(Subsampling)) subsampling = WICJpegYCrCbSubsamplingOption.WICJpegYCrCbSubsampling422; if ("444".Equals(Subsampling)) subsampling = WICJpegYCrCbSubsamplingOption.WICJpegYCrCbSubsampling444; if (subsampling != WICJpegYCrCbSubsamplingOption.WICJpegYCrCbSubsamplingDefault) { var samplingOption = new PROPBAG2[1]; samplingOption[0].pstrName = "JpegYCrCbSubsampling"; samplingOption[0].vt = VarEnum.VT_UI1; propBag.Write(1, samplingOption, new object[] { (byte)subsampling }); } } //PNG interlace if (guidEncoder.Equals(Consts.GUID_ContainerFormatPng)) { var interlaceOption = new PROPBAG2[1]; interlaceOption[0].pstrName = "InterlaceOption"; propBag.Write(1, interlaceOption, new object[] { Interlace ?? false }); } //Apply the property bag outputFrame.Initialize(propBag); //Convert the bitmap to the correct pixel format for encoding. //Jpeg: encodes as GUID_WICPixelFormat24bppBGR or GUID_WICPixelFormat8bppGray. //If the original pixel format has an alpha chanel, we need to specify a matte color. //UPDATE - IWICFormatConverter doesn't let you specify a matte color. Disabling code if (false && guidEncoder.Equals(Consts.GUID_ContainerFormatJpeg)) { ConversionUtils.HasAlphaAbility(pFormat); var conv = factory.CreateFormatConverter(); com.Add(conv); if (conv.CanConvert(pFormat, Consts.GUID_WICPixelFormat24bppBGR)) { /*dither, pIPalette, alphaThresholdPercent, and paletteTranslate are used to mitigate color loss when * converting to a reduced bit-depth format. For conversions that do not need these settings, the * following parameters values should be used: dither set to WICBitmapDitherTypeNone, pIPalette set to NULL, * alphaThresholdPercent set to 0.0f, and paletteTranslate set to WICBitmapPaletteTypeCustom.*/ conv.Initialize(data, Consts.GUID_WICPixelFormat24bppBGR, WICBitmapDitherType.WICBitmapDitherTypeNone, null, 0.0f, WICBitmapPaletteType.WICBitmapPaletteTypeCustom); data = conv; //Oops, we didn't do anything - there's no way to specify a matte color! } } //GIF encodes as GUID_WICPixelFormat8bppIndexed //If the current format is > 8bpp, quantization may be required, and we may need to manually build the palette with Median Cut. //PNG encodeds as EVERYTHING! Way too many formats supported. // If the user is specifying a colors setting, we need to // convert to GUID_WICPixelFormat8bppIndexed, GUID_WICPixelFormat4bppIndexed, GUID_WICPixelFormat2bppIndexed, or GUID_WICPixelFormat1bppIndexed if ((guidEncoder.Equals(Consts.GUID_ContainerFormatPng) && this.Colors != -1) || (guidEncoder.Equals(Consts.GUID_ContainerFormatGif))) { Guid target = Consts.GUID_WICPixelFormat8bppIndexed; int colors = this.Colors; if (colors > 0 && guidEncoder.Equals(Consts.GUID_ContainerFormatPng)) { if (colors <= 2) target = Consts.GUID_WICPixelFormat1bppIndexed; if (colors <= 4) target = Consts.GUID_WICPixelFormat2bppIndexed; if (colors <= 32) target = Consts.GUID_WICPixelFormat4bppIndexed; } if (colors < 0) colors = 256; if (colors < 2) colors = 2; if (colors > 256) colors = 256; var conv = factory.CreateFormatConverter(); com.Add(conv); if (conv.CanConvert(pFormat, target)) { var palette = factory.CreatePalette(); com.Add(palette); palette.InitializeFromBitmap(data, (uint)colors, true); /*dither, pIPalette, alphaThresholdPercent, and paletteTranslate are used to mitigate color loss when * converting to a reduced bit-depth format. For conversions that do not need these settings, the * following parameters values should be used: dither set to WICBitmapDitherTypeNone, pIPalette set to NULL, * alphaThresholdPercent set to 0.0f, and paletteTranslate set to WICBitmapPaletteTypeCustom.*/ conv.Initialize(data, target, this.Dither ? WICBitmapDitherType.WICBitmapDitherTypeErrorDiffusion : WICBitmapDitherType.WICBitmapDitherTypeNone, palette, 50.0f, WICBitmapPaletteType.WICBitmapPaletteTypeCustom); data = conv; } } //Get size uint fw, fh; data.GetSize(out fw, out fh); //Set destination frame size outputFrame.SetSize(fw,fh); // Write the data to the output frame outputFrame.WriteSource(data, null); outputFrame.Commit(); encoder.Commit(); } finally { //Manually cleanup all the com reference counts, aggressively while (com.Count > 0) { Marshal.ReleaseComObject(com[com.Count - 1]); //In reverse order, so no item is ever deleted out from under another. com.RemoveAt(com.Count - 1); } } }
public static IComObject <IWICBitmap> CreateBitmapFromSourceRect(this IWICImagingFactory factory, IWICBitmapSource source, int x, int y, int width, int height) { if (factory == null) { throw new ArgumentNullException(nameof(factory)); } if (source == null) { throw new ArgumentNullException(nameof(source)); } factory.CreateBitmapFromSourceRect(source, x, y, width, height, out var value).ThrowOnError(); return(new ComObject <IWICBitmap>(value)); }
public static IWICBitmapSource GetOrientedImageSource(this IWICImagingFactory factory, IWICBitmapSource source, WICBitmapTransformOptions opt) { if (factory == null) { throw new ArgumentNullException("factory"); } if (opt == WICBitmapTransformOptions.WICBitmapTransformRotate0) { return(source); } IWICBitmap iwicbitmap = null; factory.CreateBitmapFromSource(source, WICBitmapCreateCacheOption.WICBitmapCacheOnDemand, out iwicbitmap); IWICBitmapFlipRotator iwicbitmapFlipRotator = null; factory.CreateBitmapFlipRotator(out iwicbitmapFlipRotator); iwicbitmapFlipRotator.Initialize(iwicbitmap, opt); IWICBitmapSource result = iwicbitmapFlipRotator; GraphicsInteropNativeMethods.SafeReleaseComObject(iwicbitmap); return(result); }
public static IWICBitmap CreateBitmapFromSourceRect(this IWICImagingFactory imagingFactory, IWICBitmapSource pIBitmapSource, WICRect rect) { return(imagingFactory.CreateBitmapFromSourceRect(pIBitmapSource, rect.X, rect.Y, rect.Width, rect.Height)); }
public static IWICBitmapSource ConvertFormat(this IWICImagingFactory factory, IWICBitmapSource source, Guid imageFormat) { if (factory == null) { throw new ArgumentNullException("factory"); } IWICFormatConverter iwicformatConverter; factory.CreateFormatConverter(out iwicformatConverter); iwicformatConverter.Initialize(source, ref imageFormat, WICBitmapDitherType.WICBitmapDitherTypeNone, null, 0.0, WICBitmapPaletteType.WICBitmapPaletteTypeMedianCut); return(iwicformatConverter); }
public extern IWICBitmap CreateBitmapFromSource([In, MarshalAs(UnmanagedType.Interface)] IWICBitmapSource pIBitmapSource, [In] WICBitmapCreateCacheOption option);
public static IWICBitmapSource GetScaledImageSource(this IWICImagingFactory factory, IWICBitmapSource source, float scale) { if (factory == null) { throw new ArgumentNullException("factory"); } if (source == null) { throw new ArgumentNullException("source"); } int num; int num2; source.GetSize(out num, out num2); IWICBitmapScaler iwicbitmapScaler; factory.CreateBitmapScaler(out iwicbitmapScaler); iwicbitmapScaler.Initialize(source, (int)((float)num / scale), (int)((float)num2 / scale), WICBitmapInterpolationMode.WICBitmapInterpolationModeFant); return(iwicbitmapScaler); }
public WicTransform(WicTransform prev) { Context = prev.Context; Frame = prev.Frame; Source = prev.Source; }
protected virtual RequestedAction Encode(IWICComponentFactory factory, IWICBitmapSource data, Size imageSize, ImageJob job) { WicEncoderPlugin encoder = new WicEncoderPlugin(job.Settings, job.SourcePathData); //Create the IStream/MemoryStream var outputStream = new MemoryIStream(); encoder.EncodeToStream(factory, data, imageSize, outputStream); object dest = job.Dest; // Try to save the bitmap if (dest is string) { //Make physical and resolve variable references all at the same time. job.FinalPath = job.ResolveTemplatedPath(job.Dest as string, delegate(string var) { if ("ext".Equals(var, StringComparison.OrdinalIgnoreCase)) return encoder.Extension; if ("width".Equals(var, StringComparison.OrdinalIgnoreCase)) return imageSize.Width.ToString(); if ("height".Equals(var, StringComparison.OrdinalIgnoreCase)) return imageSize.Height.ToString(); return null; }); //If requested, auto-create the parent directory(ies) if (job.CreateParentDirectory) { string dirName = Path.GetDirectoryName(job.FinalPath); if (!Directory.Exists(dirName)) Directory.CreateDirectory(dirName); } using (FileStream fs = new FileStream(job.FinalPath, FileMode.OpenOrCreate, FileAccess.Write, FileShare.None)) { outputStream.WriteTo(fs); } } else if (dest is Stream) { outputStream.WriteTo((Stream)dest); } else return RequestedAction.None; return RequestedAction.Cancel; }
public WicBitmapSource(IWICBitmapSource source, int width, int height) { this.source = source; Width = width; Height = height; }
private WicBitmapSource(IWICBitmapSource source, Guid format) { _source = source; Format = format; Stats(); }
public static Bitmap FromWic(IWICBitmapSource source) { Guid format; //Get the WIC pixel format source.GetPixelFormat(out format); //Get the matching GDI format PixelFormat gdiFormat = ConversionUtils.GetPixelFormat(format); //If it's not GDI-supported format, convert it to one. IWICComponentFactory factory = null; IWICFormatConverter converter = null; try { if (gdiFormat == PixelFormat.Undefined) { factory = (IWICComponentFactory)new WICImagingFactory(); converter = factory.CreateFormatConverter(); converter.Initialize(source, Consts.GUID_WICPixelFormat32bppBGRA, WICBitmapDitherType.WICBitmapDitherTypeNone, null, 0.9f, WICBitmapPaletteType.WICBitmapPaletteTypeCustom); gdiFormat = PixelFormat.Format32bppArgb; } IWICBitmapSource data = converter != null ? converter : source; //Get the dimensions of the WIC bitmap uint w, h; data.GetSize(out w, out h); Bitmap b = new Bitmap((int)w, (int)h, gdiFormat); BitmapData bd = b.LockBits(new Rectangle(0, 0, (int)w, (int)h), ImageLockMode.WriteOnly, b.PixelFormat); try { long result = CopyPixels(data, IntPtr.Zero, (uint)bd.Stride, (uint)(bd.Stride * bd.Height), bd.Scan0); if (result == 0x80070057) throw new ArgumentException(); if (result < 0) throw new Exception("HRESULT " + result); return b; } finally { b.UnlockBits(bd); } } finally { if (converter != null) Marshal.ReleaseComObject(converter); if (factory != null) Marshal.ReleaseComObject(factory); } }
/// <summary> /// Decodes the image in byte[] data, performs the image proccessing, and encodes it to job.Dest /// </summary> /// <param name="data">The buffer containing the encoded image file</param> /// <param name="lData">The number of bytes to read</param> /// <param name="job"></param> /// <param name="supportsTransparency"></param> /// <returns></returns> protected virtual RequestedAction BuildJobWic(byte[] data, long lData, ImageJob job, bool supportsTransparency) { ResizeSettings settings = job.Settings; ResizeSettings q = settings; string path = job.SourcePathData; //A list of COM objects to destroy List <object> com = new List <object>(); try { //Create the factory IWICComponentFactory factory = (IWICComponentFactory) new WICImagingFactory(); com.Add(factory); //Wrap the byte[] with a IWICStream instance var streamWrapper = factory.CreateStream(); streamWrapper.InitializeFromMemory(data, (uint)lData); com.Add(streamWrapper); var decoder = factory.CreateDecoderFromStream(streamWrapper, null, WICDecodeOptions.WICDecodeMetadataCacheOnLoad); com.Add(decoder); //Figure out which frame to work with int frameIndex = 0; if (!string.IsNullOrEmpty(q["page"]) && !int.TryParse(q["page"], NumberStyles.Number, NumberFormatInfo.InvariantInfo, out frameIndex)) { if (!string.IsNullOrEmpty(q["frame"]) && !int.TryParse(q["frame"], NumberStyles.Number, NumberFormatInfo.InvariantInfo, out frameIndex)) { frameIndex = 0; } } //So users can use 1-based numbers frameIndex--; if (frameIndex > 0) { int frameCount = (int)decoder.GetFrameCount(); //Don't let the user go past the end. if (frameIndex >= frameCount) { frameIndex = frameCount - 1; } } IWICBitmapFrameDecode frame = decoder.GetFrame((uint)Math.Max(0, frameIndex)); com.Add(frame); WICBitmapInterpolationMode interpolationMode = WICBitmapInterpolationMode.WICBitmapInterpolationModeFant; if ("nearest".Equals(settings["w.filter"], StringComparison.OrdinalIgnoreCase)) { interpolationMode = WICBitmapInterpolationMode.WICBitmapInterpolationModeNearestNeighbor; } if ("bicubic".Equals(settings["w.filter"], StringComparison.OrdinalIgnoreCase)) { interpolationMode = WICBitmapInterpolationMode.WICBitmapInterpolationModeCubic; } if ("linear".Equals(settings["w.filter"], StringComparison.OrdinalIgnoreCase)) { interpolationMode = WICBitmapInterpolationMode.WICBitmapInterpolationModeLinear; } if ("nearestneighbor".Equals(settings["w.filter"], StringComparison.OrdinalIgnoreCase)) { interpolationMode = WICBitmapInterpolationMode.WICBitmapInterpolationModeLinear; } //Find the original image size uint origWidth, origHeight; frame.GetSize(out origWidth, out origHeight); Size orig = new Size((int)origWidth, (int)origHeight); Guid pixelFormat; frame.GetPixelFormat(out pixelFormat); //Calculate the new size of the image and the canvas. ImageState state = new ImageState(settings, orig, true); c.CurrentImageBuilder.Process(state); Rectangle imageDest = PolygonMath.ToRectangle(PolygonMath.GetBoundingBox(state.layout["image"])); IWICBitmapSource imageData = frame; //Are we cropping? then daisy-chain a clipper if (state.copyRect.Left != 0 || state.copyRect.Top != 0 || state.copyRect.Width != state.originalSize.Width || state.copyRect.Height != state.originalSize.Height) { //Cropping is absurdly slow... 4x slower than resizing! //Cropping after resizing (unintuitively) is faster. if (imageDest.Width != state.originalSize.Width || imageDest.Height != state.originalSize.Height) { double sx = (double)imageDest.Width / (double)state.copyRect.Width; double sy = (double)imageDest.Height / (double)state.copyRect.Height; uint uncroppedDestWidth = (uint)Math.Round(sx * state.originalSize.Width); uint uncroppedDestHeight = (uint)Math.Round(sy * state.originalSize.Height); var scaler = factory.CreateBitmapScaler(); scaler.Initialize(imageData, uncroppedDestWidth, uncroppedDestHeight, interpolationMode); com.Add(scaler); //TODO: cropping is not consistent with GDI. var clipper = factory.CreateBitmapClipper(); clipper.Initialize(scaler, new WICRect { X = (int)Math.Floor((double)state.copyRect.X * sx), Y = (int)Math.Floor((double)state.copyRect.Y * sy), Width = imageDest.Width, Height = imageDest.Height }); com.Add(clipper); imageData = clipper; } else { var clipper = factory.CreateBitmapClipper(); clipper.Initialize(imageData, new WICRect { X = (int)state.copyRect.X, Y = (int)state.copyRect.Y, Width = (int)state.copyRect.Width, Height = (int)state.copyRect.Height }); com.Add(clipper); imageData = clipper; } //If we're scaling but not cropping. } else if (imageDest.Width != state.originalSize.Width || imageDest.Height != state.originalSize.Height) { var scaler = factory.CreateBitmapScaler(); scaler.Initialize(imageData, (uint)imageDest.Width, (uint)imageDest.Height, interpolationMode); com.Add(scaler); imageData = scaler; } //Are we padding? Then we have to do an intermediate write. if (state.destSize.Width != imageDest.Width || state.destSize.Height != imageDest.Height) { byte[] bgcolor = ConversionUtils.ConvertColor(job.Settings.BackgroundColor, pixelFormat); for (int i = 0; i < bgcolor.Length; i++) { bgcolor[i] = 255; //White } var padder = new WicBitmapPadder(imageData, imageDest.X, imageDest.Y, state.destSize.Width - (imageDest.X + imageDest.Width), state.destSize.Height - (imageDest.Y + imageDest.Height), bgcolor, null); imageData = padder; } //Now encode imageData and be done with it... return(Encode(factory, imageData, imageDest.Size, job)); } finally { //Manually cleanup all the com reference counts, aggressively while (com.Count > 0) { Marshal.ReleaseComObject(com[com.Count - 1]); //In reverse order, so no item is ever deleted out from under another. com.RemoveAt(com.Count - 1); } } }
public static void Initialize(this IWICBitmapScaler bitmapScaler, IWICBitmapSource pISource, Size size, WICBitmapInterpolationMode mode) { bitmapScaler.Initialize(pISource, size.Width, size.Height, mode); }
public static Resolution GetResolution(this IWICBitmapSource bitmapSource) { bitmapSource.GetResolution(out double dpiX, out double dpiY); return(new Resolution(dpiX, dpiY)); }
protected ImageBase(IWICImagingFactory factory, IWICBitmapSource bitmapSource, Guid wicImageFormat) : this() { this.LoadFromWic(factory, bitmapSource, wicImageFormat); }