@@ -47,14 +47,33 @@ if !hasmethod(one, (Type{TransparentGray},))
47
47
Base. one (p:: Colorant ) = one (typeof (p))
48
48
end
49
49
50
- # Real values are treated like grays
51
- if ! hasmethod (gray, (Number,))
52
- ColorTypes. gray (x:: Real ) = x
50
+ if ! hasmethod (isfinite, (Colorant,))
51
+ isfinite (c:: Colorant ) = mapreducec (isfinite, & , true , c)
52
+ isinf (c:: Colorant ) = mapreducec (isinf, | , false , c)
53
+ isnan (c:: Colorant ) = mapreducec (isnan, | , false , c)
54
+ end
55
+
56
+ if ! isdefined (ColorTypes, :nan )
57
+ nan (:: Type{T} ) where {T<: AbstractFloat } = convert (T, NaN )
58
+ nan (:: Type{C} ) where {T<: AbstractFloat , C<: MathTypes{T} } = mapc (_ -> nan (T), zero (C))
59
+ end
60
+
61
+ if which (real, (Type{<: AbstractGray },)). module === Base
62
+ real (:: Type{C} ) where {C<: AbstractGray } = real (eltype (C))
63
+ end
64
+
65
+ # To help type inference
66
+ promote_rule (:: Type{T} , :: Type{C} ) where {T<: Real ,C<: AbstractGray } = promote_type (T, eltype (C))
67
+
68
+ promote_leaf_eltypes (x:: Union{AbstractArray{T},Tuple{T,Vararg{T}}} ) where {T<: MathTypes } = eltype (T)
69
+
70
+ if isdefined (Statistics, :_mean_promote )
71
+ Statistics. _mean_promote (x:: MathTypes , y:: MathTypes ) = mapc (FixedPointNumbers. Treduce, y)
53
72
end
54
73
55
74
# # Traits and key utilities
56
75
57
- # Return types for arithmetic operations
76
+ # Return eltypes for arithmetic operations
58
77
multype (:: Type{A} , :: Type{B} ) where {A,B} = coltype (typeof (zero (A)* zero (B)))
59
78
sumtype (:: Type{A} , :: Type{B} ) where {A,B} = coltype (typeof (zero (A)+ zero (B)))
60
79
divtype (:: Type{A} , :: Type{B} ) where {A,B} = coltype (typeof (zero (A)/ oneunit (B)))
@@ -99,20 +118,22 @@ _arith_colorant_type(::Type{<:AbstractRGBA}) = RGBA
99
118
parametric (:: Type{C} , :: Type{T} ) where {C,T} = C{T}
100
119
parametric (:: Type{C} , :: Type{T} ) where {T, C<: Colorant{T} } = C # e.g. parametric(RGB24, N0f8) == RGB24
101
120
121
+ rettype (:: typeof (+ ), a:: C , b:: C ) where {C <: Colorant } = C
122
+ rettype (:: typeof (- ), a:: C , b:: C ) where {C <: Colorant } = C
123
+ rettype (:: typeof (+ ), a, b) = parametric (color_rettype (a, b), sumtype (a, b))
124
+ rettype (:: typeof (- ), a, b) = parametric (color_rettype (a, b), sumtype (a, b))
125
+ rettype (:: typeof (* ), a, b) = parametric (color_rettype (a, b), multype (eltype (a), eltype (b))) # gray * gray
126
+ rettype (:: typeof (* ), a:: Real , b) = arith_colorant_type (b){multype (typeof (a), eltype (b))}
127
+ rettype (:: typeof (/ ), a, b:: Real ) = arith_colorant_type (a){divtype (eltype (a), typeof (b))}
128
+ rettype (:: typeof (^ ), a, b) = arith_colorant_type (a){powtype (eltype (a), typeof (b))}
129
+ rettype (:: typeof (^ ), a, b:: Integer ) = arith_colorant_type (a){powtype (eltype (a), Int)}
130
+
102
131
# Useful for leveraging iterator algorithms. Don't use this externally, as the implementation may change.
103
132
channels (c:: AbstractGray ) = (gray (c),)
104
133
channels (c:: TransparentGray ) = (gray (c), alpha (c))
105
134
channels (c:: AbstractRGB ) = (red (c), green (c), blue (c))
106
135
channels (c:: TransparentRGB ) = (red (c), green (c), blue (c), alpha (c))
107
136
108
- nan (:: Type{T} ) where {T<: AbstractFloat } = convert (T, NaN )
109
- nan (:: Type{C} ) where {C<: MathTypes } = _nan (eltype (C), C)
110
- _nan (:: Type{T} , :: Type{C} ) where {T<: AbstractFloat ,C<: AbstractGray } = (x = convert (T, NaN ); C (x))
111
- _nan (:: Type{T} , :: Type{C} ) where {T<: AbstractFloat ,C<: TransparentGray } = (x = convert (T, NaN ); C (x,x))
112
- _nan (:: Type{T} , :: Type{C} ) where {T<: AbstractFloat ,C<: AbstractRGB } = (x = convert (T, NaN ); C (x,x,x))
113
- _nan (:: Type{T} , :: Type{C} ) where {T<: AbstractFloat ,C<: TransparentRGB } = (x = convert (T, NaN ); C (x,x,x,x))
114
-
115
-
116
137
# # Generic algorithms
117
138
Base. add_sum (c1:: MathTypes ,c2:: MathTypes ) = mapc (Base. add_sum, c1, c2)
118
139
Base. reduce_first (:: typeof (Base. add_sum), c:: MathTypes ) = mapc (x-> Base. reduce_first (Base. add_sum, x), c)
@@ -139,47 +160,60 @@ end
139
160
dotc (x:: T , y:: T ) where {T<: Real } = acc (x)* acc (y)
140
161
dotc (x:: Real , y:: Real ) = dotc (promote (x, y)... )
141
162
163
+ """
164
+ y = complement(x)
165
+
166
+ Take the complement `1-x` of `x`. If `x` is a color with an alpha channel,
167
+ the alpha channel is left untouched. Don't forget to add a dot when `x` is
168
+ an array: `complement.(x)`
169
+ """
170
+ complement (x:: Union{Number,Colorant} ) = oneunit (x)- x
171
+ complement (x:: TransparentColor ) = typeof (x)(complement (color (x)), alpha (x))
172
+
142
173
143
174
# # Math on Colors. These implementations encourage inlining and,
144
175
# # for the case of Normed types, nearly halve the number of multiplications (for RGB)
145
176
177
+ # Common
178
+ copy (c:: MathTypes ) = c
179
+ (* )(c:: MathTypes , f:: Real ) = (* )(f, c)
180
+ (+ )(c:: MathTypes ) = mapc (+ , c)
181
+ (+ )(c:: MathTypes{Bool} ) = c
182
+ (- )(c:: MathTypes ) = mapc (- , c)
183
+ (- )(c:: MathTypes{Bool} ) = c
184
+ (/ )(c:: MathTypes , f:: Real ) = (one (f)/ f)* c
185
+ (/ )(c:: MathTypes , f:: Integer ) = (one (eltype (c))/ f)* c
186
+ abs (c:: MathTypes ) = mapc (abs, c)
187
+ norm (c:: MathTypes , p:: Real = 2 ) = (cc = channels (c); norm (cc, p)/ (p == 0 ? length (cc) : length (cc)^ (1 / p)))
188
+
189
+ # # Mixed types
190
+ (+ )(a:: MathTypes , b:: MathTypes ) = (+ )(promote (a, b)... )
191
+ (- )(a:: MathTypes , b:: MathTypes ) = (- )(promote (a, b)... )
192
+
193
+
146
194
# Scalar RGB
147
- copy (c:: AbstractRGB ) = c
148
- (+ )(c:: AbstractRGB ) = mapc (+ , c)
149
- (+ )(c:: TransparentRGB ) = mapc (+ , c)
150
- (- )(c:: AbstractRGB ) = mapc (- , c)
151
- (- )(c:: TransparentRGB ) = mapc (- , c)
152
- (* )(f:: Real , c:: AbstractRGB ) = arith_colorant_type (c){multype (typeof (f),eltype (c))}(f* red (c), f* green (c), f* blue (c))
153
- (* )(f:: Real , c:: TransparentRGB ) = arith_colorant_type (c){multype (typeof (f),eltype (c))}(f* red (c), f* green (c), f* blue (c), f* alpha (c))
195
+ (* )(f:: Real , c:: AbstractRGB ) = rettype (* , f, c)(f* red (c), f* green (c), f* blue (c))
196
+ (* )(f:: Real , c:: TransparentRGB ) = rettype (* , f, c)(f* red (c), f* green (c), f* blue (c), f* alpha (c))
154
197
function (* )(f:: Real , c:: AbstractRGB{T} ) where T<: Normed
155
198
fs = f* (1 / reinterpret (oneunit (T)))
156
- arith_colorant_type (c){ multype ( typeof (f),T)} (fs* reinterpret (red (c)), fs* reinterpret (green (c)), fs* reinterpret (blue (c)))
199
+ rettype ( * , f, c) (fs* reinterpret (red (c)), fs* reinterpret (green (c)), fs* reinterpret (blue (c)))
157
200
end
158
201
function (* )(f:: Normed , c:: AbstractRGB{T} ) where T<: Normed
159
202
fs = reinterpret (f)* (1 / widen (reinterpret (oneunit (T)))^ 2 )
160
- arith_colorant_type (c){ multype ( typeof (f),T)} (fs* reinterpret (red (c)), fs* reinterpret (green (c)), fs* reinterpret (blue (c)))
203
+ rettype ( * , f, c) (fs* reinterpret (red (c)), fs* reinterpret (green (c)), fs* reinterpret (blue (c)))
161
204
end
162
205
function (/ )(c:: AbstractRGB{T} , f:: Real ) where T<: Normed
163
206
fs = (one (f)/ reinterpret (oneunit (T)))/ f
164
- arith_colorant_type (c){ divtype ( typeof (f),T)} (fs* reinterpret (red (c)), fs* reinterpret (green (c)), fs* reinterpret (blue (c)))
207
+ rettype ( / , c, f) (fs* reinterpret (red (c)), fs* reinterpret (green (c)), fs* reinterpret (blue (c)))
165
208
end
166
209
function (/ )(c:: AbstractRGB{T} , f:: Integer ) where T<: Normed
167
210
fs = (1 / reinterpret (oneunit (T)))/ f
168
- arith_colorant_type (c){ divtype ( typeof (f),T)} (fs* reinterpret (red (c)), fs* reinterpret (green (c)), fs* reinterpret (blue (c)))
211
+ rettype ( / , c, f) (fs* reinterpret (red (c)), fs* reinterpret (green (c)), fs* reinterpret (blue (c)))
169
212
end
170
- (+ )(a:: AbstractRGB{S} , b:: AbstractRGB{T} ) where {S,T} = parametric (color_rettype (a, b), sumtype (S,T))(red (a)+ red (b), green (a)+ green (b), blue (a)+ blue (b))
171
- (- )(a:: AbstractRGB{S} , b:: AbstractRGB{T} ) where {S,T} = parametric (color_rettype (a, b), sumtype (S,T))(red (a)- red (b), green (a)- green (b), blue (a)- blue (b))
172
- (+ )(a:: TransparentRGB , b:: TransparentRGB ) =
173
- parametric (color_rettype (a, b), sumtype (a,b))(red (a)+ red (b), green (a)+ green (b), blue (a)+ blue (b), alpha (a)+ alpha (b))
174
- (- )(a:: TransparentRGB , b:: TransparentRGB ) =
175
- parametric (color_rettype (a, b), sumtype (a,b))(red (a)- red (b), green (a)- green (b), blue (a)- blue (b), alpha (a)- alpha (b))
176
- (* )(c:: AbstractRGB , f:: Real ) = (* )(f, c)
177
- (* )(c:: TransparentRGB , f:: Real ) = (* )(f, c)
178
- (/ )(c:: AbstractRGB , f:: Real ) = (one (f)/ f)* c
179
- (/ )(c:: TransparentRGB , f:: Real ) = (one (f)/ f)* c
180
- (/ )(c:: AbstractRGB , f:: Integer ) = (one (eltype (c))/ f)* c
181
- (/ )(c:: TransparentRGB , f:: Integer ) = (one (eltype (c))/ f)* c
182
-
213
+ (+ )(a:: AbstractRGB , b:: AbstractRGB ) = rettype (+ , a, b)(red (a)+ red (b), green (a)+ green (b), blue (a)+ blue (b))
214
+ (- )(a:: AbstractRGB , b:: AbstractRGB ) = rettype (- , a, b)(red (a)- red (b), green (a)- green (b), blue (a)- blue (b))
215
+ (+ )(a:: TransparentRGB , b:: TransparentRGB ) = rettype (+ , a, b)(red (a)+ red (b), green (a)+ green (b), blue (a)+ blue (b), alpha (a)+ alpha (b))
216
+ (- )(a:: TransparentRGB , b:: TransparentRGB ) = rettype (- , a, b)(red (a)- red (b), green (a)- green (b), blue (a)- blue (b), alpha (a)- alpha (b))
183
217
184
218
# New multiplication operators
185
219
(⋅ )(x:: AbstractRGB , y:: AbstractRGB ) = (T = acctype (eltype (x), eltype (y)); T (red (x))* T (red (y)) + T (green (x))* T (green (y)) + T (blue (x))* T (blue (y)))/ 3
@@ -188,24 +222,13 @@ end
188
222
(⊙ )(x:: Union{AbstractRGB,AbstractGray} , y:: Union{AbstractRGB,AbstractGray} ) = ⊙ (promote (x, y)... )
189
223
# ⊗ defined below
190
224
191
- isfinite (c:: Colorant{T} ) where {T<: Normed } = true
192
- isfinite (c:: Colorant ) = mapreducec (isfinite, & , true , c)
193
- isnan (c:: Colorant{T} ) where {T<: Normed } = false
194
- isnan (c:: Colorant ) = mapreducec (isnan, | , false , c)
195
- isinf (c:: Colorant{T} ) where {T<: Normed } = false
196
- isinf (c:: Colorant ) = mapreducec (isinf, | , false , c)
197
- abs (c:: MathTypes ) = mapc (abs, c)
198
- norm (c:: MathTypes , p:: Real = 2 ) = (cc = channels (c); norm (cc, p)/ (p == 0 ? length (cc) : length (cc)^ (1 / p)))
199
-
200
- promote_leaf_eltypes (x:: Union{AbstractArray{T},Tuple{T,Vararg{T}}} ) where {T<: MathTypes } = eltype (T)
201
225
202
226
# These constants come from squaring the conversion to grayscale
203
227
# (rec601 luma), and normalizing
204
228
dotc (x:: T , y:: T ) where {T<: AbstractRGB } = 0.200f0 * acc (red (x))* acc (red (y)) + 0.771f0 * acc (green (x))* acc (green (y)) + 0.029f0 * acc (blue (x))* acc (blue (y))
205
229
dotc (x:: AbstractRGB , y:: AbstractRGB ) = dotc (promote (x, y)... )
206
230
207
231
# Scalar Gray
208
- copy (c:: AbstractGray ) = c
209
232
const unaryOps = (:~ , :conj , :abs ,
210
233
:sin , :cos , :tan , :sinh , :cosh , :tanh ,
211
234
:asin , :acos , :atan , :asinh , :acosh , :atanh ,
@@ -232,43 +255,19 @@ function logabsgamma(c::AbstractGray)
232
255
return Gray (lagc), s
233
256
end
234
257
235
- """
236
- y = complement(x)
237
-
238
- Take the complement `1-x` of `x`. If `x` is a color with an alpha channel,
239
- the alpha channel is left untouched. Don't forget to add a dot when `x` is
240
- an array: `complement.(x)`
241
- """
242
- complement (x:: Union{Number,Colorant} ) = oneunit (x)- x
243
- complement (x:: TransparentColor ) = typeof (x)(complement (color (x)), alpha (x))
244
-
245
258
middle (c:: AbstractGray ) = arith_colorant_type (c)(middle (gray (c)))
246
259
middle (x:: C , y:: C ) where {C<: AbstractGray } = arith_colorant_type (C)(middle (gray (x), gray (y)))
247
260
248
- if isdefined (Statistics, :_mean_promote )
249
- Statistics. _mean_promote (x:: MathTypes , y:: MathTypes ) = mapc (FixedPointNumbers. Treduce, y)
250
- end
251
-
252
- (* )(f:: Real , c:: AbstractGray ) = arith_colorant_type (c){multype (typeof (f),eltype (c))}(f* gray (c))
253
- (* )(f:: Real , c:: TransparentGray ) = arith_colorant_type (c){multype (typeof (f),eltype (c))}(f* gray (c), f* alpha (c))
254
- (* )(c:: AbstractGray , f:: Real ) = (* )(f, c)
255
- (* )(c:: TransparentGray , f:: Real ) = (* )(f, c)
256
- (/ )(c:: AbstractGray , f:: Real ) = (one (f)/ f)* c
261
+ (* )(f:: Real , c:: AbstractGray ) = rettype (* , f, c)(f* gray (c))
262
+ (* )(f:: Real , c:: TransparentGray ) = rettype (* , f, c)(f* gray (c), f* alpha (c))
257
263
(/ )(n:: Number , c:: AbstractGray ) = base_color_type (c)(n/ gray (c))
258
- (/ )(c:: TransparentGray , f:: Real ) = (one (f)/ f)* c
259
- (/ )(c:: AbstractGray , f:: Integer ) = (one (eltype (c))/ f)* c
260
- (/ )(c:: TransparentGray , f:: Integer ) = (one (eltype (c))/ f)* c
261
- (+ )(a:: AbstractGray{S} , b:: AbstractGray{T} ) where {S,T} = parametric (color_rettype (a,b), sumtype (S,T))(gray (a)+ gray (b))
262
- (+ )(a:: TransparentGray , b:: TransparentGray ) = parametric (color_rettype (a,b), sumtype (eltype (a),eltype (b)))(gray (a)+ gray (b),alpha (a)+ alpha (b))
263
- (- )(a:: AbstractGray{S} , b:: AbstractGray{T} ) where {S,T} = parametric (color_rettype (a,b), sumtype (S,T))(gray (a)- gray (b))
264
- (- )(a:: TransparentGray , b:: TransparentGray ) = parametric (color_rettype (a,b), sumtype (eltype (a),eltype (b)))(gray (a)- gray (b),alpha (a)- alpha (b))
265
- (* )(a:: AbstractGray{S} , b:: AbstractGray{T} ) where {S,T} = parametric (color_rettype (a,b), multype (S,T))(gray (a)* gray (b))
266
- (^ )(a:: AbstractGray{S} , b:: Integer ) where {S} = arith_colorant_type (a){powtype (S,Int)}(gray (a)^ convert (Int,b))
267
- (^ )(a:: AbstractGray{S} , b:: Real ) where {S} = arith_colorant_type (a){powtype (S,typeof (b))}(gray (a)^ b)
268
- (+ )(c:: AbstractGray ) = c
269
- (+ )(c:: TransparentGray ) = c
270
- (- )(c:: AbstractGray ) = typeof (c)(- gray (c))
271
- (- )(c:: TransparentGray ) = typeof (c)(- gray (c),- alpha (c))
264
+ (+ )(a:: AbstractGray , b:: AbstractGray ) = rettype (+ , a, b)(gray (a)+ gray (b))
265
+ (+ )(a:: TransparentGray , b:: TransparentGray ) = rettype (+ , a, b)(gray (a)+ gray (b), alpha (a)+ alpha (b))
266
+ (- )(a:: AbstractGray , b:: AbstractGray ) = rettype (- , a, b)(gray (a)- gray (b))
267
+ (- )(a:: TransparentGray , b:: TransparentGray ) = rettype (- , a, b)(gray (a)- gray (b), alpha (a)- alpha (b))
268
+ (* )(a:: AbstractGray , b:: AbstractGray ) = rettype (* , a, b)(gray (a)* gray (b))
269
+ (^ )(a:: AbstractGray , b:: Integer ) = rettype (^ , a, b)(gray (a)^ convert (Int,b))
270
+ (^ )(a:: AbstractGray , b:: Real ) = rettype (^ , a, b)(gray (a)^ b)
272
271
(/ )(a:: C , b:: C ) where C<: AbstractGray = base_color_type (C)(gray (a)/ gray (b))
273
272
(/ )(a:: AbstractGray , b:: AbstractGray ) = / (promote (a, b)... )
274
273
(+ )(a:: AbstractGray , b:: Number ) = base_color_type (a)(gray (a)+ b)
@@ -306,20 +305,10 @@ end
306
305
dotc (x:: T , y:: T ) where {T<: AbstractGray } = acc (gray (x))* acc (gray (y))
307
306
dotc (x:: AbstractGray , y:: AbstractGray ) = dotc (promote (x, y)... )
308
307
309
- # Mixed types
310
- (+ )(a:: MathTypes , b:: MathTypes ) = (+ )(promote (a, b)... )
311
- (- )(a:: MathTypes , b:: MathTypes ) = (- )(promote (a, b)... )
312
-
313
- real (:: Type{C} ) where {C<: AbstractGray } = real (eltype (C))
314
-
315
- # To help type inference
316
- promote_rule (:: Type{T} , :: Type{C} ) where {T<: Real ,C<: AbstractGray } = promote_type (T, eltype (C))
317
-
318
- typemin (:: Type{T} ) where {T<: ColorTypes.AbstractGray } = T (typemin (eltype (T)))
319
- typemax (:: Type{T} ) where {T<: ColorTypes.AbstractGray } = T (typemax (eltype (T)))
320
-
321
- typemin (:: T ) where {T<: ColorTypes.AbstractGray } = T (typemin (eltype (T)))
322
- typemax (:: T ) where {T<: ColorTypes.AbstractGray } = T (typemax (eltype (T)))
308
+ typemin (:: Type{C} ) where {C<: AbstractGray } = C (typemin (eltype (C)))
309
+ typemax (:: Type{C} ) where {C<: AbstractGray } = C (typemax (eltype (C)))
310
+ typemin (c:: AbstractGray ) = typemin (typeof (c))
311
+ typemax (c:: AbstractGray ) = typemax (typeof (c))
323
312
324
313
# # RGB tensor products
325
314
0 commit comments