public static ProcessImageResult ProcessImage(Stream imgStream, Stream outStream, ProcessImageSettings settings) { using var ctx = new PipelineContext(settings); ctx.ImageContainer = WicImageContainer.Create(imgStream, ctx.WicContext); return(processImage(ctx, outStream)); }
public static ProcessImageResult ProcessImage(ReadOnlySpan <byte> imgBuffer, Stream outStream, ProcessImageSettings settings) { using var ctx = new PipelineContext(settings); ctx.ImageContainer = WicImageContainer.Create(imgBuffer, ctx.WicContext); return(processImage(ctx, outStream)); }
/// <inheritdoc cref="BuildPipeline(string, ProcessImageSettings)" /> /// <param name="imgStream">A stream containing a supported input image container. The stream must allow Seek and Read.</param> public static ProcessingPipeline BuildPipeline(Stream imgStream, ProcessImageSettings settings) { checkInStream(imgStream); var ctx = new PipelineContext(settings); ctx.ImageContainer = WicImageContainer.Create(imgStream, ctx.WicContext); buildPipeline(ctx, false); return(new ProcessingPipeline(ctx)); }
/// <inheritdoc cref="ProcessImage(string, Stream, ProcessImageSettings)" /> /// <param name="imgStream">A stream containing a supported input image container. The stream must allow Seek and Read.</param> public static ProcessImageResult ProcessImage(Stream imgStream, Stream outStream, ProcessImageSettings settings) { checkInStream(imgStream); checkOutStream(outStream); using var ctx = new PipelineContext(settings); ctx.ImageContainer = WicImageContainer.Create(imgStream, ctx.WicContext); buildPipeline(ctx); return(WriteOutput(ctx, outStream)); }
public static WicImageContainer Load(Stream inStream) { var gch = GCHandle.Alloc(inStream); var sti = new IStreamImpl(gch); using var ccw = new SafeHandleReleaser(new SafeComCallable <IStreamImpl>(sti)); var dec = createDecoder((IStream *)ccw.Handle !.DangerousGetHandle()); return(WicImageContainer.Create(dec, ccw.Detach())); }
/// <summary>Constructs a new <see cref="ImageFileInfo" /> instance by reading the metadata from an image file contained in a <see cref="ReadOnlySpan{T}" />.</summary> /// <param name="imgBuffer">The buffer containing the image data.</param> /// <param name="lastModified">The last modified date of the image container.</param> public static ImageFileInfo Load(ReadOnlySpan <byte> imgBuffer, DateTime lastModified) { if (imgBuffer == default) { throw new ArgumentNullException(nameof(imgBuffer)); } using var ctx = new PipelineContext(new ProcessImageSettings()); ctx.ImageContainer = WicImageContainer.Create(imgBuffer, ctx.WicContext); return(fromWicImage(ctx, imgBuffer.Length, lastModified)); }
public static WicImageContainer Load(string fileName) { using var stm = default(ComPtr <IWICStream>); HRESULT.Check(Wic.Factory->CreateStream(stm.GetAddressOf())); fixed(char *pname = fileName) HRESULT.Check(stm.Get()->InitializeFromFilename((ushort *)pname, GENERIC_READ)); var dec = createDecoder((IStream *)stm.Get()); return(WicImageContainer.Create(dec)); }
/// <summary>Constructs a new <see cref="ImageFileInfo" /> instance by reading the metadata from an image file header.</summary> /// <param name="imgPath">The path to the image file.</param> public static ImageFileInfo Load(string imgPath) { var fi = new FileInfo(imgPath); if (!fi.Exists) { throw new FileNotFoundException("File not found", imgPath); } using var ctx = new PipelineContext(new ProcessImageSettings()); ctx.ImageContainer = WicImageContainer.Create(imgPath, ctx.WicContext); return(fromWicImage(ctx, fi.Length, fi.LastWriteTimeUtc)); }
/// <summary>All-in-one processing of an image according to the specified <paramref name="settings" />.</summary> /// <param name="imgPath">The path to a file containing the input image.</param> /// <param name="outStream">The stream to which the output image will be written. The stream must allow Seek and Write.</param> /// <param name="settings">The settings for this processing operation.</param> /// <returns>A <see cref="ProcessImageResult" /> containing the settings used and basic instrumentation for the pipeline.</returns> public static ProcessImageResult ProcessImage(string imgPath, Stream outStream, ProcessImageSettings settings) { if (imgPath is null) { throw new ArgumentNullException(nameof(imgPath)); } checkOutStream(outStream); using var ctx = new PipelineContext(settings); ctx.ImageContainer = WicImageContainer.Create(imgPath, ctx.WicContext); buildPipeline(ctx); return(WriteOutput(ctx, outStream)); }
#pragma warning disable 1573 // not all params have docs /// <inheritdoc cref="ProcessImage(string, Stream, ProcessImageSettings)" /> /// <param name="imgBuffer">A buffer containing a supported input image container.</param> public static ProcessImageResult ProcessImage(ReadOnlySpan <byte> imgBuffer, Stream outStream, ProcessImageSettings settings) { if (imgBuffer == default) { throw new ArgumentNullException(nameof(imgBuffer)); } checkOutStream(outStream); using var ctx = new PipelineContext(settings); ctx.ImageContainer = WicImageContainer.Create(imgBuffer, ctx.WicContext); buildPipeline(ctx); return(WriteOutput(ctx, outStream)); }
/// <inheritdoc cref="BuildPipeline(string, ProcessImageSettings)" /> /// <param name="imgBuffer">A buffer containing a supported input image container.</param> public static ProcessingPipeline BuildPipeline(ReadOnlySpan <byte> imgBuffer, ProcessImageSettings settings) { if (imgBuffer == default) { throw new ArgumentNullException(nameof(imgBuffer)); } var ctx = new PipelineContext(settings); ctx.ImageContainer = WicImageContainer.Create(imgBuffer, ctx.WicContext); buildPipeline(ctx, false); return(new ProcessingPipeline(ctx)); }
/// <summary>Constructs a new processing pipeline from which pixels can be retrieved.</summary> /// <param name="imgPath">The path to a file containing the input image.</param> /// <param name="settings">The settings for this processing operation.</param> /// <returns>A <see cref="ProcessingPipeline" /> containing the <see cref="IPixelSource" />, settings used, and basic instrumentation for the pipeline.</returns> public static ProcessingPipeline BuildPipeline(string imgPath, ProcessImageSettings settings) { if (imgPath is null) { throw new ArgumentNullException(nameof(imgPath)); } var ctx = new PipelineContext(settings); ctx.ImageContainer = WicImageContainer.Create(imgPath, ctx.WicContext); buildPipeline(ctx, false); return(new ProcessingPipeline(ctx)); }
/// <inheritdoc cref="BuildPipeline(string, ProcessImageSettings)" /> /// <param name="imgStream">A stream containing a supported input image container. The stream must allow Seek and Read.</param> public static ProcessingPipeline BuildPipeline(Stream imgStream, ProcessImageSettings settings) { if (settings is null) { throw new ArgumentNullException(nameof(settings)); } checkInStream(imgStream); var ctx = new PipelineContext(settings); ctx.ImageContainer = WicImageContainer.Create(imgStream, ctx.WicContext); buildPipeline(ctx, false); return(new ProcessingPipeline(ctx)); }
unsafe public static WicImageContainer Load(byte *pbBuffer, int cbBuffer, PipelineContext ctx, bool ownCopy = false) { var istm = ctx.WicContext.AddRef(Wic.Factory.CreateStream()); var ptr = (IntPtr)pbBuffer; if (ownCopy) { ptr = ctx.WicContext.AddUnmanagedMemory(cbBuffer).DangerousGetHandle(); Buffer.MemoryCopy(pbBuffer, ptr.ToPointer(), cbBuffer, cbBuffer); } istm.InitializeFromMemory(ptr, (uint)cbBuffer); var dec = createDecoder(stm => Wic.Factory.CreateDecoderFromStream(stm, null, WICDecodeOptions.WICDecodeMetadataCacheOnDemand), istm); return(WicImageContainer.Create(dec, ctx)); }
public static WicImageContainer Load(byte *pbBuffer, int cbBuffer, bool ownCopy = false) { using var stream = default(ComPtr <IWICStream>); HRESULT.Check(Wic.Factory->CreateStream(stream.GetAddressOf())); var ptr = (IntPtr)pbBuffer; using var mem = default(SafeHandleReleaser); if (ownCopy) { ptr = mem.Attach(new SafeHGlobalHandle(cbBuffer)).DangerousGetHandle(); Buffer.MemoryCopy(pbBuffer, ptr.ToPointer(), cbBuffer, cbBuffer); } HRESULT.Check(stream.Get()->InitializeFromMemory((byte *)ptr, (uint)cbBuffer)); var dec = createDecoder((IStream *)stream.Get()); return(WicImageContainer.Create(dec, mem.Detach())); }
/// <summary>Constructs a new <see cref="ImageFileInfo" /> instance by reading the metadata from an image file exposed by a <see cref="Stream" />.</summary> /// <param name="imgStream">The stream containing the image data.</param> /// <param name="lastModified">The last modified date of the image container.</param> public static ImageFileInfo Load(Stream imgStream, DateTime lastModified) { if (imgStream is null) { throw new ArgumentNullException(nameof(imgStream)); } if (!imgStream.CanSeek || !imgStream.CanRead) { throw new ArgumentException("Input Stream must allow Seek and Read", nameof(imgStream)); } if (imgStream.Length <= 0 || imgStream.Position >= imgStream.Length) { throw new ArgumentException("Input Stream is empty or positioned at its end", nameof(imgStream)); } using var ctx = new PipelineContext(new ProcessImageSettings()); ctx.ImageContainer = WicImageContainer.Create(imgStream, ctx.WicContext); return(fromWicImage(ctx, imgStream.Length, lastModified)); }
public static WicImageContainer Load(Stream inStream, PipelineContext ctx) { var dec = createDecoder(stm => Wic.Factory.CreateDecoderFromStream(stm, null, WICDecodeOptions.WICDecodeMetadataCacheOnDemand), inStream.AsIStream()); return(WicImageContainer.Create(dec, ctx)); }
public static WicImageContainer Load(string fileName, PipelineContext ctx) { var dec = createDecoder(fn => Wic.Factory.CreateDecoderFromFilename(fn, null, GenericAccessRights.GENERIC_READ, WICDecodeOptions.WICDecodeMetadataCacheOnDemand), fileName); return(WicImageContainer.Create(dec, ctx)); }
public WicImageFrame(WicImageContainer decoder, uint index) { Container = decoder; using var frame = default(ComPtr <IWICBitmapFrameDecode>); HRESULT.Check(decoder.WicDecoder->GetFrame(index, frame.GetAddressOf())); using var source = new ComPtr <IWICBitmapSource>((IWICBitmapSource *)frame.Get()); double dpix, dpiy; HRESULT.Check(frame.Get()->GetResolution(&dpix, &dpiy)); (DpiX, DpiY) = (dpix, dpiy); uint frameWidth, frameHeight; HRESULT.Check(frame.Get()->GetSize(&frameWidth, &frameHeight)); using var metareader = default(ComPtr <IWICMetadataQueryReader>); if (SUCCEEDED(frame.Get()->GetMetadataQueryReader(metareader.GetAddressOf()))) { string orientationPath = MagicImageProcessor.EnableXmpOrientation ? Wic.Metadata.OrientationWindowsPolicy : Container.ContainerFormat == FileFormat.Jpeg ? Wic.Metadata.OrientationJpeg : Wic.Metadata.OrientationExif; ExifOrientation = ((Orientation)metareader.GetValueOrDefault <ushort>(orientationPath)).Clamp(); WicMetadataReader = metareader.Detach(); } using var preview = default(ComPtr <IWICBitmapSource>); if (decoder.IsRawContainer && index == 0 && SUCCEEDED(decoder.WicDecoder->GetPreview(preview.GetAddressOf()))) { uint pw, ph; HRESULT.Check(preview.Get()->GetSize(&pw, &ph)); if (pw == frameWidth && ph == frameHeight) { source.Attach(preview.Detach()); } } using var transform = default(ComPtr <IWICBitmapSourceTransform>); if (SUCCEEDED(source.Get()->QueryInterface(__uuidof <IWICBitmapSourceTransform>(), (void **)transform.GetAddressOf()))) { uint tw = 1, th = 1; HRESULT.Check(transform.Get()->GetClosestSize(&tw, &th)); SupportsNativeScale = tw < frameWidth || th < frameHeight; } using var ptransform = default(ComPtr <IWICPlanarBitmapSourceTransform>); if (SUCCEEDED(source.Get()->QueryInterface(__uuidof <IWICPlanarBitmapSourceTransform>(), (void **)ptransform.GetAddressOf()))) { var fmts = WicTransforms.PlanarPixelFormats; var desc = stackalloc WICBitmapPlaneDescription[fmts.Length]; fixed(Guid *pfmt = fmts) { uint tw = frameWidth, th = frameHeight, st = 0; HRESULT.Check(ptransform.Get()->DoesSupportTransform( &tw, &th, WICBitmapTransformOptions.WICBitmapTransformRotate0, WICPlanarOptions.WICPlanarOptionsDefault, pfmt, desc, (uint)fmts.Length, (int *)&st )); SupportsPlanarProcessing = st != 0; } ChromaSubsampling = desc[1].Width < desc[0].Width && desc[1].Height < desc[0].Height ? WICJpegYCrCbSubsamplingOption.WICJpegYCrCbSubsampling420 : desc[1].Width < desc[0].Width ? WICJpegYCrCbSubsamplingOption.WICJpegYCrCbSubsampling422 : desc[1].Height < desc[0].Height ? WICJpegYCrCbSubsamplingOption.WICJpegYCrCbSubsampling440 : WICJpegYCrCbSubsamplingOption.WICJpegYCrCbSubsampling444; } var guid = default(Guid); HRESULT.Check(source.Get()->GetPixelFormat(&guid)); if (PixelFormat.FromGuid(guid).NumericRepresentation == PixelNumericRepresentation.Indexed) { var newFormat = PixelFormat.Bgr24Bpp; if (Container.ContainerFormat == FileFormat.Gif && Container.FrameCount > 1) { newFormat = PixelFormat.Bgra32Bpp; } else { using var pal = default(ComPtr <IWICPalette>); HRESULT.Check(Wic.Factory->CreatePalette(pal.GetAddressOf())); HRESULT.Check(source.Get()->CopyPalette(pal)); int bval; if (SUCCEEDED(pal.Get()->HasAlpha(&bval)) && bval != 0) { newFormat = PixelFormat.Bgra32Bpp; } else if ((SUCCEEDED(pal.Get()->IsGrayscale(&bval)) && bval != 0) || (SUCCEEDED(pal.Get()->IsBlackWhite(&bval)) && bval != 0)) { newFormat = PixelFormat.Grey8Bpp; } } var nfmt = newFormat.FormatGuid; using var conv = default(ComPtr <IWICFormatConverter>); HRESULT.Check(Wic.Factory->CreateFormatConverter(conv.GetAddressOf())); HRESULT.Check(conv.Get()->Initialize(source, &nfmt, WICBitmapDitherType.WICBitmapDitherTypeNone, null, 0.0, WICBitmapPaletteType.WICBitmapPaletteTypeCustom)); source.Attach((IWICBitmapSource *)conv.Detach()); } WicFrame = frame.Detach(); WicSource = source.Detach(); }
public WicImageFrame(WicImageContainer decoder, uint index) { if (index >= (uint)decoder.FrameCount) { throw new IndexOutOfRangeException("Frame index does not exist"); } WicFrame = comHandles.AddRef(decoder.WicDecoder.GetFrame(index)); WicSource = WicFrame; WicFrame.GetSize(out uint frameWidth, out uint frameHeight); container = decoder; if (decoder.IsRawContainer && index == 0 && decoder.WicDecoder.TryGetPreview(out var preview)) { using var pvwSource = new ComHandle <IWICBitmapSource>(preview); preview.GetSize(out uint pw, out uint ph); if (pw == frameWidth && ph == frameHeight) { WicSource = comHandles.AddOwnRef(preview); } } WicFrame.GetResolution(out double dpix, out double dpiy); DpiX = dpix; DpiY = dpiy; if (PixelFormat.FromGuid(WicSource.GetPixelFormat()).NumericRepresentation == PixelNumericRepresentation.Indexed) { var pal = comHandles.AddRef(Wic.Factory.CreatePalette()); WicSource.CopyPalette(pal); var newFormat = Consts.GUID_WICPixelFormat24bppBGR; if (pal.HasAlpha()) { newFormat = Consts.GUID_WICPixelFormat32bppBGRA; } else if (pal.IsGrayscale() || pal.IsBlackWhite()) { newFormat = Consts.GUID_WICPixelFormat8bppGray; } var conv = comHandles.AddRef(Wic.Factory.CreateFormatConverter()); conv.Initialize(WicSource, newFormat, WICBitmapDitherType.WICBitmapDitherTypeNone, null, 0.0, WICBitmapPaletteType.WICBitmapPaletteTypeCustom); WicSource = conv; } if (WicSource is IWICBitmapSourceTransform trans) { uint pw = 1, ph = 1; trans.GetClosestSize(ref pw, ref ph); SupportsNativeScale = pw < frameWidth || ph < frameHeight; SupportsNativeTransform = trans.DoesSupportTransform(WICBitmapTransformOptions.WICBitmapTransformRotate270); } if (WicSource is IWICPlanarBitmapSourceTransform ptrans) { var desc = ArrayPool <WICBitmapPlaneDescription> .Shared.Rent(WicTransforms.PlanarPixelFormats.Length); SupportsPlanarProcessing = ptrans.DoesSupportTransform(ref frameWidth, ref frameHeight, WICBitmapTransformOptions.WICBitmapTransformRotate0, WICPlanarOptions.WICPlanarOptionsDefault, WicTransforms.PlanarPixelFormats, desc, (uint)WicTransforms.PlanarPixelFormats.Length); ChromaSubsampling = desc[1].Width < desc[0].Width && desc[1].Height < desc[0].Height ? WICJpegYCrCbSubsamplingOption.WICJpegYCrCbSubsampling420 : desc[1].Width < desc[0].Width ? WICJpegYCrCbSubsamplingOption.WICJpegYCrCbSubsampling422 : desc[1].Height < desc[0].Height ? WICJpegYCrCbSubsamplingOption.WICJpegYCrCbSubsampling440 : WICJpegYCrCbSubsamplingOption.WICJpegYCrCbSubsampling444; ArrayPool <WICBitmapPlaneDescription> .Shared.Return(desc); } if (WicFrame.TryGetMetadataQueryReader(out var metareader)) { WicMetadataReader = comHandles.AddRef(metareader); string orientationPath = MagicImageProcessor.EnableXmpOrientation ? Wic.Metadata.OrientationWindowsPolicy : decoder.ContainerFormat == FileFormat.Jpeg ? Wic.Metadata.OrientationJpegPath : Wic.Metadata.OrientationExifPath; if (metareader.TryGetMetadataByName(orientationPath, out var pvorient) && pvorient.UnmanagedType == VarEnum.VT_UI2) { ExifOrientation = (Orientation)Math.Min(Math.Max((ushort)Orientation.Normal, (ushort)pvorient.Value !), (ushort)Orientation.Rotate270); } } }
public WicImageFrame(WicImageContainer decoder, uint index) { WicFrame = comHandles.AddRef(decoder.WicDecoder.GetFrame(index)); WicSource = WicFrame; Container = decoder; WicFrame.GetResolution(out double dpix, out double dpiy); DpiX = dpix; DpiY = dpiy; WicFrame.GetSize(out uint frameWidth, out uint frameHeight); if (WicFrame.TryGetMetadataQueryReader(out var metareader)) { WicMetadataReader = comHandles.AddRef(metareader); string orientationPath = MagicImageProcessor.EnableXmpOrientation ? Wic.Metadata.OrientationWindowsPolicy : Container.ContainerFormat == FileFormat.Jpeg ? Wic.Metadata.OrientationJpeg : Wic.Metadata.OrientationExif; ExifOrientation = ((Orientation)metareader.GetValueOrDefault <ushort>(orientationPath)).Clamp(); } if (decoder.IsRawContainer && index == 0 && decoder.WicDecoder.TryGetPreview(out var preview)) { using var pvwSource = ComHandle.Wrap(preview); preview.GetSize(out uint pw, out uint ph); if (pw == frameWidth && ph == frameHeight) { WicSource = comHandles.AddOwnRef(preview); } } if (WicSource is IWICBitmapSourceTransform trans) { uint pw = 1, ph = 1; trans.GetClosestSize(ref pw, ref ph); SupportsNativeScale = pw < frameWidth || ph < frameHeight; } if (WicSource is IWICPlanarBitmapSourceTransform ptrans) { var desc = ArrayPool <WICBitmapPlaneDescription> .Shared.Rent(WicTransforms.PlanarPixelFormats.Length); uint twidth = frameWidth, theight = frameHeight; SupportsPlanarProcessing = ptrans.DoesSupportTransform( ref twidth, ref theight, WICBitmapTransformOptions.WICBitmapTransformRotate0, WICPlanarOptions.WICPlanarOptionsDefault, WicTransforms.PlanarPixelFormats, desc, (uint)WicTransforms.PlanarPixelFormats.Length ); ChromaSubsampling = desc[1].Width < desc[0].Width && desc[1].Height < desc[0].Height ? WICJpegYCrCbSubsamplingOption.WICJpegYCrCbSubsampling420 : desc[1].Width < desc[0].Width ? WICJpegYCrCbSubsamplingOption.WICJpegYCrCbSubsampling422 : desc[1].Height < desc[0].Height ? WICJpegYCrCbSubsamplingOption.WICJpegYCrCbSubsampling440 : WICJpegYCrCbSubsamplingOption.WICJpegYCrCbSubsampling444; ArrayPool <WICBitmapPlaneDescription> .Shared.Return(desc); } if (PixelFormat.FromGuid(WicSource.GetPixelFormat()).NumericRepresentation == PixelNumericRepresentation.Indexed) { var newFormat = PixelFormat.Bgr24Bpp; if (Container.ContainerFormat == FileFormat.Gif && Container.FrameCount > 1) { newFormat = PixelFormat.Bgra32Bpp; } else { using var wicpal = ComHandle.Wrap(Wic.Factory.CreatePalette()); var pal = wicpal.ComObject; WicSource.CopyPalette(pal); if (pal.HasAlpha()) { newFormat = PixelFormat.Bgra32Bpp; } else if (pal.IsGrayscale() || pal.IsBlackWhite()) { newFormat = PixelFormat.Grey8Bpp; } } var conv = comHandles.AddRef(Wic.Factory.CreateFormatConverter()); conv.Initialize(WicSource, newFormat.FormatGuid, WICBitmapDitherType.WICBitmapDitherTypeNone, null, 0.0, WICBitmapPaletteType.WICBitmapPaletteTypeCustom); WicSource = conv; } }