Use a LUT as an Array

I’m learning Fiji Macro programming and trying to do something like pseudo coloring of a TIF grayscale image. I need to color some of the TIF image pixels and not color others. My algorithm determines which pixels to color and which to leave as they are in the original image.

When the algorithm determines that a pixel is to be colored a number, called an Index number is calculated. Index numbers are in the range of 0 - 255. I want to use this Index number to get RGB values for r,g and b stored in a LUT file I create. My LUT file is 3 columns wide X 256 rows high.

I think if I had a way to convert the LUT file to an Array I could then retrieve the RGB values from the Array using the Index/row number (height) in the Array that corresponds to the RGB values I want to use. Maybe there is an easier way to accomplish what I am trying to do?

I’m open to suggestions. Do you need more information to recommend a solution? Let me know what you need to know.

Bruce

Did you have a look at the getLut macro function?

Hey Thanks, ctrueden. Not sure how I missed that in my search for a solution but I really appreciate you pointing me in the right direction.

Daddymoen

1 Like

I think a basic lack of macro programming understanding on my part is causing my code (below) not to do what I would like it to do. I want to get values for r, g, and b (RGB) from the LUT that will be used to color only some of pixels in my final image that are selected based on my algorithm (not shown). Other pixels in my image will not be colored.

Elsewhere in my code my algorithm calculates an index number (IndexNumber simulates a value of 62 for this index number). This index number is used to select the LUT row number from which the r, g and b values are to be taken.

My code so far, errors out with a message that a “)” is expected in line 9.


open();                  // open a 16-bit, TIF, Grayscale image file
run("Any ImageJ LUT");   // open an example LUT named
IndexNumber= 62;         // LUT row to retieve RGB values from 
RedValue = 0;            // intialize RedValue (the retrieved r value of RGB)
GreenValue = 0;          // intialize GreenValue (the retrieved g value of RGB)
BlueValue = 0;           // intialize BlueValue (the retrieved b value of RGB)
macro "get RGB Values" {
     getLut(reds, greens, blues);
     for (i=0; i<reds.length; i++) {
     	    if (i = IndexNumber) RedValue = reds[i];       // get r value of RGB
            if (i = IndexNumber) GreenValue = greens[i];   // get g value of RGB
            if (i = IndexNumber) BlueValue = blues[i];     // get b value of RGB
      }
print (i,IndexNumber,RedValue,GreenValue,BlueValue);
}

Any suggestion for how I can get this code to give me the r, g, b values I need for any IndexNumber?

Daddymoen

Good day,

for comparisons you may try: (i == IndexNumber).

This is not specific for the ImageJ macro-language but applies for most proramming languages…

HTH

Herbie

Herbie,

That worked.

Thanks!

Daddymoen

1 Like

With help form this forum I’ve made good progress on my project, thanks folks. Now coloring the final Image is the last major piece to my program.

I have a 2312 x 1720 pixel, 16-bit, grayscale image that I want to recolor in some areas and leave as grayscale in others. My algorithm automatically makes the decision about which pixels to leave as is and which to recolor. That section of my code so far looks like this:

macro "Recolor Red Pixels" {
  if (Pseudo == 1) {                         // "1" indicates recolor only red pixel in original image
   	 for (x = 0; x <= w; x+=2) {                     // loop thru pixels by row
		  for (y = 0; y <= h; y+=2) {            // Loop thru pixels by column    
           	
    val = getPixel(x, y);   // this the intensity value of the grayscale pixel at (x,y)
               if (val >= RedLo) {InDex = val - RedLo + lutShift;  // InDex is the LUT row number
                    getLut(reds, greens, blues);
                        RedValue = reds[InDex];     // get R value of RGB
                        GreenValue = greens[InDex]; // get G value of RGB
                        BlueValue = blues[InDex];   // get B value of RGB
                      }                        
               }    
         }                    
    }
}

The values (RedValue, GreenValue, BlueValue) are retrieved from a custom LUT entered earlier in the program. These are r, g and b values like you’d find in a set of RGB values.

What I want to do is use these r,g,b values to recolor my grayscale image at the appropriate (x,y) coordinates given by the for-loops in the code above. I’ve tried using setColor(r,g,b) but don’t see any coloring happening to the grayscale image. Once again I think my lack of understanding about something basic seems to have me stumped.

Is there a sample macro available somewhere that I could use to figure this out? Or maybe someone has some suggestions that could get me pointed in the right direction?

Thanks again for the great resource this group provides.

Daddymoen

I think your code can be significantly simpler. Since you are filtering pixels only by their value, you don’t even need to loop over your image at all—just your LUT. For each RGB triple in your LUT, it either matches your criteria, or it doesn’t. If it does match, update that entry of the LUT, by changing the array values accordingly. Finally, when done looping over your LUT, call setLut(reds, greens, blues) to lock in the changes.

If you had some other nonindependent criteria for colorization such as “what colors are neighboring pixels” then the algorithm would be different: you would indeed need to loop over the 16-bit input image, and build a new image of type RGB.

1 Like

ctrueden,

I can see how that" looping the LUT" approach would be much simpler and much, much faster and I’d like to figure out a way to use it. Unfortunately, for my situation there are two obstacles I would have to find a way around: LUT pixel intensity ranges; and separate coloring of pixel types.
Pixel Intensity Ranges:
In my images (16-bit grayscale, actually 10-bit but I use 16-bit in Fiji) the total range of pixel values is 0 - 1023. There are three separate ranges of pixel values to be colored using LUTs: 275 - 350; 350 - 430; and 480 - 600.

Obstacle: I can use LUTs with 256 values if the bottom of the range of the LUT starts 275, or 350, or 480 in the above example instead of the standard range that starts at a pixel intensity 0. Not sure how to do that.

The second obstacle is a little tricky. My grayscale image is a lossless conversion from my old Canon G2 Powershot camera raw file to a .tiff file. By knowing Bayer pattern of camera sensor I know which of the locations in the .tiff file belong to which color filter over which camera sensor pixels. For example my Canon G2 camera sensor pixel at (0,0) is a red filtered photo-sensor. All even numbered row and even numbered column pixel locations are red filtered camera photo-sensors. The green and blue filtered camera sensor pixel locations are also in a known, repetitive (Bayer) pattern.

My way around this obstacle so far uses three separate loops to loop through the three separate camera photo-sensor location sets, one loop each for red, green and blue. This will generate three separate images, one for each color of the camera’s color filtered photo-sensors.

If I were to split the grayscale image into three separate images, one for each of the camera sensor colors, I could then use your LUT looping idea. If the LUTs can be rescaled to ranges of values other than 0 to 255.

Maybe you see a different route abound the second obstacle?

Thanks again, ctrueden

Daddymoen

I still don’t understand why the following code doesn’t change the color of my image to red (255,0,0). I’ve tried it on both .tiff and .jpg versions of my image file. I feel like such an amateur. Searching for an example macro to use as a guide.

Daddymoen


open(); // open 16-bit, TIF, Grayscale image file
id = getImageID();
selectImage(id);
for (i=0; i<(1200); i++) {
for (j=0; j<(830); j+=1) {
setColor(255, 0, 0);
}
}


Daddymoen,

you try to set a 24bit color to a 16bit grayscale image. 24bit color requires a 24bit color image etc.

HTH

Herbie

Herbie,

Thanks for pointing out the problem. I’m trying a different approach to learn how to use setColor(r,g,b) to color an image, but I’m still not getting it.

To figure out how to color an image using setColor(r,g,b) I’ve written a little test code. It begins by creating a new, RGB, 250 x 150 pixel image, then get the image ID, height and width. Next I select the new image in preparation for coloring, and then run my coloring loops to set the color of all pixels to r,g,b values of 250, 120, 120. I save the resulting colored image either as a .jpg or .tif file and the close the image. Here’s my macro code:

title = "AA-RGB-test";
newImage(title,"RGB", 250, 150, 1);
id = getImageID();
h = getHeight();
w = getWidth();
selectImage(id);
  for (i=0; i<(h); i++)  {
 	for (j=0; j<(w);  j+=1)  {
        setColor(250, 120, 120);
       }
 }
 //saveAs("jpg");
 saveAs("tif");
close();

I then open the resulting image file in Fiji, which has not change to my setColor(r,g,b) color, and scroll my mouse cursor over image.

If I saved the image as a tif file every pixel the mouse cursor hovers over reports: “value=255,255,255 (white)”

If I save the resulting image file as a .jpg format every pixel the mouse cursor hovers over reports: “value 255”

It appears to me that the new image is unchanged from when is was created.

I don’t understand why?

Daddymoen

Daddymoen,

the macro call “setColor(r, g, b)” doesn’t do what you may expect. The manual for macro functions tells you the following:

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 beused to specify the color used by commands called from macros, for example run(“Fill”).”

In short:
The call doesn’t do anything to the pixels of an existing image; it simply sets the drawing color.

HTH

Herbie

Herbie,

Thanks again. Guess I didn’t really understand the implications of that last sentence when I read it the first 20 or so times.

Then, is there a call that can be used to change pixel colors of my blank image inside a macro?

Daddymoen

Daddymoen,

you could either use

setColor(250, 120, 120);
drawRect(5, 9, 1, 1);

or

setPixel(5, 9, 0xff0000);

In the latter case you have to learn how to code three values into a single Hex-code, but you may find help for this in example macros.

What bothers me most however, is that you’ve mentioned that you actually deal with 16bit RGB-images. I would recommend to split them into three 16bit graylevel images and “color” (which of course means gray values) them separately…

Best

Herbie

Herbie,

Thanks, the drawRect(x,y,1,1); works. It’s slow but it works. I’ll work on the Hex approach to see if it’s faster.

The 16bit RGB image you refer to was just kind of a “shot in the dark” experiment that I abandoned as soon as I saw the result of trying to use it.

My present approach will be to read the single pixel value from my original 16-bit grayscale image, then convert that value to r,g,b values and use those to color a new RGB image that is the same size as the original. This RGB image will be my output image.

Thanks again for your help, Herbie

Daddymoen

1 Like

With help from folks here I continue to make good progress on my project, thanks again. I tested Herbie’s two suggested solutions for my pseudo-coloring my 16-bit grayscale image:

setColor(250, 120, 120);
drawRect(5, 9, 1, 1);

or

setPixel(5, 9, 0xff0000);

I found the second one to be much faster than the first. To implement this method in my macro program I needed a simple way to convert a standard ImageJ LUT file to hexadecimal file. This allows my project to be backward compatible with existing LUT files in a way that is transparent to users. It’s novice-level elegant, but it works.

In case someone else in ImageJ / Fiji-land might have use for such a macro, the working code is below. Feel free to use it if you find a need,

Thanks again folks. When I get stuck up against some other obstacle again I’ll be back for more of your kind assistance.

Daddymoen

//  This macro converts a standard ImageJ LUT file to an Array of hexidecimal values.
//  Each of the standard LUTs 256 sets of 3, RGB values) are stored in the Array 
//  (named Ahex) as single hexadecimal values.
//  For my specific project the Ahex values will be used in conjunction with
//  the setPixel(j, i, 0xffff00); to pseudocolor a 16-bit grayscale image.
//  Thanks go to Herbie at the ImageJ/Fiji Forum for his suggestion to find a way to do
//  this for my project.
//  Author: Bruce Moen    Jan 5 2016
************************************************************
open();   // Open any standard ImageJ LUT file
R = 0;    // intialize RedValue (the retrieved R value of RGB)
G = 0;    // intialize GreenValue (the retrieved G value of RGB)
B = 0;    // intialize RedValue (the retrieved B value of RGB)

Ahex = newArray(256);
macro "get RGB Values" { 
    for (i = 0; i < 256; i++) {          // loop thru LUT by row
        getLut(reds, greens, blues);  // get the R, G, B values from a standard ImageJ LUT file
        R = reds[i];     // get Red value of RGB
        G = greens[i];   // get Green value of RGB
        B = blues[i];    // get Blue value of RGB
        cAlpha = 100;           // Opacity value (0-100%, 100 = solid color)
        r = toHex(R); g = toHex(G); b = toHex(B);
        fAlpha = toHex(255*cAlpha/100);
        hex= "#" + pad(fAlpha) + ""+pad(r) + ""+pad(g) + ""+pad(b);
        Ahex[i] = hex;
        String.resetBuffer; String.copy(hex);

        function pad(n) {
            n = toString(n);
            if(lengthOf(n)==1) n = "0"+n;
            return n;
        }  
    }
    //Array.print(Ahex);  // Remove "//" before "Array.print(Ahex);" to print the entire array
    Z = Ahex[254];   //  This is a test just to show how to access the hex values
    print(Z);        //  This prints the result of the test in the previous line
}     
1 Like

Stuck again.

No matter what I try my “should be” multi-colored RGB image always comes out as black and white instead of multi-colored as it should. It must be something simple, but nothing I try works. Maybe someone here will see my error?

I have an array, storepix, that contains the pixel intensity values of my 16-bit, grayscale image. Another array, Ahex, contains the LUT r, g, b data as single hexadecimal values. ReLo is a threshold value.

The code below gets the grayscale value, “pix”. It calculates “InDex” correctly. The “(print( i, j, hexcolor)” shows that the hex values are correct.

But. the output image is always black and white, and I don’t understand why?

I’d appreciate some advice.

Thanks,

Daddymoen


  for (i=0; i<(w); i+=1)  {
 	for (j=0; j<(h);  j+=1)  {
         pix = storepix[i+(j*w)];  //  get pixel value of grayscale array, storepix, at (i, j)
         if (pix >= RedLo) { 
         	   InDex = (pix - RedLo + nudge); // InDex is LUT row number
               hexcolor = Ahex[InDex]; //  the hexidecimal value of LUT
                  setPixel(i, j, hexcolor); //  put 0x in front of hex number
                  print(i, j, hexcolor);   
                     if (pix < RedLo) { 
          	     InDex = (pix - RedLo + nudge); // InDex is LUT row number 
          	      setPixel(i, j, 0xc0c0c0);   
          }                     
       }
    }
updateDisplay(); 
  }
saveAs("jpg");
// saveAs("tif");
close();

Daddymoen,

AFAIK your problems are at least partly not image-related.

For example:

if (pix >= RedLo) { 
        // some code
         if (pix < RedLo) { 
                // some code
         }  
 }

The code following the second if-condition will never be executed.

setPixel(i, j, hexcolor); //  put 0x in front of hex number

Does this comment really apply to this code line?

Furthermore, your code snippet doesn’t make clear how you go from a 16bit graylevel-image to an 24bit RGB-image.

Best

Herbie

Herbie,

Thanks, the RGB issue was the problem, an embarrassingly rookie mistake! After correcting that one and changing the order of the setPixel commands it’s working. I’m a little puzzled about the order of those commands.

I expected the original order would recolor pixels <(less than the threshold) to the hex value I provided. Failing that test (pixels greater than the threshold) I expected the macro would fall through to the next command within the “j” loop, coloring the pixels above the threshold. But as you correctly point out, it doesn’t work that way. It looks like failing the first test causes the macro to skip any commands after the fail and go straight to the next “j” increment of the loop. I can hear the macro writing ancestors whispering, “Rookie” :d) Something for this novice to remember.

I’m unstuck and making progress again.

Thanks Herbie,

Daddymoen