|
| 1 | +open! Base |
| 2 | +module In = Stdlib.In_channel |
| 3 | +module Out = Stdlib.Out_channel |
| 4 | +module Scanf = Stdlib.Scanf.Scanning |
| 5 | + |
| 6 | +type t = |
| 7 | + { width : int |
| 8 | + ; height : int |
| 9 | + ; data : float array |
| 10 | + } |
| 11 | + |
| 12 | +let save { width; height; data } file = |
| 13 | + Out.with_open_text file (fun out -> |
| 14 | + let header = Stdlib.Printf.sprintf "P2\n%d %d\n255\n" width height in |
| 15 | + let data = |
| 16 | + Array.(fold_right [@mode shared]) data ~init:[] ~f:(fun x acc -> |
| 17 | + (x |
| 18 | + |> Float.clamp_exn ~min:0.0 ~max:1.0 |
| 19 | + |> Float.( * ) 255.0 |
| 20 | + |> Float.round_nearest |
| 21 | + |> Float.to_int |
| 22 | + |> Int.to_string) |
| 23 | + :: acc) |
| 24 | + |> List.chunks_of ~length:width |
| 25 | + |> List.map ~f:(String.concat ~sep:" ") |
| 26 | + |> String.concat ~sep:"\n" |
| 27 | + in |
| 28 | + Out.output_string out header; |
| 29 | + Out.output_string out data; |
| 30 | + Out.output_string out "\n") |
| 31 | +;; |
| 32 | + |
| 33 | +let load file = |
| 34 | + In.with_open_text file (fun in_ -> |
| 35 | + let in_ = Scanf.from_channel in_ in |
| 36 | + let width, height, max = |
| 37 | + Stdlib.Scanf.bscanf in_ "P2\n%d %d\n%d\n" (fun width height max -> |
| 38 | + width, height, max) |
| 39 | + in |
| 40 | + let max = Float.of_int max in |
| 41 | + let data = |
| 42 | + Array.init (width * height) ~f:(fun _ -> |
| 43 | + Stdlib.Scanf.bscanf in_ " %f " (fun f -> f /. max)) |
| 44 | + in |
| 45 | + Scanf.close_in in_; |
| 46 | + { width; height; data }) |
| 47 | +;; |
| 48 | + |
| 49 | +let of_array data ~width ~height = |
| 50 | + if Array.length data <> width * height then invalid_arg "mismatched array size"; |
| 51 | + { width; height; data } |
| 52 | +;; |
| 53 | + |
| 54 | +let width { width; _ } = width |
| 55 | +let height { height; _ } = height |
| 56 | + |
| 57 | +let get { data; width; _ } ~x ~y = |
| 58 | + let idx = x + (y * width) in |
| 59 | + (Array.get [@mode shared]) data idx |
| 60 | +;; |
| 61 | + |
| 62 | +let set { data; width; _ } ~x ~y p = |
| 63 | + let idx = x + (y * width) in |
| 64 | + Array.set data idx p |
| 65 | +;; |
0 commit comments