Legend:
Page
Library
Module
Module type
Parameter
Class
Class type
Source
Source file jpeg.ml
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296(***********************************************************************)(* *)(* 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: jpeg.ml,v 1.4 2009/07/04 03:39:28 furuse Exp $ *)openUtilopenImagesopenRgb24typein_handlemoduleMarker=structtyperaw={code:int;data:string}typet=|Commentofstring|Appofint*stringlett_of_rawr=matchr.codewith|0xFE->Commentr.data|n->App(n-0xE0,r.data)letraw_of_t=function|Comments->{code=0xFE;data=s}|App(n,s)->{code=0xE0+n;data=s}openFormatletformatppf=function|Comments->fprintfppf"Comment: %s"s|App(n,s)->fprintfppf"App%d (%d bytes)"n(String.lengths)endexternalopen_in_header:string->int*int*in_handle*Marker.rawlist="open_jpeg_file_for_read"externalset_scale_denom:in_handle->int->unit="jpeg_set_scale_denom"externalopen_in_start:in_handle->int*int*in_handle="open_jpeg_file_for_read_start"externalread_scanline:in_handle->bytes->int->unit="read_jpeg_scanline"externalread_scanlines:in_handle->bytes->int->int->unit="read_jpeg_scanlines"externalclose_in:in_handle->unit="close_jpeg_file_for_read"typeout_handleexternalopen_out:string->int->int->int->out_handle="open_jpeg_file_for_write"externalopen_out_cmyk:string->int->int->int->out_handle="open_jpeg_file_for_write_cmyk"externalwrite_marker:out_handle->Marker.raw->unit="caml_jpeg_write_marker"externalwrite_scanline:out_handle->bytes->unit="write_jpeg_scanline"externalclose_out:out_handle->unit="close_jpeg_file_for_write"letopen_inname=let_,_,ic,rev_markers=open_in_headernameinletw,h,ic=open_in_starticinw,h,ic,List.rev_mapMarker.t_of_rawrev_markersletopen_in_thumbnailnamegeom_spec=ifgeom_spec.Geometry.spec_aspect=Geometry.Dont_keepthenraise(Invalid_argument"Jpeg.open_in_thumbnail: illegal geom_spec");letimage_width,image_height,ic,rev_markers=open_in_headernameinletscale=tryletgeom=Geometry.computegeom_specimage_widthimage_heightin(*
prerr_endline (Printf.sprintf "Denom %d/%d" image_width geom.Geometry.geom_width);
*)image_width/geom.Geometry.geom_widthwith|_->1inletdenom=ifscale<2then1elseifscale<4then2elseifscale<8then4else8inset_scale_denomicdenom;image_width,image_height,open_in_startic,List.rev_mapMarker.t_of_rawrev_markersletload_auxprogicwh=letprogy=matchprogwith|Somep->p(float(y+1)/.floath)|None->()inletimg=Rgb24.createwhinbeginmatchRgb24.get_scanline_ptrimgwith|Somef->letload_once_at=max1(h/10)inletrecload_scanlinesy=ify>=hthen()elsebeginlet(string,off),at_most=fyinletlines_read=minload_once_atat_mostinread_scanlinesicstringofflines_read;progy;load_scanlines(y+lines_read)endinload_scanlines0|None->(* CR jfuruse: check overflow *)letscanline=Bytes.create(w*3)infory=0toh-1doread_scanlineicscanline0;Rgb24.set_scanlineimgyscanline;progydoneend;close_inic;Rgb24imgletloadnameload_opts=letw,h,ic,_markers=open_innameinletprog=Images.load_progressload_optsinload_auxprogicwhletload_thumbnailnameload_optsgeom_spec=letprog=Images.load_progressload_optsinletow,oh,(w,h,ic),_markers=open_in_thumbnailnamegeom_specinow,oh,load_auxprogicwhletsave_with_markersnameoptsimagemarkers=letquality=matchImages.save_qualityoptswith|Someq->q|None->80inletprog=Images.save_progressoptsinmatchimagewith|Rgb24bmp->letoc=open_outnamebmp.widthbmp.heightqualityinList.iter(funmrk->write_markeroc(Marker.raw_of_tmrk))markers;fory=0tobmp.height-1dowrite_scanlineoc(Rgb24.get_scanlinebmpy);matchprogwith|Somep->p(float(y+1)/.floatbmp.height)|None->()done;close_outoc|_->raiseWrong_image_typeletsavenameoptsimage=save_with_markersnameoptsimage[]letsave_as_cmyknameoptstransimage=letquality=matchImages.save_qualityoptswith|Someq->q|None->80inletprog=Images.save_progressoptsinletget_cmyk_scanlinewidthscanline=letbuf=Bytes.create(width*4)inforx=0towidth-1doletr=scanline@%x*3+0inletg=scanline@%x*3+1inletb=scanline@%x*3+2inletc,m,y,k=trans{r=r;g=g;b=b}inbuf<<x*4+0&char_of_int(255-c);buf<<x*4+1&char_of_int(255-m);buf<<x*4+2&char_of_int(255-y);buf<<x*4+3&char_of_int(255-k)done;bufinmatchimagewith|Rgb24bmp->letoc=open_out_cmyknamebmp.widthbmp.heightqualityinfory=0tobmp.height-1doletbuf=get_cmyk_scanlinebmp.width(Rgb24.get_scanlinebmpy)inwrite_scanlineocbuf;matchprogwith|Somep->p(float(y+1)/.floatbmp.height)|None->()done;close_outoc|_->raiseWrong_image_typeletsave_cmyk_samplenameopts=letquality=matchImages.save_qualityoptswith|Someq->q|None->80inlet_prog=Images.save_progressoptsinletsample_pointxy=letc=x/16*17andm=(xmod16)*17andy=y/16*17andk=(ymod16)*17inc,m,y,kinletsample_scany=lets=Bytes.create(256*4)inforx=0to255doletc,m,y,k=sample_pointxyins<<x*4+0&char_of_intc;s<<x*4+1&char_of_intm;s<<x*4+2&char_of_inty;s<<x*4+3&char_of_intk;done;sinletoc=open_out_cmykname256256qualityinfory=0to256-1doletbuf=sample_scanyinwrite_scanlineocbufdone;close_outocletfind_jpeg_sizeic=(* jump to the next 0xff *)letrecloop()=letrecjump_to_0xff()=letch=int_of_char(input_charic)inifch<>0xffthenjump_to_0xff()inletrecjump_to_non_0xff()=letch=int_of_char(input_charic)inifch=0xffthenjump_to_non_0xff()elsechinjump_to_0xff();letch=jump_to_non_0xff()inletstr=Bytes.create4inmatchchwith|0xda->raiseNot_found|_whench>=0xc0&&ch<=0xc3->really_inputicstr03;really_inputicstr04;(str@%2)lsl8+(str@%3),(* width *)(str@%0)lsl8+(str@%1)(* height *)|_->(* skip this block *)letblocklen=really_inputicstr02;(str@%0)lsl8+(str@%1)inlets=Bytes.create(blocklen-2)inreally_inputics0(blocklen-2);loop()intryloop()with|_->raiseNot_found(* any error returns Not_found *)letcheck_headerfilename=letlen=2inletic=open_in_binfilenameintryletstr=Bytes.createleninreally_inputicstr0len;if(* I had some jpeg started with 7f58, the 7th bits were missing... *)(* int_of_char str.[0] lor 0x80 = 0xff &&
int_of_char str.[1] lor 0x80 = 0xd8 *)(str@%0)=0xff&&(str@%1)=0xd8(* && String.sub str 6 4 = "JFIF" --- JFIF standard *)thenbeginletw,h=tryfind_jpeg_sizeicwith|Not_found->-1,-1inPervasives.close_inic;{header_width=w;header_height=h;header_infos=[];}endelseraiseWrong_file_typewith|_->Pervasives.close_inic;raiseWrong_file_typeletread_markersfilename=let_,_,ic,rev_markers=open_in_headerfilenameinclose_inic;List.rev_mapMarker.t_of_rawrev_markersletwrite_markerohmrk=write_markeroh(Marker.raw_of_tmrk)let()=add_methodsJpeg{check_header=check_header;load=Someload;save=Somesave;load_sequence=None;save_sequence=None}