Writing tiff file with multi channel and slices

Hello,
I would like to make a tiff file with c=2, z=10, t=1. Input array is 4 dimension, [height, width, channel, slice]. Currently I am using the code below, however, the output tiff file becomes c=1, z=20, t=1. Can anybody help me to fix it?
function write3Dtiff_Slice(array, filename)
dims = size(array);
% Ensure the array has four dimensions
if length(dims) < 4
dims(end+1:4) = 1;
end
% Set data type specific fields
if isa(array, 'single')
bitsPerSample = 32;
sampleFormat = Tiff.SampleFormat.IEEEFP;
elseif isa(array, 'uint16')
bitsPerSample = 16;
sampleFormat = Tiff.SampleFormat.UInt;
elseif isa(array, 'uint8')
bitsPerSample = 8;
sampleFormat = Tiff.SampleFormat.UInt;
else
disp('Unsupported data type');
return;
end
% Loop through slices
for s = 1:dims(4)
% Open TIFF file for each slice in append mode
outtiff = Tiff(filename, 'a');
% Loop through channels for the current slice
for c = 1:dims(3)
% Set tag structure for each channel of each slice
tagstruct.ImageLength = dims(1);
tagstruct.ImageWidth = dims(2);
tagstruct.Photometric = Tiff.Photometric.MinIsBlack;
tagstruct.PlanarConfiguration = Tiff.PlanarConfiguration.Chunky;
tagstruct.SamplesPerPixel = 1;
tagstruct.BitsPerSample = bitsPerSample;
tagstruct.SampleFormat = sampleFormat;
% Set the tag for the current channel
outtiff.setTag(tagstruct);
% Write the channel data
outtiff.write(array(:,:,c,s));
% Create a new directory for the next channel unless it's the last channel of the last slice
if c ~= dims(3) || s ~= dims(4)
outtiff.writeDirectory();
end
end
% Close the file for the current slice
outtiff.close();
end
end

 Accepted Answer

It's doing exactly what you're telling it to do. You have a stack of size [H W C F]. You're splitting the stack into C*F individual single-channel images. If that's not what you want, then what do you want?
This writes a set of 2-channel frames instead of a bunch of loose channels.
fname = 'fname.tif';
% a MxNx2x5 4D image
inpict = imread('peppers.png');
inpict = repmat(inpict(:,:,1:2),[1 1 1 5]);
% create the file
write3Dtiff_Slice(inpict,fname)
% get the information in the multitiff image
info = imfinfo(fname);
nframes = numel(info);
% read images to check that it's the expected size
% this assumes all the frames are the same class and size
C(:,:,:,1) = imread(fname,1);
C = repmat(C,[1 1 1 nframes]);
for f = 2:nframes
C(:,:,:,f) = imread(fname,f);
end
% test it
size(C) % the size is as expected
ans = 1×4
384 512 2 5
isequal(C,inpict) % it's the same as the original
ans = logical
1
function write3Dtiff_Slice(array, filename)
dims = size(array);
% Ensure the array has four dimensions
if length(dims) < 4
dims(end+1:4) = 1;
end
% Set data type specific fields
if isa(array, 'single')
bitsPerSample = 32;
sampleFormat = Tiff.SampleFormat.IEEEFP;
elseif isa(array, 'uint16')
bitsPerSample = 16;
sampleFormat = Tiff.SampleFormat.UInt;
elseif isa(array, 'uint8')
bitsPerSample = 8;
sampleFormat = Tiff.SampleFormat.UInt;
else
disp('Unsupported data type');
return;
end
% Open TIFF file for each slice in append mode
outtiff = Tiff(filename, 'a');
% Loop through slices
for s = 1:dims(4)
% Set tag structure for each frame
tagstruct.ImageLength = dims(1);
tagstruct.ImageWidth = dims(2);
tagstruct.Photometric = Tiff.Photometric.MinIsBlack;
tagstruct.ExtraSamples = Tiff.ExtraSamples.AssociatedAlpha;
tagstruct.PlanarConfiguration = Tiff.PlanarConfiguration.Chunky;
tagstruct.SamplesPerPixel = 2;
tagstruct.BitsPerSample = bitsPerSample;
tagstruct.SampleFormat = sampleFormat;
% Set the tag for the current frame
outtiff.setTag(tagstruct);
% Write the frame
outtiff.write(array(:,:,:,s));
% Create a new directory for the next frame
if s ~= dims(4)
outtiff.writeDirectory();
end
end
% Close the file
outtiff.close();
end
Note that you're always opening the file in 'append' mode, so if you write to an existing file, you'll always add more frames to it.

1 Comment

DGM
DGM on 8 Feb 2024
Edited: DGM on 8 Feb 2024
See also:
This example uses a slightly more generalized variant of the TIFF helper function shown above.

Sign in to comment.

More Answers (1)

What is z and t?
If you want the loop to only go from c=1 to c=2, instead of this:
for c = 1:dims(3)
have this:
for c = 1 : 2
Then I think it will write only the red channel and the blue channel.

Categories

Find more on Data Import and Analysis in Help Center and File Exchange

Asked:

on 15 Dec 2023

Edited:

DGM
on 8 Feb 2024

Community Treasure Hunt

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

Start Hunting!