Advertisement
pkuderov

rgb color retriever

Jun 28th, 2013
790
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C# 10.26 KB | None | 0 0
  1. using System;
  2. using Word = Microsoft.Office.Interop.Word;
  3. using Core = Microsoft.Office.Core;
  4. using System.Drawing;
  5. using System.Runtime.InteropServices;
  6.  
  7. namespace TestWordAPI
  8. {
  9.     /// <summary>
  10.     /// static class with rgb color retrieving logic: Microsoft.Office.Interop.Word.WdColor -> System.Drawing.Color
  11.     /// </summary>
  12.     public static class RgbColorRetriever
  13.     {
  14.         #region Constants
  15.        
  16.         // first byte of WdColor determines its format type
  17.         private static readonly int
  18.             RGB = 0x00,
  19.             Automatic = 0xFF,
  20.             System = 0x80,
  21.             ThemeLow = 0xD0,
  22.             ThemeHigh = 0xDF;
  23.  
  24.         //structure to store HSL (hue, saturation, lightness) color
  25.         private struct HSL
  26.         {
  27.             public double H, S, L;
  28.         }
  29.  
  30.         #endregion
  31.  
  32.         /// <summary>
  33.         /// Get RGB-color from WdColor
  34.         /// </summary>
  35.         /// <param name="wdColor">source color</param>
  36.         /// <param name="doc">document, where this color from (for appropriate color theme)</param>
  37.         public static Color GetRGBColor(Word.WdColor wdColor, Word.Document doc)
  38.         {
  39.             // separate 1st byte (the most significant) and 3 others to different vars
  40.             int color = ((int)wdColor) & ((int)0xFFFFFF);
  41.             int colorType = (int)(((uint)wdColor) >> 24);
  42.  
  43.             if (colorType == RGB)
  44.             {
  45.                 // simple color in OLE format (it's just a BGR - blue, green, red)
  46.                 // let's use standard color translator from system.drawing
  47.                 return ColorTranslator.FromOle(color);
  48.             }
  49.             else if (colorType == Automatic)
  50.             {
  51.                 // standard contrast color. In my case I was needed color. But I don't know the proper way to understand which one (black or white) I need to choose.
  52.                 return Color.White;
  53.             }
  54.             else if (colorType == System)
  55.             {
  56.                 // In ActiveX controls in documents, and in VBA (for UserForm controls, for example) special values for system colours
  57.                 // (for some reason lost in the mists of time these are also called OLE Colors) ranging from 0x80000000 to 0x80000018.
  58.                 // I used system dll function to retrieve system color and then used standard color translator
  59.                 int sysColor = GetSysColor(color);
  60.                 return ColorTranslator.FromOle(sysColor);
  61.             }
  62.             else if (colorType >= ThemeLow && colorType <= ThemeHigh)
  63.             {
  64.                 // color based on doc's color theme
  65.                 return GetThemedColor(colorType, color, doc);
  66.             }
  67.            
  68.             throw new Exception("Unknown color type");
  69.         }
  70.  
  71.         private static Color GetThemedColor(int colorType, int color, Word.Document doc)
  72.         {
  73.             // color based on theme is base color + tint or shade
  74.             double tintAndShade = 0;
  75.             // base color index is least siginficant 4 bits from colorType
  76.             int colorThemeIndex = colorType & 0xF;
  77.            
  78.             // 2nd most significant byte is always 0
  79.             // 3rd byte - shade, 4th - tint. One of them must be 0xFF and shouldn't be used
  80.             // it means that always is used one of them and other is 0xFF
  81.             int darkness = (color & 0x00FF00) >> 8;
  82.             int lightness = color & 0x0000FF;
  83.  
  84.             if (darkness != 0xFF)
  85.                 tintAndShade = -1 + darkness / 255.0;
  86.             else
  87.                 tintAndShade = 1.0 - lightness / 255.0;
  88.             // so:
  89.             //      tintAndShade < 0 => shade base color by |tintAndShade| * 100%
  90.             //      tintAndShade > 0 => tint base color |tintAndShade| * 100%
  91.            
  92.             return GetThemedColor(colorThemeIndex, tintAndShade, doc);
  93.         }
  94.  
  95.         private static Color GetThemedColor(int colorThemeIndex, double tintAndShade, Word.Document doc)
  96.         {
  97.             // translate from wdThemeColorIndex to MsoThemeColorSchemeIndex
  98.             Core.MsoThemeColorSchemeIndex colorSchemeIndex = ThemeIndexToSchemeIndex(colorThemeIndex);
  99.             // get color scheme by this index and take its RGB property, but this RGB still OLE RGB - i.e. BGR -> need to convert it to real RGB, i.e. use ColorTranslator.FromOle() and ToArgb after
  100.             int colorSchemeRGB = ColorTranslator.FromOle(doc.DocumentTheme.ThemeColorScheme.Colors(colorSchemeIndex).RGB).ToArgb();
  101.  
  102.             // do RGB -> HSL translation to apply tint/shade
  103.             HSL colorSchemeHSL = RGBtoHSL(colorSchemeRGB);
  104.  
  105.             // apply it
  106.             if (tintAndShade > 0)
  107.                 colorSchemeHSL.L += (1 - colorSchemeHSL.L) * tintAndShade;
  108.             else
  109.                 colorSchemeHSL.L *= 1 - Math.Abs(tintAndShade);
  110.  
  111.             // do backward HSL -> RGB translation
  112.             int tintedAndShadedRGB = HSLtoRGB(colorSchemeHSL);
  113.  
  114.             return Color.FromArgb(tintedAndShadedRGB);
  115.         }
  116.  
  117.         private static int HSLtoRGB(HSL HSL)
  118.         {
  119.             // took from http://stackoverflow.com/questions/2353211/hsl-to-rgb-color-conversion
  120.             double red, green, blue;
  121.  
  122.             if (HSL.S == 0)
  123.                 red = green = blue = HSL.L;
  124.             else
  125.             {
  126.                 double q = HSL.L < 0.5 ? HSL.L * (1 + HSL.S) : HSL.L + HSL.S - HSL.L * HSL.S;
  127.                 double p = 2 * HSL.L - q;
  128.  
  129.                 red = Hue2RGB(p, q, HSL.H + 1.0 / 3);
  130.                 green = Hue2RGB(p, q, HSL.H);
  131.                 blue = Hue2RGB(p, q, HSL.H - 1.0 / 3);
  132.             }
  133.  
  134.             int r = (int) (red * 255), g = (int)(green * 255), b = (int)(blue * 255);
  135.             return (r << 16) + (g << 8) + b;
  136.         }
  137.        
  138.         private static double Hue2RGB(double p, double q, double t){
  139.             // took from http://stackoverflow.com/questions/2353211/hsl-to-rgb-color-conversion
  140.  
  141.             if(t < 0) t += 1;
  142.             if(t > 1) t -= 1;
  143.             if(t < 1.0 / 6) return p + (q - p) * 6 * t;
  144.             if(t < 1.0 / 2) return q;
  145.             if(t < 2.0 / 3) return p + (q - p) * (2.0 / 3 - t) * 6;
  146.             return p;
  147.         }
  148.  
  149.         private static HSL RGBtoHSL(int RGB)
  150.         {
  151.             // took from http://stackoverflow.com/questions/2353211/hsl-to-rgb-color-conversion
  152.             double red, green, blue;
  153.             double max, min, diff;
  154.            
  155.             red = ((RGB & 0xFF0000) >> 16) / 255.0;
  156.             green = ((RGB & 0x00FF00) >> 8) / 255.0;
  157.             blue = (RGB & 0x0000FF) / 255.0;
  158.  
  159.             max = Math.Max(red, Math.Max(green, blue));
  160.             min = Math.Min(red, Math.Min(green, blue));
  161.             diff = max - min;
  162.            
  163.             HSL res;
  164.             res.L = res.H = res.S = (max + min) / 2;
  165.             if (max == min)
  166.                 res.S = res.H = 0;
  167.             else
  168.             {
  169.                 res.S = res.L < 0.5 ? diff / (max + min) : diff / (2 - max - min);
  170.  
  171.                 if (red == max)
  172.                     res.H = (green - blue) / diff - (blue > green ? 6 : 0);
  173.                 else if (green == max)
  174.                     res.H = (blue - red) / diff + 2;
  175.                 else if (blue == max)
  176.                     res.H = (red - green) / diff + 4;
  177.                 res.H /= 6;
  178.             }
  179.  
  180.             return res;
  181.         }
  182.  
  183.         private static Core.MsoThemeColorSchemeIndex ThemeIndexToSchemeIndex(int colorThemeIndex)
  184.         {
  185.             // translation sheet from http://www.wordarticles.com/Articles/Colours/2007.php#UIConsiderations
  186.             switch((Word.WdThemeColorIndex)colorThemeIndex)
  187.             {
  188.                 case Word.WdThemeColorIndex.wdThemeColorMainDark1:
  189.                     return Core.MsoThemeColorSchemeIndex.msoThemeDark1;
  190.                 case Word.WdThemeColorIndex.wdThemeColorMainLight1:        
  191.                     return Core.MsoThemeColorSchemeIndex.msoThemeLight1;
  192.                 case Word.WdThemeColorIndex.wdThemeColorMainDark2:        
  193.                     return Core.MsoThemeColorSchemeIndex.msoThemeDark2;
  194.                 case Word.WdThemeColorIndex.wdThemeColorMainLight2:        
  195.                     return Core.MsoThemeColorSchemeIndex.msoThemeLight2;
  196.                 case Word.WdThemeColorIndex.wdThemeColorAccent1:          
  197.                     return Core.MsoThemeColorSchemeIndex.msoThemeAccent1;
  198.                 case Word.WdThemeColorIndex.wdThemeColorAccent2:          
  199.                     return Core.MsoThemeColorSchemeIndex.msoThemeAccent2;
  200.                 case Word.WdThemeColorIndex.wdThemeColorAccent3:          
  201.                     return Core.MsoThemeColorSchemeIndex.msoThemeAccent3;
  202.                 case Word.WdThemeColorIndex.wdThemeColorAccent4:          
  203.                     return Core.MsoThemeColorSchemeIndex.msoThemeAccent4;
  204.                 case Word.WdThemeColorIndex.wdThemeColorAccent5:          
  205.                     return Core.MsoThemeColorSchemeIndex.msoThemeAccent5;
  206.                 case Word.WdThemeColorIndex.wdThemeColorAccent6:          
  207.                     return Core.MsoThemeColorSchemeIndex.msoThemeAccent6;
  208.                 case Word.WdThemeColorIndex.wdThemeColorHyperlink:        
  209.                     return Core.MsoThemeColorSchemeIndex.msoThemeHyperlink;
  210.                 case Word.WdThemeColorIndex.wdThemeColorHyperlinkFollowed:
  211.                     return Core.MsoThemeColorSchemeIndex.msoThemeFollowedHyperlink;
  212.                 case Word.WdThemeColorIndex.wdThemeColorBackground1:      
  213.                     return Core.MsoThemeColorSchemeIndex.msoThemeLight1;
  214.                 case Word.WdThemeColorIndex.wdThemeColorText1:            
  215.                     return Core.MsoThemeColorSchemeIndex.msoThemeDark1;
  216.                 case Word.WdThemeColorIndex.wdThemeColorBackground2:      
  217.                     return Core.MsoThemeColorSchemeIndex.msoThemeLight2;
  218.                 case Word.WdThemeColorIndex.wdThemeColorText2:            
  219.                     return Core.MsoThemeColorSchemeIndex.msoThemeDark2;
  220.                 default:
  221.                     throw new Exception("Something is rotten in the state of Denmark...");
  222.             }
  223.         }
  224.  
  225.         [DllImport("user32.dll", CharSet = CharSet.Auto)]
  226.         public static extern int GetSysColor(int nIndex);
  227.     }
  228. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement