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

Fixing Coloramity #101

Closed
timholy opened this issue Aug 9, 2015 · 75 comments
Closed

Fixing Coloramity #101

timholy opened this issue Aug 9, 2015 · 75 comments

Comments

@timholy
Copy link
Contributor

timholy commented Aug 9, 2015

In an ideal world, one would be able to:

  • load an image from a disk file
  • visualize it using using OpenGL
  • perform some calculations on it using Image's algorithms
  • plot the results in Gadfly

Unfortunately, currently we are far from living in this world. It seems that the biggest problem is the separation between this package (Color) and ColorTypes.jl. I'm running into this in the course of trying to split out functionality in Images into the JuliaIO packages. Overall I agree that splitting this functionality is a good thing: for example, it would be great to largely divorce Images.jl from ImageMagick. The problem is that the ImageMagick.jl package started by Simon (using code lifted from Images) uses ColorTypes, while Images (and essentially all other packages) uses Color, so the GL&JuliaIO world is completely incompatible with the rest of the package ecosystem.

@rant begin
    I'd like to propose that henceforth if one snips out a chunk of functionality
    (especially, types) from one popular package into a standalone package, it's
    incumbent on the programmer to issue pull requests rebasing the
    "parent" package on the new standalone package. This includes getting
    all the parent's tests working. If you're not willing to do that, it's better to use
    the parent package unmodified.
end

I have a proposal for fixing this, and I'm (grumpily) willing to put in the (considerable) time needed to make it happen:

  • @SimonDanisch presumably needs to base color types on FixedSizeArrays.jl for smooth interoperability with GL. Consequently, I propose we keep his design of having a standalone ColorTypes package that only encodes the basic color type definitions, and that it be based on FixedSizeArrays.
  • We make some changes (see below) to the design of ColorTypes to make it a little more like Color.jl. We also pick names that are less awkward than our current names.
  • We rebase Color on top of ColorTypes, naming the new package Colors.jl. We issue a deprecation warning for using Color.
  • To ensure that people actually use the new package, I submit the necessary pull requests against Cairo, ColorBrewer, Escher, Gadfly, Gtk, Images, ImageView, ProfileView, PyPlot, Tk, and Winston. There are a few other packages that use Color, but I can't fix everything, and these are the main ones I've heard of. It's up to @SimonDanisch to update the GL packages.

CC @lobingera, @timothyrenner, @shashi, @dcjones, @vtjnash, @stevengj, @nolta, @SimonDanisch, @jiahao. I'd like feedback from most/all of you before undertaking this course, since it will be a fair amount of work and I'd like to have some confidence that the PR I submit will be accepted.

Proposed type hierarchy sketch for the new ColorTypes:

using FixedSizeArrays

# Paint means either Color or Color+Transparency
abstract AbstractPaint{T, N} <: FixedVector{T, N}

# AbstractColor means just color, no transparency
abstract AbstractColor{T, N} <: AbstractPaint{T, N}
abstract Color{T} <: AbstractColor{T, 3}
abstract AbstractRGB{T} <: Color{T}

# Types with transparency
abstract Transparent{T,N} <: AbstractPaint{T,N}
# Because storage order matters for some applications, we have both
# "AlphaColor" and "ColorAlpha"
abstract AbstractAlphaColor{T,N} <: Transparent{T,N} # storage order alpha-color
abstract AbstractColorAlpha{T,N} <: Transparent{T,N} # storage order color-alpha

# Concrete types
immutable RGB{T} <: Color{T}
    r::T
    g::T
    b::T
end

# ...and so forth

immutable AlphaColor{C<:Color,T} <: AbstractAlphaColor{T,4}
    alpha::T
    c::C   # C really has to be Color{T} (use inner constructor here)
end

immutable ColorAlpha{C<:Color,T} <: AbstractAlphaColor{T,4}
    c::C
    alpha::T
end

# Grayscale
immutable Gray{T} <: AbstractColor{T,1}
    val::T
end

immutable AlphaGray{G,T} <: Transparent{T,2}
    alpha::T
    c::G
end

immutable GrayAlpha{G,T} <: Transparent{T,2}
    c::G
    alpha::T
end
@JeffBezanson
Copy link
Contributor

The plan sounds good. Renaming Color.jl to Colors.jl is probably a good idea in any case.

I'd like to better understand why a color should be considered a FixedVector. Sure, colors form a vector space, but then again lots of things do. Often they are treated like scalar quantities within a program (e.g. like complex numbers). isa(RGB(), AbstractArray) seems a bit odd to me.

@SimonDanisch
Copy link

Oh perfect timing, I was just starting to look into this! Obviously this split wasn't intended! I was mainly waiting for FixedSizeArrays and FileIO to mature, which slowly starts to happen.

@JeffBezanson my main intention is to share a lot of functions. Starting from core functions like length, eltype (defined on the type and instance), over construction, simple conversion, math, to functions defined for arrays of FixedSizeVectors. Its really a lot of functionality which would be nasty to duplicate.
isa(RGB(), AbstractArray) seems to be odd to me as well as no one does it this way but I also don't see an appealing reasion why its bad.
We can always discuss to bend the type hierarchy a bit to account for this, but I'm not sure who would benefit from it.
So far isa(RGB(), AbstractArray) is false, as it got me into an ambigouity hell :D But this should change in the future. I would need to refactor arraymath.jl a bit to make this happen (see JuliaLang/julia#11610). I actually started building a benchmarking suite for array operations in order to get a good baseline before I start messing with Base. The first wave of changes should be relatively straight forward, but I really don't want any speed regressions whatsoever.

@SimonDanisch
Copy link

@timholy this looks good to me!
My two problems are construction of transparent colors and indexing them... But as I don't have a general problem with their structure, I'm sure we find an elegant solution there.

@SimonDanisch
Copy link

@timholy would you mind to post a nice example and requirements of your perfect world to JuliaGeometry/meta#8 ?
Like, how you want to ideally interact and represent the different images (sliders, tiles of different images, animations, history of previosly applied operations, look of the gadfly plot, etc).
Collecting them in one place helps me getting a better mental picture of the different challenges our visualization pipeline faces.

@SimonDanisch
Copy link

@JeffBezanson
It's just quite likely that you'll work with Vec's and RGB's at the same time, which makes it even more desirable to have the same interface.

a = [Vec3(1f0) for i=1:10]::Vector{Vec3{Float32}}
b = [rand(Vec{3, Float32} for i=1:10]
a[1][1:2]
map(RGB, b)
RGB([1,2,3])
Vec(Vec(2,3, 4), 1) + Vec(1,2,3,4)
a[1:end, 1] # -> [x,x,x,x, ...]
mean(a)
...

These are all functions I would like to see for all scalar like types. By the way, I'm using this for my benchmark package as well, which is quite nice for mean, max etc.

immutable BenchData{T}  <: FixedVector{5, T}
    time_ns         ::T
    gc_bytes        ::T
    gc_time_ns      ::T
    gc_num_pause    ::T
    gc_full_sweep   ::T
end
a = zeros(BenchData, N)
for i=1:N
a[i] = @bench expr
end
mean(a) #etc

Its also nice to do k-means and PCA and things like that on e.g. RGB directly, which would be a lot easier if its a subtype of FixedSizeArray (Which would work for arbitrary other data types which inherit from FixedSizeArrays).

@SimonDanisch
Copy link

immutable AlphaColor{T, C<:Color{T}} <: AbstractAlphaColor{T,4}
    alpha::T
    c::C   # C really has to be Color{T} (use inner constructor here)
end

Can we expect this to work at some point via some triangular dispatch alike pattern?

@timholy
Copy link
Contributor Author

timholy commented Aug 9, 2015

Obviously this split wasn't intended! I was mainly waiting for FixedSizeArrays and FileIO to mature, which slowly starts to happen.

I know it seems daunting, but I think it's better to make core infrastructure reasonably mature before commencing on such a split. Otherwise you're basically asking other people to carry out that maturation for you (see https://github.com/JuliaIO/FileIO.jl/commits/master). And how do you otherwise know it will work?

Starting from core functions like length, eltype (defined on the type and instance), over construction, simple conversion, math, to functions defined for arrays of FixedSizeVectors. Its really a lot of functionality which would be nasty to duplicate.

I see the point, but for Images I do a lot of that already: https://github.com/timholy/Images.jl/blob/cb9c0811cef911ff590fd58dc4eab3bc6d17274f/src/colortypes.jl#L225-L577. Is that really the only reason you use FixedSizeArrays? I thought there might be some magic GPU reason 😄.

As an example of what can make this kind of thing hard, what you'd probably like is something like this:

immutable ColorAlpha{T,N,C{T,N}} <: FixedVector{T,N+1}
    c::Color{T,N}
    alpha::T
end

but the N+1 part of that is something we may never have.

Can we expect this to work at some point via some triangular dispatch alike pattern?

I think it's on the slate in JuliaLang/julia#8974. The code in Images is looking forward to a nice haircut once that merges.

@timholy would you mind to post a nice example and requirements of your perfect world to JuliaGeometry/meta#8 ?

I think "vision about how the whole visualization pipeline should work" is a little too broad to be relevant here.

Its also nice to do k-means and PCA and things like that on e.g. RGB directly, which would be a lot easier if its a subtype of FixedSizeArray (Which would work for arbitrary other data types which inherit from FixedSizeArrays).

reinterpret is always your friend. Is there stuff you can't do that way? This is indeed an example of code that's looking forward to a haircut, but see https://github.com/timholy/Images.jl/blob/cb9c0811cef911ff590fd58dc4eab3bc6d17274f/src/core.jl#L127-L202.

On balance, so far I now lean away from the notion from making color types subtypes of FixedVector. Can you live with that?

@SimonDanisch
Copy link

Is that really the only reason you use FixedSizeArrays? I thought there might be some magic GPU reason.

Well the magic gpu reason is that it gives me an interface that I can program against, of which I can be sure that the GPU can handle it. Otherwise I would need to put Any everywhere and do a few checks in every involved function.
What do you mean by "really only"... 350 lines of code duplication with a slightly different interface means quite a lot to me. What I want to achieve is, that the user can be like "This worked for Vec, maybe it works for RGB exactly the same", et voila, it just works... This always yields extraordinary user experience, instead of frustrating people by having slightly different semantics for similar operations.
Also if we start to get more and more into optimizing the code, code duplication means we need to either maintain two high performance code bases, or one party will always be slower than the other.

Reinterpret is nice and all, but you loose type information, which you have to bring back at some point (e.g. when visualizing). I mean its not the worst, but why bother if you can easily just keep it? On top of that, PCA is best implemented with some notion of a FixedSizeVector, so I think it fits well together.

I think "vision about how the whole visualization pipeline should work" is a little too broad to be relevant here.

Definitely not relevant here, but the vision is made up of a lot of small parts which need to work together and i'm interested in how you would like to work with this.

@SimonDanisch
Copy link

Also, if I remember the results of my Images.jl load time benchmarks correctly, these https://github.com/timholy/Images.jl/blob/cb9c0811cef911ff590fd58dc4eab3bc6d17274f/src/colortypes.jl#L225-L577 lines of code where accountable for a big fraction of the load time.
This code duplication is one of my main arguments for using FixedVector for color types. I really don't see how having this in Images is an argument against using fixed vectors!
By the way, LLVM seems really smart about FixedSizeArrays. All the functions defined on them only get compiled one time for types with the same underlying LLVM type.
So quite a lot more efficient codegen, compared to having these functions defined for every single color type.

@SimonDanisch
Copy link

Also, I started using tuples, which at some point will use llvm's vector type, giving us better chances for simd optimizations. Which is a big plus for Images, I suppose.
SimonDanisch/FixedSizeArrays.jl#10
Though, I'm not sure if this is a particular nice view:

immutable RGB{T}
_::NTuple{3, T}
end

When we can overwrite getfield it might be bearable though.
Or there was the discussion of just representing homegenous types as llvm vectors, so we might not be forced to use tuples.

In the meantime I introduced a type called FixedVectorNoTuple for colors. I think I can slowly get rid of it though, since I started handling construction and indexing slightly different, to be more independant of the underlying type.

@timholy
Copy link
Contributor Author

timholy commented Aug 9, 2015

Well the magic gpu reason is that it gives me an interface that I can program against, of which I can be sure that the GPU can handle it. Otherwise I would need to put Any everywhere and do a few checks in every involved function.

You can have the same function defined for Vec and RGB.

This code duplication is one of my main arguments for using FixedVector for color types. I really don't see how having this in Images is an argument against using fixed vectors!

We could have a ColorVectorSpace.jl package for people who want such operations defined on color values. For people who prefer to think about them as "scalars," those operations don't entirely make sense anyway. (See also JuliaLang/julia#8319 (comment), which is 100% correct from a mathematical and colorimetry perspective, but often impractical for operations that many people care about). So a separate package is a good idea.

I could be persuaded that it might be workable to use FixedVectors for the color types. But clearly the priority needs to be FixedArray <: AbstractArray, which I only now realize isn't how it works currently. Until that's done, it seems crazy to make Color <: FixedArray---otherwise you might get yourself into a situation where you'd like to set FixedArray <: AbstractArray but can't because of color-related ambiguities.

FixedArrays are so much closer to AbstractArrays than to Color types, there really shouldn't even be any debate about this. So if you want Color <: FixedArray, let's first see what happens when you make the first transition. Until then, let's keep the color types separate.

Also, if I remember the results of my Images.jl load time benchmarks correctly, these https://github.com/timholy/Images.jl/blob/cb9c0811cef911ff590fd58dc4eab3bc6d17274f/src/colortypes.jl#L225-L577 lines of code where accountable for a big fraction of the load time.

Navigate to the images directory in TestImages.jl, then:

julia> @profile imread("earth_apollo17.jpg")
RGB Images.Image with:                                                                                                                                                                                                                                                         
  data: 3000x3002 Array{Color.RGB{FixedPointNumbers.UfixedBase{UInt8,8}},2}                                                                                                                                                                                                    
  properties:                                                                                                                                                                                                                                                                  
    IMcs: sRGB                                                                                                                                                                                                                                                                 
    spatialorder:  x y                                                                                                                                                                                                                                                         
    pixelspacing:  1 1                                                                                                                                                                                                                                                         

julia> Profile.print()
275 task.jl; anonymous; line: 92                                                                                                                                                                                                                                               
 275 REPL.jl; eval_user_input; line: 63                                                                                                                                                                                                                                        
  275 profile.jl; anonymous; line: 16                                                                                                                                                                                                                                          
   275 /home/tim/.julia/v0.4/Images/src/io.jl; imread; line: 139                                                                                                                                                                                                               
    178 /home/tim/.julia/v0.4/Images/src/io.jl; imread; line: 263                                                                                                                                                                                                              
     178 /home/tim/.julia/v0.4/Images/src/ioformats/libmagickwand.jl; readimage; line: 226                                                                                                                                                                                     
    47  /home/tim/.julia/v0.4/Images/src/io.jl; imread; line: 291                                                                                                                                                                                                              
    50  /home/tim/.julia/v0.4/Images/src/io.jl; imread; line: 322                                                                                                                                                                                                              
     50 /home/tim/.julia/v0.4/Images/src/ioformats/libmagickwand.jl; exportimagepixels!; line: 180

Those two lines are both ccalls to ImageMagick.

By the way, LLVM seems really smart about FixedSizeArrays. All the functions defined on them only get compiled one time for types with the same underlying LLVM type.
So quite a lot more efficient codegen, compared to having these functions defined for every single color type.

The same should apply for any dedicated color type hierarchy that looks a lot like FixedVector. You may have to compile two versions of functions (one for Vec3 and one for ColorVector3), but specific color subtypes should be no different from how you have them now.

@lobingera
Copy link

Hello colleagues,

i have to say, i'm not very deep into the differentiation between Arrays, Vectors, FixedArray etc. so i cannot contribute on this.
I like the up-thread mention of color as scalar value vs. a vector in a color space.
I also see, that there is a color representation as tuple of components (real valued, until further notice) starting at 3 with RGB/HSV but with the introduction of spot colors (maybe from a palette like PANTONEtm) does give us an N-space of components. At the same time there are the machine formats in bits/bytes/words and it's always tempting to deal with them in memory only.
An emphasis should be spend here to support conversion.

If this is done like doing a new packages Colors.jl replacing (all) the available interfaces in Colors.jl and integrate (all) color conversions i fear again the 'Graphics' situation where packages slightly went out of sync, so changes like this should have a roadmap and some process to catch all dependencies.

@SimonDanisch
Copy link

Navigate to the images directory in TestImages.jl, then:

I meant the package load time ;)
Loading only color_types.jl: ~6s (3.5 seconds for loading Color etc)
Loading Images.jl: ~ 12s

The same should apply for any dedicated color type hierarchy that looks a lot like FixedVector.

That's for sure, but that means rewriting the color types to essentially look like what I did in FixedSizeArrays.
My try at refactoring color_types.jl was the primer for me to implement FixedSizeArrays.

@jiahao's comment is definitely noteworthy. How about going with ColorVectorSpace.jl, which relies on Colors and FixedSizeArrays and just overloads the functions that deviate?!
So without it, Colors just uses generic +,*, etc and with it, it uses versions specialized to the color space?

But clearly the priority needs to be FixedArray <: AbstractArray, which I only now realize isn't how it works currently.

Yes, this is really unfortunate. It's sad how hard it is to work on abstract interfaces in Julia. I hope triangular dispatch will make this quite a bit easier.
I think its a fair concern and I can live with the AbstractPaint interface in the meantime.
I would just be very sad to drop FixedSizeArrays for colors entirely, as I'm a big fan of having this rich interface defined for many types. We can try to just implement all the functions in all the packages that use similar types, but that just sounds nightmarish.

I like the up-thread mention of color as scalar value vs. a vector in a color space.

@lobingera Can you explain this a bit more? I'm not really sure, why we should pretend that its a scalar, while we share 90% of the functions with FixedSizeVectors.

@timholy
Copy link
Contributor Author

timholy commented Aug 10, 2015

I meant the package load time ;)
Loading only color_types.jl: ~6s (3.5 seconds for loading Color etc)
Loading Images.jl: ~ 12s

Ah, yes, formerly that was really important, and the main reason I had basically stopped extending Images. It's not an issue now, though:

julia> tic(); using Images; toc()
elapsed time: 0.928678548 seconds
0.928678548

(Obviously, using precompilation. EDIT: That's without have Color already loaded. If you've already said using Color, then it's 0.42 seconds.)

@timholy
Copy link
Contributor Author

timholy commented Aug 10, 2015

I think its a fair concern and I can live with the AbstractPaint interface in the meantime.

OK, that's great! I'll put that effort into ColorTypes.jl so you get to have the more granular organization you want. If your FixedVector gets to the point of being able to serve as the abstract super-type, we can reopen the discussion.

@SimonDanisch
Copy link

Much less of an issue I would say ;) We still shouldn't stress codegen like that.
After all, even with precompilation, this means including images into my packages nearly doubles load time.

@SimonDanisch
Copy link

Great! I'll make sure to help wherever needed.
Thanks a lot for this Tim!

@timholy
Copy link
Contributor Author

timholy commented Aug 10, 2015

We still shouldn't stress codegen like that.

With precompilation, IIUC all those @eval and subtype statements are no longer "there"---they've been executed, and the results (which are straightforward function definitions) are cached.

@SimonDanisch
Copy link

Sure, but compilation takes longer and the cache will be bigger, I suppose.
Anyways, I do agree that it's much closer to 0 now and I think we found a solution for now :)

@lobingera
Copy link

@SimonDanisch
Sometimes you choose color (or access color) just by name, sometimes by an index into a palette, sometimes by a real value in a 1D colorspace (continuos colorpalette e.g. jet in matlab). So the components do not show up (on the interface).

@timothyrenner
Copy link

I don't feel like I have enough understanding to really contribute to the discussion, but @timholy I'd definitely accept the PR once a consensus has been reached.
I'm also be happy to make the switch for ColorBrewer myself to save you a (probably very very small) bit of time if that would make things easier.

@timholy
Copy link
Contributor Author

timholy commented Aug 18, 2015

OK, @SimonDanisch and I have been hard at work, and we have a lot of progress to report. There are three new packages, all hosted at JuliaGraphics:

  • ColorTypes.jl, which holds the basic type definitions and traits. This is the common meeting ground for the colorimetry folks and the GPU folks.
  • Colors.jl, forked and renamed from this package, rebased on ColorTypes, and further modified.
  • ColorVectorSpace.jl, more code ripped out of Images, this provides n-vector operations for RGB colortypes. (This ignores proper colorimetry for the sake of performance. Hence, it's only opt-in.)

I'd like to open the floor for comments on the naming, design, and implementation of those packages. Given the disruptive nature of this change, I should justify why I think it's worth switching:

  • Better names: ColorValue becomes Color. The lovely AbstractAlphaColorValue is called Transparent. These types even come with their own hierarchy diagram.
  • Better support for generic programming: in Images, I constantly had to write for CV in subtypes(...); @eval function foo{T<:Ufixed}(A::AbstractArray{$CV{T}}, ...) to dispatch on a specific color type with a specific element type. In ColorTypes, I worked hard to come up with a flexible and performant (i.e., zero-overhead) traits system that works around our current lack of triangular dispatch. ColorVectorSpace is oh-so-much prettier than its predecessor file colortypes.jl inside of Images.
  • Better testing: before, we used to test whether we could convert from one color space to another. Now, we systematically test that we actually get the right answer 😄. (Not that I discovered any bugs, other than of my own making. Kudos to the folks who wrote that code.)
  • Better performance: optimizations in several conversion functions and algorithms. distinguishable_colors is literally 20x faster than in Color.jl.
  • Extensive documentation: virtually every public function is documented via ?, e.g., ?colormatch.

This was a pretty huge pile of work. I hope folks like it!

One important detail: this will basically cause interoperability-chaos if some packages switch and others do not, or if there are long lags in switching. So first, I want to give folks a couple of days to look the new packages over and make comments; we'll modify these packages accordingly. Once that's done, it's time to transition to using them. If you want to transition your packages yourself, that's great, otherwise I'll submit pull requests for many of them. But, I propose that we hold off merging until an appointed "C-day" (Colors-day) and try to synchronize this transition across packages as well as possible.

@StefanKarpinski
Copy link
Contributor

This is a great plan and a huge amount of work. Thank you both for undertaking it.

One minor suggestion: how about Tint instead of Transparent?

@eschnett
Copy link

I see that HSV has h in the range [0,360]. Is that indeed the case? Isn't this a value in degrees, so the interval should rather be [0,360), i.e. with an open-ended interval? Is this a documentation issue only?

@stevengj
Copy link
Contributor

Transparent is not a noun. Tint in standard English is just a "light color", so it seems unnecessarily obscure to me. Maybe TransparentColor?

@stevengj
Copy link
Contributor

Why aren't ColorAlpha and AlphaColor concrete types ColorAlpha{T<:Color} and AlphaColor{T<:Color}, since it seems like for every XXX there are AXXX and XXXA transparent versions?

@StefanKarpinski
Copy link
Contributor

According to this article, "tint" and "shade" already have technical meanings in color theory, so it's probably best not to use that. TransparentColor seems pretty safe.

@StefanKarpinski
Copy link
Contributor

Are the ranges on things like HSV standard? I find the fact that it's measured in degrees jarring. A unit range or radian would both feel much more natural.

@kmsquire
Copy link
Contributor

+1 for making the apex Color

@timholy
Copy link
Contributor Author

timholy commented Aug 19, 2015

That's enough "yea"s for me, Color it will be. Tomorrow morning 😄.

@shashi
Copy link

shashi commented Aug 19, 2015

The 3 packages keep things extremely neatly layered now. And awesome - Color is finally happening!

Really appreciate the Tour de force!

@dcjones
Copy link
Contributor

dcjones commented Aug 21, 2015

I'm quite happy with this. Nice job Tim and Simon!

I'm not a big fan of Color as the apex type nor the name OpaqueColor, but admittedly for pedantic reasons. RGBA, for example, is a color plus an alpha channel, which is not a color per se. And the correct term to describe what OpaqueColor encompasses currently is "color". The proposed type hierarchy feels slightly like it's shoving the colorimetry (which was the original purpose of this library) in the corner.

My preference would be an apex type called Colorant (Paint was ok too), then rename OpaqueColor to Color.

@StefanKarpinski
Copy link
Contributor

Is "colorant" a somewhat standard term? It is in the dictionary: "a dye, pigment, or other substance that colors something." That seems apt.

@dcjones
Copy link
Contributor

dcjones commented Aug 21, 2015

It's not standard as far as I know. It's hard to find prior art because I don't know of a comparable library; most are thoroughly graphics oriented or thoroughly colorimetry oriented.

@StefanKarpinski
Copy link
Contributor

That's actually a very good thing. I suspect that custom types and external dispatch are quite necessary to satisfy both sets of needs with a single hierarchy. Maybe what is needed is a non-technical term since all the other terms are taken and mean something else.

@lobingera
Copy link

@dcjones

The transparentColor vs. OpaqueColor makes some sense in compositing, as opaque colours replace what is already 'painted' and transparent colours mix with the paint on the canvas.
This differentiation is seen e.g. in the set_source_rgb vs. set_source_rgba calls for cairo.

For plotting i sometimes like to be able to choose between opqaue and (half-)transparent colours. I understand you like to deal in Colors with color perception and currently the discussion (see ColorTypes) is more from how to technically deal with values.

@timholy
Copy link
Contributor Author

timholy commented Aug 22, 2015

@dcjones, I will change those names. I more than half-expected this to be your view of it, and I think getting the names technically correct is a good thing.

I do wish more of the colorimetry experts would chime in early in the game. I'm CCing two other folks, @glenn-sweeney and @m-lohmann. Along with @dcjones, would you please click "watch" on both https://github.com/JuliaGraphics/ColorTypes.jl and https://github.com/JuliaGraphics/Colors.jl, since those are where an increasing amount of the discussion is/will be happening?

@StefanKarpinski
Copy link
Contributor

Despite the reputation that bikeshedding has, getting names right once and for all is very important.

@timholy
Copy link
Contributor Author

timholy commented Aug 22, 2015

Perhaps the most important part of this transition, in fact. (But not the most work; that honor is easily captured by the traits system.)

@AndrewGibb
Copy link

I've been lurking around Julia a while now. I work for BBC R&D and whilst colour isn't my area of expertise, I spend a lot of time discussing all aspects of video with those who are, so perhaps my input would be valuable here.

First, sincere thanks to Tim and Simon for the work. It is the continued enthusiasm by the core Julia developers to do the dirty work which makes it so appealing as a platform.

I would support @dcjones recommendations for the names in the type hierarchy. (I see now this change is already reflected in ColorTypes.jl). Of all those discussed, those names are the clearest to me.

I also support the decisions about separating ColorVectorSpace. The relevant READMEs make it very clear what the different packages are for.

Rec709 (from which sRGB derives its colour primaries) defines a 10 bit representation of colour value, where the interval 0 to 1 maps to 64 to 940. As this is a somewhat specialised use case, perhaps I should add it myself.

One suggestion for an enhancement: Might it be useful to have a guide to adding additional colour space? Obviously Tim has captured many, but I know feature film cameras use different colour spaces, for example. I can't think of any other use cases, however.

@timholy
Copy link
Contributor Author

timholy commented Aug 24, 2015

Thanks for commenting, @AndrewGibb. If you want to add Rec709, the best approach would probably be to add the corresponding number type to FixedPointNumbers.

The idea of adding an extension guide is a good one.

@timholy
Copy link
Contributor Author

timholy commented Aug 24, 2015

@timholy
Copy link
Contributor Author

timholy commented Aug 25, 2015

Done.

@timholy timholy closed this as completed Aug 25, 2015
@SimonDanisch
Copy link

💯

@rennis250
Copy link

I haven't had a chance yet to read through this discussion, but I'm not sure I would put colorant at the apex of the type hierarchy, as pure light sources also produce color percepts, as does pressure on the surface of the eye. Not to mention that some colors are produced without the presence of a physical stimulus (e.g., percepts of blue at the fovea). The current choice seems to put too much weight on the idea that colors are the result of surfaces alone, which is not really the case. Indeed, a colorant alone will not produce a color percept and requires the presence of an emitting light source, the choice of which can have a large influence on the perceived color, as light is essential and color is ultimately a perceptual process, rather than an external physical entity.

@timholy
Copy link
Contributor Author

timholy commented Aug 31, 2015

This has been merged, many packages are now using it, and I am off working on other things. So at this point, anyone who wants further redesign has to do the work him/herself 😄.

@rennis250
Copy link

I have no problem with helping out and implementing changes, in face I am happy to do so. I just wanted to put that out there to see what people think.

Best,
Rob

@timholy
Copy link
Contributor Author

timholy commented Aug 31, 2015

Hard to say without a more concrete sketch of your idea of a redesign---my reaction could range anywhere from "great!" to "more appropriate for a LightPerception package."

But glad to hear that you're willing to help make julia better, as always.

@rennis250
Copy link

Actually, I should have started my post with a huge thank you, rather than being pedantic, especially when I haven't been active in the Julia community for so long. So, my apologies; that was rude of me. I really like the work that has gone into the color packages since I've had a time-out.

I will try to post something within the next days. I've always felt that it is unfortunate that there has been such a heavy split of color terminology over the years in industry, physiology/psychophysics, and phenomenology research. Each of these subfields shares some terminology, but not all, and it can be difficult within psychophysics/physiology, where researchers sometimes introduce new terms for concepts that phenomenologists already labeled and made clear in the past. The huge divide between the science of color and the arts also doesn't help.

Best,
Rob

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests