Additional Flags for ImageLoad
jjweimer
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)
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
// 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:
•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.
December 23, 2019 at 03:26 pm - Permalink
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.
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.
December 23, 2019 at 04:43 pm - Permalink
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)
December 23, 2019 at 04:55 pm - Permalink
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]
I have to decrement nChunks by 1 prior to the MatrixOP expression and use this:
MatrixOP/O img_red_st = imgrawsource[][][0,nChunks,3]
December 26, 2019 at 07:44 am - Permalink
So, I now have this:
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)):
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!
December 26, 2019 at 02:44 pm - Permalink