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; } }