Additional Flags for ImageLoad

I have a follow up to this posting:

https://www.wavemetrics.com/forum/igor-pro-wish-list/better-way-read-nu…

I would like to have the following options to ImageLoad.

// sets V_numImages to count of images in stack without reading tags
ImageLoad/C=0/T=TIFF/RTIO=0

// loads a stack from start by step to count
ImageLoad/S=start/CS=step/C=count/T=TIFF

// load a specific channel from a TIFF r,g,b or load rgb as grayscale
ImageLoad/T=TIFF/CH=(r,g,b,gr)

The first new flag setting /RTIO=0 will avoid the need to create and then kill a temporary folder for the tags.

The second new flag setting /CS=step will avoid the need to iterate through sequential steps in a tiff stack using an external for-endfor loop.

The third new flag setting /CH=(r,g,b,gr) will avoid the need to have to do a WaveTransform after loading.

I am also loading single channels from a TIFF stack into individual files and storing them back as a 3D wave stack. Could we therefore have this option too?

// load a stack from start by step to count into a 3D wave
// store the stack as a 3D wave (internal stack)
// works only to obtain single channel stacks
// (i.e. requires /CH flag too)
ImageLoad/S=start/CS=step/C=count/T=TIFF/CH=(r,g,b,gr)/ST

 

Some comments:

1.  I don't see why you would involve the RTIO flag when in fact you are not interested in the tags.  If you are just interested in the number of images (seems reasonable) then ask for a flag for that purpose.  Besides, RTIO applies to the old format TIFF.   This is implemented in IP9 as follows:

imageload/q/t=tiff/RONI   // Read Only Num Images
print v_numimages

2.  TIFF images may be stored in various formats (see PlanarConfiguration Tag 284).  I do not see a compelling reason to add code that converts RGBARGBARGBA into planes so that I can save only the suggested /CH configuration.  ImageTransform or MatrixOP can peel off the desired channel for you rather efficiently.

3.  I do not recall requests for the ability to load stack images using steps.

A.G.

AG

1) That works.

2) The only reason is to avoid the need to pull in the full image into memory, extract only the desired channel, and kill the source. By example, here is what I currently do.

    jc = 0
    for (ic=no;ic<nf;ic+=ns)
        ImageLoad/RAT/P=imgPath/S=(ic)/C=1/Q fname
       
        // clean up file name
        imgname = StringFromList(0,s_wavenames)
        wave source = $imgname
        rename source img_source
        wave img_source
       
        // generate red
        if (ls.red)
            ImageTransform/P=0 getPlane img_source
            wave M_ImagePlane
            if (ic == no)
                rename M_ImagePlane img_red_st
                wave img_red_st
                redimension/N=(-1,-1,nimgs) img_red_st
            else
                img_red_st[][][jc] = M_ImagePlane
            endif
        endif

        ...

        killwaves/Z img_source
        jc += 1

    endfor

When I have a TIFF stack with over 100(s) of images, the entire process will take visible time. I get a spinning wheel to load 40 red channel images from a TIFF stack of 80 images.

3) It is to avoid the time needed in explicit for-endfor loops.

I'll work on my code further to see where I can cut the time.

Thanks.

I guess I would approach it slightly differently:

1.  Load the whole stack into a wave say ddd.

2.  Get the number of chunks in ddd.

Variable nChunks=DimSize(ddd,3)

3.  Redimension/E=1/N=(-1,-1,3*nChunks) ddd

4.  MatrixOP/O redStack=ddd[][][0,numChunks-1,3)

or

  MatrixOP/O greenStack=ddd[][][1,numChunks-1,3)

Thanks AG. I'll work with this and follow up later. In the meantime, these inputs throw a syntax error for some odd reason:

MatrixOP/O img_red_st = imgrawsource[][][0,nChunks-1,3]
MatrixOP/O img_red_st = imgrawsource[][][0,(nChunks-1),3]

I have to decrement nChunks by 1 prior to the MatrixOP expression and use this:

MatrixOP/O img_red_st = imgrawsource[][][0,nChunks,3]

 

So, I now have this:

// load tags and entire stack

    ImageLoad/RTIO/P=imgPath/Q fname
    ImageLoad/P=imgPath/S=(nload)/C=(-1)/Q/N=imgrawsource fname
    wave imgrawsource
    nChunks = DimSize(imgrawsource,3)

// how many images should be kept from stack?
    if (ls.endimage == inf)
        nload = nChunks
    endif

// work on a temporary file (to keep source later)
    Duplicate/O imgrawsource imgtmp
    wave imgtmp
    Redimension/E=1/N=(-1,-1,3*nChunks) imgtmp

// set the step through and the endpoint
    ns *= 3
    nChunks = nload*ns - 1
   
// get components
    if (ls.red)
        MatrixOP/O img_red_st = imgtmp[][][0,nChunks,ns]
        wave img_red_st
    endif
    if (ls.green)
        MatrixOP/O img_green_st = imgtmp[][][1,nChunks,ns]
        wave img_green_st
    endif
    if (ls.blue)
        MatrixOP/O img_blue_st = imgtmp[][][2,nChunks,ns]
        wave img_blue_st
    endif
    if (ls.gray)
        ImageTransform rgb2gray imgrawsource
        wave M_RGB2Gray
        MatrixOP/O img_gray_st = M_RGB2gray[][][0,nChunks,ns]
        wave img_gray_st       
    endif

// keep source?
    if (!ls.source)
        killwaves/Z imgrawsource, imgtmp
    else
        killwaves/Z imgrawsource
        rename imgtmp imgrawsource
    endif

It gives an improvement in loading speed.

My request remains to be able to use the following approach instead (I replaced CH=(r,g,b,gr) with CH=(0,1,2)):

// get tags
    ImageLoad/RTIO/P=imgPath/Q fname
   
// get components
    if (ls.red)
        ImageLoad/P=imgPath/S=(no)/CS=(ns)/C=(nf)/Q/CH=0 fname
        rename $fname img_red_st
        wave img_red_st
    endif
    if (ls.green)
        ImageLoad/P=imgPath/S=(no)/CS=(ns)/C=(nf)/Q/CH=1 fname
        rename $fname img_green_st
        wave img_green_st
    endif
    ...

I hope this approach might find its way into Igor Pro 9.

Thanks for the recommendation!