Blame builtin/rawimg.ml

Packit bd2e5d
external rawget : string -> bytes
Packit bd2e5d
    = "camltk_getimgdata"
Packit bd2e5d
external rawset : string -> bytes -> int -> int -> int -> int -> unit
Packit bd2e5d
    = "camltk_setimgdata_bytecode"  (* all int parameters MUST be positive *)
Packit bd2e5d
      "camltk_setimgdata_native"
Packit bd2e5d
Packit bd2e5d
type t = {
Packit bd2e5d
  pixmap_width : int;
Packit bd2e5d
  pixmap_height: int;
Packit bd2e5d
  pixmap_data: bytes
Packit bd2e5d
}
Packit bd2e5d
Packit bd2e5d
let (.![]<-) = Bytes.set
Packit bd2e5d
Packit bd2e5d
type pixel = string  (* 3 chars *)
Packit bd2e5d
Packit bd2e5d
(* pixmap will be an abstract type *)
Packit bd2e5d
let width pix = pix.pixmap_width
Packit bd2e5d
let height pix = pix.pixmap_height
Packit bd2e5d
Packit bd2e5d
Packit bd2e5d
(* note: invalid size would have been caught by Bytes.create, but we put
Packit bd2e5d
 * it here for documentation purpose *)
Packit bd2e5d
let create w h =
Packit bd2e5d
  if w < 0 || h < 0 then invalid_arg "invalid size"
Packit bd2e5d
  else {
Packit bd2e5d
    pixmap_width = w;
Packit bd2e5d
    pixmap_height = h;
Packit bd2e5d
    pixmap_data = Bytes.create (w * h * 3);
Packit bd2e5d
  }
Packit bd2e5d
Packit bd2e5d
(*
Packit bd2e5d
 * operations on pixmaps
Packit bd2e5d
 *)
Packit bd2e5d
let unsafe_copy pix_from pix_to =
Packit bd2e5d
  Bytes.unsafe_blit pix_from.pixmap_data 0
Packit bd2e5d
                     pix_to.pixmap_data 0
Packit bd2e5d
                     (Bytes.length pix_from.pixmap_data)
Packit bd2e5d
Packit bd2e5d
(* We check only the length. w,h might be different... *)
Packit bd2e5d
let copy pix_from pix_to =
Packit bd2e5d
  let l = Bytes.length pix_from.pixmap_data in
Packit bd2e5d
  if l <> Bytes.length pix_to.pixmap_data then
Packit bd2e5d
    raise (Invalid_argument "copy: incompatible length")
Packit bd2e5d
  else unsafe_copy pix_from pix_to
Packit bd2e5d
Packit bd2e5d
Packit bd2e5d
(* Pixel operations *)
Packit bd2e5d
let unsafe_get_pixel pixmap x y =
Packit bd2e5d
  let pos = (y * pixmap.pixmap_width + x) * 3 in
Packit bd2e5d
  Bytes.sub_string pixmap.pixmap_data pos 3
Packit bd2e5d
Packit bd2e5d
let unsafe_set_pixel pixmap x y pixel =
Packit bd2e5d
  let pos = (y * pixmap.pixmap_width + x) * 3 in
Packit bd2e5d
  Bytes.unsafe_blit (Bytes.unsafe_of_string pixel) 0 pixmap.pixmap_data pos 3
Packit bd2e5d
Packit bd2e5d
(* To get safe operations, we can either check x,y wrt [0,w[ and [0,h[
Packit bd2e5d
   or rely on blit checking. We choose the first for clarity.
Packit bd2e5d
 *)
Packit bd2e5d
let get_pixel pix x y =
Packit bd2e5d
  if x < 0 || y < 0 || x >= pix.pixmap_width || y >= pix.pixmap_height
Packit bd2e5d
  then invalid_arg "invalid pixel"
Packit bd2e5d
  else unsafe_get_pixel pix x y
Packit bd2e5d
Packit bd2e5d
(* same check (pixel being abstract, it must be of good size *)
Packit bd2e5d
let set_pixel pix x y pixel =
Packit bd2e5d
  if x < 0 || y < 0 || x >= pix.pixmap_width || y >= pix.pixmap_height
Packit bd2e5d
  then invalid_arg "invalid pixel"
Packit bd2e5d
  else unsafe_set_pixel pix x y pixel
Packit bd2e5d
Packit bd2e5d
(* black as default_color, if at all needed *)
Packit bd2e5d
let default_color = "\000\000\000"
Packit bd2e5d
Packit bd2e5d
(* Char.chr does range checking *)
Packit bd2e5d
let pixel r g b =
Packit bd2e5d
  let s = Bytes.create 3 in
Packit bd2e5d
  s.![0] <- Char.chr r;
Packit bd2e5d
  s.![1] <- Char.chr g;
Packit bd2e5d
  s.![2] <- Char.chr b;
Packit bd2e5d
  Bytes.unsafe_to_string s
Packit bd2e5d
Packit bd2e5d
##ifdef CAMLTK
Packit bd2e5d
Packit bd2e5d
(* create pixmap from an existing image *)
Packit bd2e5d
let get photo =
Packit bd2e5d
  match photo with
Packit bd2e5d
  | PhotoImage s -> {
Packit bd2e5d
      pixmap_width = CImagephoto.width photo;
Packit bd2e5d
      pixmap_height = CImagephoto.height photo;
Packit bd2e5d
      pixmap_data = rawget s;
Packit bd2e5d
    }
Packit bd2e5d
Packit bd2e5d
(* copy a full pixmap into an image *)
Packit bd2e5d
let set photo pix =
Packit bd2e5d
  match photo with
Packit bd2e5d
  | PhotoImage s ->
Packit bd2e5d
      rawset s pix.pixmap_data 0 0 pix.pixmap_width pix.pixmap_height
Packit bd2e5d
Packit bd2e5d
(* general blit of pixmap into image *)
Packit bd2e5d
let blit photo pix x y w h =
Packit bd2e5d
  if x < 0 || y < 0 || w < 0 || h < 0 then invalid_arg "negative argument"
Packit bd2e5d
  else match photo with
Packit bd2e5d
  | PhotoImage s ->
Packit bd2e5d
      rawset s pix.pixmap_data x y w h
Packit bd2e5d
Packit bd2e5d
(* get from a file *)
Packit bd2e5d
let from_file filename =
Packit bd2e5d
  let img = CImagephoto.create [File filename] in
Packit bd2e5d
  let pix = get img in
Packit bd2e5d
  CImagephoto.delete img;
Packit bd2e5d
  pix
Packit bd2e5d
Packit bd2e5d
##else
Packit bd2e5d
Packit bd2e5d
(* create pixmap from an existing image *)
Packit bd2e5d
let get photo =
Packit bd2e5d
  match photo with
Packit bd2e5d
  | `Photo s -> {
Packit bd2e5d
      pixmap_width = Imagephoto.width photo;
Packit bd2e5d
      pixmap_height = Imagephoto.height photo;
Packit bd2e5d
      pixmap_data = rawget s;
Packit bd2e5d
    }
Packit bd2e5d
Packit bd2e5d
(* copy a full pixmap into an image *)
Packit bd2e5d
let set photo pix =
Packit bd2e5d
  match photo with
Packit bd2e5d
  | `Photo s -> rawset s pix.pixmap_data 0 0 pix.pixmap_width pix.pixmap_height
Packit bd2e5d
Packit bd2e5d
(* general blit of pixmap into image *)
Packit bd2e5d
let blit photo pix x y w h =
Packit bd2e5d
  if x < 0 || y < 0 || w < 0 || h < 0 then invalid_arg "negative argument"
Packit bd2e5d
  else match photo with
Packit bd2e5d
  | `Photo s -> rawset s pix.pixmap_data x y w h
Packit bd2e5d
Packit bd2e5d
(* get from a file *)
Packit bd2e5d
let from_file filename =
Packit bd2e5d
  let img = Imagephoto.create ~file: filename () in
Packit bd2e5d
  let pix = get img in
Packit bd2e5d
  Imagephoto.delete img;
Packit bd2e5d
  pix
Packit bd2e5d
Packit bd2e5d
##endif