30 | `Rect of int * int * int * int
31 | `RGB of int * int * int
32 | `RGBA of int * int * int * int
33 | `ARGB of int * int * int * int
39 type s = [ byte | compose ]
43 | `Size of (int -> s list) * s list
46 type t = [ s | backpatch ]
48 let rec g_si mask shift n value =
49 unfold begin fun (n,value) ->
53 Some (mask value,(n-1,shift value))
57 g_si ((land) 0xff) (fun x -> x lsr 8) n value
64 BitsOut.put s ~width ~bits
66 if bits < - mask (width - 1) - 1 || mask (width - 1) < bits then
67 raise (Invalid_argument "SB");
68 BitsOut.put s ~width ~bits:(bits land mask width)
73 (bits -. int) *. float 0x1_00_00 in
75 BitsOut.put s ~width:16 ~bits:(int_of_float decimal) in
76 BitsOut.put t ~width:(width-16) ~bits:(int_of_float int)
78 let to_int : byte -> int list = function
81 | `Si16 n | `Ui16 n ->
83 | `Si24 n | `Ui24 n ->
85 | `Si32 n | `Ui32 n ->
87 (fun n -> Int32.to_int @@ Int32.logand 0xFFl n)
88 (fun n -> Int32.shift_right n 8)
92 (fun n -> Int64.to_int @@ Int64.logand 0xffL n)
93 (fun n -> Int64.shift_right n 8)
102 else if 0l < x && x <= 0x7Fl then
103 Some (Int32.to_int (Int32.logand x 0x7Fl),0l)
106 Int32.shift_right x 7 in
108 Int32.to_int @@ Int32.logor 0x80l @@ Int32.logand x 0x7Fl in
112 List.fold_left ~f:bits ~init:BitsOut.empty xs
120 float @@ 1 + HList.maximum xs in
121 int_of_float @@ 1. +. ceil (log bits /. log 2.)
123 let to_byte : compose -> byte list = function
128 (x -. int) *. float 0x1_00_00 in
129 [`Ui16 (int_of_float decimal);
130 `Ui16 (int_of_float int)]
135 (x -. int) *. float 0x1_00 in
136 [`Ui8 (int_of_float decimal);
137 `Ui8 (int_of_float int)]
139 [`Ui32 (Int32.bits_of_float x)]
141 [`Ui64 (Int64.bits_of_float x)]
142 | `Rect (x_min,x_max,y_min,y_max) ->
144 bit_width [x_min; x_max; y_min; y_max] in
146 SB(w, x_min); SB(w, x_max);
147 SB(w, y_min); SB(w, y_max)]]
149 [`Ui8 r; `Ui8 g; `Ui8 b]
151 [`Ui8 r; `Ui8 g; `Ui8 b; `Ui8 a]
152 | `ARGB(a, r, g, b) ->
153 [`Ui8 a; `Ui8 r; `Ui8 g; `Ui8 b]
155 List.map ~f:char (String.explode s) @ [`Ui8 0]
158 | `Matrix {scale; rotate; translate=(x,y) } ->
162 List.concat [ begin match scale with
167 16 + bit_width [int_of_float @@ ceil x; int_of_float @@ ceil y] in
168 [UB(1,1); UB(5,w); FB(w,x); FB(w,y)]
170 begin match rotate with
173 | Some (skew0, skew1) ->
175 16 + bit_width [int_of_float @@ ceil skew0; int_of_float @@ ceil skew1] in
176 [UB(1,1); UB(5,w); FB(w,skew0); FB(w,skew1)]
179 [ UB(5,t_w); SB(t_w,x); SB(t_w,y) ] ] in
182 let int_of_compose x =
184 #compose as c -> HList.concat_map to_int @@ to_byte c
185 | #byte as b -> to_int b
187 let backpatch (xs : [byte | backpatch] list) : int list =
189 List.fold_right xs ~init:(const [],0) ~f:begin fun x (f,size) ->
195 size + List.length ints in
196 ((fun ctx -> ints @ f ctx), size')
201 ((fun size -> to_int (`Ui32 (Int32.of_int size)) @ f size), size')
204 HList.concat_map int_of_compose xs in
208 HList.concat_map int_of_compose @@ g size' in
209 ((fun ctx -> i @ ints @ f ctx), List.length i + size'+size)
215 +> HList.concat_map begin function
217 | #compose as c -> (to_byte c :> [ byte | backpatch] list )
218 | #backpatch as bp -> [bp]