Skip to content

Commit

Permalink
support UInt8/UInt16 for im_to_matlab
Browse files Browse the repository at this point in the history
  • Loading branch information
johnnychen94 committed Apr 17, 2022
1 parent 2fc256a commit 02c9214
Show file tree
Hide file tree
Showing 3 changed files with 71 additions and 5 deletions.
40 changes: 35 additions & 5 deletions src/matlab.jl
Original file line number Diff line number Diff line change
Expand Up @@ -218,18 +218,48 @@ im_to_matlab(::Type{T}, img::AbstractArray{CT}) where {T,CT<:TransparentColor} =
im_to_matlab(T, of_eltype(base_color_type(CT), img))
im_to_matlab(::Type{T}, img::AbstractArray{<:Color}) where {T} =
im_to_matlab(T, of_eltype(RGB{T}, img))
im_to_matlab(::Type{T}, img::AbstractArray{<:Gray}) where {T} =
no_offset_view(of_eltype(T, channelview(img)))
im_to_matlab(::Type{T}, img::AbstractArray{CT}) where {T,CT<:Union{Gray,RGB,Number}} =
_im_to_matlab_try_reinterpret(T, img)

# eltype conversion doesn't work in general, e.g., `UInt8(N0f8(0.3))` would fail. For special
# types that we know solution, directly reinterpret them via `rawview`.
function _im_to_matlab_try_reinterpret(::Type{T}, img::AbstractArray{CT}) where {T,CT<:Union{Gray,Real}}
throw(ArgumentError("Can not convert to MATLAB format: invalid conversion from `$(CT)` to `$T`."))
end
function _im_to_matlab_try_reinterpret(::Type{T}, img::AbstractArray{CT}) where {T<:Union{AbstractFloat, Normed},CT<:Union{Gray,Real}}
return no_offset_view(of_eltype(T, channelview(img)))
end
for (T, NT) in ((:UInt8, :N0f8), (:UInt16, :N0f16))
@eval function _im_to_matlab_try_reinterpret(::Type{$T}, img::AbstractArray{CT}) where {CT<:Union{Gray,Real}}
if eltype(CT) != $NT
nt_str = string($NT)
throw(ArgumentError("Can not convert to MATLAB format: invalid conversion from `$(CT)` to `$nt_str`."))
end
return no_offset_view(rawview(channelview(img)))
end
end
# for RGB, unroll the color channel in the last dimension
function im_to_matlab(::Type{T}, img::AbstractArray{<:RGB, N}) where {T, N}
_im_to_matlab_try_reinterpret(::Type{T}, img::AbstractArray{CT}) where {T,CT<:RGB} =
throw(ArgumentError("Can not convert to MATLAB format: invalid conversion from `$(CT)` to `$T`."))
function _im_to_matlab_try_reinterpret(::Type{T}, img::AbstractArray{<:RGB,N}) where {T<:Union{AbstractFloat, Normed},N}
v = no_offset_view(of_eltype(T, channelview(img)))
perm = (ntuple(i->i+1, N)..., 1)
perm = (ntuple(i -> i + 1, N)..., 1)
return PermutedDimsArray(v, perm)
end
for (T, NT) in ((:UInt8, :N0f8), (:UInt16, :N0f16))
@eval function _im_to_matlab_try_reinterpret(::Type{$T}, img::AbstractArray{CT,N}) where {CT<:RGB,N}
if eltype(CT) != $NT
nt_str = string($NT)
throw(ArgumentError("Can not convert to MATLAB format: invalid conversion from `$(CT)` to `$nt_str`."))
end
v = no_offset_view(rawview(channelview(img)))
perm = (ntuple(i -> i + 1, N)..., 1)
return PermutedDimsArray(v, perm)
end
end

# indexed image
function im_to_matlab(::Type{T}, img::IndirectArray{CT}) where {T<:Real, CT<:Colorant}
function im_to_matlab(::Type{T}, img::IndirectArray{CT}) where {T<:Real,CT<:Colorant}
return no_offset_view(img.index), im_to_matlab(T, img.values)
end

Expand Down
35 changes: 35 additions & 0 deletions test/matlab.jl
Original file line number Diff line number Diff line change
Expand Up @@ -266,6 +266,41 @@
@test eltype(m_values) == N0f8
@test m_values == permutedims(channelview(values), (2, 1))
end

@testset "UInt8/UInt16" begin
# directly doing eltype conversion doesn't work for UInt8/UInt16
# thus we can reinterpret, aka, `rawview`.
for (T, NT) in ((UInt8, N0f8), (UInt16, N0f16))
img = rand(Gray{NT}, 4, 5)
img_m_normed = im_to_matlab(NT, img)
img_m = im_to_matlab(T, img)
@test eltype(img_m_normed) == NT
@test eltype(img_m) == T
@test img_m_normed != img_m
@test img_m_normed == channelview(img)
@test img_m == rawview(channelview(img))

img = rand(RGB{NT}, 4, 5)
img_m_normed = im_to_matlab(NT, img)
img_m = im_to_matlab(T, img)
@test eltype(img_m_normed) == NT
@test eltype(img_m) == T
@test img_m_normed != img_m
@test img_m_normed == permutedims(channelview(img), (2, 3, 1))
@test img_m == permutedims(rawview(channelview(img)), (2, 3, 1))
end

# We only patch for special types that MATLAB expects, for anything that is
# non-standard MATLAB layout, manual conversions or other tools are needed. Here
# we test that we have informative error messages.
for CT in (Gray, RGB)
img = rand(CT{N0f8}, 4, 5)
msg = "Can not convert to MATLAB format: invalid conversion from `$CT{$N0f8}` to `$N0f16`."
@test_throws ArgumentError(msg) im_to_matlab(UInt16, img)
msg = "Can not convert to MATLAB format: invalid conversion from `$CT{$N0f8}` to `$Int`."
@test_throws ArgumentError(msg) im_to_matlab(Int, img)
end
end
end

# test `im_from_matlab` and `im_to_matlab` are inverses of each other.
Expand Down
1 change: 1 addition & 0 deletions test/runtests.jl
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
module ImageCoreTests

using ImageCore
using OffsetArrays: OffsetArray
using Test, ReferenceTests
using Aqua, Documenter # for meta quality checks

Expand Down

0 comments on commit 02c9214

Please sign in to comment.