【Openxml】颜色变化属性计算

打印 上一主题 下一主题

主题 766|帖子 766|积分 2298

Openxml的颜色变化属性

目前Openxml存在颜色变化属性如下:
参数说明Hue色调(色相)HueModulate色调调制,百分比HueOffset色调偏移量,角度值Saturation饱和度SaturationModulation饱和度调制,百分比SaturationOffset饱和度偏移量Luminance亮度LuminanceModulation亮度调制,百分比LuminanceOffset亮度偏移量AlphaAlphaAlphaModulationAlpha 调制,百分比AlphaOffsetAlpha 偏移量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的类:
  1.     /// <summary>
  2.     /// 用 A R G B 表示的颜色
  3.     /// </summary>
  4.     public class ARgbColor
  5.     {
  6.         /// <summary>
  7.         /// 创建 A R G B 颜色
  8.         /// </summary>
  9.         public ARgbColor()
  10.         {
  11.         }
  12.         /// <summary>
  13.         /// 创建 A R G B 颜色
  14.         /// </summary>
  15.         /// <param name="a"></param>
  16.         /// <param name="r"></param>
  17.         /// <param name="g"></param>
  18.         /// <param name="b"></param>
  19.         public ARgbColor(byte a, byte r, byte g, byte b)
  20.         {
  21.             A = a;
  22.             R = r;
  23.             G = g;
  24.             B = b;
  25.         }
  26.         /// <summary>
  27.         /// 表示透明色
  28.         /// </summary>
  29.         public byte A { set; get; }
  30.         /// <summary>
  31.         /// 表示红色
  32.         /// </summary>
  33.         public byte R { set; get; }
  34.         /// <summary>
  35.         /// 表示绿色
  36.         /// </summary>
  37.         public byte G { set; get; }
  38.         /// <summary>
  39.         /// 表示蓝色
  40.         /// </summary>
  41.         public byte B { set; get; }
  42.     }
复制代码
定义颜色变化相关类ColorTransform,并且定义RGB和Hsl的相互转换逻辑方法:
  1.     /// <summary>
  2.     ///     处理颜色之间的变换,调整,格式转换
  3.     /// </summary>
  4.     public static class ColorTransform
  5.     {
  6.         /// <summary>
  7.         ///  将<see cref="Color" />的数据转换为Hsl
  8.         /// </summary>
  9.         /// <param name="color"></param>
  10.         /// <returns></returns>
  11.         public static (Degree hue, Percentage sat, Percentage lum, byte alpha) ColorToHsl(Color color)
  12.         {
  13.             var max = System.Math.Max(color.R, System.Math.Max(color.G, color.B));
  14.             var min = System.Math.Min(color.R, System.Math.Min(color.G, color.B));
  15.             var delta = max - min;
  16.             var l = Percentage.FromDouble((max + min) / 2.0 / 255.0);
  17.             var h = Degree.FromDouble(0);
  18.             var s = Percentage.Zero;
  19.             if (delta > 0)
  20.             {
  21.                 s = l < Percentage.FromDouble(0.5)
  22.                     ? Percentage.FromDouble((max - min) * 1.0 / (max + min))
  23.                     : Percentage.FromDouble((max - min) * 1.0 / (2 * 255 - max - min));
  24.                 if (max == color.R)
  25.                 {
  26.                     h = Degree.FromDouble((0 + (color.G - color.B) * 1.0 / delta) * 60);
  27.                 }
  28.                 else if (max == color.G)
  29.                 {
  30.                     h = Degree.FromDouble((2 + (color.B - color.R) * 1.0 / delta) * 60);
  31.                 }
  32.                 else
  33.                 {
  34.                     h = Degree.FromDouble((4 + (color.R - color.G) * 1.0 / delta) * 60);
  35.                 }
  36.             }
  37.             return (h, s, l, color.A);
  38.         }
  39.     }
  40.             /// <summary>
  41.         ///     将Hsl的数据转换为<see cref="Color" />
  42.         /// </summary>
  43.         /// <param name="hue">色相</param>
  44.         /// <param name="saturation">饱和度</param>
  45.         /// <param name="lightness">亮度</param>
  46.         /// <param name="a">透明度</param>
  47.         /// <returns></returns>
  48.         public static Color HslToColor(Degree hue, Percentage saturation, Percentage lightness, byte a = 0xFF)
  49.         {
  50.             var color = new Color { A = a };
  51.             var hueValue = hue.DoubleValue;
  52.             var saturationValue = saturation.DoubleValue;
  53.             var lightnessValue = lightness.DoubleValue;
  54.             var c = (1 - System.Math.Abs(2 * lightnessValue - 1)) * saturationValue;
  55.             var x = c * (1 - System.Math.Abs((hueValue / 60) % 2 - 1));
  56.             var m = lightnessValue - c / 2;
  57.             var r = 0d;
  58.             var g = 0d;
  59.             var b = 0d;
  60.             if (hueValue is >= 0 and < 60)
  61.             {
  62.                 r = c;
  63.                 g = x;
  64.                 b = 0;
  65.             }
  66.             if (hueValue is >= 60 and < 120)
  67.             {
  68.                 r = x;
  69.                 g = c;
  70.                 b = 0;
  71.             }
  72.             if (hueValue is >= 120 and < 180)
  73.             {
  74.                 r = 0;
  75.                 g = c;
  76.                 b = x;
  77.             }
  78.             if (hueValue is >= 180 and < 240)
  79.             {
  80.                 r = 0;
  81.                 g = x;
  82.                 b = c;
  83.             }
  84.             if (hueValue is >= 240 and < 300)
  85.             {
  86.                 r = x;
  87.                 g = 0;
  88.                 b = c;
  89.             }
  90.             if (hueValue is >= 300 and < 360)
  91.             {
  92.                 r = c;
  93.                 g = 0;
  94.                 b = x;
  95.             }
  96.             color.R = (byte) ((r + m) * 255);
  97.             color.G = (byte) ((g + m) * 255);
  98.             color.B = (byte) ((b + m) * 255);
  99.             return color;
  100.         }
复制代码
然后我们来写真正处理Openxml的Hsl相关属性逻辑:
  1.        /// <summary>
  2.         ///     将<see cref="RgbColorModelHex" />转换为<see cref="Color" />
  3.         /// </summary>
  4.         /// <param name="color"></param>
  5.         /// <returns></returns>
  6.         public static Color? ToColor(this RgbColorModelHex color)
  7.         {
  8.             if (color.Val is not null)
  9.             {
  10.                 if (uint.TryParse(color.Val.Value, NumberStyles.HexNumber, null, out var result))
  11.                 {
  12.                     var solidColor = result.HexToColor();
  13.                     var modifiedColor = ColorTransform.AppendColorModify(solidColor, color.ChildElements);
  14.                     return modifiedColor;
  15.                 }
  16.             }
  17.             return null;
  18.         }
  19.         private static Color HexToColor(this uint rgb)
  20.         {
  21.             var color = new Color();
  22.             const int maxByte = 0xff;
  23.             color.B = (byte) (rgb & maxByte);
  24.             color.G = (byte) ((rgb >> 8) & maxByte);
  25.             color.R = (byte) ((rgb >> 16) & maxByte);
  26.             color.A = 0xFF;
  27.             return color;
  28.         }
  29.         /// <summary>
  30.         /// 给颜色叠加转换
  31.         /// </summary>
  32.         /// <param name="color"></param>
  33.         /// <param name="list"></param>
  34.         /// <returns></returns>
  35.         public static Color AppendColorModify(ARgbColor color, OpenXmlElementList list)
  36.         {
  37.             var updatedColor = color;
  38.             foreach (var element in list)
  39.             {
  40.                 if (element is Hue hue)
  41.                 {
  42.                     updatedColor = HandleHue(updatedColor, hue, null, null);
  43.                     continue;
  44.                 }
  45.                 if (element is HueModulation hueModulation)
  46.                 {
  47.                     updatedColor = HandleHue(updatedColor, null, hueModulation, null);
  48.                     continue;
  49.                 }
  50.                 if (element is HueOffset hueOffset)
  51.                 {
  52.                     updatedColor = HandleHue(updatedColor, null, null, hueOffset);
  53.                     continue;
  54.                 }
  55.                 if (element is Saturation saturation)
  56.                 {
  57.                     updatedColor = HandleSaturation(updatedColor, saturation, null, null);
  58.                     continue;
  59.                 }
  60.                 if (element is SaturationModulation saturationModulation)
  61.                 {
  62.                     updatedColor = HandleSaturation(updatedColor, null, saturationModulation, null);
  63.                     continue;
  64.                 }
  65.                 if (element is SaturationOffset saturationOffset)
  66.                 {
  67.                     updatedColor = HandleSaturation(updatedColor, null, null, saturationOffset);
  68.                     continue;
  69.                 }
  70.                 if (element is Luminance luminance)
  71.                 {
  72.                     updatedColor = HandleLuminance(updatedColor, luminance, null, null);
  73.                     continue;
  74.                 }
  75.                 if (element is LuminanceModulation luminanceModulation)
  76.                 {
  77.                     updatedColor = HandleLuminance(updatedColor, null, luminanceModulation, null);
  78.                     continue;
  79.                 }
  80.                 if (element is LuminanceOffset luminanceOffset)
  81.                 {
  82.                     updatedColor = HandleLuminance(updatedColor, null, null, luminanceOffset);
  83.                     continue;
  84.                 }
  85.             }
  86.         private static Color HandleHue(Color color, Hue? hueElement, HueModulation? hueModElement,
  87.             HueOffset? hueOffsetElement)
  88.         {
  89.             if (hueElement is null && hueModElement is null && hueOffsetElement is null)
  90.             {
  91.                 return color;
  92.             }
  93.             var updatedColor = HandleHslCore(color, hueElement: hueElement, hueModElement: hueModElement, hueOffsetElement: hueOffsetElement);
  94.             return updatedColor;
  95.         }
  96.         private static Color HandleSaturation(Color color, Saturation? satElement, SaturationModulation? satModElement,
  97.             SaturationOffset? satOffsetElement)
  98.         {
  99.             if (satElement is null && satModElement is null && satOffsetElement is null)
  100.             {
  101.                 return color;
  102.             }
  103.             var updatedColor = HandleHslCore(color, satElement: satElement, satModElement: satModElement, satOffsetElement: satOffsetElement);
  104.             return updatedColor;
  105.         }
  106.         private static Color HandleLuminance(Color color, Luminance? lumElement, LuminanceModulation? lumModElement,
  107.             LuminanceOffset? lumOffsetElement)
  108.         {
  109.             if (lumElement is null && lumModElement is null && lumOffsetElement is null)
  110.             {
  111.                 return color;
  112.             }
  113.             var updatedColor = HandleHslCore(color, lumElement: lumElement, lumModElement: lumModElement, lumOffsetElement: lumOffsetElement);
  114.             return updatedColor;
  115.         }
  116.         private static Color HandleHslCore(Color color,
  117.             Hue? hueElement = null, HueModulation? hueModElement = null, HueOffset? hueOffsetElement = null,
  118.             Saturation? satElement = null, SaturationModulation? satModElement = null, SaturationOffset? satOffsetElement = null,
  119.             Luminance? lumElement = null, LuminanceModulation? lumModElement = null, LuminanceOffset? lumOffsetElement = null)
  120.         {
  121.             if (hueElement is null && hueModElement is null && hueOffsetElement is null
  122.                 && satElement is null && satModElement is null && satOffsetElement is null
  123.                 && lumElement is null && lumModElement is null && lumOffsetElement is null)
  124.             {
  125.                 return color;
  126.             }
  127.             var (hue, sat, lum, alpha) = ColorToHsl(color);
  128.             var hueElementVal = hueElement?.Val;
  129.             var hueValue = hueElementVal is not null ? new Angle(hueElementVal).ToDegreeValue() : hue.DoubleValue;
  130.             var satElementVal = satElement?.Val;
  131.             var satValue = satElementVal is not null ? new Percentage(satElementVal).DoubleValue : sat.DoubleValue;
  132.             var lumElementVal = lumElement?.Val;
  133.             var lumValue = lumElementVal is not null ? new Percentage(lumElementVal).DoubleValue : lum.DoubleValue;
  134.             var hueModElementVal = hueModElement?.Val;
  135.             var hueModValue = hueModElementVal is not null && hueModElementVal.HasValue
  136.                 ? new Percentage(hueModElementVal)
  137.                 : Percentage.FromDouble(1);
  138.             var satModElementVal = satModElement?.Val;
  139.             var satModValue = satModElementVal is not null && satModElementVal.HasValue
  140.                 ? new Percentage(satModElementVal)
  141.                 : Percentage.FromDouble(1);
  142.             var lumModElementVal = lumModElement?.Val;
  143.             var lumModValue = lumModElementVal is not null && lumModElementVal.HasValue
  144.                 ? new Percentage(lumModElementVal)
  145.                 : Percentage.FromDouble(1);
  146.             var hueOffsetVal = hueOffsetElement?.Val;
  147.             var hueOffset = hueOffsetVal is not null && hueOffsetVal.HasValue
  148.                 ? new Angle(hueOffsetVal).ToDegreeValue()
  149.                 : new Angle(0).ToDegreeValue();
  150.             var saturationOffsetVal = satOffsetElement?.Val;
  151.             var saturationOffset = saturationOffsetVal is not null && saturationOffsetVal.HasValue
  152.                 ? new Percentage(saturationOffsetVal)
  153.                 : Percentage.Zero;
  154.             var lumOffsetElementVal = lumOffsetElement?.Val;
  155.             var lumOffset = lumOffsetElementVal is not null && lumOffsetElementVal.HasValue
  156.                 ? new Percentage(lumOffsetElementVal)
  157.                 : Percentage.Zero;
  158.             var hueResult = hueValue * hueModValue.DoubleValue + hueOffset;
  159.             hue = Degree.FromDouble(hueResult);
  160.             var satResult = satValue * satModValue.DoubleValue + saturationOffset.DoubleValue;
  161.             sat = Percentage.FromDouble(satResult);
  162.             sat = sat > Percentage.FromDouble(1) ? Percentage.FromDouble(1) : sat;
  163.             sat = sat < Percentage.Zero ? Percentage.Zero : sat;
  164.             var lumResult = lumValue * lumModValue.DoubleValue + lumOffset.DoubleValue;
  165.             lum = Percentage.FromDouble(lumResult);
  166.             lum = lum > Percentage.FromDouble(1) ? Percentage.FromDouble(1) : lum;
  167.             lum = lum < Percentage.Zero ? Percentage.Zero : lum;
  168.             return HslToColor(hue, sat, lum, alpha);
  169.         }
复制代码
处理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
处理透明度

以下为处理透明度的逻辑代码:
  1.   
  2.         private static Color HandleAlphaModify(Color color, Alpha? alphaElement, AlphaModulation? alphaModulation, AlphaOffset? alphaOffset)
  3.         {
  4.             if (alphaElement is null && alphaModulation is null && alphaOffset is null)
  5.             {
  6.                 return color;
  7.             }
  8.             var alphaValue = alphaElement?.Val;
  9.             var modulationVal = alphaModulation?.Val;
  10.             var offsetVal = alphaOffset?.Val;
  11.             var alpha = alphaValue is not null && alphaValue.HasValue
  12.                 ? new Percentage(alphaValue)
  13.                 : Percentage.FromDouble(1);
  14.             var mod = modulationVal is not null && modulationVal.HasValue
  15.                 ? new Percentage(modulationVal)
  16.                 : Percentage.FromDouble(1);
  17.             var off = offsetVal is not null && offsetVal.HasValue
  18.                 ? new Percentage(offsetVal)
  19.                 : Percentage.Zero;
  20.             var alphaResult = alpha.DoubleValue * mod.DoubleValue + off.DoubleValue;
  21.             color.A = (byte) (color.A * alphaResult);
  22.             return color;
  23.         }        
复制代码
处理RGB的红色、蓝色、绿色

以下为处理RGB的红色、蓝色、绿色的逻辑代码:
[code]        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 = 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        ///         ///         ///         private static double SRgbToLinearRgb(double sRgb)        {            if (sRgb

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有账号?立即注册

x
回复

使用道具 举报

0 个回复

倒序浏览

快速回复

您需要登录后才可以回帖 登录 or 立即注册

本版积分规则

玛卡巴卡的卡巴卡玛

金牌会员
这个人很懒什么都没写!

标签云

快速回复 返回顶部 返回列表