1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142
|
external rawget : string -> string
= "camltk_getimgdata"
external rawset : string -> string -> int -> int -> int -> int -> unit
= "camltk_setimgdata_bytecode" (* all int parameters MUST be positive *)
"camltk_setimgdata_native"
type t = {
pixmap_width : int;
pixmap_height: int;
pixmap_data: string
}
type pixel = string (* 3 chars *)
(* pixmap will be an abstract type *)
let width pix = pix.pixmap_width
let height pix = pix.pixmap_height
(* note: invalid size would have been caught by String.create, but we put
* it here for documentation purpose *)
let create w h =
if w < 0 || h < 0 then invalid_arg "invalid size"
else {
pixmap_width = w;
pixmap_height = h;
pixmap_data = String.create (w * h * 3);
}
(*
* operations on pixmaps
*)
let unsafe_copy pix_from pix_to =
String.unsafe_blit pix_from.pixmap_data 0
pix_to.pixmap_data 0
(String.length pix_from.pixmap_data)
(* We check only the length. w,h might be different... *)
let copy pix_from pix_to =
let l = String.length pix_from.pixmap_data in
if l <> String.length pix_to.pixmap_data then
raise (Invalid_argument "copy: incompatible length")
else unsafe_copy pix_from pix_to
(* Pixel operations *)
let unsafe_get_pixel pixmap x y =
let pos = (y * pixmap.pixmap_width + x) * 3 in
let r = String.create 3 in
String.unsafe_blit pixmap.pixmap_data pos r 0 3;
r
let unsafe_set_pixel pixmap x y pixel =
let pos = (y * pixmap.pixmap_width + x) * 3 in
String.unsafe_blit pixel 0 pixmap.pixmap_data pos 3
(* To get safe operations, we can either check x,y wrt [0,w[ and [0,h[
or rely on blit checking. We choose the first for clarity.
*)
let get_pixel pix x y =
if x < 0 || y < 0 || x >= pix.pixmap_width || y >= pix.pixmap_height
then invalid_arg "invalid pixel"
else unsafe_get_pixel pix x y
(* same check (pixel being abstract, it must be of good size *)
let set_pixel pix x y pixel =
if x < 0 || y < 0 || x >= pix.pixmap_width || y >= pix.pixmap_height
then invalid_arg "invalid pixel"
else unsafe_set_pixel pix x y pixel
(* black as default_color, if at all needed *)
let default_color = "\000\000\000"
(* Char.chr does range checking *)
let pixel r g b =
let s = String.create 3 in
s.[0] <- Char.chr r;
s.[1] <- Char.chr g;
s.[2] <- Char.chr b;
s
##ifdef CAMLTK
(* create pixmap from an existing image *)
let get photo =
match photo with
| PhotoImage s -> {
pixmap_width = CImagephoto.width photo;
pixmap_height = CImagephoto.height photo;
pixmap_data = rawget s;
}
(* copy a full pixmap into an image *)
let set photo pix =
match photo with
| PhotoImage s ->
rawset s pix.pixmap_data 0 0 pix.pixmap_width pix.pixmap_height
(* general blit of pixmap into image *)
let blit photo pix x y w h =
if x < 0 || y < 0 || w < 0 || h < 0 then invalid_arg "negative argument"
else match photo with
| PhotoImage s ->
rawset s pix.pixmap_data x y w h
(* get from a file *)
let from_file filename =
let img = CImagephoto.create [File filename] in
let pix = get img in
CImagephoto.delete img;
pix
##else
(* create pixmap from an existing image *)
let get photo =
match photo with
| `Photo s -> {
pixmap_width = Imagephoto.width photo;
pixmap_height = Imagephoto.height photo;
pixmap_data = rawget s;
}
(* copy a full pixmap into an image *)
let set photo pix =
match photo with
| `Photo s -> rawset s pix.pixmap_data 0 0 pix.pixmap_width pix.pixmap_height
(* general blit of pixmap into image *)
let blit photo pix x y w h =
if x < 0 || y < 0 || w < 0 || h < 0 then invalid_arg "negative argument"
else match photo with
| `Photo s -> rawset s pix.pixmap_data x y w h
(* get from a file *)
let from_file filename =
let img = Imagephoto.create ~file: filename () in
let pix = get img in
Imagephoto.delete img;
pix
##endif
|