Class: ColorConverters::XyzConverter

Inherits:
BaseConverter show all
Defined in:
lib/color_converters/converters/xyz_converter.rb

Constant Summary

Constants inherited from BaseConverter

BaseConverter::IMPORT_DP, BaseConverter::OUTPUT_DP

Instance Attribute Summary

Attributes inherited from BaseConverter

#original_value, #rgba

Class Method Summary collapse

Methods inherited from BaseConverter

#alpha, #cielab, #cielch, #cmyk, factory, #hex, #hsb, #hsl, #hsv, inherited, #initialize, #name, #oklab, #oklch, #rgb, #xyz

Constructor Details

This class inherits a constructor from ColorConverters::BaseConverter

Class Method Details

.boundsObject



11
12
13
# File 'lib/color_converters/converters/xyz_converter.rb', line 11

def self.bounds
  { x: [0.0, 100.0], y: [0.0, 100.0], z: [0.0, 110.0] }
end

.d50_to_d65(xyz_array) ⇒ Object



90
91
92
93
94
95
96
97
98
99
100
# File 'lib/color_converters/converters/xyz_converter.rb', line 90

def self.d50_to_d65(xyz_array)
  x, y, z = xyz_array

  conversion_matrix = ::Matrix[
    [BigDecimal('0.955473421488075'), BigDecimal('-0.02309845494876471'), BigDecimal('0.06325924320057072')],
    [BigDecimal('-0.0283697093338637'), BigDecimal('1.0099953980813041'), BigDecimal('0.021041441191917323')],
    [BigDecimal('0.012314014864481998'), BigDecimal('-0.020507649298898964'), BigDecimal('1.330365926242124')]
  ]

  (conversion_matrix * ::Matrix.column_vector([x, y, z])).to_a.flatten
end

.d65Object



15
16
17
# File 'lib/color_converters/converters/xyz_converter.rb', line 15

def self.d65
  { x: 95.047, y: 100.0, z: 108.883 }
end

.d65_to_d50(xyz_array) ⇒ Object



102
103
104
105
106
107
108
109
110
111
112
# File 'lib/color_converters/converters/xyz_converter.rb', line 102

def self.d65_to_d50(xyz_array)
  x, y, z = xyz_array

  conversion_matrix = ::Matrix[
    [BigDecimal('1.0479297925449969'), BigDecimal('0.022946870601609652'), BigDecimal('-0.05019226628920524')],
    [BigDecimal('0.02962780877005599'), BigDecimal('0.9904344267538799'), BigDecimal('-0.017073799063418826')],
    [BigDecimal('-0.009243040646204504'), BigDecimal('0.015055191490298152'), BigDecimal('0.7518742814281371')]
  ]

  (conversion_matrix * ::Matrix.column_vector([x, y, z])).to_a.flatten
end

.matches?(colour_input) ⇒ Boolean

Returns:

  • (Boolean)


5
6
7
8
9
# File 'lib/color_converters/converters/xyz_converter.rb', line 5

def self.matches?(colour_input)
  return false unless colour_input.is_a?(Hash)

  colour_input.keys - [:x, :y, :z] == []
end

.rgb_to_xyz(rgb_array_frac) ⇒ Object



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
# File 'lib/color_converters/converters/xyz_converter.rb', line 64

def self.rgb_to_xyz(rgb_array_frac)
  rr, gg, bb = RgbConverter.rgb_to_lrgb(rgb_array_frac)

  # Convert using the RGB/XYZ matrix and sRGB's own white, D65 (no chromatic adaptation)
  # https://www.w3.org/TR/css-color-4/#color-conversion-code
  conversion_matrix = ::Matrix[
    [BigDecimal('0.4123907992659595'), BigDecimal('0.35758433938387796'), BigDecimal('0.1804807884018343')],
    [BigDecimal('0.21263900587151036'), BigDecimal('0.7151686787677559'), BigDecimal('0.07219231536073371')],
    [BigDecimal('0.01933081871559185'), BigDecimal('0.11919477979462599'), BigDecimal('0.9505321522496606')]
  ]

  x, y, z = (conversion_matrix * ::Matrix.column_vector([rr, gg, bb])).to_a.flatten

  # Now, scale X, Y, Z so that Y for D65 white would be 100.
  x *= 100.0
  y *= 100.0
  z *= 100.0

  # Clamping XYZ values to prevent out-of-gamut issues and numerical errors and ensures these values stay within the valid and expected range.
  # x = x.clamp(0.0..95.047)
  # y = y.clamp(0.0..100.0)
  # z = z.clamp(0.0..108.883)

  [x, y, z]
end

.xyz_to_rgb(xyz_hash) ⇒ Object



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
# File 'lib/color_converters/converters/xyz_converter.rb', line 37

def self.xyz_to_rgb(xyz_hash)
  # [0, 100]
  x = xyz_hash[:x].to_d
  y = xyz_hash[:y].to_d
  z = xyz_hash[:z].to_d

  # Convert XYZ (typically with Y=100 for white) to normalized XYZ (Y=1 for white).
  # The transformation matrix expects X, Y, Z values in the 0-1 range.
  x /= 100.0.to_d
  y /= 100.0.to_d
  z /= 100.0.to_d

  # Convert normalized XYZ to Linear sRGB values using sRGB's own white, D65 (no chromatic adaptation)
  # https://www.w3.org/TR/css-color-4/#color-conversion-code
  conversion_matrix = ::Matrix[
    [BigDecimal('3.2409699419045213'), BigDecimal('-1.5373831775700935'), BigDecimal('-0.4986107602930033')],
    [BigDecimal('-0.9692436362808798'), BigDecimal('1.8759675015077206'), BigDecimal('0.04155505740717561')],
    [BigDecimal('0.05563007969699361'), BigDecimal('-0.20397695888897657'), BigDecimal('1.0569715142428786')]
  ]

  rr, gg, bb = (conversion_matrix * ::Matrix.column_vector([x, y, z])).to_a.flatten

  # [0, 1]
  RgbConverter.lrgb_to_rgb([rr, gg, bb])
end