Code:
                         / Net / Net / 3.5.50727.3053 / DEVDIV / depot / DevDiv / releases / Orcas / SP / wpf / src / Core / CSharp / System / Windows / Media / Imaging / BitmapEncoder.cs / 1 / BitmapEncoder.cs
                        
                        
                            //------------------------------------------------------------------------------ 
//  Copyright (c) Microsoft Corporation, 2003
//
//  File: BitmapEncoder.cs
// 
//-----------------------------------------------------------------------------
 
using System; 
using System.Collections.Generic;
using System.Collections.ObjectModel; 
using System.ComponentModel;
using System.ComponentModel.Design.Serialization;
using System.Reflection;
using System.IO; 
using MS.Internal;
using System.Diagnostics; 
using System.Windows.Media; 
using System.Windows.Threading;
using System.Globalization; 
using System.Runtime.InteropServices;
using System.Windows.Media.Imaging;
using System.Security;
using System.Security.Permissions; 
using MS.Win32.PresentationCore;
using SR=MS.Internal.PresentationCore.SR; 
using SRID=MS.Internal.PresentationCore.SRID; 
using System.Diagnostics.CodeAnalysis;
 
#pragma warning disable 1634, 1691  // suppressing PreSharp warnings
namespace System.Windows.Media.Imaging
{ 
    #region PROPBAG2
 
    [StructLayout(LayoutKind.Sequential, Pack=1)] 
    internal struct PROPBAG2
    { 
        internal UInt32 dwType;
        internal ushort vt;
        internal ushort cfType;
        internal IntPtr dwHint; 
        [SecurityCritical] 
        internal IntPtr pstrName; //this is string array 
        internal Guid clsid; 
        /// 
        /// Critical -Initializes a pointer to unmanaged memory to hold onto a string
        /// TreatAsSafe - there are no inputs 
        ///  
        [SecurityCritical, SecurityTreatAsSafe] 
        internal void Init(String name) 
        {
            pstrName = Marshal.StringToCoTaskMemUni(name); 
        }
        /// 
        /// Critical -Releases an unmanaged pointer into unmanaged memory. 
        /// TreatAsSafe - there are no inputs
        ///   
        [SecurityCritical, SecurityTreatAsSafe] 
        internal void Clear()
        { 
            Marshal.FreeCoTaskMem(pstrName);
            pstrName = IntPtr.Zero;
        }
    } 
    #endregion 
 
    #region BitmapEncoder
 
    /// 
    /// BitmapEncoder collects a set of frames (BitmapSource's) with their associated
    /// thumbnails and saves them to a specified stream.  In addition
    /// to frame-specific thumbnails, there can also be an bitmap-wide 
    /// (global) thumbnail, if the codec supports it.
    ///   
    public abstract class BitmapEncoder : DispatcherObject 
    {
        #region Constructors 
        /// 
        /// Constructor.
        ///   
        protected BitmapEncoder()
        { 
        } 
        ///  
        /// Internal Constructor.
        ///  
        internal BitmapEncoder(bool isBuiltIn)
        { 
            _isBuiltIn = isBuiltIn;
        } 
 
        /// 
        /// Creates a BitmapEncoder from a container format Guid 
        ///  
        /// Container format for the codec
        /// 
        /// Critical - guid used for creation of critical resources 
        ///  
        [SecurityCritical] 
        public static BitmapEncoder Create(Guid containerFormat) 
        {
            if (containerFormat == Guid.Empty) 
            {
                throw new ArgumentException(
                    SR.Get(SRID.Image_GuidEmpty, "containerFormat"),
                    "containerFormat" 
                    );
            } 
            else if (containerFormat == MILGuidData.GUID_ContainerFormatBmp) 
            {
                return new BmpBitmapEncoder(); 
            }
            else if (containerFormat == MILGuidData.GUID_ContainerFormatGif)
            {
                return new GifBitmapEncoder(); 
            }
            else if (containerFormat == MILGuidData.GUID_ContainerFormatJpeg) 
            { 
                return new JpegBitmapEncoder();
            } 
            else if (containerFormat == MILGuidData.GUID_ContainerFormatPng)
            {
                return new PngBitmapEncoder();
            } 
            else if (containerFormat == MILGuidData.GUID_ContainerFormatTiff)
            { 
                return new TiffBitmapEncoder(); 
            }
            else if (containerFormat == MILGuidData.GUID_ContainerFormatWmp) 
            {
                return new WmpBitmapEncoder();
            }
            else 
            {
                return new UnknownBitmapEncoder(containerFormat); 
            } 
        }
 
        #endregion
        #region Public Properties
 
        /// 
        /// Set or get the bitmap's color profile. 
        ///   
        public virtual ReadOnlyCollection ColorContexts
        { 
            get
            {
                VerifyAccess();
                EnsureBuiltIn(); 
                return _readOnlycolorContexts;
            } 
            set 
            {
                VerifyAccess(); 
                EnsureBuiltIn();
                if (value == null)
                { 
                    throw new ArgumentNullException("value");
                } 
 
                if (!_supportsColorContext)
                { 
                    throw new InvalidOperationException(SR.Get(SRID.Image_EncoderNoColorContext));
                }
                _readOnlycolorContexts = value; 
            }
        } 
 
        /// 
        /// Set or get the bitmap's global embedded thumbnail. 
        ///  
        public virtual BitmapSource Thumbnail
        {
            get 
            {
                VerifyAccess(); 
                EnsureBuiltIn(); 
                return _thumbnail;
            } 
            set
            {
                VerifyAccess();
                EnsureBuiltIn(); 
                if (value == null) 
                { 
                    throw new ArgumentNullException("value");
                } 
                if (!_supportsGlobalThumbnail)
                {
                    throw new InvalidOperationException(SR.Get(SRID.Image_EncoderNoGlobalThumbnail)); 
                }
 
                _thumbnail = value; 
            }
        } 
        /// 
        /// Set or get the bitmap's global embedded metadata.
        ///   
        public virtual BitmapMetadata Metadata
        { 
            get 
            {
                VerifyAccess(); 
                EnsureBuiltIn();
                EnsureMetadata(true);
                return _metadata; 
            }
            set 
            { 
                VerifyAccess();
                EnsureBuiltIn(); 
                if (value == null)
                {
                    throw new ArgumentNullException("value"); 
                }
 
                if (value.GuidFormat != ContainerFormat) 
                {
                    throw new InvalidOperationException(SR.Get(SRID.Image_MetadataNotCompatible)); 
                }
                if (!_supportsGlobalMetadata)
                { 
                    throw new InvalidOperationException(SR.Get(SRID.Image_EncoderNoGlobalMetadata));
                } 
 
                _metadata = value;
            } 
        }
        /// 
        /// Set or get the bitmap's global preview 
        ///  
        public virtual BitmapSource Preview 
        { 
            get
            { 
                VerifyAccess();
                EnsureBuiltIn();
                return _preview;
            } 
            set
            { 
                VerifyAccess(); 
                EnsureBuiltIn();
 
                if (value == null)
                {
                    throw new ArgumentNullException("value");
                } 
                if (!_supportsPreview) 
                { 
                    throw new InvalidOperationException(SR.Get(SRID.Image_EncoderNoPreview));
                } 
                _preview = value;
            }
        } 
        ///  
        /// The info that identifies this codec. 
        ///  
        ///  
        /// Critical - Access unmanaged code, codecs
        /// PublicOK - Getting codecinfo data is OK
        ///  
        public virtual BitmapCodecInfo CodecInfo 
        {
            [SecurityCritical ] 
            get 
            {
                VerifyAccess(); 
                EnsureBuiltIn();
                EnsureUnmanagedEncoder();
                // There should always be a codec info. 
                if (_codecInfo == null)
                { 
                    SafeMILHandle /* IWICBitmapEncoderInfo */ codecInfoHandle =  new SafeMILHandle(); 
                    HRESULT.Check(UnsafeNativeMethods.WICBitmapEncoder.GetEncoderInfo( 
                        _encoderHandle,
                        out codecInfoHandle
                        ));
 
                    _codecInfo = new BitmapCodecInfoInternal(codecInfoHandle);
                } 
 
                return _codecInfo;
            } 
        }
        /// 
        /// Provides access to this bitmap's palette 
        ///  
        public virtual BitmapPalette Palette 
        { 
            get
            { 
                VerifyAccess();
                EnsureBuiltIn();
                return _palette;
            } 
            set
            { 
                VerifyAccess(); 
                EnsureBuiltIn();
 
                if (value == null)
                {
                    throw new ArgumentNullException("value");
                } 
                _palette = value; 
            } 
        }
 
        /// 
        /// Access to the individual frames.
        ///  
        public virtual IList Frames 
        {
            get 
            { 
                VerifyAccess();
                EnsureBuiltIn(); 
                if (_frames == null)
                {
                    _frames = new List(0);
                } 
                return _frames; 
            } 
            set
            { 
                VerifyAccess();
                EnsureBuiltIn();
                if (value == null) 
                {
                    throw new ArgumentNullException("value"); 
                } 
                _frames = value; 
            }
        }
        #endregion 
        #region Public Methods 
 
        /// 
        /// Save (encode) the bitmap to the specified stream. 
        ///  
        /// Stream to save into
        /// 
        /// Critical - calls unmanaged code 
        ///  
        [SecurityPermission(SecurityAction.LinkDemand, Flags=SecurityPermissionFlag.UnmanagedCode)] 
        [SecurityPermission(SecurityAction.InheritanceDemand, Flags=SecurityPermissionFlag.UnmanagedCode)] 
        [SecurityCritical]
        public virtual void Save(System.IO.Stream stream) 
        {
            VerifyAccess();
            EnsureBuiltIn();
            EnsureUnmanagedEncoder(); 
            // No-op to get rid of build error 
            if (_encodeState == EncodeState.None) 
            {
            } 
            if (_hasSaved)
            {
                throw new InvalidOperationException(SR.Get(SRID.Image_OnlyOneSave)); 
            }
 
            if (_frames == null) 
            {
                throw new System.NotSupportedException(SR.Get(SRID.Image_NoFrames, null)); 
            }
            int count = _frames.Count;
            if (count <= 0) 
            {
                throw new System.NotSupportedException(SR.Get(SRID.Image_NoFrames, null)); 
            } 
            IntPtr comStream = IntPtr.Zero; 
            SafeMILHandle encoderHandle = _encoderHandle;
            try
            { 
                comStream = StreamAsIStream.IStreamFrom(stream);
 
                // does this addref the stream? 
                HRESULT.Check(UnsafeNativeMethods.WICBitmapEncoder.Initialize(
                    encoderHandle, 
                    comStream,
                    WICBitmapEncodeCacheOption.WICBitmapEncodeNoCache
                    ));
 
                // Helpful for debugging stress and remote dumps
                _encodeState = EncodeState.EncoderInitialized; 
 
                // Save global thumbnail if any.
                if (_thumbnail != null) 
                {
                    Debug.Assert(_supportsGlobalThumbnail);
                    SafeMILHandle thumbnailBitmapSource = _thumbnail.WicSourceHandle;
 
                    lock (_thumbnail.SyncObject)
                    { 
                        HRESULT.Check(UnsafeNativeMethods.WICBitmapEncoder.SetThumbnail( 
                            encoderHandle,
                            thumbnailBitmapSource 
                            ));
                        // Helpful for debugging stress and remote dumps
                        _encodeState = EncodeState.EncoderThumbnailSet; 
                    }
                } 
 
                // Save global palette if any.
                if (_palette != null && _palette.Colors.Count > 0) 
                {
                    SafeMILHandle paletteHandle = _palette.InternalPalette;
                    HRESULT.Check(UnsafeNativeMethods.WICBitmapEncoder.SetPalette( 
                        encoderHandle,
                        paletteHandle 
                        )); 
                    // Helpful for debugging stress and remote dumps 
                    _encodeState = EncodeState.EncoderPaletteSet;
                }
                // Save global metadata if any. 
                if (_metadata != null && _metadata.GuidFormat == ContainerFormat)
                { 
                    Debug.Assert(_supportsGlobalMetadata); 
                    EnsureMetadata(false); 
                    if (_metadata.InternalMetadataHandle != _metadataHandle)
                    {
                        PROPVARIANT propVar = new PROPVARIANT(); 
                        try 
                        { 
                            propVar.Init(_metadata);
 
                            lock (_metadata.SyncObject)
                            {
                                HRESULT.Check(UnsafeNativeMethods.WICMetadataQueryWriter.SetMetadataByName(
                                    _metadataHandle, 
                                    "/",
                                    ref propVar 
                                    )); 
                            }
                        } 
                        finally
                        {
                            propVar.Clear();
                        } 
                    }
                } 
 
                for (int i = 0; i < count; i++)
                { 
                    SafeMILHandle frameEncodeHandle = new SafeMILHandle();
                    SafeMILHandle encoderOptions = new SafeMILHandle();
                    HRESULT.Check(UnsafeNativeMethods.WICBitmapEncoder.CreateNewFrame(
                        encoderHandle, 
                        out frameEncodeHandle,
                        out encoderOptions 
                        )); 
                    // Helpful for debugging stress and remote dumps 
                    _encodeState = EncodeState.EncoderCreatedNewFrame;
                    _frameHandles.Add(frameEncodeHandle);
                    SaveFrame(frameEncodeHandle, encoderOptions, _frames[i]); 
                    // If multiple frames are not supported, break out 
                    if (!_supportsMultipleFrames) 
                    {
                        break; 
                    }
                }
                // Now let the encoder know we are done encoding the file. 
                HRESULT.Check(UnsafeNativeMethods.WICBitmapEncoder.Commit(encoderHandle));
 
                // Helpful for debugging stress and remote dumps 
                _encodeState = EncodeState.EncoderCommitted;
            } 
            finally
            {
                UnsafeNativeMethods.MILUnknown.ReleaseInterface(ref comStream);
            } 
            _hasSaved = true; 
        } 
        #endregion 
        #region Internal Properties / Methods
        ///  
        /// Returns the container format for this encoder
        ///   
        internal virtual Guid ContainerFormat 
        {
            get 
            {
                return Guid.Empty;
            }
        } 
        ///  
        /// Returns whether metadata is fixed size or not. 
        ///  
        internal virtual bool IsMetadataFixedSize 
        {
            get
            {
                return false; 
            }
        } 
 
        /// 
        /// Setups the encoder and other properties before encoding each frame 
        ///  
        internal virtual void SetupFrame(SafeMILHandle frameEncodeHandle, SafeMILHandle encoderOptions)
        {
            throw new NotImplementedException(); 
        }
 
        #endregion 
        #region Private Methods 
        /// 
        /// Checks to see if encoder is built in.
        ///   
        private void EnsureBuiltIn()
        { 
            if (!_isBuiltIn) 
            {
                throw new NotImplementedException(); 
            }
        }
        ///  
        /// Checks to see if encoder has built-in metadata.
        ///   
        ///  
        /// Critical - Accesses unmanaged code
        /// TreatAsSafe - inputs are verified or safe 
        ///  
        [SecurityCritical, SecurityTreatAsSafe]
        private void EnsureMetadata(bool createBitmapMetadata)
        { 
            if (!_supportsGlobalMetadata)
            { 
                return; 
            }
 
            if (_metadataHandle == null)
            {
                SafeMILHandle /* IWICMetadataQueryWriter */ metadataHandle = new SafeMILHandle();
 
                int hr = UnsafeNativeMethods.WICBitmapEncoder.GetMetadataQueryWriter(
                    _encoderHandle, 
                    out metadataHandle 
                    );
 
                if (hr == (int)WinCodecErrors.WINCODEC_ERR_UNSUPPORTEDOPERATION)
                {
                    _supportsGlobalMetadata = false;
                    return; 
                }
                HRESULT.Check(hr); 
 
                _metadataHandle = metadataHandle;
            } 
            if (createBitmapMetadata &&
                _metadata == null &&
                _metadataHandle != null) 
            {
                _metadata = new BitmapMetadata(_metadataHandle, false, IsMetadataFixedSize, _metadataHandle); 
            } 
        }
 
        /// 
        /// Creates the unmanaged encoder object
        ///  
        ///  
        /// Critical - calls unmanaged code, codecs, creates codec based on GUID
        ///   
        [SecurityCritical] 
        private void EnsureUnmanagedEncoder()
        { 
            if (_encoderHandle == null)
            {
                using (FactoryMaker myFactory = new FactoryMaker())
                { 
                    SafeMILHandle encoderHandle = null;
 
                    Guid vendorMicrosoft = new Guid(MILGuidData.GUID_VendorMicrosoft); 
                    Guid containerFormat = ContainerFormat;
 
                    HRESULT.Check(UnsafeNativeMethods.WICImagingFactory.CreateEncoder(
                                myFactory.ImagingFactoryPtr,
                                ref containerFormat,
                                ref vendorMicrosoft, 
                                out encoderHandle
                                )); 
 
                    _encoderHandle = encoderHandle;
                } 
            }
        }
        ///  
        /// Save the frame
        ///   
        ///  
        /// Critical - calls unmanaged code
        ///   
        [SecurityCritical]
        private void SaveFrame(SafeMILHandle frameEncodeHandle, SafeMILHandle encoderOptions, BitmapFrame frame)
        {
            SetupFrame(frameEncodeHandle, encoderOptions); 
            // Helpful for debugging stress and remote dumps 
            _encodeState = EncodeState.FrameEncodeInitialized; 
            // Set the size 
            HRESULT.Check(UnsafeNativeMethods.WICBitmapFrameEncode.SetSize(
                frameEncodeHandle,
                frame.PixelWidth,
                frame.PixelHeight 
                ));
 
            // Helpful for debugging stress and remote dumps 
            _encodeState = EncodeState.FrameEncodeSizeSet;
 
            // Set the resolution
            double dpiX = frame.DpiX;
            double dpiY = frame.DpiY;
 
            if (dpiX <= 0)
            { 
                dpiX = 96; 
            }
            if (dpiY <= 0) 
            {
                dpiY = 96;
            }
 
            HRESULT.Check(UnsafeNativeMethods.WICBitmapFrameEncode.SetResolution(
                frameEncodeHandle, 
                dpiX, 
                dpiY
                )); 
            // Helpful for debugging stress and remote dumps
            _encodeState = EncodeState.FrameEncodeResolutionSet;
 
            if (_supportsFrameThumbnails)
            { 
                // Set the thumbnail. 
                BitmapSource thumbnail = frame.Thumbnail;
 
                if (thumbnail != null)
                {
                    SafeMILHandle thumbnailHandle = thumbnail.WicSourceHandle;
 
                    lock (thumbnail.SyncObject)
                    { 
                        HRESULT.Check(UnsafeNativeMethods.WICBitmapFrameEncode.SetThumbnail( 
                            frameEncodeHandle,
                            thumbnailHandle 
                            ));
                        // Helpful for debugging stress and remote dumps
                        _encodeState = EncodeState.FrameEncodeThumbnailSet; 
                    }
                } 
            } 
            //if the source has been color corrected, we want to use a corresponding color profile 
            if (frame._isColorCorrected)
            {
                unsafe
                { 
                    IntPtr* pcolorContextslocal = stackalloc IntPtr[1];
                    pcolorContextslocal[0] = IntPtr.Zero; 
 
                    try
                    { 
                        Guid wicColorContextGuid = MILGuidData.IID_IWICColorContext;
                        ColorContext colorContext = new ColorContext(frame.Format);
                        HRESULT.Check(UnsafeNativeMethods.MILUnknown.QueryInterface(colorContext.ColorContextHandle, ref wicColorContextGuid, out pcolorContextslocal[0])); 
                        int hr = UnsafeNativeMethods.WICBitmapFrameEncode.SetColorContexts( 
                            frameEncodeHandle, 
                            (uint)1,
                            (IntPtr)pcolorContextslocal 
                            );
                        // It's possible that some encoders may not support color contexts
                        if (hr == HRESULT.S_OK) 
                        {
                            // Helpful for debugging stress and remote dumps 
                            _encodeState = EncodeState.FrameEncodeColorContextsSet; 
                        }
                    } 
                    finally
                    {
                        #pragma warning suppress 6031
                        UnsafeNativeMethods.MILUnknown.Release(pcolorContextslocal[0]); 
                    }
 
                } 
            }
            // if the caller has explicitly provided color context(s), add it/them to the encoder 
            else if ((frame.ColorContexts != null) && (frame.ColorContexts.Count > 0))
            {
                unsafe
                { 
                    int iCount = frame.ColorContexts.Count;
 
                    IntPtr* pcolorContextslocal = stackalloc IntPtr[iCount]; 
                    for (int i = 0; i < iCount; i++) pcolorContextslocal[i] = IntPtr.Zero;
 
                    try
                    {
                        for (int i = 0; i < iCount; i++)
                        { 
                            Guid wicColorContextGuid = MILGuidData.IID_IWICColorContext;
 
                            HRESULT.Check(UnsafeNativeMethods.MILUnknown.QueryInterface(frame.ColorContexts[i].ColorContextHandle, ref wicColorContextGuid, out pcolorContextslocal[i])); 
                        }
 
                        int hr = UnsafeNativeMethods.WICBitmapFrameEncode.SetColorContexts(
                            frameEncodeHandle,
                            (uint)iCount,
                            (IntPtr)pcolorContextslocal 
                            );
 
 
                        // It's possible that some encoders may not support color contexts
                        if (hr == HRESULT.S_OK) 
                        {
                            // Helpful for debugging stress and remote dumps
                            _encodeState = EncodeState.FrameEncodeColorContextsSet;
                        } 
                    }
                    finally 
                    { 
                        for (int i = 0; i < iCount; i++)
                        { 
                            #pragma warning suppress 6031
                            UnsafeNativeMethods.MILUnknown.Release(pcolorContextslocal[i]);
                        }
                    } 
                } 
            } 
            // Set the pixel format and palette 
            lock (frame.SyncObject)
            {
                SafeMILHandle outSourceHandle = new SafeMILHandle(); 
                SafeMILHandle bitmapSourceHandle = frame.WicSourceHandle;
                SafeMILHandle paletteHandle = new SafeMILHandle(); 
 
                // Set the pixel format and palette of the bitmap.
                // This could (but hopefully won't) introduce a format converter. 
                HRESULT.Check(UnsafeNativeMethods.WICCodec.WICSetEncoderFormat(
                    bitmapSourceHandle,
                    paletteHandle,
                    frameEncodeHandle, 
                    out outSourceHandle
                    )); 
 
                // Helpful for debugging stress and remote dumps
                _encodeState = EncodeState.FrameEncodeFormatSet; 
                _writeSourceHandles.Add(outSourceHandle);
                // Set the metadata
                if (_supportsFrameMetadata) 
                {
                    BitmapMetadata metadata = frame.Metadata as BitmapMetadata; 
 
                    // If the frame has metadata associated with a different container format, then we ignore it.
                    if (metadata != null && metadata.GuidFormat == ContainerFormat) 
                    {
                        SafeMILHandle /* IWICMetadataQueryWriter */ metadataHandle = new SafeMILHandle();
                        HRESULT.Check(UnsafeNativeMethods.WICBitmapFrameEncode.GetMetadataQueryWriter( 
                            frameEncodeHandle,
                            out metadataHandle 
                            )); 
                        PROPVARIANT propVar = new PROPVARIANT(); 
                        try
                        {
                            propVar.Init(metadata); 
                            lock (metadata.SyncObject) 
                            { 
                                HRESULT.Check(UnsafeNativeMethods.WICMetadataQueryWriter.SetMetadataByName(
                                    metadataHandle, 
                                    "/",
                                    ref propVar
                                    ));
 
                                // Helpful for debugging stress and remote dumps
                                _encodeState = EncodeState.FrameEncodeMetadataSet; 
                            } 
                        }
                        finally 
                        {
                            propVar.Clear();
                        }
                    } 
                }
 
                Int32Rect r = new Int32Rect(); 
                HRESULT.Check(UnsafeNativeMethods.WICBitmapFrameEncode.WriteSource(
                    frameEncodeHandle, 
                    outSourceHandle,
                    ref r
                    ));
 
                // Helpful for debugging stress and remote dumps
                _encodeState = EncodeState.FrameEncodeSourceWritten; 
 
                HRESULT.Check(UnsafeNativeMethods.WICBitmapFrameEncode.Commit(
                    frameEncodeHandle 
                    ));
                // Helpful for debugging stress and remote dumps
                _encodeState = EncodeState.FrameEncodeCommitted; 
            }
        } 
 
        #endregion
 
        #region Internal Abstract
        /// "Seals" the object
        internal abstract void SealObject(); 
        #endregion 
 
        #region Data Members
 
        /// does encoder support a preview?
        internal bool _supportsPreview = true;
        /// does encoder support a global thumbnail? 
        internal bool _supportsGlobalThumbnail = true;
 
        /// does encoder support a global metadata? 
        internal bool _supportsGlobalMetadata = true;
 
        /// does encoder support per frame thumbnails?
        internal bool _supportsFrameThumbnails = true;
        /// does encoder support per frame thumbnails? 
        internal bool _supportsFrameMetadata = true;
 
        /// does encoder support multiple frames? 
        internal bool _supportsMultipleFrames = false;
 
        /// does encoder support color context?
        internal bool _supportsColorContext = false;
        /// is it a built in encoder 
        private bool _isBuiltIn;
 
        /// Internal WIC encoder handle 
        private SafeMILHandle _encoderHandle;
 
        /// metadata
        private BitmapMetadata _metadata;
        /// Internal WIC metadata handle 
        private SafeMILHandle _metadataHandle;
 
        /// colorcontext 
        private ReadOnlyCollection _readOnlycolorContexts;
 
        /// codecinfo
        private BitmapCodecInfoInternal _codecInfo;
        /// thumbnail 
        private BitmapSource _thumbnail;
 
        /// preview 
        private BitmapSource _preview;
 
        /// palette
        private BitmapPalette _palette;
        /// frames 
        private IList _frames;
 
        /// true if Save has been called. 
        private bool _hasSaved;
 
        /// The below data members have been added for stress or remote dump debugging purposes
        /// By the time we get an exception in managed code, we loose all context of what was
        /// on the stack and our locals are gone. The below will cache some critcal locals and state
        /// so they can be retrieved during debugging. 
        private IList _frameHandles = new List(0);
        private IList _writeSourceHandles = new List(0); 
        private enum EncodeState 
        {
            None = 0, 
            EncoderInitialized = 1,
            EncoderThumbnailSet = 2,
            EncoderPaletteSet = 3,
            EncoderCreatedNewFrame = 4, 
            FrameEncodeInitialized = 5,
            FrameEncodeSizeSet = 6, 
            FrameEncodeResolutionSet = 7, 
            FrameEncodeThumbnailSet = 8,
            FrameEncodeMetadataSet = 9, 
            FrameEncodeFormatSet = 10,
            FrameEncodeSourceWritten = 11,
            FrameEncodeCommitted = 12,
            EncoderCommitted = 13, 
            FrameEncodeColorContextsSet = 14,
        }; 
        private EncodeState _encodeState; 
        #endregion 
    }
    #endregion // BitmapEncoder
} 
// File provided for Reference Use Only by Microsoft Corporation (c) 2007.
// Copyright (c) Microsoft Corporation. All rights reserved.
//------------------------------------------------------------------------------ 
//  Copyright (c) Microsoft Corporation, 2003
//
//  File: BitmapEncoder.cs
// 
//-----------------------------------------------------------------------------
 
using System; 
using System.Collections.Generic;
using System.Collections.ObjectModel; 
using System.ComponentModel;
using System.ComponentModel.Design.Serialization;
using System.Reflection;
using System.IO; 
using MS.Internal;
using System.Diagnostics; 
using System.Windows.Media; 
using System.Windows.Threading;
using System.Globalization; 
using System.Runtime.InteropServices;
using System.Windows.Media.Imaging;
using System.Security;
using System.Security.Permissions; 
using MS.Win32.PresentationCore;
using SR=MS.Internal.PresentationCore.SR; 
using SRID=MS.Internal.PresentationCore.SRID; 
using System.Diagnostics.CodeAnalysis;
 
#pragma warning disable 1634, 1691  // suppressing PreSharp warnings
namespace System.Windows.Media.Imaging
{ 
    #region PROPBAG2
 
    [StructLayout(LayoutKind.Sequential, Pack=1)] 
    internal struct PROPBAG2
    { 
        internal UInt32 dwType;
        internal ushort vt;
        internal ushort cfType;
        internal IntPtr dwHint; 
        [SecurityCritical] 
        internal IntPtr pstrName; //this is string array 
        internal Guid clsid; 
        /// 
        /// Critical -Initializes a pointer to unmanaged memory to hold onto a string
        /// TreatAsSafe - there are no inputs 
        ///  
        [SecurityCritical, SecurityTreatAsSafe] 
        internal void Init(String name) 
        {
            pstrName = Marshal.StringToCoTaskMemUni(name); 
        }
        /// 
        /// Critical -Releases an unmanaged pointer into unmanaged memory. 
        /// TreatAsSafe - there are no inputs
        ///   
        [SecurityCritical, SecurityTreatAsSafe] 
        internal void Clear()
        { 
            Marshal.FreeCoTaskMem(pstrName);
            pstrName = IntPtr.Zero;
        }
    } 
    #endregion 
 
    #region BitmapEncoder
 
    /// 
    /// BitmapEncoder collects a set of frames (BitmapSource's) with their associated
    /// thumbnails and saves them to a specified stream.  In addition
    /// to frame-specific thumbnails, there can also be an bitmap-wide 
    /// (global) thumbnail, if the codec supports it.
    ///   
    public abstract class BitmapEncoder : DispatcherObject 
    {
        #region Constructors 
        /// 
        /// Constructor.
        ///   
        protected BitmapEncoder()
        { 
        } 
        ///  
        /// Internal Constructor.
        ///  
        internal BitmapEncoder(bool isBuiltIn)
        { 
            _isBuiltIn = isBuiltIn;
        } 
 
        /// 
        /// Creates a BitmapEncoder from a container format Guid 
        ///  
        /// Container format for the codec
        /// 
        /// Critical - guid used for creation of critical resources 
        ///  
        [SecurityCritical] 
        public static BitmapEncoder Create(Guid containerFormat) 
        {
            if (containerFormat == Guid.Empty) 
            {
                throw new ArgumentException(
                    SR.Get(SRID.Image_GuidEmpty, "containerFormat"),
                    "containerFormat" 
                    );
            } 
            else if (containerFormat == MILGuidData.GUID_ContainerFormatBmp) 
            {
                return new BmpBitmapEncoder(); 
            }
            else if (containerFormat == MILGuidData.GUID_ContainerFormatGif)
            {
                return new GifBitmapEncoder(); 
            }
            else if (containerFormat == MILGuidData.GUID_ContainerFormatJpeg) 
            { 
                return new JpegBitmapEncoder();
            } 
            else if (containerFormat == MILGuidData.GUID_ContainerFormatPng)
            {
                return new PngBitmapEncoder();
            } 
            else if (containerFormat == MILGuidData.GUID_ContainerFormatTiff)
            { 
                return new TiffBitmapEncoder(); 
            }
            else if (containerFormat == MILGuidData.GUID_ContainerFormatWmp) 
            {
                return new WmpBitmapEncoder();
            }
            else 
            {
                return new UnknownBitmapEncoder(containerFormat); 
            } 
        }
 
        #endregion
        #region Public Properties
 
        /// 
        /// Set or get the bitmap's color profile. 
        ///   
        public virtual ReadOnlyCollection ColorContexts
        { 
            get
            {
                VerifyAccess();
                EnsureBuiltIn(); 
                return _readOnlycolorContexts;
            } 
            set 
            {
                VerifyAccess(); 
                EnsureBuiltIn();
                if (value == null)
                { 
                    throw new ArgumentNullException("value");
                } 
 
                if (!_supportsColorContext)
                { 
                    throw new InvalidOperationException(SR.Get(SRID.Image_EncoderNoColorContext));
                }
                _readOnlycolorContexts = value; 
            }
        } 
 
        /// 
        /// Set or get the bitmap's global embedded thumbnail. 
        ///  
        public virtual BitmapSource Thumbnail
        {
            get 
            {
                VerifyAccess(); 
                EnsureBuiltIn(); 
                return _thumbnail;
            } 
            set
            {
                VerifyAccess();
                EnsureBuiltIn(); 
                if (value == null) 
                { 
                    throw new ArgumentNullException("value");
                } 
                if (!_supportsGlobalThumbnail)
                {
                    throw new InvalidOperationException(SR.Get(SRID.Image_EncoderNoGlobalThumbnail)); 
                }
 
                _thumbnail = value; 
            }
        } 
        /// 
        /// Set or get the bitmap's global embedded metadata.
        ///   
        public virtual BitmapMetadata Metadata
        { 
            get 
            {
                VerifyAccess(); 
                EnsureBuiltIn();
                EnsureMetadata(true);
                return _metadata; 
            }
            set 
            { 
                VerifyAccess();
                EnsureBuiltIn(); 
                if (value == null)
                {
                    throw new ArgumentNullException("value"); 
                }
 
                if (value.GuidFormat != ContainerFormat) 
                {
                    throw new InvalidOperationException(SR.Get(SRID.Image_MetadataNotCompatible)); 
                }
                if (!_supportsGlobalMetadata)
                { 
                    throw new InvalidOperationException(SR.Get(SRID.Image_EncoderNoGlobalMetadata));
                } 
 
                _metadata = value;
            } 
        }
        /// 
        /// Set or get the bitmap's global preview 
        ///  
        public virtual BitmapSource Preview 
        { 
            get
            { 
                VerifyAccess();
                EnsureBuiltIn();
                return _preview;
            } 
            set
            { 
                VerifyAccess(); 
                EnsureBuiltIn();
 
                if (value == null)
                {
                    throw new ArgumentNullException("value");
                } 
                if (!_supportsPreview) 
                { 
                    throw new InvalidOperationException(SR.Get(SRID.Image_EncoderNoPreview));
                } 
                _preview = value;
            }
        } 
        ///  
        /// The info that identifies this codec. 
        ///  
        ///  
        /// Critical - Access unmanaged code, codecs
        /// PublicOK - Getting codecinfo data is OK
        ///  
        public virtual BitmapCodecInfo CodecInfo 
        {
            [SecurityCritical ] 
            get 
            {
                VerifyAccess(); 
                EnsureBuiltIn();
                EnsureUnmanagedEncoder();
                // There should always be a codec info. 
                if (_codecInfo == null)
                { 
                    SafeMILHandle /* IWICBitmapEncoderInfo */ codecInfoHandle =  new SafeMILHandle(); 
                    HRESULT.Check(UnsafeNativeMethods.WICBitmapEncoder.GetEncoderInfo( 
                        _encoderHandle,
                        out codecInfoHandle
                        ));
 
                    _codecInfo = new BitmapCodecInfoInternal(codecInfoHandle);
                } 
 
                return _codecInfo;
            } 
        }
        /// 
        /// Provides access to this bitmap's palette 
        ///  
        public virtual BitmapPalette Palette 
        { 
            get
            { 
                VerifyAccess();
                EnsureBuiltIn();
                return _palette;
            } 
            set
            { 
                VerifyAccess(); 
                EnsureBuiltIn();
 
                if (value == null)
                {
                    throw new ArgumentNullException("value");
                } 
                _palette = value; 
            } 
        }
 
        /// 
        /// Access to the individual frames.
        ///  
        public virtual IList Frames 
        {
            get 
            { 
                VerifyAccess();
                EnsureBuiltIn(); 
                if (_frames == null)
                {
                    _frames = new List(0);
                } 
                return _frames; 
            } 
            set
            { 
                VerifyAccess();
                EnsureBuiltIn();
                if (value == null) 
                {
                    throw new ArgumentNullException("value"); 
                } 
                _frames = value; 
            }
        }
        #endregion 
        #region Public Methods 
 
        /// 
        /// Save (encode) the bitmap to the specified stream. 
        ///  
        /// Stream to save into
        /// 
        /// Critical - calls unmanaged code 
        ///  
        [SecurityPermission(SecurityAction.LinkDemand, Flags=SecurityPermissionFlag.UnmanagedCode)] 
        [SecurityPermission(SecurityAction.InheritanceDemand, Flags=SecurityPermissionFlag.UnmanagedCode)] 
        [SecurityCritical]
        public virtual void Save(System.IO.Stream stream) 
        {
            VerifyAccess();
            EnsureBuiltIn();
            EnsureUnmanagedEncoder(); 
            // No-op to get rid of build error 
            if (_encodeState == EncodeState.None) 
            {
            } 
            if (_hasSaved)
            {
                throw new InvalidOperationException(SR.Get(SRID.Image_OnlyOneSave)); 
            }
 
            if (_frames == null) 
            {
                throw new System.NotSupportedException(SR.Get(SRID.Image_NoFrames, null)); 
            }
            int count = _frames.Count;
            if (count <= 0) 
            {
                throw new System.NotSupportedException(SR.Get(SRID.Image_NoFrames, null)); 
            } 
            IntPtr comStream = IntPtr.Zero; 
            SafeMILHandle encoderHandle = _encoderHandle;
            try
            { 
                comStream = StreamAsIStream.IStreamFrom(stream);
 
                // does this addref the stream? 
                HRESULT.Check(UnsafeNativeMethods.WICBitmapEncoder.Initialize(
                    encoderHandle, 
                    comStream,
                    WICBitmapEncodeCacheOption.WICBitmapEncodeNoCache
                    ));
 
                // Helpful for debugging stress and remote dumps
                _encodeState = EncodeState.EncoderInitialized; 
 
                // Save global thumbnail if any.
                if (_thumbnail != null) 
                {
                    Debug.Assert(_supportsGlobalThumbnail);
                    SafeMILHandle thumbnailBitmapSource = _thumbnail.WicSourceHandle;
 
                    lock (_thumbnail.SyncObject)
                    { 
                        HRESULT.Check(UnsafeNativeMethods.WICBitmapEncoder.SetThumbnail( 
                            encoderHandle,
                            thumbnailBitmapSource 
                            ));
                        // Helpful for debugging stress and remote dumps
                        _encodeState = EncodeState.EncoderThumbnailSet; 
                    }
                } 
 
                // Save global palette if any.
                if (_palette != null && _palette.Colors.Count > 0) 
                {
                    SafeMILHandle paletteHandle = _palette.InternalPalette;
                    HRESULT.Check(UnsafeNativeMethods.WICBitmapEncoder.SetPalette( 
                        encoderHandle,
                        paletteHandle 
                        )); 
                    // Helpful for debugging stress and remote dumps 
                    _encodeState = EncodeState.EncoderPaletteSet;
                }
                // Save global metadata if any. 
                if (_metadata != null && _metadata.GuidFormat == ContainerFormat)
                { 
                    Debug.Assert(_supportsGlobalMetadata); 
                    EnsureMetadata(false); 
                    if (_metadata.InternalMetadataHandle != _metadataHandle)
                    {
                        PROPVARIANT propVar = new PROPVARIANT(); 
                        try 
                        { 
                            propVar.Init(_metadata);
 
                            lock (_metadata.SyncObject)
                            {
                                HRESULT.Check(UnsafeNativeMethods.WICMetadataQueryWriter.SetMetadataByName(
                                    _metadataHandle, 
                                    "/",
                                    ref propVar 
                                    )); 
                            }
                        } 
                        finally
                        {
                            propVar.Clear();
                        } 
                    }
                } 
 
                for (int i = 0; i < count; i++)
                { 
                    SafeMILHandle frameEncodeHandle = new SafeMILHandle();
                    SafeMILHandle encoderOptions = new SafeMILHandle();
                    HRESULT.Check(UnsafeNativeMethods.WICBitmapEncoder.CreateNewFrame(
                        encoderHandle, 
                        out frameEncodeHandle,
                        out encoderOptions 
                        )); 
                    // Helpful for debugging stress and remote dumps 
                    _encodeState = EncodeState.EncoderCreatedNewFrame;
                    _frameHandles.Add(frameEncodeHandle);
                    SaveFrame(frameEncodeHandle, encoderOptions, _frames[i]); 
                    // If multiple frames are not supported, break out 
                    if (!_supportsMultipleFrames) 
                    {
                        break; 
                    }
                }
                // Now let the encoder know we are done encoding the file. 
                HRESULT.Check(UnsafeNativeMethods.WICBitmapEncoder.Commit(encoderHandle));
 
                // Helpful for debugging stress and remote dumps 
                _encodeState = EncodeState.EncoderCommitted;
            } 
            finally
            {
                UnsafeNativeMethods.MILUnknown.ReleaseInterface(ref comStream);
            } 
            _hasSaved = true; 
        } 
        #endregion 
        #region Internal Properties / Methods
        ///  
        /// Returns the container format for this encoder
        ///   
        internal virtual Guid ContainerFormat 
        {
            get 
            {
                return Guid.Empty;
            }
        } 
        ///  
        /// Returns whether metadata is fixed size or not. 
        ///  
        internal virtual bool IsMetadataFixedSize 
        {
            get
            {
                return false; 
            }
        } 
 
        /// 
        /// Setups the encoder and other properties before encoding each frame 
        ///  
        internal virtual void SetupFrame(SafeMILHandle frameEncodeHandle, SafeMILHandle encoderOptions)
        {
            throw new NotImplementedException(); 
        }
 
        #endregion 
        #region Private Methods 
        /// 
        /// Checks to see if encoder is built in.
        ///   
        private void EnsureBuiltIn()
        { 
            if (!_isBuiltIn) 
            {
                throw new NotImplementedException(); 
            }
        }
        ///  
        /// Checks to see if encoder has built-in metadata.
        ///   
        ///  
        /// Critical - Accesses unmanaged code
        /// TreatAsSafe - inputs are verified or safe 
        ///  
        [SecurityCritical, SecurityTreatAsSafe]
        private void EnsureMetadata(bool createBitmapMetadata)
        { 
            if (!_supportsGlobalMetadata)
            { 
                return; 
            }
 
            if (_metadataHandle == null)
            {
                SafeMILHandle /* IWICMetadataQueryWriter */ metadataHandle = new SafeMILHandle();
 
                int hr = UnsafeNativeMethods.WICBitmapEncoder.GetMetadataQueryWriter(
                    _encoderHandle, 
                    out metadataHandle 
                    );
 
                if (hr == (int)WinCodecErrors.WINCODEC_ERR_UNSUPPORTEDOPERATION)
                {
                    _supportsGlobalMetadata = false;
                    return; 
                }
                HRESULT.Check(hr); 
 
                _metadataHandle = metadataHandle;
            } 
            if (createBitmapMetadata &&
                _metadata == null &&
                _metadataHandle != null) 
            {
                _metadata = new BitmapMetadata(_metadataHandle, false, IsMetadataFixedSize, _metadataHandle); 
            } 
        }
 
        /// 
        /// Creates the unmanaged encoder object
        ///  
        ///  
        /// Critical - calls unmanaged code, codecs, creates codec based on GUID
        ///   
        [SecurityCritical] 
        private void EnsureUnmanagedEncoder()
        { 
            if (_encoderHandle == null)
            {
                using (FactoryMaker myFactory = new FactoryMaker())
                { 
                    SafeMILHandle encoderHandle = null;
 
                    Guid vendorMicrosoft = new Guid(MILGuidData.GUID_VendorMicrosoft); 
                    Guid containerFormat = ContainerFormat;
 
                    HRESULT.Check(UnsafeNativeMethods.WICImagingFactory.CreateEncoder(
                                myFactory.ImagingFactoryPtr,
                                ref containerFormat,
                                ref vendorMicrosoft, 
                                out encoderHandle
                                )); 
 
                    _encoderHandle = encoderHandle;
                } 
            }
        }
        ///  
        /// Save the frame
        ///   
        ///  
        /// Critical - calls unmanaged code
        ///   
        [SecurityCritical]
        private void SaveFrame(SafeMILHandle frameEncodeHandle, SafeMILHandle encoderOptions, BitmapFrame frame)
        {
            SetupFrame(frameEncodeHandle, encoderOptions); 
            // Helpful for debugging stress and remote dumps 
            _encodeState = EncodeState.FrameEncodeInitialized; 
            // Set the size 
            HRESULT.Check(UnsafeNativeMethods.WICBitmapFrameEncode.SetSize(
                frameEncodeHandle,
                frame.PixelWidth,
                frame.PixelHeight 
                ));
 
            // Helpful for debugging stress and remote dumps 
            _encodeState = EncodeState.FrameEncodeSizeSet;
 
            // Set the resolution
            double dpiX = frame.DpiX;
            double dpiY = frame.DpiY;
 
            if (dpiX <= 0)
            { 
                dpiX = 96; 
            }
            if (dpiY <= 0) 
            {
                dpiY = 96;
            }
 
            HRESULT.Check(UnsafeNativeMethods.WICBitmapFrameEncode.SetResolution(
                frameEncodeHandle, 
                dpiX, 
                dpiY
                )); 
            // Helpful for debugging stress and remote dumps
            _encodeState = EncodeState.FrameEncodeResolutionSet;
 
            if (_supportsFrameThumbnails)
            { 
                // Set the thumbnail. 
                BitmapSource thumbnail = frame.Thumbnail;
 
                if (thumbnail != null)
                {
                    SafeMILHandle thumbnailHandle = thumbnail.WicSourceHandle;
 
                    lock (thumbnail.SyncObject)
                    { 
                        HRESULT.Check(UnsafeNativeMethods.WICBitmapFrameEncode.SetThumbnail( 
                            frameEncodeHandle,
                            thumbnailHandle 
                            ));
                        // Helpful for debugging stress and remote dumps
                        _encodeState = EncodeState.FrameEncodeThumbnailSet; 
                    }
                } 
            } 
            //if the source has been color corrected, we want to use a corresponding color profile 
            if (frame._isColorCorrected)
            {
                unsafe
                { 
                    IntPtr* pcolorContextslocal = stackalloc IntPtr[1];
                    pcolorContextslocal[0] = IntPtr.Zero; 
 
                    try
                    { 
                        Guid wicColorContextGuid = MILGuidData.IID_IWICColorContext;
                        ColorContext colorContext = new ColorContext(frame.Format);
                        HRESULT.Check(UnsafeNativeMethods.MILUnknown.QueryInterface(colorContext.ColorContextHandle, ref wicColorContextGuid, out pcolorContextslocal[0])); 
                        int hr = UnsafeNativeMethods.WICBitmapFrameEncode.SetColorContexts( 
                            frameEncodeHandle, 
                            (uint)1,
                            (IntPtr)pcolorContextslocal 
                            );
                        // It's possible that some encoders may not support color contexts
                        if (hr == HRESULT.S_OK) 
                        {
                            // Helpful for debugging stress and remote dumps 
                            _encodeState = EncodeState.FrameEncodeColorContextsSet; 
                        }
                    } 
                    finally
                    {
                        #pragma warning suppress 6031
                        UnsafeNativeMethods.MILUnknown.Release(pcolorContextslocal[0]); 
                    }
 
                } 
            }
            // if the caller has explicitly provided color context(s), add it/them to the encoder 
            else if ((frame.ColorContexts != null) && (frame.ColorContexts.Count > 0))
            {
                unsafe
                { 
                    int iCount = frame.ColorContexts.Count;
 
                    IntPtr* pcolorContextslocal = stackalloc IntPtr[iCount]; 
                    for (int i = 0; i < iCount; i++) pcolorContextslocal[i] = IntPtr.Zero;
 
                    try
                    {
                        for (int i = 0; i < iCount; i++)
                        { 
                            Guid wicColorContextGuid = MILGuidData.IID_IWICColorContext;
 
                            HRESULT.Check(UnsafeNativeMethods.MILUnknown.QueryInterface(frame.ColorContexts[i].ColorContextHandle, ref wicColorContextGuid, out pcolorContextslocal[i])); 
                        }
 
                        int hr = UnsafeNativeMethods.WICBitmapFrameEncode.SetColorContexts(
                            frameEncodeHandle,
                            (uint)iCount,
                            (IntPtr)pcolorContextslocal 
                            );
 
 
                        // It's possible that some encoders may not support color contexts
                        if (hr == HRESULT.S_OK) 
                        {
                            // Helpful for debugging stress and remote dumps
                            _encodeState = EncodeState.FrameEncodeColorContextsSet;
                        } 
                    }
                    finally 
                    { 
                        for (int i = 0; i < iCount; i++)
                        { 
                            #pragma warning suppress 6031
                            UnsafeNativeMethods.MILUnknown.Release(pcolorContextslocal[i]);
                        }
                    } 
                } 
            } 
            // Set the pixel format and palette 
            lock (frame.SyncObject)
            {
                SafeMILHandle outSourceHandle = new SafeMILHandle(); 
                SafeMILHandle bitmapSourceHandle = frame.WicSourceHandle;
                SafeMILHandle paletteHandle = new SafeMILHandle(); 
 
                // Set the pixel format and palette of the bitmap.
                // This could (but hopefully won't) introduce a format converter. 
                HRESULT.Check(UnsafeNativeMethods.WICCodec.WICSetEncoderFormat(
                    bitmapSourceHandle,
                    paletteHandle,
                    frameEncodeHandle, 
                    out outSourceHandle
                    )); 
 
                // Helpful for debugging stress and remote dumps
                _encodeState = EncodeState.FrameEncodeFormatSet; 
                _writeSourceHandles.Add(outSourceHandle);
                // Set the metadata
                if (_supportsFrameMetadata) 
                {
                    BitmapMetadata metadata = frame.Metadata as BitmapMetadata; 
 
                    // If the frame has metadata associated with a different container format, then we ignore it.
                    if (metadata != null && metadata.GuidFormat == ContainerFormat) 
                    {
                        SafeMILHandle /* IWICMetadataQueryWriter */ metadataHandle = new SafeMILHandle();
                        HRESULT.Check(UnsafeNativeMethods.WICBitmapFrameEncode.GetMetadataQueryWriter( 
                            frameEncodeHandle,
                            out metadataHandle 
                            )); 
                        PROPVARIANT propVar = new PROPVARIANT(); 
                        try
                        {
                            propVar.Init(metadata); 
                            lock (metadata.SyncObject) 
                            { 
                                HRESULT.Check(UnsafeNativeMethods.WICMetadataQueryWriter.SetMetadataByName(
                                    metadataHandle, 
                                    "/",
                                    ref propVar
                                    ));
 
                                // Helpful for debugging stress and remote dumps
                                _encodeState = EncodeState.FrameEncodeMetadataSet; 
                            } 
                        }
                        finally 
                        {
                            propVar.Clear();
                        }
                    } 
                }
 
                Int32Rect r = new Int32Rect(); 
                HRESULT.Check(UnsafeNativeMethods.WICBitmapFrameEncode.WriteSource(
                    frameEncodeHandle, 
                    outSourceHandle,
                    ref r
                    ));
 
                // Helpful for debugging stress and remote dumps
                _encodeState = EncodeState.FrameEncodeSourceWritten; 
 
                HRESULT.Check(UnsafeNativeMethods.WICBitmapFrameEncode.Commit(
                    frameEncodeHandle 
                    ));
                // Helpful for debugging stress and remote dumps
                _encodeState = EncodeState.FrameEncodeCommitted; 
            }
        } 
 
        #endregion
 
        #region Internal Abstract
        /// "Seals" the object
        internal abstract void SealObject(); 
        #endregion 
 
        #region Data Members
 
        /// does encoder support a preview?
        internal bool _supportsPreview = true;
        /// does encoder support a global thumbnail? 
        internal bool _supportsGlobalThumbnail = true;
 
        /// does encoder support a global metadata? 
        internal bool _supportsGlobalMetadata = true;
 
        /// does encoder support per frame thumbnails?
        internal bool _supportsFrameThumbnails = true;
        /// does encoder support per frame thumbnails? 
        internal bool _supportsFrameMetadata = true;
 
        /// does encoder support multiple frames? 
        internal bool _supportsMultipleFrames = false;
 
        /// does encoder support color context?
        internal bool _supportsColorContext = false;
        /// is it a built in encoder 
        private bool _isBuiltIn;
 
        /// Internal WIC encoder handle 
        private SafeMILHandle _encoderHandle;
 
        /// metadata
        private BitmapMetadata _metadata;
        /// Internal WIC metadata handle 
        private SafeMILHandle _metadataHandle;
 
        /// colorcontext 
        private ReadOnlyCollection _readOnlycolorContexts;
 
        /// codecinfo
        private BitmapCodecInfoInternal _codecInfo;
        /// thumbnail 
        private BitmapSource _thumbnail;
 
        /// preview 
        private BitmapSource _preview;
 
        /// palette
        private BitmapPalette _palette;
        /// frames 
        private IList _frames;
 
        /// true if Save has been called. 
        private bool _hasSaved;
 
        /// The below data members have been added for stress or remote dump debugging purposes
        /// By the time we get an exception in managed code, we loose all context of what was
        /// on the stack and our locals are gone. The below will cache some critcal locals and state
        /// so they can be retrieved during debugging. 
        private IList _frameHandles = new List(0);
        private IList _writeSourceHandles = new List(0); 
        private enum EncodeState 
        {
            None = 0, 
            EncoderInitialized = 1,
            EncoderThumbnailSet = 2,
            EncoderPaletteSet = 3,
            EncoderCreatedNewFrame = 4, 
            FrameEncodeInitialized = 5,
            FrameEncodeSizeSet = 6, 
            FrameEncodeResolutionSet = 7, 
            FrameEncodeThumbnailSet = 8,
            FrameEncodeMetadataSet = 9, 
            FrameEncodeFormatSet = 10,
            FrameEncodeSourceWritten = 11,
            FrameEncodeCommitted = 12,
            EncoderCommitted = 13, 
            FrameEncodeColorContextsSet = 14,
        }; 
        private EncodeState _encodeState; 
        #endregion 
    }
    #endregion // BitmapEncoder
} 
// 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
- SQLInt64.cs
- BindingNavigatorDesigner.cs
- GeneralTransform2DTo3D.cs
- Merger.cs
- LabelLiteral.cs
- SuppressIldasmAttribute.cs
- RefreshPropertiesAttribute.cs
- MonikerBuilder.cs
- Serializer.cs
- FontUnit.cs
- HtmlShimManager.cs
- EndpointAddressProcessor.cs
- ExtenderControl.cs
- datacache.cs
- XmlParserContext.cs
- InternalBase.cs
- UpdatePanel.cs
- OutOfMemoryException.cs
- HttpRequestTraceRecord.cs
- DataGridHeadersVisibilityToVisibilityConverter.cs
- MessagePropertyFilter.cs
- UnconditionalPolicy.cs
- BitmapEffectInput.cs
- NameGenerator.cs
- CaseCqlBlock.cs
- ListControlActionList.cs
- SqlConnection.cs
- LinkLabel.cs
- AuthorizationRuleCollection.cs
- MenuItemStyle.cs
- FakeModelPropertyImpl.cs
- ToggleProviderWrapper.cs
- WebPartTransformer.cs
- XmlEnumAttribute.cs
- ConstantSlot.cs
- AssemblyAttributes.cs
- XmlDataSourceNodeDescriptor.cs
- DataComponentGenerator.cs
- InvokeHandlers.cs
- NativeDirectoryServicesQueryAPIs.cs
- ToggleButton.cs
- TreeNodeStyle.cs
- FirstMatchCodeGroup.cs
- SqlBuilder.cs
- EdmItemError.cs
- MappingItemCollection.cs
- ServiceBusyException.cs
- PeerName.cs
- ResXResourceReader.cs
- SqlTriggerContext.cs
- XmlUnspecifiedAttribute.cs
- WriteStateInfoBase.cs
- FileEnumerator.cs
- Converter.cs
- EntitySetBase.cs
- ListViewItem.cs
- AssemblySettingAttributes.cs
- EditorZone.cs
- ToolboxDataAttribute.cs
- GridViewSortEventArgs.cs
- ChangeToolStripParentVerb.cs
- ListViewItemEventArgs.cs
- PasswordTextContainer.cs
- ResourceDescriptionAttribute.cs
- HtmlInputImage.cs
- SafeEventLogReadHandle.cs
- SecurityImpersonationBehavior.cs
- _NetworkingPerfCounters.cs
- ComplexBindingPropertiesAttribute.cs
- PenLineJoinValidation.cs
- UIElementHelper.cs
- EmptyEnumerator.cs
- XmlIgnoreAttribute.cs
- FreezableDefaultValueFactory.cs
- Model3D.cs
- ObjectHelper.cs
- AssociationSetEnd.cs
- TraceAsyncResult.cs
- ListenerElementsCollection.cs
- GeometryModel3D.cs
- DbConnectionPool.cs
- ImageSourceConverter.cs
- UnsupportedPolicyOptionsException.cs
- ParallelRangeManager.cs
- SecurityElement.cs
- PassportAuthenticationEventArgs.cs
- InkPresenterAutomationPeer.cs
- ToolStripDropTargetManager.cs
- GridEntry.cs
- XmlToDatasetMap.cs
- PerformanceCounterPermissionAttribute.cs
- WebPartMenu.cs
- FormatControl.cs
- EmptyEnumerator.cs
- Logging.cs
- FrameAutomationPeer.cs
- Vector.cs
- CompressionTracing.cs
- TableLayoutRowStyleCollection.cs
- WindowsRebar.cs