Skip to content

Commit

Permalink
Merge branch 'master' into jc+ash/structure
Browse files Browse the repository at this point in the history
  • Loading branch information
ashwani-rathee authored Aug 16, 2023
2 parents 251fb2d + 0d7ea6c commit 565a90a
Show file tree
Hide file tree
Showing 20 changed files with 209 additions and 291 deletions.
4 changes: 2 additions & 2 deletions .github/workflows/UnitTest.yml
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ jobs:
strategy:
fail-fast: false
matrix:
julia-version: ['1.0', '1', 'nightly']
julia-version: ['1.6', '1', 'nightly']
os: [ubuntu-latest]
arch: [x64]
include:
Expand All @@ -41,7 +41,7 @@ jobs:
env:
cache-name: cache-artifacts
with:
path: ~/.julia/artifacts
path: ~/.julia/artifacts
key: ${{ runner.os }}-test-${{ env.cache-name }}-${{ hashFiles('**/Project.toml') }}
restore-keys: |
${{ runner.os }}-test-${{ env.cache-name }}-
Expand Down
13 changes: 13 additions & 0 deletions NEWS.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,16 @@
# 0.10.0

## Breaking changes

- `clamp01` has been restricted to `AbstractGray` and `AbstractRGB`, as it did not make sense for colors like `HSV` (#181)
- Step 3 of [ColorVectorSpace's `abs2` transition has been completed](https://github.com/JuliaGraphics/ColorVectorSpace.jl#abs-and-abs2); users and developers should now replace any `ColorVectorSpace.Future.abs2` calls with `abs2` to prevent breakage when the final step completes.

## Other changes

- AbstractFFTs.jl is no longer a dependency; error hints are now used for `fft` operations on deliberately-unsupported `Colorant` types
- Graphics.jl is no longer a dependency
- PrecompileTools.jl is now used for precompilation

# 0.7.0

## Breaking changes
Expand Down
18 changes: 8 additions & 10 deletions Project.toml
Original file line number Diff line number Diff line change
@@ -1,47 +1,45 @@
name = "ImageCore"
uuid = "a09fc81d-aa75-5fe9-8630-4744c3626534"
version = "0.9.3"
version = "0.10.1"

[deps]
AbstractFFTs = "621f4979-c628-5d54-868e-fcf4e3e8185c"
ColorVectorSpace = "c3611d14-8923-5661-9e6a-0046d554d3a4"
Colors = "5ae59095-9a9b-59fe-a467-6f913c188581"
FixedPointNumbers = "53c48c17-4a7d-5ca2-90c5-79b7896eea93"
Graphics = "a2bd30eb-e257-5431-a919-1863eab51364"
IndirectArrays = "9b13fd28-a010-5f03-acff-a1bbcff69959"
MappedArrays = "dbb5928d-eab1-5f90-85c2-b9b0edb7c900"
MosaicViews = "e94cdb99-869f-56ef-bcf0-1ae2bcbe0389"
OffsetArrays = "6fe1bfb0-de20-5000-8ca7-80f57d26f881"
PaddedViews = "5432bcbf-9aad-5242-b902-cca2824c8663"
PrecompileTools = "aea7be01-6a6a-4083-8856-8a6e6704d82a"
Reexport = "189a3867-3050-52da-a836-e630ba90ab69"
StructArrays = "09ab397b-f2b6-538f-b94a-2f83cf4a842a"

[compat]
AbstractFFTs = "0.4, 0.5, 1.0"
ColorVectorSpace = "0.9.7"
ColorVectorSpace = "0.10"
Colors = "0.12"
FixedPointNumbers = "0.8"
Graphics = "0.4, 1.0"
IndirectArrays = "0.5, 1"
MappedArrays = "0.2, 0.3, 0.4"
MosaicViews = "0.3.3"
OffsetArrays = "0.8, 0.9, 0.10, 0.11, 1.0.1"
PaddedViews = "0.5.8"
PrecompileTools = "1"
Reexport = "0.2, 1.0"
StructArrays = "0.5, 0.6"
julia = "1"
julia = "1.6"

[extras]
Aqua = "4c88cf16-eb10-579e-8560-4a9242c79595"
ColorVectorSpace = "c3611d14-8923-5661-9e6a-0046d554d3a4"
BlockArrays = "8e7c35d0-a365-5155-bbbb-fb81a777f24e"
Documenter = "e30172f5-a6a5-5a46-863b-614d45cd2de4"
FFTW = "7a1cc6ca-52ef-59f5-83cd-3a7055c09341"
ImageIO = "82e4d734-157c-48bb-816b-45c225c6df19"
ImageInTerminal = "d8c32880-2388-543b-8c61-d9f865259254"
ImageMagick = "6218d12a-5da1-5696-b52f-db25d2ecc6d1"
Random = "9a3f8284-a2c9-5f02-9a11-845980a1fd5c"
ReferenceTests = "324d217c-45ce-50fc-942e-d289b448e8cf"
Statistics = "10745b16-79ce-11e8-11f9-7d13ad32a3b2"
Test = "8dfed614-e22c-5e08-85e1-65c5234f0b40"

[targets]
test = ["Aqua", "ColorVectorSpace", "Documenter", "FFTW", "ImageInTerminal", "ImageMagick", "Random", "ReferenceTests", "Statistics", "Test"]
test = ["Aqua", "BlockArrays", "Documenter", "FFTW", "ImageIO", "ImageInTerminal", "Random", "ReferenceTests", "Statistics", "Test"]
2 changes: 1 addition & 1 deletion docs/src/views.md
Original file line number Diff line number Diff line change
Expand Up @@ -139,7 +139,7 @@ julia> img
RGB{N0f8}(0.0,0.0,1.0) RGB{N0f8}(0.0,0.0,0.0)
```

The hexidecimal representation of 128 is 0x80; this is approximately
The hexadecimal representation of 128 is 0x80; this is approximately
halfway to 255, and as a consequence the `N0f8` representation is
very near 0.5. You can see the same change is reflected in `r`, `v`,
and `img`: there is only one underlying array, `img`, and the two
Expand Down
47 changes: 26 additions & 21 deletions src/ImageCore.jl
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ using Reexport

@reexport using MosaicViews
@reexport using PaddedViews
using MappedArrays, Graphics
using MappedArrays
using OffsetArrays # for show.jl
using OffsetArrays: no_offset_view
using .ColorTypes: colorant_string
Expand All @@ -29,30 +29,24 @@ end
using Base: tail, @pure, Indices
import Base: float

import Graphics: width, height

# TODO: just use .+
# See https://github.com/JuliaLang/julia/pull/22932#issuecomment-330711997
plus(r::AbstractUnitRange, i::Integer) = broadcast(+, r, i)
plus(a::AbstractArray, i::Integer) = a .+ i

using .ColorTypes: AbstractGray, TransparentGray, Color3, Transparent3
Color1{T} = Colorant{T,1}
Color2{T} = Colorant{T,2}
Color4{T} = Colorant{T,4}
AColor{N,C,T} = AlphaColor{C,T,N}
ColorA{N,C,T} = ColorAlpha{C,T,N}
const Color1{T} = Colorant{T,1}
const Color2{T} = Colorant{T,2}
const Color4{T} = Colorant{T,4}
const AColor{N,C,T} = AlphaColor{C,T,N}
const ColorA{N,C,T} = ColorAlpha{C,T,N}
const NonparametricColors = Union{RGB24,ARGB32,Gray24,AGray32}
Color1Array{C<:Color1,N} = AbstractArray{C,N}
const Color1Array{C<:Color1,N} = AbstractArray{C,N}
# Type that arises from reshape(reinterpret(To, A), sz):
if VERSION >= v"1.6.0-DEV.1083"
const RRArray{To,From,M,P} = Base.ReinterpretArray{To,M,From,P,true}
else
const RRArray{To,From,N,M,P} = Base.ReshapedArray{To,N,Base.ReinterpretArray{To,M,From,P}}
end
const RRArray{To,From,M,P} = Base.ReinterpretArray{To,M,From,P,true}
const RGArray = Union{Base.ReinterpretArray{<:AbstractGray,M,<:Number,P}, Base.ReinterpretArray{<:Number,M,<:AbstractGray,P}} where {M,P}

# delibrately not export these constants to enable extensibility for downstream packages
# Deliberately not export these constants to enable extensibility for downstream packages
const NumberLike = Union{Number,AbstractGray}
const Pixel = Union{Number,Colorant}
const GenericGrayImage{T<:NumberLike,N} = AbstractArray{T,N}
Expand Down Expand Up @@ -94,7 +88,6 @@ export
# traits
assert_timedim_last,
coords_spatial,
height,
indices_spatial,
namedaxes,
nimages,
Expand All @@ -109,14 +102,12 @@ export
im_from_matlab,
im_to_matlab


include("colorchannels.jl")
include("stackedviews.jl")
include("convert_reinterpret.jl")
include("traits.jl")
include("map.jl")
include("show.jl")
include("functions.jl")
include("matlab.jl")
include("deprecations.jl")

Expand Down Expand Up @@ -188,9 +179,23 @@ function Base.transpose(a::AbstractVector{C}) where C<:Colorant
out
end

if VERSION >= v"1.4.2" # work around https://github.com/JuliaLang/julia/issues/34121
include("precompile.jl")
_precompile_()
# It's better not to define fft on Colorant arrays, because keeping
# track of the color dimension and the fft-dims is prone to omissions
# or problems due to later operations. So we put the bookkeeping on
# the user, but we try to give helpful suggestions.
function throw_ffterror(io, @nospecialize(f), x, dims=1:ndims(x))
newdims = plus(dims, channelview_dims_offset(x))
print(io, '\n', f, " not defined for eltype $(eltype(x)). Use channelview, and likely $newdims for the dims in the fft.")
end

function __init__()
Base.Experimental.register_error_hint(MethodError) do io, exc, argtypes, kwargs
if nameof(exc.f) (:fft, :rfft, :plan_fft, :plan_rfft, :realfloat) && argtypes[1] <: AbstractArray{<:Colorant}
throw_ffterror(io, exc.f, exc.args...)
end
end
end

include("precompile.jl")

end ## module
51 changes: 16 additions & 35 deletions src/colorchannels.jl
Original file line number Diff line number Diff line change
Expand Up @@ -27,22 +27,19 @@ dimorder(::Type{<:AlphaColor{<:Color3,T,N}}) where {T,N} = ColorChanPerm((4, 1,

const ColorChanPermSubArray{T,N,P,I<:Tuple,L} =
SubArray{T,N,P,I,L}
if VERSION >= v"1.6.0-DEV.1083"
const RRPermArray{To,From,M,P<:ColorChanPermSubArray} =
RRArray{To,From,M,P}
else
const RRPermArray{To,From,N,M,P<:ColorChanPermSubArray} =
RRArray{To,From,N,M,P}
end
const RRPermArray{To,From,M,P<:ColorChanPermSubArray} =
RRArray{To,From,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}

NVector{T,N}(x::NTuple{N}) where {T,N} = new{T,N}(x)
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)
NVector(x1::T, x::Vararg{T,N}) where {T,N} = NVector{T,N+1}((x1, x...))

@inline Base.setindex!(A::RRPermArray{<:RGBX,<:Number,N}, val::AbstractRGB, i::Vararg{Int,N}) where N =
setindex!(parent(parent(parent(A))), NVector(red(val), green(val), blue(val)), :, i...)
Expand All @@ -66,13 +63,8 @@ A = channelview(img) # a 3×10×10 array
See also: [`colorview`](@ref)
"""
channelview(A::AbstractArray{T}) where {T<:Number} = A
if VERSION >= v"1.6.0-DEV.1083"
channelview(A::RRArray{<:Colorant,<:Number}) = parent(A)
channelview(A::RRPermArray{<:Colorant,<:Number}) = parent(parent(A))
else
channelview(A::RRArray{<:Colorant,<:Number}) = parent(parent(A))
channelview(A::RRPermArray{<:Colorant,<:Number}) = parent(parent(parent(A)))
end
channelview(A::RRArray{<:Colorant,<:Number}) = parent(A)
channelview(A::RRPermArray{<: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)
function channelview(A::AbstractArray{C}) where {C<:AbstractRGB}
Expand Down Expand Up @@ -117,25 +109,14 @@ _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))
if VERSION >= v"1.6.0-DEV.1083"
_ccolorview(::Type{C}, A::Base.ReinterpretArray{T,M,C,AA,false}) where {C<:RGB,T<:Number,M,AA} =
reshape(parent(A), Base.tail(axes(parent(A))))
# _ccolorview(::Type{C}, A::Base.ReinterpretArray{T,M,C,AA,true}) where {C<:RGB,T<:Number,M,AA} =
# parent(A)
_ccolorview(::Type{C}, A::Base.ReinterpretArray{T,M,C,AA,false}) where {C<:Color,T<:Number,M,AA} =
reshape(parent(A), Base.tail(axes(parent(A))))
# _ccolorview(::Type{C}, A::Base.ReinterpretArray{T,M,C,AA,true}) where {C<:Color,T<:Number,M,AA} =
# parent(A)
else
_ccolorview(::Type{C}, A::Base.ReinterpretArray{T,M,C}) where {C<:AbstractGray,T<:Number,M} =
parent(A)
_ccolorview(::Type{C}, A::Base.ReinterpretArray{T,M,C}) where {C<:RGB,T<:Number,M} =
reshape(parent(A), Base.tail(axes(parent(A))))
_ccolorview(::Type{C}, A::Base.ReinterpretArray{T,M,C}) where {C<:Color,T<:Number,M} =
reshape(parent(A), Base.tail(axes(parent(A))))
end
# _ccolorview(::Type{C}, A::Base.ReinterpretArray{T,M,C}) where {C<:AbstractRGB,T<:Number,M} =
# _colorview_reorder(C, A)
_ccolorview(::Type{C}, A::Base.ReinterpretArray{T,M,C,AA,false}) where {C<:RGB,T<:Number,M,AA} =
reshape(parent(A), Base.tail(axes(parent(A))))
# _ccolorview(::Type{C}, A::Base.ReinterpretArray{T,M,C,AA,true}) where {C<:RGB,T<:Number,M,AA} =
# parent(A)
_ccolorview(::Type{C}, A::Base.ReinterpretArray{T,M,C,AA,false}) where {C<:Color,T<:Number,M,AA} =
reshape(parent(A), Base.tail(axes(parent(A))))
# _ccolorview(::Type{C}, A::Base.ReinterpretArray{T,M,C,AA,true}) where {C<:Color,T<:Number,M,AA} =
# parent(A)
_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)
Expand Down Expand Up @@ -198,7 +179,7 @@ Create a function that is equivalent to `(As...) -> colorview(C, Ax...)`.
```jldoctest; setup = :(using ImageCore)
julia> ones(Float32, 2, 2) |> colorview(Gray)
2×2 reinterpret($(VERSION >= v"1.6.0-DEV.1083" ? "reshape, " : "")Gray{Float32}, ::$(Array{Float32,2}))$(VERSION >= v"1.6.0-DEV.1083" ? " with eltype Gray{Float32}" : ""):
2×2 reinterpret(reshape, Gray{Float32}, ::$(Array{Float32,2})) with eltype Gray{Float32}:
Gray{Float32}(1.0) Gray{Float32}(1.0)
Gray{Float32}(1.0) Gray{Float32}(1.0)
```
Expand Down
57 changes: 2 additions & 55 deletions src/convert_reinterpret.jl
Original file line number Diff line number Diff line change
Expand Up @@ -2,61 +2,8 @@

@pure samesize(::Type{T}, ::Type{S}) where {T,S} = sizeof(T) == sizeof(S)

if VERSION >= v"1.6.0-DEV.1083"
reinterpretc(::Type{T}, a::AbstractArray) where T = reinterpret(reshape, ccolor_number(T, eltype(a)), a)
reinterpretc(::Type{T}, a::Base.ReinterpretArray{S,N,T,AA,true}) where {T,S,N,AA<:AbstractArray{T}} = parent(a)
else
# Color->Color
function reinterpretc(::Type{CV1}, a::Array{CV2,1}) where {CV1<:Colorant,CV2<:Colorant}
CV = ccolor(CV1, CV2)
l = (length(a)*sizeof(CV2))÷sizeof(CV1)
l*sizeof(CV1) == length(a)*sizeof(CV2) || throw(ArgumentError("sizes are incommensurate"))
reshape(reinterpret(CV, a), (l,))
end
function reinterpretc(::Type{CV1}, a::AbstractArray{CV2}) where {CV1<:Colorant,CV2<:Colorant}
CV = ccolor(CV1, CV2)
if samesize(CV, CV2)
return reshape(reinterpret(CV, a), size(a))
end
throw(ArgumentError("result shape not specified"))
end

# Color->T
function reinterpretc(::Type{T}, a::AbstractArray{CV}) where {T<:Number,CV<:Colorant}
if samesize(T, CV)
return reinterpret(T, a)
end
axs = axes(a)
if sizeof(CV) == sizeof(T)*_len(CV)
return reinterpret(T, reshape(a, Base.OneTo(1), axs...))
end
throw(ArgumentError("result shape not specified"))
end
reinterpretc(::Type{T}, a::AbstractArray{CV,0}) where {T<:Number,CV<:Colorant} =
reinterpret(T, reshape(a, 1))

_len(::Type{C}) where {C} = _len(C, eltype(C))
_len(::Type{C}, ::Type{Any}) where {C} = error("indeterminate type")
_len(::Type{C}, ::Type{T}) where {C,T} = sizeof(C) ÷ sizeof(T)

## T->Color
# We have to distinguish two forms of call:
# form 1: reinterpretc(RGB{N0f8}, img)
# form 2: reinterpretc(RGB, img)
function reinterpretc(CV::Type{<:Colorant}, a::AbstractArray{T}) where T<:Number # {CV<:Colorant,T<:Number}
@noinline throwdm(C::Type, ind1) =
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
axs = axes(a)
if axs[1] == Base.OneTo(sizeof(CVT) ÷ sizeof(eltype(CVT)))
return reshape(reinterpret(CVT, a), tail(axs))
end
throwdm(CV, axs[1])
end
end
reinterpretc(::Type{T}, a::AbstractArray) where T = reinterpret(reshape, ccolor_number(T, eltype(a)), a)
reinterpretc(::Type{T}, a::Base.ReinterpretArray{S,N,T,AA,true}) where {T,S,N,AA<:AbstractArray{T}} = parent(a)

# ccolor_number converts form 2 calls to form 1 calls
ccolor_number(::Type{T}, ::Any) where T<:Number = T
Expand Down
24 changes: 10 additions & 14 deletions src/deprecations.jl
Original file line number Diff line number Diff line change
@@ -1,19 +1,15 @@
const warned_once = Ref(false)
if VERSION >= v"1.5"
function forced_depwarn(msg, sym)
opts = Base.JLOptions()
if !warned_once[] && !(opts.depwarn == 1)
@warn msg
@info """It is recommended that you fix this now to avoid breakage when a new version is released and this warning is removed.
Tip: to see all deprecation warnings together with code locations, launch Julia with `--depwarn=yes` and rerun your code."""
warned_once[] = true
else
Base.depwarn(msg, sym)
end
return nothing
function forced_depwarn(msg, sym)
opts = Base.JLOptions()
if !warned_once[] && !(opts.depwarn == 1)
@warn msg
@info """It is recommended that you fix this now to avoid breakage when a new version is released and this warning is removed.
Tip: to see all deprecation warnings together with code locations, launch Julia with `--depwarn=yes` and rerun your code."""
warned_once[] = true
else
Base.depwarn(msg, sym)
end
else
forced_depwarn(msg, sym) = Base.depwarn(msg, sym)
return nothing
end

# a perhaps "permanent" deprecation
Expand Down
20 changes: 0 additions & 20 deletions src/functions.jl

This file was deleted.

Loading

0 comments on commit 565a90a

Please sign in to comment.