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 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534
|
(***********************************************************************)
(* *)
(* Objective Caml *)
(* *)
(* Jun Furuse, projet Cristal, INRIA Rocquencourt *)
(* *)
(* Copyright 1999,2000,2001,2002,2001,2002 *)
(* Institut National de Recherche en Informatique et en Automatique. *)
(* Distributed only by permission. *)
(* *)
(***********************************************************************)
open Lvmisc
open Gui
open Tout
open Gdk
open GDraw
open GMain
open Ximage
open OXimage
type filter = [ `TRANSPARENT_BORDER
| `SIZE of int * int * [ `ATMOST | `ATLEAST | `ALWAYS ]
| `NORMALIZE | `ENHANCE ]
let filters = (ref [] : filter list ref)
class type display = object
method display : Ximage.t -> unit
end
class win = object
val mutable backstore = (None : OXimage.ximage option)
method display ximage =
let oldbackstore = backstore in
backstore <- None;
darea#set_size ~width: ximage#width ~height: ximage#height;
fixed#misc#set_geometry ~width: ximage#width ~height: ximage#height ();
backstore <- Some ximage;
sync ();
set_timeout ()
initializer
darea#event#connect#expose ~callback: (fun ev ->
begin match backstore with
| Some ximage ->
let area = GdkEvent.Expose.area ev in
let x = Gdk.Rectangle.x area in
let y = Gdk.Rectangle.y area in
let width =
min (ximage#width - x) (Gdk.Rectangle.width area)
in
let height =
min (ximage#height - y) (Gdk.Rectangle.height area)
in
(*
prerr_endline (Printf.sprintf "Expose some (%d)%dx%d+%d+%d"
(GdkEvent.Expose.count ev)
width height x y);
*)
drawing#put_image ~width ~height
~xsrc: x ~ysrc: y
~x: x ~y: y ximage#data
| None -> ()
end; true);
()
end
let root_pixmap = lazy begin
let pix = GDraw.pixmap ~window
~width: screen_width
~height: screen_height ()
in
pix#set_foreground `BLACK;
pix#rectangle ~x:0 ~y:0 ~width: screen_width ~height: screen_height
~filled: true ();
pix#pixmap
end
let root_drawing = lazy begin
new drawable !!root_pixmap
end
type root_geom = {
width : int;
height : int;
xdest : int;
xsrc : int;
ydest : int;
ysrc : int;
put_width : int;
put_height : int
}
let root_geom ximage x y =
let width0 = ximage#width in
let height0 = ximage#height in
let xdest0 = if x < 0 then 0 else x in
let xsrc0 = if x < 0 then -x else 0 in
let put_width0 =
if x + width0 > screen_width then screen_width - xdest0
else x + width0 - xdest0
in
let ydest0 = if y < 0 then 0 else y in
let ysrc0 = if y < 0 then -y else 0 in
let put_height0 =
if y + height0 > screen_height then screen_height - ydest0
else y + height0 - ydest0
in
{ width= width0;
height= height0;
xdest= xdest0;
ydest= ydest0;
xsrc= xsrc0;
ysrc= ysrc0;
put_width= put_width0;
put_height= put_height0;
}
class root =
object
method display_at (ximage : OXimage.ximage) x y =
let geom = root_geom ximage x y in
!!root_drawing#put_image ximage#data
~xsrc: geom.xsrc ~ysrc: geom.ysrc
~x: geom.xdest ~y: geom.ydest
~width: geom.put_width ~height: geom.put_height;
Window.set_back_pixmap root_win (`PIXMAP(!!root_pixmap));
Window.clear root_win;
set_timeout ()
end
(*
class virtual root_random = object (self)
method virtual display_at : OXimage.ximage -> int -> int -> unit
method display ximage =
let w = screen_width - ximage#width
and h = screen_height - ximage#height
in
let overwrap x y =
match !root_prev_pos with
| None -> 0
| Some (pw,ph,px,py) ->
let w = min (x + w - 1) (px + pw - 1) - max x px in
let h = min (y + h - 1) (py + ph - 1) - max y py in
if w < 0 || h < 0 then 0 else w * h
in
let random_x_y () =
let x = if w <= 0 then w / 2 else Random.int w
and y = if h <= 0 then h / 2 else Random.int h
in (x,y),overwrap x y
in
let min = ref (random_x_y ()) in
for i = 0 to 10 do
let (x,y),over = random_x_y () in
if snd !min > over then begin
prerr_endline (Printf.sprintf "%d" over);
min := (x,y),over
end
done;
let x, y = fst !min in
root_prev_pos := Some (w,h,x,y);
self#display_at ximage x y
end
class virtual root_center = object (self)
method virtual display_at : OXimage.ximage -> int -> int -> unit
method display ximage =
let w = screen_width - ximage#width
and h = screen_height - ximage#height
in
self#display_at ximage (w/2) (h/2)
end
*)
(* src will be modified *)
let transparent_border src geom dst =
let width = src#width
and height = src#height in
let src = src#data in
let dst = dst#data in
let color_at image x y = quick_color_parser (Image.get_pixel image ~x ~y) in
let border = min width height / 10 + 1 in
let doit b x y ox oy =
let cd = color_at src x y in
let co = color_at dst ox oy in
let red,green,blue = color_merge co cd (border + 1) b in
let pixel = quick_color_create ~red ~green ~blue in
Image.put_pixel src ~x: x ~y: y ~pixel
in
for b = 0 to border do
let y = b in
let oy = y - geom.ysrc in
if oy < 0 || oy >= geom.put_height then ()
else begin
for x = b to width - b - 1 do
let ox = x - geom.xsrc in
if ox < 0 ||ox >= geom.put_width then ()
else doit b x y ox oy
done
end;
let y = height - b - 1 in
let oy = y - geom.ysrc in
if oy < 0 || oy >= geom.put_height then ()
else begin
for x = b to width - b - 1 do
let ox = x - geom.xsrc in
if ox < 0 ||ox >= geom.put_width then ()
else doit b x y ox oy
done
end;
let x = b in
let ox = x - geom.xsrc in
if ox < 0 || ox >= geom.put_height then ()
else begin
for y = b + 1 to height - b - 2 do
let oy = y - geom.ysrc in
if oy < 0 || oy >= geom.put_height then ()
else doit b x y ox oy
done
end;
let x = width - b - 1 in
let ox = x - geom.xsrc in
if ox < 0 || ox >= geom.put_width then ()
else begin
for y = b + 1 to height - b - 2 do
let oy = y - geom.ysrc in
if oy < 0 ||oy >= geom.put_height then ()
else doit b x y ox oy
done
end;
done
;;
class root_filter =
object
inherit root as super
method display_at ximage x y =
let geom = root_geom ximage x y in
let dst = lazy begin
OXimage.get_image !!root_pixmap ~x: geom.xdest ~y: geom.ydest
~width: geom.put_width ~height: geom.put_height;
end
in
List.iter (function
| `TRANSPARENT_BORDER ->
transparent_border ximage geom !!dst
| _ -> ()) !filters;
super#display_at ximage x y
end
class root_myst = object
inherit root_filter as super
val mutable id = None
val mutable finish = fun () -> ()
method display_at ximage x y =
let geom = root_geom ximage x y in
let array =
Array.init (geom.put_width * geom.put_height)
(fun x -> x mod geom.put_width, x / geom.put_width)
in
for i = 0 to geom.put_width * geom.put_height - 1 do
let pos = Random.int (geom.put_width * geom.put_height - 1) in
let tmp = array.(i) in
array.(i) <- array.(pos);
array.(pos) <- tmp
done;
let cntr = ref 0 in
finish <- (fun () -> super#display_at ximage x y);
id <- Some (Timeout.add ~ms:100 ~callback: (fun () ->
try
for i = 0 to geom.put_width * geom.put_height / 10 do
let x, y = array.(!cntr) in
!!root_drawing#put_image ximage#data
~xsrc: (geom.xsrc+x) ~ysrc: (geom.ysrc+y)
~x: (geom.xdest+x) ~y: (geom.ydest+y)
~width: 1 ~height: 1;
incr cntr;
if !cntr = geom.put_width * geom.put_height then raise Exit
done;
Window.set_back_pixmap root_win (`PIXMAP(!!root_pixmap));
Window.clear root_win;
true
with
Exit ->
Window.set_back_pixmap root_win (`PIXMAP(!!root_pixmap));
Window.clear root_win;
prerr_endline "finished";
id <- None;
set_timeout ();
false))
method force_finish =
match id with
| Some i ->
Timeout.remove i;
id <- None;
finish ();
finish <- fun () -> ()
| None -> ()
end
(*
class display_root_transparent ximage x y =
object (self)
inherit display_root_myst ximage x y as super
method display =
let orgimg = self#orgimg in
let tmpimg = self#tmpimg in
self#init;
let max = 4 in
cntr <- 1;
id <- Some (Timeout.add ~ms:100 ~callback: (fun () ->
for y = 0 to geom.put_height - 1 do
for x = 0 to geom.put_width - 1 do
let cd =
quick_color_parser (Image.get_pixel ximage#data
~x:(geom.xsrc+x) ~y:(geom.ysrc+y))
in
let co =
quick_color_parser (Image.get_pixel orgimg ~x ~y)
in
let red,green,blue = color_merge co cd max cntr in
let pixel =
quick_color_create ~red ~green ~blue
in
Image.put_pixel tmpimg ~x ~y ~pixel;
done
done;
if cntr = max then begin
drawing_root_pixmap#put_image tmpimg
~xsrc:0 ~ysrc:0 ~xdest: geom.xdest ~ydest: geom.ydest
~width: geom.put_width ~height: geom.put_height;
Window.set_back_pixmap root_win ~pixmap: (`PIXMAP(pix));
Window.clear root_win;
finished <- true;
self#free_tmps;
set_timeout ();
false
end else begin
drawing_root#put_image tmpimg
~xsrc:0 ~ysrc:0 ~xdest: geom.xdest ~ydest: geom.ydest
~width: geom.put_width ~height: geom.put_height;
cntr <- cntr + 1;
true
end))
end
*)
type root_mode = [`NONE|`CENTER|`RANDOM]
type transition = [`NONE|`MYST|`TRANSPARENT]
let root_mode = ref (`NONE : root_mode)
let transition = ref (`NONE : transition)
let win = new win
let root = new root_filter
let root_myst = new root_myst
let root_prev_pos = ref None
let display_ximage ximage =
match !root_mode with
| `CENTER | `RANDOM ->
let x, y =
let w = screen_width - ximage#width
and h = screen_height - ximage#height
in
match !root_mode with
| `RANDOM ->
let w = screen_width - ximage#width
and h = screen_height - ximage#height
in
let overwrap x y =
match !root_prev_pos with
| None -> 0
| Some (pw,ph,px,py) ->
let w = min (x + w - 1) (px + pw - 1) - max x px in
let h = min (y + h - 1) (py + ph - 1) - max y py in
if w < 0 || h < 0 then 0 else w * h
in
let random_x_y () =
let x = if w <= 0 then w / 2 else Random.int w
and y = if h <= 0 then h / 2 else Random.int h
in (x,y),overwrap x y
in
let min = ref (random_x_y ()) in
for i = 0 to 5 do
let (x,y),over = random_x_y () in
if snd !min > over then begin
prerr_endline (Printf.sprintf "%d" over);
min := (x,y),over
end
done;
let x,y = fst !min in
root_prev_pos := Some (w,h,x,y);
x,y
| _ ->
w/2, h/2
in
begin match !transition with
| `MYST ->
root_myst#display_at ximage x y
(*
| `TRANSPARENT ->
new display_root_transparent ximage x y
*)
| _ ->
root#display_at ximage x y
end
| _ ->
win#display ximage
;;
let display image =
let image = ref image in
let get_hist img =
prog#set_format_string "histgram";
let hist = Colorhist.create () in
let width = img#width in
let height = img#height in
let f_height = float height in
for y = 0 to height - 1 do
for x = 0 to width - 1 do
Colorhist.store_sample hist (img#unsafe_get x y)
done;
prog#set_percentage (float (y+1) /. f_height)
done;
hist
in
List.iter (function
| `SIZE(w,h,cond) ->
let old = !image in
let mag =
let mag =
let xmag = float w /. float old#width
and ymag = float h /. float old#height
in
if xmag > ymag then ymag else xmag
in
let mag =
match cond with
| `ALWAYS -> mag
| `ATMOST -> if mag > 1.0 then 1.0 else mag
| `ATLEAST -> if mag < 1.0 then 1.0 else mag
in
let nw = truncate (float old#width *. mag)
and nh = truncate (float old#height *. mag)
in
if nw > fst root_size || nh > snd root_size then begin
let xmag = float (fst root_size) /. float old#width
and ymag = float (snd root_size) /. float old#height
in
if xmag > ymag then ymag else xmag
end else mag
in
if mag = 1.0 then ()
else begin
let nw = truncate (float old#width *. mag)
and nh = truncate (float old#height *. mag)
in
prog#set_format_string begin
if mag > 1.0 then (Printf.sprintf "enlarging to %dx%d" nw nh)
else (Printf.sprintf "reducing to %dx%d" nw nh)
end;
image := old#resize (Some prog#set_percentage) nw nh;
end
| `NORMALIZE ->
let normalize img =
(* Make monochrome *)
let hist = get_hist img in
let normalizer = Colorhist.normalize 0.95 hist in
prog#set_format_string "normalizing...";
let width = img#width
and height = img#height in
let f_height = float height in
for y = 0 to height - 1 do
for x = 0 to width - 1 do
let rgb = img#unsafe_get x y in
let new_rgb = normalizer rgb in
img#unsafe_set x y new_rgb;
done;
prog#set_percentage (float (y+1) /. f_height)
done;
in
normalize !image;
| `ENHANCE ->
let enhance img =
(* Make monochrome *)
let hist = get_hist img in
let log, enhancer = Enhance.enhance 0.90 hist in
(*
if log > 0.7 && log < 1.2 then ()
else *) begin
prog#set_format_string "enhancing...";
let width = img#width
and height = img#height in
let f_height = float height in
for y = 0 to height - 1 do
for x = 0 to width - 1 do
let rgb = img#unsafe_get x y in
let new_rgb = enhancer rgb in
img#unsafe_set x y new_rgb;
done;
prog#set_percentage (float (y+1) /. f_height)
done;
end
in
enhance !image;
| _ -> () ) !filters;
(* prerr_endline "display"; *)
prog#set_format_string "mapping";
let ximage = OXimage.of_image visual (Some prog#set_percentage)
(!image)#coerce in
display_ximage ximage;
ximage (* for cache *)
;;
|