Image Tools


This package is presented as a way for users to load, display, and print out summary views from sets of TIFF (or other) images or internally-existing xy/image waves without needing to write code.


Once installed, the package is accessible from the Analysis --> Image Tools sub-menu.

The displayed content is divided as four frames.

  • An image display window shows the currently active image
  • A control bar on the top of the main display sets the parameters in the viewing window
  • A histogram graph shows the histograms for the image being displayed.
  • Operation of the package is done using inputs on a control panel.

Image Control Bar

  • Expand window size to free ..., minimum (showing all controls) [..], or preferred [ ]
  • Change the color scale used to display the image (main and split)
  • Change the image range (contrast adjustments) using sliders or numerical inputs or invert (only for main image)
  • Split view to show two images from current folder side-by-side or top-to-bottom (default)
  • Swap main and split images

Main Tab

Image Displayed
  • Step through images that are loaded as sets using buttons to advance or go backward in the loaded sets.
  • See the image size (pixels) and bit depth.
  • View/Add notes to an image file (wave).
  • Play a movie from a stack
Display Information
  • Shows the positions of the marquee when drawn on the image
  • Toggle on/off the histogram display with linear and log scales as well as cumulative and derivative histograms.
  • Scale the derivative histogram to search for positions of zero crossings (peaks in histogram).
  • Choose a region of interest (RoI) for a sub-set of analysis
  • Choose inside, outside, inside - outside, and outside - inside analysis for histogram
  • See where the RoI is in image coordinates.
  • Lock the RoI to continue using the selection tool on the image.
  • Shows the min/max in the image and in the selected RoI (if present)

Load Tab

Load Image(s)
  • Load a single RGB image, multiple RGB images, a folder of RGB images, or a selection of RGB images from a stack.
  • Load uncompressed or compressed TIFFs as well as other image file formats
  • Do the same to load grayscale images.
  • Load / Convert existing xy waves to a format that can be used within the package
  • Choose to keep the source (or not), to extract any one or all of the RGB channels, and/or to create a grayscale image
  • Create your own image file loader and have it automatically recognized (ask for details)

Calibrate Tab

Calibrate XY
  • Set a calibration factor for pixel, image width, or image height to apply locally or globally
Calibrate Intensity
  • Invert, remove negatives, remove outliers, normalize (by height or flux density), and apply an equation using "I" for intensity as well as "x,y" for position
    Example Equations: (I^2) will square the intensity or (I < 20 ? 0 : I) will set all intensity values below 20 to zero

Process Tab

Remove Background
  • Manually set or edit grid points that denote the background locations
  • Create NxM grids that ignore marquee regions (rectangle or oval), threshold, or fill regions
  • Apply an operation to remove a background having various plane orders through the grid points
  • Remove a zero order plane to subtract the minimum value from the image
  • Apply a thresholding method to one image, each image, or all images in a stack
  • Select various threshold methods as documented in the Igor Pro options, including manual or range 
  • Fill the threshold
Mask Image Regions
  • Use drawing regions, the marquee, a threshold image, or a fill image to highlight regions of interest
Stack Math (for Image Stacks)
  • Average + Standard Uncertainty, Derivative, or Integral over the stack
Split Math (when view is split)
  • Add, Subtract, Multiply, Divide with left (operation) right. Process only displayed or process selectively for stacks.
  • Input equation using L (left) and R (right) for split math operation.
Crop to Marquee
  • Crop using the marquee to exact or to smallest feature

Publish Tab

  • Turn on/off axes
  • Turn on/off scale bar and set its location / color
  • Store the image to a list to use for a layout (with tags as desired) or a contact print format
  • Allow the layout image to update dynamically as changes are made to the main image


  • This package has been developed for analyzing single-channel images. It may do some things correctly with RGB images or 4-stack images, however no guarantees are given for these types of images. Convert RGB or 4-stack images to grayscale or read only each individual channel accordingly.
  • This program can load image stacks (TIFF movies). That does not however mean that it will handle them all with equal efficiency. Load larger files as stacks using the selections to load only a certain range in the movie and/or to load only a certain sequence (e.g. every 10th image).

Further Help

Tutorial videos for portions of this package are available at either link below.

Dropbox Link to Video Tutorials

GoogleDrive Link to Video Tutorials


Image Tools v3.80 Image Tools v3.00

Project Details

Current Project Release

Release File: Image Tools (201.7 KB)
Version: 4.00
Version Date:
Version Major: 4
Version Patch Level: 00
OS Compatibility: Windows Mac-Intel
Release Notes:

Squashed Bugs

● changing the color for the background points no longer gives error if background points are not present
● background points now honor the color setting when being placed manually for the first time
● background method to ignore threshold now properly uses threshold rather than fill
● starting the mask processing now properly turns off control bar

Improved Code

● setting background points now works solely from the root directory
● threshold can be set to fractional values down to zero
● threshold, fill, background, mask (and eventually all other) processing results now go to the split view rather than replacing the main view

Improved UI

● min, max, ave, and stdev values on panel now show decimal points as needed
● adjusted positions and naming for some controls on the panel

Added New Features

● you can define your own image file loader (ask for information)
● you can remove a ZERO order plane as background —> subtracts minimum from image
● you can set image scale contrast ranges using numerical set variable inputs
● you can show split views at right or at bottom (used as starting default)

Known Issues

● you may need in some cases to click off and back on the panel to set or reset buttons or values
● Igor Pro line profile menu do the line profiles at the split view window on bottom

View All Releases

I would be grateful to hear from folks who find this package useful, who would like to see features added to it, or who would like to contribute to its development. Please contact me with comments here or via a direct email.

JJ, while I don't use your tool (yet) I took a look how things are done in your code. ;) I found a few bugs and inconsistencies, so I thought you might want to know about them. Here is a (non-exhaustive) list of what I found so far:

1) the include statements fail if not all the procedures are inside the standard procedures folder. I often rather want to have just a shortcut to the main procedure (Image Tools Main.ipf in this case) and leave all the rest somewhere else. This would work if you would provide relative paths to the included files, e.g.,

#include ":Supporting:Image Tools Headers" instead of #include "Image Tools Headers" within Image Tools Main.ipf
#include ":Image Tools Background" instead of #include "Image Tools Background" within Image Tools Process.ipf

and so on.

2) I am not such a fan of creating stuff upon start of every experiment. Why do you want to initialize the package upon start? It might be better to initialize the folder structure upon first start.

3) line 384 in Image Tools Main.ipf: Missing /Z flag in

wave swave = $lwfile

4) The controls overlap and have an inconsistent font size on Windows (see attachment).

5) Toggling marquee 'lock' on and off shifts the marquee area down a bit each time.

6) If I click the |< button directly after start, the 'Folder' popup menu appears, which is broken at this stage.

7) I think do_strsplitmath() has a possible bug: If the name of limg contains an 'r' the command execution would break, since all 'r's are replaced by the name of rimg.

8) If I switch loading to Internal Data Folder, press Convert but then cancel I get an error.

9) Related to 8, I then can click through the different tabs without a proper wave loaded, which breaks all kinds of things. The tab controls need hard checks if / when they are safe to be activated.

Image Tools panel.png (27.47 KB)

@chozo -- Thanks. I agree, parts of the code may need a robust sanity check. A few quick notes ...

1) I prefer to "hide" supporting procedures in a folder within the main folder. I'd not considered this would cause disruption using your approach. I'll implement the relative file path designation to allow it.

2) I should only be checking behind at the start of each experiment to discover whether the Image Tools procedures have been updated. I'll make sure this is the case.

4) Ah yes, Windows. I'll have to fire up my Parallels version and adjust.

5) I've fought with the distinctions in placement of a marquee as pixels versus axes versus graph coordinates until my head spins. I'll revisit this.

3, 6-9) I should hope to tackle these issues ASAP.

I think you've given me my plans for the upcoming week, and I'm looking forward to the non-non-exhaustive list. :-)

Great, here's more. :)

1) The #include issue was not fully resolved yet. You need to put a ':' in front of each statement in Image Tools Process.ipf.

2) ImageLoad is apparently unable to load compressed Tiff images (at least with LZW), so you need to add a /Z flag and handle the loading error (lines 464 ... in Load Tools).

3) The Histogram graph is actually partly outside my monitor area. You might want to calculate the size of the image display and the placement of the histogram view according to the screen size. (This one is a bit tedious, so just if you want to go for it.)

4) Similar to 3, enabling split view can possibly stretch the whole thing far beyond the available screen area.

5) I was trying to load a tiff image now, but the Folder popup and <> buttons never appeared and the loaded image was also not displayed automatically. So I was unable to display the loaded image.

6) I guess it is not intended to save the main graph, so I would use /K=1 when building the graphs for the tool to prevent the dialog.

7) When I lock the marquee and drag a new marquee anyway, all values change to NaN (this may be intended)?

8) When I press 'include' for Contact print without selecting anything in particular, I get an error in line 198 in Publish.ipf

9) When I remove the pre-placed cursor from the histogram, I get an error. Handle that the cursor might be absent or make sure that it always exists (by forcefully readding it). (Also, why is it called B when it is cursor A, or does the B stand for something else?)

10) imgT_bckg... waves are created in the current folder and not in packages (this may be intended?).

11) In split view (using one of the background-subtracted waves), the BW, invert and color controls do not seem to work properly, as they apply to both, just the left or just the right image depending on whether they are toggled on or off.

12) Related to 11, after toggling the BW checkbox and removing the split, I managed to have the wrong image displayed so that the contrast sliders give errors.

13) I just realized you still have the aftercompiledhook() in there, which still creates all data each time a new Igor session is started. Of course, your choice if you want to keep it that way. :)

14) Just curious, your default image gives a highly noisy impression with the rapidly varying sin/cos. I wondered if something less frequent like img_default = 200*sin(x/30)*cos(y/30)+200 would be nice.

That's all for now. I can give it some more testing when the image loading + display works.

In reply to by chozo

Quick comment about Chozo (2) above:

ImageLoad supports reading TIFF images in two branches: Igor's TIFF code and LibTiff.  Igor's TIFF code does not support LZW compression.  If you are working with compressed TIFF it is best to use /BIGT=1.  If that fails to read the image use /RAT to get more information about the file to determine how to proceed.



@chozo -- I'll handle the critical errors promptly. Otherwise ...

2) I'll revise with the /Z and decide what is best to proceed. In the meantime, I suggest loading the compressed tiff in a standard way and using convert folder to add the compressed tiff.

3) and 4) I will eventually prefer to handle this by including a #if compiler reference to check whether the Screen Sizer package is installed in the experiment ( ). It has functions to position windows by fraction of screen size. I'm reluctant rebuild the features in the Screen Sizer toolset again from scratch, especially since I think (pat myself on the back here) that the Screen Sizer package does what is needed in a robust, easy, and intuitive way. In the meantime, 27in+ 4K+ monitors (or MacBook Pro 16in Retina monitors) are great assets to have when you must work with images. :-)

13) The AfterCompiledHook is there to assure that Image Tools handles updates itself properly. The package folder is created from scratch only the first time. After this, the code drops into the imgT_Update() function. This checks the version number of the current against the version number when the experiment was first created. If the version number changed, the package updates itself. I've only had one time that I truly needed to add additional data to the package (perhaps back at the version 1 or 2 stage). I see that I could simply reference back to when this happened and/or check so as not recreate the scaling factors (e.g. if they exist). Otherwise, I still have to drop to an update branch after compiling because sometimes the panel controls change. So I have to also the package to remove and recreate the image + panel. I am curious whether you have an alternative way to resolve the need to handle package updates that do not use a hook function.

3) / 4) It is actually not as tedious as I made it seem. :) Here is some code as a start:

variable TFTResX, TFTResY, pix = 72/ScreenResolution
if (cmpstr(IgorInfo(2),"Macintosh")==0)         // Mac
    string TFTInfo = StringByKey("RECT",ReplaceString(",RECT",StringByKey("SCREEN1",IgorInfo(0),":"),";RECT"),"=")
    TFTResX = (Str2Num(StringFromList(2,TFTInfo,",")) - Str2Num(StringFromList(0,TFTInfo,",")))*(72/ScreenResolution)  
    TFTResY = (Str2Num(StringFromList(3,TFTInfo,",")) - Str2Num(StringFromList(1,TFTInfo,",")))*(72/ScreenResolution)  
else                            // Windows
    GetWindow kwFrameInner wsizeDC
    TFTResX = (v_right-v_left)
    TFTResY = (v_bottom-v_top)
variable WinTop = 50, WinLeft = 250         // screen margins
variable WinBottom  = TFTResY - 250
variable WinRight   = TFTResX - 350
WinBottom = limit(WinBottom, WinTop+300, inf)       // min size
WinRight  = limit(WinRight, WinLeft+300, inf)
NewImage/K=1/N=$k_imgDisplay itd
MoveWindow/W=$k_imgDisplay WinLeft*pix, WinTop*pix, WinRight*pix, WinBottom*pix

Also, you then might want to use within disp_ShowHistograms():

AutoPositionWindow/E/M=1/R=$k_imgDisplay $k_histGraphs

13) I assume you are operating from the POV that the tool will be used when it is (manually) loaded by the user. But I usually have all tools I might use loaded all the time, so some procedures creating data all the time is somewhat undesired. There are many ways to approach that. To roll with your current implementation, how about only running the update function within AfterCompiledHook()? If the updater does not find any folders, this means the tool has not been started => back out quietly without doing anything. This way you never have to do any initialization from this function, which can be solely shifted to the startup of the tool. I personally have update code attached to the window hook functions, however. In general, I also make sure that the code works with all previous graphs/panels ever created in the past which were left open (yes, this can be tiresome at time, I know, but I also did not discover the magic trick to teach my users to properly close tools when they are done).

@chozo - Try v3.40, especially to load compressed TIFFs. A few notes in the meantime ...

1), 5) - 7), 9) fixed
2) try it and let me know (I have no immediate access to compressed TIFFs)
3) and 4) to be addressed later when I have enough motivation to include compiler directives to test for ScreenSizer
8) I suspect this was an issue with something else and this error should not happen again
10) yes, I keep the background waves in the source folder in case someone wants to export just that folder and post-process separately
11) the color scale goes across both but the scalings and invert only work on the main window. This is purposeful to allow comparisons such as .... Is my background corrected image really better than simply adjusting the lower and upper contrast on the main image?
12) the B&W checkbox is removed (perhaps forever or at least until I decide what purpose it really should serve and how to handle it more robustly)
13) see my previous note
14) cool and now implemented!!!!

Follow up -- You were posting when I was.

* I'll look at incorporating your code for window sizings.
* I missed the AutoPosition ... function.
* OK. Now I understand exactly what you mean. I should initialize the package at the menu call, not at compilation. Apologies ... I see the difference once you explained how you operate. I prefer to load procedures only as needed. As to assuring backward compatibility with previous panel controls ... not my cup of tea. I'd rather just kill off an "outdated" panel and redraw the new panel.

Please let me know whether you can load compressed TIFFs. I can implement further changes and any bug fixes as needed for a 3.41 version.

JJ - No, unfortunately compressed images do not load yet. I'll attach a few example files for you to play around with. I think moving to compressed tif would be very beneficial, since the file size can be 1-2 orders of magnitude smaller. To batch compress images you could for example use ImageMagick.

test (47.37 KB)

@chozo -- I was able to load both images, albeit not properly into a single channel grayscale. I could extract the R, G, or B channels.

Let's go off-line. Follow up with me at weimerj at uah dot edu.




Igor Pro 9

Learn More

Igor XOP Toolkit

Learn More

Igor NIDAQ Tools MX

Learn More