help-octave
[Top][All Lists]
Advanced

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

Re: load image in different format


From: en254
Subject: Re: load image in different format
Date: Wed, 7 Jun 2000 20:31:26 -0400 (EDT)

On Tue, 6 Jun 2000, Joao Cardoso wrote:
> Stephen Eglen wrote:
> > 
> > Hi, a similar request was made a couple of months ago.  I suggested:
> > 
> > ----------------------------------------------------------------------
> > > Does it exists m files to read BMP, TIFF or GIF files into Matlab ?
> > > Thanks for help
> > 
> > I'm not aware of any octave/matlab implementations at the moment.  If
> 
> Some year ago (1996!) I have done it, using giftoppm etc to convert the
> images to ppm and scanning the resulting files in octave. Without any
> warranty (as usual) I enclose then.
> 

This approach works, but unfortunately is very inefficient for
large size images.

One approach is to avoid converting to temprorary ppm files,
but to use popen to directly suck in the output from the
???top?n tools. This is a little faster and avoids having
to create and delete tmp files.

I'm including a sample imread.m to do this.

The problem with this approach is 
1) It's still slow
2) It depends on the pbmtools being installed


The other approach is to write *oct files which directly
link to the appropriate graphics library, ie libjpeg,
lib(un)gif, libtiff. This is a much faster and cleaner
way to do it.

I'll submit something to octave-sources to do this for
*jpeg files. I've been planning to write something
for the other graphics files, but I haven't found the
time.

______________________________________________________________
Andy Adler,                               address@hidden


------file: imread.m----------
#IMREAD: read images into octave from various file formats
#
# [im]=    imread(fname, fmt, imgno); -> im is a greyscale (0-255) of image in 
fname
# [r,g,b]= imread(fname, fmt, imgno); -> rgb are red,green,blue (0-255) 
components
# [im,map]=imread(fname, fmt, imgno); -> index and colourmap 
# filename -> image to read
#
#      fmt -> image storage type
# currently the following formats are supported
# if fmt is not supplied, imread will attempt to get it from the filename
#
# fmt == "img" or "octave"
# [im]= imread(fname, "img") -> read 'octave' format images
#
# fmt == "gif"
# [im]= imread(fname, "gif") -> read gif file to im,
# [im]= imread(fname, "gif", imgno ) -> read image # imgno from gif
#
# fmt == "bmp"
# [im]= imread(fname, "bmp") -> read bmp file to im,
#
# fmt == "jpg" or "jpeg"
# [im]= imread(filename, "jpg") -> read jpeg file to im,
#                                  if rgb, compress to greyscale
# [r,g,b]= imread(fname, "jpg") -> read jpeg file to red, green, blue
#                                  components
#
# fmt == "tiff" or "tif"
# [im,map]= imread(fname, "tif" ) -> read the 1st image from the file
#
# fmt == "libtiff"
# [im,map]= imread(fname, "libtif", imagenumber) 
#                get the 'imagenumber'th image from a tif format file;
#            force reading a tif file using the libtiff library (slower,
#            but sometimes works better than the libgr-progs version)
#
# fmt == "ppm" or "pgm" or "pnm" or "pbm" (imshow reads the
#         file type from the file, so any specification is ok)
#         pbm is binary, pgm is 8 bit grey, ppm is colour
# [im]= imread(filename, "pgm") -> read pnm file to im,
#                                  if rgb, compress to greyscale
# [r,g,b]= imread(fname, "ppm") -> read pnm file to red, green, blue
#                                  components

# $Id: imread.m,v 1.7 1999/06/10 19:18:00 aadler Exp aadler $

#TODO:
#  support mulitiple image tif files

function [out1,out2,out3]= imread(filename, fmt, imgno);

save_empty_list_elements_ok= empty_list_elements_ok;
unwind_protect
empty_list_elements_ok= 1;

if (nargin == 0)
  usage ("[img, map] = imread (filename,[ fmt ,[imgno] ])");
elseif (! isstr (filename))
  error ("imread: expecting filename as a string");
endif

fname= file_in_path(IMAGEPATH,filename);
if isempty(fname)
   error(['imread: file ' filename ' not found']);
end

if nargin<2 || isempty(fmt)
   dot= find(fname=='.'); dot= dot(length(dot));
   if isempty(dot) || dot >= length(fname)
      error("imread: can't figure out the file type");
   end
   fmt= fname(dot+1:length(fname));
end
fmt= tolower(fmt);

#
# decode the nargout to output what the user wants
#
if     nargout==1;  wantgreyscale= 1; wantmap= 0;
elseif nargout==2;  wantgreyscale= 0; wantmap= 1;
else                wantgreyscale= 0; wantmap= 0;
end

#
# Begin the image processing proper
#
if      strcmp( fmt, 'tif') || strcmp( fmt, 'tiff') || ...
        strcmp( fmt, 'jpg') || strcmp( fmt, 'jpeg') || ...
        strcmp( fmt, 'pnm') || strcmp( fmt, 'pbm') || ...
        strcmp( fmt, 'pgm') || strcmp( fmt, 'ppm') || ...
        strcmp( fmt, 'gif') || strcmp( fmt, 'bmp') 

   if fmt(1)=='j'
# jpeg: use djpeg to convert to pnm
      if wantgreyscale; pname= ['djpeg -grayscale -pnm ' fname];
      else              pname= ['djpeg -pnm ' fname ];
      end
   elseif fmt(1)=='g'
# gif: use giftopnm to convert to pnm
      if nargin > 2;
         pname= sprintf('giftopnm -image %d %s 2>/dev/null ',imgno,fname);
      else
         pname= ['giftopnm 2>/dev/null ' fname ];
      end
   elseif fmt(1)=='b'
# bmp: use bmptoppm to convert to pnm
      pname= ['bmptoppm 2>/dev/null ' fname ];
   elseif fmt(1)=='t'
# tiff: use tifftopnm to convert to pnm
      pname= ['tifftopnm 2>/dev/null ' fname ];
   else
# p?m: use cat so that we can open it with a pipe
      pname= ['cat ' fname ];
   end

   fid= popen(pname ,'r');
#
# can we open the pipe?
# if not 1) The file format is wrong and the conver program has bailed out
#        2) The apropriate converter program hasn't been installed
#
   if fid<0;
      error(['could not popen ' pname '. Are libgr-progs installed?']);
   end

# get file type
   line= fgetl( fid );
   if     strcmp(line, 'P1');   bpp=1; spp=1; bindata=0;
   elseif strcmp(line, 'P4');   bpp=1; spp=1; bindata=1;
   elseif strcmp(line, 'P2');   bpp=8; spp=1; bindata=0;
   elseif strcmp(line, 'P5');   bpp=8; spp=1; bindata=1;
   elseif strcmp(line, 'P3');   bpp=8; spp=3; bindata=0;
   elseif strcmp(line, 'P6');   bpp=8; spp=3; bindata=1;
   else error([fname 'does not appear to be a pnm file']);
   end

# ignore comments
   line= fgetl( fid );
   while length(line)==0 || line(1)=='#'
      line= fgetl( fid );
   end

# get width, height   
   [wid, hig]= sscanf( line, '%d %d', 'C' );

# get max component value
   if bpp==8
      max_component= sscanf( fgetl(fid), '%d' );
   end

   if bindata
      data= fread(fid);
      numdata= size(data,1);
      
      if bpp==1
         data= rem( floor( (data*ones(1,8)) ./ ...
                 (ones(length(data),1)*[128 64 32 16 8 4 2 1]) ), 2)';
      end
   else
      numdata= wid*hig*spp;
      data= zeros( numdata,1 );
      dptr= 1;
   
         line= fgetl( fid );
      while !feof( fid) 
         rdata= sscanf( line ,' %d');
         nptr= dptr + size(rdata,1);
         data( dptr:nptr-1 ) = rdata;
         dptr= nptr;
         line= fgetl( fid );
      end # feof
   end #if bindata

   fclose( fid );

   if spp==1
      greyimg= reshape( data(:), wid, hig )';
   elseif spp==3
      redimg= reshape( data(1:spp:numdata), wid, hig )';
      grnimg= reshape( data(2:spp:numdata), wid, hig )';
      bluimg= reshape( data(3:spp:numdata), wid, hig )';
   else
      error(sprintf("imread: don't know how to handle pnm with spp=%d",spp));
   end

elseif strcmp(fmt,'img') || strcmp(fmt,'octave')
   eval (['load ', fname]);
   
   if exist ("map") && ( exist("img") || exist("X") )
      if (exist ("img"))
         idximg = img;
      elseif (exist ("X"))
         idximg = X;
      end
   else
     error ("imread: invalid image file found");
   endif

elseif strcmp(fmt,'libtiff')
# 
# read a tif file using the libtiff library instead of libgr-progs
# it sometimes works better, which is bizarre because

   fid= popen(['tiffinfo -d ' fname],'r');
   if fid<0; error(['could not open tiffinfo ' fname ]); end

   while !feof( fid) 
      line= fgetl( fid );
      if length(line)<6; continue; end
      if strcmp(line(1:6), 'Strip ')
         break;
      end

# get all the number on the line
      nums= toascii(line);
      nums( nums<toascii('0') | nums>toascii('9'))= toascii(' ');
      nums= sscanf(setstr(nums),'%d');
      
      if     strcmp(line(3:12) , 'Image Widt')
         wid= nums(1); hig= nums(2);
      elseif strcmp(line(3:12) , 'Resolution')
         # DPI scanning resolution - not required
      elseif strcmp(line(3:12) , 'Bits/Sampl')
         bpp = nums(1);
      elseif strcmp(line(3:12) , 'Compressio')
         if !strcmp( line( length(line)+(-3:0) ),'None' )
            error('imread: compressed tiffs not supported. Bummer');
         end
      elseif strcmp(line(3:12) , 'Photometri')
      elseif strcmp(line(3:12) , 'Image Desc')
      elseif strcmp(line(3:12) , 'Orientatio')
      elseif strcmp(line(3:12) , 'Samples/Pi')
          spp= nums(1);
      elseif strcmp(line(3:12) , 'Rows/Strip')
      elseif strcmp(line(3:12) , 'Planar Con')
      end
   end

   numdata= wid*hig*spp;
   data= zeros( numdata,1 );
   dptr= 1;

   while !feof( fid) 
      rdata= sscanf( line ,' %x');
      nptr= dptr + size(rdata,1);
      data( dptr:nptr-1 ) = rdata;
      dptr= nptr;
      line= fgetl( fid );
   end # feof

   fclose( fid );

   if spp==1
      greyimg= reshape( data, wid, hig )';
   elseif spp==3
      redimg= reshape( data(1:spp:numdata), wid, hig )';
      grnimg= reshape( data(2:spp:numdata), wid, hig )';
      bluimg= reshape( data(3:spp:numdata), wid, hig )';
   else
      printf("imread: Warning: don't know how to handle tif with spp=%d\n",spp) 
;
# lets wing it and do the best we can
      data= mean(reshape( data(1:numdata), spp, wid*hig ));
      greyimg= reshape( data, wid, hig )';
   end

else
   error(['imread: format ' fmt ' is not supported. Bummer!']);
end

#   This section outputs the image in the desired output format
# if the user requested the colour map, the we regenerate it from
# the image. 
#
#   Of course, 1) This may result in huge colourmaps 
#              2) The colourmap will not be in the same order as
#                   in the original file

if wantgreyscale

   if exist('greyimg')
      out1= greyimg;
   elseif exist('idximg')
      greymap= mean(map')';
      out1= reshape( greymap( idximg ) , size(idximg,1), size(idximg,2) );
   else
      out1= ( redimg+grnimg+bluimg ) / 3 ;
   end

elseif wantmap

   if exist('idximg')
      out1= idximg;
      out2= map;
   elseif exist('greyimg')
      [simg, sidx] = sort( greyimg(:) );
      [jnkval, sidx] = sort( sidx );

      dimg= [1; diff(simg)>0 ];
      cimg= cumsum( dimg );
      out1= reshape( cimg( sidx ) , size(greyimg,1), size(greyimg,2) );
      out2= ( simg(find( dimg ))*[1,1,1] - 1)/255; 
   else
#
# attempt to generate a colourmap for r,g,b images, assume range is 0<v<1000
# for each value ( This will also be inaccurate for noninteger v )
# however, we shouldn't be getting any of that from the pnm converters
#
      [simg, sidx] = sort( round(redimg(:)) + ...
                       1e3*round(grnimg(:)) + ...
                       1e6*round(bluimg(:)) );
      [jnkval, sidx] = sort( sidx );

      dimg= [1; diff(simg)>0 ];
      cimg= cumsum( dimg );
      out1= reshape( cimg( sidx ) , size(redimg,1), size(redimg,2) );
      tmpv= simg(find( dimg )) - 1;
      out2= [ rem(tmpv,1000), rem(floor(tmpv/1e3), 1000), floor(tmpv/1e6) ]/255;
   end


else

   if exist('greyimg')
      out1= greyimg;
      out2= greyimg;
      out3= greyimg;
   else
      out1= redimg;
      out2= grnimg;
      out3= bluimg;
   end

end
   
unwind_protect_cleanup
empty_list_elements_ok= save_empty_list_elements_ok;
end_unwind_protect

----------endoffile: imread.m-----------



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

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



reply via email to

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