12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879(***********************************************************************)(* *)(* 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: reduce.ml,v 1.1 2006/11/28 15:43:28 rousse Exp $*)openColoropenRgb24moduletypeREDUCER=sigvalfind_nearest:Color.rgbColor.map->Color.rgb->intend(* Error diffusion weight table *)letdiffusion_table=letsum=1.0+.1.0+.1.0/.sqrt2.0inletbase=1.0/.sumin[|[|0.0;base|];[|base;base/.(sqrt2.0)|]|](* Reduce colors to the given colormap (<= 256 colors) using error diffusion *)moduleErrorDiffuse(R:REDUCER)=structletfsrccolormap=ifcolormap.max>256thenraise(Invalid_argument"Rgb24.to_index8: too large colormap");leterror_table=Array.init2(fun_->Array.init(src.width+1)(fun_->{r=0;g=0;b=0}))inletget_errorxy=lety'=ymod2inerror_table.(y').(x)inletadd_errorxyrgb=lety'=ymod2inletrgb'=error_table.(y').(x)inerror_table.(y').(x)<-Color.plusrgbrgb'inletnext_liney=(* reset the error table of the current line *)lety'=ymod2inforx=0tosrc.widthdoerror_table.(y').(x)<-{r=0;g=0;b=0}doneinletid8=Index8.create(src.width)(src.height)inid8.Index8.colormap<-colormap;fory=0tosrc.height-1doforx=0tosrc.width-1doletideal_rgb=Color.plus(unsafe_getsrcxy)(get_errorxy)inletc=R.find_nearestcolormapideal_rgbinIndex8.unsafe_setid8xyc;letnew_error=Color.minusideal_rgbcolormap.map.(c)inforey=0to1doforex=0to1doletdiffuse_rgb={r=truncate(floatnew_error.r*.diffusion_table.(ex).(ey));g=truncate(floatnew_error.g*.diffusion_table.(ex).(ey));b=truncate(floatnew_error.b*.diffusion_table.(ex).(ey));}inadd_error(x+ex)(y+ey)diffuse_rgbdonedonedone;next_lineydone;id8endmoduleErrorDiffuseIndex8=ErrorDiffuse(Color.Rgb)leterror_diffuse=ErrorDiffuseIndex8.f