Macro to save snapshot/ outline files based image name after performing particle measurements

Hello Image-Pro Plus programmers: I just recently started to use Image-Pro Plus (version 7) to perform particle analysis on images captured using light microscopy.  My goal is to write a macro that reads images from a folder (perhaps up to 100+ images/ folder), perform pre-filtering (e.g. HiPass), threshold, measure 10+ parameters for each particle in the image, save a snapshot of the particle outlines/ numbers, save the outlines file (.scl), record the particle measurements in the Data Recorder, and finally export the measurement data to a text file for analysis in R.  <?xml:namespace prefix = o ns = "urn:schemas-microsoft-com:office:office" />

I have used the macro recorder, Data Collector and the Batch Process plug-in to get most of the way there (see code below).  The issue that I have is how to write a for loop (or other coding method) that saves the snapshot image and outlines file as the image name including the addition of “_outlines” to the name: e.g. Image1_outlines.scl and Image1_outlines.tif.  Note the image names are more complex; I simplified them for the example. 

Note the lines for saving the image/ outline files are hard-coded to save only a single name, not one that assigns a name that is based on the actual image/ file name.

ret = IpSCalSelect("10x_0.3NA_LU_Plan") ‘this assigns magnification calibration
ret = IpFltHiPass(3, 10, 1) ‘ applies an initial hi-pass filter to image
ret = IpBlbCount() ‘performs particle size/ count measurements
ret = IpBlbUpdate(0) ‘
ret = IpDcSet(DC_AUTO, 0) ‘Data Collector
ret = IpDcUpdate(DC_FETCH) ’collects data using Data Collector
ret = IpBlbSaveOutline("C:\Documents And Settings\jhietpas\Desktop\Images\Processed\Image1_outlines.scl") ‘saves outlines file to folder
ret = IpSnap() ‘snaps an image of the particle outlines/ numbers
ret = IpWsSaveAs("C:\Documents And Settings\jhietpas\Desktop \Images\Processed\Image1_outlines.tif", "TIF") ‘ saves the snapshot to folder
ret = IpDocClose() ‘ closes the image after analysis

Thanks very much for any information/ help you can provide,



  • Hi Jack,

    You can use batch processing macro to do your loop. Check this link

    The ProcessDirectory() macro will load images one by one, you will have file names from there (fName). You just append the extension you need (".scl") to save your output files.

  • edited May 2014
    What you are asking for is essentially how to work with the file name strings to generate the names you wish. Attached is some sample code for string handling.


    fileName: C:\IPWIN70\Images\DemoBlue.TIF
    extension: TIF
    baseName: C:\IPWIN70\Images\DemoBlue
    dirName: C:\IPWIN70\Images\
    name_Script: C:\IPWIN70\Images\DemoBlue_outlines.scl
    name_Image: C:\IPWIN70\Images\DemoBlue_outlines.TIF

  • Sorry, I didn't attach the macro properly:
  • Hi Kevin- Thank you very much for your help, I really appreciate it!  Sorry for the delay in getting back to you.  I have incorporated your code into mine (below).  It is working very well, the image and the outline files are being properly labeled and saved!  The only question that I have is that I have to select each image individually from the directory.  Is there a way to only select one of the images and have the code use all the images in the selected directory?  I have been trying to figure this out myself using parts of the Batch_Process script (Yuri's suggestion)... but failing miserably.   Do you have any suggestions?  Thanks again for your help.



    'Dim Firstfile As String
    'Dim Formattype As String
    'Firstfile = "C:\Documents and Settings\jhietpas\Desktop\Images\Image1.TIF"
    'Formattype = "TIF"
    'ret = IpWsLoad(Firstfile, Formattype)
    Dim fileName As String, dirName As String
    Dim extension As String, baseName As String
    Dim name_Script As String, name_Image As String
    Dim delim As Integer
    fileName = GetFilePath(, , , , 0)
    If fileName = "" Then Exit Sub
    ' Chop up the file name using searches for "." and "\" delimiters
    delim = InStrRev(fileName, ".")
    extension = Right(fileName, Len(fileName)- delim)
    baseName = Left(fileName, delim - 1)
    delim = InStrRev(fileName, "\")
    dirName = Left(fileName, delim)
    ' Build new file names for later use
    name_Script = baseName + "_outlines" + "." + "scl"
    name_Image = baseName + "_outlines" + "." + extension
    ' Output results
    'Debug.Print "fileName: "; vbTab; fileName
    'Debug.Print "extension: "; vbTab; extension
    ' Debug.Print "baseName: "; vbTab; baseName
    ' Debug.Print "dirName: "; vbTab; dirName
    ' Debug.Print "name_Script: "; vbTab; name_Script
    ' Debug.Print "name_Image: "; vbTab; name_Image
    ' Debug.Print ""
    'ret = IpSCalSelect("4x_0.2_NA_Nikon")   
    'ret = IpSCalSelect("10x_0.45_NA_APO_Nikon")   
    ret = IpSCalSelect("20x_0.75_NA_APO_Nikon")   
    ret = IpFltHiPass(3, 10, 1)   
    ret = IpBlbSetAttr(BLOB_CLEANBORDER,1)   
    ret = IpBlbCount()   
    ret = IpBlbUpdate(0)   
    ret = IpDcShow(3)   
    ret = IpDcSet(DC_AUTO, 0)   
    ret = IpDcUpdate(DC_FETCH)   
    ret = IpBlbSaveOutline(name_Script)   
    ret = IpSnap()   
    ret = IpWsSaveAs(name_Image,"TIF")   
    ret = IpDocClose()



  • The code in Batch_Process.ipm, specifically Sub ProcessDirectory( ), implements just such a loop. Calling Dir(directory + "*.*) returns the first matching file, calling Dir( ) again gives the next in alphabetical order. In that macro the following steps are performed:
    • Initialize to a reasonable starting path
    • Select a file in the desired directory
    • Extract the directory path from the file
    • Search for files in that directory, looping through all
    • For each of those files call a processing macro
    • End when no more files can be found (returned file name is "")
    You can use the ProcessDirectory( ) routine as a base for your work - copy it into your script file, put your setup code into one macro, your calibration/filtering/counting into another, and insert calls to those in the lines of ProcessDirectory( ) marked with '***'. You will be replacing the example DoStuff call with your own. That's how that example code is intended to be used - you need no other changes to do looping over all files in a directory. 

    As a programming note, I strongly suggest that you break your code up into separate routines. One for overall loop control, one for setup (printing your column labels, for example), one for processing that's called for each image, and if desired one for cleanup/reporting. Smaller pieces are easier to understand, and to swap in/out as needed. Add comments (lots!) describing what you are doing with the code, plus empty lines and indentation to show the workflow. 

    A single unindented block of code rapidly becomes unreadable, and impossible to maintain or reuse. And you may end up just rewriting it for the next experiment, discarding all the effort, because you cannot understand what it's doing. 
Sign In or Register to comment.