BitmapEncoder.cs source code in C# .NET

Source code for the .NET framework in C#

                        

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

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