Posted by
Joachim Wesner on
May 18, 2008; 7:50pm
URL: http://imagej.273.s1.nabble.com/Writing-to-file-Matlab-tp3696191p3696192.html
Tifff16 bit (writing) is still not supported in Matlab, for 16 bit however,
you might be able to use png for writing (see the imwrite docs).
For READING 16 bit tiff and also multi-image tiffs there is a nice macro I
found on Matlab central that works pretty good:
(However, iunfortunatelly there still seems not to be any tiffwrite2.m!)
Joachim
function [stack, img_read] = tiffread2(filename, img_first, img_last)
% tiffread, version 2.4
%
% [stack, nbImages] = tiffread;
% [stack, nbImages] = tiffread(filename);
% [stack, nbImages] = tiffread(filename, imageIndex);
% [stack, nbImages] = tiffread(filename, firstImageIndex,
lastImageIndex);
%
% Reads 8,16,32 bits uncompressed grayscale and (some) color tiff files,
% as well as stacks or multiple tiff images, for example those produced
% by metamorph or NIH-image. However, the entire TIFF standard is not
% supported (but you may extend it).
%
% The function can be called with a file name in the current directory,
% or without argument, in which case it pop up a file openning dialog
% to allow manual selection of the file.
% If the stacks contains multiples images, loading can be restricted by
% specifying the first and last images to read, or just one image to
read.
%
% at return, nbimages contains the number of images read, and S is a
vector
% containing the different images with some additional informations. The
% image pixels values are stored in the field .data, for gray level
images,
% or in the fields .red, .green and .blue
% the pixels values are in the native (integer) format,
% and must be converted to be used in most matlab functions.
%
% Example:
% im = tiffread('spindle.stk');
% imshow( double(im(5).data), [] );
%
% Francois Nedelec, EMBL, Copyright 1999-2006.
% rewriten July 7th, 2004 at Woods Hole during the physiology course.
% last modified April 12, 2006.
% Contributions:
% Kendra Burbank suggested the waitbar
% Hidenao Iwai for the code to read floating point images,
% Stephen Lang made tiffread more compliant with PlanarConfiguration
%
% Please, help us improve this software: send us
feedback/bugs/suggestions
% This software is provided at no cost by a public research institution.
% However, postcards are always welcome!
%
% Francois Nedelec
% nedelec (at) embl.de
% Cell Biology and Biophysics, EMBL; Meyerhofstrasse 1; 69117
Heidelberg; Germany
%
http://www.embl.org %
http://www.cytosim.org %Optimization: join adjacent TIF strips: this results in faster reads
consolidateStrips = 1;
%if there is no argument, we ask the user to choose a file:
if (nargin == 0)
[filename, pathname] = uigetfile('*.tif;*.stk;*.lsm', 'select image
file');
filename = [ pathname, filename ];
end
if (nargin<=1); img_first = 1; img_last = 10000; end
if (nargin==2); img_last = img_first; end
% not all valid tiff tags have been included, as they are really a
lot...
% if needed, tags can easily be added to this code
% See the official list of tags:
%
http://partners.adobe.com/asn/developer/pdfs/tn/TIFF6.pdf %
% the structure IMG is returned to the user, while TIF is not.
% so tags usefull to the user should be stored as fields in IMG, while
% those used only internally can be stored in TIF.
global TIF;
TIF = [];
%counters for the number of images read and skipped
img_skip = 0;
img_read = 0;
% set defaults values :
TIF.SampleFormat = 1;
TIF.SamplesPerPixel = 1;
TIF.BOS = 'l'; %byte order string
if isempty(findstr(filename,'.'))
filename = [filename,'.tif'];
end
TIF.file = fopen(filename,'r','l');
if TIF.file == -1
filename = strrep(filename, '.tif', '.stk');
TIF.file = fopen(filename,'r','l');
if TIF.file == -1
error(['file <',filename,'> not found.']);
end
end
% read header
% read byte order: II = little endian, MM = big endian
byte_order = fread(TIF.file, 2, '*char');
if ( strcmp(byte_order', 'II') )
TIF.BOS = 'l'; %normal PC format
elseif ( strcmp(byte_order','MM') )
TIF.BOS = 'b';
else
error('This is not a TIFF file (no MM or II).');
end
%----- read in a number which identifies file as TIFF format
tiff_id = fread(TIF.file,1,'uint16', TIF.BOS);
if (tiff_id ~= 42)
error('This is not a TIFF file (missing 42).');
end
%----- read the byte offset for the first image file directory (IFD)
ifd_pos = fread(TIF.file,1,'uint32', TIF.BOS);
while (ifd_pos ~= 0)
clear IMG;
IMG.filename = fullfile( pwd, filename );
% move in the file to the first IFD
fseek(TIF.file, ifd_pos, -1);
%disp(strcat('reading img at pos :',num2str(ifd_pos)));
%read in the number of IFD entries
num_entries = fread(TIF.file,1,'uint16', TIF.BOS);
%disp(strcat('num_entries =', num2str(num_entries)));
%read and process each IFD entry
for i = 1:num_entries
% save the current position in the file
file_pos = ftell(TIF.file);
% read entry tag
TIF.entry_tag = fread(TIF.file, 1, 'uint16', TIF.BOS);
entry = readIFDentry;
%disp(strcat('reading entry <',num2str(TIF.entry_tag),'>'));
switch TIF.entry_tag
case 254
TIF.NewSubfiletype = entry.val;
case 256 % image width - number of column
IMG.width = entry.val;
case 257 % image height - number of row
IMG.height = entry.val;
TIF.ImageLength = entry.val;
case 258 % BitsPerSample per sample
TIF.BitsPerSample = entry.val;
TIF.BytesPerSample = TIF.BitsPerSample / 8;
IMG.bits = TIF.BitsPerSample(1);
%fprintf(1,'BitsPerSample %i %i %i\n', entry.val);
case 259 % compression
if (entry.val ~= 1); error('Compression format not
supported.'); end
case 262 % photometric interpretation
TIF.PhotometricInterpretation = entry.val;
if ( TIF.PhotometricInterpretation == 3 )
fprintf(1, 'warning: ignoring the look-up table
defined in the TIFF file');
end
case 269
IMG.document_name = entry.val;
case 270 % comment:
TIF.info = entry.val;
case 271
IMG.make = entry.val;
case 273 % strip offset
TIF.StripOffsets = entry.val;
TIF.StripNumber = entry.cnt;
%fprintf(1,'StripNumber = %i, size(StripOffsets) = %i
%i\n', TIF.StripNumber, size(TIF.StripOffsets));
case 277 % sample_per pixel
TIF.SamplesPerPixel = entry.val;
%fprintf(1,'Color image: sample_per_pixel=%i\n',
TIF.SamplesPerPixel);
case 278 % rows per strip
TIF.RowsPerStrip = entry.val;
case 279 % strip byte counts - number of bytes in
each strip after any compressio
TIF.StripByteCounts= entry.val;
case 282 % X resolution
IMG.x_resolution = entry.val;
case 283 % Y resolution
IMG.y_resolution = entry.val;
case 284 %planar configuration describe the order of
RGB
TIF.PlanarConfiguration = entry.val;
case 296 % resolution unit
IMG.resolution_unit= entry.val;
case 305 % software
IMG.software = entry.val;
case 306 % datetime
IMG.datetime = entry.val;
case 315
IMG.artist = entry.val;
case 317 %predictor for compression
if (entry.val ~= 1); error('unsuported predictor
value'); end
case 320 % color map
IMG.cmap = entry.val;
IMG.colors = entry.cnt/3;
case 339
TIF.SampleFormat = entry.val;
case 33628 %metamorph specific data
IMG.MM_private1 = entry.val;
case 33629 %this tag identify the image as a Metamorph
stack!
TIF.MM_stack = entry.val;
TIF.MM_stackCnt = entry.cnt;
if ( img_last > img_first )
waitbar_handle = waitbar(0,'Please
wait...','Name',['Reading ' filename]);
end
case 33630 %metamorph stack data: wavelength
TIF.MM_wavelength = entry.val;
case 33631 %metamorph stack data: gain/background?
TIF.MM_private2 = entry.val;
otherwise
fprintf(1,'ignored TIFF entry with tag %i (cnt %i)\n',
TIF.entry_tag, entry.cnt);
end
% move to next IFD entry in the file
fseek(TIF.file, file_pos+12,-1);
end
%Planar configuration is not fully supported
%Per tiff spec 6.0 PlanarConfiguration irrelevent if
SamplesPerPixel==1
%Contributed by Stephen Lang
if ((TIF.SamplesPerPixel ~= 1) && (TIF.PlanarConfiguration == 1))
error('PlanarConfiguration = %i not supported',
TIF.PlanarConfiguration);
end
%total number of bytes per image:
PlaneBytesCnt = IMG.width * IMG.height * TIF.BytesPerSample;
if consolidateStrips
%Try to consolidate the strips into a single one to speed-up
reading:
BytesCnt = TIF.StripByteCounts(1);
if BytesCnt < PlaneBytesCnt
ConsolidateCnt = 1;
%Count how many Strip are needed to produce a plane
while TIF.StripOffsets(1) + BytesCnt ==
TIF.StripOffsets(ConsolidateCnt+1)
ConsolidateCnt = ConsolidateCnt + 1;
BytesCnt = BytesCnt +
TIF.StripByteCounts(ConsolidateCnt);
if ( BytesCnt >= PlaneBytesCnt ); break; end
end
%Consolidate the Strips
if ( BytesCnt <= PlaneBytesCnt(1) ) && ( ConsolidateCnt > 1
)
%fprintf(1,'Consolidating %i stripes out of %i',
ConsolidateCnt, TIF.StripNumber);
TIF.StripByteCounts = [BytesCnt;
TIF.StripByteCounts(ConsolidateCnt+1:TIF.StripNumber ) ];
TIF.StripOffsets = TIF.StripOffsets( [1 ,
ConsolidateCnt+1:TIF.StripNumber] );
TIF.StripNumber = 1 + TIF.StripNumber - ConsolidateCnt;
end
end
end
%read the next IFD address:
ifd_pos = fread(TIF.file, 1, 'uint32', TIF.BOS);
%if (ifd_pos) disp(['next ifd at', num2str(ifd_pos)]); end
if isfield( TIF, 'MM_stack' )
if ( img_last > TIF.MM_stackCnt )
img_last = TIF.MM_stackCnt;
end
%this loop is to read metamorph stacks:
for ii = img_first:img_last
TIF.StripCnt = 1;
%read the image
fileOffset = PlaneBytesCnt * ( ii - 1 );
%fileOffset = 0;
%fileOffset = ftell(TIF.file) - TIF.StripOffsets(1);
if ( TIF.SamplesPerPixel == 1 )
IMG.data = read_plane(fileOffset, IMG.width,
IMG.height, 1);
else
IMG.red = read_plane(fileOffset, IMG.width,
IMG.height, 1);
IMG.green = read_plane(fileOffset, IMG.width,
IMG.height, 2);
IMG.blue = read_plane(fileOffset, IMG.width,
IMG.height, 3);
end
% print a text timer on the main window, or update the
waitbar
% fprintf(1,'img_read %i img_skip %i\n', img_read,
img_skip);
if exist('waitbar_handle', 'var')
waitbar( img_read/TIF.MM_stackCnt, waitbar_handle);
end
[ IMG.info, IMG.MM_stack, IMG.MM_wavelength, IMG.MM_private2
] = extractMetamorphData(ii);
img_read = img_read + 1;
stack( img_read ) = IMG;
end
break;
else
%this part to read a normal TIFF stack:
if ( img_skip + 1 >= img_first )
TIF.StripCnt = 1;
%read the image
if ( TIF.SamplesPerPixel == 1 )
IMG.data = read_plane(0, IMG.width, IMG.height, 1);
else
IMG.red = read_plane(0, IMG.width, IMG.height, 1);
IMG.green = read_plane(0, IMG.width, IMG.height, 2);
IMG.blue = read_plane(0, IMG.width, IMG.height, 3);
end
img_read = img_read + 1;
try
stack( img_read ) = IMG;
catch
%stack
%IMG
error('The file contains dissimilar images: you can only
read them one by one');
end
else
img_skip = img_skip + 1;
end
if ( img_skip + img_read >= img_last )
break;
end
end
end
%clean-up
fclose(TIF.file);
if exist('waitbar_handle', 'var')
delete( waitbar_handle );
clear waitbar_handle;
end
drawnow;
%return empty array if nothing was read
if ~ exist( 'stack', 'var')
stack = [];
end
return;
%============================================================================
function plane = read_plane(offset, width, height, planeCnt)
global TIF;
%return an empty array if the sample format has zero bits
if ( TIF.BitsPerSample(planeCnt) == 0 )
plane=[];
return;
end
%fprintf(1,'reading plane %i size %i %i\n', planeCnt, width, height);
%determine the type needed to store the pixel values:
switch( TIF.SampleFormat )
case 1
classname = sprintf('uint%i', TIF.BitsPerSample(planeCnt));
case 2
classname = sprintf('int%i', TIF.BitsPerSample(planeCnt));
case 3
if ( TIF.BitsPerSample(planeCnt) == 32 )
classname = 'single';
else
classname = 'double';
end
otherwise
error('unsuported TIFF sample format %i', TIF.SampleFormat);
end
% Preallocate a matrix to hold the sample data:
plane = zeros(width, height, classname);
% Read the strips and concatenate them:
line = 1;
while ( TIF.StripCnt <= TIF.StripNumber )
strip = read_strip(offset, width, planeCnt, TIF.StripCnt,
classname);
TIF.StripCnt = TIF.StripCnt + 1;
% copy the strip onto the data
plane(:, line:(line+size(strip,2)-1)) = strip;
line = line + size(strip,2);
if ( line > height )
break;
end
end
% Extract valid part of data if needed
if ~all(size(plane) == [width height]),
plane = plane(1:width, 1:height);
error('Cropping data: more bytes read than needed...');
end
% transpose the image (otherwise display is rotated in matlab)
plane = plane';
return;
%=================== sub-functions to read a strip ===================
function strip = read_strip(offset, width, planeCnt, stripCnt,
classname)
global TIF;
%fprintf(1,'reading strip at position %i\n',TIF.StripOffsets(stripCnt) +
offset);
StripLength = TIF.StripByteCounts(stripCnt) ./
TIF.BytesPerSample(planeCnt);
%fprintf(1, 'reading strip %i\n', stripCnt);
fseek(TIF.file, TIF.StripOffsets(stripCnt) + offset, 'bof');
bytes = fread( TIF.file, StripLength, classname, TIF.BOS );
if ( length(bytes) ~= StripLength )
error('End of file reached unexpectedly.');
end
strip = reshape(bytes, width, StripLength / width);
return;
%===================sub-functions that reads an IFD
entry:===================
function [nbBytes, matlabType] = convertType(tiffType)
switch (tiffType)
case 1
nbBytes=1;
matlabType='uint8';
case 2
nbBytes=1;
matlabType='uchar';
case 3
nbBytes=2;
matlabType='uint16';
case 4
nbBytes=4;
matlabType='uint32';
case 5
nbBytes=8;
matlabType='uint32';
case 11
nbBytes=4;
matlabType='float32';
case 12
nbBytes=8;
matlabType='float64';
otherwise
error('tiff type %i not supported', tiffType)
end
return;
%===================sub-functions that reads an IFD
entry:===================
function entry = readIFDentry()
global TIF;
entry.tiffType = fread(TIF.file, 1, 'uint16', TIF.BOS);
entry.cnt = fread(TIF.file, 1, 'uint32', TIF.BOS);
%disp(['tiffType =', num2str(entry.tiffType),', cnt =
',num2str(entry.cnt)]);
[ entry.nbBytes, entry.matlabType ] = convertType(entry.tiffType);
if entry.nbBytes * entry.cnt > 4
%next field contains an offset:
offset = fread(TIF.file, 1, 'uint32', TIF.BOS);
%disp(strcat('offset = ', num2str(offset)));
fseek(TIF.file, offset, -1);
end
if TIF.entry_tag == 33629 %special metamorph 'rationals'
entry.val = fread(TIF.file, 6*entry.cnt, entry.matlabType, TIF.BOS);
else
if entry.tiffType == 5
entry.val = fread(TIF.file, 2*entry.cnt, entry.matlabType,
TIF.BOS);
else
entry.val = fread(TIF.file, entry.cnt, entry.matlabType,
TIF.BOS);
end
end
if ( entry.tiffType == 2 ); entry.val = char(entry.val'); end
return;
%==============distribute the metamorph infos to each frame:
function [info, stack, wavelength, private2 ] =
extractMetamorphData(imgCnt)
global TIF;
info = [];
stack = [];
wavelength = [];
private2 = [];
if TIF.MM_stackCnt == 1
return;
end
left = imgCnt - 1;
if isfield( TIF, 'info' )
S = length(TIF.info) / TIF.MM_stackCnt;
info = TIF.info(S*left+1:S*left+S);
end
if isfield( TIF, 'MM_stack' )
S = length(TIF.MM_stack) / TIF.MM_stackCnt;
stack = TIF.MM_stack(S*left+1:S*left+S);
end
if isfield( TIF, 'MM_wavelength' )
S = length(TIF.MM_wavelength) / TIF.MM_stackCnt;
wavelength = TIF.MM_wavelength(S*left+1:S*left+S);
end
if isfield( TIF, 'MM_private2' )
S = length(TIF.MM_private2) / TIF.MM_stackCnt;
private2 = TIF.MM_private2(S*left+1:S*left+S);
end
return;
ImageJ Interest Group <
[hidden email]> schrieb am 18.05.2008 00:20:01:
> Hi All,
>
> Can anyone tell me if it is possible to write a 16 (or better yet)
> 32-bit image from Matlab?
>
> The command used is
>
> imwrite(image.jpeg,'filename',.........................);
>
> but I am unfamiliar with standard image file type designations and
> Matlab's capabilities.
>
> It seems Matlab only supports tiff files to 8-bit - has anyone had any
> luck otherwise using jpeg or gif or the other filetypes?
>
> Much Appreciated for your input
>
> Robert
______________________________________________________________________
This email has been scanned by the MessageLabs Email Security System.
For more information please visit
http://www.messagelabs.com/email
______________________________________________________________________