Legend:
Page
Library
Module
Module type
Parameter
Class
Class type
Source
Source file images.ml
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396(***********************************************************************)(* *)(* 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: images.ml,v 1.3 2008/06/16 22:35:42 furuse Exp $ *)(* The image data structure definition. *)(**************************************************************** Exceptions *)exceptionOut_of_image(* exception for illegal point access *)exceptionWrong_image_type(* exception for illegal internal image type *)exceptionWrong_file_type(* exception for unsupported image FILE format *)(* Update region.error *)let()=Region.error:=(fun()->raiseOut_of_image)(************************************************************* Generic image *)typet=|Index8ofIndex8.t|Rgb24ofRgb24.t|Index16ofIndex16.t|Rgba32ofRgba32.t|Cmyk32ofCmyk32.t(* Generic image type *)typesequence={seq_width:int;seq_height:int;seq_frames:framelist;seq_loops:int}andframe={frame_left:int;frame_top:int;frame_image:t;frame_delay:int(* mili secs *)}(******************************************************************** Colors *)(* Colors: the copies of color.mli *)typergb=Color.rgb={mutabler:int;mutableg:int;mutableb:int}typergba=Color.rgba={color:rgb;mutablealpha:int}typecmyk=Color.cmyk={mutablec:int;mutablem:int;mutabley:int;mutablek:int}type'amap='aColor.map={mutablemax:int;(* maximum number allowed in the color map (-1 = unlimited) *)mutablemap:'aarray}(********************************************************* Image file format *)(* Image formats *)typeformat=|Gif|Bmp|Jpeg|Tiff|Png|Xpm|Ppm|Ps(************************************************ Image file name extensions *)letextension=function|Gif->"gif"|Bmp->"bmp"|Jpeg->"jpg"|Tiff->"tif"|Png->"png"|Xpm->"xpm"|Ppm->"ppm"|Ps->"eps"letget_extensions=tryletdotpos=String.rindexs'.'inString.subs0dotpos,String.subs(dotpos+1)(String.lengths-dotpos-1)with|_->s,""letguess_extensions=lets=String.lowercasesinmatchswith|"gif"->Gif|"bmp"->Bmp|"jpeg"|"jpg"->Jpeg|"tiff"|"tif"->Tiff|"png"->Png|"xpm"->Xpm|"ppm"|"pgm"|"pbm"->Ppm|"eps"|"ps"|"epsf"|"epsi"->Ps|_->raiseNot_foundletguess_formatfile=guess_extension(snd(get_extensionfile))(******************************************** Image file header informations *)typecolormodel=Info.colormodel=|Gray|RGB|Index|GrayA|RGBA|YCbCr|CMYK(* Infos attached to bitmaps *)typeinfo=Info.info=|Info_DPIoffloat(* dot per inch *)|Info_BigEndian|Info_LittleEndian(* endianness of image file *)|Info_ColorModelofcolormodel(* color model of image file *)|Info_Depthofint(* Image bit depth *)|Info_Corrupted(* For corrupted PNG files *)(* Info query *)letrecdpi=function|[]->None|Info_DPIdpi::_->Somedpi|_::xs->dpixs(* Image file header *)typeheader={header_width:int;header_height:int;header_infos:infolist}(**************************************************** Image file I/O options *)(* Load options *)typeload_option=|Load_Progressof(float->unit)(* For progress meters *)|Load_Resolutionoffloat*float(* Pixel/Inch for rasterization of PS *)|Load_only_the_first_frame(* Save options *)typesave_option=|Save_Qualityofint(* Save quality for Jpeg compression *)|Save_Progressof(float->unit)(* For progress meters *)|Save_Interlace(* Interlaced Gif *)(* Option queries *)letrecload_progress=function|[]->None|Load_Progressp::_->Somep|_::xs->load_progressxsletrecload_resolution=function|[]->None|Load_Resolution(px,py)::_->Some(px,py)|_::xs->load_resolutionxsletrecsave_progress=function|[]->None|Save_Progressp::_->Somep|_::xs->save_progressxsletrecsave_interlace=function|[]->false|Save_Interlace::_->true|_::xs->save_interlacexsletrecsave_quality=function|[]->None|Save_Qualityq::_->Someq|_::xs->save_qualityxs(******************************** The type for methods of image file formats *)typeformat_methods={check_header:(string->header);load:(string->load_optionlist->t)option;save:(string->save_optionlist->t->unit)option;load_sequence:(string->load_optionlist->sequence)option;save_sequence:(string->save_optionlist->sequence->unit)option;}letmethods_list=ref[]letfile_formatfilename=letresult=refNoneintryList.iter(fun(format,methods)->tryresult:=Some(format,methods.check_headerfilename);raiseExitwith|Wrong_file_type->())!methods_list;raiseWrong_file_typewith|Exit->match!resultwith|Somer->r|None->assertfalse(************************************************ Generic image manupilation *)letadd_methodsformatmethods=methods_list:=(format,methods)::!methods_listletloadfilenameload_options=letresult=refNoneintryList.iter(fun(_format,methods)->trylet_=methods.check_headerfilenameinmatchmethods.loadwithSomeload->result:=Some(loadfilenameload_options);raiseExit|None->raiseWrong_file_typewith|Wrong_file_type->())!methods_list;raiseWrong_file_typewith|Exit->match!resultwith|Somer->r|None->assertfalseletsavefilenameformatoptsave_optionst=tryletformat=matchformatoptwith|Someformat->format|None->guess_formatfilenameinletmethods=List.assocformat!methods_listinmatchmethods.savewithSomesave->savefilenamesave_optionst|None->raiseWrong_file_typewith|Not_found->raiseWrong_file_typeletsizeimg=matchimgwith|Index8bmp->bmp.Index8.width,bmp.Index8.height|Index16bmp->bmp.Index16.width,bmp.Index16.height|Rgb24bmp->bmp.Rgb24.width,bmp.Rgb24.height|Rgba32bmp->bmp.Rgba32.width,bmp.Rgba32.height|Cmyk32bmp->bmp.Cmyk32.width,bmp.Cmyk32.heightletwidthimg=matchimgwith|Index8bmp->bmp.Index8.width|Index16bmp->bmp.Index16.width|Rgb24bmp->bmp.Rgb24.width|Rgba32bmp->bmp.Rgba32.width|Cmyk32bmp->bmp.Cmyk32.widthletheightimg=matchimgwith|Index8bmp->bmp.Index8.height|Index16bmp->bmp.Index16.height|Rgb24bmp->bmp.Rgb24.height|Rgba32bmp->bmp.Rgba32.height|Cmyk32bmp->bmp.Cmyk32.heightletdestroyimg=matchimgwith|Index8bmp->Index8.destroybmp|Rgb24bmp->Rgb24.destroybmp|Index16bmp->Index16.destroybmp|Rgba32bmp->Rgba32.destroybmp|Cmyk32bmp->Cmyk32.destroybmpletsubimgxywh=letf=matchimgwith|Index8img->(funxywh->Index8(Index8.subimgxywh))|Rgb24img->(funxywh->Rgb24(Rgb24.subimgxywh))|Index16img->(funxywh->Index16(Index16.subimgxywh))|Rgba32img->(funxywh->Rgba32(Rgba32.subimgxywh))|Cmyk32img->(funxywh->Cmyk32(Cmyk32.subimgxywh))infxywhletcopyimg=subimg00(widthimg)(heightimg)letblitsrcsxsydstdxdy=letf=matchsrc,dstwith|Index8src,Index8dst->(funsxsy->Index8.blitsrcsxsydst)|Rgb24src,Rgb24dst->(funsxsy->Rgb24.blitsrcsxsydst)|Index16src,Index16dst->(funsxsy->Index16.blitsrcsxsydst)|Rgba32src,Rgba32dst->(funsxsy->Rgba32.blitsrcsxsydst)|Cmyk32src,Cmyk32dst->(funsxsy->Cmyk32.blitsrcsxsydst)|_->raise(Invalid_argument"Images.blit")infsxsydxdy(* image sequences *)letmake_sequencet={seq_width=widtht;seq_height=heightt;seq_frames=[{frame_left=0;frame_top=0;frame_image=t;frame_delay=0}];seq_loops=0}letunoptimize_sequenceseq=(* sequence must be non-empty *)letcoe=function|Index8t->Rgba32(Index8.to_rgba32t)|Index16t->Rgba32(Index16.to_rgba32t)|t->tin{seqwithseq_frames=beginlet_,result=lethead_frame=List.hdseq.seq_framesinList.fold_left(fun(previmage,result)frame->letnewimage=copyprevimageinletsrc=coeframe.frame_imageinbeginmatchsrc,newimagewith|Rgb24_,_|Cmyk32_,_->(* non transparent *)blitsrc00newimageframe.frame_leftframe.frame_top(widthsrc)(heightsrc)|Rgba32src32,Rgba32dst32->(* transparent *)Rgba32.mapColor.Rgba.mergesrc3200dst32frame.frame_leftframe.frame_top(widthsrc)(heightsrc)|_->assertfalseend;(newimage,{frame_left=0;frame_top=0;frame_image=newimage;frame_delay=frame.frame_delay}::result))(coehead_frame.frame_image,[head_frame])(List.tlseq.seq_frames)inList.revresultend}letload_sequencefilenameload_options=letresult=refNoneintryList.iter(fun(_format,methods)->trylet_=methods.check_headerfilenameinmatchmethods.load_sequence,methods.loadwith|Someload,_->result:=Some(loadfilenameload_options);raiseExit|None,Someload->result:=Some(make_sequence(loadfilenameload_options));|None,None->raiseWrong_file_typewith|Wrong_file_type->())!methods_list;raiseWrong_file_typewith|Exit->match!resultwith|Somer->r|None->assertfalseletsave_sequencefilenameformatoptsave_optionsseq=tryletformat=matchformatoptwith|Someformat->format|None->guess_formatfilenameinletmethods=List.assocformat!methods_listinmatchmethods.save_sequencewithSomesave->savefilenamesave_optionsseq|None->raiseWrong_file_typewith|Not_found->raiseWrong_file_typeletblocksimg=matchimgwith|Index8img->Index8.blocksimg|Rgb24img->Rgb24.blocksimg|Index16img->Index16.blocksimg|Rgba32img->Rgba32.blocksimg|Cmyk32img->Cmyk32.blocksimg