//  pgmio.sce - Copyright 2009 by Peter Urban
//
//  This program is free software: you can redistribute it and/or modify
//  it under the terms of the GNU General Public License as published by
//  the Free Software Foundation, either version 3 of the License, or
//  (at your option) any later version.
//
//  This program is distributed in the hope that it will be useful,
//  but WITHOUT ANY WARRANTY; without even the implied warranty of
//  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
//  GNU General Public License for more details.
//
//  You should have received a copy of the GNU General Public License
//  along with this program.  If not, see <http://www.gnu.org/licenses/>.

//reads a binary pgm image from a file
//path        - a string specifying the path of the image file
//image       - a matrix with greyvalues in the range [0,greylevels] 
//greylevels  - the maximum pixel greyvalue coresponding to white 
function [image,greylevels] = readpgm(path)
  if argn(2)<1,error(39),end;

  //checking for correct types
  if type(path)<>10,error(55,1),return,end;

  //open file in binary mode
  [infile,err] = mopen(path,"rb");
  if err<>0,error(err),return,end

  //check magic number
  line = mgetl(infile,1);
  if part(line,1:2)=="P5"
    //read PGM header
    disp("Reading image: "+path)
    line = mgetl(infile,1);
    while part(line,1)=='#'
      disp(line)
      line=mgetl(infile,1);
    end
    [m,n] = sscanf (line, "%ld %ld");
    [greylevels,err] = evstr(mgetl(infile,1));
    if err<>0,error(err),end;
    disp("dimensions x: "+string(m)+" y: "+string(n))
    disp("maximum grey value: "+string(greylevels))
    if greylevels>255
      //use 2byte per pixel in big endian encoding
      image = mget(m*n,"usb",infile);
    else
      //use 1byte per pixel
      image = mget(m*n,"uc",infile);
    end
    image = matrix(image,m,n)';
  else
    error("Unknown magic number "+line);
  end
  mclose(infile); 

endfunction

//writes a binary pgm image to a file
//image       - a matrix with greyvalues in the range [0,greylevels]
//path        - a string specifying the path of the image file
//greylevels  - the maximum pixel greyvalue coresponding to white (optional)
//comments    - a vector of strings containing comments written to the file
function writepgm(image,path,greylevels,comments)
  if argn(2)<2,error(39),end;

  //checking maximum grey value
  maxval=max(image);
  if argn(2)<3 
    if maxval>255;
      greylevels = 65535;
    else
      greylevels = 255;
    end    
  end
  if maxval>65535
    warning("Grey values exceed permitted range. Rescaling to 65535");
    image = image./maxval*65535;
    greylevels=65535;
  end  
  
  //setting up comments
  if argn(2)<4 
    comments = "#binary PGM file created on "+date();
  else
    comments="#"+comments;
  end
  
  //checking for correct types
  if type(image)<>1 & type(image)<>8          ,error(36,1),return,end;
  if type(path)<>10                           ,error(55,2),return,end;
  if type(greylevels)<>1 & type(greylevels)<>8,error(36,3),return,end;
  if type(comments)<>10                       ,error(55,4),return,end; 
    
  //rotate image about 90° 
  image=image';
  
  //open file in binary mode
  [outfile,err] = mopen(path,"wb");
  if err<>0,error(err),return,end;
    
  //write magic number      
  mputl("P5",outfile);
  //write comments
  mputl(comments,outfile);
  //image dimensions      
  mputl(string(size(image,1))+" "+string(size(image,2)),outfile);
  //maximum grey value      
  mputl(string(greylevels),outfile);          
  //write image data
  if greylevels>255
    //use 2byte per pixel in big endian encoding
    mput(uint16(image),"sb",outfile);
  else
    //use 1byte per pixel  
    mput(uint8(image),"c",outfile);
  end
  mclose(outfile); 
  disp("File "+path+" successfully written")
endfunction

//displays an image
//image       - a matrix with greyvalues in the range [0,greylevels]
//greylevels  - the maximum pixel greyvalue coresponding to white (optional)
function plotimage(image,greylevels)
  if argn(2)<1,error(39),end;
  
  //checking maximum grey value  
  if argn(2)<2 
    maxval=max(image);
    if maxval>255
      greylevels = 65535;
    else
      greylevels = 255;
    end
  end  

  //checking for correct types
  if type(image)<>1 & type(image)<>8           ,error(36,1),return,end
  if type(greylevels)<>1 & type(greylevels)<>8 ,error(36,2),return,end

  f=scf()
  Matplot(image)
  f.color_map = graycolormap(greylevels)
endfunction
