193
193
end
194
194
end
195
195
196
+ # plot multispectral images as rgb
197
+ @userplot RGBPlot
198
+
199
+ @recipe function f (p:: RGBPlot ; bands= 1 : 3 , low= 0.02 , high= 0.98 )
200
+ r = first (p. args)
201
+ if ! (typeof (r) <: AbstractRaster )
202
+ error (" Plotting RGB images is only implemented for AbstractRasters." )
203
+ end
204
+ if ! hasdim (r, Band)
205
+ error (" Raster must have a band dimension." )
206
+ end
207
+ if ! (0 <= low <= 1 ) || ! (0 <= high <= 1 )
208
+ error (" 'low' and 'high' have to be between 0 and 1 (inclusive)." )
209
+ end
210
+ img = Float32 .(copy (r[Band ([bands... ])]))
211
+ normalize! (img, low, high)
212
+ img = permutedims (img, (Band, X, Y))
213
+ img = DD. reorder (img, X=> DD. ForwardOrdered, Y=> DD. ForwardOrdered)
214
+ plot_image = ImageCore. colorview (RGB, img)
215
+
216
+ yguide, xguide = DD. label (dims (img, (Y,X)))
217
+
218
+ y, x = map (Rasters. _prepare, dims (img, (Y,X)))
219
+
220
+ rdt = DD. refdims_title (img; issingle= true )
221
+ :title --> (rdt === " " ? Rasters. _maybename (img) : Rasters. _maybename (img) * " \n " * rdt)
222
+ :xguide --> xguide
223
+ :xrotation --> 45
224
+ :yguide --> yguide
225
+ :tick_direction --> :out
226
+ :framestyle --> :box
227
+
228
+ if all (d -> lookup (d) isa Mapped, (x, y))
229
+ :xlims --> mappedbounds (x)
230
+ :ylims --> mappedbounds (y)
231
+ :aspect_ratio --> :equal
232
+ else
233
+ :xlims --> bounds (img, x)
234
+ :ylims --> bounds (img, y)
235
+ bnds = bounds (img, (X, Y))
236
+ # # TODO : Rethink this....
237
+ s1, s2 = map (((l, u),) -> (u - l), bnds) ./ (size (img, X), size (img, Y))
238
+ square_pixels = s2 / s1
239
+ :aspect_ratio --> square_pixels
240
+ end
241
+
242
+ :seriestype --> :image
243
+ :yflip --> false
244
+ DD. index (x), DD. index (y), plot_image'
245
+ end
246
+
247
+
196
248
# Plots.jl heatmaps pixels are centered.
197
249
# So we should center the index, and use the projected value.
198
250
_prepare (d:: Dimension ) = d |> _maybe_shift |> _maybe_mapped
@@ -248,3 +300,26 @@ function DD.refdims_title(refdim::Band; issingle=false)
248
300
end
249
301
end
250
302
303
+ function eachband_view (r:: Raster )
304
+ nbands = size (r, Band)
305
+ return (view (r, Band (n)) for n in 1 : nbands)
306
+ end
307
+
308
+ function normalize! (raster, low= 0.1 , high= 0.9 )
309
+ if ! hasdim (raster, Band)
310
+ l = quantile (skipmissing (raster), low)
311
+ h = quantile (skipmissing (raster), high)
312
+ raster .- = l
313
+ raster ./= h - l + eps (float (eltype (raster)))
314
+ raster .= clamp .(raster, zero (eltype (raster)), one (eltype (raster)))
315
+ else
316
+ for band in eachband_view (raster)
317
+ l = quantile (skipmissing (band), low)
318
+ h = quantile (skipmissing (band), high)
319
+ band .- = l
320
+ band ./= h - l + eps (float (eltype (raster)))
321
+ band .= clamp .(band, zero (eltype (raster)), one (eltype (raster)))
322
+ end
323
+ end
324
+ return raster
325
+ end
0 commit comments