Code:
/ 4.0 / 4.0 / DEVDIV_TFS / Dev10 / Releases / RTMRel / wpf / src / Core / CSharp / System / Windows / Media / Imaging / BitmapFrameDecode.cs / 1305600 / BitmapFrameDecode.cs
//------------------------------------------------------------------------------ // Microsoft Avalon // Copyright (c) Microsoft Corporation // // File: BitmapFrameDecode.cs // //----------------------------------------------------------------------------- using System; using System.Collections; using System.Collections.ObjectModel; using System.Collections.Generic; using System.ComponentModel; using System.ComponentModel.Design.Serialization; using System.Reflection; using MS.Internal; using MS.Internal.PresentationCore; using System.Diagnostics; using System.Windows.Media; using System.Globalization; using System.Security; using System.Security.Permissions; using System.Runtime.InteropServices; using System.Windows.Media.Animation; using System.Windows.Media.Composition; using System.Windows.Media.Imaging; using MS.Win32.PresentationCore; #pragma warning disable 1634, 1691 // Allow suppression of certain presharp messages namespace System.Windows.Media.Imaging { #region BitmapFrameDecode ////// BitmapFrameDecode abstract class /// internal sealed class BitmapFrameDecode : BitmapFrame { #region Constructors ////// Internal constructor -- Creates new frame using specified decoder /// internal BitmapFrameDecode( int frameNumber, BitmapCreateOptions createOptions, BitmapCacheOption cacheOption, BitmapDecoder decoder ) : base(true) { _bitmapInit.BeginInit(); _frameNumber = frameNumber; _isThumbnailCached = false; _isMetadataCached = false; _frameSource = null; Debug.Assert(decoder != null); _decoder = decoder; _syncObject = decoder.SyncObject; _createOptions = createOptions; _cacheOption = cacheOption; _bitmapInit.EndInit(); if ((createOptions & BitmapCreateOptions.DelayCreation) != 0) { DelayCreation = true; } else { FinalizeCreation(); } } ////// Internal constructor -- Creates frame from another frame /// ////// SecurityCritical: Accesses unmanaged resources (_wicSource) /// SecurityTreatAsSafe: Inputs are verified and _wicSource and the get is Critical /// [SecurityCritical, SecurityTreatAsSafe] internal BitmapFrameDecode( int frameNumber, BitmapCreateOptions createOptions, BitmapCacheOption cacheOption, BitmapFrameDecode frameDecode ) : base(true) { _bitmapInit.BeginInit(); _frameNumber = frameNumber; WicSourceHandle = frameDecode.WicSourceHandle; IsSourceCached = frameDecode.IsSourceCached; CreationCompleted = frameDecode.CreationCompleted; _frameSource = frameDecode._frameSource; _decoder = frameDecode.Decoder; _syncObject = _decoder.SyncObject; _createOptions = createOptions; _cacheOption = cacheOption; _thumbnail = frameDecode._thumbnail; _isThumbnailCached = frameDecode._isThumbnailCached; _metadata = frameDecode._metadata; _isMetadataCached = frameDecode._isMetadataCached; _readOnlycolorContexts = frameDecode._readOnlycolorContexts; _isColorContextCached = frameDecode._isColorContextCached; _bitmapInit.EndInit(); if ((createOptions & BitmapCreateOptions.DelayCreation) != 0) { DelayCreation = true; } else if (!CreationCompleted) { FinalizeCreation(); } else { UpdateCachedSettings(); } } ////// Internal constructor -- Creates frame thats being downloaded /// ////// SecurityCritical: Accesses unmanaged resources (_wicSource) /// SecurityTreatAsSafe: Inputs are verified and _wicSource and the get is Critical /// [SecurityCritical, SecurityTreatAsSafe] internal BitmapFrameDecode( int frameNumber, BitmapCreateOptions createOptions, BitmapCacheOption cacheOption, LateBoundBitmapDecoder decoder ) : base(true) { _bitmapInit.BeginInit(); _frameNumber = frameNumber; byte[] pixels = new byte[4]; BitmapSource source = BitmapSource.Create( 1, 1, 96, 96, PixelFormats.Pbgra32, null, pixels, 4 ); WicSourceHandle = source.WicSourceHandle; Debug.Assert(decoder != null); _decoder = decoder; _createOptions = createOptions; _cacheOption = cacheOption; // // Hook the decoders download events // _decoder.DownloadCompleted += OnDownloadCompleted; _decoder.DownloadProgress += OnDownloadProgress; _decoder.DownloadFailed += OnDownloadFailed; _bitmapInit.EndInit(); } ////// Do not allow construction /// private BitmapFrameDecode() : base(true) { } #endregion #region IUriContext ////// Provides the base uri of the current context. /// public override Uri BaseUri { get { ReadPreamble(); return _decoder._baseUri; } set { WritePreamble(); // Nothing to do here. } } #endregion #region Public Properties ////// Accesses the Thumbnail property for this BitmapFrameDecode /// public override BitmapSource Thumbnail { get { ReadPreamble(); EnsureThumbnail(); return _thumbnail; } } ////// Accesses the Metadata property for this BitmapFrameDecode /// public override ImageMetadata Metadata { get { ReadPreamble(); return InternalMetadata; } } ////// Accesses the Decoder property for this BitmapFrameDecode /// public override BitmapDecoder Decoder { get { ReadPreamble(); return _decoder; } } ////// Used as a delegate in ColorContexts to get the unmanaged IWICColorContexts /// ////// Critical - Calls critical, unmanaged method /// [SecurityCritical] private int GetColorContexts(ref uint numContexts, IntPtr[] colorContextPtrs) { Invariant.Assert(colorContextPtrs == null || numContexts <= colorContextPtrs.Length); return UnsafeNativeMethods.WICBitmapFrameDecode.GetColorContexts(_frameSource, numContexts, colorContextPtrs, out numContexts); } ////// If there is an embedded color profile, return it. /// Otherwise, return null. This method does NOT create a /// color profile for bitmaps that don't already have one. /// ////// Provides access to this encoders color profile /// /// ////// Critical - Access unmanaged code, codecs /// TreatAsSafe - We are exposing specific, non-sensitive data that came from /// a Uri or a bitmap. If the profile data came from a Uri, the /// WebRequest we did to get it demandend the appropriate /// permission and we did not expose the request or response. If it came /// from a bitmap, it may be cross-domain, but the restricted /// nature of the data combined with the fact that it has been /// inspected by WCS which is hardened against malicious data /// makes this OK. /// public override ReadOnlyCollectionColorContexts { [SecurityCritical, SecurityTreatAsSafe] get { ReadPreamble(); if (!_isColorContextCached && !IsDownloading) { EnsureSource(); lock (_syncObject) { IList colorContextList = ColorContext.GetColorContextsHelper(GetColorContexts); if (colorContextList != null) { _readOnlycolorContexts = new ReadOnlyCollection (colorContextList); } _isColorContextCached = true; } } return _readOnlycolorContexts; } } /// /// Returns if the BitmapFrame is downloading content /// public override bool IsDownloading { get { ReadPreamble(); return Decoder.IsDownloading; } } #endregion #region Public Methods ////// Create an in-place bitmap metadata writer. /// public override InPlaceBitmapMetadataWriter CreateInPlaceBitmapMetadataWriter() { ReadPreamble(); if (_decoder != null) { _decoder.CheckOriginalWritable(); } // Demand Site Of Origin on the URI before usage of metadata. CheckIfSiteOfOrigin(); EnsureSource(); return InPlaceBitmapMetadataWriter.CreateFromFrameDecode(_frameSource, _syncObject); } #endregion #region ToString ////// Can serialze "this" to a string /// internal override bool CanSerializeToString() { ReadPreamble(); return _decoder.CanConvertToString(); } ////// Creates a string representation of this object based on the format string /// and IFormatProvider passed in. /// If the provider is null, the CurrentCulture is used. /// See the documentation for IFormattable for more information. /// ////// A string representation of this object. /// internal override string ConvertToString(string format, IFormatProvider provider) { ReadPreamble(); if (_decoder != null) { return _decoder.ToString(); } return base.ConvertToString(format, provider); } #endregion #region Freezable ////// Implementation of ///Freezable.CreateInstanceCore . ///The new Freezable. protected override Freezable CreateInstanceCore() { return new BitmapFrameDecode(); } ////// Copy the fields not covered by DPs. This is used by /// CloneCore(), CloneCurrentValueCore(), GetAsFrozenCore() and /// GetCurrentValueAsFrozenCore(). /// ////// Critical - access critical resources (_metadata) /// TreatAsSafe - All inputs verified /// [SecurityCritical, SecurityTreatAsSafe] private void CopyCommon(BitmapFrameDecode sourceBitmapFrameDecode) { _bitmapInit.BeginInit(); _frameNumber = sourceBitmapFrameDecode._frameNumber; _isThumbnailCached = sourceBitmapFrameDecode._isThumbnailCached; _isMetadataCached = sourceBitmapFrameDecode._isMetadataCached; _isColorContextCached = sourceBitmapFrameDecode._isColorContextCached; _frameSource = sourceBitmapFrameDecode._frameSource; _thumbnail = sourceBitmapFrameDecode._thumbnail; _metadata = sourceBitmapFrameDecode.InternalMetadata; _readOnlycolorContexts = sourceBitmapFrameDecode._readOnlycolorContexts; _decoder = sourceBitmapFrameDecode._decoder; if (_decoder != null && _decoder.IsDownloading) { // UpdateDecoder must be called when download completes and the real decoder // is created. Normally _decoder will call UpdateDecoder, but in this case the // decoder will not know about the cloned BitmapFrameDecode and will only call // UpdateDecoder on the original. The clone will need to listen to the original // BitmapFrameDecode for DownloadCompleted, then call UpdateDecoder on itself. // The weak event sink hooks up handlers on DownloadCompleted, DownloadFailed, // and DownloadProgress _weakBitmapFrameDecodeEventSink = new WeakBitmapFrameDecodeEventSink(this, sourceBitmapFrameDecode); } _syncObject = _decoder.SyncObject; _createOptions = sourceBitmapFrameDecode._createOptions; _cacheOption = sourceBitmapFrameDecode._cacheOption; _bitmapInit.EndInit(); } ////// Implementation of protected override void CloneCore(Freezable sourceFreezable) { BitmapFrameDecode sourceBitmapFrameDecode = (BitmapFrameDecode)sourceFreezable; base.CloneCore(sourceFreezable); CopyCommon(sourceBitmapFrameDecode); } ///Freezable.CloneCore . ////// Implementation of protected override void CloneCurrentValueCore(Freezable sourceFreezable) { BitmapFrameDecode sourceBitmapFrameDecode = (BitmapFrameDecode)sourceFreezable; base.CloneCurrentValueCore(sourceFreezable); CopyCommon(sourceBitmapFrameDecode); } ///Freezable.CloneCurrentValueCore . ////// Implementation of protected override void GetAsFrozenCore(Freezable sourceFreezable) { BitmapFrameDecode sourceBitmapFrameDecode = (BitmapFrameDecode)sourceFreezable; base.GetAsFrozenCore(sourceFreezable); CopyCommon(sourceBitmapFrameDecode); } ///Freezable.GetAsFrozenCore . ////// Implementation of protected override void GetCurrentValueAsFrozenCore(Freezable sourceFreezable) { BitmapFrameDecode sourceBitmapFrameDecode = (BitmapFrameDecode)sourceFreezable; base.GetCurrentValueAsFrozenCore(sourceFreezable); CopyCommon(sourceBitmapFrameDecode); } #endregion #region Internal Properties / Methods ///Freezable.GetCurrentValueAsFrozenCore . ////// Updates the internal decoder -- usually happens with a LateBoundBitmapDecoder /// ////// Critical - access critical resources /// TreatAsSafe - All inputs verified /// [SecurityCritical, SecurityTreatAsSafe] internal void UpdateDecoder(BitmapDecoder decoder) { Debug.Assert(_decoder != null); _decoder = decoder; _syncObject = decoder.SyncObject; WicSourceHandle = null; _needsUpdate = true; FinalizeCreation(); // Trigger a update of the UCE resource RegisterForAsyncUpdateResource(); } ////// Create the unmanaged resources /// ////// Critical - access critical resources /// TreatAsSafe - All inputs verified /// [SecurityCritical, SecurityTreatAsSafe] internal override void FinalizeCreation() { EnsureSource(); // Set the WicSourceHandle and Update the cached settings so that we // can query the source for information such as the palette which we need // to determine if we need to format convert or not. WicSourceHandle = _frameSource; UpdateCachedSettings(); lock (_syncObject) { WicSourceHandle = CreateCachedBitmap(this, _frameSource, _createOptions, _cacheOption, Palette); } IsSourceCached = (_cacheOption != BitmapCacheOption.None); CreationCompleted = true; UpdateCachedSettings(); EnsureThumbnail(); } // // Workaround for a change caused by a bug fix, CopyCommon checks this property when // copying the delegates attached to events. // Default implementation in BitmapSource, see comments in BitmapSource.cs for details. // internal override bool ShouldCloneEventDelegates { get { return false; } } #endregion #region Private Methods /// Fired when the decoder download has completed private void OnDownloadCompleted(object sender, EventArgs e) { // // The sender should be the LateBoundDecoder that we hooked when it was _decoder. // LateBoundBitmapDecoder decoder = (LateBoundBitmapDecoder)sender; // // Unhook the decoders download events // decoder.DownloadCompleted -= OnDownloadCompleted; decoder.DownloadProgress -= OnDownloadProgress; decoder.DownloadFailed -= OnDownloadFailed; FireChanged(); _downloadEvent.InvokeEvents(this, null); } /// Called when download progress is made private void OnDownloadProgress(object sender, DownloadProgressEventArgs e) { _progressEvent.InvokeEvents(this, e); } /// Called when download fails private void OnDownloadFailed(object sender, ExceptionEventArgs e) { // // The sender should be the LateBoundDecoder that we hooked when it was _decoder. // LateBoundBitmapDecoder decoder = (LateBoundBitmapDecoder)sender; // // Unhook the decoders download events // decoder.DownloadCompleted -= OnDownloadCompleted; decoder.DownloadProgress -= OnDownloadProgress; decoder.DownloadFailed -= OnDownloadFailed; _failedEvent.InvokeEvents(this, e); } /// Fired when the original's decoder's download has completed private void OnOriginalDownloadCompleted(BitmapFrameDecode original, EventArgs e) { CleanUpWeakEventSink(); // Update the underlying decoder to match the original's // We already have a _decoder from the cloning, but it's referencing the // LateBoundBitmapDecoder. When download completes, LateBoundBitmapDecoder calls // EnsureDecoder to make the _realDecoder (something like JpegBitmapDecoder), // then calls SetupFrames on the _realDecoder, which calls BitmapFrameDecode's // UpdateDecoder to set _decoder to the JpegBitmapDecoder. So the original's _decoder // changes after download completes, and the clone should change as well. UpdateDecoder(original.Decoder); FireChanged(); _downloadEvent.InvokeEvents(this, e); } /// Called when the original's decoder's download fails private void OnOriginalDownloadFailed(ExceptionEventArgs e) { CleanUpWeakEventSink(); _failedEvent.InvokeEvents(this, e); } private void CleanUpWeakEventSink() { // Unhook the decoders download events _weakBitmapFrameDecodeEventSink.DetachSourceDownloadHandlers(); _weakBitmapFrameDecodeEventSink = null; } ////// Ensure that the thumbnail is created/cached /// ////// Critical - Access unmanaged code, codecs /// TreatAsSafe - Getting thumbnail data is OK /// [SecurityCritical, SecurityTreatAsSafe] 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(); } } } ////// Returns cached metadata and creates BitmapMetadata if it does not exist. /// This code will demand site of origin permissions. /// ////// Critical - Access unmanaged code /// TreatAsSafe - demands site of origin permissions /// internal override BitmapMetadata InternalMetadata { [SecurityCritical, SecurityTreatAsSafe] get { // Demand Site Of Origin on the URI before usage of metadata. CheckIfSiteOfOrigin(); if (!_isMetadataCached && !IsDownloading) { EnsureSource(); IntPtr /* IWICMetadataQueryReader */ metadata = IntPtr.Zero; lock (_syncObject) { // Check if there is embedded metadata or not int hr = UnsafeNativeMethods.WICBitmapFrameDecode.GetMetadataQueryReader( _frameSource, out metadata ); if (hr != (int)WinCodecErrors.WINCODEC_ERR_UNSUPPORTEDOPERATION) { HRESULT.Check(hr); } } if (metadata != IntPtr.Zero) { SafeMILHandle metadataHandle = new SafeMILHandle(metadata); _metadata = new BitmapMetadata(metadataHandle, true, _decoder != null ? _decoder.IsMetadataFixedSize : false, _syncObject); _metadata.Freeze(); } _isMetadataCached = true; } return _metadata; } set { throw new System.NotImplementedException(); } } ////// Ensure that a BitmapSource is created /// ////// Critical - Access unmanaged code, codecs /// TreatAsSafe - Getting frame data is OK /// [SecurityCritical, SecurityTreatAsSafe] 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(); } } } #endregion #region Data Members /// IWICBitmapFrameDecode source private BitmapSourceSafeMILHandle _frameSource = null; /// Frame number private int _frameNumber; /// Is the thumbnail cached private bool _isThumbnailCached; /// Is the metadata cached private bool _isMetadataCached; /// If the ColorContext is already cached private bool _isColorContextCached = false; /// CreateOptions for this Frame private BitmapCreateOptions _createOptions; /// CacheOption for this Frame private BitmapCacheOption _cacheOption; /// Decoder private BitmapDecoder _decoder; #endregion #region WeakBitmapSourceEvents // Used to propagate DownloadCompleted events for cloned BitmapFrameDecodes that are still downloading private WeakBitmapFrameDecodeEventSink _weakBitmapFrameDecodeEventSink; private class WeakBitmapFrameDecodeEventSink : WeakReference { public WeakBitmapFrameDecodeEventSink(BitmapFrameDecode cloned, BitmapFrameDecode original) : base(cloned) { _original = original; if (!_original.IsFrozen) { _original.DownloadCompleted += OnSourceDownloadCompleted; _original.DownloadFailed += OnSourceDownloadFailed; _original.DownloadProgress += OnSourceDownloadProgress; } } public void OnSourceDownloadCompleted(object sender, EventArgs e) { BitmapFrameDecode clone = this.Target as BitmapFrameDecode; if (null != clone) { clone.OnOriginalDownloadCompleted(_original, e); } else { DetachSourceDownloadHandlers(); } } public void OnSourceDownloadFailed(object sender, ExceptionEventArgs e) { BitmapFrameDecode clone = this.Target as BitmapFrameDecode; if (null != clone) { clone.OnOriginalDownloadFailed(e); } else { DetachSourceDownloadHandlers(); } } public void OnSourceDownloadProgress(object sender, DownloadProgressEventArgs e) { BitmapFrameDecode clone = this.Target as BitmapFrameDecode; if (null != clone) { clone.OnDownloadProgress(sender, e); } else { DetachSourceDownloadHandlers(); } } public void DetachSourceDownloadHandlers() { if (!_original.IsFrozen) { _original.DownloadCompleted -= OnSourceDownloadCompleted; _original.DownloadFailed -= OnSourceDownloadFailed; _original.DownloadProgress -= OnSourceDownloadProgress; } } private BitmapFrameDecode _original; } #endregion WeakBitmapSourceEvents } #endregion // BitmapFrameDecode } // File provided for Reference Use Only by Microsoft Corporation (c) 2007. // Copyright (c) Microsoft Corporation. All rights reserved. //------------------------------------------------------------------------------ // Microsoft Avalon // Copyright (c) Microsoft Corporation // // File: BitmapFrameDecode.cs // //----------------------------------------------------------------------------- using System; using System.Collections; using System.Collections.ObjectModel; using System.Collections.Generic; using System.ComponentModel; using System.ComponentModel.Design.Serialization; using System.Reflection; using MS.Internal; using MS.Internal.PresentationCore; using System.Diagnostics; using System.Windows.Media; using System.Globalization; using System.Security; using System.Security.Permissions; using System.Runtime.InteropServices; using System.Windows.Media.Animation; using System.Windows.Media.Composition; using System.Windows.Media.Imaging; using MS.Win32.PresentationCore; #pragma warning disable 1634, 1691 // Allow suppression of certain presharp messages namespace System.Windows.Media.Imaging { #region BitmapFrameDecode ////// BitmapFrameDecode abstract class /// internal sealed class BitmapFrameDecode : BitmapFrame { #region Constructors ////// Internal constructor -- Creates new frame using specified decoder /// internal BitmapFrameDecode( int frameNumber, BitmapCreateOptions createOptions, BitmapCacheOption cacheOption, BitmapDecoder decoder ) : base(true) { _bitmapInit.BeginInit(); _frameNumber = frameNumber; _isThumbnailCached = false; _isMetadataCached = false; _frameSource = null; Debug.Assert(decoder != null); _decoder = decoder; _syncObject = decoder.SyncObject; _createOptions = createOptions; _cacheOption = cacheOption; _bitmapInit.EndInit(); if ((createOptions & BitmapCreateOptions.DelayCreation) != 0) { DelayCreation = true; } else { FinalizeCreation(); } } ////// Internal constructor -- Creates frame from another frame /// ////// SecurityCritical: Accesses unmanaged resources (_wicSource) /// SecurityTreatAsSafe: Inputs are verified and _wicSource and the get is Critical /// [SecurityCritical, SecurityTreatAsSafe] internal BitmapFrameDecode( int frameNumber, BitmapCreateOptions createOptions, BitmapCacheOption cacheOption, BitmapFrameDecode frameDecode ) : base(true) { _bitmapInit.BeginInit(); _frameNumber = frameNumber; WicSourceHandle = frameDecode.WicSourceHandle; IsSourceCached = frameDecode.IsSourceCached; CreationCompleted = frameDecode.CreationCompleted; _frameSource = frameDecode._frameSource; _decoder = frameDecode.Decoder; _syncObject = _decoder.SyncObject; _createOptions = createOptions; _cacheOption = cacheOption; _thumbnail = frameDecode._thumbnail; _isThumbnailCached = frameDecode._isThumbnailCached; _metadata = frameDecode._metadata; _isMetadataCached = frameDecode._isMetadataCached; _readOnlycolorContexts = frameDecode._readOnlycolorContexts; _isColorContextCached = frameDecode._isColorContextCached; _bitmapInit.EndInit(); if ((createOptions & BitmapCreateOptions.DelayCreation) != 0) { DelayCreation = true; } else if (!CreationCompleted) { FinalizeCreation(); } else { UpdateCachedSettings(); } } ////// Internal constructor -- Creates frame thats being downloaded /// ////// SecurityCritical: Accesses unmanaged resources (_wicSource) /// SecurityTreatAsSafe: Inputs are verified and _wicSource and the get is Critical /// [SecurityCritical, SecurityTreatAsSafe] internal BitmapFrameDecode( int frameNumber, BitmapCreateOptions createOptions, BitmapCacheOption cacheOption, LateBoundBitmapDecoder decoder ) : base(true) { _bitmapInit.BeginInit(); _frameNumber = frameNumber; byte[] pixels = new byte[4]; BitmapSource source = BitmapSource.Create( 1, 1, 96, 96, PixelFormats.Pbgra32, null, pixels, 4 ); WicSourceHandle = source.WicSourceHandle; Debug.Assert(decoder != null); _decoder = decoder; _createOptions = createOptions; _cacheOption = cacheOption; // // Hook the decoders download events // _decoder.DownloadCompleted += OnDownloadCompleted; _decoder.DownloadProgress += OnDownloadProgress; _decoder.DownloadFailed += OnDownloadFailed; _bitmapInit.EndInit(); } ////// Do not allow construction /// private BitmapFrameDecode() : base(true) { } #endregion #region IUriContext ////// Provides the base uri of the current context. /// public override Uri BaseUri { get { ReadPreamble(); return _decoder._baseUri; } set { WritePreamble(); // Nothing to do here. } } #endregion #region Public Properties ////// Accesses the Thumbnail property for this BitmapFrameDecode /// public override BitmapSource Thumbnail { get { ReadPreamble(); EnsureThumbnail(); return _thumbnail; } } ////// Accesses the Metadata property for this BitmapFrameDecode /// public override ImageMetadata Metadata { get { ReadPreamble(); return InternalMetadata; } } ////// Accesses the Decoder property for this BitmapFrameDecode /// public override BitmapDecoder Decoder { get { ReadPreamble(); return _decoder; } } ////// Used as a delegate in ColorContexts to get the unmanaged IWICColorContexts /// ////// Critical - Calls critical, unmanaged method /// [SecurityCritical] private int GetColorContexts(ref uint numContexts, IntPtr[] colorContextPtrs) { Invariant.Assert(colorContextPtrs == null || numContexts <= colorContextPtrs.Length); return UnsafeNativeMethods.WICBitmapFrameDecode.GetColorContexts(_frameSource, numContexts, colorContextPtrs, out numContexts); } ////// If there is an embedded color profile, return it. /// Otherwise, return null. This method does NOT create a /// color profile for bitmaps that don't already have one. /// ////// Provides access to this encoders color profile /// /// ////// Critical - Access unmanaged code, codecs /// TreatAsSafe - We are exposing specific, non-sensitive data that came from /// a Uri or a bitmap. If the profile data came from a Uri, the /// WebRequest we did to get it demandend the appropriate /// permission and we did not expose the request or response. If it came /// from a bitmap, it may be cross-domain, but the restricted /// nature of the data combined with the fact that it has been /// inspected by WCS which is hardened against malicious data /// makes this OK. /// public override ReadOnlyCollectionColorContexts { [SecurityCritical, SecurityTreatAsSafe] get { ReadPreamble(); if (!_isColorContextCached && !IsDownloading) { EnsureSource(); lock (_syncObject) { IList colorContextList = ColorContext.GetColorContextsHelper(GetColorContexts); if (colorContextList != null) { _readOnlycolorContexts = new ReadOnlyCollection (colorContextList); } _isColorContextCached = true; } } return _readOnlycolorContexts; } } /// /// Returns if the BitmapFrame is downloading content /// public override bool IsDownloading { get { ReadPreamble(); return Decoder.IsDownloading; } } #endregion #region Public Methods ////// Create an in-place bitmap metadata writer. /// public override InPlaceBitmapMetadataWriter CreateInPlaceBitmapMetadataWriter() { ReadPreamble(); if (_decoder != null) { _decoder.CheckOriginalWritable(); } // Demand Site Of Origin on the URI before usage of metadata. CheckIfSiteOfOrigin(); EnsureSource(); return InPlaceBitmapMetadataWriter.CreateFromFrameDecode(_frameSource, _syncObject); } #endregion #region ToString ////// Can serialze "this" to a string /// internal override bool CanSerializeToString() { ReadPreamble(); return _decoder.CanConvertToString(); } ////// Creates a string representation of this object based on the format string /// and IFormatProvider passed in. /// If the provider is null, the CurrentCulture is used. /// See the documentation for IFormattable for more information. /// ////// A string representation of this object. /// internal override string ConvertToString(string format, IFormatProvider provider) { ReadPreamble(); if (_decoder != null) { return _decoder.ToString(); } return base.ConvertToString(format, provider); } #endregion #region Freezable ////// Implementation of ///Freezable.CreateInstanceCore . ///The new Freezable. protected override Freezable CreateInstanceCore() { return new BitmapFrameDecode(); } ////// Copy the fields not covered by DPs. This is used by /// CloneCore(), CloneCurrentValueCore(), GetAsFrozenCore() and /// GetCurrentValueAsFrozenCore(). /// ////// Critical - access critical resources (_metadata) /// TreatAsSafe - All inputs verified /// [SecurityCritical, SecurityTreatAsSafe] private void CopyCommon(BitmapFrameDecode sourceBitmapFrameDecode) { _bitmapInit.BeginInit(); _frameNumber = sourceBitmapFrameDecode._frameNumber; _isThumbnailCached = sourceBitmapFrameDecode._isThumbnailCached; _isMetadataCached = sourceBitmapFrameDecode._isMetadataCached; _isColorContextCached = sourceBitmapFrameDecode._isColorContextCached; _frameSource = sourceBitmapFrameDecode._frameSource; _thumbnail = sourceBitmapFrameDecode._thumbnail; _metadata = sourceBitmapFrameDecode.InternalMetadata; _readOnlycolorContexts = sourceBitmapFrameDecode._readOnlycolorContexts; _decoder = sourceBitmapFrameDecode._decoder; if (_decoder != null && _decoder.IsDownloading) { // UpdateDecoder must be called when download completes and the real decoder // is created. Normally _decoder will call UpdateDecoder, but in this case the // decoder will not know about the cloned BitmapFrameDecode and will only call // UpdateDecoder on the original. The clone will need to listen to the original // BitmapFrameDecode for DownloadCompleted, then call UpdateDecoder on itself. // The weak event sink hooks up handlers on DownloadCompleted, DownloadFailed, // and DownloadProgress _weakBitmapFrameDecodeEventSink = new WeakBitmapFrameDecodeEventSink(this, sourceBitmapFrameDecode); } _syncObject = _decoder.SyncObject; _createOptions = sourceBitmapFrameDecode._createOptions; _cacheOption = sourceBitmapFrameDecode._cacheOption; _bitmapInit.EndInit(); } ////// Implementation of protected override void CloneCore(Freezable sourceFreezable) { BitmapFrameDecode sourceBitmapFrameDecode = (BitmapFrameDecode)sourceFreezable; base.CloneCore(sourceFreezable); CopyCommon(sourceBitmapFrameDecode); } ///Freezable.CloneCore . ////// Implementation of protected override void CloneCurrentValueCore(Freezable sourceFreezable) { BitmapFrameDecode sourceBitmapFrameDecode = (BitmapFrameDecode)sourceFreezable; base.CloneCurrentValueCore(sourceFreezable); CopyCommon(sourceBitmapFrameDecode); } ///Freezable.CloneCurrentValueCore . ////// Implementation of protected override void GetAsFrozenCore(Freezable sourceFreezable) { BitmapFrameDecode sourceBitmapFrameDecode = (BitmapFrameDecode)sourceFreezable; base.GetAsFrozenCore(sourceFreezable); CopyCommon(sourceBitmapFrameDecode); } ///Freezable.GetAsFrozenCore . ////// Implementation of protected override void GetCurrentValueAsFrozenCore(Freezable sourceFreezable) { BitmapFrameDecode sourceBitmapFrameDecode = (BitmapFrameDecode)sourceFreezable; base.GetCurrentValueAsFrozenCore(sourceFreezable); CopyCommon(sourceBitmapFrameDecode); } #endregion #region Internal Properties / Methods ///Freezable.GetCurrentValueAsFrozenCore . ////// Updates the internal decoder -- usually happens with a LateBoundBitmapDecoder /// ////// Critical - access critical resources /// TreatAsSafe - All inputs verified /// [SecurityCritical, SecurityTreatAsSafe] internal void UpdateDecoder(BitmapDecoder decoder) { Debug.Assert(_decoder != null); _decoder = decoder; _syncObject = decoder.SyncObject; WicSourceHandle = null; _needsUpdate = true; FinalizeCreation(); // Trigger a update of the UCE resource RegisterForAsyncUpdateResource(); } ////// Create the unmanaged resources /// ////// Critical - access critical resources /// TreatAsSafe - All inputs verified /// [SecurityCritical, SecurityTreatAsSafe] internal override void FinalizeCreation() { EnsureSource(); // Set the WicSourceHandle and Update the cached settings so that we // can query the source for information such as the palette which we need // to determine if we need to format convert or not. WicSourceHandle = _frameSource; UpdateCachedSettings(); lock (_syncObject) { WicSourceHandle = CreateCachedBitmap(this, _frameSource, _createOptions, _cacheOption, Palette); } IsSourceCached = (_cacheOption != BitmapCacheOption.None); CreationCompleted = true; UpdateCachedSettings(); EnsureThumbnail(); } // // Workaround for a change caused by a bug fix, CopyCommon checks this property when // copying the delegates attached to events. // Default implementation in BitmapSource, see comments in BitmapSource.cs for details. // internal override bool ShouldCloneEventDelegates { get { return false; } } #endregion #region Private Methods /// Fired when the decoder download has completed private void OnDownloadCompleted(object sender, EventArgs e) { // // The sender should be the LateBoundDecoder that we hooked when it was _decoder. // LateBoundBitmapDecoder decoder = (LateBoundBitmapDecoder)sender; // // Unhook the decoders download events // decoder.DownloadCompleted -= OnDownloadCompleted; decoder.DownloadProgress -= OnDownloadProgress; decoder.DownloadFailed -= OnDownloadFailed; FireChanged(); _downloadEvent.InvokeEvents(this, null); } /// Called when download progress is made private void OnDownloadProgress(object sender, DownloadProgressEventArgs e) { _progressEvent.InvokeEvents(this, e); } /// Called when download fails private void OnDownloadFailed(object sender, ExceptionEventArgs e) { // // The sender should be the LateBoundDecoder that we hooked when it was _decoder. // LateBoundBitmapDecoder decoder = (LateBoundBitmapDecoder)sender; // // Unhook the decoders download events // decoder.DownloadCompleted -= OnDownloadCompleted; decoder.DownloadProgress -= OnDownloadProgress; decoder.DownloadFailed -= OnDownloadFailed; _failedEvent.InvokeEvents(this, e); } /// Fired when the original's decoder's download has completed private void OnOriginalDownloadCompleted(BitmapFrameDecode original, EventArgs e) { CleanUpWeakEventSink(); // Update the underlying decoder to match the original's // We already have a _decoder from the cloning, but it's referencing the // LateBoundBitmapDecoder. When download completes, LateBoundBitmapDecoder calls // EnsureDecoder to make the _realDecoder (something like JpegBitmapDecoder), // then calls SetupFrames on the _realDecoder, which calls BitmapFrameDecode's // UpdateDecoder to set _decoder to the JpegBitmapDecoder. So the original's _decoder // changes after download completes, and the clone should change as well. UpdateDecoder(original.Decoder); FireChanged(); _downloadEvent.InvokeEvents(this, e); } /// Called when the original's decoder's download fails private void OnOriginalDownloadFailed(ExceptionEventArgs e) { CleanUpWeakEventSink(); _failedEvent.InvokeEvents(this, e); } private void CleanUpWeakEventSink() { // Unhook the decoders download events _weakBitmapFrameDecodeEventSink.DetachSourceDownloadHandlers(); _weakBitmapFrameDecodeEventSink = null; } ////// Ensure that the thumbnail is created/cached /// ////// Critical - Access unmanaged code, codecs /// TreatAsSafe - Getting thumbnail data is OK /// [SecurityCritical, SecurityTreatAsSafe] 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(); } } } ////// Returns cached metadata and creates BitmapMetadata if it does not exist. /// This code will demand site of origin permissions. /// ////// Critical - Access unmanaged code /// TreatAsSafe - demands site of origin permissions /// internal override BitmapMetadata InternalMetadata { [SecurityCritical, SecurityTreatAsSafe] get { // Demand Site Of Origin on the URI before usage of metadata. CheckIfSiteOfOrigin(); if (!_isMetadataCached && !IsDownloading) { EnsureSource(); IntPtr /* IWICMetadataQueryReader */ metadata = IntPtr.Zero; lock (_syncObject) { // Check if there is embedded metadata or not int hr = UnsafeNativeMethods.WICBitmapFrameDecode.GetMetadataQueryReader( _frameSource, out metadata ); if (hr != (int)WinCodecErrors.WINCODEC_ERR_UNSUPPORTEDOPERATION) { HRESULT.Check(hr); } } if (metadata != IntPtr.Zero) { SafeMILHandle metadataHandle = new SafeMILHandle(metadata); _metadata = new BitmapMetadata(metadataHandle, true, _decoder != null ? _decoder.IsMetadataFixedSize : false, _syncObject); _metadata.Freeze(); } _isMetadataCached = true; } return _metadata; } set { throw new System.NotImplementedException(); } } ////// Ensure that a BitmapSource is created /// ////// Critical - Access unmanaged code, codecs /// TreatAsSafe - Getting frame data is OK /// [SecurityCritical, SecurityTreatAsSafe] 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(); } } } #endregion #region Data Members /// IWICBitmapFrameDecode source private BitmapSourceSafeMILHandle _frameSource = null; /// Frame number private int _frameNumber; /// Is the thumbnail cached private bool _isThumbnailCached; /// Is the metadata cached private bool _isMetadataCached; /// If the ColorContext is already cached private bool _isColorContextCached = false; /// CreateOptions for this Frame private BitmapCreateOptions _createOptions; /// CacheOption for this Frame private BitmapCacheOption _cacheOption; /// Decoder private BitmapDecoder _decoder; #endregion #region WeakBitmapSourceEvents // Used to propagate DownloadCompleted events for cloned BitmapFrameDecodes that are still downloading private WeakBitmapFrameDecodeEventSink _weakBitmapFrameDecodeEventSink; private class WeakBitmapFrameDecodeEventSink : WeakReference { public WeakBitmapFrameDecodeEventSink(BitmapFrameDecode cloned, BitmapFrameDecode original) : base(cloned) { _original = original; if (!_original.IsFrozen) { _original.DownloadCompleted += OnSourceDownloadCompleted; _original.DownloadFailed += OnSourceDownloadFailed; _original.DownloadProgress += OnSourceDownloadProgress; } } public void OnSourceDownloadCompleted(object sender, EventArgs e) { BitmapFrameDecode clone = this.Target as BitmapFrameDecode; if (null != clone) { clone.OnOriginalDownloadCompleted(_original, e); } else { DetachSourceDownloadHandlers(); } } public void OnSourceDownloadFailed(object sender, ExceptionEventArgs e) { BitmapFrameDecode clone = this.Target as BitmapFrameDecode; if (null != clone) { clone.OnOriginalDownloadFailed(e); } else { DetachSourceDownloadHandlers(); } } public void OnSourceDownloadProgress(object sender, DownloadProgressEventArgs e) { BitmapFrameDecode clone = this.Target as BitmapFrameDecode; if (null != clone) { clone.OnDownloadProgress(sender, e); } else { DetachSourceDownloadHandlers(); } } public void DetachSourceDownloadHandlers() { if (!_original.IsFrozen) { _original.DownloadCompleted -= OnSourceDownloadCompleted; _original.DownloadFailed -= OnSourceDownloadFailed; _original.DownloadProgress -= OnSourceDownloadProgress; } } private BitmapFrameDecode _original; } #endregion WeakBitmapSourceEvents } #endregion // BitmapFrameDecode } // File provided for Reference Use Only by Microsoft Corporation (c) 2007. // Copyright (c) Microsoft Corporation. All rights reserved.
Link Menu
This book is available now!
Buy at Amazon US or
Buy at Amazon UK
- XmlWrappingReader.cs
- Propagator.JoinPropagator.cs
- BuildProvider.cs
- ThreadAttributes.cs
- CngAlgorithm.cs
- DrawingBrush.cs
- newinstructionaction.cs
- XmlArrayAttribute.cs
- BoolExpr.cs
- CategoryAttribute.cs
- ToolStripDesignerAvailabilityAttribute.cs
- Rect3D.cs
- BulletedList.cs
- PagesSection.cs
- PersonalizableAttribute.cs
- StrokeNode.cs
- BulletedListDesigner.cs
- ReadOnlyHierarchicalDataSourceView.cs
- CheckedListBox.cs
- XmlSchemaProviderAttribute.cs
- FileDialogPermission.cs
- EntitySqlQueryCacheEntry.cs
- InvalidEnumArgumentException.cs
- TableLayoutPanelCodeDomSerializer.cs
- AQNBuilder.cs
- COM2FontConverter.cs
- EncoderFallback.cs
- UpdateCommandGenerator.cs
- Accessible.cs
- complextypematerializer.cs
- CopyNodeSetAction.cs
- DoubleUtil.cs
- ValueChangedEventManager.cs
- ServiceChannelFactory.cs
- AppSettingsSection.cs
- DataRowChangeEvent.cs
- jithelpers.cs
- TemplatedWizardStep.cs
- Privilege.cs
- DocumentReference.cs
- ToolStripProgressBar.cs
- SerializableAttribute.cs
- SqlAliaser.cs
- ValueConversionAttribute.cs
- MetadataPropertyCollection.cs
- StructuralObject.cs
- RecognizeCompletedEventArgs.cs
- DisableDpiAwarenessAttribute.cs
- XmlStringTable.cs
- StreamMarshaler.cs
- InfoCardRSAOAEPKeyExchangeDeformatter.cs
- DataGridTable.cs
- ItemContainerGenerator.cs
- HoistedLocals.cs
- RemoteWebConfigurationHost.cs
- X509IssuerSerialKeyIdentifierClause.cs
- WindowInteropHelper.cs
- DrawingBrush.cs
- DateTimeHelper.cs
- LocalizableResourceBuilder.cs
- DataSetViewSchema.cs
- WindowsToolbarAsMenu.cs
- EllipseGeometry.cs
- OdbcErrorCollection.cs
- JoinTreeNode.cs
- XamlReaderHelper.cs
- EventLogPermissionEntryCollection.cs
- XmlSchemaComplexContentRestriction.cs
- XmlSchemaAttribute.cs
- PlatformCulture.cs
- DesignerTextBoxAdapter.cs
- RemoteWebConfigurationHostStream.cs
- HttpGetProtocolImporter.cs
- MatrixAnimationBase.cs
- WebPartTracker.cs
- Vector3D.cs
- CodeTypeReference.cs
- updateconfighost.cs
- GridView.cs
- _SingleItemRequestCache.cs
- SemaphoreSecurity.cs
- StrokeCollectionConverter.cs
- XmlSchemaExternal.cs
- BufferedStream.cs
- Propagator.JoinPropagator.cs
- MasterPageParser.cs
- DataColumnMappingCollection.cs
- List.cs
- StringBuilder.cs
- VisualTreeUtils.cs
- XmlBuffer.cs
- TypeConverter.cs
- UrlAuthFailureHandler.cs
- PrintSystemException.cs
- IDQuery.cs
- TraceSource.cs
- TextEditorParagraphs.cs
- ImageDesigner.cs
- SimpleFileLog.cs
- NameValuePair.cs