Writing to file - Matlab

Previous Topic Next Topic
 
classic Classic list List threaded Threaded
2 messages Options
Reply | Threaded
Open this post in threaded view
|

Writing to file - Matlab

Robert Martin-3
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
Reply | Threaded
Open this post in threaded view
|

Antwort: Writing to file - Matlab

Joachim Wesner
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 
______________________________________________________________________