TransformedBitmap.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 / TransformedBitmap.cs / 1 / TransformedBitmap.cs

                            //------------------------------------------------------------------------------ 
//  Microsoft Avalon
//  Copyright (c) Microsoft Corporation.  All Rights Reserved.
//
//  File: TransformedBitmap.cs 
//
//----------------------------------------------------------------------------- 
 

using System; 
using System.IO;
using System.Collections;
using System.Collections.Generic;
using System.ComponentModel; 
using System.ComponentModel.Design.Serialization;
using System.Reflection; 
using MS.Internal; 
using MS.Win32.PresentationCore;
using System.Security; 
using System.Security.Permissions;
using System.Diagnostics;
using System.Windows.Media;
using System.Globalization; 
using System.Runtime.InteropServices;
using System.Windows.Media.Animation; 
using System.Windows.Media.Composition; 

using SR=MS.Internal.PresentationCore.SR; 
using SRID=MS.Internal.PresentationCore.SRID;

namespace System.Windows.Media.Imaging
{ 
    #region TransformedBitmap
    ///  
    /// TransformedBitmap provides caching functionality for a BitmapSource. 
    /// 
    public sealed partial class TransformedBitmap : Imaging.BitmapSource, ISupportInitialize 
    {
        /// 
        /// TransformedBitmap construtor
        ///  
        public TransformedBitmap()
            : base(true) // Use base class virtuals 
        { 
        }
 
        /// 
        /// Construct a TransformedBitmap with the given newTransform
        /// 
        /// BitmapSource to apply to the newTransform to 
        /// Transform to apply to the bitmap
        public TransformedBitmap(BitmapSource source, Transform newTransform) 
            : base(true) // Use base class virtuals 
        {
            if (source == null) 
            {
                throw new ArgumentNullException("source");
            }
 
            if (newTransform == null)
            { 
                throw new InvalidOperationException(SR.Get(SRID.Image_NoArgument, "Transform")); 
            }
 
            if (!CheckTransform(newTransform))
            {
                throw new InvalidOperationException(SR.Get(SRID.Image_OnlyOrthogonal));
            } 

            _bitmapInit.BeginInit(); 
 
            Source = source;
            Transform = newTransform; 

            _bitmapInit.EndInit();
            FinalizeCreation();
        } 

        // ISupportInitialize 
 
        /// 
        /// Prepare the bitmap to accept initialize paramters. 
        /// 
        public void BeginInit()
        {
            WritePreamble(); 
            _bitmapInit.BeginInit();
        } 
 
        /// 
        /// Prepare the bitmap to accept initialize paramters. 
        /// 
        /// 
        /// Critical - eventually accesses critical resources
        /// PublicOK - All inputs verified 
        /// 
        [SecurityCritical ] 
        public void EndInit() 
        {
            WritePreamble(); 
            _bitmapInit.EndInit();

            if (Source == null)
            { 
                throw new InvalidOperationException(SR.Get(SRID.Image_NoArgument, "Source"));
            } 
 
            Transform transform = Transform;
            if (transform == null) 
            {
                throw new InvalidOperationException(SR.Get(SRID.Image_NoArgument, "Transform"));
            }
 
            if (!CheckTransform(transform))
            { 
                throw new InvalidOperationException(SR.Get(SRID.Image_OnlyOrthogonal)); 
            }
 
            FinalizeCreation();
        }

        private void ClonePrequel(TransformedBitmap otherTransformedBitmap) 
        {
            BeginInit(); 
        } 

        private void ClonePostscript(TransformedBitmap otherTransformedBitmap) 
        {
            EndInit();
        }
 
        /// 
        /// Check the transformation to see if it's a simple scale and/or rotation and/or flip. 
        ///  
        internal bool CheckTransform(Transform newTransform)
        { 
            Matrix m = newTransform.Value;
            bool canHandle = false;

            if ( (DoubleUtil.IsZero(m.M11) && DoubleUtil.IsZero(m.M22)) || 
                 (DoubleUtil.IsZero(m.M12) && DoubleUtil.IsZero(m.M21)) )
            { 
                canHandle = true; 
            }
 
            return canHandle;
        }

        ///  
        /// Check the transformation to see if it's a simple scale and/or rotation and/or flip.
        ///  
        internal void GetParamsFromTransform( 
            Transform newTransform,
            out double scaleX, 
            out double scaleY,
            out WICBitmapTransformOptions options)
        {
            Matrix m = newTransform.Value; 

            if (DoubleUtil.IsZero(m.M12) && DoubleUtil.IsZero(m.M21)) 
            { 
                scaleX = Math.Abs(m.M11);
                scaleY = Math.Abs(m.M22); 

                options = WICBitmapTransformOptions.WICBitmapTransformRotate0;

                if (m.M11 < 0) 
                {
                    options |= WICBitmapTransformOptions.WICBitmapTransformFlipHorizontal; 
                } 

                if (m.M22 < 0) 
                {
                    options |= WICBitmapTransformOptions.WICBitmapTransformFlipVertical;
                }
            } 
            else
            { 
                Debug.Assert(DoubleUtil.IsZero(m.M11) && DoubleUtil.IsZero(m.M22)); 

                scaleX = Math.Abs(m.M12); 
                scaleY = Math.Abs(m.M21);

                options = WICBitmapTransformOptions.WICBitmapTransformRotate90;
 
                if (m.M12 < 0)
                { 
                    options |= WICBitmapTransformOptions.WICBitmapTransformFlipHorizontal; 
                }
 
                if (m.M21 >= 0)
                {
                    options |= WICBitmapTransformOptions.WICBitmapTransformFlipVertical;
                } 
            }
        } 
 
        ///
        /// Create the unmanaged resources 
        ///
        /// 
        /// Critical - access critical resource
        ///  
        [SecurityCritical]
        internal override void FinalizeCreation() 
        { 
            _bitmapInit.EnsureInitializedComplete();
            BitmapSourceSafeMILHandle wicTransformer = null; 

            double scaleX, scaleY;
            WICBitmapTransformOptions options;
 
            GetParamsFromTransform(Transform, out scaleX, out scaleY, out options);
 
            using (FactoryMaker factoryMaker = new FactoryMaker()) 
            {
                try 
                {
                    IntPtr wicFactory = factoryMaker.ImagingFactoryPtr;

                    wicTransformer = _source.WicSourceHandle; 

                    if (!DoubleUtil.IsOne(scaleX) || !DoubleUtil.IsOne(scaleY)) 
                    { 
                        uint width = Math.Max(1, (uint)(scaleX * _source.PixelWidth + 0.5));
                        uint height = Math.Max(1, (uint)(scaleY * _source.PixelHeight + 0.5)); 

                        HRESULT.Check(UnsafeNativeMethods.WICImagingFactory.CreateBitmapScaler(
                                wicFactory,
                                out wicTransformer)); 

                        lock (_syncObject) 
                        { 
                            HRESULT.Check(UnsafeNativeMethods.WICBitmapScaler.Initialize(
                                    wicTransformer, 
                                    _source.WicSourceHandle,
                                    width,
                                    height,
                                    WICInterpolationMode.Fant)); 
                        }
                    } 
 
                    if (options != WICBitmapTransformOptions.WICBitmapTransformRotate0)
                    { 
                        // Rotations are extremely slow if we're pulling from a decoder because we end
                        // up decoding multiple times.  Caching the source lets us rotate faster at the cost
                        // of increased memory usage.
                        wicTransformer = CreateCachedBitmap( 
                            null,
                            wicTransformer, 
                            BitmapCreateOptions.PreservePixelFormat, 
                            BitmapCacheOption.Default,
                            _source.Palette); 

                        BitmapSourceSafeMILHandle rotator = null;

                        HRESULT.Check(UnsafeNativeMethods.WICImagingFactory.CreateBitmapFlipRotator( 
                                wicFactory,
                                out rotator)); 
 
                        lock (_syncObject)
                        { 
                            HRESULT.Check(UnsafeNativeMethods.WICBitmapFlipRotator.Initialize(
                                    rotator,
                                    wicTransformer,
                                    options)); 
                        }
 
                        wicTransformer = rotator; 
                    }
 
                    // If we haven't introduced either a scaler or rotator, add a null rotator
                    // so that our WicSourceHandle isn't the same as our Source's.
                    if (options == WICBitmapTransformOptions.WICBitmapTransformRotate0 &&
                        DoubleUtil.IsOne(scaleX) && DoubleUtil.IsOne(scaleY)) 
                    {
                        HRESULT.Check(UnsafeNativeMethods.WICImagingFactory.CreateBitmapFlipRotator( 
                                wicFactory, 
                                out wicTransformer));
 
                        lock (_syncObject)
                        {
                            HRESULT.Check(UnsafeNativeMethods.WICBitmapFlipRotator.Initialize(
                                    wicTransformer, 
                                    _source.WicSourceHandle,
                                    WICBitmapTransformOptions.WICBitmapTransformRotate0)); 
                        } 
                    }
 
                    WicSourceHandle = wicTransformer;
                    _isSourceCached = _source.IsSourceCached;
                }
                catch 
                {
                    _bitmapInit.Reset(); 
                    throw; 
                }
            } 

            CreationCompleted = true;
            UpdateCachedSettings();
        } 

        ///  
        ///     Notification on source changing. 
        /// 
        private void SourcePropertyChangedHook(DependencyPropertyChangedEventArgs e) 
        {
            if (!e.IsASubPropertyChange)
            {
                BitmapSource newSource = e.NewValue as BitmapSource; 
                _source = newSource;
                _syncObject = (newSource != null) ? newSource.SyncObject : _bitmapInit; 
            } 
        }
 
        /// 
        ///     Notification on transform changing.
        /// 
        private void TransformPropertyChangedHook(DependencyPropertyChangedEventArgs e) 
        {
            if (!e.IsASubPropertyChange) 
            { 
                _transform = e.NewValue as Transform;
            } 
        }

        /// 
        ///     Coerce Source 
        /// 
        private static object CoerceSource(DependencyObject d, object value) 
        { 
            TransformedBitmap bitmap = (TransformedBitmap)d;
            if (!bitmap._bitmapInit.IsInInit) 
            {
                return bitmap._source;
            }
            else 
            {
                return value; 
            } 
        }
 
        /// 
        ///     Coerce Transform
        /// 
        private static object CoerceTransform(DependencyObject d, object value) 
        {
            TransformedBitmap bitmap = (TransformedBitmap)d; 
            if (!bitmap._bitmapInit.IsInInit) 
            {
                return bitmap._transform; 
            }
            else
            {
                return value; 
            }
        } 
 
        #region Data Members
 
        private BitmapSource _source;

        private Transform _transform;
 
        #endregion
    } 
 
    #endregion // TransformedBitmap
} 

// File provided for Reference Use Only by Microsoft Corporation (c) 2007.
//------------------------------------------------------------------------------ 
//  Microsoft Avalon
//  Copyright (c) Microsoft Corporation.  All Rights Reserved.
//
//  File: TransformedBitmap.cs 
//
//----------------------------------------------------------------------------- 
 

using System; 
using System.IO;
using System.Collections;
using System.Collections.Generic;
using System.ComponentModel; 
using System.ComponentModel.Design.Serialization;
using System.Reflection; 
using MS.Internal; 
using MS.Win32.PresentationCore;
using System.Security; 
using System.Security.Permissions;
using System.Diagnostics;
using System.Windows.Media;
using System.Globalization; 
using System.Runtime.InteropServices;
using System.Windows.Media.Animation; 
using System.Windows.Media.Composition; 

using SR=MS.Internal.PresentationCore.SR; 
using SRID=MS.Internal.PresentationCore.SRID;

namespace System.Windows.Media.Imaging
{ 
    #region TransformedBitmap
    ///  
    /// TransformedBitmap provides caching functionality for a BitmapSource. 
    /// 
    public sealed partial class TransformedBitmap : Imaging.BitmapSource, ISupportInitialize 
    {
        /// 
        /// TransformedBitmap construtor
        ///  
        public TransformedBitmap()
            : base(true) // Use base class virtuals 
        { 
        }
 
        /// 
        /// Construct a TransformedBitmap with the given newTransform
        /// 
        /// BitmapSource to apply to the newTransform to 
        /// Transform to apply to the bitmap
        public TransformedBitmap(BitmapSource source, Transform newTransform) 
            : base(true) // Use base class virtuals 
        {
            if (source == null) 
            {
                throw new ArgumentNullException("source");
            }
 
            if (newTransform == null)
            { 
                throw new InvalidOperationException(SR.Get(SRID.Image_NoArgument, "Transform")); 
            }
 
            if (!CheckTransform(newTransform))
            {
                throw new InvalidOperationException(SR.Get(SRID.Image_OnlyOrthogonal));
            } 

            _bitmapInit.BeginInit(); 
 
            Source = source;
            Transform = newTransform; 

            _bitmapInit.EndInit();
            FinalizeCreation();
        } 

        // ISupportInitialize 
 
        /// 
        /// Prepare the bitmap to accept initialize paramters. 
        /// 
        public void BeginInit()
        {
            WritePreamble(); 
            _bitmapInit.BeginInit();
        } 
 
        /// 
        /// Prepare the bitmap to accept initialize paramters. 
        /// 
        /// 
        /// Critical - eventually accesses critical resources
        /// PublicOK - All inputs verified 
        /// 
        [SecurityCritical ] 
        public void EndInit() 
        {
            WritePreamble(); 
            _bitmapInit.EndInit();

            if (Source == null)
            { 
                throw new InvalidOperationException(SR.Get(SRID.Image_NoArgument, "Source"));
            } 
 
            Transform transform = Transform;
            if (transform == null) 
            {
                throw new InvalidOperationException(SR.Get(SRID.Image_NoArgument, "Transform"));
            }
 
            if (!CheckTransform(transform))
            { 
                throw new InvalidOperationException(SR.Get(SRID.Image_OnlyOrthogonal)); 
            }
 
            FinalizeCreation();
        }

        private void ClonePrequel(TransformedBitmap otherTransformedBitmap) 
        {
            BeginInit(); 
        } 

        private void ClonePostscript(TransformedBitmap otherTransformedBitmap) 
        {
            EndInit();
        }
 
        /// 
        /// Check the transformation to see if it's a simple scale and/or rotation and/or flip. 
        ///  
        internal bool CheckTransform(Transform newTransform)
        { 
            Matrix m = newTransform.Value;
            bool canHandle = false;

            if ( (DoubleUtil.IsZero(m.M11) && DoubleUtil.IsZero(m.M22)) || 
                 (DoubleUtil.IsZero(m.M12) && DoubleUtil.IsZero(m.M21)) )
            { 
                canHandle = true; 
            }
 
            return canHandle;
        }

        ///  
        /// Check the transformation to see if it's a simple scale and/or rotation and/or flip.
        ///  
        internal void GetParamsFromTransform( 
            Transform newTransform,
            out double scaleX, 
            out double scaleY,
            out WICBitmapTransformOptions options)
        {
            Matrix m = newTransform.Value; 

            if (DoubleUtil.IsZero(m.M12) && DoubleUtil.IsZero(m.M21)) 
            { 
                scaleX = Math.Abs(m.M11);
                scaleY = Math.Abs(m.M22); 

                options = WICBitmapTransformOptions.WICBitmapTransformRotate0;

                if (m.M11 < 0) 
                {
                    options |= WICBitmapTransformOptions.WICBitmapTransformFlipHorizontal; 
                } 

                if (m.M22 < 0) 
                {
                    options |= WICBitmapTransformOptions.WICBitmapTransformFlipVertical;
                }
            } 
            else
            { 
                Debug.Assert(DoubleUtil.IsZero(m.M11) && DoubleUtil.IsZero(m.M22)); 

                scaleX = Math.Abs(m.M12); 
                scaleY = Math.Abs(m.M21);

                options = WICBitmapTransformOptions.WICBitmapTransformRotate90;
 
                if (m.M12 < 0)
                { 
                    options |= WICBitmapTransformOptions.WICBitmapTransformFlipHorizontal; 
                }
 
                if (m.M21 >= 0)
                {
                    options |= WICBitmapTransformOptions.WICBitmapTransformFlipVertical;
                } 
            }
        } 
 
        ///
        /// Create the unmanaged resources 
        ///
        /// 
        /// Critical - access critical resource
        ///  
        [SecurityCritical]
        internal override void FinalizeCreation() 
        { 
            _bitmapInit.EnsureInitializedComplete();
            BitmapSourceSafeMILHandle wicTransformer = null; 

            double scaleX, scaleY;
            WICBitmapTransformOptions options;
 
            GetParamsFromTransform(Transform, out scaleX, out scaleY, out options);
 
            using (FactoryMaker factoryMaker = new FactoryMaker()) 
            {
                try 
                {
                    IntPtr wicFactory = factoryMaker.ImagingFactoryPtr;

                    wicTransformer = _source.WicSourceHandle; 

                    if (!DoubleUtil.IsOne(scaleX) || !DoubleUtil.IsOne(scaleY)) 
                    { 
                        uint width = Math.Max(1, (uint)(scaleX * _source.PixelWidth + 0.5));
                        uint height = Math.Max(1, (uint)(scaleY * _source.PixelHeight + 0.5)); 

                        HRESULT.Check(UnsafeNativeMethods.WICImagingFactory.CreateBitmapScaler(
                                wicFactory,
                                out wicTransformer)); 

                        lock (_syncObject) 
                        { 
                            HRESULT.Check(UnsafeNativeMethods.WICBitmapScaler.Initialize(
                                    wicTransformer, 
                                    _source.WicSourceHandle,
                                    width,
                                    height,
                                    WICInterpolationMode.Fant)); 
                        }
                    } 
 
                    if (options != WICBitmapTransformOptions.WICBitmapTransformRotate0)
                    { 
                        // Rotations are extremely slow if we're pulling from a decoder because we end
                        // up decoding multiple times.  Caching the source lets us rotate faster at the cost
                        // of increased memory usage.
                        wicTransformer = CreateCachedBitmap( 
                            null,
                            wicTransformer, 
                            BitmapCreateOptions.PreservePixelFormat, 
                            BitmapCacheOption.Default,
                            _source.Palette); 

                        BitmapSourceSafeMILHandle rotator = null;

                        HRESULT.Check(UnsafeNativeMethods.WICImagingFactory.CreateBitmapFlipRotator( 
                                wicFactory,
                                out rotator)); 
 
                        lock (_syncObject)
                        { 
                            HRESULT.Check(UnsafeNativeMethods.WICBitmapFlipRotator.Initialize(
                                    rotator,
                                    wicTransformer,
                                    options)); 
                        }
 
                        wicTransformer = rotator; 
                    }
 
                    // If we haven't introduced either a scaler or rotator, add a null rotator
                    // so that our WicSourceHandle isn't the same as our Source's.
                    if (options == WICBitmapTransformOptions.WICBitmapTransformRotate0 &&
                        DoubleUtil.IsOne(scaleX) && DoubleUtil.IsOne(scaleY)) 
                    {
                        HRESULT.Check(UnsafeNativeMethods.WICImagingFactory.CreateBitmapFlipRotator( 
                                wicFactory, 
                                out wicTransformer));
 
                        lock (_syncObject)
                        {
                            HRESULT.Check(UnsafeNativeMethods.WICBitmapFlipRotator.Initialize(
                                    wicTransformer, 
                                    _source.WicSourceHandle,
                                    WICBitmapTransformOptions.WICBitmapTransformRotate0)); 
                        } 
                    }
 
                    WicSourceHandle = wicTransformer;
                    _isSourceCached = _source.IsSourceCached;
                }
                catch 
                {
                    _bitmapInit.Reset(); 
                    throw; 
                }
            } 

            CreationCompleted = true;
            UpdateCachedSettings();
        } 

        ///  
        ///     Notification on source changing. 
        /// 
        private void SourcePropertyChangedHook(DependencyPropertyChangedEventArgs e) 
        {
            if (!e.IsASubPropertyChange)
            {
                BitmapSource newSource = e.NewValue as BitmapSource; 
                _source = newSource;
                _syncObject = (newSource != null) ? newSource.SyncObject : _bitmapInit; 
            } 
        }
 
        /// 
        ///     Notification on transform changing.
        /// 
        private void TransformPropertyChangedHook(DependencyPropertyChangedEventArgs e) 
        {
            if (!e.IsASubPropertyChange) 
            { 
                _transform = e.NewValue as Transform;
            } 
        }

        /// 
        ///     Coerce Source 
        /// 
        private static object CoerceSource(DependencyObject d, object value) 
        { 
            TransformedBitmap bitmap = (TransformedBitmap)d;
            if (!bitmap._bitmapInit.IsInInit) 
            {
                return bitmap._source;
            }
            else 
            {
                return value; 
            } 
        }
 
        /// 
        ///     Coerce Transform
        /// 
        private static object CoerceTransform(DependencyObject d, object value) 
        {
            TransformedBitmap bitmap = (TransformedBitmap)d; 
            if (!bitmap._bitmapInit.IsInInit) 
            {
                return bitmap._transform; 
            }
            else
            {
                return value; 
            }
        } 
 
        #region Data Members
 
        private BitmapSource _source;

        private Transform _transform;
 
        #endregion
    } 
 
    #endregion // TransformedBitmap
} 

// File provided for Reference Use Only by Microsoft Corporation (c) 2007.
                        

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