redgreenblue 0.6.0 → 0.11.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: 1cac7c885ca1de3e3fe22ebfaf7207dd17b7bd25e8c1dd6f82cfdab0e0b5cee1
4
- data.tar.gz: 7ca71212d78ae2a638d8bfb54dcb8a824367eac6e7fe8ca1eaa1e239b22bbaa9
3
+ metadata.gz: dc4e866d75637857fb5a4b27b77829e20f488e321fa287b73a5d6d9c21d194a9
4
+ data.tar.gz: e3f9e875b0a8893bd21a6cd503702881833f54873557f84c4cf4776338294668
5
5
  SHA512:
6
- metadata.gz: 23316f3526690807fabde09d5a909ae7afe396da7b039baa6352c814ab653d02ee5646aa23ece364748cf090f4b9218a34c0cd19b8a04313086b2c5f9dcadf97
7
- data.tar.gz: 19f71a26312a83d845f8ff508758e653b693289be129e02281e65cb8da4b13d32ab5b58282883ea0d0dc4c156ddd775c0179354bea5dccc6065f00ad49b7f66c
6
+ metadata.gz: 94b96125e65443d7ceb66cfabf9ba6b0681bfc51046b8d308e86d0904a58a7f745f6ea159a040ee79dcb9713ace9adbc416a5705c4b2ebb85333bf09f0dd9a43
7
+ data.tar.gz: f3e0bd4c0cdcd432dd50fc518f1d2062c66ac907f55b3235405589b2d797791c48b3d62284ae665a8fc4d60c4209ce0b3d46d07a459e15d2fa261d9b1aa8df1d
@@ -1,22 +1,26 @@
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/lazy'
13
- require 'redgreenblue/nice'
10
+ 24bit 48bit hex int
14
11
 
15
- require 'redgreenblue/rgb565'
16
- require 'redgreenblue/bgr24bit'
17
- require 'redgreenblue/gif'
12
+ hsl hsv hsb
18
13
 
19
- require 'redgreenblue/misc'
20
- require 'redgreenblue/random'
14
+ ostwald
21
15
 
22
- require 'redgreenblue/os'
16
+ gamma cie
17
+
18
+ inspect lazy
19
+
20
+ rgb565 bgr24bit gif terminal web gpl
21
+
22
+ mix misc random
23
+
24
+ os
25
+
26
+ ).each { |m| require "redgreenblue/#{m}" }
@@ -2,46 +2,79 @@ class RGB
2
2
 
3
3
  # r, g, b methods
4
4
 
5
+ # Returns the red component as an integer in the range 0..255 (an 8-bit value).
5
6
  def r
6
7
  (red * 255).round
7
8
  end
8
9
 
10
+ # Returns the green component as an integer in the range 0..255 (an 8-bit value).
9
11
  def g
10
12
  (green * 255).round
11
13
  end
12
14
 
15
+ # Returns the blue component as an integer in the range 0..255 (an 8-bit value).
13
16
  def b
14
17
  (blue * 255).round
15
18
  end
16
19
 
20
+ # Sets the red component using an integer in the range 0..255 (an 8-bit value).
17
21
  def r=(n)
18
22
  self.red = n / 255.0
19
23
  end
20
24
 
25
+ # Sets the green component using an integer in the range 0..255 (an 8-bit value).
21
26
  def g=(n)
22
27
  self.green = n / 255.0
23
28
  end
24
29
 
30
+ # Sets the blue component using an integer in the range 0..255 (an 8-bit value).
25
31
  def b=(n)
26
32
  self.blue = n / 255.0
27
33
  end
28
34
 
29
35
  # rgb methods
30
36
 
37
+ # Returns the red, green, and blue components as integers in the range 0..255 (three 8-bit values).
31
38
  def rgb
32
39
  [r,g,b]
33
40
  end
34
41
 
35
- def rgb=(rgb)
36
- self.r, self.g, self.b = rgb
42
+ # Sets the red, green, and blue components using three integers in the range 0..255 (three 8-bit values).
43
+ def rgb=(*rgb)
44
+ self.r, self.g, self.b = rgb.flatten
37
45
  end
38
46
 
39
- # factory method
40
-
41
- def self.rgb(rgb)
47
+ # Creates a new object from red, green, and blue components as integers in the range 0..255 (three 8-bit values).
48
+ def self.rgb(*rgb)
42
49
  c = self.new
43
50
  c.rgb = rgb
44
51
  c
45
52
  end
46
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
+
65
+ # Calls the given block for each 24-bit RGB color (from black to white), passing the color as an RGB object.
66
+ #
67
+ # Returns the number of iterations.
68
+ def self.each_24bit_color
69
+ range = 0..255
70
+ range.each do |r|
71
+ range.each do |g|
72
+ range.each do |b|
73
+ yield self.rgb(r,g,b)
74
+ end
75
+ end
76
+ end
77
+ range.size ** 3
78
+ end
79
+
47
80
  end
@@ -2,43 +2,50 @@ class RGB
2
2
 
3
3
  # rr, gg, bb methods
4
4
 
5
+ # Returns the red component as an integer in the range 0..65535 (a 16-bit value).
5
6
  def rr
6
7
  (red * 65535).round
7
8
  end
8
9
 
10
+ # Returns the green component as an integer in the range 0..65535 (a 16-bit value).
9
11
  def gg
10
12
  (green * 65535).round
11
13
  end
12
14
 
15
+ # Returns the blue component as an integer in the range 0..65535 (a 16-bit value).
13
16
  def bb
14
17
  (blue * 65535).round
15
18
  end
16
19
 
20
+ # Sets the red component using an integer in the range 0..65535 (a 16-bit value).
17
21
  def rr=(n)
18
22
  self.red = n / 65535.0
19
23
  end
20
24
 
25
+ # Sets the green component using an integer in the range 0..65535 (a 16-bit value).
21
26
  def gg=(n)
22
27
  self.green = n / 65535.0
23
28
  end
24
29
 
30
+ # Sets the blue component using an integer in the range 0..65535 (a 16-bit value).
25
31
  def bb=(n)
26
32
  self.blue = n / 65535.0
27
33
  end
28
34
 
29
35
  # rrggbb methods
30
36
 
37
+ # Returns the red, green, and blue components as integers in the range 0..65535 (three 16-bit values).
31
38
  def rrggbb
32
39
  [rr,gg,bb]
33
40
  end
34
41
 
35
- def rrggbb=(rrggbb)
36
- self.rr, self.gg, self.bb = rrggbb
42
+ # Sets the red, green, and blue components using three integers in the range 0..65535 (three 16-bit values).
43
+ def rrggbb=(*rrggbb)
44
+ self.rr, self.gg, self.bb = rrggbb.flatten
37
45
  end
38
46
 
39
- # factory method
40
-
41
- def self.rrggbb(rrggbb)
47
+ # Creates a new object from red, green, and blue components as integers in the range 0..65535 (three 16-bit values).
48
+ def self.rrggbb(*rrggbb)
42
49
  c = self.new
43
50
  c.rrggbb = rrggbb
44
51
  c
@@ -1,36 +1,82 @@
1
1
  class RGB
2
2
 
3
- attr_reader :red, :green, :blue
3
+ def initialize(*a)
4
+ self.values = a.any? ? a : [ 0.5, 0.5, 0.5 ]
5
+ end
6
+
7
+ # Returns the color space.
8
+ #
9
+ # Currently always 'sRGB'.
10
+ def color_space
11
+ @color_space ||= 'sRGB'
12
+ end
4
13
 
5
- def initialize(a=[0.5, 0.5, 0.5])
6
- self.values = a
14
+ # Returns the red component as a value between 0 and 1.
15
+ def red
16
+ @red
7
17
  end
8
18
 
9
- def red=(n)
10
- @red = limit(n)
19
+ # Returns the green component as a value between 0 and 1.
20
+ def green
21
+ @green
11
22
  end
12
23
 
13
- def green=(n)
14
- @green = limit(n)
24
+ # Returns the blue component as a value between 0 and 1.
25
+ def blue
26
+ @blue
15
27
  end
16
28
 
17
- def blue=(n)
18
- @blue = limit(n)
29
+ # Sets the red component to a value between 0 and 1.
30
+ #
31
+ # Values outside the range 0..1 will be clipped.
32
+ def red=(value)
33
+ @red = limit(value)
19
34
  end
20
35
 
36
+ # Sets the green component to a value between 0 and 1.
37
+ #
38
+ # Values outside the range 0..1 will be clipped.
39
+ def green=(value)
40
+ @green = limit(value)
41
+ end
42
+
43
+ # Sets the blue component to a value between 0 and 1.
44
+ #
45
+ # Values outside the range 0..1 will be clipped.
46
+ def blue=(value)
47
+ @blue = limit(value)
48
+ end
49
+
50
+ # Returns the red, green, and blue components as three values between 0 and 1.
21
51
  def values
22
52
  [ red, green, blue ]
23
53
  end
24
54
 
25
55
  alias to_a values
26
56
 
27
- def values=(a)
28
- self.red, self.green, self.blue = a
57
+ # Sets the red, green, and blue components using three values between 0 and 1.
58
+ #
59
+ # Values outside the range 0..1 will be clipped.
60
+ def values=(*a)
61
+ self.red, self.green, self.blue = a.flatten
62
+ end
63
+
64
+ # Returns true if this object and another object represent exactly the same color. Otherwise returns false.
65
+ def ==(other)
66
+ ( self.class == other.class ) && ( self.values == other.values )
67
+ end
68
+
69
+ # Returns a sorted hash of 3 key/value pairs for red, green, and blue,
70
+ # sorted in order of decreasing value.
71
+ def to_h
72
+ ([:red, :green, :blue].zip values).sort_by {
73
+ |k,v| [-v,[:red, :green, :blue].index(k)]
74
+ }.to_h
29
75
  end
30
76
 
31
77
  private
32
78
 
33
- # limit to 0..1
79
+ # limits to range 0..1
34
80
  def limit(n)
35
81
  n <= 0 ? 0.0 : n >= 1 ? 1.0 : n
36
82
  end
@@ -1,16 +1,16 @@
1
1
  class RGB
2
2
 
3
- # bgr 24-bit methods (as used by BMP bitmaps)
4
-
3
+ # Returns a 3-byte string containing the object's color in BGR24 format.
5
4
  def bgr24
6
5
  [b, g, r].pack('C3')
7
6
  end
8
7
 
9
- def bgr24=(s)
10
- self.b, self.g, self.r = s.unpack('C3')
8
+ # Sets red, green, and blue using BGR24 data (a 3-byte string).
9
+ def bgr24=(bgr_string)
10
+ self.b, self.g, self.r = bgr_string.unpack('C3')
11
11
  end
12
12
 
13
- # factory method
13
+ # Creates a new RGB object from BGR24 data (a 3-byte string).
14
14
  def self.bgr24(bgr)
15
15
  c = self.new
16
16
  c.bgr24 = bgr
@@ -0,0 +1,45 @@
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 by Bruce Lindbloom:
9
+ # - http://www.brucelindbloom.com/index.html?Eqn_RGB_XYZ_Matrix.html
10
+ def cie_xyz
11
+ r, g, b = linear_values
12
+ [
13
+ r * 0.4124564 + g * 0.3575761 + b * 0.1804375,
14
+ r * 0.2126729 + g * 0.7151522 + b * 0.0721750,
15
+ r * 0.0193339 + g * 0.1191920 + b * 0.9503041
16
+ ].map { |v| v.round(6) }
17
+ end
18
+
19
+ alias xyz cie_xyz
20
+
21
+ # Returns CIE 1931 xyY values for the RGB object.
22
+ #
23
+ # Based on:
24
+ # - https://en.wikipedia.org/wiki/CIE_1931_color_space
25
+ # - http://www.brucelindbloom.com/index.html?Eqn_XYZ_to_xyY.html
26
+ # - https://ninedegreesbelow.com/photography/xyz-rgb.html
27
+ def cie_xyy
28
+ x, y, z = xyz
29
+ [
30
+ x / ( x + y + z ),
31
+ y / ( x + y + z ),
32
+ y
33
+ ].map { |v| v.round(6) }
34
+ end
35
+
36
+ alias xyy cie_xyy
37
+
38
+ # Returns CIE 1931 xy values for the RGB object.
39
+ def cie_xy
40
+ cie_xyy[0..1]
41
+ end
42
+
43
+ alias xy cie_xy
44
+
45
+ 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
@@ -1,15 +1,16 @@
1
1
  class RGB
2
2
 
3
- # Return a 1-pixel GIF
3
+ # Returns a 1-pixel GIF image set to the color.
4
4
  #
5
5
  # With help from:
6
- # - http://www.perlmonks.org/?node_id=7974
6
+ # - https://www.perlmonks.org/?node_id=7974
7
7
  def gif_pixel
8
8
  "GIF89a\1\0\1\0\x90\0\0".b +
9
9
  rgb.pack('C3') +
10
10
  "\0\0\0,\0\0\0\0\1\0\1\0\0\x02\x02\x04\1\0;".b
11
11
  end
12
12
 
13
+ # Writes a 1-pixel GIF image to a file.
13
14
  def gif_pixel_write(file_path)
14
15
  File.binwrite(file_path, gif_pixel)
15
16
  end
@@ -0,0 +1,30 @@
1
+ class RGB
2
+
3
+ ########################################################################
4
+ # Class methods #
5
+ ########################################################################
6
+
7
+ class << self
8
+
9
+ private
10
+
11
+ # Reverse-engineered from:
12
+ # - https://github.com/GNOME/gimp/blob/5d79fba8238a27b8691556489898d33b3fa0dda0/app/core/gimppalette-load.c
13
+ def gpl_header(name, columns=nil)
14
+ "GIMP Palette\n" +
15
+ "Name: #{name}\n" +
16
+ ( columns ? "Columns: #{columns}\n" : '' )
17
+ end
18
+
19
+ end
20
+
21
+ ########################################################################
22
+ # Instance methods #
23
+ ########################################################################
24
+
25
+ # Returns the color in the format used in .gpl files (Gimp color palettes). A name for the color is optional.
26
+ def gpl(name=nil)
27
+ ( "%3d %3d %3d" % rgb ) + ( name ? "\t#{name}" : '' )
28
+ end
29
+
30
+ end