public UnmanagedBitmapWrapper(BitmapSourceSafeMILHandle bitmapSource) : base(true) { _bitmapInit.BeginInit(); // // This constructor is used by BitmapDecoder and BitmapFrameDecode for thumbnails and // previews. The bitmapSource parameter comes from BitmapSource.CreateCachedBitmap // which already calculated memory pressure, so there's no need to do it here. // WicSourceHandle = bitmapSource; _bitmapInit.EndInit(); UpdateCachedSettings(); }
static internal InPlaceBitmapMetadataWriter CreateFromFrameDecode(BitmapSourceSafeMILHandle frameHandle, object syncObject) { Invariant.Assert(frameHandle != null); SafeMILHandle /* IWICFastMetadataEncoder */ fmeHandle = null; SafeMILHandle /* IWICMetadataQueryWriter */ metadataHandle = null; using (FactoryMaker factoryMaker = new FactoryMaker()) { lock (syncObject) { HRESULT.Check(UnsafeNativeMethods.WICImagingFactory.CreateFastMetadataEncoderFromFrameDecode( factoryMaker.ImagingFactoryPtr, frameHandle, out fmeHandle)); } } HRESULT.Check(UnsafeNativeMethods.WICFastMetadataEncoder.GetMetadataQueryWriter( fmeHandle, out metadataHandle)); return new InPlaceBitmapMetadataWriter(fmeHandle, metadataHandle, syncObject); }
internal static extern int /* HRESULT */ WICConvertBitmapSource( ref Guid dstPixelFormatGuid, SafeMILHandle /* IWICBitmapSource */ pISrc, out BitmapSourceSafeMILHandle /* IWICBitmapSource* */ ppIDst);
internal static extern int /*HRESULT*/ CreateFastMetadataEncoderFromFrameDecode( IntPtr THIS_PTR, BitmapSourceSafeMILHandle /* IWICBitmapFrameDecode */ pIFrameDecode, out SafeMILHandle /* IWICFastMetadataEncoder */ ppIBitmap);
internal static extern int /*HRESULT*/ CreateBitmapFromHICON( IntPtr THIS_PTR, IntPtr hIcon, out BitmapSourceSafeMILHandle /* IWICBitmap */ ppIBitmap);
internal static extern void GetBackBuffer( SafeMILHandle /* CSwDoubleBufferedBitmap */ THIS_PTR, out BitmapSourceSafeMILHandle /* IWICBitmap */ pBackBuffer, out uint pBackBufferSize );
private void EnsureSource() { if (_frameSource == null) { if (_decoder == null) { HRESULT.Check((int)WinCodecErrors.WINCODEC_ERR_NOTINITIALIZED); } // // Its possible that the frame was originally created with a network URI // and DelayCreation was enabled. In this case, the decoder may not yet // exist even though the download is complete. The code below creates a // decoder if one does not exist. // if (_decoder.InternalDecoder == null) { Debug.Assert(_decoder is LateBoundBitmapDecoder); Debug.Assert(IsDownloading == false); _decoder = ((LateBoundBitmapDecoder)_decoder).Decoder; _syncObject = _decoder.SyncObject; Debug.Assert(_decoder.InternalDecoder != null); } IntPtr frameDecode = IntPtr.Zero; Debug.Assert(_syncObject != null); lock (_syncObject) { HRESULT.Check(UnsafeNativeMethods.WICBitmapDecoder.GetFrame( _decoder.InternalDecoder, (uint)_frameNumber, out frameDecode )); _frameSource = new BitmapSourceSafeMILHandle(frameDecode); _frameSource.CalculateSize(); } } }
internal static extern int /*HRESULT*/ CreateBitmapFromSection( UInt32 width, UInt32 height, ref Guid pixelFormatGuid, IntPtr hSection, UInt32 stride, UInt32 offset, out BitmapSourceSafeMILHandle /* IWICBitmap */ ppIBitmap);
internal static extern int GetAsSoftwareBitmap(SafeMILHandle pInteropDeviceBitmap, out BitmapSourceSafeMILHandle pIWICBitmapSource);
internal static extern int /* HRESULT */ CreateBitmapFlipRotator( IntPtr pICodecFactory, out BitmapSourceSafeMILHandle /* IWICBitmapFlipRotator */ ppBitmapFlipRotator);
internal static extern int /* HRESULT */ CreateFormatConverter( IntPtr pICodecFactory, out BitmapSourceSafeMILHandle /* IWICFormatConverter */ ppFormatConverter);
internal override void FinalizeCreation() { _bitmapInit.EnsureInitializedComplete(); BitmapSourceSafeMILHandle wicFormatter = null; using (FactoryMaker factoryMaker = new FactoryMaker()) { try { IntPtr wicFactory = factoryMaker.ImagingFactoryPtr; HRESULT.Check(UnsafeNativeMethods.WICImagingFactory.CreateFormatConverter( wicFactory, out wicFormatter)); SafeMILHandle internalPalette; if (DestinationPalette != null) { internalPalette = DestinationPalette.InternalPalette; } else { internalPalette = new SafeMILHandle(); } Guid format = DestinationFormat.Guid; lock (_syncObject) { HRESULT.Check(UnsafeNativeMethods.WICFormatConverter.Initialize( wicFormatter, Source.WicSourceHandle, ref format, DitherType.DitherTypeErrorDiffusion, internalPalette, AlphaThreshold, WICPaletteType.WICPaletteTypeOptimal )); } // // This is just a link in a BitmapSource chain. The memory is being used by // the BitmapSource at the end of the chain, so no memory pressure needs // to be added here. // WicSourceHandle = wicFormatter; // Even if our source is cached, format conversion is expensive and so we'll // always maintain our own cache for the purpose of rendering. _isSourceCached = false; } catch { _bitmapInit.Reset(); throw; } finally { if (wicFormatter != null) { wicFormatter.Close(); } } } CreationCompleted = true; UpdateCachedSettings(); }
internal override void FinalizeCreation() { _bitmapInit.EnsureInitializedComplete(); BitmapSourceSafeMILHandle wicTransformer = null; double scaleX, scaleY; WICBitmapTransformOptions options; GetParamsFromTransform(Transform, out scaleX, out scaleY, out options); using (FactoryMaker factoryMaker = new FactoryMaker()) { try { IntPtr wicFactory = factoryMaker.ImagingFactoryPtr; wicTransformer = _source.WicSourceHandle; if (!DoubleUtil.IsOne(scaleX) || !DoubleUtil.IsOne(scaleY)) { uint width = Math.Max(1, (uint)(scaleX * _source.PixelWidth + 0.5)); uint height = Math.Max(1, (uint)(scaleY * _source.PixelHeight + 0.5)); HRESULT.Check(UnsafeNativeMethods.WICImagingFactory.CreateBitmapScaler( wicFactory, out wicTransformer)); lock (_syncObject) { HRESULT.Check(UnsafeNativeMethods.WICBitmapScaler.Initialize( wicTransformer, _source.WicSourceHandle, width, height, WICInterpolationMode.Fant)); } } if (options != WICBitmapTransformOptions.WICBitmapTransformRotate0) { // Rotations are extremely slow if we're pulling from a decoder because we end // up decoding multiple times. Caching the source lets us rotate faster at the cost // of increased memory usage. wicTransformer = CreateCachedBitmap( null, wicTransformer, BitmapCreateOptions.PreservePixelFormat, BitmapCacheOption.Default, _source.Palette); // BitmapSource.CreateCachedBitmap already calculates memory pressure for // the new bitmap, so there's no need to do it before setting it to // WicSourceHandle. BitmapSourceSafeMILHandle rotator = null; HRESULT.Check(UnsafeNativeMethods.WICImagingFactory.CreateBitmapFlipRotator( wicFactory, out rotator)); lock (_syncObject) { HRESULT.Check(UnsafeNativeMethods.WICBitmapFlipRotator.Initialize( rotator, wicTransformer, options)); } wicTransformer = rotator; } // If we haven't introduced either a scaler or rotator, add a null rotator // so that our WicSourceHandle isn't the same as our Source's. if (options == WICBitmapTransformOptions.WICBitmapTransformRotate0 && DoubleUtil.IsOne(scaleX) && DoubleUtil.IsOne(scaleY)) { HRESULT.Check(UnsafeNativeMethods.WICImagingFactory.CreateBitmapFlipRotator( wicFactory, out wicTransformer)); lock (_syncObject) { HRESULT.Check(UnsafeNativeMethods.WICBitmapFlipRotator.Initialize( wicTransformer, _source.WicSourceHandle, WICBitmapTransformOptions.WICBitmapTransformRotate0)); } } WicSourceHandle = wicTransformer; _isSourceCached = _source.IsSourceCached; } catch { _bitmapInit.Reset(); throw; } } CreationCompleted = true; UpdateCachedSettings(); }
internal static extern int /*HRESULT*/ GetBitmap( SafeMILHandle /* IMILRenderTargetBitmap */ THIS_PTR, out BitmapSourceSafeMILHandle /* IWICBitmap */ ppIBitmap);
internal static extern int /* HRESULT */ CreateColorTransform( out BitmapSourceSafeMILHandle /* IWICColorTransform */ ppWICColorTransform);
internal static extern int /*HRESULT*/ CreateBitmapFromSource( IntPtr THIS_PTR, SafeMILHandle /* IWICBitmapSource */ pIBitmapSource, WICBitmapCreateCacheOptions options, out BitmapSourceSafeMILHandle /* IWICBitmap */ ppIBitmap);
internal static extern int /* HRESULT */ CreateBitmapRenderTargetForBitmap( IntPtr THIS_PTR, BitmapSourceSafeMILHandle /* IWICBitmap */ pIBitmap, out SafeMILHandle /* IMILRenderTargetBitmap */ ppIRenderTargetBitmap);
internal static extern int /*HRESULT*/ CreateBitmapFromMemory( IntPtr THIS_PTR, UInt32 width, UInt32 height, ref Guid pixelFormatGuid, UInt32 stride, UInt32 cbBufferSize, IntPtr /* BYTE* */ pvPixels, out BitmapSourceSafeMILHandle /* IWICBitmap */ ppIBitmap);
internal unsafe static extern int /* HRESULT */ CreateCWICWrapperBitmap( BitmapSourceSafeMILHandle /* IWICBitmapSource */ pIWICBitmapSource, out BitmapSourceSafeMILHandle /* CWICWrapperBitmap as IWICBitmapSource */ pCWICWrapperBitmap);
internal static extern int /*HRESULT*/ CreateBitmap( IntPtr THIS_PTR, UInt32 width, UInt32 height, ref Guid pixelFormatGuid, WICBitmapCreateCacheOptions options, out BitmapSourceSafeMILHandle /* IWICBitmap */ ppIBitmap);
private void EnsureThumbnail() { if (_isThumbnailCached || IsDownloading) { return; } else { EnsureSource(); IntPtr /* IWICBitmapSource */ thumbnail = IntPtr.Zero; lock (_syncObject) { // Check if there is embedded thumbnail or not int hr = UnsafeNativeMethods.WICBitmapFrameDecode.GetThumbnail( _frameSource, out thumbnail ); if (hr != (int)WinCodecErrors.WINCODEC_ERR_CODECNOTHUMBNAIL) { HRESULT.Check(hr); } } _isThumbnailCached = true; if (thumbnail != IntPtr.Zero) { BitmapSourceSafeMILHandle thumbHandle = new BitmapSourceSafeMILHandle(thumbnail); SafeMILHandle unmanagedPalette = BitmapPalette.CreateInternalPalette(); BitmapPalette palette = null; int hr = UnsafeNativeMethods.WICBitmapSource.CopyPalette( thumbHandle, unmanagedPalette ); if (hr == HRESULT.S_OK) { palette = new BitmapPalette(unmanagedPalette); } _thumbnail = new UnmanagedBitmapWrapper( CreateCachedBitmap( null, thumbHandle, BitmapCreateOptions.PreservePixelFormat, _cacheOption, palette )); _thumbnail.Freeze(); } } }
internal static extern int /*HRESULT*/ CreateBitmapFromHBITMAP( IntPtr THIS_PTR, IntPtr hBitmap, IntPtr hPalette, WICBitmapAlphaChannelOption options, out BitmapSourceSafeMILHandle /* IWICBitmap */ ppIBitmap);
internal static BitmapSourceSafeMILHandle CreateCachedBitmap( BitmapFrame frame, BitmapSourceSafeMILHandle wicSource, BitmapCreateOptions createOptions, BitmapCacheOption cacheOption, BitmapPalette palette ) { BitmapSourceSafeMILHandle wicConverter = null; BitmapSourceSafeMILHandle wicConvertedSource = null; // For NoCache, return the original if (cacheOption == BitmapCacheOption.None) { return wicSource; } using (FactoryMaker factoryMaker = new FactoryMaker()) { IntPtr wicFactory = factoryMaker.ImagingFactoryPtr; bool changeFormat = false; PixelFormat originalFmt = PixelFormats.Pbgra32; WICBitmapCreateCacheOptions wicCache = WICBitmapCreateCacheOptions.WICBitmapCacheOnLoad; if (cacheOption == BitmapCacheOption.OnDemand) { wicCache = WICBitmapCreateCacheOptions.WICBitmapCacheOnDemand; } originalFmt = PixelFormat.GetPixelFormat(wicSource); PixelFormat destFmt = originalFmt; // check that we need to change the format of the bitmap if (0 == (createOptions & BitmapCreateOptions.PreservePixelFormat)) { if (!IsCompatibleFormat(originalFmt)) changeFormat = true; destFmt = BitmapSource.GetClosestDUCEFormat(originalFmt, palette); } if (frame != null && (createOptions & BitmapCreateOptions.IgnoreColorProfile) == 0 && frame.ColorContexts != null && frame.ColorContexts[0] != null && frame.ColorContexts[0].IsValid && !frame._isColorCorrected && PixelFormat.GetPixelFormat(wicSource).Format != PixelFormatEnum.Extended ) { ColorContext destinationColorContext; // We need to make sure, we can actually create the ColorContext for the destination destFmt // If the destFmt is gray or scRGB, the following is not supported, so we cannot // create the ColorConvertedBitmap try { destinationColorContext = new ColorContext(destFmt); } catch (NotSupportedException) { destinationColorContext = null; } if (destinationColorContext != null) { // NOTE: Never do this for a non-MIL pixel format, because the format converter has // special knowledge to deal with the profile bool conversionSuccess = false; bool badColorContext = false; // First try if the color converter can handle the source format directly // Its possible that the color converter does not support certain pixelformats, so put a try/catch here. try { ColorConvertedBitmap colorConvertedBitmap = new ColorConvertedBitmap( frame, frame.ColorContexts[0], destinationColorContext, destFmt ); wicSource = colorConvertedBitmap.WicSourceHandle; frame._isColorCorrected = true; conversionSuccess = true; changeFormat = false; // Changeformat no longer necessary, because destFmt already created // by ColorConvertedBitmap } catch (NotSupportedException) { } catch (FileFormatException) { // If the file contains a bad color context, we catch the exception here // and don't bother trying the color conversion below, since color transform isn't possible // with the given color context. badColorContext = true; } if (!conversionSuccess && changeFormat && !badColorContext) { // If the conversion failed, we first use // a FormatConvertedBitmap, and then Color Convert that one... changeFormat = false; FormatConvertedBitmap formatConvertedBitmap = new FormatConvertedBitmap(frame, destFmt, null, 0.0); ColorConvertedBitmap colorConvertedBitmap = new ColorConvertedBitmap( formatConvertedBitmap, frame.ColorContexts[0], destinationColorContext, destFmt ); wicSource = colorConvertedBitmap.WicSourceHandle; frame._isColorCorrected = true; Debug.Assert(destFmt == colorConvertedBitmap.Format); changeFormat = false; // Changeformat no longer necessary, because destFmt already created // by ColorConvertedBitmap } } } if (changeFormat) { // start up a format converter Guid fmtDestFmt = destFmt.Guid; HRESULT.Check(UnsafeNativeMethods.WICCodec.WICConvertBitmapSource( ref fmtDestFmt, wicSource, out wicConverter)); // dump the converted contents into a bitmap HRESULT.Check(UnsafeNativeMethods.WICImagingFactory.CreateBitmapFromSource( wicFactory, wicConverter, wicCache, out wicConvertedSource)); } else { // Create the unmanaged resources HRESULT.Check(UnsafeNativeMethods.WICImagingFactory.CreateBitmapFromSource( wicFactory, wicSource, wicCache, out wicConvertedSource)); } wicConvertedSource.CalculateSize(); } return wicConvertedSource; }
internal CachedBitmap(BitmapSourceSafeMILHandle bitmap) : base(true) { if (bitmap == null) { throw new ArgumentNullException("bitmap"); } // We're not calling CachedBitmap.Begin/EndInit because that would // invoke FinalizeCreation which calls CreateCachedBitmap that does // unnecessary work and only deals with BitmapFrames _bitmapInit.BeginInit(); _source = null; _createOptions = BitmapCreateOptions.None; _cacheOption = BitmapCacheOption.OnLoad; // // This constructor is used by D3DImage, which does not calculate memory pressure for // the bitmap parameter before calling the constructor. // bitmap.CalculateSize(); // This will QI to IWICBitmapSource for us. QI also AddRefs, of course. WicSourceHandle = bitmap; _syncObject = WicSourceHandle; IsSourceCached = true; CreationCompleted = true; _bitmapInit.EndInit(); }