Skip to content

Commit 911cfc7

Browse files
committed
Move promotion rules and some typealiases to ColorTypes.jl v0.10
Since gray-->rgb conversions were supported and some rgb-->rgb conversions were fixed in ColorTypes.jl, this commit delegates the conversions to ColorType.jl.
1 parent 7cfe475 commit 911cfc7

File tree

7 files changed

+52
-112
lines changed

7 files changed

+52
-112
lines changed

.travis.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ os:
44
- linux
55
julia:
66
- 1.0
7-
- 1.2
7+
- 1
88
- nightly
99
notifications:
1010
email: false

Project.toml

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
name = "Colors"
22
uuid = "5ae59095-9a9b-59fe-a467-6f913c188581"
3-
version = "0.11.2"
3+
version = "0.12.0"
44

55
[deps]
66
ColorTypes = "3da002f7-5984-5a60-b8a6-cbb66c0b333f"
@@ -9,8 +9,8 @@ InteractiveUtils = "b77e0a4c-d291-57a0-90e8-8db25a27a240"
99
Reexport = "189a3867-3050-52da-a836-e630ba90ab69"
1010

1111
[compat]
12-
ColorTypes = "0.9"
13-
FixedPointNumbers = "0.6, 0.7"
12+
ColorTypes = "0.10"
13+
FixedPointNumbers = "0.6, 0.7, 0.8"
1414
Reexport = "0.2"
1515
julia = "1"
1616

appveyor.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
environment:
22
matrix:
33
- julia_version: 1.0
4-
- julia_version: 1.2
4+
- julia_version: 1
55
- julia_version: latest
66

77
platform:

src/Colors.jl

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -7,9 +7,6 @@ using Reexport
77
Base.@deprecate_binding RGB1 XRGB
88
Base.@deprecate_binding RGB4 RGBX
99

10-
# TODO: why these types are defined here? Can they move to ColorTypes.jl?
11-
AbstractAGray{C<:AbstractGray,T} = AlphaColor{C,T,2}
12-
AbstractGrayA{C<:AbstractGray,T} = ColorAlpha{C,T,2}
1310

1411
import Base: ==, +, -, *, /
1512
import Base: convert, eltype, isless, range, show, typemin, typemax
@@ -29,7 +26,6 @@ include("utilities.jl")
2926

3027
# Include other module components
3128
include("conversions.jl")
32-
include("promotions.jl")
3329
include("algorithms.jl")
3430
include("parse.jl")
3531
include("differences.jl")

src/conversions.jl

Lines changed: 47 additions & 85 deletions
Original file line numberDiff line numberDiff line change
@@ -1,50 +1,52 @@
11
# Conversions
22
# -----------
33

4-
# convert(C, c) might be called as convert(RGB, c) or convert(RGB{Float32}, c)
5-
# This is handled in ColorTypes, which calls functions
6-
# _convert(::Type{Cdest}, ::Type{Odest}, ::Type{Osrc}, c)
7-
# _convert(::Type{Cdest}, ::Type{Odest}, ::Type{Osrc}, c, alpha)
8-
# Here are the argument types:
9-
# - Cdest may be any concrete Color{T,N} type. For parametric Color types
10-
# it _always_ has the desired element type (e.g., Float32), so it's
11-
# safe to dispatch on Cdest{T}.
12-
# - Odest and Osrc are Color subtypes, i.e., things like RGB
13-
# or HSV. They have no element type.
14-
# - c is the Colorant object you wish to convert.
15-
# - alpha, if present, is a user-supplied alpha value (to be used in
16-
# place of any default alpha or alpha present in c).
17-
#
18-
# The motivation for this arrangement is that Julia doesn't (yet) support
19-
# "triangular dispatch", e.g.,
20-
# convert{T,C}(::Type{C{T}}, c)
21-
# The various arguments of _convert therefore "peel off" element types
22-
# (or guarantee them) so that comparisons may be made via
23-
# dispatch. The alternative design is
24-
# for C in parametric_colors
25-
# @eval convert{T}(::Type{$C{T}}, c) = ...
26-
# @eval convert( ::Type{$C}, c) = convert($C{eltype(c)}, c)
27-
# ...
28-
# end
29-
# but this requires a fair amount of codegen (especially for all
30-
# the various alpha variants) and can break if not all C support
31-
# the same eltypes.
32-
#
33-
# Note that ColorTypes handles the cases where Odest == Osrc, or they
34-
# are both subtypes of AbstractRGB. Therefore, here we only have to
35-
# deal with conversions between different spaces.
36-
37-
38-
function ColorTypes._convert(::Type{Cdest}, ::Type{Odest}, ::Type{Osrc}, p, alpha) where {Cdest<:TransparentColor,Odest,Osrc}
4+
#=
5+
`convert(C, c)` might be called as `convert(RGB, c)` or
6+
`convert(RGB{Float32}, c)`.
7+
This is handled in ColorTypes, which calls functions
8+
```
9+
_convert(::Type{Cdest}, ::Type{Odest}, ::Type{Osrc}, c)
10+
_convert(::Type{Cdest}, ::Type{Odest}, ::Type{Osrc}, c, alpha)
11+
```
12+
Here are the argument types:
13+
- `Cdest` may be any concrete `Colorant{T,N}` type. For parametric Color types
14+
it _always_ has the desired element type (e.g., `Float32`), so it's safe to
15+
dispatch on `Cdest <: Colorant{T}`.
16+
- `Odest` and `Osrc` are opaque `Color` subtypes, i.e., things like `RGB` or
17+
`HSV`. They have no element type.
18+
- `c` is the `Colorant` object you wish to convert.
19+
- `alpha`, if present, is a user-supplied alpha value (to be used in place of
20+
any default alpha or alpha present in `c`).
21+
22+
The original motivation for this arrangement was that Julia "did not" support
23+
"triangular dispatch", e.g.,
24+
```
25+
convert(::Type{C{T}}, c) where {C, T}
26+
```
27+
On Julia v0.6 or later, parameter constraints can refer to previous parameters.
28+
Threfore, we can use:
29+
```
30+
convert(::Type{C}, c) where {T, C <: Colorant{T}}
31+
```
32+
However, the example above does not match `convert(RGB, c)`. Also, we should
33+
catch all the various alpha variants (e.g. `ARGB`/`RGBA` with/without element
34+
type).
35+
The various arguments of `_convert` "peel off" element types (or guarantee them)
36+
so that comparisons may be made via dispatch. Therefore, this arrangement is
37+
still helpful.
38+
39+
Note that ColorTypes handles the cases where `Odest == Osrc`, or they are both
40+
subtypes of `AbstractRGB` or `AbstractGray`. Therefore, here we only have to
41+
deal with conversions between different spaces.
42+
=#
43+
44+
function ColorTypes._convert(::Type{Cdest}, ::Type{Odest}, ::Type{Osrc}, p, alpha=alpha(p)) where {Cdest<:TransparentColor,Odest,Osrc}
3945
# Convert the base color
4046
c = cnvt(color_type(Cdest), color(p))
4147
# Append the alpha
4248
ColorTypes._convert(Cdest, Odest, Odest, c, alpha)
4349
end
44-
function ColorTypes._convert(::Type{Cdest}, ::Type{Odest}, ::Type{Osrc}, p) where {Cdest<:TransparentColor,Odest,Osrc}
45-
c = cnvt(color_type(Cdest), color(p))
46-
ColorTypes._convert(Cdest, Odest, Odest, c, alpha(p))
47-
end
4850

4951
ColorTypes._convert(::Type{Cdest}, ::Type{Odest}, ::Type{Osrc}, c) where {Cdest<:Color,Odest,Osrc} = cnvt(Cdest, c)
5052

@@ -188,10 +190,7 @@ cnvt(::Type{CV}, c::LCHab) where {CV<:AbstractRGB} = cnvt(CV, convert(Lab{eltyp
188190
cnvt(::Type{CV}, c::LCHuv) where {CV<:AbstractRGB} = cnvt(CV, convert(Luv{eltype(c)}, c))
189191
cnvt(::Type{CV}, c::Color3) where {CV<:AbstractRGB} = cnvt(CV, convert(XYZ{eltype(c)}, c))
190192

191-
function cnvt(::Type{CV}, c::AbstractGray) where CV<:AbstractRGB
192-
g = convert(eltype(CV), gray(c))
193-
CV(g, g, g)
194-
end
193+
# AbstractGray --> AbstractRGB conversions are implemented in ColorTypes.jl
195194

196195

197196
# Everything to HSV
@@ -735,51 +734,15 @@ end
735734

736735
cnvt(::Type{YCbCr{T}}, c::Color3) where {T} = cnvt(YCbCr{T}, convert(RGB{T}, c))
737736

738-
# Everything to RGB24
739-
# -------------------
740-
741-
convert(::Type{RGB24}, c::RGB24) = c
742-
convert(::Type{RGB24}, c::AbstractRGB{N0f8}) = RGB24(red(c), green(c), blue(c))
743-
function convert(::Type{RGB24}, c::AbstractRGB)
744-
u = (reinterpret(N0f8(red(c))) % UInt32)<<16 +
745-
(reinterpret(N0f8(green(c))) % UInt32)<<8 +
746-
reinterpret(N0f8(blue(c))) % UInt32
747-
reinterpret(RGB24, u)
748-
end
749-
750-
convert(::Type{RGB24}, c::Color) = convert(RGB24, convert(RGB{N0f8}, c))
751-
752-
# To ARGB32
753-
# ----------------
754-
755-
convert(::Type{ARGB32}, c::ARGB32) = c
756-
convert(::Type{ARGB32}, c::TransparentColor{CV}) where {CV<:AbstractRGB{N0f8}} =
757-
ARGB32(red(c), green(c), blue(c), alpha(c))
758-
function convert(::Type{ARGB32}, c::TransparentColor)
759-
u = reinterpret(UInt32, convert(RGB24, c)) | (reinterpret(N0f8(alpha(c)))%UInt32)<<24
760-
reinterpret(ARGB32, u)
761-
end
762-
function convert(::Type{ARGB32}, c::Color)
763-
u = reinterpret(UInt32, convert(RGB24, c)) | 0xff000000
764-
reinterpret(ARGB32, u)
765-
end
766-
function convert(::Type{ARGB32}, c::Color, alpha)
767-
u = reinterpret(UInt32, convert(RGB24, c)) | (reinterpret(N0f8(alpha))%UInt32)<<24
768-
reinterpret(ARGB32, u)
769-
end
770737

771738
# To Gray
772739
# -------
740+
# AbstractGray --> AbstractRGB conversions are implemented in ColorTypes.jl, but
741+
# AbstractRGB --> AbstractGray conversions should be implemented here.
773742

774743
# Rec 601 luma conversion
775-
const unsafe_trunc = Base.unsafe_trunc
776-
777-
convert(::Type{Gray{T}}, x::Gray{T}) where {T} = x
778-
convert(::Type{Gray24}, x::Gray24) = x
779-
780-
convert(::Type{G}, x::AbstractGray) where {G<:AbstractGray} = G(gray(x))
781744

782-
function convert(::Type{G}, x::AbstractRGB{T}) where {G<:AbstractGray,T<:Normed}
745+
function cnvt(::Type{G}, x::AbstractRGB{T}) where {G<:AbstractGray,T<:Normed}
783746
TU, Tf = FixedPointNumbers.rawtype(T), floattype(T)
784747
if sizeof(TU) < sizeof(UInt)
785748
val = Tf(0.001)*(299*reinterpret(red(x)) + 587*reinterpret(green(x)) + 114*reinterpret(blue(x)))
@@ -788,8 +751,7 @@ function convert(::Type{G}, x::AbstractRGB{T}) where {G<:AbstractGray,T<:Normed}
788751
end
789752
return G(reinterpret(T, round(TU, val)))
790753
end
791-
convert(::Type{G}, x::AbstractRGB) where {G<:AbstractGray} =
754+
cnvt(::Type{G}, x::AbstractRGB) where {G<:AbstractGray} =
792755
G(0.299f0*red(x) + 0.587f0*green(x) + 0.114f0*blue(x))
793756

794-
convert(::Type{G}, x::Color) where {G<:AbstractGray} =
795-
convert(G, convert(RGB, x))
757+
cnvt(::Type{G}, x::Color) where {G<:AbstractGray} = convert(G, convert(RGB, x))

src/promotions.jl

Lines changed: 0 additions & 6 deletions
This file was deleted.

test/conversion.jl

Lines changed: 0 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -5,18 +5,6 @@ using ColorTypes: eltype_default, parametric3
55
@testset "Conversion" begin
66
r8(x) = reinterpret(N0f8, x)
77

8-
# Promotions
9-
a, b = promote(RGB(1,0,0), Gray(0.8))
10-
@test isa(a, RGB{Float64}) && isa(b, RGB{Float64})
11-
a, b = promote(RGBA(1,0,0), Gray(0.8))
12-
@test isa(a, RGBA{Float64}) && isa(b, RGBA{Float64})
13-
a, b = promote(RGBA(1,0,0), GrayA(0.8))
14-
@test isa(a, RGBA{Float64}) && isa(b, RGBA{Float64})
15-
a, b = promote(RGB(1,0,0), GrayA(0.8))
16-
@test isa(a, RGBA{Float64}) && isa(b, RGBA{Float64})
17-
a, b = promote(RGB(1,0,0), AGray(0.8))
18-
@test isa(a, ARGB{Float64}) && isa(b, ARGB{Float64})
19-
208
# srgb_compand / invert_srgb_compand
219
@test Colors.srgb_compand(0.5) 0.7353569830524494 atol=eps()
2210
@test Colors.invert_srgb_compand(0.7353569830524494) 0.5 atol=eps()

0 commit comments

Comments
 (0)