#IMREAD: read images into octave from various file formats
#bug-fixed version, because of octave problem with lab1 in ecf
#this version creates temp.pnm and does system call
#
# [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');
   system([pname," > temp.pnm"]);
   fid=fopen("temp.pnm","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 );
   system("rm -f temp.pnm"); #clean up

   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



