// ============================================================================
// Copyright © 2026 Hexagon Technology Center GmbH. All Rights Reserved.
// 文件名: GammaProcessor.cs
// 描述: Gamma校正算子,用于调整图像亮度和对比度
// 功能:
// - Gamma非线性校正
// - 增益调整
// - 使用查找表(LUT)加速处理
// - 适用于图像显示和亮度调整
// 算法: Gamma校正公式 output = (input^(1/gamma)) * gain
// 作者: 李伟 wei.lw.li@hexagon.com
// ============================================================================
using Emgu.CV;
using Emgu.CV.Structure;
using XP.ImageProcessing.Core;
using Serilog;
namespace XP.ImageProcessing.Processors;
///
/// Gamma校正算子(支持 8 位和 16 位灰度图像)
/// 16 位模式下 LUT 为 ushort[65536]
///
public class GammaProcessor : ImageProcessorBase
where TDepth : struct, IComparable
{
private static readonly ILogger _logger = Log.ForContext>();
public GammaProcessor()
{
Name = LocalizationHelper.GetString("GammaProcessor_Name");
Description = LocalizationHelper.GetString("GammaProcessor_Description");
}
protected override void InitializeParameters()
{
Parameters.Add("Gamma", new ProcessorParameter(
"Gamma",
LocalizationHelper.GetString("GammaProcessor_Gamma"),
typeof(double),
1.0,
0.1,
5.0,
LocalizationHelper.GetString("GammaProcessor_Gamma_Desc")));
Parameters.Add("Gain", new ProcessorParameter(
"Gain",
LocalizationHelper.GetString("GammaProcessor_Gain"),
typeof(double),
1.0,
0.1,
3.0,
LocalizationHelper.GetString("GammaProcessor_Gain_Desc")) { IsAdvanced = true });
_logger.Debug("InitializeParameters");
}
public override Image Process(Image inputImage)
{
double gamma = GetParameter("Gamma");
double gain = GetParameter("Gain");
if (typeof(TDepth) == typeof(ushort))
{
var lut16 = BuildLUT16(gamma, gain);
var img16 = inputImage as Image;
var result = new Image(inputImage.Width, inputImage.Height);
Parallel.For(0, inputImage.Height, y =>
{
for (int x = 0; x < inputImage.Width; x++)
result.Data[y, x, 0] = lut16[img16!.Data[y, x, 0]];
});
_logger.Debug("Process(16bit): Gamma={G}, Gain={Gain}", gamma, gain);
return (result as Image)!;
}
else
{
var lut8 = BuildLUT8(gamma, gain);
var result = (inputImage as Image)!.Clone();
int h = inputImage.Height, w = inputImage.Width;
for (int y = 0; y < h; y++)
for (int x = 0; x < w; x++)
result.Data[y, x, 0] = lut8[result.Data[y, x, 0]];
_logger.Debug("Process(8bit): Gamma={G}, Gain={Gain}", gamma, gain);
return (result as Image)!;
}
}
private static byte[] BuildLUT8(double gamma, double gain)
{
var lut = new byte[256];
double invGamma = 1.0 / gamma;
for (int i = 0; i < 256; i++)
{
double normalized = i / 255.0;
double corrected = Math.Pow(normalized, invGamma) * gain;
lut[i] = (byte)Math.Clamp((int)(corrected * 255.0), 0, 255);
}
return lut;
}
private static ushort[] BuildLUT16(double gamma, double gain)
{
var lut = new ushort[65536];
double invGamma = 1.0 / gamma;
for (int i = 0; i < 65536; i++)
{
double normalized = i / 65535.0;
double corrected = Math.Pow(normalized, invGamma) * gain;
lut[i] = (ushort)Math.Clamp((int)(corrected * 65535.0), 0, 65535);
}
return lut;
}
}