Color 結構表示轉換演算法參考 Wikipedia HSL color space。
功能:
Hue (0-360)、Saturation (0-1)、Lightness (0-1)、Alpha (0-255)ToString() 格式化輸出// RGB → HSL
double r = color.R / 255.0, g = color.G / 255.0, b = color.B / 255.0;
double min = Math.Min(Math.Min(r, g), b);
double max = Math.Max(Math.Max(r, g), b);
double delta = max - min;
_lightness = (max + min) / 2;
if (delta == 0) { _hue = 0; _saturation = 0; }
else {
_saturation = (_lightness < 0.5) ? delta / (max + min) : delta / (2 - max - min);
// 色相計算略...
_hue = (int)(hueTmp * 360);
}
// HSL → RGB
if (_saturation == 0) { r = g = b = (byte)(_lightness * 255); }
else {
double vH = _hue / 360.0;
double v2 = (_lightness < 0.5) ? _lightness * (1 + _saturation) : _lightness + _saturation - _lightness * _saturation;
double v1 = 2 * _lightness - v2;
r = (byte)(255 * HueToRGB(v1, v2, vH + 1/3.0));
g = (byte)(255 * HueToRGB(v1, v2, vH));
b = (byte)(255 * HueToRGB(v1, v2, vH - 1/3.0));
}
繼承 FilterColorToColor,使用 unsafe 指標 直接操作像素記憶體,大幅提升處理速度。編譯需勾選「允許不安全程式碼」。
protected override unsafe void ProcessFilter(BitmapData imageData)
{
int width = imageData.Width, height = imageData.Height;
int stride = imageData.Stride;
byte* ptr = (byte*)imageData.Scan0.ToPointer();
HSLColor hsl = new HSLColor();
for (int y = 0; y < height; y++)
{
byte* row = ptr + y * stride;
for (int x = 0; x < width; x++)
{
// 像素順序 BGR (2,1,0)
Color rgb = Color.FromArgb(row[2], row[1], row[0]);
hsl.Color = rgb;
hsl.Hue += _hue;
hsl.Saturation += _saturation;
hsl.Lightness += _lightness;
rgb = hsl.Color;
row[2] = rgb.R; row[1] = rgb.G; row[0] = rgb.B;
}
}
}
原圖 → 調整 Hue/Saturation/Lightness 後的圖片對比:
