1
1
# Conversions
2
2
# -----------
3
3
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}
39
45
# Convert the base color
40
46
c = cnvt (color_type (Cdest), color (p))
41
47
# Append the alpha
42
48
ColorTypes. _convert (Cdest, Odest, Odest, c, alpha)
43
49
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
48
50
49
51
ColorTypes. _convert (:: Type{Cdest} , :: Type{Odest} , :: Type{Osrc} , c) where {Cdest<: Color ,Odest,Osrc} = cnvt (Cdest, c)
50
52
@@ -188,10 +190,7 @@ cnvt(::Type{CV}, c::LCHab) where {CV<:AbstractRGB} = cnvt(CV, convert(Lab{eltyp
188
190
cnvt (:: Type{CV} , c:: LCHuv ) where {CV<: AbstractRGB } = cnvt (CV, convert (Luv{eltype (c)}, c))
189
191
cnvt (:: Type{CV} , c:: Color3 ) where {CV<: AbstractRGB } = cnvt (CV, convert (XYZ{eltype (c)}, c))
190
192
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
195
194
196
195
197
196
# Everything to HSV
@@ -735,51 +734,15 @@ end
735
734
736
735
cnvt (:: Type{YCbCr{T}} , c:: Color3 ) where {T} = cnvt (YCbCr{T}, convert (RGB{T}, c))
737
736
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
770
737
771
738
# To Gray
772
739
# -------
740
+ # AbstractGray --> AbstractRGB conversions are implemented in ColorTypes.jl, but
741
+ # AbstractRGB --> AbstractGray conversions should be implemented here.
773
742
774
743
# 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))
781
744
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 }
783
746
TU, Tf = FixedPointNumbers. rawtype (T), floattype (T)
784
747
if sizeof (TU) < sizeof (UInt)
785
748
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}
788
751
end
789
752
return G (reinterpret (T, round (TU, val)))
790
753
end
791
- convert (:: Type{G} , x:: AbstractRGB ) where {G<: AbstractGray } =
754
+ cnvt (:: Type{G} , x:: AbstractRGB ) where {G<: AbstractGray } =
792
755
G (0.299f0 * red (x) + 0.587f0 * green (x) + 0.114f0 * blue (x))
793
756
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))
0 commit comments