@@ -362,20 +362,33 @@ def _make_image(self, A, in_bbox, out_bbox, clip_bbox, magnification=1.0,
362362 if A .ndim == 2 :
363363 A = self .norm (A )
364364 if A .dtype .kind == 'f' :
365- # If the image is greyscale, convert to RGBA with the
366- # correct alpha channel for resizing
365+ # If the image is greyscale, convert to RGBA and
366+ # use the extra channels for resizing the over,
367+ # under, and bad pixels. This is needed because
368+ # Agg's resampler is very aggressive about
369+ # clipping to [0, 1] and we use out-of-bounds
370+ # values to carry the over/under/bad information
367371 rgba = np .empty ((A .shape [0 ], A .shape [1 ], 4 ), dtype = A .dtype )
368372 rgba [..., 0 ] = A # normalized data
369373 rgba [..., 1 ] = A < 0 # under data
370- # TODO: get threshold from the norm or colormap
371374 rgba [..., 2 ] = A > 1 # over data
372- rgba [..., 3 ] = ~ A .mask
375+ rgba [..., 3 ] = ~ A .mask # bad data
373376 A = rgba
374377 output = np .zeros ((out_height , out_width , 4 ),
375378 dtype = A .dtype )
376379 alpha = 1.0
377380 created_rgba_mask = True
378381 else :
382+ # colormap norms that output integers (ex NoNorm
383+ # and BoundaryNorm) to RGBA space before
384+ # interpolating. This is needed due to the the
385+ # Agg resampler only working on floats in the
386+ # range [0, 1] and because interpolating indexes
387+ # into an arbitrary LUT maybe problematic.
388+ #
389+ # This falls back to interpolating in RGBA space which
390+ # can produce it's own artifacts of colors not in the map
391+ # showing up in the final image.
379392 A = self .cmap (A , alpha = self .get_alpha (), bytes = True )
380393
381394 if not created_rgba_mask :
0 commit comments