NIH LISTSERV
NIH LISTSERV
IMAGEJ archives -- November 2002 (#5)

Go to: Previous Message | Next Message
Previous in Topic | Next in Topic
Previous by Same Author | Next by Same Author
Previous Page (November 2002) | Back to Main IMAGEJ Page


Options: Reply | Post a New Message | Join or Leave IMAGEJ, or Change Options | Search
View: Chronologically | Most Recent First | Wrap Text (Proportional Font) | Don't Wrap Text (Non-proportional Font)
*

Message-ID:  <[log in to unmask]>
Date:         Tue, 5 Nov 2002 08:56:35 -0500
Reply-To:     ImageJ Interest Group <[log in to unmask]>
Sender:       ImageJ Interest Group <[log in to unmask]>
From:         Bill Bug <[log in to unmask]>
Subject:      Help - need to force LUT application for 16-bit greyscale PNG
              images

Dear ImageJ folks, Many thanks to Wayne and all the others who've helped to make ImageJ such a unique, powerful & flexible tool!!! I've been away from scientific imaging & 'NIH Image' for about a decade and simply can't believe what a powerful tool has evolved out of these efforts. The plugin architecture and scripting features especially make ImageJ an extremely powerful lab automation tool! Thanks, again. Now my question: We are capturing 12-bit grayscale images via NI's LabView. The only format we are currently able to save them in is PNG. Unfortunately, we don't currently have an NI product enabling us to view & manipulate these images. That's where ImageJ comes in. Using the Java Advanced Imaging I/O plugin (http://ij-plugins.sourceforge.net/jai-imageio.html), we open these images in ImageJ. There are two things we need to do in ImageJ. 1) We need to visually identify the regions of the image coming close to the limits of the sensor's 12-bit range - those pixels below 100 and above 3950. Our quick solution was to build a LUT with entries below 6 ((255 * 100)/4096) set to R:255|G:0|B:0 and entries above 247 ((255 * 3950)/4096) set to R:0|G:0|B:255. We then used the 'LUT Importer' plugin to apply the LUT to the images, so that low-end pixels show up red and near-saturated pixels show up blue. 2) Our other requirement is to visually compare one image to another during the acquisition process. This requires each image to be displayed using the same LUT applied with an identical transfer function. An object 'appearing' twice as bright across two ImageJ images should in fact - once you account for the non-linearity of visual perception - be twice as intense according to the underlying pixel data values. Both of these tasks require a given LUT be applied to a set of identical bit-depth images in an identical manner. For instance, the full 0 - 4095 range of our 12-bit grayscale images would first be scaled to 0 - 255, then the display value would be pulled from the LUT. Please correct me if I've got this wrong, but I don't believe this is how LUTs are applied in ImageJ. As I understand it, our 12-bit images are instantiated as ImagePlus objects in ImageJ with a ShortProcessor member object to handle all processing of the underlying image data including LUT translation and display. My brief perusal of the ImageJ source code, leads me to believe LUT translation is performed in the following member function: ShortProcessor.createImage() /** Create an 8-bit AWT image by scaling pixels in the range min-max to 0-255. */ The translation occurs in the following lines found within this function: ... int value; double scale = 255.0/(max-min); for (int i=0; i < width*height; i++) { value = (pixels[i]&0xffff)-min; if (value<0) value = 0; value = (int)(value*scale); if (value>255) value = 255; pixels8[i] = (byte)value; } ... This new 'pixel8 array is then passed to the constructor for the 'MemoryImageSource' object stored in the ShortProcessor.source member variable used to as an off-screen buffer for displaying the image. The LUT transfer function given above is: DATA RANGE = ( DATA MAX ) - (DATA MIN) SCALING FACTOR = 255.0 / ( DATA RANGE ) LUT INDEX = ((DATA VALUE) - ( DATA MIN ) ) * ( SCALING FACTOR ) The final value is then truncated within the range of 0 - 255, to insure no value lies outside the 8-bit integer range. This 8-bit integer is then used as the index into the LUT to find the actual display value. Both of our above requirements would require that this scaling algorithm be applied across the fixed range 0 thru 4095 without using the DATA MINIMUM as an offset. Applying the algorithm as it appears in 'createImage' will always set the lowest pixels to red and the highest pixels to blue, regardless of their absolute values. I tried to 'trick' the algorithm into doing what we need by artificially setting the bottom left pixel to '0' and the bottom right pixel to '4095'. This did not change the appearance of the image. However, when displaying the intensity histogram, the LUT band shown at the bottom did appear correct with the 'red band' running from 0 - 100 and the 'blue band' running from 3950 - 4095. The ShortProcessor.applyTable() member function seems like it might also be relevant to this issue, but I can't quite tell how. It appears to transform the underlying pixel data array according to entries in a LUT with 65536 entries. This method is called at the end of the super class ImageProcessor.process() method after performing the requested image processing function. We'd greatly appreciate any help you all can offer that would help us to achieve our desired result. Again - many thanks for all the wonderful work you've done on ImageJ. Cheers, Bill Bug Bill Bug Senior Analyst/Ontological Engineer Computer Vision Laboratory for Vertebrate Brain Mapping Department of Neurobiology & Anatomy Drexel University College of Medicine 2900 Queen Lane Philadelphia, PA 19129 [log in to unmask] 215 991 8430 (ph)




Back to: Top of message | Previous page | Main IMAGEJ page

NIH LISTSERV Home Page

CIT
Center for Information Technology
National Institutes of Health
Bethesda, Maryland 20892
301 594 6248 (v) 301 496 8294 (TDD)
Comments and Assistance
Accessibility wheelchair icon