Surprising behaviour of HiLo LUT

I stumbled upon a (for me) surprising behaviour of the HiLo LUT.
I wanted to manually delete some dirt structures in an image by selecting them with a rectangle/circle and then deleting them with pressing the “del” key. With gray LUT this works as expected, the deleted area has the value 0.
I then wanted to do the same with HiLo-LUT active because I thought I see then blue where I deleted already … but to my surprise this does not work! The deleted areas are not 0 but 1 !!!
I always thought that the LUT is only manipulating the display, but it seems in this case choice of LUT also has an influence on image processing. Is this expected behaviour?

The macro below illustrated this. ROI 1 is deleted with Grays LUT active — the deleted area has the value 0.
ROI 2 is deleted with HiLo active, the deleted area has the value 1

setBackgroundColor(0, 0, 0);
run("Blobs (25K)");
run("Subtract...", "value=80");
run("Grays");
doWand(140, 50, 44.0, "Legacy");
roiManager("add");
run("Clear", "slice");

run("HiLo");
doWand(92, 162, 44.0, "Legacy");
run("Clear", "slice");
roiManager("add");
roiManager("show all with labels");

That behavior can indeed be surprising, but it is explainable at least :smiley:

This sets the background color of the Color Picker tool to an RGB value. Once you call:

… the selection will be filled with the value closest to the currently selected (RGB) background color, depending on your LUT, resulting in 0 for the Grays LUT, and 1 for the HiLo LUT.

You can work around this by setting your background to (0, 0, 255) after choosing the HiLo LUT:

setBackgroundColor(0, 0, 0);
run("Blobs (25K)");
run("Subtract...", "value=80");
run("Grays");
doWand(140, 50, 44.0, "Legacy");
roiManager("add");
run("Clear", "slice");

run("HiLo");
setBackgroundColor(0, 0, 255); // <= this line was added
doWand(92, 162, 44.0, "Legacy");
run("Clear", "slice");
roiManager("add");
roiManager("show all with labels");

What I find surprising is that there’s no setBackgroundColor(value) function in the macro language, in analogy to the setColor(value) function:

setColor(r, g, b)
Sets the drawing color, where r , g , and b are >= 0 and <= 255. With 16 and 32 bit images, sets the color to 0 if r=g=b=0. With 16 and 32 bit images, use setColor(1,0,0) to make the drawing color the same is the minimum displayed pixel value. SetColor() is faster than setForegroundColor(), and it does not change the system wide foreground color or repaint the color picker tool icon, but it cannot be used to specify the color used by commands called from macros, for example run(“Fill”) .

setColor(value)
Sets the drawing color. For 8 bit images, 0<= value <=255. For 16 bit images, 0<= value <=65535. For RGB images, use hex constants (e.g., 0xff0000 for red). This function does not change the foreground color used by run(“Draw”) and run(“Fill”) .

setBackgroundColor(r, g, b)
Sets the background color, where r , g , and b are >= 0 and <= 255. See also: setForegroundColor.


In the Java API of ImageProcessor, there is:

setBackgroundValue(double value)
Sets the background fill value used by the rotate() and scale() methods.

… but as the javadoc says, that’s only used for rotating and scaling, not for clearing ROIs.


As to why it is like it is, we might have to ask @Wayne.

Thank you for this detailed explanation. No way that I would have managed to understand this without this great forum!

Now I understand that for my initial task (manually selecting certain areas and deleting them) I should have set the background color in the ColorPicker to blue if I wanted to do this task with the HiLo-Lut active.