open Printf
open Bigarray

(* from http://rosettacode.org/wiki/Read_ppm_file#OCaml *)
let read_ppm ~filename =
  Printf.printf "Trying to read %s.\n" filename;
  let ic = open_in filename in
  let line = input_line ic in
  if line <> "P6" then invalid_arg "not a P6 ppm file";
  let line = input_line ic in
  let line =
    try if line.[0] = '#'  (* skip comments *)
    then input_line ic
    else line
    with _ -> line
  in
  let width, height =
    Scanf.sscanf line "%d %d" (fun w h -> (w, h))
  in
    Printf.printf "%dx%d\n" width height;
  let line = input_line ic in
  if line <> "255" then invalid_arg "not a 8 bit depth image";
  let all_channels =
    let kind = Bigarray.int8_unsigned
    and layout = Bigarray.c_layout
    in 
      Array3.create kind layout height width 3
  in
    try  (* shouldn't need this try! *)
      for y = 0 to pred height do 
        for x = 0 to pred width do 
          all_channels.{y,x,0} <- (input_byte ic);
          all_channels.{y,x,1} <- (input_byte ic);
          all_channels.{y,x,2} <- (input_byte ic);
        done;
      done;
      close_in ic;
      all_channels 
    with End_of_file -> close_in ic; all_channels
(*,
   r_channel,
   g_channel,
   b_channel)   *)

let output_ppm ~filename 
      ~(all_channels:
          (int, Bigarray.int8_unsigned_elt, Bigarray.c_layout) Array3.t ) =
  Printf.printf "\n dim=%dx%dx%d\n" 
    ( Array3.dim1 all_channels )
    ( Array3.dim2 all_channels )
    ( Array3.dim3 all_channels );
  let width = Bigarray.Array3.dim2 all_channels
  and height = Bigarray.Array3.dim1 all_channels in
    Printf.printf "Image size = %dx%d\n" width height;
  let oc = open_out filename in 
    Printf.fprintf oc "P6\n%d %d\n255 " width height;
    try  (* shouldn't need this try! *) 
      for y = 0 to pred height do
        for x = 0 to pred width do
          (*Printf.printf "(y=%d,x=%d)..." y x; *)
          output_char oc (char_of_int all_channels.{y,x,0});
          output_char oc (char_of_int all_channels.{y,x,1});
          output_char oc (char_of_int all_channels.{y,x,2});
          (*Printf.printf "success\n"; *)
        done;
      done;
      output_char oc '\n';
      flush oc;
      close_out oc;
    with End_of_file ->
  output_char oc '\n';
  flush oc;
  close_out oc;
;;
