redgreenblue 0.8.0 → 0.13.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 766113ae54ad00c066d264e8bd8d63610f5347e75d95aee3c34bacac0b027a99
4
- data.tar.gz: a91d7d49e36ebfc29328e32c2aa67df908e4fbc9d36c4ec957e1e6d8ed3220b7
3
+ metadata.gz: 65191c26a6dcae9a6bb52abe182d376e0975b79672686120185c9a2b3d49e4e9
4
+ data.tar.gz: 3fb9dc542660f5edaec8283a2e74ec0687e369e05475bf6840344ca5cca0304f
5
5
  SHA512:
6
- metadata.gz: 587d547ca6139b84ef36f8064a768aee1cdb3f5618f4f03c9ab606df477ad6ebffe82b00837fe55b06fcf2ba6275a1d85484f758394755567b1aab81351bf1df
7
- data.tar.gz: e5203156810f3f577bbe20de7d862f96518db292b1f848778dc2c9dc5223b16c9e15e6effc2e08ed4dba655891805873fdf95cda511c5a533f87462200401746
6
+ metadata.gz: 4c0d6a47aa611822dba62189c14ebf38c0ef6315f08ac9b5eb9efe04b28487d2c95105c0e86536cb52fdc9ce36df445d060623a14e99f2dbab34df5e0d10e515
7
+ data.tar.gz: 756bdaa8c6859c685e51342ee8a6d34e7340ea0580bd79b4487443d97b04629ed1b7c8f1631bf3ac26a5570e6c243aba7f7b931243ea967f07d8437fa223d495
@@ -1,28 +1,30 @@
1
1
  class RGB
2
2
  end
3
3
 
4
- require 'redgreenblue/version'
4
+ %w(
5
5
 
6
- require 'redgreenblue/base'
6
+ version
7
7
 
8
- require 'redgreenblue/24bit'
9
- require 'redgreenblue/48bit'
10
- require 'redgreenblue/hex'
8
+ base
11
9
 
12
- require 'redgreenblue/hsl_hsv'
13
- require 'redgreenblue/cie'
10
+ 24bit 48bit hex int
14
11
 
15
- require 'redgreenblue/inspect'
16
- require 'redgreenblue/lazy'
12
+ hsl hsv hsb
17
13
 
18
- require 'redgreenblue/rgb565'
19
- require 'redgreenblue/bgr24bit'
20
- require 'redgreenblue/gif'
21
- require 'redgreenblue/terminal'
22
- require 'redgreenblue/web'
14
+ ostwald
23
15
 
24
- require 'redgreenblue/mix'
25
- require 'redgreenblue/misc'
26
- require 'redgreenblue/random'
16
+ gamma
27
17
 
28
- require 'redgreenblue/os'
18
+ cie_1931 cie_1976
19
+
20
+ name
21
+
22
+ inspect view lazy
23
+
24
+ rgb565 bgr24bit gif terminal web gpl mac
25
+
26
+ match mix misc random
27
+
28
+ os
29
+
30
+ ).each { |m| require "redgreenblue/#{m}" }
@@ -51,6 +51,17 @@ class RGB
51
51
  c
52
52
  end
53
53
 
54
+ # Sets the red, green, and blue values to those of the nearest 24-bit color.
55
+ def snap!
56
+ self.rgb = rgb
57
+ self
58
+ end
59
+
60
+ # Creates a new RGB object containing the nearest 24-bit color.
61
+ def snap
62
+ RGB.rgb rgb
63
+ end
64
+
54
65
  # Calls the given block for each 24-bit RGB color (from black to white), passing the color as an RGB object.
55
66
  #
56
67
  # Returns the number of iterations.
@@ -8,7 +8,7 @@ class RGB
8
8
  #
9
9
  # Currently always 'sRGB'.
10
10
  def color_space
11
- @color_space ||= 'sRGB'
11
+ 'sRGB'
12
12
  end
13
13
 
14
14
  # Returns the red component as a value between 0 and 1.
@@ -66,7 +66,7 @@ class RGB
66
66
  ( self.class == other.class ) && ( self.values == other.values )
67
67
  end
68
68
 
69
- # Returns a sorted hash of 3 key/value pairs for red, green and blue,
69
+ # Returns a sorted hash of 3 key/value pairs for red, green, and blue,
70
70
  # sorted in order of decreasing value.
71
71
  def to_h
72
72
  ([:red, :green, :blue].zip values).sort_by {
@@ -0,0 +1,51 @@
1
+ class RGB
2
+
3
+ # Returns CIE 1931 XYZ values for the RGB object.
4
+ #
5
+ # Based on:
6
+ # - http://www.brucelindbloom.com/index.html?Eqn_RGB_to_XYZ.html
7
+ # - https://en.wikipedia.org/wiki/CIE_1931_color_space
8
+ # sRGB to XYZ matrix for D65 reference white calculated with Javascript by Bruce Lindbloom:
9
+ # - http://www.brucelindbloom.com/ColorCalculator.html
10
+ def cie_xyz(round: true)
11
+ r, g, b = linear_values
12
+
13
+ [
14
+
15
+ r * 0.4124_5643_9090 + g * 0.3575_7607_7644 + b * 0.1804_3748_3266,
16
+ r * 0.2126_7285_1406 + g * 0.7151_5215_5288 + b * 0.0721_7499_3307,
17
+ r * 0.0193_3389_5582 + g * 0.1191_9202_5881 + b * 0.9503_0407_8536
18
+
19
+ ].map { |v| round ? v.round(8) : v }
20
+ end
21
+
22
+ alias xyz cie_xyz
23
+
24
+ # Returns CIE 1931 xyY values for the RGB object.
25
+ #
26
+ # Based on:
27
+ # - https://en.wikipedia.org/wiki/CIE_1931_color_space
28
+ # - http://www.brucelindbloom.com/index.html?Eqn_XYZ_to_xyY.html
29
+ # - https://ninedegreesbelow.com/photography/xyz-rgb.html
30
+ def cie_xyy
31
+ x, y, z = cie_xyz(round: false)
32
+
33
+ [
34
+
35
+ x / ( x + y + z ),
36
+ y / ( x + y + z ),
37
+ y
38
+
39
+ ].map { |v| v.round(8) }
40
+ end
41
+
42
+ alias xyy cie_xyy
43
+
44
+ # Returns CIE 1931 xy values for the RGB object.
45
+ def cie_xy
46
+ cie_xyy[0..1]
47
+ end
48
+
49
+ alias xy cie_xy
50
+
51
+ end
@@ -0,0 +1,105 @@
1
+ class RGB
2
+
3
+ # Returns CIE 1976 L*a*b* (CIELAB) values for the RGB object.
4
+ def cie_lab(round: true)
5
+ cie_lab_luv(round: round, type: :lab)
6
+ end
7
+
8
+ alias lab cie_lab
9
+
10
+ # Returns CIE 1976 LCHab values for the RGB object, derived from L*a*b* (CIELAB).
11
+ #
12
+ # When C is 0, H is nil.
13
+ def cie_lch_ab
14
+ cie_lch_ab_uv(type: :lab)
15
+ end
16
+
17
+ # Returns CIE 1976 L*u*v* (CIELUV) values for the RGB object.
18
+ def cie_luv(round: true)
19
+ cie_lab_luv(round: round, type: :luv)
20
+ end
21
+
22
+ alias luv cie_luv
23
+
24
+ # Returns CIE 1976 LCHuv values for the RGB object, derived from L*u*v* (CIELUV).
25
+ #
26
+ # When C is 0, H is nil.
27
+ def cie_lch_uv
28
+ cie_lch_ab_uv(type: :luv)
29
+ end
30
+
31
+ # Returns the difference between this color and another color, according to the CIE 1976 delta E formula.
32
+ #
33
+ # Based on:
34
+ # - http://www.brucelindbloom.com/Eqn_DeltaE_CIE76.html
35
+ # - https://en.wikipedia.org/wiki/Color_difference
36
+ def delta_e_cie_1976(another)
37
+ l , a , b = cie_lab(round: false)
38
+ l2, a2, b2 = another.cie_lab(round: false)
39
+
40
+ Math.sqrt( (l - l2) ** 2 + (a - a2) ** 2 + (b - b2) ** 2 ).round(8)
41
+ end
42
+
43
+ alias de76 delta_e_cie_1976
44
+
45
+ private
46
+
47
+ # Returns either CIE 1976 L*a*b* (CIELAB) or CIE 1976 L*u*v* (CIELUV) values for the RGB object.
48
+ #
49
+ # L*a*b* formula based on:
50
+ # - http://www.brucelindbloom.com/Eqn_XYZ_to_Lab.html
51
+ # - https://en.wikipedia.org/wiki/CIELAB_color_space
52
+ # With peeking at:
53
+ # - https://github.com/halostatue/color/blob/master/lib/color/rgb.rb
54
+ #
55
+ # L*u*v* formula based on:
56
+ # - http://www.brucelindbloom.com/Eqn_XYZ_to_Luv.html
57
+ # - https://en.wikipedia.org/wiki/CIELUV
58
+ def cie_lab_luv(round: true, type: :lab)
59
+ x , y , z = cie_xyz(round: false)
60
+ xr, yr, zr = RGB.white.cie_xyz(round: false)
61
+
62
+ f = [ x / xr, y / yr, z / zr ].map { |v|
63
+ if v > ( 216.0 / 24389 )
64
+ Math.cbrt v
65
+ else
66
+ ( 24389.0 / 27 * v + 16 ) / 116.0
67
+ end
68
+ }
69
+
70
+ if type == :luv
71
+ [
72
+ l = 116 * f[1] - 16,
73
+ 13 * l * ( ( 4 * x ) / ( x + 15 * y + 3 * z ) - ( 4 * xr ) / ( xr + 15 * yr + 3 * zr ) ),
74
+ 13 * l * ( ( 9 * y ) / ( x + 15 * y + 3 * z ) - ( 9 * yr ) / ( xr + 15 * yr + 3 * zr ) )
75
+ ]
76
+ else
77
+ [
78
+ 116 * f[1] - 16,
79
+ 500 * (f[0] - f[1]),
80
+ 200 * (f[1] - f[2])
81
+ ]
82
+ end.map { |v| v.nan? ? 0.0 : ( round ? v.round(8) : v ) }
83
+ end
84
+
85
+ # Returns either CIE 1976 LCHab or CIE 1976 LCHuv values for the RGB object.
86
+ #
87
+ # Based on:
88
+ # - http://www.brucelindbloom.com/Eqn_Lab_to_LCH.html
89
+ # - http://www.brucelindbloom.com/Eqn_Luv_to_LCH.html
90
+ # - https://en.wikipedia.org/wiki/CIELAB_color_space
91
+ def cie_lch_ab_uv(type: :lab)
92
+ if type == :luv
93
+ l, v1, v2 = cie_luv(round: false)
94
+ else
95
+ l, v1, v2 = cie_lab(round: false)
96
+ end
97
+
98
+ [
99
+ l.round(8),
100
+ c = Math.hypot(v1, v2).round(8),
101
+ c == 0 ? nil : ( Math.atan2(v2, v1) * 180.0 / Math::PI ).modulo(360).round(8)
102
+ ]
103
+ end
104
+
105
+ end
@@ -0,0 +1,44 @@
1
+ class RGB
2
+
3
+ # Returns gamma-expanded (inverse-companded) RGB values for the object (three values between 0 and 1).
4
+ #
5
+ # Based on:
6
+ # - https://en.wikipedia.org/wiki/SRGB
7
+ # - http://www.brucelindbloom.com/Eqn_RGB_to_XYZ.html
8
+ # - https://entropymine.com/imageworsener/srgbformula/
9
+ def linear_values
10
+ if color_space == 'sRGB'
11
+ values.map { |v|
12
+ if v <= 0.04045
13
+ v / 12.92
14
+ else
15
+ ( ( v + 0.055 ) / 1.055 ) ** 2.4
16
+ end
17
+ }
18
+ else
19
+ raise "can not compute gamma for color space '#{color_space}'"
20
+ end
21
+ end
22
+
23
+ # Sets the object's RGB values using three linear RGB values, each between 0 and 1.
24
+ # Linear values will be converted to the object's gamma (gamma-companded).
25
+ #
26
+ # Based on:
27
+ # - https://en.wikipedia.org/wiki/SRGB
28
+ # - http://www.brucelindbloom.com/Eqn_XYZ_to_RGB.html
29
+ # - https://entropymine.com/imageworsener/srgbformula/
30
+ def linear_values=(*a)
31
+ if color_space == 'sRGB'
32
+ self.values = a.flatten.map { |v|
33
+ if v <= 0.0031308
34
+ v * 12.92
35
+ else
36
+ 1.055 * ( v ** ( 1/2.4 ) ) - 0.055
37
+ end
38
+ }.map { |v| v.round(9) }
39
+ else
40
+ raise "can not compute gamma for color space '#{color_space}'"
41
+ end
42
+ end
43
+
44
+ end
@@ -0,0 +1,91 @@
1
+ class RGB
2
+
3
+ #----------------------------------------------------------------------#
4
+ # Class Methods #
5
+ #----------------------------------------------------------------------#
6
+
7
+ class << self
8
+
9
+ # Creates a new RGB object from a line of gpl (Gimp color palette) input. Returns nil if not successful.
10
+ #
11
+ # @example
12
+ # RGB.gpl "255 153 204\tpink"
13
+ def gpl(line)
14
+ if line.chomp.match( /^\s*(?<r>\d{1,3})\s+(?<g>\d{1,3})\s+(?<b>\d{1,3})(\s+(?<name>.*))?/ )
15
+ color = RGB.rgb $~[:r].to_i, $~[:g].to_i, $~[:b].to_i
16
+ color.name = $~[:name] if $~[:name]
17
+ color
18
+ else
19
+ nil
20
+ end
21
+ end
22
+
23
+ # Loads a gpl (Gimp color palette) source and returns an array of RGB objects.
24
+ #
25
+ # Options:
26
+ # - file: Path to a .gpl file to be loaded.
27
+ # - url: URL for a .gpl source to be loaded.
28
+ # - compact: Defaults to true. If set to false, returns nil for each line that can not be parsed to an RGB color.
29
+ # - freeze: Defaults to false. If set to true, returns a frozen array of frozen objects.
30
+ #
31
+ # @example String
32
+ # RGB.load_gpl "255 0 0\tred\n255 153 204\tpink\n"
33
+ # @example File
34
+ # RGB.load_gpl file: '/path/to/palette.gpl'
35
+ # RGB.load_gpl file: '/path/to/palette.gpl', compact: false
36
+ # @example URL
37
+ # RGB.load_gpl url: 'https://lospec.com/palette-list/yuko-tomita-time.gpl'
38
+ def load_gpl(source=nil, file: nil, url: nil, compact: true, freeze: false)
39
+
40
+ if ! source
41
+ if file
42
+ source = File.open file
43
+ elsif url
44
+ require 'open-uri'
45
+ source = URI.open url
46
+ end
47
+ end
48
+
49
+ if source.respond_to? :each_line
50
+ list = source.each_line.map { |line| RGB.gpl(line) }
51
+
52
+ if compact
53
+ list.compact!
54
+ end
55
+
56
+ if freeze
57
+ list.freeze
58
+ list.each &:freeze
59
+ end
60
+
61
+ list
62
+ else
63
+ raise ArgumentError, 'Not a valid source'
64
+ end
65
+ end
66
+
67
+ private
68
+
69
+ # Reverse-engineered from:
70
+ # - https://github.com/GNOME/gimp/blob/5d79fba8238a27b8691556489898d33b3fa0dda0/app/core/gimppalette-load.c
71
+ def gpl_header(name, columns=nil)
72
+ "GIMP Palette\n" +
73
+ "Name: #{name}\n" +
74
+ ( columns ? "Columns: #{columns}\n" : '' )
75
+ end
76
+
77
+ end
78
+
79
+ #----------------------------------------------------------------------#
80
+ # Instance Methods #
81
+ #----------------------------------------------------------------------#
82
+
83
+ # Returns the color in the format used in .gpl files (Gimp color palettes), including its name (if present).
84
+ #
85
+ # You can optionally supply a name as argument.
86
+ def gpl(gpl_name=name)
87
+ ( "%3d %3d %3d" % rgb ) +
88
+ ( gpl_name.to_s.size != 0 ? "\t#{gpl_name}" : '' )
89
+ end
90
+
91
+ end
@@ -0,0 +1,61 @@
1
+ require 'redgreenblue/hsv'
2
+
3
+ class RGB
4
+
5
+ #----------------------------------------------------------------------#
6
+ # Class Methods #
7
+ #----------------------------------------------------------------------#
8
+
9
+ class << self
10
+
11
+ # Creates a new RGB object from HSB values: hue (0..360), saturation (0..1), and brightness (0..1).
12
+ alias hsb hsv
13
+
14
+ end
15
+
16
+ #----------------------------------------------------------------------#
17
+ # Instance Methods #
18
+ #----------------------------------------------------------------------#
19
+
20
+ # Returns color as HSB:
21
+ # hue (0..360), saturation (0..1), brightness (0..1).
22
+ # When saturation is 0, hue is nil.
23
+ alias hsb hsv
24
+
25
+ # Returns the object's HSB-hue (0..360).
26
+ alias hsb_h hsv_h
27
+
28
+ # Returns the object's HSB-saturation (0..1).
29
+ alias hsb_s hsv_s
30
+
31
+ # Returns the object's HSB-brightness (0..1).
32
+ alias hsb_b hsv_v
33
+
34
+ # Sets red, green, and blue using HSB values: hue (0..360), saturation (0..1), and brightness (0..1).
35
+ alias hsb= hsv=
36
+
37
+ # Sets HSB-hue to a number of degrees (0..360) or nil.
38
+ #
39
+ # Adjusts red, green, and blue, leaving HSB-saturation and -brightness unchanged.
40
+ # When hue is nil, saturation will be 0.
41
+ alias hsb_h= hsv_h=
42
+
43
+ # Sets HSB-saturation to a number between 0 and 1.
44
+ #
45
+ # Adjusts red, green, and blue, leaving HSB-hue and -brightness unchanged.
46
+ # When saturation is 0, hue will be nil.
47
+ alias hsb_s= hsv_s=
48
+
49
+ # Sets HSB-brightness to a number between 0 and 1.
50
+ #
51
+ # Adjusts red, green, and blue, leaving HSB-hue and -saturation unchanged.
52
+ # When brightness is 0, hue will be nil, and saturation will be 0.
53
+ alias hsb_b= hsv_v=
54
+
55
+ # Sets red, green, and blue by rotating the object's HSB-hue a number of degrees.
56
+ alias hsb_rotate! hsv_rotate!
57
+
58
+ # Creates one or more new RGB objects by rotating this object's HSB-hue a number of degrees.
59
+ alias hsb_rotate hsv_rotate
60
+
61
+ end