BitmapFrameDecode.cs source code in C# .NET

Source code for the .NET framework in C#

                        

Code:

/ Dotnetfx_Win7_3.5.1 / Dotnetfx_Win7_3.5.1 / 3.5.1 / DEVDIV / depot / DevDiv / releases / Orcas / NetFXw7 / wpf / src / Core / CSharp / System / Windows / Media / Imaging / BitmapFrameDecode.cs / 1 / 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,
            BitmapSourceSafeMILHandle sourceHandle,
            BitmapCreateOptions createOptions,
            BitmapCacheOption cacheOption, 
            BitmapDecoder decoder
            ) : base(true) 
        { 
            _bitmapInit.BeginInit();
            _frameNumber = frameNumber; 
            _isThumbnailCached = false;
            _isMetadataCached = false;
            _frameSource = sourceHandle;
 
            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;
            } 
        } 

        ///  
        /// 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 - Getting Color Context data is OK
        /// 
        public override ReadOnlyCollection ColorContexts 
        {
            [SecurityCritical, SecurityTreatAsSafe] 
            get 
            {
                ReadPreamble(); 
                if (!_isColorContextCached && !IsDownloading)
                {
                    EnsureSource();
 
                    // Check if there is colorContext or not
                    lock (_syncObject) 
                    { 
                        unsafe
                        { 
                            uint uiCount = 0;

                            int hr = UnsafeNativeMethods.WICBitmapFrameDecode.GetColorContexts(
                                _frameSource, 
                                0,
                                IntPtr.Zero, 
                                out uiCount 
                                );
 
                            if (hr != (int)WinCodecErrors.WINCODEC_ERR_UNSUPPORTEDOPERATION)
                            {
                                HRESULT.Check(hr);
                            } 
                            if (uiCount > 0)
                            { 
                                List colorContextsList = new List((int)uiCount); 

                                IntPtr *pcolorContextslocal = stackalloc IntPtr[(int)uiCount]; 
                                for (int i = 0; i < uiCount; i++) pcolorContextslocal[i] = IntPtr.Zero;

                                SafeMILHandle[] colorContextHandles = new SafeMILHandle[uiCount];
 
                                using (FactoryMaker factoryMaker = new FactoryMaker())
                                { 
                                    try 
                                    {
                                        for (int i = 0; i < uiCount; i++) 
                                        {
                                            Guid wicColorContextGuid = MILGuidData.IID_IWICColorContext;

                                            HRESULT.Check(UnsafeNativeMethods.WICCodec.CreateColorContext(factoryMaker.ImagingFactoryPtr, out colorContextHandles[i])); 

                                            HRESULT.Check(UnsafeNativeMethods.MILUnknown.QueryInterface(colorContextHandles[i], ref wicColorContextGuid, out pcolorContextslocal[i])); 
                                        } 

                                    } 
                                    finally
                                    {
                                        for (int i = 0; i < uiCount; i++)
                                        { 
                                            #pragma warning suppress 6031
                                            UnsafeNativeMethods.MILUnknown.Release(pcolorContextslocal[i]); 
                                        } 
                                    }
 
                                    HRESULT.Check(UnsafeNativeMethods.WICBitmapFrameDecode.GetColorContexts(
                                        _frameSource,
                                        uiCount,
                                        (IntPtr)pcolorContextslocal, 
                                        out uiCount
                                        )); 
                                } 
                                for (uint i = 0; i < uiCount; i++)
                                { 
                                    colorContextsList.Add(new ColorContext(colorContextHandles[i]));
                                }

                                _readOnlycolorContexts = new ReadOnlyCollection(colorContextsList); 

                            } 
                        } 

                        _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;
            _syncObject = _decoder.SyncObject; 
            _createOptions = sourceBitmapFrameDecode._createOptions;
            _cacheOption = sourceBitmapFrameDecode._cacheOption;
            _bitmapInit.EndInit();
        } 

        ///  
        /// Implementation of Freezable.CloneCore. 
        /// 
        protected override void CloneCore(Freezable sourceFreezable) 
        {
            BitmapFrameDecode sourceBitmapFrameDecode = (BitmapFrameDecode)sourceFreezable;
            base.CloneCore(sourceFreezable);
 
            CopyCommon(sourceBitmapFrameDecode);
        } 
 
        /// 
        /// Implementation of Freezable.CloneCurrentValueCore. 
        /// 
        protected override void CloneCurrentValueCore(Freezable sourceFreezable)
        {
            BitmapFrameDecode sourceBitmapFrameDecode = (BitmapFrameDecode)sourceFreezable; 
            base.CloneCurrentValueCore(sourceFreezable);
 
            CopyCommon(sourceBitmapFrameDecode); 
        }
 

        /// 
        /// Implementation of Freezable.GetAsFrozenCore.
        ///  
        protected override void GetAsFrozenCore(Freezable sourceFreezable)
        { 
            BitmapFrameDecode sourceBitmapFrameDecode = (BitmapFrameDecode)sourceFreezable; 
            base.GetAsFrozenCore(sourceFreezable);
 
            CopyCommon(sourceBitmapFrameDecode);
        }

 
        /// 
        /// Implementation of Freezable.GetCurrentValueAsFrozenCore. 
        ///  
        protected override void GetCurrentValueAsFrozenCore(Freezable sourceFreezable)
        { 
            BitmapFrameDecode sourceBitmapFrameDecode = (BitmapFrameDecode)sourceFreezable;
            base.GetCurrentValueAsFrozenCore(sourceFreezable);

            CopyCommon(sourceBitmapFrameDecode); 
        }
 
        #endregion 

        #region Internal Properties / Methods 

        /// 
        /// 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();
        } 
 
        #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); 
        }
 
        /// 
        /// 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, 0); 

                        _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);
                } 
            }
        } 
 
        #endregion
 
        #region Internal Abstract

        /// Need to implement this to derive from the "sealed" object
        internal override void SealObject() 
        {
            throw new NotImplementedException(); 
        } 

        #endregion 

        #region Data Members

        /// Frame number 
        private int _frameNumber;
 
        /// Is the thumbnail cached 
        internal bool _isThumbnailCached;
 
        /// Is the metadata cached
        internal bool _isMetadataCached;

        /// If the ColorContext is already cached 
        internal bool _isColorContextCached = false;
 
        /// CreateOptions for this Frame 
        private BitmapCreateOptions _createOptions;
 
        /// CacheOption for this Frame
        private BitmapCacheOption _cacheOption;

        #endregion 
    }
 
    #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,
            BitmapSourceSafeMILHandle sourceHandle,
            BitmapCreateOptions createOptions,
            BitmapCacheOption cacheOption, 
            BitmapDecoder decoder
            ) : base(true) 
        { 
            _bitmapInit.BeginInit();
            _frameNumber = frameNumber; 
            _isThumbnailCached = false;
            _isMetadataCached = false;
            _frameSource = sourceHandle;
 
            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;
            } 
        } 

        ///  
        /// 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 - Getting Color Context data is OK
        /// 
        public override ReadOnlyCollection ColorContexts 
        {
            [SecurityCritical, SecurityTreatAsSafe] 
            get 
            {
                ReadPreamble(); 
                if (!_isColorContextCached && !IsDownloading)
                {
                    EnsureSource();
 
                    // Check if there is colorContext or not
                    lock (_syncObject) 
                    { 
                        unsafe
                        { 
                            uint uiCount = 0;

                            int hr = UnsafeNativeMethods.WICBitmapFrameDecode.GetColorContexts(
                                _frameSource, 
                                0,
                                IntPtr.Zero, 
                                out uiCount 
                                );
 
                            if (hr != (int)WinCodecErrors.WINCODEC_ERR_UNSUPPORTEDOPERATION)
                            {
                                HRESULT.Check(hr);
                            } 
                            if (uiCount > 0)
                            { 
                                List colorContextsList = new List((int)uiCount); 

                                IntPtr *pcolorContextslocal = stackalloc IntPtr[(int)uiCount]; 
                                for (int i = 0; i < uiCount; i++) pcolorContextslocal[i] = IntPtr.Zero;

                                SafeMILHandle[] colorContextHandles = new SafeMILHandle[uiCount];
 
                                using (FactoryMaker factoryMaker = new FactoryMaker())
                                { 
                                    try 
                                    {
                                        for (int i = 0; i < uiCount; i++) 
                                        {
                                            Guid wicColorContextGuid = MILGuidData.IID_IWICColorContext;

                                            HRESULT.Check(UnsafeNativeMethods.WICCodec.CreateColorContext(factoryMaker.ImagingFactoryPtr, out colorContextHandles[i])); 

                                            HRESULT.Check(UnsafeNativeMethods.MILUnknown.QueryInterface(colorContextHandles[i], ref wicColorContextGuid, out pcolorContextslocal[i])); 
                                        } 

                                    } 
                                    finally
                                    {
                                        for (int i = 0; i < uiCount; i++)
                                        { 
                                            #pragma warning suppress 6031
                                            UnsafeNativeMethods.MILUnknown.Release(pcolorContextslocal[i]); 
                                        } 
                                    }
 
                                    HRESULT.Check(UnsafeNativeMethods.WICBitmapFrameDecode.GetColorContexts(
                                        _frameSource,
                                        uiCount,
                                        (IntPtr)pcolorContextslocal, 
                                        out uiCount
                                        )); 
                                } 
                                for (uint i = 0; i < uiCount; i++)
                                { 
                                    colorContextsList.Add(new ColorContext(colorContextHandles[i]));
                                }

                                _readOnlycolorContexts = new ReadOnlyCollection(colorContextsList); 

                            } 
                        } 

                        _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;
            _syncObject = _decoder.SyncObject; 
            _createOptions = sourceBitmapFrameDecode._createOptions;
            _cacheOption = sourceBitmapFrameDecode._cacheOption;
            _bitmapInit.EndInit();
        } 

        ///  
        /// Implementation of Freezable.CloneCore. 
        /// 
        protected override void CloneCore(Freezable sourceFreezable) 
        {
            BitmapFrameDecode sourceBitmapFrameDecode = (BitmapFrameDecode)sourceFreezable;
            base.CloneCore(sourceFreezable);
 
            CopyCommon(sourceBitmapFrameDecode);
        } 
 
        /// 
        /// Implementation of Freezable.CloneCurrentValueCore. 
        /// 
        protected override void CloneCurrentValueCore(Freezable sourceFreezable)
        {
            BitmapFrameDecode sourceBitmapFrameDecode = (BitmapFrameDecode)sourceFreezable; 
            base.CloneCurrentValueCore(sourceFreezable);
 
            CopyCommon(sourceBitmapFrameDecode); 
        }
 

        /// 
        /// Implementation of Freezable.GetAsFrozenCore.
        ///  
        protected override void GetAsFrozenCore(Freezable sourceFreezable)
        { 
            BitmapFrameDecode sourceBitmapFrameDecode = (BitmapFrameDecode)sourceFreezable; 
            base.GetAsFrozenCore(sourceFreezable);
 
            CopyCommon(sourceBitmapFrameDecode);
        }

 
        /// 
        /// Implementation of Freezable.GetCurrentValueAsFrozenCore. 
        ///  
        protected override void GetCurrentValueAsFrozenCore(Freezable sourceFreezable)
        { 
            BitmapFrameDecode sourceBitmapFrameDecode = (BitmapFrameDecode)sourceFreezable;
            base.GetCurrentValueAsFrozenCore(sourceFreezable);

            CopyCommon(sourceBitmapFrameDecode); 
        }
 
        #endregion 

        #region Internal Properties / Methods 

        /// 
        /// 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();
        } 
 
        #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); 
        }
 
        /// 
        /// 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, 0); 

                        _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);
                } 
            }
        } 
 
        #endregion
 
        #region Internal Abstract

        /// Need to implement this to derive from the "sealed" object
        internal override void SealObject() 
        {
            throw new NotImplementedException(); 
        } 

        #endregion 

        #region Data Members

        /// Frame number 
        private int _frameNumber;
 
        /// Is the thumbnail cached 
        internal bool _isThumbnailCached;
 
        /// Is the metadata cached
        internal bool _isMetadataCached;

        /// If the ColorContext is already cached 
        internal bool _isColorContextCached = false;
 
        /// CreateOptions for this Frame 
        private BitmapCreateOptions _createOptions;
 
        /// CacheOption for this Frame
        private BitmapCacheOption _cacheOption;

        #endregion 
    }
 
    #endregion // BitmapFrameDecode 
}
 

// File provided for Reference Use Only by Microsoft Corporation (c) 2007.
// Copyright (c) Microsoft Corporation. All rights reserved.

                        

Link Menu

Network programming in C#, Network Programming in VB.NET, Network Programming in .NET
This book is available now!
Buy at Amazon US or
Buy at Amazon UK