File: grayscale.rb

package info (click to toggle)
ruby-color 2.1.1-1
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid
  • size: 300 kB
  • sloc: ruby: 1,801; makefile: 5
file content (165 lines) | stat: -rw-r--r-- 4,000 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
# frozen_string_literal: true

##
# \Grayscale is a color object representing shades of gray as a ratio of black to white,
# where 0% (0.0) gray is black and 100% (1.0) gray is white.
#
# \Grayscale colors are immutable Data class instances. Array deconstruction is `[gray]`
# and hash deconstruction is `{g:, gray:}`. See #g, #gray.
class Color::Grayscale
  include Color

  ##
  # :attr_reader: brightness
  # Returns the grayscale value as a proportion of white (0.0 .. 1.0).

  ##
  # :attr_reader: g
  # Returns the grayscale value as a proportion of white (0.0 .. 1.0).

  ##
  # :attr_reader: gray
  # Returns the grayscale value as a percentage of white (0.0 .. 100.0).

  ##
  # Creates a grayscale color object from a percentage value (0.0 .. 100.0).
  #
  # ```ruby
  # Color::Grayscale.from_percentage(50) # => Grayscale [0.50%]
  # Color::Grayscale.from_values(50) # => Grayscale [0.50%]
  # ```
  #
  # :call-seq:
  #   from_percentage(g)
  #   from_percentage(g:)
  #   from_values(g)
  #   from_values(g:)
  def self.from_percentage(*args, **kwargs)
    g =
      case [args, kwargs]
      in [[g], {}]
        g
      in [[], {g:}]
        g
      else
        new(*args, **kwargs)
      end

    new(g: g / 100.0)
  end

  class << self
    alias_method :from_values, :from_percentage
    alias_method :from_fraction, :new
    alias_method :from_internal, :from_fraction # :nodoc:
  end

  ##
  # Creates a grayscale color object from a fractional value (0.0 .. 1.0).
  #
  # ```ruby
  # Color::Grayscale.from_fraction(0.5)
  # Color::Grayscale.new(0.5)
  # Color::Grayscale[g: 0.5]
  # ```
  def initialize(g:)
    super(g: normalize(g))
  end

  ##
  # Coerces the other Color object to grayscale.
  def coerce(other) = other.to_grayscale

  ##
  # Convert \Grayscale to Color::CMYK.
  def to_cmyk(...) = Color::CMYK.from_fraction(0, 0, 0, 1.0 - g.to_f)

  ##
  # Convert \Grayscale to Color::RGB.
  def to_rgb(...) = Color::RGB.from_fraction(g, g, g)

  ##
  def to_grayscale(...) = self

  ##
  # Convert \Grayscale to Color::YIQ.
  #
  # This approximates the actual value, as I and Q are calculated by treating the
  # grayscale value as a RGB value. The Y (intensity or brightness) value is the same as
  # the grayscale value.
  def to_yiq(...)
    y = g
    i = (g * 0.596) + (g * -0.275) + (g * -0.321)
    q = (g * 0.212) + (g * -0.523) + (g * 0.311)
    Color::YIQ.from_fraction(y, i, q)
  end

  ##
  # Converts \Grayscale to Color::HSL.
  def to_hsl(...) = Color::HSL.from_fraction(0, 0, g)

  ##
  # Converts \Grayscale to Color::CIELAB via Color::RGB.
  def to_lab(...) = to_rgb(...).to_lab(...)

  ##
  # Present the color as an HTML/CSS color string (e.g., `#dddddd`).
  def html
    "##{("%02x" % translate_range(g, to: 0.0..255.0)) * 3}"
  end

  ##
  # Present the color as a CSS `rgb` color with optional `alpha`.
  #
  # ```ruby
  # Color::Grayscale[0.5].css               # => rgb(50.00% 50.00% 50.00%)
  # Color::Grayscale[0.5].css(alpha: 0.75)  # => rgb(50.00% 50.00% 50.00% / 0.75)
  # ```
  def css(alpha: nil)
    params = ([css_value(gray, :percent)] * 3).join(" ")
    params = "#{params} / #{css_value(alpha)}" if alpha

    "rgb(#{params})"
  end

  ##
  # Lightens the grayscale color by the stated percent.
  def lighten_by(percent) = Color::Grayscale.from_fraction([g + (g * (percent / 100.0)), 1.0].min)

  ##
  # Darken the grayscale color by the stated percent.
  def darken_by(percent) = Color::Grayscale.from_fraction([g - (g * (percent / 100.0)), 0.0].max)

  ##
  alias_method :brightness, :g

  ##
  def gray = g * 100.0

  ##
  def inspect = "Grayscale [%.2f%%]" % [gray] # :nodoc:

  ##
  def pretty_print(q) # :nodoc:
    q.text "Grayscale"
    q.breakable
    q.group 2, "[", "]" do
      q.text "%.2f%%" % gray
    end
  end

  ##
  def to_a = [gray] # :nodoc:

  ##
  alias_method :deconstruct, :to_a

  ##
  def deconstruct_keys(_keys) = {g:, gray:}

  ##
  def to_internal = [g] # :nodoc:

  ##
  def components = 1 # :nodoc:
end