function [img_cell, metadata_cell] = ipl2tif(file)
% Reads an IPL (IPLab) file and returns a cell of images that it contains,
% as well as any optional metadata information.
%
% Currently, the following image data type representaions are supported:
% - uint8
% - int16
% - uint16
% - int32
% - float32
% - float64
%
% Data types to add:
% - Color24
% - Color48
%
% See comments below for processing of optional and custom tags.
% Tomasz Piech - May 2008
metadata_cell = {};
img_cell = {};
% NOTE: to display debug information in the console, set debug to true
debug = true;
fid = fopen(file, 'r'); % 'r' - read is the default
if fid ~= -1
try
%% 1st Required TAG, byte order
tag = fread(fid, 4, 'uint8=>char');
size = fread(fid, 1, 'uint32');
data = fread(fid, 4, 'uint8=>char');
if debug
display(sprintf('tag: %s, file version: %s\n', tag, data'));
end
%% 2nd Required TAG, data set
tag = fread(fid, 4, 'uint8=>char'); % should be 'data'
if ~strcmpi(tag', 'data')
return;
end
size = fread(fid, 1, 'uint32');
width = fread(fid, 1, 'uint32'); % # columns
height = fread(fid, 1, 'uint32'); % # rows
channels = fread(fid, 1, 'uint32'); % 1 = grayscale, 3 = RGB
zDepth = fread(fid, 1, 'uint32');
tDepth = fread(fid, 1, 'uint32');
dataType = fread(fid, 1, 'uint32');
if debug
display(sprintf('# images: %d, img width: %d, img height: %d\n', tDepth, width, height));
end
switch dataType
case 0
dt = 'uint8';
case 1
dt = 'int16';
case 2
dt = 'uint16';
case 3
dt = 'int32';
case 4
dt = 'float32';
case 5
dt = 'Color24';
case 6
dt = 'Color48';
case 7
dt = '(reserved)';
case 8
dt = '(reserved)';
case 9
dt = '(reserved)';
case 10
dt = 'float64';
otherwise
dt = 'unknown';
end
img_cell = cell(1, tDepth);
%% read images - source and destination data types are the same
% TODO: add processing for remaining formats: Color24 & Color48
% precision, e.g. '*uint16' is equivalent to 'uint16=>uint16'
if dataType == 0 || dataType == 1 || dataType == 2 || ...
dataType == 3 || dataType == 4 || dataType == 10
precision = sprintf('*%s', dt);
else
if debug
display(sprintf('Data type %s (%d) is not supported.', dt, dataType));
end
return;
end
for t=1:tDepth
for z=1:zDepth
for c=1:channels
% read, reshape then transform
img = fread(fid, width * height, precision);
img = reshape(img, width, height)';
img_cell(1, t) = {img};
end
end
end
clear img;
%% Optional TAGS before last required TAG ('fini')
tag = fread(fid, 4, 'uint8=>char');
tag = tag';
size = fread(fid, 1, 'uint32');
while strcmp(tag, 'fini') == 0
switch tag
% add processing of optional/custom tags here
% for example, a custom tag might store a string
% representation of the software version of the application
% used to acquire your images, such as 'soft'
%
% case 'soft'
% data = fread(fid, size, 'uint8=>char');
% data = data';
% metadata_cell = [metadata_cell; { tag, data }];
%
% or, some IPL files include segmentation information in
% the 'mask' tag
%
% case 'mask'
% data = fread(fid, size, 'uint8');
% metadata_cell = [metadata_cell; { tag, data }];
%
% see IPLab SDK documentation for more information
otherwise
if debug
% read as char data
data = fread(fid, size, 'uint8=>char');
data = data';
else
fseek(fid, size, 'cof');
end
end
if debug
display(sprintf('Tag name %s, size %d, data %s\n', tag, size, data));
end
% read next tag and its data size
tag = fread(fid, 4, 'uint8=>char');
tag = tag';
size = fread(fid, 1, 'uint32');
end
catch ME
%% finally, close the file
fclose(fid);
rethrow(ME);
end
fclose(fid);
end