#open "windows";;
#open "camlwin";;
#open "sys";;


let ascii_0 = int_of_char `0`;;


let read_int Channel =
  let rec decode x start =
    let a = input_char Channel in
      if a = `#` then (input_line Channel; decode x start)
      else if a = ` ` or a = `\n`
           then if start then decode x true else x
           else decode (10*x+(int_of_char a) -ascii_0) false
  in
    decode 0 true
;;

let readpbm_head file_name =
  let in_file = open_in file_name in
    let format_type = input_line in_file 
    and width = read_int in_file 
    and height = read_int in_file 
    and nb_color = if (gr_suffix_only file_name) = "pbm" then 2 else read_int in_file in
      close_in in_file;
   {
     magic_number = format_type;
     pbm_width    = width;
     pbm_height   = height;
     pbmmax_color = nb_color
  }
;;

let read_ascii_color in_file width height max_color=
  let col_array = make_matrix height width 0 in
    let x = ref 0
    and y = ref 0 
    and read = ref 0 in
      while(!y<height) do
        let r = (read_int in_file) * 255 / max_color
        and g = (read_int in_file) * 255 / max_color
        and b = (read_int in_file) * 255 / max_color in
          let col = (r lsl 16) lor (g lsl 8) lor b in
            col_array.(!y).(!x) <- col;
              if !x<width-1 then x := !x+1 else (x := 0; y:= !y + 1)
    done;
  col_array
;;

let read_ascii_grey in_file width height max_color =
   let col_array = make_matrix height width 0 in
    let x = ref 0
    and y = ref 0 
    and read = ref 0 in
      while(!y<height) do
        let read = (read_int in_file) * 255 / max_color in
          let col = (read lsl 16) lor (read lsl 8) lor read in
            col_array.(!y).(!x) <- col;
              if !x<width-1 then x := !x+1 else (x := 0; y:= !y + 1)
    done;
  col_array
;;


let read_ascii_blackwhite in_file width height =
  let col_array = make_matrix height width 0 in
    let x = ref 0
    and y = ref 0 
    and read = ref 0 in
      while(!y<height) do
        let read =  if read_int in_file = 0 then white else black in
          col_array.(!y).(!x) <- read;
          if !x<width-1 then x := !x+1 else (x := 0; y:= !y + 1)
    done;
  col_array
;;



let read_raw_color in_file width height max_color =
  let col_array = make_matrix height width 0 in
    let x = ref 0
    and y = ref 0 
    and read = ref 0 in
      while(!y<height) do
        let r = (int_of_char (input_char in_file)) * 255 / max_color
        and g = (int_of_char (input_char in_file)) * 255 / max_color
        and b = (int_of_char (input_char in_file)) * 255 / max_color in
          let col = (r lsl 16) lor (g lsl 8) lor b in
            col_array.(!y).(!x) <- col;
              if !x<width-1 then x := !x+1 else (x := 0; y:= !y + 1)
    done;
  col_array
;;


let read_raw_grey in_file width height max_color =
  let col_array = make_matrix height width 0 in
    let x = ref 0
    and y = ref 0 
    and read = ref 0 in
      while(!y<height) do
        let read = (int_of_char (input_char in_file)) * 255 / max_color in
          let col = (read lsl 16) lor (read lsl 8) lor read in
            col_array.(!y).(!x) <- col;
              if !x<width-1 then x := !x+1 else (x := 0; y:= !y + 1)
    done;
  col_array
;;


let read_raw_blackwhite in_file width height =
  let col_array = make_matrix height width 0 in
    let x = ref 0
    and y = ref 0 
    and read = ref 0 in
      while(!y<height) do
        let read = int_of_char (input_char in_file) in
          for i = 0 to 7 do
            let mask = 0x80 lsr i in
              let col = if read land mask = 0 then white else black in
                if !x<width-1 then (col_array.(!y).(!x) <- col; x := !x+1 )
          done;
          if !x>=width-1 then (x := 0; y:= !y + 1)
    done;
  col_array
;;






let readpbm file_name =
  let in_file = open_in file_name in
    let format_type = input_line in_file 
    and width = read_int in_file 
    and height = read_int in_file 
    and nb_color = if (gr_suffix_only file_name) = "pbm" then 2 else read_int in_file in
        let result = 
              match format_type with
               "P1" -> read_ascii_blackwhite in_file width height
             | "P2" -> read_ascii_grey       in_file width height nb_color
             | "P3" -> read_ascii_color      in_file width height nb_color
             | "P4" -> read_raw_blackwhite   in_file width height
             | "P5" -> read_raw_grey         in_file width height nb_color
             | "P6" -> read_raw_color        in_file width height nb_color
             | _ ->    raise (Failure "read pbm: pbm unknown format")
       in
        close_in in_file;
        result
;;








