Skip to content

Commit

Permalink
Support arithmetic on Gray. Fixes #178
Browse files Browse the repository at this point in the history
  • Loading branch information
timholy committed Sep 8, 2014
1 parent 24856b3 commit f556bdd
Show file tree
Hide file tree
Showing 2 changed files with 89 additions and 3 deletions.
53 changes: 50 additions & 3 deletions src/colortypes.jl
Original file line number Diff line number Diff line change
Expand Up @@ -274,6 +274,53 @@ for CV in subtypes(AbstractRGB)
abs{T<:Ufixed}(c::$CV{T}) = float32(c.r)+float32(c.g)+float32(c.b) # should this have a different name?
end
end
# Math on Gray
for CV in subtypes(AbstractGray)
@eval begin
(*){R<:Real,T}(f::R, c::$CV{T}) = $CV{multype(R,T)}(f*c.val)
(*)(c::$CV, f::Real) = (*)(f, c)
(.*)(f::Real, c::$CV) = (*)(f, c)
(.*)(c::$CV, f::Real) = (*)(f, c)
(/)(c::$CV, f::Real) = (one(f)/f)*c
(/)(c::$CV, f::Integer) = (one(eltype(c))/f)*c
(./)(c::$CV, f::Real) = (/)(c, f)
(+){S,T}(a::$CV{S}, b::$CV{T}) = $CV{sumtype(S,T)}(a.val+b.val)
(-){S,T}(a::$CV{S}, b::$CV{T}) = $CV{sumtype(S,T)}(a.val-b.val)
(+)(A::AbstractArray{$CV}, b::AbstractGray) = (.+)(A, b)
(-)(A::AbstractArray{$CV}, b::AbstractGray) = (.-)(A, b)
(+)(b::AbstractGray, A::AbstractArray{$CV}) = (.+)(b, A)
(-)(b::AbstractGray, A::AbstractArray{$CV}) = (.-)(b, A)
function (.+){T}(A::AbstractArray{$CV{T}}, b::AbstractGray)
bT = convert($CV{T}, b)
out = similar(A)
add!(out, A, bT)
end
(.+){T}(b::AbstractGray, A::AbstractArray{$CV{T}}) = (.+)(A, b)
function (.-){T}(A::AbstractArray{$CV{T}}, b::AbstractGray)
bT = convert($CV{T}, b)
out = similar(A)
sub!(out, A, bT)
end
function (.-){T}(A::AbstractArray{$CV{T}}, b::AbstractGray)
bT = convert($CV{T}, b)
out = similar(A)
sub!(out, A, bT)
end
function (.-){T}(b::AbstractGray, A::AbstractArray{$CV{T}})
bT = convert($CV{T}, b)
out = similar(A)
sub!(out, bT, A)
end
isfinite{T<:Ufixed}(c::$CV{T}) = true
isfinite{T<:FloatingPoint}(c::$CV{T}) = isfinite(c.val)
isnan{T<:Ufixed}(c::$CV{T}) = false
isnan{T<:FloatingPoint}(c::$CV{T}) = isnan(c.val)
isinf{T<:Ufixed}(c::$CV{T}) = false
isinf{T<:FloatingPoint}(c::$CV{T}) = isinf(c.val)
abs(c::$CV) = abs(c.val) # should this have a different name?
abs{T<:Ufixed}(c::$CV{T}) = float32(c.val) # should this have a different name?
end
end

@ngenerate N typeof(out) function add!{T,N}(out, A::AbstractArray{T,N}, b::T)
@inbounds begin
Expand All @@ -284,15 +331,15 @@ end
out
end
# need a separate sub! because of unsigned types
@ngenerate N typeof(out) function sub!{T,N}(out, A::AbstractArray{T,N}, b::AbstractRGB)
@ngenerate N typeof(out) function sub!{T,N}(out, A::AbstractArray{T,N}, b::Union(AbstractRGB, AbstractGray))
@inbounds begin
@nloops N i A begin
@nref(N, out, i) = @nref(N, A, i) - b
end
end
out
end
@ngenerate N typeof(out) function sub!{T,N}(out, b::AbstractRGB, A::AbstractArray{T,N})
@ngenerate N typeof(out) function sub!{T,N}(out, b::Union(AbstractRGB, AbstractGray), A::AbstractArray{T,N})
@inbounds begin
@nloops N i A begin
@nref(N, out, i) = b - @nref(N, A, i)
Expand All @@ -302,7 +349,7 @@ end
end

# To help type inference
for ACV in (ColorValue, AbstractRGB)
for ACV in (ColorValue, AbstractRGB, AbstractGray)
for CV in subtypes(ACV)
(length(CV.parameters) == 1 && !(CV.abstract)) || continue
@eval promote_array_type{T<:Real,S<:Real}(::Type{T}, ::Type{$CV{S}}) = $CV{promote_type(T, S)}
Expand Down
39 changes: 39 additions & 0 deletions test/colortypes.jl
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import Images, Images.ColorTypes
using Base.Test, Color, FixedPointNumbers
import Images.Gray

@test length(RGB) == 3
@test length(ColorTypes.BGR) == 3
Expand All @@ -17,6 +18,44 @@ using Base.Test, Color, FixedPointNumbers
c = ColorTypes.AlphaColor(RGB{Ufixed8}(0.8,0.2,0.4), Ufixed8(0.5))
@test length(c) == 4

# Arithmetic with Gray
cf = Gray{Float32}(0.1)
ccmp = Gray{Float32}(0.2)
@test 2*cf == ccmp
@test cf*2 == ccmp
@test ccmp/2 == cf
@test 2.0f0*cf == ccmp
@test eltype(2.0*cf) == Float64
cu = Gray{Ufixed8}(0.1)
@test 2*cu == Gray(2*cu.val)
@test 2.0f0*cu == Gray(2.0f0*cu.val)
f = Ufixed8(0.5)
@test_approx_eq (f*cu).val f*cu.val
@test 2.*cf == ccmp
@test cf.*2 == ccmp
@test cf/2.0f0 == Gray{Float32}(0.05)
@test cu/2 == Gray(cu.val/2)
@test cu/0.5f0 == Gray(cu.val/0.5f0)
@test cf+cf == ccmp
@test isfinite(cf)
@test !isinf(cf)
@test !isnan(cf)
@test isfinite(Gray(NaN)) == false
@test isinf(Gray(NaN)) == false
@test isnan(Gray(NaN)) == true
@test isfinite(Gray(Inf)) == false
@test isinf(Gray(Inf)) == true
@test isnan(Gray(Inf)) == false
@test_approx_eq abs(Gray(0.1)) 0.1

acu = Gray{Ufixed8}[cu]
acf = Gray{Float32}[cf]
@test typeof(acu+acf) == Vector{Gray{Float32}}
@test typeof(2*acf) == Vector{Gray{Float32}}
@test typeof(uint8(2)*acu) == Vector{Gray{Float32}}
@test typeof(acu/2) == Vector{Gray{typeof(Ufixed8(0.5)/2)}}

# Arithemtic with RGB
cf = RGB{Float32}(0.1,0.2,0.3)
ccmp = RGB{Float32}(0.2,0.4,0.6)
@test 2*cf == ccmp
Expand Down

0 comments on commit f556bdd

Please sign in to comment.