Skip to content

@fantasy-color has sRGB and RGB completely backwards #507

@thomcc

Description

@thomcc

Hi, I'm writing a blog post on how a color math bug in a spec ended up spreading through the web development ecosystem in some pretty baffling ways, and so I've looked through a bunch of JS packages that do color stuff, and yours were one of them. (Note: You don't seem to have the bug I'm writing the blog post on, that's not why I'm filing this)

I did notice that you have a serious enough bug that I can't leave it be without saying something though. You have a major confusion in all of your @fantasy-color packages:

You seem to have sRGB completely backwards. In particular, what you call the sRGB color space is actually usually called linear RGB — often just RGB (the terminology here is actually pretty complex and vague, unfortunately — this is also the wrong name, but it's not important here), and what you call RGB is actually sRGB.


In general, unless you've gone out of your way to convert it, or happen to get very surprising data, the right assumption is that a random RGB input is in the sRGB color space. In fact, this is specified for the web — if you don't know anything else, you are supposed to assume sRGB: https://www.w3.org/Graphics/Color/sRGB.html. (And even when it's not sRGB, it's likely something that has an sRGB-like gamma curve for its transfer function — for example P3, Adobe RGB, ...).

A couple rules of thumb here are:

  • If it is on the web and you have on other indication of the color space, for example most images and any color constants coming from CSS and such, its considered to be sRGB.
  • If the values of the channels are 8-bit, e.g. RGB all between 0-255 (as opposed to 0.0-1.0), it's almost definitely sRGB — since that's just not enough resolution for linear RGB to be useful.

Anyway, that's to say, most of your functions, documentation, etc have this completely backwards.

This is easy to verify too. For example, the wikipedia article for sRGB includes the step where you go from linear RGB into sRGB here:

Screen Shot 2021-06-06 at 8 50 46 PM

If you compare it with

(normalized > NORMALIZED_BELOW_10
? Math.pow(((normalized + 0.055) / 1.055), 2.4)
: normalized / 12.92)
, you'll see that these are inverse operations. Ditto with the other direction and such.

Metadata

Metadata

Assignees

Labels

No labels
No labels

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions