Skip to content

Commit

Permalink
Redesign color constructors
Browse files Browse the repository at this point in the history
This eliminates the macro-based constructor generation.
Instead, this uses the abstract types to provide the constructor interfaces.
This also allows grays to be used in the constructor argument in more cases.
  • Loading branch information
kimikage committed Mar 10, 2021
1 parent 3507106 commit e4977cf
Show file tree
Hide file tree
Showing 10 changed files with 339 additions and 306 deletions.
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -427,4 +427,4 @@ In most cases, adding a new color space is quite straightforward:

In special cases, there may be other considerations:
- For RGB-related types, 0 means "black" and 1 means "saturated." If your type has unusual numeric interpretation, you may need to add a new number type to [FixedPointNumbers](https://github.com/JeffBezanson/FixedPointNumbers.jl) and set up appropriate `eltype_default` and `eltype_ub` traits.
- If your type has extra fields, check the "Generated code" section of `types.jl` carefully. You may need to define a `colorfields` function and/or call `@make_constructors` or `@make_alpha` manually.
- If your type has extra fields, check the "Generated code" section of `types.jl` carefully. You may need to define a `colorfields` function and/or call `@make_alpha` manually.
19 changes: 2 additions & 17 deletions src/conversions.jl
Original file line number Diff line number Diff line change
Expand Up @@ -99,29 +99,14 @@ _convert(::Type{A}, ::Type{C1}, ::Type{C2}, c, alpha=alpha(c)) where {A<:Transpa
_convert(::Type{Cout}, ::Type{C1}, ::Type{C2}, c) where {Cout<:AbstractRGB,C1<:AbstractRGB,C2<:AbstractGray} = (g = convert(eltype(Cout), gray(c)); Cout(g, g, g))
_convert(::Type{A}, ::Type{C1}, ::Type{C2}, c, alpha=alpha(c)) where {A<:TransparentRGB,C1<:AbstractRGB,C2<:AbstractGray} = (g = convert(eltype(A), gray(c)); A(g, g, g, alpha))

convert(::Type{RGB24}, x::Real) = RGB24(x, x, x)
convert(::Type{ARGB32}, x::Real) = ARGB32(x, x, x)
convert(::Type{ARGB32}, x::Real, alpha) = ARGB32(x, x, x, alpha)
convert(::Type{Gray24}, x::Real) = Gray24(x)
convert(::Type{AGray32}, x::Real) = AGray32(x)
convert(::Type{AGray32}, x::Real, alpha) = AGray32(x, alpha)

convert(::Type{Gray{T}}, x::Real) where {T} = Gray{T}(x)
convert(::Type{AGray{T}}, x::Real) where {T} = AGray{T}(x)
convert(::Type{GrayA{T}}, x::Real) where {T} = GrayA{T}(x)
convert(::Type{C}, x::Number, alpha) where {C<:TransparentColorN{2}} = C(x, alpha)
convert(::Type{C}, x::Number, alpha) where {C<:TransparentRGB} = C(x, x, x, alpha)

convert(::Type{T}, x::Gray ) where {T<:Real} = convert(T, x.val)
convert(::Type{T}, x::Gray24) where {T<:Real} = convert(T, gray(x))
(::Type{T})(x::AbstractGray) where {T<:Real} = T(gray(x))
Base.real(x::AbstractGray) = gray(x)

# Define some constructors that just call convert since the fallback constructor in Base
# is removed in Julia 0.7
# The parametric types are handled in @make_constructors and @make_alpha
for t in (:ARGB32, :Gray24, :RGB24)
@eval $t(x) = convert($t, x)
end

# reinterpret
for T in (RGB24, ARGB32, Gray24, AGray32)
@eval begin
Expand Down
10 changes: 9 additions & 1 deletion src/traits.jl
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,9 @@ without an alpha channel, it will always return 1.
"""
alpha(c::TransparentColor) = c.alpha
alpha(c::Color) = oneunit(eltype(c))
alpha(c::RGB24) = N0f8(1)
alpha(c::ARGB32) = N0f8((c.color & 0xff000000)>>24, 0)
alpha(c::AGray32) = N0f8((c.color & 0xff000000)>>24, 0)
alpha(x::Number) = oneunit(eltype(Gray(x)))

"`red(c)` returns the red component of an `AbstractRGB` opaque or transparent color."
red(c::AbstractRGB ) = c.r
Expand Down Expand Up @@ -122,6 +122,14 @@ to_top(::Type{Colorant{T,N}}) where {T,N} = Colorant{T,N}

to_top(c::Colorant) = to_top(typeof(c))


# Return the number of components in the color
# Note this is different from div(sizeof(c), sizeof(eltype(c))) (e.g., XRGB)
length(::Type{<:ColorantN{N}}) where N = N

length(c::Colorant) = length(typeof(c))


# eltype(RGB{Float32}) -> Float32
eltype(::Type{C}) where {C<:Colorant{T}} where {T} = T

Expand Down
Loading

0 comments on commit e4977cf

Please sign in to comment.