package camlimages
Image processing library
Install
dune-project
Dependency
Authors
Maintainers
Sources
camlimages-5.0.4.tar.bz2
sha256=1c9a68bdc3d348c9f859d490dadf384926213e47a584159832f7fc4a20242865
md5=1ddba74d210b86a899b5d6565f45c2dc
doc/src/camlimages.jpeg/jpeg.ml.html
Source file jpeg.ml
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 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312
(***********************************************************************) (* *) (* Objective Caml *) (* *) (* François Pessaux, projet Cristal, INRIA Rocquencourt *) (* Pierre Weis, projet Cristal, INRIA Rocquencourt *) (* Jun Furuse, projet Cristal, INRIA Rocquencourt *) (* *) (* Copyright 1999-2004 *) (* Institut National de Recherche en Informatique et en Automatique. *) (* Distributed only by permission. *) (* *) (***********************************************************************) (* $Id: jpeg.ml,v 1.4 2009/07/04 03:39:28 furuse Exp $ *) open Util open Images open Rgb24 module Pervasives = Stdlib type in_handle module Marker = struct type raw = { code : int; data : string } type t = | Comment of string | App of int * string let t_of_raw r = match r.code with | 0xFE -> Comment r.data | n -> App (n - 0xE0, r.data) let raw_of_t = function | Comment s -> { code = 0xFE; data = s } | App (n, s) -> { code = 0xE0 + n; data = s } open Format let format ppf = function | Comment s -> fprintf ppf "Comment: %s" s | App (n, s) -> fprintf ppf "App%d (%d bytes)" n (String.length s) end external open_in_header : string -> int * int * in_handle * Marker.raw list = "open_jpeg_file_for_read" external set_scale_denom : in_handle -> int -> unit = "jpeg_set_scale_denom" external open_in_start : in_handle -> int * int * in_handle = "open_jpeg_file_for_read_start" external read_scanline : in_handle -> bytes -> int -> unit = "read_jpeg_scanline" external read_scanlines : in_handle -> bytes -> int -> int -> unit = "read_jpeg_scanlines" external close_in : in_handle -> unit = "close_jpeg_file_for_read" type out_handle external open_out : string -> int -> int -> int -> out_handle = "open_jpeg_file_for_write" external open_out_cmyk : string -> int -> int -> int -> out_handle = "open_jpeg_file_for_write_cmyk" external write_marker : out_handle -> Marker.raw -> unit = "caml_jpeg_write_marker" external write_scanline : out_handle -> bytes -> unit = "write_jpeg_scanline" external close_out : out_handle -> unit = "close_jpeg_file_for_write" let open_in name = let _, _, ic, rev_markers = open_in_header name in let w, h, ic = open_in_start ic in w, h, ic, List.rev_map Marker.t_of_raw rev_markers let open_in_thumbnail name geom_spec = if geom_spec.Geometry.spec_aspect = Geometry.Dont_keep then raise (Invalid_argument "Jpeg.open_in_thumbnail: illegal geom_spec"); let image_width, image_height, ic, rev_markers = open_in_header name in let scale = try let geom = Geometry.compute geom_spec image_width image_height in (* prerr_endline (Printf.sprintf "Denom %d/%d" image_width geom.Geometry.geom_width); *) image_width / geom.Geometry.geom_width with | _ -> 1 in let denom = if scale < 2 then 1 else if scale < 4 then 2 else if scale < 8 then 4 else 8 in set_scale_denom ic denom; image_width, image_height, open_in_start ic, List.rev_map Marker.t_of_raw rev_markers let load_aux prog ic w h = let prog y = match prog with | Some p -> p (float (y + 1) /. float h) | None -> () in let img = Rgb24.create w h in begin match Rgb24.get_scanline_ptr img with | Some f -> let load_once_at = max 1 (h / 10) in let rec load_scanlines y = if y >= h then () else begin let (string, off), at_most = f y in let lines_read = min load_once_at at_most in read_scanlines ic string off lines_read; prog y; load_scanlines (y + lines_read) end in load_scanlines 0 | None -> (* CR jfuruse: check overflow *) let scanline = Bytes.create (w * 3) in for y = 0 to h - 1 do read_scanline ic scanline 0; Rgb24.set_scanline img y scanline; prog y done end; close_in ic; Rgb24 img let load name load_opts = let w, h, ic, _markers = open_in name in let prog = Images.load_progress load_opts in load_aux prog ic w h let load_thumbnail name load_opts geom_spec = let prog = Images.load_progress load_opts in let ow, oh, (w, h, ic), _markers = open_in_thumbnail name geom_spec in ow, oh, load_aux prog ic w h let save_with_markers name opts image markers = let quality = match Images.save_quality opts with | Some q -> q | None -> 80 in let prog = Images.save_progress opts in match image with | Rgb24 bmp -> let oc = open_out name bmp.width bmp.height quality in List.iter (fun mrk -> write_marker oc (Marker.raw_of_t mrk)) markers; for y = 0 to bmp.height - 1 do write_scanline oc (Rgb24.get_scanline bmp y); match prog with | Some p -> p (float (y + 1) /. float bmp.height) | None -> () done; close_out oc | _ -> raise Wrong_image_type let save name opts image = save_with_markers name opts image [] let save_as_cmyk name opts trans image = let quality = match Images.save_quality opts with | Some q -> q | None -> 80 in let prog = Images.save_progress opts in let get_cmyk_scanline width scanline = let buf = Bytes.create (width * 4) in for x = 0 to width - 1 do let r = scanline @% x * 3 + 0 in let g = scanline @% x * 3 + 1 in let b = scanline @% x * 3 + 2 in let c, m, y, k = trans {r = r; g = g; b = b} in buf << x * 4 + 0 & char_of_int (255 - c); buf << x * 4 + 1 & char_of_int (255 - m); buf << x * 4 + 2 & char_of_int (255 - y); buf << x * 4 + 3 & char_of_int (255 - k) done; buf in match image with | Rgb24 bmp -> let oc = open_out_cmyk name bmp.width bmp.height quality in for y = 0 to bmp.height - 1 do let buf = get_cmyk_scanline bmp.width (Rgb24.get_scanline bmp y) in write_scanline oc buf; match prog with | Some p -> p (float (y + 1) /. float bmp.height) | None -> () done; close_out oc | _ -> raise Wrong_image_type let save_cmyk_sample name opts = let quality = match Images.save_quality opts with | Some q -> q | None -> 80 in let _prog = Images.save_progress opts in let sample_point x y = let c = x / 16 * 17 and m = (x mod 16) * 17 and y = y / 16 * 17 and k = (y mod 16) * 17 in c, m, y, k in let sample_scan y = let s = Bytes.create (256 * 4) in for x = 0 to 255 do let c, m, y, k = sample_point x y in s << x * 4 + 0 & char_of_int c; s << x * 4 + 1 & char_of_int m; s << x * 4 + 2 & char_of_int y; s << x * 4 + 3 & char_of_int k; done; s in let oc = open_out_cmyk name 256 256 quality in for y = 0 to 256 - 1 do let buf = sample_scan y in write_scanline oc buf done; close_out oc let find_jpeg_size_and_colormodel ic = (* jump to the next 0xff *) let rec loop () = let rec jump_to_0xff () = let ch = int_of_char (input_char ic) in if ch <> 0xff then jump_to_0xff () in let rec jump_to_non_0xff () = let ch = int_of_char (input_char ic) in if ch = 0xff then jump_to_non_0xff () else ch in jump_to_0xff (); let ch = jump_to_non_0xff () in let str = Bytes.create 5 in match ch with | 0xda (* SOS *) -> raise Not_found | _ when ch >= 0xc0 (* SOF0 *) && ch <= 0xc3 (* SOF3 *) -> really_input ic str 0 3; (* Lf and P *) really_input ic str 0 5; (* Y, X, and Nf *) let colormodel = (* Number of components *) match str @% 4 with | 1 -> Some (Info_ColorModel Gray) | 3 -> Some (Info_ColorModel YCbCr) | 4 -> Some (Info_ColorModel CMYK) | _ -> None in (str @% 2) lsl 8 + (str @% 3), (* width *) (str @% 0) lsl 8 + (str @% 1), (* height *) colormodel | _ -> (* skip this block *) let blocklen = really_input ic str 0 2; (str @% 0) lsl 8 + (str @% 1) in let s = Bytes.create (blocklen - 2) in really_input ic s 0 (blocklen - 2); loop () in try loop () with | _ -> raise Not_found (* any error returns Not_found *) let check_header filename = let len = 2 in let ic = open_in_bin filename in try let str = Bytes.create len in really_input ic str 0 len; if (* I had some jpeg started with 7f58, the 7th bits were missing... *) (* int_of_char str.[0] lor 0x80 = 0xff && int_of_char str.[1] lor 0x80 = 0xd8 *) (str @% 0) = 0xff && (str @% 1) = 0xd8 (* && String.sub str 6 4 = "JFIF" --- JFIF standard *) then begin let w, h, infos = try let w, h, colormodel = find_jpeg_size_and_colormodel ic in w, h, match colormodel with Some x -> [x] | None -> [] with | Not_found -> -1, -1, [] in Pervasives.close_in ic; { header_width = w; header_height = h; header_infos = infos; } end else raise Wrong_file_type with | _ -> Pervasives.close_in ic; raise Wrong_file_type let read_markers filename = let _, _, ic, rev_markers = open_in_header filename in close_in ic; List.rev_map Marker.t_of_raw rev_markers let write_marker oh mrk = write_marker oh (Marker.raw_of_t mrk) let () = add_methods Jpeg { check_header = check_header; load = Some load; save = Some save; load_sequence = None; save_sequence = None}
sectionYPositions = computeSectionYPositions($el), 10)"
x-init="setTimeout(() => sectionYPositions = computeSectionYPositions($el), 10)"
>