WPF 对应用程序进行灰度设置
控件名:GrayscaleEffect
作 者:WPFDevelopersOrg - 驚鏵
原文链接[1]:https://github.com/WPFDevelopersOrg/WPFDevelopers
简易源码[2]:https://github.com/yanjinhuagood/WPFApplicationGrayscale
框架使用
.NET4 至 .NET6
;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.1.0.2-preview3推荐使用Shazzam Shader Editor[8]进行编辑。
1) GrayscaleEffect.hlsl
代码如下:
HLSL 语言编写的像素着色器(Pixel Shader)代码:
对输入纹理进行采样得到每个像素的颜色值。
对每个像素的 R、G、B 值进行除以 A 值操作,以避免由于透明度不同而产生的颜色变化。
对每个像素的亮度进行调整,通过修改 brightness
参数来控制亮度。
将每个像素转换为灰度值。
对转换后的每个像素的 R、G、B 值进行进一步的处理,通过修改 factor
参数来控制调整效果。
返回调整后的像素颜色值。
sampler2D
:纹理采样器类型,用于从纹理中提取像素颜色信息。register()
:用于定义常量寄存器和纹理寄存器等,类似于 C++ 中的变量声明。float
:浮点数类型。TEXCOORD
:纹理坐标通道类型,表示 UV 坐标数据。COLOR
:输出颜色类型,表示最终渲染的像素颜色信息。tex2D()
:采样纹理函数,用于从纹理中提取指定纹理坐标处的像素颜色值。sqrt()
:开方函数,用于计算灰度值。float4 result
:表示颜色值的四维向量类型。result.r
、result.g
、result.b
和 result.a
分别表示 RGB 值和 Alpha 值。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
代码如下:
继承自
ShaderEffect
类,并使用像素着色器(Pixel Shader)来实现灰度效果。在代码中定义了三个依赖属性,分别是
Input
、Factor
和Brightness
。其中:Input
属性表示作为着色器输入的Brush
对象,可以是任何可用的画刷类型。Factor
属性表示灰度效果的因子。Brightness
属性表示效果的亮度。
通过在构造函数中创建像素着色器对象,并将其设置为PixelShader
属性,以及使用UpdateShaderValue
方法更新着色器属性的值,完成特效的初始化工作。
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
代码如下,默认原色:
<wd: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:wd="https://github.com/WPFDevelopersOrg/WPFDevelopers">
<wd:Window.Effect>
<wd:GrayscaleEffect x:Name="grayscaleEffect" Factor="1"/>
</wd: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);
}
参考资料
原文链接: 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]Shazzam Shader Editor: https://github.com/JohanLarsson/Shazzam