123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325(***********************************************************************)(* *)(* 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: ppm.ml,v 1.2 2008/06/16 22:35:42 furuse Exp $ *)(* Manipulating images in portable format: PPM, PGM, and PBM.
PPM: portable pixmap (pixels (picture element) map).
PGM: portable greymap (grey scale map).
PBM: portable bitmap (binary digit map).
*)openImages(* Reading PPM images. *)typeppm_magic_number=|P1|P2|P3|P4|P5|P6(* Magic numbers for PPM images.
P1 and P4 indicate bitmaps (P1 is ascii encoding, P4 is raw encoding).
P2 and P5 indicate greymaps, in raw or ascii encoding.
P3 and P6 indicate pixmaps (P3 is ascii encoding, P6 is raw encoding).
The library systematically saves images in raw form (which is more compact).
*)letmagic_number_of_string=function|"P1"(* BITMAP, ASCII form *)->P1|"P2"(* BITMAP, ASCII form *)->P2|"P3"(* PIXMAP, ASCII form *)->P3|"P4"(* BITMAP, RAW form *)->P4|"P5"(* BITMAP, ASCII form *)->P5|"P6"(* PIXMAP, RAW form *)->P6|s->invalid_arg("Unknown magic number for PPM image: "^s)letread_ppm_magic_numberic=magic_number_of_string(input_lineic)letstring_of_magic_number=function|P1->"P1"|P2->"P2"|P3->"P3"|P4->"P4"|P5->"P5"|P6->"P6"(* Auxiliaries: skipping comments and reading numbers into strings. *)letskip_commentic=letrecr0()=matchinput_charicwith|'#'->r1()|' '->r0()|'\n'->r0()|c->candr1()=matchinput_charicwith|'\n'->r0()|_->r1()inr0()(* Read a sequence of digits eventually followed by a single space. *)letread_int_accuaccuic=letrecreadaccu=matchinput_charicwith|'0'..'9'asc->read1(10*accu+int_of_charc-48)|' '->readaccu|'\n'->readaccu|_->invalid_arg"read_int"andread1accu=matchinput_charicwith|'0'..'9'asc->read1(10*accu+int_of_charc-48)|_->accuinreadacculetread_intic=read_int_accu0icletread_dimscic=letcols=read_int_accu(int_of_charc-48)icinletlines=read_inticincols,linesletread_maxic=read_inticletread_ppm_headeric=(* Reads something like
P6
# CREATOR: XV Version 3.10 Rev: 12/16/94
256 162
255
*)letmn=read_ppm_magic_numbericinletchar=skip_commenticinletc,l=read_dimscharicinmn,l,cletcheck_headerfilename=letic=open_in_binfilenameintrylet_mn,l,c=read_ppm_headericinclose_inic;{header_width=c;header_height=l;header_infos=[]}with|_->close_inic;raiseWrong_file_type(* Reading pixmaps. *)letread_raw_pixel24ic=letr=input_byteicinletg=input_byteicinletb=input_byteicin{r=r;g=g;b=b}letread_ascii_pixel24ic=letr=read_inticinletg=read_inticinletb=read_inticin{r=r;g=g;b=b}letread_raw_ppm_iciclc_max=letimg=Rgb24.createclinfori=0tol-1doforj=0toc-1doRgb24.setimgji(read_raw_pixel24ic)donedone;imgletread_ascii_ppm_iciclc_max=letimg=Rgb24.createclinfori=0tol-1doforj=0toc-1doRgb24.setimgji(read_ascii_pixel24ic)donedone;img(* Reading greymaps. *)letread_raw_grey=input_byteletread_ascii_grey=read_intletread_raw_gen_icread_pixeliclcmax=letimg=Index8.createclinletgreymap={Color.max=max;Color.map=letmake_greyi={r=i;g=i;b=i}inArray.init(max+1)make_grey}inimg.Index8.colormap<-greymap;fori=0tol-1doforj=0toc-1doIndex8.setimgji(read_pixelic)donedone;imgletread_raw_pgm_icic=read_raw_gen_icread_raw_greyicletread_ascii_pgm_icic=read_raw_gen_icread_ascii_greyicletblack=0andwhite=255letmax_byte=255(* Reading bitmaps. *)letread_raw_pbm_iciclc=letimg=Index8.createclinletgreymap={Color.max=max_byte;Color.map=letmake_greyi={r=i;g=i;b=i}inArray.init(max_byte+1)make_grey}inimg.Index8.colormap<-greymap;fori=0tol-1doletrecloopjbnbyte=ifj=cthen()elseifbn=8thenloopj0(input_byteic)elseletcolor=matchbyteland0x80with|0->white|_->blackinIndex8.setimgjicolor;letnew_byte=bytelsl1inloop(j+1)(bn+1)new_byteinloop00(input_byteic)done;imgletrecread_ascii_bitic=matchinput_charicwith|'0'->white|' '->read_ascii_bitic|'\n'->read_ascii_bitic|_->blackletread_ascii_pbm_iciclc=read_raw_gen_icread_ascii_biticlcmax_byteletread_ppm_icic=letmn,l,c=read_ppm_headericinletimg=matchmnwith|P1->Index8(read_ascii_pbm_iciclc)|P4->Index8(read_raw_pbm_iciclc)|P2|P3|P5|P6->letmax=read_maxicinmatchmnwith|P2->Index8(read_ascii_pgm_iciclcmax)|P3->Rgb24(read_ascii_ppm_iciclcmax)|P5->Index8(read_raw_pgm_iciclcmax)|_->Rgb24(read_raw_ppm_iciclcmax)inimgletread_ppms=letic=open_in_binsintryletimg=read_ppm_icicinclose_inic;imgwithEnd_of_file->close_inic;invalid_arg"read_ppm: premature end of file"letload_ppms=matchread_ppmswith|Rgb24img->img|_->invalid_arg(s^" is not a ppm file.")(* Saving images. *)letsave_ppm_header_imgmnoclc=output_stringoc(Printf.sprintf"%s\n"(string_of_magic_numbermn));output_stringoc"# CREATOR: CamlImages package\n";output_stringoc(Printf.sprintf"%d %d\n"cl);ifmn<>P1&&mn<>P4thenoutput_stringoc(Printf.sprintf"%d\n"255)letbit_set=1andbit_cleared=0letgen_save_raw_pbm_ocis_whiteimgoclc=save_ppm_headerimgP4oclc;fori=0tol-1doletrecloopjbnbyte=ifj=cthenifbn=0then()elseletbyte=bytelsl(8-bn)inoutput_byteocbyteelseifbn=8then(output_byteocbyte;loopj00)elseletcolor=ifis_white(Index8.get_rgbimgji)thenbit_setelsebit_clearedinletnew_byte=(bytelsl1)lorcolorinloop(j+1)(bn+1)new_byteinloop000done(* Save a bitmap in raw form. *)letsave_raw_pbm_oc=gen_save_raw_pbm_oc(func->c.r=255&&c.g=255&&c.b=255)(* Save a pixmap in raw form. *)letsave_raw_ppm_ocimgoclc=save_ppm_headerimgP6oclc;fori=0tol-1doforj=0toc-1doletcolor=Rgb24.getimgjiinoutput_byteoccolor.r;output_byteoccolor.g;output_byteoccolor.bdonedoneletsave_ppm_ocimgoc=letl=img.Rgb24.heightinifl=0theninvalid_arg"save_ppm: invalid null line number";letc=img.Rgb24.widthinifc=0theninvalid_arg"save_ppm: invalid null column number";save_raw_ppm_ocimgoclcletsave_ppmsimg=letoc=open_out_binsinsave_ppm_ocimgoc;close_outocletsave_bitmap_ocimgoc=letl=img.Index8.heightinifl=0theninvalid_arg"save_ppm: invalid null line number";letc=img.Index8.widthinifc=0theninvalid_arg"save_ppm: invalid null column number";save_raw_pbm_ocimgoclcletsave_bitmapsimg=letoc=open_out_binsinsave_bitmap_ocimgoc;close_outocletloads_=read_ppmsletload_bitmaps=matchloads[]with|Index8t->t|_->invalid_arg"Not a pbm file."letsaves_=function|Index8t->save_bitmapst|Rgb24t->save_ppmst|_->invalid_arg"Ppm.save"let()=add_methodsPpm{check_header=check_header;load=Someload;save=Somesave;load_sequence=None;save_sequence=None}