From e1d45dec5d8b826aa373e3169bee60971e11ad75 Mon Sep 17 00:00:00 2001 From: yha Date: Tue, 3 Dec 2019 17:40:55 +0200 Subject: [PATCH] Use GR.drawimage for uniform heatmaps; Fix for general color spaces. --- src/backends/gr.jl | 43 +++++++++++++++++++++++++++++++------------ src/utils.jl | 5 +++++ 2 files changed, 36 insertions(+), 12 deletions(-) diff --git a/src/backends/gr.jl b/src/backends/gr.jl index f64eab57..ec93edb7 100644 --- a/src/backends/gr.jl +++ b/src/backends/gr.jl @@ -69,6 +69,19 @@ const gr_font_family = Dict( # -------------------------------------------------------------------------------------- +gr_color(c) = gr_color(c, color_type(c)) + +gr_color(c, ::Type{<:AbstractRGB}) = UInt32( round(UInt, clamp(alpha(c) * 255, 0, 255)) << 24 + + round(UInt, clamp(blue(c) * 255, 0, 255)) << 16 + + round(UInt, clamp(green(c) * 255, 0, 255)) << 8 + + round(UInt, clamp(red(c) * 255, 0, 255)) ) +function gr_color(c, ::Type{<:AbstractGray}) + g = round(UInt, clamp(gray(c) * 255, 0, 255)) + α = round(UInt, clamp(alpha(c) * 255, 0, 255)) + rgba = UInt32( α<<24 + g<<16 + g<<8 + g ) +end +gr_color(c, ::Type) = gr_color(RGBA(c), RGB) + function gr_getcolorind(c) gr_set_transparency(float(alpha(c))) convert(Int, GR.inqcolorfromrgb(red(c), green(c), blue(c))) @@ -1318,9 +1331,23 @@ function gr_display(sp::Subplot{GRBackend}, w, h, viewport_canvas) x, y = heatmap_edges(series[:x], sp[:xaxis][:scale], series[:y], sp[:yaxis][:scale], size(series[:z])) w, h = length(x) - 1, length(y) - 1 z_normalized = map(x -> GR.jlgr.normalize_color(x, zmin, zmax), z) - z_normalized = map(x -> isnan(x) ? 256/255 : x, z_normalized) # results in color index = 1256 -> transparent - colors = Int32[round(Int32, 1000 + _i * 255) for _i in z_normalized] - GR.nonuniformcellarray(x, y, w, h, colors) + if is_uniformly_spaced(x) && is_uniformly_spaced(y) + # For uniformly spaced data use GR.drawimage, which can be + # much faster than GR.nonuniformcellarray, especially for + # pdf output, and also supports alpha values. + # Note that drawimage draws uniformly spaced data correctly + # even on log scales, where it is visually non-uniform. + colors = plot_color.(series[:fillcolor][z_normalized], series[:fillalpha]) + colors[isnan.(z_normalized)] .= RGBA(0,0,0,0) + rgba = gr_color.(colors) + GR.drawimage(first(x), last(x), last(y), first(y), w, h, rgba) + else + (something(series[:fillalpha],1) < 1 || any(_gr_gradient_alpha .< 1)) && @warn( + "GR: transparency not supported in non-uniform heatmaps. Alpha values ignored.") + z_normalized = map(x -> isnan(x) ? 256/255 : x, z_normalized) # results in color index = 1256 -> transparent + colors = Int32[round(Int32, 1000 + _i * 255) for _i in z_normalized] + GR.nonuniformcellarray(x, y, w, h, colors) + end else phimin, phimax = 0.0, 360.0 # nonuniform polar array is not yet supported in GR.jl nx, ny = length(series[:x]), length(series[:y]) @@ -1439,15 +1466,7 @@ function gr_display(sp::Subplot{GRBackend}, w, h, viewport_canvas) z = transpose_z(series, series[:z].surf, true)' w, h = size(z) xmin, xmax = ignorenan_extrema(series[:x]); ymin, ymax = ignorenan_extrema(series[:y]) - if eltype(z) <: Colors.AbstractGray - grey = round.(UInt8, clamp.(float(z) * 255, 0, 255)) - rgba = map(c -> UInt32( 0xff000000 + UInt(c)<<16 + UInt(c)<<8 + UInt(c) ), grey) - else - rgba = map(c -> UInt32( round(UInt, clamp(alpha(c) * 255, 0, 255)) << 24 + - round(UInt, clamp(blue(c) * 255, 0, 255)) << 16 + - round(UInt, clamp(green(c) * 255, 0, 255)) << 8 + - round(UInt, clamp(red(c) * 255, 0, 255)) ), z) - end + rgba = gr_color.(z) GR.drawimage(xmin, xmax, ymax, ymin, w, h, rgba) end diff --git a/src/utils.jl b/src/utils.jl index 324aa2cb..381f8e75 100644 --- a/src/utils.jl +++ b/src/utils.jl @@ -375,6 +375,11 @@ function heatmap_edges(x::AVec, xscale::Symbol, y::AVec, yscale::Symbol, z_size: return x, y end +function is_uniformly_spaced(v; tol=1e-6) + dv = diff(v) + maximum(dv) - minimum(dv) < tol * mean(abs.(dv)) +end + function convert_to_polar(theta, r, r_extrema = ignorenan_extrema(r)) rmin, rmax = r_extrema r = (r .- rmin) ./ (rmax .- rmin)