I think there should be some way from the distance to the primaries, or the intersection of the line that connects the point and the white point with the limits of the gamut.
How to calculate the maximum possible value of Y for a pair of chromaticity coordinates x, y in sRGB
-
Welcome to SO. Have you written any code to try to solve this yourself? Right now your question doesn't show any research effort, which means it will likely be downvoted. Check out the [Help Docs](https://stackoverflow.com/help) for info on how to write a good question that will attract good answers. – Sean Mar 28 '19 at 19:03
-
You cannot do it. x,y do no provide luminance. The true colour space is Yxy (or xyz, but this is less interesting), where Y is the 3rd dimention. You may have notices that you see many different xy diagrams (look for the yellows). The diagrams are just a projection (a cut) of the Yxy space. – Giacomo Catenazzi Mar 29 '19 at 08:18
-
Yes, you are right, I have edited the question. – Alex 23 Mar 29 '19 at 14:16
2 Answers
I think you can approximate your Y very well with numerical methods, but it is quite hard to pin down a formula.
The max for Y is 100, so to avoid the difficulty of finding a starting point that is inside sRGB, I would probably implement a numerical approximation of a slightly different question.
I know that a Yxy of (100, x, y) is probably out of bounds, so I would decrease Y until I'm in sRGB gamut. An interval of about 0.5 - 0.2 should suffice.

- 576
- 4
- 15
-
Thanks, that's way easier. Still trying to figure out the logic to do it in a geometric way though. – Alex 23 Apr 01 '19 at 13:12
The simplest and most accurate way to do this is to convert to sRGB, set the luminance to the maximum, and convert back to XYZ. When converting to sRGB you have to make sure to choose a value for Y that will give a result within the gamut for any point x,y (it must be below the minimum relative luminance coefficient, which for sRGB is ≃ 0.072 for blue). Note that this doesn't check that the point x,y is inside the gamut:
#include <Math.au3>
;XYZtosRGB
Global $RsRGB[3] = [3.2409699, -1.5373832, -0.4986108]
Global $GsRGB[3] = [-0.9692436, 1.8759675, 0.0415551]
Global $BsRGB[3] = [0.0556301, -0.203977, 1.0569715]
;sRGBtoXYZ
Global $XsRGB[3] = [0.4123908, 0.3575843, 0.1804808]
Global $YsRGB[3] = [0.212639, 0.7151687, 0.0721923]
Global $ZsRGB[3] = [0.0193308, 0.1191948, 0.9505322]
Global $Wx = 0.3127, $Wy = 0.3290
Func DP($T, $S)
return $T[0] * $S[0] + $T[1] * $S[1] + $T[2] * $S[2]
EndFunc
Func xyYtoXYZ($xyY)
Local $XYZ = $xyY
If $xyY[2] <> 0 Then
$XYZ[0] = $xyY[0] * $xyY[2] / $xyY[1]
$XYZ[2] = $xyY[2] * (1 - $xyY[0] - $xyY[1]) / $xyY[1]
Else
$XYZ[0] = 0
$XYZ[2] = 0
EndIf
$XYZ[1] = $xyY[2]
Return $XYZ
EndFunc
Func FindY($x, $y)
Local $xyY = [$x, $y, 0.07]
Local $XYZ = xyYtoXYZ($xyY)
Local $sRGBin = [DP($RsRGB, $XYZ), DP($GsRGB, $XYZ), DP($BsRGB, $XYZ)]
Local $inc = _Min(_Min(1 / $RGBin[0], 1 / $RGBin[1]), 1 / $RGBin[2])
Local $sRGBout = [$sRGBin[0] * $inc, $sRGBin[1] * $inc, $sRGBin[2] * $inc]
Return DP($YsRGB, $sRGBout)
EndFunc

- 1
- 2