Image Montage

This snippet is designed to take a TIFF stack and array it into a montage of m rows x n columns. You can specify the grouting between each image. The code works for 8bit grayscale and RGB TIFF stacks. Unfortunately, I think this will only run on Igor Pro 7 due to the /RMD flag in Duplicate. Any updates will happen over at github. I wrote this because the command to make a montage in ImageJ had a bug, which has since been fixed. I'm posting this here in case it is useful for anybody.
// Menu item for easy execution
Menu "Macros"
    "Make Montage...",  MontageSetUp()
End

// Requires 8-bit images. Will accept RGB and grayscale.
// Triggers load of TIFF stack for making montage
Function MontageSetUp()
    ImageLoad/O/Q/T=tiff/S=0/C=-1/LR3D/N=masterImage ""
    WAVE/Z masterImage
    if(!WaveExists(masterImage))
        Abort "Image load error"
    endif
    Variable nSlices = V_numImages
    if(nSlices < 2)
        Abort "Must have two or more slices"
    endif
   
    Variable rr=1,cc=1,gg=0
    String usrmsg = "        (note that your stack has " + num2str(nSlices) + " slices)"
    Prompt rr, "Rows:" + usrmsg
    Prompt cc, "Columns:"
    Prompt gg, "Grout (px):"
    DoPrompt "Montage details", rr,cc,gg
    if(V_Flag == 1)
        Abort "The user pressed Cancel"
    endif
   
    if(rr == 0 || cc == 0)
        Print "Rows or columns must be > 0"
        return -1
    elseif((rr * cc) < nSlices)
        Print "Montage shows first", (rr * cc), "slices only."
    elseif((rr * cc) > nSlices)
        Print "Montage has", ((rr * cc) - nSlices), "blanks."
    endif
   
    MontageMaker(masterImage,rr,cc,gg,S_path)
End

//This procedure works in Igor 7.0 and later
////    @param  masterImage TIFF stack to be split
////    @param  nRows           Montage will be nRows tall
////    @param  nColumns        Montage will be nColumns wide
////    @param  grout           Pixels of grouting between panels (no border)
////    @param  pathString  String containing path to original TIFF stack
Function MontageMaker(masterImage,nRows,nColumns,grout,pathString)
    Wave masterImage
    Variable nRows,nColumns,grout
    String pathString
    NewPath/O/Q imagePath, pathString
   
    if(!WaveExists(masterImage))
        Print "Image does not exist"
        return 0
    endif
   
    Variable tSize = dimsize(masterImage,3)
    Variable zSize = dimsize(masterImage,2)
    Variable xSize = dimsize(masterImage,1)
    Variable ySize = dimsize(masterImage,0)
    Variable x1 = (xSize * nColumns) + (grout * (nColumns-1))
    Variable y1 = (ySize * nRows) + (grout * (nRows-1))
    Variable nLayers
    if(tSize == 0)
        // case where there are no chunks assume BW stack
        nLayers = zSize
        Make/B/U/O/N=(x1,y1) newMontage = 255
    else
        // if there are chunks then assume RGB stack
        nLayers = tSize
        Make/B/U/O/N=(x1,y1,zSize) newMontage = 255
    endif
   
    Variable xPos=0,ypos=0
    Variable i,j
   
    for(i = 0; i < nLayers; i += 1)
        xPos = mod(i,nColumns)
        yPos = floor(i/nColumns)
        x1 = (xSize * xPos) + (grout * xPos)
        y1 = (ySize * yPos) + (grout * yPos)
        if(tSize == 0)
            Duplicate/O/FREE/RMD=[][][i,i] masterImage, subImage
            ImageTransform /INSI=subImage/INSX=(x1)/INSY=(y1) InsertImage newMontage
        else
            for(j = 0; j < 3; j += 1)
                Duplicate/O/FREE/RMD=[][][j][i,i] masterImage, subImage
                ImageTransform/P=(j)/INSI=subImage/INSX=(x1)/INSY=(y1) InsertImage newMontage
            endfor
        endif
    endfor
    KillWindow/Z result
    NewImage/N=result newMontage
    KillWaves masterImage
    ImageSave/P=imagePath/T="tiff" newMontage
End

Forum

Support

Gallery

Igor Pro 8

Learn More

Igor XOP Toolkit

Learn More

Igor NIDAQ Tools MX

Learn More