How can I save an image with four channels (or more) into an ImageJ-compatible TIFF format?

67 views (last 30 days)
I have four channels image data and want to save it to TIFF format that is compatible with ImageJ/Fiji.
Standard imwrite does not support TIFF format with more than three channels. In fact, I wanted to save it into jpeg 2000, in which the original data was stored, but it looks like impossible.
So I'm playing around with Tiff class. It has lots of Tags to be specified, and ....
The following can save a file, but it seems incompatible with ImageJ. Image data in channel 1 repeatedly appear in all the four channels.
% I contains image data
% size(I) == [m,n,4]
tif = Tiff(filename,'w');
tif.setTag('ImageWidth',size(I,2));
tif.setTag('ImageLength',size(I,1));
tif.setTag('Photometric',Tiff.Photometric.MinIsBlack);
%NOTE Photometric must be before BitsPerSample and Compression
tif.setTag('PlanarConfiguration',Tiff.PlanarConfiguration.Separate);
%NOTE PlanarConfiguration must be Separate for Fiji to open the file properly
tif.setTag('BitsPerSample',16);
tif.setTag('SamplesPerPixel',4);
tif.setTag('Compression',Tiff.Compression.LZW);
tif.write(I);
tif.close();
Is there a way to save images with 4+ channels, other than Bio-Formats's bfsave, which is really slow?

Accepted Answer

Kouichi C. Nakamura
Kouichi C. Nakamura on 28 Mar 2018
This is quite a tough issue.
Here's a summary of what I've learned so far.
1. bfsave()
Bio-formats MATLAB plugin's bfsave() can save multiple channels into a *.ome.tif file, which is compatible with ImageJ. But it's quite slow (~2 min per 2048*2048*4 image). Not sure if this is Stitching's problem or bfsave's, but these *.oime.tif files are not compatible with Fiji > plugins > Stitching, as far as I tried.
2. Tiff class
As mentioned in the question, as far as I could see, multi-channel TIFF files saved with Tiff class are not compatible with ImageJ. They are cannot be opened properly. There might be a hidden combination of parameters that allow this to happen. If you find one, let me know!
3. Use imwrite() for each channel
This is a low level work around. Instead of saving four channels at one time, you can save each channel as a separate TIFF and the combine them from within ImageJ.
4. Use ImageJ-MATLAB
As introduced in ImageJ web site, somebody developed a way to commnucate with ImageJ from within MATLAB.
The documentation was incredibly unkind, so I had to spend a lot of time to work out what's going on. Now I've extensively edited the documentation above, so you guys are lucky.
Although it was not very clear in the original documentation, the simple code below can launch an instance of ImageJ from within MATLAB. Moreover, you can throw and catch data between ImageJ and MATLAB bidirectionally, with full access to ImageJ JAVA API.
addpath('/Applications/Fiji.app/scripts') % Update for your ImageJ installation as appropriate
ImageJ;
The code below essentially works for me now.
Strangely in my case, the image shown in ImageJ is 90 degrees rotated to the left. Also, the four channels are treated as a stack of four images rather than one image with four channels. So I needed to fix them.
You can also specify LUTs before saving.
This method is ~10 times slower (8.6 sec per 2048*2048*4 image) than saving four separate TIFF files (0.6 sec), but still 10-fold faster than bfsave (~2 min). And you don't have to mess around a folder with many intermediate images.
IJM.show('var1')
imp = ij.IJ.getImage();
IJ.run(imp, "Rotate... ", "angle=90 grid=1 interpolation=Bilinear stack");
IJ.run(imp, "16-bit", ""); % convert back to 16 bit per channel
% Need to change stacks to channels
IJ.run("Stack to Images", "");
IJ.run(imp, "Merge Channels...", "c1=-0001 c2=-0002 c3=-0003 c4=-0004 create ignore");
imp.close()
imp2 = IJ.getImage(); % need to get anew
IJ.saveAsTiff(imp2, fullfile(datadir,'test.tif'));
These might be API for stitching.

More Answers (1)

Martin Privat
Martin Privat on 25 May 2020
Fiji uses a specific 'ImageDescription' Tiff field to know how the data is organized. This field is also used to save a normal stack or a hyperstack. You can just store the images one after the other as a multipage tiff, and specify the right ImageDescription field to tell Fiji how to organize the tiff pages.
To save a 16 bits multidimensional image with 4 chanels, 5 Z slices and 6 time points, one could do something like:
MultiDimImg = zeros(300,400,4,5,6,'uint16');
fiji_descr = ['ImageJ=1.52p' newline ...
'images=' num2str(size(MultiDimImg,3)*...
size(MultiDimImg,4)*...
size(MultiDimImg,5)) newline...
'channels=' num2str(size(MultiDimImg,3)) newline...
'slices=' num2str(size(MultiDimImg,4)) newline...
'frames=' num2str(size(MultiDimImg,5)) newline...
'hyperstack=true' newline...
'mode=grayscale' newline...
'loop=false' newline...
'min=0.0' newline...
'max=65535.0']; % change this to 256 if you use an 8bit image
t = Tiff('test.tif','w')
tagstruct.ImageLength = size(MultiDimImg,1);
tagstruct.ImageWidth = size(MultiDimImg,2);
tagstruct.Photometric = Tiff.Photometric.MinIsBlack;
tagstruct.BitsPerSample = 16;
tagstruct.SamplesPerPixel = 1;
tagstruct.Compression = Tiff.Compression.LZW;
tagstruct.PlanarConfiguration = Tiff.PlanarConfiguration.Chunky;
tagstruct.SampleFormat = Tiff.SampleFormat.UInt;
tagstruct.ImageDescription = fiji_descr;
for frame = 1:size(MultiDimImg,5)
for slice = 1:size(MultiDimImg,4)
for channel = 1:size(MultiDimImg,3)
t.setTag(tagstruct)
t.write(im2uint16(MultiDimImg(:,:,channel,slice,frame)));
t.writeDirectory(); % saves a new page in the tiff file
end
end
end
t.close()
In my experience this is faster than bfsave

Products

Community Treasure Hunt

Find the treasures in MATLAB Central and discover how the community can help you!

Start Hunting!