-
Notifications
You must be signed in to change notification settings - Fork 20
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
Important decisions with respect to color math (please comment) #126
Comments
This does not seem to have generated much controversy, so I'll begin implementing these changes. I will use |
I have no objection about the multiplication.The multiplication of Regarding ColorVectorSpace.jl/src/ColorVectorSpace.jl Lines 160 to 166 in f2baf1d
|
I'm eager to get this right, and so the sooner we fix problems the better. But I'm all in favor of a staged migration with good deprecation warnings. I haven't yet begun to plan for how to do the migration; I'm more interested in finding out whether the considerations I outline in the OP represent where we want to end up. For |
This comment has been minimized.
This comment has been minimized.
BTW, when |
With this proposal, we won't even need var((x, μ)->(x - μ)⊗(x - μ), collection) |
I agree to some degree. However, WRT |
BTW, I'm going to create a new package ColorBlendModes, which implements the blend modes specified in the Compositing and Blending Level 1 (cf. JuliaGraphics/ColorTypes.jl#167). Edit: |
Well, my effort to add these operators "correctly" (in a way that permits sharing with other packages that have compatible meaning) turned into an epic thread, see JuliaLang/julia#35150. It's finally resolved, and there's a new package, https://github.com/JuliaMath/TensorCore.jl. Once that finishes being registered, maybe it will be time to finish this. |
BTW, the ambiguity of the product will be solved by TensorCore.jl, but what about the division? |
Here's a proposal: |
🤔
👍 What should the result of |
Sorry, I was very unclear. |
This notably defines 3 multiplication operators for RGB colors. It also un-defines `abs2`, because how that should work is a bit ambiguous. Finally, it defines a new `varmult` function, which allows one to compute variance using a specific multiplication operator. There are some compatibility definitions for current releases of ColorTypes. Closes #126 Co-authored-by: Johnny Chen <[email protected]>
RGB multiplication and implications for
var
(#119, #125)Currently multiplication of two RGBs is undefined, but sometimes this causes problems (#119, "tinting" as in https://discourse.julialang.org/t/loaderror-dimensionmismatch/35507?u=tim.holy). In #119, we hit on the possibility of defining
⋅
(\cdot
) as the "dot product" (with channels viewed as a vector),*
operating channelwise, and⊗
(\otimes
) some day being the outer product (though we currently lack a type to express this result). I'll modify this proposal below, but for now let's run with it and explore the implications. An important route lies throughabs2
...Currently,
abs2(c)
returns a scalar, which in this proposed framework would be equivalent to definingabs2(c) = c⋅c
. This is similar to howabs2
behaves with respect to the real and imaginary components of a complex number. This results in the following:However, if you load Images it changes the behavior of☹️ . Rather than overloading
var
to be channelwise, because Images specializesvar
for arrays of Colorantsvar
for certain element types, we could let*
be channelwise multiplication and defineabs2(c) = c*c
, and it should even make it robust with respect to thedims
keyword argument (#125, CC @wizofe).However, since this package is called ColorVectorSpace it's also worth noting this comparison:
so this is an issue that doesn't have an agreed-upon resolution elsewhere in the ecosystem. We might actually want to be able to pass an operator, and the thinking above inspires me to propose
var(⋅, a)
,var(*, a)
, andvar(⊗, a)
.However, this conflicts with the very clear decision that
u*v
for two vectorsu
andv
is deliberately undefined, and specifically does not mean elementwise multiplication (that's what broadcasting is for). Unfortunately, it's not possible to pass broadcasted-*
(.*
) as an argument to a function. Consequently we might consider choosing an operator to be a synonym for elementwise multiplication, and leaving*
undefined for RGB. Options include∗
(\ast
),•
(\bullet
), and⊙
(\odot
). I worry that\ast
looks too similar to*
and would be confused for it; if we go this way I think my preference is for\odot
but curious to see what others think.By this token
abs2
should be undefined for colors,var(a)
should throw an error for color arrays, butvar(⊙, a)
should do what users want.Because of the analogy with arrays-of-vectors I'll open a similar issue in Statistics.jl and see what folks outside of the JuliaImages world think. (Update: https://github.com/JuliaLang/Statistics.jl/issues/29)
Interaction between color math and conversions
Another factor that would argue in favor of changing the behavior of
abs2
is the following set of logical-sounding conclusions:x
is a real number, thenGray(x)
is basically the same thing (other than being a display hint)RGB(Gray(x))
should returnRGB(x, x, x)
, so by the same tokenRGB(x, x, x)
is essentially equivalent tox
Our current scheme has a big gotcha:
so we're in a situation where
a
andb
can be equivalent butabs2(a)
is very different fromabs2(b)
. If we changedabs2
to behave channelwise, we'd restore consistency. An error would also fix it; we don't object to-1 == -1+0im
but havingsqrt
return an error for just one of them.Result types from arithmetic (#38)
I originally designed the rules to be inspired to unitful arithmetic. However, most others who have commented seem to expect that colors will be "poisoning" in much the same way that
NaN
is poisoning in arithmetic. (#38 (comment) as well as the OP in #38).Given that we support
Gray(0.1)^2
and there is no type encodingGray^2
, I now think the poisoning metaphor is overall the better choice.I suspect there is one interesting exception to the poisoning rule, however, which comes from linear algebra:
Note the returned value is a scalar, not an
SVector{3}
. (The value minimizesnorm(α*u - v)
for real-valuedα
.) Should we define\
forGray
andRGB
?/
cannot be defined forRGB
(EDIT: in the denominator), but it can forGray
; shouldGray(0.2) / Gray(0.1)
likewise be "colorless"? That is a little bit more like the unitful design. Is that a good thing, or would that be annoying?The text was updated successfully, but these errors were encountered: