hsl.go 3.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139
  1. // Copyright (c) 2012 Rodrigo Moraes. All rights reserved.
  2. //
  3. // Redistribution and use in source and binary forms, with or without
  4. // modification, are permitted provided that the following conditions are
  5. // met:
  6. //
  7. // * Redistributions of source code must retain the above copyright
  8. // notice, this list of conditions and the following disclaimer.
  9. // * Redistributions in binary form must reproduce the above
  10. // copyright notice, this list of conditions and the following disclaimer
  11. // in the documentation and/or other materials provided with the
  12. // distribution.
  13. // * Neither the name of Google Inc. nor the names of its
  14. // contributors may be used to endorse or promote products derived from
  15. // this software without specific prior written permission.
  16. //
  17. // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
  18. // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
  19. // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
  20. // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
  21. // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
  22. // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
  23. // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
  24. // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
  25. // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
  26. // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
  27. // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  28. package excelize
  29. import (
  30. "image/color"
  31. "math"
  32. )
  33. // HSLModel converts any color.Color to a HSL color.
  34. var HSLModel = color.ModelFunc(hslModel)
  35. // HSL represents a cylindrical coordinate of points in an RGB color model.
  36. //
  37. // Values are in the range 0 to 1.
  38. type HSL struct {
  39. H, S, L float64
  40. }
  41. // RGBA returns the alpha-premultiplied red, green, blue and alpha values
  42. // for the HSL.
  43. func (c HSL) RGBA() (uint32, uint32, uint32, uint32) {
  44. r, g, b := HSLToRGB(c.H, c.S, c.L)
  45. return uint32(r) * 0x101, uint32(g) * 0x101, uint32(b) * 0x101, 0xffff
  46. }
  47. // hslModel converts a color.Color to HSL.
  48. func hslModel(c color.Color) color.Color {
  49. if _, ok := c.(HSL); ok {
  50. return c
  51. }
  52. r, g, b, _ := c.RGBA()
  53. h, s, l := RGBToHSL(uint8(r>>8), uint8(g>>8), uint8(b>>8))
  54. return HSL{h, s, l}
  55. }
  56. // RGBToHSL converts an RGB triple to a HSL triple.
  57. func RGBToHSL(r, g, b uint8) (h, s, l float64) {
  58. fR := float64(r) / 255
  59. fG := float64(g) / 255
  60. fB := float64(b) / 255
  61. max := math.Max(math.Max(fR, fG), fB)
  62. min := math.Min(math.Min(fR, fG), fB)
  63. l = (max + min) / 2
  64. if max == min {
  65. // Achromatic.
  66. h, s = 0, 0
  67. } else {
  68. // Chromatic.
  69. d := max - min
  70. if l > 0.5 {
  71. s = d / (2.0 - max - min)
  72. } else {
  73. s = d / (max + min)
  74. }
  75. switch max {
  76. case fR:
  77. h = (fG - fB) / d
  78. if fG < fB {
  79. h += 6
  80. }
  81. case fG:
  82. h = (fB-fR)/d + 2
  83. case fB:
  84. h = (fR-fG)/d + 4
  85. }
  86. h /= 6
  87. }
  88. return
  89. }
  90. // HSLToRGB converts an HSL triple to a RGB triple.
  91. func HSLToRGB(h, s, l float64) (r, g, b uint8) {
  92. var fR, fG, fB float64
  93. if s == 0 {
  94. fR, fG, fB = l, l, l
  95. } else {
  96. var q float64
  97. if l < 0.5 {
  98. q = l * (1 + s)
  99. } else {
  100. q = l + s - s*l
  101. }
  102. p := 2*l - q
  103. fR = hueToRGB(p, q, h+1.0/3)
  104. fG = hueToRGB(p, q, h)
  105. fB = hueToRGB(p, q, h-1.0/3)
  106. }
  107. r = uint8((fR * 255) + 0.5)
  108. g = uint8((fG * 255) + 0.5)
  109. b = uint8((fB * 255) + 0.5)
  110. return
  111. }
  112. // hueToRGB is a helper function for HSLToRGB.
  113. func hueToRGB(p, q, t float64) float64 {
  114. if t < 0 {
  115. t++
  116. }
  117. if t > 1 {
  118. t--
  119. }
  120. if t < 1.0/6 {
  121. return p + (q-p)*6*t
  122. }
  123. if t < 0.5 {
  124. return q
  125. }
  126. if t < 2.0/3 {
  127. return p + (q-p)*(2.0/3-t)*6
  128. }
  129. return p
  130. }