Converting 16-bit signed tiffs to 16-bit unsigned

Updated from original

I have begun to understand signed and unsigned image data. The data is collected in ScanImage as 16-bit signed to include noise in the histogram, as noise can be centred around low negative values/zero. I think the previous versions of this software that I have used collected data as unsigned 16-bit.

I am running in to a problem with plugins such as MultiStackReg, which pad the image with zeros, but in this case, the true zero is -2^15 (half of 16-bit). So once the image has been registered I have a problem with my LUTs trying to auto-contrast to include these negative values.

Is there an easy way to convert the data from signed 16-bit to unsigned 16-bit?

I’ve converted to 32-bit and back to 16-bit and this seems to solve the problem, I’m not entirely sure, but is that a viable solution?

Thanks,

Rob

In addition to the above question, it seems the LUT problem is a separate one altogether. When switching between channels in a hyperstack (4D or 5D) the LUTs reset for both channels to make min/max 0 and 2^16. How can I stop the LUTs resetting every time I switch channels?

ImageJ has a command (Plugins>Filters>Signed 16-bit to Unsigned) that converts 16-bit signed images to unsigned. It is implemented by this JavaScript:

  // This script implements the Plugins>Filters>Signed 16-bit
  // to Unsigned command, which converts signed 16-bit 
  // images and stacks to unsigned.
  imp = IJ.getImage();
  stack = imp.getStack();
  if (stack.isVirtual())
     IJ.error("Non-virtual stack required");
  cal = imp.getCalibration();
  if (!cal.isSigned16Bit())
     IJ.error("Signed 16-bit image required");
  cal.disableDensityCalibration();
  ip = imp.getProcessor();
  min = ip.getMin();
  max = ip.getMax();
  stats = new StackStatistics(imp);
  minv = stats.min;
  for (i=1; i<=stack.getSize(); i++) {
     ip = stack.getProcessor(i);
     ip.add(-minv);
  }
  imp.setStack(stack);
  ip = imp.getProcessor();
  ip.setMinAndMax(min-minv, max-minv);
  imp.updateAndDraw();
1 Like

In addition to the above question, it seems the LUT problem is a separate one altogether. When switching between channels in a hyperstack (4D or 5D) the LUTs reset for both channels to make min/max 0 and 2^16. How can I stop the LUTs resetting every time I switch channels?

How can we reproduce this problem? I do not see it with the 4D and 5D hyperstacks in the File>Open Samples menu, such as Confocal Series and Mitosis.

ImageJ has a command (Plugins>Filters>Signed 16-bit to Unsigned) that converts 16-bit signed images to unsigned. It is implemented by this JavaScript:

What update site do I need to have active to get this plugin? I’ve done a quick search of commands and I don’t currently have this on my FIJI, can’t find it with a google search.

How can we reproduce this problem? I do not see it with the 4D and 5D hyperstacks in the File>Open Samples menu, such as Confocal Series and Mitosis.

Concerning the LUT problem, I’m trying to find a way to reproduce it faithfully, at the moment it seems to be only happening to my 16-bit signed 4D stacks sometimes, and I’m not sure why. The signed to unsigned plugin might solve my problems, but I’ll keep trying to find a faithful way to reproduce this and update here if I find one.

Edit: I think it is when I set the LUTs ‘unsigned 16-bit range’ to be something other than ‘automatic’ for my signed 16-bit images, is the problem just that imageJ doesn’t deal with signed 16-bit images?

Edit 2: The above can be reproduced in the sample ‘Mitosis’

Good day Rob Lees,

concerning your first question, Wayne has posted the necessary script for you. You may paste it to an empty JS-window (Plugins > new > Javascript). If you prefer to install the script, then you will find it at:

https://imagej.nih.gov/ij/macros/js/

(scroll down the page)

HTH

Herbie

1 Like

Apologies for my ignorance! I assumed @Wayne meant that is should already be installed in my ‘Plugins’ folder and provided the script to show me what it does.

concerning your first question, Wayne has posted the necessary script for you. You may paste it to an empty JS-window (Plugins > new > Javascript). If you prefer to install the script, then you will find it at:

I use IJ1 macro language for everything I do in FIJI and I’m unfamiliar with ways of implementing a JavaScript to batch run on my images. I have saved the .js in my plugins folder, the best way I can find of batch processing my images is to use runMacro([insert .js path here]) in an IJ1 macro - is this a reasonably good way to do it?

[…] is to use runMacro([insert .js path here]) in an IJ1 macro - is this a reasonably good way to do it?

Works for me – go ahead!

Herbie

The plugin provided by imageJ converts the image, but by doing so it also does a kind of normalization. Therefore the resulting image has different values than original.

I have modified the code slightly, so that it only converts the image. I pasted the code below. (Disclaimer: I have no background knowledge, but the code seems to work for me.)

// This script implements the Plugins>Tools>Signed 16-bit to 
// Unsigned command.  What it does is convert signed 16-bit 
// images and stacks to unsigned.
// Modified by Matevž Bokalič, UL FE, 7.12.2020 
//  - removed normalization: now it does what it should actually do. Only converts, nothing else.

  imp = IJ.getImage();
  stack = imp.getStack();
  if (stack.isVirtual())
     IJ.error("Non-virtual stack required");
  cal = imp.getCalibration();
  if (!cal.isSigned16Bit())
     IJ.error("Signed 16-bit image required");
  cal.disableDensityCalibration();
  ip = imp.getProcessor();
  min = 0;
  max = 32767;
  stats = new StackStatistics(imp);
  minv = 32768;
  for (i=1; i<=stack.getSize(); i++) {
     ip = stack.getProcessor(i);
     ip.add(-minv);
  }
  imp.setStack(stack);
  ip = imp.getProcessor();
  ip.setMinAndMax(stats.min-minv, stats.max-minv);
  imp.updateAndDraw();