![](/profiles/wavemetrics/themes/wavemetrics/logo.png)
Code for TIFF export
![](/sites/default/files/styles/thumbnail/public/images-imported/picture-18.jpg?itok=Xf2urm6F)
jamie
Exporting a TIFF image with Igor Script Alone
This function exports a multiplane greyscale tiff from a 3D wave. Igor at one point didn't export multiplane TIFFs "out of the box'. Before that, it didn't import them, either, but I have lost my TIFF import procedure.
This function handles waves of different bit depths, signed or unsigned, and sets the tags appropriately so other apps will know how to open it, if they support it, that is. I have tested 8 and 16 bit signed and unsigned integer and 32 bit floating point import into ImageJ.
This should work with Igor Pro version 4, though I haven't recently recently tested it, not having version 4 lying around.
Function ExportGreyScaleTIFF (datawave, ExportPath) wave DataWave //reference to a 2 or 3d wave with greyscale information String ExportPath //contains the name of an Igor Path where the file will be saved //make sure the wave exists if (!(WaveExists (dataWave))) doAlert 0, "Sorry, but the wave, " + nameofwave (datawave) + ", does not exist." return 1 endif //Check the path PathInfo $ExportPath if (V_Flag == 0) if ((cmpStr (ExportPath, "")) == 0) ExportPath = "ExportPath" endif NewPath /M="Where do you want to save the TIFF?" /O/Q ExportPath if (V_Flag) // User cancelled the dialog to make new path return 1 endif endif //check wave diminsions. 1D and 4D waves are no-go. variable imdims = wavedims (datawave) if (imdims == 1) doalert 0, "Sorry, but you need an image or an image stack to write a tiff file." return 1 else if (imdims == 4) doalert 0, "Sorry, but this procedure hasn't been extended to 4 dimensions yet" return 1 endif endif // No Complex waves if (WaveType(Datawave) & 0x01) doalert 0, "Sorry, but this procedure doesn't do complex waves." return 1 endif //Make a name for the exported tiff from the wavename plus the tif extension String FileNameStr = nameofwave (datawave) + ".TIF" // Check the file name/location for existence FileNameStr = CheckFileOnDisk (ExportPath, FileNameStr) if ((cmpstr (FileNameStr, "")) == 0) return 1 endif //define some variables and find out some information about the image, // also make a temp wave of right bit depth to hold a plane of the wave variable ii // used for iterations variable temp // a variable used to hold various values temporarily while writing to the file variable imwidth = dimsize (datawave, 0) // the width of the image, in pixels variable imlength=dimsize (datawave, 1) // the length of the image, in pixels variable imdepth = max (1, dimsize (datawave, 2))// the image depth, i.e., number of planes variable sampleBits // number of bits/per sample (8, 16, or 32) variable sampleFormat // Sample Format 1 = unsigned integer data, // 2 = two’s complement signed integer data ,3 = IEEE floating point data [IEEE] if (!(datafolderExists ("root:packages:"))) newdatafolder root:packages endif if (WaveType (Datawave) & 0x04) // 64 bit floating point SampleBits = 64 make/o/D/n= ((imwidth), (imlength)) root:Packages:aTIFFplane elseif (WaveType (DataWave) & 0x02) // 32 bit floating point sampleBits = 32 make/o/s/n= ((imwidth), (imlength)) root:Packages:aTIFFplane elseif (WaveType (DataWave) & 0x20) // 32 bit integer sampleBits = 32 if (WaveType(datawave) & 0x40) // unsigned SampleFormat = 1 make/I/u/o/n= ((imwidth), (imlength)) root:Packages:aTIFFplane else SampleFormat = 2 // signed make/I/o/n= ((imwidth), (imlength)) root:Packages:aTIFFplane endif elseif (WaveType(datawave) & 0x10) // 16 bit integer sampleBits = 16 if (WaveType(datawave) & 0x40) // unsigned SampleFormat = 1 make/W/u/o/n= ((imwidth), (imlength)) root:Packages:aTIFFplane else SampleFormat = 2 // signed make/W/o/n= ((imwidth), (imlength)) root:Packages:aTIFFplane endif elseif (WaveType(datawave) & 0x08) // 8 bit integer sampleBits = 8 if (WaveType(datawave) & 0x40) // unsigned SampleFormat = 1 make/B/u/o/n= ((imwidth), (imlength)) root:Packages:aTIFFplane else SampleFormat = 2 // signed make/B/o/n= ((imwidth), (imlength)) root:Packages:aTIFFplane endif else doalert 0, "Sorry, but the data type of the wave, " + nameofwave (dataWave) + ", was not recognized." return 1 endif WAVE aplane = root:Packages:aTIFFplane variable imBytes = imwidth * imlength * (sampleBits/8) // the number of bytes in an individual image plane string byteOrderStr // MM for Macintosh, II for intel; we will write native byte order // for the platform we are running on if ((cmpstr (IgorInfo(2), "Macintosh")) == 0) byteOrderStr = "MM" else byteOrderStr = "II" endif // Open a new file in the export path directory variable daRefNum // reference number of the file we will open Open/P=ExportPath/T= "TIFF" darefNum as FileNameStr // first write the byte order string and the magic 42, in two bytes each FBinWrite darefNum, byteOrderStr temp = 42 FBinWrite /F=2/U darefNum, temp //write offset to the first IFD unsigned 4 bytes, it will be after this 8 bit header, so 8 temp = 8 FBinWrite /F=3/U darefNum, temp //Iterate through each plane in the image, making an image file directory and writing the plane // Thus, IFDs and images alternate in the file. One could make a TIFF file with the IFDs all at the start, or // any other way you like, this just seemed simplest to me. For (ii = 0; ii < imdepth; ii += 1) //write the IFD - start with 2 byte count of number of directories temp = 10 FBinWrite /F=2/U darefNum, temp temp = 256 //tag 256 = image width FBinWrite /F=2 darefNum, temp temp = 4 // Field type 4byte unsihned integer FBinWrite /F=2/U darefNum, temp temp = 1 // number of values = 1 FBinWrite /F=3/U darefNum, temp FBinWrite /F=3/U darefNum, imwidth temp = 257 // tag 257 = image length FBinWrite /F=2 darefNum, temp temp = 4 // Field type 4byte unsigned integer FBinWrite /F=2/U darefNum, temp temp = 1 // number of values = 1 FBinWrite /F=3/U darefNum, temp FBinWrite /F=3/U darefNum, imlength temp = 258 // tag258 = bits/sample FBinWrite /F=2 darefNum, temp temp = 3 // Field type 2 byte unsigned integer FBinWrite /F=2/U darefNum, temp temp = 1 // number of values = 1 FBinWrite /F=3/U darefNum, temp temp = sampleBits // number of bits per sample FBinWrite /F=2/U darefNum, temp temp = 0 // need to pad with 0 FBinWrite /F=2/U darefNum, temp temp = 259 // tag259 = compression FBinWrite /F=2 darefNum, temp temp = 3 // Field type 2 byte unsigned integer FBinWrite /F=2 darefNum, temp temp = 1 // number of values = 1 FBinWrite /F=3/U darefNum, temp temp = 1 // No compression FBinWrite /F=2 darefNum, temp temp = 0 // need to pad with 0 FBinWrite /F=2/U darefNum, temp temp = 262 // tag262 = photometric interpretation FBinWrite /F=2 darefNum, temp temp = 3 // Field type 2 byte unsigned integer FBinWrite /F=2/U darefNum, temp temp = 1 //number of values = 1 FBinWrite /F=3/U darefNum, temp temp = 1 // black is 0, max value is white FBinWrite /F=2/U darefNum, temp temp = 0 // need to pad with 0 FBinWrite /F=2/U darefNum, temp temp = 273 // tag 273 = strip offsets, we will only make 1 strip, so there is only one offset FBinWrite /F=2 darefNum, temp temp = 4 // Field type 4 byte unsigned integer FBinWrite /F=2/U darefNum, temp temp = 1 //number of values = 1 FBinWrite /F=3/U darefNum, temp temp = 134 + ((126+ imBytes) * ii)// The image starts immediatley after this IFD. // Initial header is 8 bytes, an IFD is 126 bytes FBinWrite /F=3/U darefNum, temp temp = 277 // tag 277 = samples/pixel FBinWrite /F=2 darefNum, temp temp = 3 // Field type 2 byte unsigned integer FBinWrite /F=2/U darefNum, temp temp = 1 // number of values = 1 FBinWrite /F=3/U darefNum, temp temp = 1 // 1 sample/pixel, i.e., greyscale image FBinWrite /F=2 darefNum, temp temp = 0 // need to pad with 0 FBinWrite /F=2/U darefNum, temp temp = 278 // tag278 = rows/strip we only make 1 strip/image, so this is the same as rows FBinWrite /F=2 darefNum, temp temp = 3 // Field type 2 byte unsigned integer FBinWrite /F=2/U darefNum, temp temp = 1 FBinWrite /F=3/U darefNum, temp temp = imlength //1 strip/image, so this is the same as rows FBinWrite /F=2/U darefNum, temp temp = 0 // need to pad with 0 FBinWrite /F=2/U darefNum, temp temp = 279 // tag279 = strip bytecounts (number of bytes in each strip, after compresion) FBinWrite /F=2 darefNum, temp temp = 4 // Field type 4 byte unsigned integer FBinWrite /F=2/U darefNum, temp temp = 1 // number of values = 1 FBinWrite /F=3/U darefNum, temp FBinWrite /F=3/U darefNum, imBytes // only 1 strip, so byte count is same as bytes in an image temp = 339 // tag339 = Data Sample Format FBinWrite /F=2 darefNum, temp temp = 3 // Field type 2 byte unsigned integer FBinWrite /F=2/U darefNum, temp temp = 1 // number of samples = 1 FBinWrite /F=3/U darefNum, temp FBinWrite /F=2 darefNum, sampleFormat temp = 0 // need to pad with 0 FBinWrite /F=2/U darefNum, temp // Last thing in the IFD is 4 bytes for offset to start of next IFD (it will be right after the image), //unless it's the last image plane, when 4 bytes of 0 suffice if (ii < imdepth-1) temp = 8 + ((126 +imBytes) * (ii + 1)) else temp= 0 endif FBinWrite/F=3 darefnum, temp // finally, write the image plane aplane = datawave [p] [q] [ii] FBinWrite /f =0 darefNum,aplane endfor //Clean up close darefnum killwaves/z aplane return 0 end
![](/sites/default/files/forum.png)
Forum
![](/sites/default/files/support.png)
Support
![](/sites/default/files/gallery.png)
Gallery
Igor Pro 9
Learn More
Igor XOP Toolkit
Learn More
Igor NIDAQ Tools MX
Learn More
Seems that ImageSave now enables this
December 17, 2024 at 11:28 am - Permalink