Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Incorrect YIQ conversion #185

Closed
facelessuser opened this issue Jan 21, 2023 · 3 comments
Closed

Incorrect YIQ conversion #185

facelessuser opened this issue Jan 21, 2023 · 3 comments
Labels
Bug Something isn't working Documentation

Comments

@facelessuser
Copy link

facelessuser commented Jan 21, 2023

I was implementing YIQ and wanted to compare my numbers to another library as a sanity check. I found that our values differed quite a bit.

> culori.yiq('purple')
{
  mode: 'yiq',
  y: 0.0892318825202534,
  i: 0.059183790065278435,
  q: 0.11281239073268069
}
>>> Color('purple').convert('yiq')
color(--yiq 0.2075 0.13763 0.26233 / 1)

I then compared it against one more source just to get another data point. They are using FCC NTSC Standard (SMPTE C) as mentioned in the Wikipedia article, instead of what's shown in http://www.progmat.uaem.mx:8080/artVol2Num2/Articulo3Vol2Num2.pdf, but the results are comparable.

>>> import colorsys
>>> colorsys.rgb_to_yiq(128 / 255, 0, 128 / 255)
(0.20580392156862742, 0.13919372549019607, 0.2635796078431373)

I think they are probably doing things wrong in a different way as they are using the SMPTE C values, but not using SMPTE C RGB which uses different chromaticities. I guess the original 1953 NTSC also used different chromaticities than sRGB as well. It may be that lots of people are doing it slightly differently. The research paper seems to suggest it is using sRGB, but I have no idea where exactly they got their matrix from either. This statement can probably be ignored as it seems there is the "official" YIQ used by TV, but people generally use YIQ like a color model for any RGB, even if it is specifically weighted for a specific RGB.

Looking over your code, I found out why yours differs so much; you are converting the color in linear sRGB and YIQ is supposed to be transformed using the gamma-encoded color, not linear:

From http://www.progmat.uaem.mx:8080/artVol2Num2/Articulo3Vol2Num2.pdf (emphasis added)

The values of Y, I and Q can be
directly calculated from the non-linear r’, g’
and b’ components in the following way [21]:

From https://en.wikipedia.org/wiki/YIQ (emphasis added)

These formulas allow conversion between YIQ and RGB color spaces, where R, G, and B are gamma-corrected values.

It seems that linear sRGB is not meant to be used with this transform. The one thing that does seem consistent across the different implementations I've looked at is that they don't use linear RGB values. It is certainly possible that I've somehow misinterpreted something.

@danburzo
Copy link
Collaborator

Hi Isaac, thanks for opening this issue. You're totally right! I must have misread non-linear for linear in the paper when I implemented the Kotsarenko-Ramos color difference formula, which was the impetus for introducing the YIQ color space as a mapping of sRGB (the color space assumed in the authors' paper).

I should also probably clarify in the color space reference what flavor of YIQ we're using.

@danburzo danburzo added Bug Something isn't working Documentation labels Jan 24, 2023
@facelessuser
Copy link
Author

Yep, no problem. I think it is a color space used casually here and there as a model instead of the "official" spec. Something I did not understand until I began researching it.

Anyways, glad I could help!

@danburzo
Copy link
Collaborator

The corrected conversion is included in the [email protected] release.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Bug Something isn't working Documentation
Projects
None yet
Development

No branches or pull requests

2 participants