BitmapEffect.cs source code in C# .NET

Source code for the .NET framework in C#

                        

Code:

/ DotNET / DotNET / 8.0 / untmp / WIN_WINDOWS / lh_tools_devdiv_wpf / Windows / wcp / Core / System / Windows / Media / Effects / BitmapEffect.cs / 1 / BitmapEffect.cs

                            //------------------------------------------------------------------------------ 
//  Microsoft Avalon
//  Copyright (c) Microsoft Corporation, 2005
//
//  File:       BitmapEffect.cs 
//-----------------------------------------------------------------------------
 
using MS.Internal; 
using System;
using System.IO; 
using System.ComponentModel;
using System.ComponentModel.Design.Serialization;
using System.Diagnostics;
using System.Reflection; 
using System.Windows.Threading;
using System.Threading; 
using System.Runtime.InteropServices; 
using System.Windows;
using System.Windows.Media; 
using System.Windows.Markup;
using System.Windows.Media.Animation;
using System.Windows.Media.Composition;
using System.Windows.Media.Imaging; 
using System.Security;
using MS.Internal.PresentationCore; 
using System.Security.Permissions; 

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

namespace System.Windows.Media.Effects
{ 
    internal class BitmapEffectException : Exception
    { 
        public BitmapEffectException() 
        {
        } 
    }

    /// 
    /// BitmapEffect 
    /// 
    ///  
    /// We have the Inheritance demand, because we don't want 
    /// third parties to be able to subclass BitmapEffect in the partial trust scenario
    ///  
    [UIPermissionAttribute(SecurityAction.InheritanceDemand, Window = UIPermissionWindow.AllWindows)]
    public abstract partial class BitmapEffect
    {
        private SafeMILHandle _unmanagedEffectGroup; 
        private SafeHandle _unmanagedEffect;
        private BitmapEffectRenderContext _renderContext = new BitmapEffectRenderContext(); 
        private Rect _visualBounds = Rect.Empty; 
        private const double DefaultDevicePixelsPerInch = 96.0;
 
        internal bool _connectionsSetup = false;

        #region Constructors
        ///  
        /// Constructor
        ///  
        protected BitmapEffect() 
        {
            // STA Requirement 
            //
            // Avalon doesn't necessarily require STA, but many components do.  Examples
            // include Cicero, OLE, COM, etc.  So we throw an exception here if the
            // thread is not STA. 
            if (Thread.CurrentThread.GetApartmentState() != ApartmentState.STA)
            { 
                throw new InvalidOperationException(SR.Get(SRID.RequiresSTA)); 
            }
 
            //
            //

 

 
 

 
            if (Dispatcher != null)
            {
                MediaContext.From(Dispatcher).BitmapEffectsUsed = true;
            } 
            else
            { 
                // object is frozen 
                MediaContext.CurrentMediaContext.BitmapEffectsUsed = true;
            } 
        }

        #endregion
 
        #region Protected Methods
        ///  
        /// This method is called before calling GetOutput on an effect. 
        /// It gives a chance for the managed effect to update the properties
        /// of the unmanaged object. 
        /// 
        abstract protected void UpdateUnmanagedPropertyState(SafeHandle unmanagedEffect);

 
        /// 
        /// Returns a safe handle to an unmanaged effect clone 
        ///  
        unsafe abstract protected SafeHandle CreateUnmanagedEffect();
 
        /// 
        /// SetValue
        /// 
        ///  SafeHandle to the unmanaged effect object 
        /// Name of the unmanaged property to be set
        /// Object value to set unmanaged property to 
        ///  
        /// 
        /// Critical - calls native code 
        /// TreatAsSafe - as there is a demand
        /// 
        [SecurityCritical, SecurityTreatAsSafe]
        unsafe static protected void SetValue(SafeHandle effect, string propertyName, object value) 
        {
            SecurityHelper.DemandUIWindowPermission(); 
 
            if (value is Color)
            { 
                Color clr = (Color)value;
                uint packedColor = (((uint)clr.A << 24) | ((uint)clr.B << 16) | ((uint)clr.G << 8) | (uint)clr.R);
                value = (object)packedColor;
            } 
            HRESULT.Check(MS.Win32.PresentationCore.UnsafeNativeMethods.IMILBitmapEffect.SetValue(effect, propertyName, ref value));
        } 
 
        /// 
        /// Creates an IMILBitmapEffect object 
        /// 
        /// IMILBitmapEffect object
        /// 
        /// Critical - calls native code 
        /// TreatAsSafe - as there is a demand
        ///  
        [SecurityCritical, SecurityTreatAsSafe] 
        unsafe static protected SafeHandle /* IMILBitmapEffect */ CreateBitmapEffectOuter()
        { 
            SecurityHelper.DemandUIWindowPermission();

            SafeMILHandle outer = null;
            HRESULT.Check(MS.Win32.PresentationCore.UnsafeNativeMethods.MILFactoryEffects.CreateBitmapEffectOuter(out outer)); 
            return outer;
        } 
 
        /// 
        /// Initializes the IMILBitmapEffect object with the IMILBitmapEffectPrimitive object 
        /// 
        /// The IMILBitmapEffect object
        /// The IMILBitmapEffectPrimitive object
        ///  
        /// Critical - calls native code
        /// TreatAsSafe - as there is a demand 
        ///  
        [SecurityCritical, SecurityTreatAsSafe]
        unsafe static protected void InitializeBitmapEffect(SafeHandle /*IMILBitmapEffect */ outerObject, 
                 SafeHandle/* IMILBitmapEffectPrimitive */ innerObject)
        {
            SecurityHelper.DemandUIWindowPermission();
 
            HRESULT.Check(MS.Win32.PresentationCore.UnsafeNativeMethods.MILFactoryEffects.InitializeBitmapEffect(outerObject, innerObject));
        } 
 
        #endregion
 
        #region Public Methods
        /// 
        /// This returns the output at index 0
        ///  
        public BitmapSource GetOutput(BitmapEffectInput input)
        { 
            if (input == null) 
            {
                throw new ArgumentNullException("input"); 
            }

            // if we don't have the input set, we should not be calling the output property
            if (input.Input == null) 
            {
                throw new ArgumentException(SR.Get(SRID.Effect_No_InputSource), "input"); 
            } 

            if (input.Input == BitmapEffectInput.ContextInputSource) 
            {
                throw new InvalidOperationException(SR.Get(SRID.Effect_No_ContextInputSource, null));
            }
 
            BitmapSource inputSource = input.Input.Clone();
            if (UpdateUnmanagedGroupState() == false || 
                UpdateRenderContext(input, new Rect(0, 0, inputSource.PixelWidth, inputSource.PixelHeight)) == false) 
            {
                return inputSource; 
            }

            SetInputSource(UnmanagedEffectGroup, 0, inputSource);
 
            return GetOutput(UnmanagedEffectGroup, 0, RenderContext);
        } 
        #endregion 

        #region Internal Methods 

        /// 
        /// This returns a handle to the unmanaged group effect
        ///  
        internal SafeMILHandle UnmanagedEffectGroup
        { 
            get 
            {
                if (_unmanagedEffectGroup == null) 
                {
                    _unmanagedEffectGroup = Create(new Guid("AC9C1A9A-7E18-4F64-AC7E-47CF7F051E95"));
                }
 
                return _unmanagedEffectGroup;
            } 
 
            set
            { 
                _unmanagedEffectGroup = value;
            }
        }
 
        /// 
        /// This returns a handle to an unmanaged effect 
        ///  
        /// 
        private SafeHandle UnmanagedEffect 
        {
            get
            {
                if (_unmanagedEffect == null) 
                {
                    _unmanagedEffect = CreateUnmanagedEffect(); 
                } 

                return _unmanagedEffect; 
            }
        }

        ///  
        /// Returns the bounds of the visual to which the effect is applied
        ///  
        internal Rect VisualBounds 
        {
            get { return _visualBounds; } 
            set { _visualBounds = value; }
        }

        ///  
        /// This method is called before calling GetOutput on an effect.
        /// It gives a chance for the managed effect to update the properties 
        /// of the unmanaged object. 
        /// 
        internal void Internal_UpdateUnmanagedPropertyState(SafeHandle unmanagedEffect) 
        {
            UpdateUnmanagedPropertyState(unmanagedEffect);
        }
 

        ///  
        /// Returns a safe handle to an unmanaged effect clone 
        /// 
        unsafe internal SafeHandle Internal_CreateUnmanagedEffect() 
        {
            return CreateUnmanagedEffect();
        }
 
        private void SetupConnections()
        { 
            if (!_connectionsSetup) 
            {
                // Update the unmanaged connections 
                int iInputs = GetNumberInputs(UnmanagedEffect);
                for (int i = 0; i < iInputs; i++)
                {
                    BitmapEffectOutputConnector input = GetInteriorInputConnector(UnmanagedEffectGroup, i); 
                    GetInputConnector(UnmanagedEffect, i).ConnectTo(input);
                } 
 
                int iOutputs = GetNumberOutputs(UnmanagedEffect);
                for (int i = 0; i < iOutputs; i++) 
                {
                    BitmapEffectInputConnector output = GetInteriorOutputConnector(UnmanagedEffectGroup, i);
                    output.ConnectTo(GetOutputConnector(UnmanagedEffect, i));
                } 

                Add(UnmanagedEffectGroup, UnmanagedEffect); 
                _connectionsSetup = true; 
            }
        } 

        /// 
        /// Updates (propagates) all the properties to the unmanaged effect
        /// Wraps the effect with an group one 
        ///
        /// This method is only called if GetOutput is called directly on the 
        /// effect. 
        /// 
        ///  
        internal virtual bool UpdateUnmanagedGroupState()
        {
            UpdateUnmanagedPropertyState(UnmanagedEffect);
            SetupConnections(); 

            return GetNumberOutputs(UnmanagedEffect) > 0; 
        } 

        ///  
        /// Number of inputs to the effect
        /// 
        ///  unmanaged effect
        internal static int GetNumberInputs(SafeHandle unmanagedEffect) 
        {
            Debug.Assert(unmanagedEffect != null, "We should have been initialized first"); 
            uint numInputs; 
            HRESULT.Check(MS.Win32.PresentationCore.UnsafeNativeMethods.IMILBitmapEffect.GetNumberInputs(unmanagedEffect,
                                                                                                         out numInputs)); 
            return (int)numInputs;
        }

        ///  
        /// Number of outputs from the effect
        ///  
        ///  unmanaged effect 
        internal static int GetNumberOutputs(SafeHandle unmanagedEffect)
        { 
            Debug.Assert(unmanagedEffect != null, "We should have been initialized first");
            uint numOutputs;
            HRESULT.Check(MS.Win32.PresentationCore.UnsafeNativeMethods.IMILBitmapEffect.GetNumberOutputs(unmanagedEffect,
                                                                                                          out numOutputs)); 
            return (int)numOutputs;
        } 
 
        /// 
        /// Creates the effect given a guid. 
        /// 
        /// kind of effect
        /// 
        /// Critical - calls critical code method FactoryMaker.FactoryMaker 
        /// TreatAsSafe - as there is a demand
        ///  
        [SecurityCritical, SecurityTreatAsSafe] 
        internal static SafeMILHandle Create(Guid guid)
        { 
            SecurityHelper.DemandUIWindowPermission();
            SafeMILHandle bitmapEffect = null;
            using (FactoryMaker myFactory = new FactoryMaker())
            { 

                HRESULT.Check(MS.Win32.PresentationCore.UnsafeNativeMethods.MILFactoryEffects.CreateBitmapEffect( 
                    myFactory.FactoryPtr, 
                    ref guid,
                    out bitmapEffect)); 
            }
            return bitmapEffect;
        }
 
        /// 
        /// This is the render contect for the effect 
        ///  
        internal BitmapEffectRenderContext RenderContext
        { 
            get { return _renderContext; }
            set { _renderContext = value; }
        }
 
        /// 
        /// Updates the render context given the input 
        ///  
        /// 
        ///  
        private bool UpdateRenderContext(BitmapEffectInput input, Rect inputSize)
        {
            _renderContext.OutputPixelFormat = PixelFormats.Pbgra32;
            _renderContext.RenderRect = input.AreaToApplyEffect; 

            double dpiX = DefaultDevicePixelsPerInch, dpiY = DefaultDevicePixelsPerInch; 
            if (input.Input != BitmapEffectInput.ContextInputSource && input.Input != null) 
            {
                dpiX = input.Input.DpiX; 
                dpiY = input.Input.DpiY;
            }

            _renderContext.OutputDPI = new Point(dpiX, dpiY); 

            if (!input.AreaToApplyEffect.IsEmpty) 
            { 
                Rect area = input.AreaToApplyEffect;
 
                if (input.AreaToApplyEffectUnits == BrushMappingMode.RelativeToBoundingBox)
                {
                    checked
                    { 
                        // the inputSize here is in pixels (device space)
                        // the area is normalized, i.e. between (0, 0, 1, 1) 
                        area = new Rect(inputSize.X + area.X * inputSize.Width, 
                                        inputSize.Y + area.Y * inputSize.Height,
                                        area.Width * inputSize.Width, 
                                        area.Height * inputSize.Height);
                    }
                }
 
                area.Intersect(inputSize);
 
                _renderContext.RenderRect = area; 

                if (area.IsEmpty) 
                {
                    return false;
                }
            } 

            return true; 
        } 

        ///  
        /// Transform rectangle
        /// 
        /// input
        ///  
        /// 
        ///  
        internal Rect TransformRect(BitmapEffectInput input, Rect rect, bool fInverse) 
        {
            if (input == null) 
                throw new ArgumentNullException("input");

            if (rect == Rect.Empty)
                return rect; 

            if (UpdateUnmanagedGroupState() == false || 
                UpdateRenderContext(input, rect) == false) 
            {
                return new Rect(rect.X, rect.Y, rect.Width, rect.Height); 
            }

            return TransformRect(UnmanagedEffectGroup, 0, rect, !fInverse, RenderContext);
        } 

        ///  
        /// Returns true if the effect has an affine transform 
        /// Throws if there is anything wrong with setting up the effect state
        ///  
        private bool IsAffineTransformInternal()
        {
            // if update failed, assume identity
            if (UpdateUnmanagedGroupState() == false) 
                throw new BitmapEffectException();
 
            return HasAffineTransform(UnmanagedEffectGroup, 0); 
        }
 

        /// 
        /// Returns true if the effect has an affine transform
        ///  
        internal bool IsAffineTransform
        { 
            get 
            {
                try 
                {
                    return IsAffineTransformInternal();
                }
                catch (BitmapEffectException) 
                {
                    // return true if we failed to set up the effect 
                    // this means no effect will be applied 
                    // so we assume identity here
                    return true; 
                }
            }
        }
 
        /// 
        /// Return true if the effect's transform has an inverse 
        ///  
        internal bool IsInverseTransform
        { 
            get
            {
                // if update failed, assume identity
                if (UpdateUnmanagedGroupState() == false) 
                    return true;
 
 
                return HasInverseTransform(UnmanagedEffectGroup, 0);
            } 
        }

        /// 
        /// Returns the affine matrix if the effect has an affine transform 
        /// 
        ///  
        internal Matrix GetAffineMatrix() 
        {
            try 
            {
                if (IsAffineTransformInternal() == false)
                    throw new InvalidOperationException(SR.Get(SRID.Effect_Not_Affine, null));
            } 
            catch (BitmapEffectException)
            { 
                // return identity if we failed to set up the effect 
                // this means no effect will be applied
                return Matrix.Identity; 
            }

            return GetAffineMatrix(UnmanagedEffectGroup, 0);
        } 

        ///  
        /// Transforms a point 
        /// 
        /// Effect input 
        /// input point
        /// output point
        /// The direction in which the point is transformed
        ///  
        internal bool TransformPoint(BitmapEffectInput input, Point inPoint, out Point outPoint, bool fInverse)
        { 
            outPoint = inPoint; 

            // if this called failed, it means that we will never be able to actual 
            // call GetOutput either. that means the effect is a noop
            if (UpdateUnmanagedGroupState() == false)
                return true;
 
            // get the bounds of the image or visual.
            // if the effect is applied to a visual, we need to get the size of the 
            // visual and then apply the region of interest to it 
            // if the effect is applied to an image, we need to get the size of the image
            Rect rect = VisualBounds; 
            if (input.Input == BitmapEffectInput.ContextInputSource || input.Input == null)
            {
                if (rect == Rect.Empty)
                { 
                    rect = new Rect(inPoint, inPoint);
                } 
            } 
            else
            { 
                rect = new Rect(0, 0, input.Input.Width, input.Input.Height);
            }

            UpdateRenderContext(input, rect); 

            // reset bounds 
            VisualBounds = Rect.Empty; 

            bool fPointTransformed; 
            outPoint = TransformPoint(UnmanagedEffectGroup, 0, inPoint, !fInverse, RenderContext, out fPointTransformed);
            return fPointTransformed;
        }
        ///  
        /// Add the effect to the group effect
        ///  
        ///  the group effect 
        ///  the effect to add to the graph
        internal static void Add(SafeHandle effectGroup, SafeHandle effect) 
        {
            HRESULT.Check(MS.Win32.PresentationCore.UnsafeNativeMethods.IMILBitmapEffect.Add(
                effectGroup,
                effect)); 
        }
 
        ///  
        /// Sets the input source for a given input pin
        ///  
        ///  unmanaged effect
        /// index
        /// image
        ///  
        /// SecurityCritical: This is code that retrieves the WicSourceHandle which is critical
        /// SecurityTreatAsSafe: The inputs are safe and WicSourceHandle is not given out as well as there is a demand. 
        ///  
        [SecurityCritical, SecurityTreatAsSafe]
        internal static void SetInputSource(SafeHandle unmanagedEffect, int index, BitmapSource bitmap) 
        {
            SecurityHelper.DemandUIWindowPermission();
            Debug.Assert(unmanagedEffect != null, "We should have been initialized first");
 
            HRESULT.Check(MS.Win32.PresentationCore.UnsafeNativeMethods.IMILBitmapEffect.SetInputSource(unmanagedEffect, (uint)index,
                                                                                                bitmap.WicSourceHandle)); 
        } 

        ///  
        /// Returns the output of the effect on the given output pin
        /// 
        ///  unmanaged effect
        /// index 
        /// context
        ///  Bitmap source 
        internal static BitmapSource GetOutput(SafeHandle unmanagedEffect, int index, BitmapEffectRenderContext context) 
        {
            Debug.Assert(unmanagedEffect != null, "We should have been initialized first"); 

            BitmapSourceSafeMILHandle bitmapSource;
            HRESULT.Check(MS.Win32.PresentationCore.UnsafeNativeMethods.IMILBitmapEffect.GetOutput(unmanagedEffect, (uint)index,
                                                              context.NativeContextSafeHandle, out bitmapSource)); 

            return new UnmanagedBitmapWrapper(bitmapSource); 
        } 

        ///  
        /// Returns the connector object for a given input pin
        /// 
        ///  unmanaged effect
        /// Index of the connector 
        /// Input connector
        internal static BitmapEffectInputConnector GetInputConnector(SafeHandle unmanagedEffect, int index) 
        { 
            SafeMILHandle connector;
            HRESULT.Check(MS.Win32.PresentationCore.UnsafeNativeMethods.IMILBitmapEffect.GetInputConnector(unmanagedEffect, 
                                                                                                           (uint)index, out connector));
            return new BitmapEffectInputConnector(connector);
        }
 
        /// 
        /// Returns the connector object for a given output pin 
        ///  
        ///  unmanaged effect
        /// Index of the connector 
        /// Input connector
        internal static BitmapEffectOutputConnector GetOutputConnector(SafeHandle unmanagedEffect, int index)
        {
            SafeMILHandle connector; 
            HRESULT.Check(MS.Win32.PresentationCore.UnsafeNativeMethods.IMILBitmapEffect.GetOutputConnector(unmanagedEffect,
                                                                                                            (uint)index, out connector)); 
            return new BitmapEffectOutputConnector(connector); 
        }
 
        /// 
        /// Transforms a point by running it through the effect
        /// 
        ///  unmanaged effect 
        /// 
        ///  
        ///  
        /// 
        ///  
        /// 
        internal static Point TransformPoint(SafeHandle unmanagedEffect,
                                             int iIndex,
                                             Point point, 
                                             bool fForwardTransform,
                                             BitmapEffectRenderContext context, 
                                             out bool fPointTransformed) 
        {
            HRESULT.Check(MS.Win32.PresentationCore.UnsafeNativeMethods.IMILBitmapEffect.TransformPoint(unmanagedEffect, 
                                                                                                 (uint)iIndex, ref point,
                                                                                                 fForwardTransform,
                                                                                                 context.NativeContextSafeHandle,
                                                                                                 out fPointTransformed)); 
            return point;
        } 
 
        /// 
        /// Transforms a rectangle by running it through the effect 
        /// 
        ///  unmanaged effect
        /// 
        ///  
        /// 
        ///  
        ///  
        internal static Rect TransformRect(SafeHandle unmanagedEffect, int iIndex, Rect rect, bool fForwardTransform, BitmapEffectRenderContext context)
        { 
            HRESULT.Check(MS.Win32.PresentationCore.UnsafeNativeMethods.IMILBitmapEffect.TransformRect(
                unmanagedEffect,
                (uint)iIndex, ref rect,
                fForwardTransform, 
                context.NativeContextSafeHandle));
            return rect; 
        } 

        ///  
        /// Returns the interior output connector
        /// 
        ///  unmanaged group effect
        /// connector index 
        /// intput connector
        internal static BitmapEffectInputConnector GetInteriorOutputConnector(SafeHandle effect, int index) 
        { 
            SafeMILHandle connector;
            HRESULT.Check( 
                MS.Win32.PresentationCore.UnsafeNativeMethods.IMILBitmapEffect.GetInteriorOutputConnector(
                        effect,
                        (uint) index,
                        out connector)); 

            return new BitmapEffectInputConnector(connector); 
        } 

        ///  
        /// Returns the interior input connector
        /// 
        ///  unmanaged group effect
        /// connector index 
        /// outtput connector
        internal static BitmapEffectOutputConnector GetInteriorInputConnector(SafeHandle effect, int index) 
        { 
            SafeMILHandle connector;
            HRESULT.Check(MS.Win32.PresentationCore.UnsafeNativeMethods.IMILBitmapEffect.GetInteriorInputConnector(effect, 
                                                                                                  (uint)index, out connector));

            return new BitmapEffectOutputConnector(connector);
        } 

        ///  
        /// Returns true if the effect has an affine transform 
        /// 
        /// unmanaged effect 
        /// zero basex index
        /// 
        internal static bool HasAffineTransform(SafeHandle effect, int index)
        { 
            bool hasAffineTransform;
            HRESULT.Check(MS.Win32.PresentationCore.UnsafeNativeMethods.IMILBitmapEffect.HasAffineTransform(effect, 
                                                                                                  (uint)index, out hasAffineTransform)); 

            return hasAffineTransform; 
        }

        /// 
        /// Returns true if the effect's transform has an inverse 
        /// 
        /// unmanaged effect 
        /// zero bazed index 
        /// 
        internal static bool HasInverseTransform(SafeHandle effect, int index) 
        {
            bool hasInverseTransform;
            HRESULT.Check(MS.Win32.PresentationCore.UnsafeNativeMethods.IMILBitmapEffect.HasInverseTransform(effect,
                                                                                                  (uint)index, out hasInverseTransform)); 

            return hasInverseTransform; 
        } 

        ///  
        /// Returns an affine matrix if the effect transformation is affine
        /// 
        /// unmanaged effect
        /// zero based index 
        /// 
        internal static Matrix GetAffineMatrix(SafeHandle effect, int index) 
        { 
            MIL_MATRIX3X2D matrix = CompositionResourceManager.MatrixToMIL_MATRIX3X2D(new Matrix());
            HRESULT.Check(MS.Win32.PresentationCore.UnsafeNativeMethods.IMILBitmapEffect.GetAffineMatrix(effect, 
                                                                                                  (uint)index, ref matrix));


            return new Matrix(matrix.S_11, matrix.S_12, matrix.S_21, matrix.S_22, matrix.DX, matrix.DY); 
        }
 
        #endregion 

    } 
}


// 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