yanjinhua

V1

2022/12/06阅读:21主题:蓝莹

如何对整个 WPF 应用程序进行灰度

如何对整个 WPF 应用程序进行灰度

控件名:GrayscaleEffect

作 者:WPFDevelopersOrg - 驚鏵

原文链接[1]:https://github.com/WPFDevelopersOrg/WPFDevelopers 简易源码[2]

  • 框架使用.NET40

  • Visual Studio 2019;

  • 如果要实现灰度第一反是使用主题色更改,但是使用主题色需要重新配色比较慢,需 Effect 类派生以实现自定义位图效果,将使用ShaderEffect[3]进行更改灰度,从 ShaderEffect 类派生,以基于单个像素着色器实现自定义效果。

  • 必须安装 .NET Framework 3.5 sp1 或更高版本才能正常工作。

  • 需要安装DirectX SDK才能编译像素着色器效果。
    • PixelShader[4]从预编译的高级着色语言 (HLSL) 字节代码加载 。
    • 定义表示效果参数和基于表面输入的 Brush 依赖属性。 使用其中 RegisterPixelShaderSamplerProperty[5] 一个重载将这些输入与 HLSL 字节码中引用的寄存器号相关联。
    • DirectX SDK[6]
    • 下载完成DirectX SDK安装完成。
  • 到安装目录下\Utilities\bin\x86执行以下命令,就会输出.ps文件。
  • Nuget 最新[7] Install-Package WPFDevelopers 1.0.9.5-preview
  • Nuget 最新[8] Install-Package WPFDevelopers..Minimal 1.0.0.1-preview
  • 推荐使用Shazzam Shader Editor进行编辑。

1) GrayscaleEffect.hlsl 代码如下:

sampler2D implicitInput : register(s0);
float factor : register(c0);

/// <summary>The brightness offset.</summary>
/// <minValue>-1</minValue>
/// <maxValue>1</maxValue>
/// <defaultValue>0</defaultValue>
float brightness : register(c1);

float4 main(float2 uv : TEXCOORD) : COLOR
{
    float4 pixelColor = tex2D(implicitInput, uv);
  pixelColor.rgb /= pixelColor.a;
    
  // Apply brightness.
  pixelColor.rgb += brightness;
    
  // Return final pixel color.
  pixelColor.rgb *= pixelColor.a;

    float4 color = pixelColor;

    float pr = .299;
    float pg = .587;
    float pb = .114;
    
    float gray = sqrt(color.r * color.r * pr + color.g * color.g * pg + color.b * color.b * pb);

  float4 result;    
  result.r = (color.r - gray) * factor + gray;
  result.g = (color.g - gray) * factor + gray;
  result.b = (color.b - gray) * factor + gray;
  result.a = color.a;
    
  return result;
}

2)执行命令 代码如下:

  fxc /T ps_2_0 /Fo E:\GrayscaleEffect\GrayscaleEffect.ps E:\GrayscaleEffect\GrayscaleEffect.hlsl

3)得到以下文件

4)新建GrayscaleEffect.cs 代码如下:

using System;
using System.Windows;
using System.Windows.Media;
using System.Windows.Media.Effects;

namespace WPFDevelopers
{
    public class GrayscaleEffect : ShaderEffect
    {
        /// <summary>
        /// Identifies the Input property.
        /// </summary>
        public static readonly DependencyProperty InputProperty = RegisterPixelShaderSamplerProperty("Input"typeof(GrayscaleEffect), 0);

        /// <summary>
        /// Identifies the Factor property.
        /// </summary>
        public static readonly DependencyProperty FactorProperty = DependencyProperty.Register("Factor"typeof(double), typeof(GrayscaleEffect), new UIPropertyMetadata(0D, PixelShaderConstantCallback(0)));

        /// <summary>
        /// Identifies the Brightness property.
        /// </summary>
        public static readonly DependencyProperty BrightnessProperty = DependencyProperty.Register("Brightness"typeof(double), typeof(GrayscaleEffect), new UIPropertyMetadata(0D, PixelShaderConstantCallback(1)));

        /// <summary>
        /// Creates a new instance of the <see cref="GrayscaleEffect"/> class.
        /// </summary>
        public GrayscaleEffect()
        {
            var pixelShader = new PixelShader();
            pixelShader.UriSource = new Uri("WPFDevelopers;component/Effects/GrayscaleEffect.ps", UriKind.Relative);

            PixelShader = pixelShader;

            UpdateShaderValue(InputProperty);
            UpdateShaderValue(FactorProperty);
            UpdateShaderValue(BrightnessProperty);
        }

        /// <summary>
        /// Gets or sets the <see cref="Brush"/> used as input for the shader.
        /// </summary>
        public Brush Input
        {
            get => ((Brush)(GetValue(InputProperty)));
            set => SetValue(InputProperty, value);
        }

        /// <summary>
        /// Gets or sets the factor used in the shader.
        /// </summary>
        public double Factor
        {
            get => ((double)(GetValue(FactorProperty)));
            set => SetValue(FactorProperty, value);
        }

        /// <summary>
        /// Gets or sets the brightness of the effect.
        /// </summary>
        public double Brightness
        {
            get => ((double)(GetValue(BrightnessProperty)));
            set => SetValue(BrightnessProperty, value);
        }
    }
}

5)使用Window.Xaml 代码如下,默认原色:

<wpfdev:Window x:Class="WPFDevelopers.Samples.MainWindow"
               xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
               xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
               xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
               xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
               xmlns:wpfdev="https://github.com/WPFDevelopersOrg/WPFDevelopers">

    <wpfdev:Window.Effect>
        <wpfdev:GrayscaleEffect x:Name="grayscaleEffect" Factor="1"/>
    </wpfdev:Window.Effect>
  <TextBlock Text="开启程序灰度" FontSize="20" Margin="0,20,0,0"/>
  <ToggleButton Margin="10" Name="tbGrayscale" 
                Checked="tbGrayscale_Checked"
                Unchecked="tbGrayscale_Unchecked"
                HorizontalAlignment="Left"/>

6)使用Window.Xaml.cs 灰度代码如下:

private void tbGrayscale_Checked(object sender, RoutedEventArgs e)
        {
            Create(0);
        }
        void Create(double to)
        {
            var sineEase = new SineEase() { EasingMode = EasingMode.EaseOut };
            var doubleAnimation = new DoubleAnimation
            {
                To = to,
                Duration = TimeSpan.FromMilliseconds(1000),
                EasingFunction = sineEase
            };
            grayscaleEffect.BeginAnimation(GrayscaleEffect.FactorProperty, doubleAnimation);
        }
        private void tbGrayscale_Unchecked(object sender, RoutedEventArgs e)
        {
            Create(1);
        }

参考资料

[1]

原文链接: https://github.com/WPFDevelopersOrg/WPFDevelopers

[2]

简易源码: https://github.com/yanjinhuagood/WPFApplicationGrayscale

[3]

ShaderEffect: https://learn.microsoft.com/zh-cn/dotnet/api/system.windows.media.effects.shadereffect?view=windowsdesktop-7.0

[4]

PixelShader: https://learn.microsoft.com/zh-cn/dotnet/api/system.windows.media.effects.pixelshader?view=windowsdesktop-7.0

[5]

RegisterPixelShaderSamplerProperty: https://learn.microsoft.com/zh-cn/dotnet/api/system.windows.media.effects.shadereffect.registerpixelshadersamplerproperty?view=windowsdesktop-7.0

[6]

DirectX SDK: https://www.microsoft.com/zh-cn/download/details.aspx?id=6812

[7]

Nuget : https://www.nuget.org/packages/WPFDevelopers/

[8]

Nuget : https://www.nuget.org/packages/WPFDevelopers.Minimal/

分类:

后端

标签:

C#

作者介绍

yanjinhua
V1