如何复现Photoshop亮度提升操作?求对应数学公式及C#实现
模拟Photoshop「亮度/对比度」亮度提升的C#实现
我已经掌握通过HSV提升颜色Value值的方法,但这种方式是对所有色调统一增幅,容易导致颜色泛白;而Photoshop的亮度操作会差异化处理不同色调,效果更自然。现在需要基于输入RGB颜色和亮度增量,通过数学公式计算出调整后的RGB颜色(示例中亮度增量为150)。
以下是基础代码框架:
// ARGB color public Color m_color = new Color(255, 255, 0, 255); public Color IncreaseBrightness(Color colorToModify, float brightnessAmount) { Color newColor = colorToModify; // 使用Photoshop公式按brightnessAmount提升newColor的RGB亮度(待实现) return newColor; } // 调用示例,需达到示例图片中的效果 IncreaseBrightness(m_color, 150f);
实现逻辑
Photoshop的「亮度/对比度」调整并非对RGB通道做线性增益,而是基于sRGB色彩空间与线性光转换的非线性映射,核心是对暗部区域的增益大于高光区域,避免高光过曝泛白。完整步骤如下:
- sRGB转线性RGB:将0-255的通道值转换为线性光空间,这是PS调整的基础
- 应用亮度调整公式:根据亮度增量对线性光值做差异化增益
- 线性RGB转回sRGB:将调整后的线性值转换回标准sRGB范围
关键公式
sRGB转线性RGB:
linear = norm <= 0.04045 ? norm / 12.92 : pow((norm + 0.055)/1.055, 2.4)其中
norm是通道值归一化到0-1的结果亮度调整(适配PS滑块范围[-100,100]):
if brightness >= 0: adjusted_linear = linear + (1 - linear) * (brightness / 100) else: adjusted_linear = linear * (1 + brightness / 100)线性RGB转回sRGB:
norm = adjusted_linear <= 0.0031308 ? adjusted_linear * 12.92 : 1.055 * pow(adjusted_linear, 1/2.4) - 0.055
完整C#代码实现
using System; using System.Drawing; public class BrightnessAdjuster { public Color m_color = Color.FromArgb(255, 255, 0, 255); public Color IncreaseBrightness(Color colorToModify, float brightnessAmount) { // 将输入的亮度增量(示例150)转换为PS滑块的[-100,100]范围 float psBrightness = brightnessAmount - 100f; // 处理红色通道 byte rAdjusted = AdjustChannel(colorToModify.R, psBrightness); // 处理绿色通道 byte gAdjusted = AdjustChannel(colorToModify.G, psBrightness); // 处理蓝色通道 byte bAdjusted = AdjustChannel(colorToModify.B, psBrightness); return Color.FromArgb(colorToModify.A, rAdjusted, gAdjusted, bAdjusted); } private byte AdjustChannel(byte channelValue, float brightness) { // 归一化到0-1 float norm = channelValue / 255f; // 转线性光 float linear = sRgbToLinear(norm); // 应用亮度调整 float adjustedLinear = ApplyBrightness(linear, brightness); // 转回sRGB并转为字节 return linearToSRgb(adjustedLinear); } private float sRgbToLinear(float norm) { return norm <= 0.04045f ? norm / 12.92f : (float)Math.Pow((norm + 0.055f) / 1.055f, 2.4f); } private byte linearToSRgb(float linear) { float norm = linear <= 0.0031308f ? linear * 12.92f : (float)(1.055f * Math.Pow(linear, 1 / 2.4f) - 0.055f); // 限制在0-1范围内,避免溢出 norm = Math.Clamp(norm, 0f, 1f); return (byte)Math.Round(norm * 255f); } private float ApplyBrightness(float linearValue, float brightness) { float adjusted; if (brightness >= 0) { // 提升亮度:暗部增益更大 adjusted = linearValue + (1 - linearValue) * (brightness / 100f); } else { // 降低亮度:高光衰减更小 adjusted = linearValue * (1 + brightness / 100f); } return Math.Clamp(adjusted, 0f, 1f); } // 测试调用 public void RunTest() { Color adjustedColor = IncreaseBrightness(m_color, 150f); // 输出调整后的颜色值,应匹配PS中亮度+50的效果 Console.WriteLine($"调整后颜色:A={adjustedColor.A}, R={adjustedColor.R}, G={adjustedColor.G}, B={adjustedColor.B}"); } }
说明
- 代码中
brightnessAmount参数若传入150,对应Photoshop亮度滑块调至+50的效果(PS滑块范围为-100到+100,这里将0映射为-100,200映射为+100),可根据需求调整转换逻辑 - 通过sRGB与线性光的转换,完全模拟PS的色彩空间调整逻辑,解决HSV Value提升导致的泛白问题
- 所有计算都做了区间限制,确保最终RGB值在0-255的有效范围内
内容的提问来源于stack exchange,提问作者flask
相关产品推荐
相关产品推荐

