@@ -69,15 +69,6 @@ function ColorTypes._convert(::Type{Cdest}, ::Type{Odest}, ::Type{Osrc}, g) wher
6969 cnvt (Cdest, convert (RGB{eltype (Cdest)}, g))
7070end
7171
72- macro mul3x3 (T, M, c1, c2, c3)
73- esc (quote
74- @inbounds ret = $ T ($ M[1 ,1 ]* $ c1 + $ M[1 ,2 ]* $ c2 + $ M[1 ,3 ]* $ c3,
75- $ M[2 ,1 ]* $ c1 + $ M[2 ,2 ]* $ c2 + $ M[2 ,3 ]* $ c3,
76- $ M[3 ,1 ]* $ c1 + $ M[3 ,2 ]* $ c2 + $ M[3 ,3 ]* $ c3)
77- ret
78- end )
79- end
80-
8172# Everything to RGB
8273# -----------------
8374
@@ -88,7 +79,7 @@ correct_gamut(c::CV) where {CV<:TransparentRGB} =
8879 CV (clamp01 (red (c)), clamp01 (green (c)), clamp01 (blue (c)), clamp01 (alpha (c))) # for `hex`
8980
9081@inline function srgb_compand (v)
91- F = typeof (0.5 * v )
82+ F = typeof (0.5f0 v) === Float32 ? Float32 : promote_type (Float64, typeof (v) )
9283 vf = F (v)
9384 # `pow5_12` is an optimized function to get `v^(1/2.4)`
9485 vf > F (0.0031308 ) ? muladd (F (1.055 ), F (pow5_12 (vf)), F (- 0.055 )) : F (12.92 ) * vf
@@ -168,11 +159,12 @@ function cnvt(::Type{CV}, c::HSI) where {T, CV<:AbstractRGB{T}}
168159 T <: FixedPoint && typemax (T) >= 1 ? CV (r % T, g % T, b % T) : CV (r, g, b)
169160end
170161
162+ # the following matrix is based on the sRGB color primaries in `xy` and D65 whitepoint in `XYZ`
163+ const M_XYZ2RGB = Mat3x3 ([ 3.2404541621141054 - 1.5371385127977166 - 0.4985314095560162
164+ - 0.9692660305051868 1.8760108454466942 0.04155601753034984
165+ 0.05564343095911469 - 0.20402591351675387 1.0572251882231791 ])
171166function xyz_to_linear_rgb (c:: XYZ )
172- r = 3.2404542 * c. x - 1.5371385 * c. y - 0.4985314 * c. z
173- g = - 0.9692660 * c. x + 1.8760108 * c. y + 0.0415560 * c. z
174- b = 0.0556434 * c. x - 0.2040259 * c. y + 1.0572252 * c. z
175- RGB (r, g, b)
167+ @mul3x3 RGB M_XYZ2RGB c. x c. y c. z
176168end
177169function cnvt (:: Type{CV} , c:: XYZ ) where CV<: AbstractRGB
178170 rgb = xyz_to_linear_rgb (c)
@@ -181,13 +173,16 @@ function cnvt(::Type{CV}, c::XYZ) where CV<:AbstractRGB
181173 clamp01 (srgb_compand (rgb. b)))
182174end
183175
176+ const M_YIQ2RGB = Mat3x3 ([1.0 0.9563 0.621
177+ 1.0 - 0.2721 - 0.6474
178+ 1.0 - 1.107 1.7046 ])
184179function cnvt (:: Type{CV} , c:: YIQ ) where CV<: AbstractRGB
185180 cc = correct_gamut (c)
186- CV (clamp01 (cc. y+ 0.9563 * cc. i+ 0.6210 * cc. q),
187- clamp01 (cc. y- 0.2721 * cc. i- 0.6474 * cc. q),
188- clamp01 (cc. y- 1.1070 * cc. i+ 1.7046 * cc. q))
181+ rgb = @mul3x3 RGB M_YIQ2RGB cc. y cc. i cc. q
182+ CV (clamp01 (rgb. r), clamp01 (rgb. g), clamp01 (rgb. b))
189183end
190184
185+ # FIXME
191186function cnvt (:: Type{CV} , c:: YCbCr ) where CV<: AbstractRGB
192187 cc = correct_gamut (c)
193188 ny = cc. y - 16
@@ -285,41 +280,43 @@ cnvt(::Type{HSI{T}}, c::Color) where {T} = cnvt(HSI{T}, convert(RGB{T}, c))
285280# -----------------
286281
287282@inline function invert_srgb_compand (v)
288- F = typeof (0.5 * v )
283+ F = typeof (0.5f0 v) === Float32 ? Float32 : promote_type (Float64, typeof (v) )
289284 vf = F (v)
290285 # `pow12_5` is an optimized function to get `x^2.4`
291286 vf > F (0.04045 ) ? pow12_5 (muladd (F (1000 / 1055 ), vf, F (55 / 1055 ))) : F (100 / 1292 ) * vf
292287end
293288
294289# lookup table for `N0f8` (the extra two elements are for `Float32` splines)
295- const invert_srgb_compand_n0f8 = [invert_srgb_compand (v/ 255.0 ) for v = 0 : 257 ]
290+ const invert_srgb_compand_n0f8 = Float32 [invert_srgb_compand (v/ 255.0 ) for v = 0 : 257 ]
296291
297292function invert_srgb_compand (v:: N0f8 )
298- @inbounds invert_srgb_compand_n0f8[reinterpret (UInt8, v) + 1 ]
293+ @inbounds invert_srgb_compand_n0f8[reinterpret (v) + 1 ]
299294end
300295
301296function invert_srgb_compand (v:: Float32 )
302297 i = unsafe_trunc (Int32, v * 255 )
303- (i < 13 || i > 255 ) && return invert_srgb_compand (Float64 (v))
298+ (i < 13 || i > 255 ) && return Float32 ( invert_srgb_compand (Float64 (v) ))
304299 @inbounds y = view (invert_srgb_compand_n0f8, i: i+ 3 )
305- dv = v * 255.0 - i
306- dv == 0.0 && @inbounds return y[2 ]
300+ dv = v * 255.0f0 - i
301+ dv == 0.0f0 && @inbounds return y[2 ]
307302 if v < 0.38857287f0
308- return @fastmath (y[2 ]+ 0.5 * dv* ((- 2 / 3 * y[1 ]- y[2 ])+ (2 y[3 ]- 1 / 3 * y[4 ])+
309- dv* (( y[1 ]- 2 y[2 ])+ y[3 ]-
310- dv* (( 1 / 3 * y[1 ]- y[2 ])+ ( y[3 ]- 1 / 3 * y[4 ]) ))))
303+ return @fastmath (y[2 ]+ 0.5f0 * dv* ((- 2 / 3f0 * y[1 ]- y[2 ])+ (2 y[3 ]- 1 / 3f0 * y[4 ])+
304+ dv* (( y[1 ]- 2 y[2 ])+ y[3 ]-
305+ dv* (( 1 / 3f0 * y[1 ]- y[2 ])+ ( y[3 ]- 1 / 3f0 * y[4 ]) ))))
311306 else
312- return @fastmath (y[2 ]+ 0.5 * dv* ((4 y[3 ]- 3 y[2 ])- y[4 ]+ dv* ((y[4 ]- y[3 ])+ (y[2 ]- y[3 ]))))
307+ return @fastmath (y[2 ]+ 0.5f0 * dv* ((4 y[3 ]- 3 y[2 ])- y[4 ]+ dv* ((y[4 ]- y[3 ])+ (y[2 ]- y[3 ]))))
313308 end
314309end
315310
311+ # the following matrix is based on the sRGB color primaries in `xy` and D65 whitepoint in `XYZ`
312+ const M_RGB2XYZ = Mat3x3 ([0.4124564390896921 0.357576077643909 0.18043748326639894
313+ 0.21267285140562248 0.715152155287818 0.07217499330655958
314+ 0.019333895582329317 0.119192025881303 0.9503040785363677 ])
316315function cnvt (:: Type{XYZ{T}} , c:: AbstractRGB ) where T
317316 r = invert_srgb_compand (red (c))
318317 g = invert_srgb_compand (green (c))
319318 b = invert_srgb_compand (blue (c))
320- XYZ {T} (0.4124564 * r + 0.3575761 * g + 0.1804375 * b,
321- 0.2126729 * r + 0.7151522 * g + 0.0721750 * b,
322- 0.0193339 * r + 0.1191920 * g + 0.9503041 * b)
319+ return @mul3x3 XYZ{T} M_RGB2XYZ r g b
323320end
324321
325322
@@ -702,18 +699,18 @@ cnvt(::Type{DIN99o{T}}, c::Color) where {T} = cnvt(DIN99o{T}, convert(Lab{T}, c)
702699# -----------------
703700
704701# Chromatic adaptation from CIECAM97s
705- const CAT97s = [ 0.8562 0.3372 - 0.1934
706- - 0.8360 1.8327 0.0033
707- 0.0357 - 0.0469 1.0112 ]
702+ const CAT97s = Mat3x3 ( [ 0.8562 0.3372 - 0.1934
703+ - 0.8360 1.8327 0.0033
704+ 0.0357 - 0.0469 1.0112 ])
708705
709- const CAT97s_INV = inv (CAT97s)
706+ const CAT97s_INV = Mat3x3 ( inv (Float64 .( CAT97s)) )
710707
711708# Chromatic adaptation from CIECAM02
712- const CAT02 = [ 0.7328 0.4296 - 0.1624
713- - 0.7036 1.6975 0.0061
714- 0.0030 0.0136 0.9834 ]
709+ const CAT02 = Mat3x3 ( [ 0.7328 0.4296 - 0.1624
710+ - 0.7036 1.6975 0.0061
711+ 0.0030 0.0136 0.9834 ])
715712
716- const CAT02_INV = inv (CAT02)
713+ const CAT02_INV = Mat3x3 ( inv (Float64 .( CAT02)) )
717714
718715
719716function cnvt (:: Type{LMS{T}} , c:: XYZ ) where T
@@ -727,26 +724,27 @@ cnvt(::Type{LMS{T}}, c::Color) where {T} = cnvt(LMS{T}, convert(XYZ{T}, c))
727724# -----------------
728725
729726correct_gamut (c:: YIQ{T} ) where {T} = YIQ {T} (clamp (c. y, zero (T), one (T)),
730- clamp (c. i, convert (T,- 0.5957 ), convert (T,0.5957 )),
731- clamp (c. q, convert (T,- 0.5226 ), convert (T,0.5226 )))
727+ clamp (c. i, convert (T,- 0.595716 ), convert (T,0.595716 )),
728+ clamp (c. q, convert (T,- 0.522591 ), convert (T,0.522591 )))
732729
730+ const M_RGB2YIQ = Mat3x3 ([0.299 0.587 0.114
731+ 0.595716 - 0.274453 - 0.321263
732+ 0.211456 - 0.522591 0.311135 ])
733733function cnvt (:: Type{YIQ{T}} , c:: AbstractRGB ) where T
734734 rgb = correct_gamut (c)
735- YIQ {T} (0.299 * red (rgb)+ 0.587 * green (rgb)+ 0.114 * blue (rgb),
736- 0.595716 * red (rgb)- 0.274453 * green (rgb)- 0.321263 * blue (rgb),
737- 0.211456 * red (rgb)- 0.522591 * green (rgb)+ 0.311135 * blue (rgb))
735+ @mul3x3 YIQ{T} M_RGB2YIQ red (rgb) green (rgb) blue (rgb)
738736end
739737
740738cnvt (:: Type{YIQ{T}} , c:: Color ) where {T} = cnvt (YIQ{T}, convert (RGB{T}, c))
741739
742740
743741# Everything to YCbCr
744742# -------------------
745-
743+ # FIXME
746744correct_gamut (c:: YCbCr{T} ) where {T} = YCbCr {T} (clamp (c. y, convert (T,16 ), convert (T,235 )),
747745 clamp (c. cb, convert (T,16 ), convert (T,240 )),
748746 clamp (c. cr, convert (T,16 ), convert (T,240 )))
749-
747+ # FIXME
750748function cnvt (:: Type{YCbCr{T}} , c:: AbstractRGB ) where T
751749 rgb = correct_gamut (c)
752750 YCbCr {T} (16 + 65.481 * red (rgb)+ 128.553 * green (rgb)+ 24.966 * blue (rgb),
0 commit comments