help-octave
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: How to use debugging tools


From: Colin Ingram
Subject: Re: How to use debugging tools
Date: Mon, 19 Sep 2005 19:56:23 -0500
User-agent: Mozilla Thunderbird 1.0 (Windows/20041206)

Colin Ingram wrote:


**************************************************************
I've attached tiffread.m. I've experienced some more strange behavior with the db tools but we will save that for later.


Oh bother I've really attached it this time.


-------------------------------------------------------------
Octave is freely available under the terms of the GNU GPL.

Octave's home on the web:  http://www.octave.org
How to fund new projects:  http://www.octave.org/funding.html
Subscription information:  http://www.octave.org/archive.html
-------------------------------------------------------------


function [stack, img_read] = tiffread(filename, img_first, img_last)
% tiffread, version 2.1
%
% [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-2004.
% Last modified July 7th, 2004 at Woods Hole during the physiology course.
% Thanks to Kendra Burbank for suggesting the waitbar
%
% 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
% 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 = true;

##if there is no argument, we ask the user to choose a file:
if (nargin == 0)
  ##    **to-fix** [CJI: no octave ui compat.]
  ##    [filename, pathname] = uigetfile('*.tif;*.stk;*.lsm', 'select image 
file');
  ##    filename = [ pathname, filename ];
  fflush(stdout);
  filename=input("Input Filename?", "s")
endif

if (nargin<=1)  img_first = 1; img_last = 10000; endif
if (nargin==2)  img_last = img_first;            endif


% 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,".stk"];
endif

[TIF.file, message] = fopen(filename,"rb","ieee-le");
if TIF.file == -1
  filename = strrep(filename, ".stk", ".tif");
  [TIF.file, message] = fopen(filename,"rb","ieee-le");
  if TIF.file == -1
    error(["Could not open <",filename,"> for reading!"]);
  endif
endif


## read header
## read byte order: II = little endian, MM = big endian
byte_order = char(fread(TIF.file, 2, "uchar"));
if ( strcmp(byte_order', "II") )
  TIF.BOS = "ieee-le";                               # normal PC format
elseif ( strcmp(byte_order',"MM") )
  TIF.BOS = "ieee-be";
else
  error("This is not a TIFF file. Headers Specifies an Invalid File Format.");
endif

##----- read in a number which identifies file as TIFF format
tiff_id = fread(TIF.file,1,"uint16", 0, TIF.BOS);
if (tiff_id ~= 42)
  error("This is not a TIFF file. Header Specifies an invalid TIFF file_ID");
endif

##----- read the byte offset for the first image file directory (IFD)
ifd_pos = fread(TIF.file,1,"uint32", 0 ,TIF.BOS);

while (ifd_pos ~= 0)

  clear IMG;
  IMG.filename = filename;
  ## move in the file to the first IFD
  fseek(TIF.file, ifd_pos, -1);

  ## read in the number of IFD entries
  num_entries = fread(TIF.file,1,"uint16", 0, TIF.BOS);

  ## 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", 0, TIF.BOS);
    entry = readIFDentry;
      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);
        case 259           # compression
          if (entry.val ~= 1) error("Compression format not supported.");  endif
        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"); 
          endif  
        case 269 
          IMG.document_name  = entry.val;
        case 270          % comment:
%           TIF.info           = entry.val;
          TIF.info           = parseMM_info(entry.val);
        case 271 
          IMG.make           = entry.val;
        case 273          % strip offset
          TIF.StripOffsets   = entry.val;
          TIF.StripNumber    = entry.cnt;
        case 277             % sample_per pixel
          TIF.SamplesPerPixel  = entry.val; 
             
        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;  
              %planar configuration is not fully supported here
          if ( TIF.PlanarConfiguration == 1 )
            error(sprintf("PlanarConfiguration = %i not supported", 
TIF.PlanarConfiguration)); 
          endif  
        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; 
          if ( TIF.SampleFormat > 2 ) 
            error(sprintf("unsuported sample format = %i", TIF.SampleFormat)); 
          endif 
        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; 
          ## **to fix** GUI
##          if ( img_last > img_first ) 
##            waitbar_handle = waitbar(0,"Please wait...","Name",["Reading " 
filename]); 
##          endif 
        case 33630        %metamorph stack data: wavelength
          TIF.MM_wavelength  = entry.val; 
        case 33631        %metamorph stack data: gain/background?
          TIF.MM_private2    = entry.val; 
        case 34412        % Zeiss LSM data (I have no idea what that 
represents...)
          IMG.LSM            = entry.val; 
        otherwise 
          fprintf(1,"ignored TIFF entry with tag %i (cnt %i)\n", TIF.entry_tag, 
entry.cnt); 
      endswitch    

#    IMG = assignIFDentry(entry);
#    keyboard;
    ## move to next IFD entry in the file
    fseek(TIF.file, file_pos+12,-1);  
  endfor  

  ## 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; endif  
      endwhile

      ## Consolidate the Strips
      if ( BytesCnt <= PlaneBytesCnt(1) ) && ( ConsolidateCnt > 1 ) 
        TIF.StripByteCounts = [BytesCnt; 
TIF.StripByteCounts(ConsolidateCnt+1:TIF.StripNumber) ]; 
        TIF.StripOffsets = TIF.StripOffsets( [1 , 
ConsolidateCnt+1:TIF.StripNumber]); 
        TIF.StripNumber  = 1 + TIF.StripNumber - ConsolidateCnt; 
      endif 
    endif 
  endif 

   %read the next IFD address:
   ifd_pos = fread(TIF.file, 1, "uint32", 0,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
%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;
   endif

   %fprintf(1,'reading plane %i size %i %i\n', planeCnt, width, height);

   %string description of the type of integer needed: int8 or int16...
   typecode = sprintf("int%i", TIF.BitsPerSample(planeCnt) );
   %unsigned int if SampleFormat == 1
   if ( TIF.SampleFormat == 1 )
       typecode = [ "u", typecode ];
   end

   % Preallocate a matrix to hold the sample data:
   plane = eval( [ typecode, "(zeros(width, height));"] );

   line = 1;

   while ( TIF.StripCnt <= TIF.StripNumber )

       strip = read_strip(offset, width, planeCnt, TIF.StripCnt, typecode );
       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
   plane = plane';

return;


%=================== sub-functions to read a strip ===================

function strip = read_strip(offset, width, planeCnt, stripCnt, typecode)

   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, typecode, 0,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, typechar] = octave_type(tiff_typecode)
  switch (tiff_typecode)
    case 1
      nbbytes=1;
      typechar="uint8";
    case 2
      nbbytes=1;
      typechar="uchar";
    case 3
      nbbytes=2;
      typechar="uint16";
    case 4
      nbbytes=4;
      typechar="uint32";
    case 5
      nbbytes=8;
      typechar="uint32";
    case 6
      nbbytes=1;
      typechar="int8";
    case 8
      nbbytes=2;
      typechar="int16";
    case 9
      nbbytes=4;
      typechar="int32";
    case 10
      nbbytes=8;
      typechar="int32";
    case 11
      nbbytes=4;
      typechar="single";
    case 12
      nbbytes=8;
      typechar="double";
    otherwise
      error("tiff type not supported")
  endswitch
  return;
endfunction

%===================sub-functions that reads an IFD entry:===================

function  entry = readIFDentry()
  global TIF;
  entry.typecode = fread(TIF.file, 1, "uint16", 0,TIF.BOS);
  entry.cnt      = fread(TIF.file, 1, "uint32", 0,TIF.BOS);

  [ entry.nbbytes, entry.typechar ] = octave_type(entry.typecode);

  if entry.nbbytes * entry.cnt > 4
    ## next field contains an offset:
    offset = fread(TIF.file, 1, "uint32", 0,TIF.BOS);

    fseek(TIF.file, offset, -1);
  endif

  if TIF.entry_tag == 33629   # special metamorph "rationals"
    entry.val = fread(TIF.file, 6*entry.cnt, entry.typechar, ...
                      0,TIF.BOS);
  elseif (entry.typechar == 5 || entry.typechar == 10)
    entry.val = fread(TIF.file, 2*entry.cnt, entry.typechar, 0, ...
                      TIF.BOS);
  else
    entry.val = fread(TIF.file, entry.cnt, entry.typechar, ...
                        0,TIF.BOS);
  endif

  if ( entry.typecode == 2 ) entry.val = char(entry.val'); endif

  return;
endfunction

##==================sub-functions that assigns an IFD entry:===================
function IMG = assignIFDentry(entry)
  global TIF;
  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);
        case 259           # compression
          if (entry.val ~= 1) error("Compression format not supported.");  endif
        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"); 
          endif  
        case 269 
          IMG.document_name  = entry.val;
        case 270          % comment:
%           TIF.info           = entry.val;
          TIF.info           = parseMM_info(entry.val);
        case 271 
          IMG.make           = entry.val;
        case 273          % strip offset
          TIF.StripOffsets   = entry.val;
          TIF.StripNumber    = entry.cnt;
        case 277             % sample_per pixel
          TIF.SamplesPerPixel  = entry.val; 
             
        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;  
              %planar configuration is not fully supported here
          if ( TIF.PlanarConfiguration == 1 )
            error(sprintf("PlanarConfiguration = %i not supported", 
TIF.PlanarConfiguration)); 
          endif  
        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; 
          if ( TIF.SampleFormat > 2 ) 
            error(sprintf("unsuported sample format = %i", TIF.SampleFormat)); 
          endif 
        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; 
          ## **to fix** GUI
##          if ( img_last > img_first ) 
##            waitbar_handle = waitbar(0,"Please wait...","Name",["Reading " 
filename]); 
##          endif 
        case 33630        %metamorph stack data: wavelength
          TIF.MM_wavelength  = entry.val; 
        case 33631        %metamorph stack data: gain/background?
          TIF.MM_private2    = entry.val; 
        case 34412        % Zeiss LSM data (I have no idea what that 
represents...)
          IMG.LSM            = entry.val; 
        otherwise 
          fprintf(1,"ignored TIFF entry with tag %i (cnt %i)\n", TIF.entry_tag, 
entry.cnt); 
      endswitch    

%==============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(imgCnt);
    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;


%%%%  Parse the Metamorph camera info tag into respective fields
% EVBR 2/7/2005
function mm_infor = parseMM_info(info)

i=0;
kk=info;
kk(find(double(kk)==0)) = "";
while(length(kk))
    i=i+1;
    [tmp, kk] = strtok(kk, 13);
%     [tmp,b] = strtok(tmp, 0);
    token{i} = sscanf(tmp, "%s");
end
tok = {token{1:end-1}};

len = length(tok)/11;
k=0;
for i=1:length(tok)
    if ~isempty(token{i})
        [tkk, remk] = strtok(token{i}, 58);
        if strcmp(tkk, "Exposure")
            k=k+1;
        end
        switch tkk
            case "Exposure"
                % Exposure: 200 ms -> 200
                mm_infor(k).Exposure = str2double(remk(2:strfind(remk, 
"ms")-1));
            case "Binning"
                % Binning: 1 x 1 -> [1 1]
                tmp = sscanf(remk, "%c %d %c %d")';
                mm_infor(k).Binning = tmp([2,4]);
            case "Region"
                % Region: 1392 x 1040, offset at (0, 0) -> [1392 1040], [0 0]
                [a,b] = strtok(remk, ",");
                tmp = sscanf(a, "%c %d %c %d")';
                mm_infor(k).Region.Size = tmp([2,4]);
                [a,b] = strtok(b, ",");
                mm_infor(k).Region.Offset = [str2double(a(end)), 
str2double(b(2))];
            case "Subtract"
                % Subtract: Off -> 0
                mm_infor(k).Subtract = ~strcmp(remk(2:end),"Off");
            case "Shading"
                % Shading: Off -> 0
                mm_infor(k).Shading = ~strcmp(remk(2:end),"Off");
            case "Digitizer"
                % Digitizer: 5MHz -> 5
                mm_infor(k).Digitizer = sscanf(remk(2:end), "%d %*s")';
            case "Gain"
                % Gain: Gain 1 (1x) -> 1
                mm_infor(k).Gain = sscanf(remk(strfind(remk,"(")+1:end),...
                    "%d %*s %d")';
            case "CameraShutter"
                % Camera Shutter: Always Open -> 'AlwaysOpen'
                mm_infor(k).CameraShutter = remk(2:end);
            case "ClearCount"
                % Clear Count: 2 -> 2
                tmp = sscanf(remk, "%c %d")';
                mm_infor(k).ClearCount = tmp(2);
            case "TriggerMode"
                % Trigger Mode: Normal -> "Normal"
                mm_infor(k).TriggerMode = remk(2:end);
            case "Temperature"
                % Temperature: 20 -> 20
                tmp = sscanf(remk, "%c %d")';
                mm_infor(k).Temperature = tmp(2);
            otherwise
                warning("Uknown MM_Tag")
        end
    end
end

reply via email to

[Prev in Thread] Current Thread [Next in Thread]