Correcting a signed 16-bit grayscale image to exact signed 16-bit values

Hello and good afternoon.

I’m using ImageJ 1.53g59 and I need to adjust the ‘brightness’ and ‘contrast’ values (as in Ctrl+Shift+C) of a grayscale image in such a way that it’s dynamic range may be constrained to EXACT signed 16-bit values (e.g. 0 and 65535 becoming -17441 and 23015 respectively), but unfortunately the controls on this particular tool aren’t precise enough for this manner of fine tuning and I’m somewhat at loss as to how to ‘macro’ my way out of this.

The image is already in signed 16-bit format, and whether or not the computations are internally carried out with floating point precision (hopefully it will be at least 16-bit as suggested by the documentation) is not an issue so long as the output is indeed, ranged to the exact values.

Any help would be greatly appreciated.
Best regards and sorry any inconveniences.

I don’t know what you want to archive. However here is a an explanation of an older thread in the ImageJ mailing list (see the answer of @schmid):

looks like a task for Analyze>Calibrate; select “straight line” as a calibration function:
Enter 0 and 65535 in the left column, -17441 and 23015 in the right column.
[Note, however, that 65535 is not a signed 16-bit value, signed 16-bit values are between -32768 and +32767, but you should enter unsigned values here anyhow]
It won’t change the pixel values, but the calibrated values. The calibrated values are used for measurements, profile plots, etc.
If you want to change the pixel values (required, e.g., if you want to multiply the pixel values by a constant or by another image), convert to 32 bits thereafter.

Concerning the B&C panel: You can enter precise values when pressing the ‘Set’ button.

The Macro Recorder (Process>Macros>Record) should work for these commands, so you can use it to translate your clicks to the macro language.


Use the Set button in the Image>Adjust>Brightness/Contrast dialog to set the display range to exact values. The following macro was generated by the recorder (Plugins>Macro>Record) when I used the Set button to set the display range of the File>Open Sample>CT signed 16-bit sample image to -400 to 150.

  run("CT (16-bit DICOM)");
  run("Out [-]");
  run("Out [-]");
  setMinAndMax(-400, 150);
  run("Show Info...");

Alright. Sorry about the delay and thank you all for the suggestions; I was finally able to do exactly what I needed to do.

Here’s the scenario in case anybody’s still curious:

I’m servicing this old MRI scanner from early 90’s (actually a prototype, not the finished product) which utilizes a 12-bit grayscale LUT loaded from disk. Unfortunately the LUT got corrupted due to disk rot so it had to be reconstructed from the indications in the manual. While the LUT itself was stored in a 16-bit format because of byte size, the DAC can only handle these compressed 12-bit values which are then expanded to full 16-bit values much like a PC’s VGA output did with 6-bit color palettes back in the day. Correction (specifically dynamic range compression) of the output values was therefore required in order to avoid a variety of visual artifacts during display.

But why not correct with 8-bit values directly? wouldn’t that yield a practically identical result? Turns out the ROM actually goes through every single entry in the LUT upon startup, and anything outside a very, very tight range, causes the bootup sequence to fail altogether. It’s not not even a checksum, which’s what I figured at the beginning; it’s actually a very precise test that demands EXACT 16-bit values in this particular format.

Ultimately the missing piece of the puzzle was the calibration trick suggested by Michael Schmid, though I still had figure out the exact sequence of actions necessary for the changes to stick correctly, which thing was made a bit more complicated than necessary due to ImageJ auto-correcting said values in the background, which of course may be a desirable default for the type of work this beautiful piece of software was originally intended to perform, but it certainly almost had me.

Best regards.