Unfortunate interaction between ImageCore and Gadfly

I’ve discovered an unfortunate interaction in which just loading ImageCore causes Gadfly to fail. This took me days to debug :frowning: as initially I assumed the error was in my code. It was only when I guessed that the problem was in Images and stripped out all references to Images that I started to make progress.

using Gadfly
using Colors

curves = 1:3

const palette = distinguishable_colors(
    [ RGB(253 / 255, 253 / 255, 241 / 255), RGB(0, 0, 0), colorant"DodgerBlue4"],
    transform = deuteranopic,

ls = [layer(x=1:10, y=map(x->x^i, 1:10), Geom.line, Theme(default_color = palette[i] )) for i in curves ]
# Succeeds
plot(ls..., Guide.manual_color_key("Curves", [ "Curve $i" for i in curves ], palette[curves]))

println("Loading ImageCore")
using ImageCore
# Fails on the second plot...
plot(ls..., Guide.manual_color_key("Curves", [ "Curve $i" for i in curves ], palette[curves]))

The problem is the line in ImageCore/convert_reinterpret.jl line 80-83

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

This leads to this error:

ERROR: LoadError: TypeError: in new, expected Array{Colorant,1}, got a value of type Array{RGB{Float64},1}
 [1] ManualDiscreteKey at C:\Users\nritchie\.julia\dev\Gadfly\src\guide\keys.jl:267 [inlined]
 [2] Gadfly.Guide.ManualDiscreteKey(; title::String, labels::Array{String,1}, pos::Array{Any,1}, color::Array{RGB{Float64},1}, shape::Array{Function,1}, size::Array{Measures.Measure,1}) at C:\Users\nritchie\.julia\dev\Gadfly\src\guide\keys.jl:295
 [3] #manual_color_key#131 at C:\Users\nritchie\.julia\dev\Gadfly\src\guide\keys.jl:321 [inlined]
 [4] manual_color_key(::String, ::Array{String,1}, ::Array{RGB{Float64},1}) at C:\Users\nritchie\.julia\dev\Gadfly\src\guide\keys.jl:321
 [5] top-level scope at c:\users\nritchie\.julia\dev\NeXLDatabase\weave\testgadfly.jl:18
 [6] include(::String) at .\client.jl:457
 [7] top-level scope at REPL[1]:1
in expression starting at c:\users\nritchie\.julia\dev\NeXLDatabase\weave\testgadfly.jl:18

One would like to be able to assume that libraries are largely independent of each other and that there is no chance of one library breaking another. However, this may be baked into the dynamic design of the Julia language.

This is partly a type-piracy problem, which package authors usually avoid. The situation which inspired the piratical implementation in ImageCore has changed; it is unfortunate that you encountered a bad side effect before it could be replaced.

Tim drafted a correction last month: