JuliaGraphics / ColorTypes.jl

Basic color definitions and traits
Other
78 stars 36 forks source link

Add type aliases for RGB{N0f8} and RGBA{N0f8} #218

Closed jlumpe closed 5 months ago

jlumpe commented 3 years ago

RGB{N0f8} (along with RGBA{N0f8}) is probably the color format programmers are most used to working with, but the name is pretty obscure-looking if you're not yet familiar with FixedPointNumbers. I think it would be useful to define and export type aliases for the two of these.

kimikage commented 3 years ago

I think having the aliases is a good idea in itself.

However, I worry that the using aliases will further confuse users who are not familiar with FixedPointNumbers. If you just want to load, view and save images, you don't have to care about the element type, but if you try to do any specific image processing, you will almost certainly face the N0f8. Additionally it might show up as Normed{UInt8, 8}. :dizzy_face:

Another problem is that there may not be good aliases for them. The RGB24 and ARGB32 are already in use as 32-bit types, and they are equivalent to BGRX{N0f8}/BGRA{N0f8} on little-endian machines, despite the names. If we really want to create the aliases, I would recommend RGB888/RGBA8888, but it is meaningful only in the context of contrast with RGB565 etc. In terms of analogy with RGB{Float32}, RGB888 will confuse the novice even more. :sweat_smile:

johnnychen94 commented 3 years ago

We definitely need a better tutorial on the colorant and number types in juliaimages.org 😆

timholy commented 3 years ago

In VSCode's terminal, if you hover over the text "N0f8" and ctrl-click, it pastes it into a textbox and appears to try to open it as if it were a file or link. Might be nice to have a way to get it to display some help instead.

jlumpe commented 3 years ago

I've just been getting familiar with this package and Colors.jl over the last couple of days, but my impression has been that it has a very nice design from a theoretical point of view but is somewhat lacking when it comes to the practical aspects... Like FixedPointNumbers.N0f8 is definitely the correct theoretical treatment of how an 8-bit color channel actually works, but if I just want to work with the large number of external image or plotting libraries that weren't designed around this package I'm going to need to convert colors to/from Vector{UInt8}s at some point and it's not very obvious how to do things like that.

timholy commented 3 years ago

Most of those mechanisms are in ImageCore. See https://juliaimages.org/latest/tutorials/conversions_views/.

kimikage commented 3 years ago

I believe that excessive overloading of Base.convert should be avoided from the point of view of preventing accidental operation, but it may be possible to provide error hints.

julia> convert(Vector{UInt8}, RGB{N0f8}(1,0,0))
ERROR: MethodError: Cannot `convert` an object of type RGB{Normed{UInt8,8}} to an object of type Array{UInt8,1}

julia> convert(UInt32, RGB{N0f8}(1,0,0))
ERROR: MethodError: Cannot `convert` an object of type RGB{Normed{UInt8,8}} to an object of type UInt32

julia> convert(UInt32, RGB24(1,0,0))
ERROR: MethodError: Cannot `convert` an object of type RGB24 to an object of type UInt32
julia> convert(RGB{N0f8}, [0x12, 0x34, 0x56])
ERROR: MethodError: Cannot `convert` an object of type Array{UInt8,1} to an object of type RGB{Normed{UInt8,8}}

julia> convert(RGB{N0f8}, 0x123456) # In this case, it's slightly kinder
ERROR: ArgumentError: Normed{UInt8,8} is an 8-bit type representing 256 values from 0.0 to 1.0; cannot represent 1193046

julia> convert(RGB24, 0x123456) # In this case, it's even kinder
ERROR: ArgumentError: RGB24 cannot be constructed or converted directly from a UInt32 input as a bit pattern.
  Use `reinterpret(RGB24, 0x00123456)` instead.

The problem is that when users face these errors, they don't know which documentation in which package to read. With the increased interactivity of Julia's coding environment, I think it's not only the quality of the documentation, but also the reachability of the documentation that is important.

In any case, this is a separate issue from adding aliases.