Skip to content

Commit

Permalink
WIP
Browse files Browse the repository at this point in the history
  • Loading branch information
timholy committed Dec 12, 2017
1 parent 73e745a commit e7b3e00
Show file tree
Hide file tree
Showing 14 changed files with 185 additions and 221 deletions.
6 changes: 1 addition & 5 deletions src/ImageCore.jl
Original file line number Diff line number Diff line change
Expand Up @@ -14,11 +14,7 @@ import Graphics: width, height

# TODO: just use .+
# See https://github.com/JuliaLang/julia/pull/22932#issuecomment-330711997
if VERSION < v"0.7.0-DEV.1759"
plus(r::AbstractUnitRange, i::Integer) = r + i
else
plus(r::AbstractUnitRange, i::Integer) = broadcast(+, r, i)
end
plus(r::AbstractUnitRange, i::Integer) = broadcast(+, r, i)
plus(a::AbstractArray, i::Integer) = a .+ i

AbstractGray{T} = Color{T,1}
Expand Down
66 changes: 53 additions & 13 deletions src/colorchannels.jl
Original file line number Diff line number Diff line change
@@ -1,3 +1,48 @@
# Create a special type for permutations. The real point here is to be able to
# unambiguously identify an RRPermArray (see below) so that we may "unwrap" in
# expressions like `channelview(colorview(C, A))`.

"""
ColorChanPerm(perm)
Construct a reordering permutation for the color channel.
This handles swaps between memory layout and constructor argument order for `AbstractRGB` and
various `AlphaChannel` and `ChannelAlpha` color types.
"""
struct ColorChanPerm{N} <: AbstractVector{Int}
perm::NTuple{N,Int}
end
Base.IndexStyle(::Type{<:ColorChanPerm}) = IndexLinear()
Base.size(v::ColorChanPerm{N}) where N = (N,)
Base.getindex(v::ColorChanPerm, i::Int) = v.perm[i]

dimorder(::Type{<:RGB}) = ColorChanPerm((1, 2, 3))
dimorder(::Type{<:BGR}) = ColorChanPerm((3, 2, 1))
dimorder(::Type{<:RGB1}) = ColorChanPerm((1, 1, 2, 3))
dimorder(::Type{<:RGB4}) = ColorChanPerm((1, 2, 3, 3)) # this causes problems for setindex!, fixed below
dimorder(::Type{<:BGRA}) = ColorChanPerm((3, 2, 1, 4))
dimorder(::Type{<:ABGR}) = ColorChanPerm((4, 3, 2, 1))
dimorder(::Type{<:AlphaColor{<:Color1,T,N}}) where {T,N} = ColorChanPerm((2, 1))
dimorder(::Type{<:AlphaColor{<:Color3,T,N}}) where {T,N} = ColorChanPerm((4, 1, 2, 3))

const ColorChanPermIndexType{NC} = Tuple{<:ColorChanPerm,Vararg{<:Base.Slice,NC}}
const ColorChanPermSubArray{T,N,P,I<:ColorChanPermIndexType,L} =
SubArray{T,N,P,I,L}
const RRPermArray{To,From,N,M,P<:ColorChanPermSubArray} =
RRArray{To,From,N,M,P}

# This type exists solely to set multiple values in the color channel axis
struct NVector{T,N} <: AbstractVector{T}
v::NTuple{N,T}
end
Base.IndexStyle(::Type{<:NVector}) = IndexLinear()
Base.size(v::NVector{T,N}) where {T,N} = (N,)
Base.getindex(v::NVector, i::Int) = v.v[i]
NVector(x::Vararg{T,N}) where {T,N} = NVector{T,N}(x)

@inline Base.setindex!(A::RRPermArray{<:RGB4,<:Number,N}, val::AbstractRGB, i::Vararg{Int,N}) where N =
setindex!(parent(parent(parent(A))), NVector(red(val), green(val), blue(val)), :, i...)

"""
channelview(A)
Expand All @@ -14,6 +59,7 @@ img = rand(RGB{N0f8}, 10, 10)
A = channelview(img) # a 3×10×10 array
"""
channelview(A::AbstractArray{T}) where {T<:Number} = A
channelview(A::RRPermArray{<:Colorant,<:Number}) = parent(parent(parent(A)))
channelview(A::RRArray{<:Colorant,<:Number}) = parent(parent(A))
channelview(A::Base.ReinterpretArray{<:AbstractGray,M,<:Number}) where M = parent(A)
channelview(A::AbstractArray{RGB{T}}) where {T} = reinterpretc(T, A)
Expand Down Expand Up @@ -53,6 +99,8 @@ img = colorview(RGB, A)
"""
colorview(::Type{C}, A::AbstractArray{T}) where {C<:Colorant,T<:Number} =
_ccolorview(ccolor_number(C, T), A)
_ccolorview(::Type{C}, A::RRPermArray{T,C}) where {C<:Colorant,T<:Number} =
parent(parent(parent(A)))
_ccolorview(::Type{C}, A::RRArray{T,C}) where {C<:Colorant,T<:Number} =
parent(parent(A))
_ccolorview(::Type{C}, A::Base.ReinterpretArray{T,M,C}) where {C<:AbstractGray,T<:Number,M} =
Expand All @@ -61,17 +109,17 @@ _ccolorview(::Type{C}, A::AbstractArray{T}) where {C<:Colorant,T<:Number} =
__ccolorview(C, A) # necessary to avoid ambiguities from dispatch on eltype
__ccolorview(::Type{C}, A::AbstractArray{T}) where {T<:Number,C<:RGB{T}} = reinterpretc(C, A)
__ccolorview(::Type{C}, A::AbstractArray{T}) where {T<:Number,C<:AbstractRGB} =
reinterpret(C, view(A, dimorder(C), Base.tail(colons(A))...))
reinterpretc(C, view(A, dimorder(C), Base.tail(colons(A))...))
__ccolorview(::Type{C}, A::AbstractArray{T}) where {T<:Number,C<:Color{T}} = reinterpretc(C, A)
__ccolorview(::Type{C}, A::AbstractArray{T}) where {T<:Number,C<:ColorAlpha} =
_colorviewalpha(base_color_type(C), C, eltype(C), A)
__ccolorview(::Type{C}, A::AbstractArray{T}) where {T<:Number,C<:AlphaColor} =
reinterpretc(C, view(A, dimorder(C), Base.tail(colons(A))...))
_colorviewalpha(::Type{C}, ::Type{CA}, ::Type{T}, A::Array{T}) where {C<:RGB,CA,T} =
_colorviewalpha(::Type{C}, ::Type{CA}, ::Type{T}, A::AbstractArray{T}) where {C<:RGB,CA,T} =
reinterpretc(CA, A)
_colorviewalpha(::Type{C}, ::Type{CA}, ::Type, A::Array) where {C<:AbstractRGB,CA} =
reinterpretc(C, view(A, dimorder(C), Base.tail(colons(A))...))
_colorviewalpha(::Type{C}, ::Type{CA}, ::Type{T}, A::Array{T}) where {C<:Color,CA,T} =
_colorviewalpha(::Type{C}, ::Type{CA}, ::Type{T}, A::AbstractArray{T}) where {C<:AbstractRGB,CA,T} =
reinterpretc(CA, view(A, dimorder(CA), Base.tail(colons(A))...))
_colorviewalpha(::Type{C}, ::Type{CA}, ::Type{T}, A::AbstractArray{T}) where {C<:Color,CA,T} =
reinterpretc(CA, A)

colorview(::Type{ARGB32}, A::AbstractArray{BGRA{N0f8}}) = reinterpret(ARGB32, A)
Expand All @@ -80,14 +128,6 @@ colorview(::Type{C1}, A::AbstractArray{C2}) where {C1<:Colorant,C2<:Colorant} =
colorview(C1, channelview(A))

colons(A::AbstractArray{T,N}) where {T,N} = ntuple(d->Colon(), Val(N))
dimorder(::Type{<:RGB}) = 1:3
dimorder(::Type{<:BGR}) = 3:-1:1
dimorder(::Type{<:RGB1}) = 2:4
dimorder(::Type{<:RGB4}) = 1:3
dimorder(::Type{<:BGRA}) = [3,2,1,4]
dimorder(::Type{<:ABGR}) = 4:-1:1
dimorder(::Type{<:AlphaColor{<:Color3,T,N}}) where {T,N} = [2,3,4,1]
dimorder(::Type{<:AlphaColor{<:Color1,T,N}}) where {T,N} = 2:-1:1

"""
colorview(C, gray1, gray2, ...) -> imgC
Expand Down
44 changes: 24 additions & 20 deletions src/convert_reinterpret.jl
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,8 @@ function reinterpretc(::Type{T}, a::AbstractArray{CV}) where {T<:Number,CV<:Colo
return reinterpret(T, a)
end
if sizeof(CV) == sizeof(T)*_len(CV)
return reshape(reinterpret(T, a), (_len(CV), size(a)...))
inds = indices(a)
return reshape(reinterpret(T, a), (convert(typeof(inds[1]), Base.OneTo(_len(CV))), inds...))
end
throw(ArgumentError("result shape not specified"))
end
Expand All @@ -50,14 +51,17 @@ function reinterpretc(::Type{CV}, a::AbstractArray{T,1}) where {CV<:Colorant,T<:
reshape(reinterpret(CVT, a), (l,))
end
function reinterpretc(::Type{CV}, a::AbstractArray{T}) where {CV<:Colorant,T<:Number}
@noinline throwdm(::Type{C}, ind1) where C =
throw(DimensionMismatch("indices $ind1 are not consistent with color type $C"))
CVT = ccolor_number(CV, T)
if samesize(CVT, T)
return reinterpret(CVT, a)
end
if size(a, 1)*sizeof(T) == sizeof(CVT)
return reshape(reinterpret(CVT, a), tail(size(a)))
inds = indices(a)
if inds[1] == Base.OneTo(sizeof(CVT) ÷ sizeof(eltype(CVT)))
return reshape(reinterpret(CVT, a), tail(inds))
end
throw(ArgumentError("result shape not specified"))
throwdm(CV, inds[1])
end

# ccolor_number converts form 2 calls to form 1 calls
Expand All @@ -66,19 +70,19 @@ ccolor_number(::Type{CV}, ::Type{T}) where {CV<:Colorant,T<:Number} =
ccolor_number(::Type{CV}, ::Type{CVT}, ::Type{T}) where {CV,CVT<:Number,T} = CV # form 1
ccolor_number(::Type{CV}, ::Type{Any}, ::Type{T}) where {CV<:Colorant,T} = CV{T} # form 2

function Base.IndexStyle(::Type{Base.ReinterpretArray{T,N,S,A}}) where {T<:Number,N,S<:AbstractGray,A}
if samesize(T, S)
return IndexStyle(A)
end
IndexCartesian()
end
# function Base.IndexStyle(::Type{Base.ReinterpretArray{T,N,S,A}}) where {T<:Number,N,S<:AbstractGray,A}
# if samesize(T, S)
# return IndexStyle(A)
# end
# IndexCartesian()
# end

function Base.IndexStyle(::Type{Base.ReinterpretArray{T,N,S,A}}) where {T<:AbstractGray,N,S<:Number,A}
if samesize(T, S)
return IndexStyle(A)
end
IndexCartesian()
end
# function Base.IndexStyle(::Type{Base.ReinterpretArray{T,N,S,A}}) where {T<:AbstractGray,N,S<:Number,A}
# if samesize(T, S)
# return IndexStyle(A)
# end
# IndexCartesian()
# end

### convert
#
Expand All @@ -99,7 +103,7 @@ end

function Base.convert(::Type{Array{Cdest,n}},
img::AbstractArray{Csrc,n}) where {Cdest<:Colorant,n,Csrc<:Colorant}
copy!(Array{ccolor(Cdest, Csrc)}(size(img)), img)
copy!(Array{ccolor(Cdest, Csrc)}(uninitialized, size(img)), img)
end

function Base.convert(::Type{Array{Cdest}},
Expand All @@ -114,12 +118,12 @@ end

function Base.convert(::Type{Array{Cdest,n}},
img::BitArray{n}) where {Cdest<:Color1,n}
copy!(Array{ccolor(Cdest, Gray{Bool})}(size(img)), img)
copy!(Array{ccolor(Cdest, Gray{Bool})}(uninitialized, size(img)), img)
end

function Base.convert(::Type{Array{Cdest,n}},
img::AbstractArray{T,n}) where {Cdest<:Color1,n,T<:Real}
copy!(Array{ccolor(Cdest, Gray{T})}(size(img)), img)
copy!(Array{ccolor(Cdest, Gray{T})}(uninitialized, size(img)), img)
end

# for docstrings in the operations below
Expand All @@ -140,7 +144,7 @@ for (fn,T) in (#(:float16, Float16), # Float16 currently has promotion problem
($fn)(::Type{S}) where {S<:Number } = $T
($fn)(c::Colorant) = convert(($fn)(typeof(c)), c)
($fn)(n::Number) = convert(($fn)(typeof(n)), n)
@deprecate ($fn){C<:Colorant}(A::AbstractArray{C}) ($fn).(A)
@deprecate ($fn)(A::AbstractArray{C}) where {C<:Colorant} ($fn).(A)
fname = $(Expr(:quote, fn))
Tname = shortname($T)
@doc """
Expand Down
5 changes: 5 additions & 0 deletions src/deprecations.jl
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
Base.@deprecate_binding ChannelView channelview

export ColorView

struct ColorView{C<:Colorant,N,A<:AbstractArray} <: AbstractArray{C,N}
parent::A

Expand All @@ -11,7 +13,10 @@ struct ColorView{C<:Colorant,N,A<:AbstractArray} <: AbstractArray{C,N}
colorview(C, A)
end
end

function ColorView{C}(A::AbstractArray) where C<:Colorant
Base.depwarn("ColorView{C}(A) is deprecated, use colorview(C, A)", :ColorView)
colorview(C, A)
end

ColorView(parent::AbstractArray) = error("must specify the colortype, use colorview(C, A)")
103 changes: 15 additions & 88 deletions src/show.jl
Original file line number Diff line number Diff line change
@@ -1,16 +1,6 @@
if VERSION < v"0.7.0-DEV.1790"
function ShowItLikeYouBuildIt.showarg(io::IO, A::PermutedDimsArray{T,N,perm}) where {T,N,perm}
print(io, "PermutedDimsArray(")
showarg(io, parent(A))
print(io, ", ", perm, ')')
end

Base.summary(A::PermutedDimsArray) = summary_build(A)
end

# rawview
AAFixed{T<:FixedPoint,N} = AbstractArray{T,N}
function ShowItLikeYouBuildIt.showarg(io::IO, A::MappedArray{T,N,AA,typeof(reinterpret)}, toplevel=false) where {T<:Integer,N,AA<:AAFixed}
function Base.showarg(io::IO, A::MappedArray{T,N,AA,typeof(reinterpret)}, toplevel=false) where {T<:Integer,N,AA<:AAFixed}
print(io, "rawview(")
showarg(io, parent(A))
print(io, ')')
Expand All @@ -21,7 +11,7 @@ Base.summary(A::MappedArray{T,N,AA,typeof(reinterpret)}) where {T<:Integer,N,AA}

# normedview
AAInteger{T<:Integer,N} = AbstractArray{T,N}
function ShowItLikeYouBuildIt.showarg(io::IO, A::MappedArray{T,N,AA,F,typeof(reinterpret)}, toplevel=false) where {T<:FixedPoint,N,AA<:AAInteger,F}
function Base.showarg(io::IO, A::MappedArray{T,N,AA,F,typeof(reinterpret)}, toplevel=false) where {T<:FixedPoint,N,AA<:AAInteger,F}
print(io, "normedview(")
ColorTypes.showcoloranttype(io, T)
print(io, ", ")
Expand All @@ -32,81 +22,18 @@ end

Base.summary(A::MappedArray{T,N,AA,F,typeof(reinterpret)}) where {T<:FixedPoint,N,AA,F} = summary_build(A)

if VERSION < v"0.7.0-DEV.1790"
# SubArray of Colorant
_showindices(io, indices) = print(io, indices)
_showindices(io, ::Base.Slice) = print(io, ':')
function ShowItLikeYouBuildIt.showarg(io::IO, A::SubArray{T,N}) where {T<:Colorant,N}
print(io, "view(")
showarg(io, parent(A))
print(io, ", ")
for (i, indices) in enumerate(A.indexes)
_showindices(io, indices)
i < length(A.indexes) && print(io, ", ")
end
print(io, ')')
end

Base.summary(A::SubArray{T,N}) where {T<:Colorant,N} = summary_build(A)


## Specializations of other containers based on a color or fixed-point eltype
# These may be going too far, but let's see how it works out
function ShowItLikeYouBuildIt.showarg(io::IO, A::Array{T,N}) where {T<:Union{FixedPoint,Colorant},N}
print(io, "::")
_showarg_type(io, A)
end
function _showarg_type(io::IO, A::Array)
print(io, "Array{")
T = eltype(A)
if T<:Colorant
ColorTypes.colorant_string_with_eltype(io, T)
else
ColorTypes.showcoloranttype(io, T)
end
print(io, ',', ndims(A), '}')
end

function Base.summary(A::Array{T}) where T<:Union{FixedPoint,Colorant}
io = IOBuffer()
print(io, ShowItLikeYouBuildIt.dimstring(indices(A)), ' ')
_showarg_type(io, A)
String(io)
end

function ShowItLikeYouBuildIt.showarg(io::IO, A::OffsetArray{T,N,AA}) where {T<:Union{FixedPoint,Colorant},N,AA<:Array}
print(io, "::")
_showarg_type(io, A)
end
function _showarg_type(io::IO, A::OffsetArray{T,N,AA}) where {T,N,AA<:Array}
print(io, "OffsetArray{")
if T<:Colorant
ColorTypes.colorant_string_with_eltype(io, T)
else
ColorTypes.showcoloranttype(io, T)
end
print(io, ',', ndims(A), '}')
end
function _showarg_type(io::IO, A::OffsetArray{T,N}) where {T,N}
print(io, "OffsetArray{")
if T<:Colorant
ColorTypes.colorant_string_with_eltype(io, T)
else
ColorTypes.showcoloranttype(io, T)
end
print(io, ',', ndims(A), ',')
_showarg_type(io, parent(A))
print(io, '}')
end

function Base.summary(A::OffsetArray{T}) where T<:Union{FixedPoint,Colorant}
io = IOBuffer()
print(io, ShowItLikeYouBuildIt.dimstring(indices(A)), ' ')
_showarg_type(io, A)
String(io)
end
function Base.showarg(io::IO, r::Base.ReinterpretArray{T}, toplevel) where {T<:Colorant}
print(io, "reinterpret(")
ColorTypes.colorant_string_with_eltype(io, T)
print(io, ", ")
showarg(io, parent(r), false)
print(io, ')')
end

function _showarg_type(io::IO, A)
print(io, typeof(A))
end
function Base.showarg(io::IO, r::Base.ReinterpretArray{T}, toplevel) where {T<:FixedPoint}
print(io, "reinterpret(")
ColorTypes.showcoloranttype(io, T)
print(io, ", ")
showarg(io, parent(r), false)
print(io, ')')
end
Loading

0 comments on commit e7b3e00

Please sign in to comment.