vivid
vivid copied to clipboard
Converting from RGB to HSV and then back doesn't result in the original values
This assert fails:
local vivid = require 'vivid'
local small = 1e-6
for w = 0, 10 do
for z = 0, 10 do
for y = 0, 10 do
for x = 0, 10 do
local x, y, z, w = x / 10, y / 10, z / 10, w / 10
local h, s, v, _ = vivid.RGBtoHSV(x, y, z, w)
local r, g, b, a = vivid.HSVtoRGB(h, s, v, _)
assert(
math.abs(x - r) < small and
math.abs(y - g) < small and
math.abs(z - b) < small and
math.abs(w - a) < small,
string.format(
'%.3f,%.3f,%.3f,%.3f ~= %.3f,%.3f,%.3f,%.3f',
x, y, z, w, r, g, b, a
)
)
end
end
end
end
luajit: main.lua:10: 0.000,0.000,0.100,0.000 ~= 0.000,0.100,0.100,0.000
stack traceback:
[C]: in function 'assert'
main.lua:10: in main chunk
[C]: at 0x7ff6b59947d0
This is to be expected. The conversation itself is a lossy operation. The recommended practice is to keep your color in one base color system and only convert one direction.
On top of that the RGB and HSV color spaces aren't 1:1 and have a different color gamut. I think this is just inherent in the concept rather than a bug in the code. It appears you put in a PR so I'll review it because that may fix the inconsistencies.
Well sure, there's floating point errors involved, but I've accounted for them in the snippet above by checking if the values are within a small margin instead of equating them. I'm not too knowledgeable about color spaces, but from what I understand the snippet above shouldn't fail.
If you convert from hsv to rgb and then back, then sure, it might not match. For instance the hue might be different if saturation was originally 0. But I believe the case for rgb to hsv and back is different. From the error above it seems like the hue has shifted going from blue to a sort of turquoise. I would expect it to at least maintain the hue.
Anyway, my PR does not fail the test above. Again, I might not be knowledgeable enough about this. The code in my PR I must've found somewhere on stack exchange or something and then converted it to lua, so I didn't really look into how this works, but I just noticed that I seemingly got unexpected results in my projects when using this library, so I figured I'd 'fix' it.