主頁 > .NET開發 > 【Openxml】顏色變化屬性計算

【Openxml】顏色變化屬性計算

2022-06-14 06:47:33 .NET開發

Openxml的顏色變化屬性

目前Openxml存在顏色變化屬性如下:

引數 說明
Hue 色調(色相)
HueModulate 色調調制,百分比
HueOffset 色調偏移量,角度值
Saturation 飽和度
SaturationModulation 飽和度調制,百分比
SaturationOffset 飽和度偏移量
Luminance 亮度
LuminanceModulation 亮度調制,百分比
LuminanceOffset 亮度偏移量
Alpha Alpha
AlphaModulation Alpha 調制,百分比
AlphaOffset Alpha 偏移量
Red 紅色
RedModulation 紅色調制,百分比
RedOffset 紅色偏移量
Blue 藍色
BlueModification 藍色調制
BlueOffse 藍色偏移量,百分比
Green 綠色
GreenModification 綠色調制,百分比
GreenOffset 綠色偏移量
Complement 補充
Gamma 伽瑪
Gray 灰色
Inverse 反函式
Inverse Gamma 反函式伽瑪
Shade 底紋,百分比
Tint 底紋,百分比

RGB和Hsl的相互轉換

其中有關RGB和Hsl的相互轉換的公式如下:

RGB轉Hsl公式如下:

Hsl轉RGB公式如下:

其中涉及到有Hsl計算的有以下九個屬性:

  • Hue、HueModulate、HueOffset
  • Saturation、SaturationModulation、SaturationOffset
  • Luminance、LuminanceModulation、LuminanceOffset

那么我們開始寫代碼:

定義RGB的類:

    /// <summary>
    /// 用 A R G B 表示的顏色
    /// </summary>
    public class ARgbColor
    {
        /// <summary>
        /// 創建 A R G B 顏色
        /// </summary>
        public ARgbColor()
        {
        }

        /// <summary>
        /// 創建 A R G B 顏色
        /// </summary>
        /// <param name="a"></param>
        /// <param name="r"></param>
        /// <param name="g"></param>
        /// <param name="b"></param>
        public ARgbColor(byte a, byte r, byte g, byte b)
        {
            A = a;
            R = r;
            G = g;
            B = b;
        }

        /// <summary>
        /// 表示透明色
        /// </summary>
        public byte A { set; get; }

        /// <summary>
        /// 表示紅色
        /// </summary>
        public byte R { set; get; }

        /// <summary>
        /// 表示綠色
        /// </summary>
        public byte G { set; get; }

        /// <summary>
        /// 表示藍色
        /// </summary>
        public byte B { set; get; }

    }

定義顏色變化相關類ColorTransform,并且定義RGB和Hsl的相互轉換邏輯方法:

    /// <summary>
    ///     處理顏色之間的變換,調整,格式轉換
    /// </summary>
    public static class ColorTransform
    {

        /// <summary>
        ///  將<see cref="Color" />的資料轉換為Hsl
        /// </summary>
        /// <param name="color"></param>
        /// <returns></returns>
        public static (Degree hue, Percentage sat, Percentage lum, byte alpha) ColorToHsl(Color color)
        {
            var max = System.Math.Max(color.R, System.Math.Max(color.G, color.B));
            var min = System.Math.Min(color.R, System.Math.Min(color.G, color.B));
            var delta = max - min;
            var l = Percentage.FromDouble((max + min) / 2.0 / 255.0);
            var h = Degree.FromDouble(0);
            var s = Percentage.Zero;

            if (delta > 0)
            {
                s = l < Percentage.FromDouble(0.5)
                    ? Percentage.FromDouble((max - min) * 1.0 / (max + min))
                    : Percentage.FromDouble((max - min) * 1.0 / (2 * 255 - max - min));

                if (max == color.R)
                {
                    h = Degree.FromDouble((0 + (color.G - color.B) * 1.0 / delta) * 60);
                }
                else if (max == color.G)
                {
                    h = Degree.FromDouble((2 + (color.B - color.R) * 1.0 / delta) * 60);
                }
                else
                {
                    h = Degree.FromDouble((4 + (color.R - color.G) * 1.0 / delta) * 60);
                }
            }

            return (h, s, l, color.A);
        }

    }

            /// <summary>
        ///     將Hsl的資料轉換為<see cref="Color" />
        /// </summary>
        /// <param name="hue">色相</param>
        /// <param name="saturation">飽和度</param>
        /// <param name="lightness">亮度</param>
        /// <param name="a">透明度</param>
        /// <returns></returns>
        public static Color HslToColor(Degree hue, Percentage saturation, Percentage lightness, byte a = 0xFF)
        {
            var color = new Color { A = a };

            var hueValue = https://www.cnblogs.com/ryzen/p/hue.DoubleValue;
            var saturationValue = saturation.DoubleValue;
            var lightnessValue = lightness.DoubleValue;

            var c = (1 - System.Math.Abs(2 * lightnessValue - 1)) * saturationValue;
            var x = c * (1 - System.Math.Abs((hueValue / 60) % 2 - 1));
            var m = lightnessValue - c / 2;

            var r = 0d;
            var g = 0d;
            var b = 0d;

            if (hueValue is >= 0 and < 60)
            {
                r = c;
                g = x;
                b = 0;
            }

            if (hueValue is >= 60 and < 120)
            {
                r = x;
                g = c;
                b = 0;
            }

            if (hueValue is >= 120 and < 180)
            {
                r = 0;
                g = c;
                b = x;
            }

            if (hueValue is >= 180 and < 240)
            {
                r = 0;
                g = x;
                b = c;
            }

            if (hueValue is >= 240 and < 300)
            {
                r = x;
                g = 0;
                b = c;
            }

            if (hueValue is >= 300 and < 360)
            {
                r = c;
                g = 0;
                b = x;
            }

            color.R = (byte) ((r + m) * 255);
            color.G = (byte) ((g + m) * 255);
            color.B = (byte) ((b + m) * 255);

            return color;
        }


然后我們來寫真正處理Openxml的Hsl相關屬性邏輯:

       /// <summary>
        ///     將<see cref="RgbColorModelHex" />轉換為<see cref="Color" />
        /// </summary>
        /// <param name="color"></param>
        /// <returns></returns>
        public static Color? ToColor(this RgbColorModelHex color)
        {
            if (color.Val is not null)
            {
                if (uint.TryParse(color.Val.Value, NumberStyles.HexNumber, null, out var result))
                {
                    var solidColor = result.HexToColor();
                    var modifiedColor = ColorTransform.AppendColorModify(solidColor, color.ChildElements);
                    return modifiedColor;
                }
            }

            return null;
        }


        private static Color HexToColor(this uint rgb)
        {
            var color = new Color();
            const int maxByte = 0xff;

            color.B = (byte) (rgb & maxByte);
            color.G = (byte) ((rgb >> 8) & maxByte);
            color.R = (byte) ((rgb >> 16) & maxByte);
            color.A = 0xFF;

            return color;
        }

        /// <summary>
        /// 給顏色疊加轉換
        /// </summary>
        /// <param name="color"></param>
        /// <param name="list"></param>
        /// <returns></returns>
        public static Color AppendColorModify(ARgbColor color, OpenXmlElementList list)
        {
            var updatedColor = color;
            foreach (var element in list)
            {
                if (element is Hue hue)
                {
                    updatedColor = HandleHue(updatedColor, hue, null, null);
                    continue;
                }

                if (element is HueModulation hueModulation)
                {
                    updatedColor = HandleHue(updatedColor, null, hueModulation, null);
                    continue;
                }

                if (element is HueOffset hueOffset)
                {
                    updatedColor = HandleHue(updatedColor, null, null, hueOffset);
                    continue;
                }

                if (element is Saturation saturation)
                {
                    updatedColor = HandleSaturation(updatedColor, saturation, null, null);
                    continue;
                }

                if (element is SaturationModulation saturationModulation)
                {
                    updatedColor = HandleSaturation(updatedColor, null, saturationModulation, null);
                    continue;
                }

                if (element is SaturationOffset saturationOffset)
                {
                    updatedColor = HandleSaturation(updatedColor, null, null, saturationOffset);
                    continue;
                }

                if (element is Luminance luminance)
                {
                    updatedColor = HandleLuminance(updatedColor, luminance, null, null);
                    continue;
                }

                if (element is LuminanceModulation luminanceModulation)
                {
                    updatedColor = HandleLuminance(updatedColor, null, luminanceModulation, null);
                    continue;
                }

                if (element is LuminanceOffset luminanceOffset)
                {
                    updatedColor = HandleLuminance(updatedColor, null, null, luminanceOffset);
                    continue;
                }
            }


        private static Color HandleHue(Color color, Hue? hueElement, HueModulation? hueModElement,
            HueOffset? hueOffsetElement)
        {
            if (hueElement is null && hueModElement is null && hueOffsetElement is null)
            {
                return color;
            }

            var updatedColor = HandleHslCore(color, hueElement: hueElement, hueModElement: hueModElement, hueOffsetElement: hueOffsetElement);

            return updatedColor;
        }

        private static Color HandleSaturation(Color color, Saturation? satElement, SaturationModulation? satModElement,
            SaturationOffset? satOffsetElement)
        {
            if (satElement is null && satModElement is null && satOffsetElement is null)
            {
                return color;
            }

            var updatedColor = HandleHslCore(color, satElement: satElement, satModElement: satModElement, satOffsetElement: satOffsetElement);

            return updatedColor;
        }

        private static Color HandleLuminance(Color color, Luminance? lumElement, LuminanceModulation? lumModElement,
            LuminanceOffset? lumOffsetElement)
        {
            if (lumElement is null && lumModElement is null && lumOffsetElement is null)
            {
                return color;
            }

            var updatedColor = HandleHslCore(color, lumElement: lumElement, lumModElement: lumModElement, lumOffsetElement: lumOffsetElement);

            return updatedColor;
        }


        private static Color HandleHslCore(Color color,
            Hue? hueElement = null, HueModulation? hueModElement = null, HueOffset? hueOffsetElement = null,
            Saturation? satElement = null, SaturationModulation? satModElement = null, SaturationOffset? satOffsetElement = null,
            Luminance? lumElement = null, LuminanceModulation? lumModElement = null, LuminanceOffset? lumOffsetElement = null)
        {
            if (hueElement is null && hueModElement is null && hueOffsetElement is null
                && satElement is null && satModElement is null && satOffsetElement is null
                && lumElement is null && lumModElement is null && lumOffsetElement is null)
            {
                return color;
            }

            var (hue, sat, lum, alpha) = ColorToHsl(color);

            var hueElementVal = hueElement?.Val;
            var hueValue = https://www.cnblogs.com/ryzen/p/hueElementVal is not null ? new Angle(hueElementVal).ToDegreeValue() : hue.DoubleValue;
            var satElementVal = satElement?.Val;
            var satValue = satElementVal is not null ? new Percentage(satElementVal).DoubleValue : sat.DoubleValue;
            var lumElementVal = lumElement?.Val;
            var lumValue = lumElementVal is not null ? new Percentage(lumElementVal).DoubleValue : lum.DoubleValue;

            var hueModElementVal = hueModElement?.Val;
            var hueModValue = hueModElementVal is not null && hueModElementVal.HasValue
                ? new Percentage(hueModElementVal)
                : Percentage.FromDouble(1);
            var satModElementVal = satModElement?.Val;
            var satModValue = satModElementVal is not null && satModElementVal.HasValue
                ? new Percentage(satModElementVal)
                : Percentage.FromDouble(1);
            var lumModElementVal = lumModElement?.Val;
            var lumModValue = lumModElementVal is not null && lumModElementVal.HasValue
                ? new Percentage(lumModElementVal)
                : Percentage.FromDouble(1);

            var hueOffsetVal = hueOffsetElement?.Val;
            var hueOffset = hueOffsetVal is not null && hueOffsetVal.HasValue
                ? new Angle(hueOffsetVal).ToDegreeValue()
                : new Angle(0).ToDegreeValue();
            var saturationOffsetVal = satOffsetElement?.Val;
            var saturationOffset = saturationOffsetVal is not null && saturationOffsetVal.HasValue
                ? new Percentage(saturationOffsetVal)
                : Percentage.Zero;
            var lumOffsetElementVal = lumOffsetElement?.Val;
            var lumOffset = lumOffsetElementVal is not null && lumOffsetElementVal.HasValue
                ? new Percentage(lumOffsetElementVal)
                : Percentage.Zero;

            var hueResult = hueValue * hueModValue.DoubleValue + hueOffset;
            hue = Degree.FromDouble(hueResult);

            var satResult = satValue * satModValue.DoubleValue + saturationOffset.DoubleValue;
            sat = Percentage.FromDouble(satResult);
            sat = sat > Percentage.FromDouble(1) ? Percentage.FromDouble(1) : sat;
            sat = sat < Percentage.Zero ? Percentage.Zero : sat;

            var lumResult = lumValue * lumModValue.DoubleValue + lumOffset.DoubleValue;
            lum = Percentage.FromDouble(lumResult);
            lum = lum > Percentage.FromDouble(1) ? Percentage.FromDouble(1) : lum;
            lum = lum < Percentage.Zero ? Percentage.Zero : lum;

            return HslToColor(hue, sat, lum, alpha);

        }



處理RGB相關屬性

涉及到RGB相關的Openxml屬性如下:

  • 透明度:Alpha、AlphaModulation、AlphaOffset
  • RGB的紅色:Red、RedModulation、RedOffset
  • RGB的藍色:Blue、BlueModulation、BlueOffset
  • RGB的綠色:Green、GreenModulation、GreenOffset
  • RGB的反函式:Inverse
  • RGB的補碼: Complement
  • RGB的伽瑪校正和反伽瑪矯正: Gamma、InverseGamma
  • RGB的灰階(灰度):Gray

處理透明度

以下為處理透明度的邏輯代碼:

  
        private static Color HandleAlphaModify(Color color, Alpha? alphaElement, AlphaModulation? alphaModulation, AlphaOffset? alphaOffset)
        {
            if (alphaElement is null && alphaModulation is null && alphaOffset is null)
            {
                return color;
            }

            var alphaValue = https://www.cnblogs.com/ryzen/p/alphaElement?.Val;
            var modulationVal = alphaModulation?.Val;
            var offsetVal = alphaOffset?.Val;

            var alpha = alphaValue is not null && alphaValue.HasValue
                ? new Percentage(alphaValue)
                : Percentage.FromDouble(1);

            var mod = modulationVal is not null && modulationVal.HasValue
                ? new Percentage(modulationVal)
                : Percentage.FromDouble(1);

            var off = offsetVal is not null && offsetVal.HasValue
                ? new Percentage(offsetVal)
                : Percentage.Zero;


            var alphaResult = alpha.DoubleValue * mod.DoubleValue + off.DoubleValue;
            color.A = (byte) (color.A * alphaResult);


            return color;
        }        

處理RGB的紅色、藍色、綠色

以下為處理RGB的紅色、藍色、綠色的邏輯代碼:


        private static Color HandleRgb(Color color, Red? redElement, Green? greenElement, Blue? blueElement)
        {
            if (redElement is null && greenElement is null && blueElement is null)
            {
                return color;
            }

            var updatedColor = HandleRgbCore(color, redElement: redElement, greenElement: greenElement,
                blueElement: blueElement);


            return updatedColor;
        }
        private static Color HandleRgbModulation(Color color, RedModulation? redModulationElement, GreenModulation? greenModulationElement, BlueModulation? blueModulationElement)
        {
            if (redModulationElement is null && greenModulationElement is null && blueModulationElement is null)
            {
                return color;
            }

            var updatedColor = HandleRgbCore(color, redModulationElement: redModulationElement,
                greenModulationElement: greenModulationElement, blueModulationElement: blueModulationElement);


            return updatedColor;
        }


        private static Color HandleRgbOffset(Color color, RedOffset? redOffsetElement, GreenOffset? greenOffsetElement, BlueOffset? blueOffsetElement)
        {
            if (redOffsetElement is null && blueOffsetElement is null && greenOffsetElement is null)
            {
                return color;
            }

            var updatedColor = HandleRgbCore(color, redOffsetElement: redOffsetElement,
                greenOffsetElement: greenOffsetElement, blueOffsetElement: blueOffsetElement);


            return updatedColor;
        }


         private static Color HandleRgbCore(Color color,
            Red? redElement = null, Green? greenElement = null, Blue? blueElement = null,
            RedModulation? redModulationElement = null, GreenModulation? greenModulationElement = null, BlueModulation? blueModulationElement = null,
            RedOffset? redOffsetElement = null, GreenOffset? greenOffsetElement = null, BlueOffset? blueOffsetElement = null)
        {
            if (redElement is null && greenElement is null && blueElement is null
                && redModulationElement is null && greenModulationElement is null && blueModulationElement is null
                && redOffsetElement is null && greenOffsetElement is null && blueOffsetElement is null)
            {
                return color;
            }

            var updatedColor = color;

            var redModulationValue = https://www.cnblogs.com/ryzen/p/redModulationElement?.Val;
            var redMod = redModulationValue is not null ? new Percentage(redModulationValue) : Percentage.FromDouble(1);

            var greenModulationValue = greenModulationElement?.Val;
            var greenMod = greenModulationValue is not null ? new Percentage(greenModulationValue) : Percentage.FromDouble(1);

            var blueModulationValue = blueModulationElement?.Val;
            var blueMod = blueModulationValue is not null ? new Percentage(blueModulationValue) : Percentage.FromDouble(1);

            var redOffsetValue = redOffsetElement?.Val;
            var redOffset = redOffsetValue is not null ? new Percentage(redOffsetValue) : Percentage.FromDouble(0);

            var greenOffsetValue = greenOffsetElement?.Val;
            var greenOffset = greenOffsetValue is not null ? new Percentage(greenOffsetValue) : Percentage.FromDouble(0);

            var blueOffsetValue = blueOffsetElement?.Val;
            var blueOffset = blueOffsetValue is not null ? new Percentage(blueOffsetValue) : Percentage.FromDouble(0);


            var linearR = SRgbToLinearRgb(updatedColor.R / 255.0);
            var linearG = SRgbToLinearRgb(updatedColor.G / 255.0);
            var linearB = SRgbToLinearRgb(updatedColor.B / 255.0);

            var redValue = redElement?.Val;
            var red = redValue is not null ? new Percentage(redValue).DoubleValue : linearR;

            var greenValue = greenElement?.Val;
            var green = greenValue is not null ? new Percentage(greenValue).DoubleValue : linearG;

            var blueValue = blueElement?.Val;
            var blue = blueValue is not null ? new Percentage(blueValue).DoubleValue : linearB;

            var redResult = red * redMod.DoubleValue + redOffset.DoubleValue;
            var greenResult = green * greenMod.DoubleValue + greenOffset.DoubleValue;
            var blueResult = blue * blueMod.DoubleValue + blueOffset.DoubleValue;


            var r = redResult < 0 ? 0 : redResult > 1 ? 1 : redResult;
            var g = greenResult < 0 ? 0 : greenResult > 1 ? 1 : greenResult;
            var b = blueResult < 0 ? 0 : blueResult > 1 ? 1 : blueResult;
            updatedColor.R = (byte) System.Math.Round(255 * LinearRgbToSRgb(r));
            updatedColor.G = (byte) System.Math.Round(255 * LinearRgbToSRgb(g));
            updatedColor.B = (byte) System.Math.Round(255 * LinearRgbToSRgb(b));

            return updatedColor;
        }

        /// 
        /// https://en.wikipedia.org/wiki/SRGB#The_forward_transformation_.28CIE_xyY_or_CIE_XYZ_to_sRGB.29
        /// 
        /// 

RGB的反函式

以下為處理RGB的反函式的邏輯代碼:

        private static Color HandleInverse(Color color, Inverse? inverseElement)
        {
            var updatedColor = color;
            if (inverseElement != null)
            {
                var linearR = SRgbToLinearRgb(updatedColor.R / 255.0);
                var linearG = SRgbToLinearRgb(updatedColor.G / 255.0);
                var linearB = SRgbToLinearRgb(updatedColor.B / 255.0);
                var r = System.Math.Abs(1.0 - linearR);
                var g = System.Math.Abs(1.0 - linearG);
                var b = System.Math.Abs(1.0 - linearB);
                updatedColor.R = (byte) System.Math.Round(255 * LinearRgbToSRgb(r));
                updatedColor.G = (byte) System.Math.Round(255 * LinearRgbToSRgb(g));
                updatedColor.B = (byte) System.Math.Round(255 * LinearRgbToSRgb(b));
            }

            return updatedColor;
        }

RGB的補碼

以下為處理RGB的補碼的邏輯代碼:


        private static Color HandleComplement(Color color, Complement? complementElement)
        {
            var updatedColor = color;
            if (complementElement != null)
            {
                var r = updatedColor.B;
                var g = updatedColor.R + updatedColor.B - updatedColor.G;
                var b = updatedColor.R;
                updatedColor.R = r;
                updatedColor.G = (byte) g;
                updatedColor.B = b;
            }

            return updatedColor;
        }

RGB的伽瑪校正和反伽瑪矯正

伽瑪校正

?實際上就是顯示幕的非線性特性讓亮度在我們眼中看起來更好, 但是在渲染時反而會因此導致問題. 我們的渲染計算都是在伽馬值為 1 的理想線性空間進行的,而顯示幕的非線性則是伽馬值為 2.2計算的即為輸入值的pow 2.2,伽馬校正的思路就是在顏色被輸送到顯示幕之前, 我們先對其進行 pow 1/2.2 的逆運算以抵消顯示幕的作用

因此計算伽瑪校正的邏輯代碼如下:


        /// <summary>
        /// 對于sRGB的伽瑪校正,也就是 1/2.2的冪運算
        /// </summary>
        /// <param name="color"></param>
        /// <param name="gammaElement"></param>
        /// <returns></returns>
        private static Color HandleGamma(Color color, Gamma? gammaElement)
        {
            var updatedColor = color;
            if (gammaElement != null)
            {
                var r = System.Math.Pow(updatedColor.R / 255.0, 1 / 2.2);
                var g = System.Math.Pow(updatedColor.G / 255.0, 1 / 2.2);
                var b = System.Math.Pow(updatedColor.B / 255.0, 1 / 2.2);
                updatedColor.R = (byte) System.Math.Round(255 * r);
                updatedColor.G = (byte) System.Math.Round(255 * g);
                updatedColor.B = (byte) System.Math.Round(255 * b);
            }

            return updatedColor;
        }

而對于反伽瑪校正,則其指數為2.2,代碼如下:


        /// <summary>
        /// 對于sRGB的反伽瑪校正,也就是2.2的冪運算
        /// </summary>
        /// <param name="color"></param>
        /// <param name="inverseGammaElement"></param>
        /// <returns></returns>
        private static Color HandleInverseGamma(Color color, InverseGamma? inverseGammaElement)
        {
            var updatedColor = color;
            if (inverseGammaElement != null)
            {
                var r = System.Math.Pow(updatedColor.R / 255.0, 2.2);
                var g = System.Math.Pow(updatedColor.G / 255.0, 2.2);
                var b = System.Math.Pow(updatedColor.B / 255.0, 2.2);
                updatedColor.R = (byte) System.Math.Round(255 * r);
                updatedColor.G = (byte) System.Math.Round(255 * g);
                updatedColor.B = (byte) System.Math.Round(255 * b);
            }

            return updatedColor;
        }

RGB的灰階

不同的RGB空間,灰階的計算公式有所不同,常見的幾種RGB空間的計算灰階的公式如下:

//簡化 sRGB IEC61966-2.1 [gamma=2.20]
Gray = (R^2.2 * 0.2126  + G^2.2  * 0.7152  + B^2.2  * 0.0722)^(1/2.2)

//Adobe RGB (1998) [gamma=2.20]
Gray = (R^2.2 * 0.2973  + G^2.2  * 0.6274  + B^2.2  * 0.0753)^(1/2.2)

//Apple RGB [gamma=1.80]
Gray = (R^1.8 * 0.2446  + G^1.8  * 0.6720  + B^1.8  * 0.0833)^(1/1.8)

//ColorMatch RGB [gamma=1.8]
Gray = (R^1.8 * 0.2750  + G^1.8  * 0.6581  + B^1.8  * 0.0670)^(1/1.8)

//簡化 KODAK DC Series Digital Camera [gamma=2.2]
Gray = (R^2.2 * 0.2229  + G^2.2  * 0.7175  + B^2.2  * 0.0595)^(1/2.2)

而我們選擇了灰度系數2.2,即伽馬值為2.2的sRGB的計算公式,那么邏輯代碼如下:

        /// <summary>
        /// 對于sRGB的灰階計算
        /// </summary>
        /// <param name="color"></param>
        /// <param name="grayElement"></param>
        /// <returns></returns>
        /// sRGB IEC61966-2.1 [gamma=2.20]:sRGB計算灰階:Gray = (R^2.2 * 0.2126  + G^2.2  * 0.7152  + B^2.2  * 0.0722)^(1/2.2)
        private static Color HandleGray(Color color, Gray? grayElement)
        {
            var updatedColor = color;
            if (grayElement != null)
            {
                var gray = System.Math.Pow(
                          System.Math.Pow(updatedColor.R, 2.2) * 0.2126 +
                          System.Math.Pow(updatedColor.G, 2.2) * 0.7152 +
                          System.Math.Pow(updatedColor.B, 2.2) * 0.0722,
                          1 / 2.2);

                var grayResult = (byte) System.Math.Round(gray);

                updatedColor.R = grayResult;
                updatedColor.G = grayResult;
                updatedColor.B = grayResult;
            }

            return updatedColor;
        }

參考

  • 將RGB值轉換為灰度值的簡單演算法
  • 伽馬校正(Gamma Correction)與sRGB
  • RGB to HSL converter | color conversion
  • HSL to RGB conversion | color conversion
  • dotnet OpenXML 顏色變換

轉載請註明出處,本文鏈接:https://www.uj5u.com/net/490096.html

標籤:C#

上一篇:C#學習19————方法呼叫的4個例子

下一篇:使用javascript有效地搜索字串陣列中的字母

標籤雲
其他(157675) Python(38076) JavaScript(25376) Java(17977) C(15215) 區塊鏈(8255) C#(7972) AI(7469) 爪哇(7425) MySQL(7132) html(6777) 基礎類(6313) sql(6102) 熊猫(6058) PHP(5869) 数组(5741) R(5409) Linux(5327) 反应(5209) 腳本語言(PerlPython)(5129) 非技術區(4971) Android(4554) 数据框(4311) css(4259) 节点.js(4032) C語言(3288) json(3245) 列表(3129) 扑(3119) C++語言(3117) 安卓(2998) 打字稿(2995) VBA(2789) Java相關(2746) 疑難問題(2699) 细绳(2522) 單片機工控(2479) iOS(2429) ASP.NET(2402) MongoDB(2323) 麻木的(2285) 正则表达式(2254) 字典(2211) 循环(2198) 迅速(2185) 擅长(2169) 镖(2155) 功能(1967) .NET技术(1958) Web開發(1951) python-3.x(1918) HtmlCss(1915) 弹簧靴(1913) C++(1909) xml(1889) PostgreSQL(1872) .NETCore(1853) 谷歌表格(1846) Unity3D(1843) for循环(1842)

熱門瀏覽
  • WebAPI簡介

    Web體系結構: 有三個核心:資源(resource),URL(統一資源識別符號)和表示 他們的關系是這樣的:一個資源由一個URL進行標識,HTTP客戶端使用URL定位資源,表示是從資源回傳資料,媒體型別是資源回傳的資料格式。 接下來我們說下HTTP. HTTP協議的系統是一種無狀態的方式,使用請求/ ......

    uj5u.com 2020-09-09 22:07:47 more
  • asp.net core 3.1 入口:Program.cs中的Main函式

    本文分析Program.cs 中Main()函式中代碼的運行順序分析asp.net core程式的啟動,重點不是剖析原始碼,而是理清程式開始時執行的順序。到呼叫了哪些實體,哪些法方。asp.net core 3.1 的程式入口在專案Program.cs檔案里,如下。ususing System; us ......

    uj5u.com 2020-09-09 22:07:49 more
  • asp.net網站作為websocket服務端的應用該如何寫

    最近被websocket的一個問題困擾了很久,有一個需求是在web網站中搭建websocket服務。客戶端通過網頁與服務器建立連接,然后服務器根據ip給客戶端網頁發送資訊。 其實,這個需求并不難,只是剛開始對websocket的內容不太了解。上網搜索了一下,有通過asp.net core 實作的、有 ......

    uj5u.com 2020-09-09 22:08:02 more
  • ASP.NET 開源匯入匯出庫Magicodes.IE Docker中使用

    Magicodes.IE在Docker中使用 更新歷史 2019.02.13 【Nuget】版本更新到2.0.2 【匯入】修復單列匯入的Bug,單元測驗“OneColumnImporter_Test”。問題見(https://github.com/dotnetcore/Magicodes.IE/is ......

    uj5u.com 2020-09-09 22:08:05 more
  • 在webform中使用ajax

    如果你用過Asp.net webform, 說明你也算是.NET 開發的老兵了。WEBform應該是2011 2013左右,當時還用visual studio 2005、 visual studio 2008。后來基本都用的是MVC。 如果是新開發的專案,估計沒人會用webform技術。但是有些舊版 ......

    uj5u.com 2020-09-09 22:08:50 more
  • iis添加asp.net網站,訪問提示:由于擴展配置問題而無法提供您請求的

    今天在iis服務器配置asp.net網站,遇到一個問題,記錄一下: 問題:由于擴展配置問題而無法提供您請求的頁面。如果該頁面是腳本,請添加處理程式。如果應下載檔案,請添加 MIME 映射。 WindowServer2012服務器,添加角色安裝完.netframework和iis之后,運行aspx頁面 ......

    uj5u.com 2020-09-09 22:10:00 more
  • WebAPI-處理架構

    帶著問題去思考,大家好! 問題1:HTTP請求和回傳相應的HTTP回應資訊之間發生了什么? 1:首先是最底層,托管層,位于WebAPI和底層HTTP堆疊之間 2:其次是 訊息處理程式管道層,這里比如日志和快取。OWIN的參考是將訊息處理程式管道的一些功能下移到堆疊下端的OWIN中間件了。 3:控制器處理 ......

    uj5u.com 2020-09-09 22:11:13 more
  • 微信門戶開發框架-使用指導說明書

    微信門戶應用管理系統,采用基于 MVC + Bootstrap + Ajax + Enterprise Library的技術路線,界面層采用Boostrap + Metronic組合的前端框架,資料訪問層支持Oracle、SQLServer、MySQL、PostgreSQL等資料庫。框架以MVC5,... ......

    uj5u.com 2020-09-09 22:15:18 more
  • WebAPI-HTTP編程模型

    帶著問題去思考,大家好!它是什么?它包含什么?它能干什么? 訊息 HTTP編程模型的核心就是訊息抽象,表示為:HttPRequestMessage,HttpResponseMessage.用于客戶端和服務端之間交換請求和回應訊息。 HttpMethod類包含了一組靜態屬性: private stat ......

    uj5u.com 2020-09-09 22:15:23 more
  • 部署WebApi隨筆

    一、跨域 NuGet參考Microsoft.AspNet.WebApi.Cors WebApiConfig.cs中配置: // Web API 配置和服務 config.EnableCors(new EnableCorsAttribute("*", "*", "*")); 二、清除默認回傳XML格式 ......

    uj5u.com 2020-09-09 22:15:48 more
最新发布
  • C#多執行緒學習(二) 如何操縱一個執行緒

    <a href="https://www.cnblogs.com/x-zhi/" target="_blank"><img width="48" height="48" class="pfs" src="https://pic.cnblogs.com/face/2943582/20220801082530.png" alt="" /></...

    uj5u.com 2023-04-19 09:17:20 more
  • C#多執行緒學習(二) 如何操縱一個執行緒

    C#多執行緒學習(二) 如何操縱一個執行緒 執行緒學習第一篇:C#多執行緒學習(一) 多執行緒的相關概念 下面我們就動手來創建一個執行緒,使用Thread類創建執行緒時,只需提供執行緒入口即可。(執行緒入口使程式知道該讓這個執行緒干什么事) 在C#中,執行緒入口是通過ThreadStart代理(delegate)來提供的 ......

    uj5u.com 2023-04-19 09:16:49 more
  • 記一次 .NET某醫療器械清洗系統 卡死分析

    <a href="https://www.cnblogs.com/huangxincheng/" target="_blank"><img width="48" height="48" class="pfs" src="https://pic.cnblogs.com/face/214741/20200614104537.png" alt="" /&g...

    uj5u.com 2023-04-18 08:39:04 more
  • 記一次 .NET某醫療器械清洗系統 卡死分析

    一:背景 1. 講故事 前段時間協助訓練營里的一位朋友分析了一個程式卡死的問題,回過頭來看這個案例比較經典,這篇稍微整理一下供后來者少踩坑吧。 二:WinDbg 分析 1. 為什么會卡死 因為是表單程式,理所當然就是看主執行緒此時正在做什么? 可以用 ~0s ; k 看一下便知。 0:000> k # ......

    uj5u.com 2023-04-18 08:33:10 more
  • SignalR, No Connection with that ID,IIS

    <a href="https://www.cnblogs.com/smartstar/" target="_blank"><img width="48" height="48" class="pfs" src="https://pic.cnblogs.com/face/u36196.jpg" alt="" /></a>...

    uj5u.com 2023-03-30 17:21:52 more
  • 一次對pool的誤用導致的.net頻繁gc的診斷分析

    <a href="https://www.cnblogs.com/dotnet-diagnostic/" target="_blank"><img width="48" height="48" class="pfs" src="https://pic.cnblogs.com/face/3115652/20230225090434.png" alt=""...

    uj5u.com 2023-03-28 10:15:33 more
  • 一次對pool的誤用導致的.net頻繁gc的診斷分析

    <a href="https://www.cnblogs.com/dotnet-diagnostic/" target="_blank"><img width="48" height="48" class="pfs" src="https://pic.cnblogs.com/face/3115652/20230225090434.png" alt=""...

    uj5u.com 2023-03-28 10:13:31 more
  • C#遍歷指定檔案夾中所有檔案的3種方法

    <a href="https://www.cnblogs.com/xbhp/" target="_blank"><img width="48" height="48" class="pfs" src="https://pic.cnblogs.com/face/957602/20230310105611.png" alt="" /></a&...

    uj5u.com 2023-03-27 14:46:55 more
  • C#/VB.NET:如何將PDF轉為PDF/A

    <a href="https://www.cnblogs.com/Carina-baby/" target="_blank"><img width="48" height="48" class="pfs" src="https://pic.cnblogs.com/face/2859233/20220427162558.png" alt="" />...

    uj5u.com 2023-03-27 14:46:35 more
  • 武裝你的WEBAPI-OData聚合查詢

    <a href="https://www.cnblogs.com/podolski/" target="_blank"><img width="48" height="48" class="pfs" src="https://pic.cnblogs.com/face/616093/20140323000327.png" alt="" /><...

    uj5u.com 2023-03-27 14:46:16 more