(***********************************************************************)
(*                                                                     *)
(*                           Objective Caml                            *)
(*                                                                     *)
(*            François Pessaux, projet Cristal, INRIA Rocquencourt     *)
(*            Pierre Weis, projet Cristal, INRIA Rocquencourt          *)
(*            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 Color
open Bitmap

type elt = Color.cmyk

type t = {
    width: int;
    height: int;
    mutable infos: Info.info list;
    data: Bitmap.t
  } 

let create_with width height init_buffer =
  { width= width;
    height= height;
    infos= [];
    data= Bitmap.create_with 4 width height init_buffer }
;;

let create width height =
  { width= width;
    height= height;
    infos= [];
    data= Bitmap.create 4 width height None }
;;

let make width height init =
  let init = 
    let s = String.create 4 in
    s.[0] <- char_of_int init.c;
    s.[1] <- char_of_int init.m;
    s.[2] <- char_of_int init.y;
    s.[3] <- char_of_int init.k;
    Some s
  in
  { width= width;
    height= height;
    infos= [];
    data= Bitmap.create 4 width height init }
;;

let unsafe_get t x y =
  let str, pos = t.data.access x y in
  { c= int_of_char str.[pos    ];
    m= int_of_char str.[pos + 1];
    y= int_of_char str.[pos + 2];
    k= int_of_char str.[pos + 3] }
;;

let unsafe_set t x y c =
  let str, pos = t.data.access x y in
  str.[pos    ] <- char_of_int c.c;
  str.[pos + 1] <- char_of_int c.m;
  str.[pos + 2] <- char_of_int c.y;
  str.[pos + 3] <- char_of_int c.k
;;

let get t x y = 
  Region.check t.width t.height x y;
  unsafe_get t x y
;;

let set t x y c =
  Region.check t.width t.height x y;
  unsafe_set t x y c
;;

let destroy t =
  Bitmap.destroy t.data
;;

let sub src x y w h =
  { width= w;
    height= h;
    infos= [];
    data= Bitmap.sub src.data x y w h }
;;

let blit src sx sy dst dx dy w h =
  Bitmap.blit src.data sx sy dst.data dx dy w h
;;

(* image resize with smoothing *)
let resize img nw nh =
  let newimage = create nw nh in
  let xscale = float nw /. float img.width in  
  let yscale = float nh /. float img.height in  
  for x = 0 to nw - 1 do
    for y = 0 to nh - 1 do
      let start_x = truncate (float x /. xscale)
      and start_y = truncate (float y /. yscale)
      in
      let end_x = truncate ((float x +. 0.99) /. xscale)
      and end_y = truncate ((float y +. 0.99) /. yscale)
      in
(*
      let end_x = if end_x >= img.width then img.width - 1 else end_x
      and end_y = if end_y >= img.height then img.height - 1 else end_y
      in
*)
      let size = (end_x - start_x + 1) * (end_y - start_y + 1) in
      let sc = ref 0
      and sm = ref 0
      and sy = ref 0
      and sk = ref 0
      in
      for xx = start_x to end_x do
  	for yy = start_y to end_y do
  	  let c = unsafe_get img xx yy in
  	  sc := !sc + c.c;
  	  sm := !sm + c.m;
  	  sy := !sy + c.y;
	  sk := !sk + c.k
  	done
      done;
      unsafe_set newimage x y { c= (!sc/size);
				m= (!sm/size);
				y= (!sy/size);
				k= (!sk/size) }
    done
  done;
  newimage
;;
