12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091openBigarraytype'aresult=('a,[`Msgofstring])Result.ttype'kindbuffer=('a,'b,c_layout)Array1.tconstraint'kind=('a,'b)kindtype'kindt={width:int;height:int;channels:int;offset:int;stride:int;data:'kindbuffer;}typefloat32=(float,float32_elt)kindtypeint8=(int,int8_unsigned_elt)kindexternalload_unmanaged:?channels:int->string->int8tresult="ml_stbi_load"externalloadf_unmanaged:?channels:int->string->float32tresult="ml_stbi_loadf"externaldecode_unmanaged:?channels:int->_buffer->int8tresult="ml_stbi_load_mem"externaldecodef_unmanaged:?channels:int->_buffer->float32tresult="ml_stbi_loadf_mem"externalml_stbi_image_free:_buffer->unit="ml_stbi_image_free"letfree_unmanagedimage=ml_stbi_image_freeimage.dataletclonebuf=letbuf'=Array1.create(Array1.kindbuf)c_layout(Array1.dimbuf)inArray1.blitbufbuf';buf'letmanagef?channelsfilename=matchf?channelsfilenamewith|Result.Error_aserr->err|Result.Okimage->letmanaged={imagewithdata=cloneimage.data}infree_unmanagedimage;Result.Okmanagedletload?channelsfilename=manageload_unmanaged?channelsfilenameletloadf?channelsfilename=manageloadf_unmanaged?channelsfilenameletdecode?channelsfilename=managedecode_unmanaged?channelsfilenameletdecodef?channelsfilename=managedecodef_unmanaged?channelsfilenameletimage~width~height~channels?(offset=0)?(stride=width*channels)data=letsize=Array1.dimdatainifwidth<0thenResult.Error(`Msg"width should be positive")elseifheight<0thenResult.Error(`Msg"height should be positive")elseifchannels<0||channels>4thenResult.Error(`Msg"channels should be between 1 and 4")elseifoffset<0thenResult.Error(`Msg"offset should be positive")elseifoffset+(stride*height)>sizethenResult.Error(`Msg"image does not fit in buffer")elseResult.Ok{width;height;channels;offset;stride;data}letwidtht=t.widthletheightt=t.heightletchannelst=t.channelsletdatat=t.dataletvalidate_mipmapt1t2=ift1.channels<>t2.channelstheninvalid_arg"mipmap: images have different number of channels";ift1.width/2<>t2.width||t1.height/2<>t2.heighttheninvalid_arg"mipmap: second image size should exactly be half of first image"externalmipmap:int8t->int8t->unit="ml_stbi_mipmap"externalmipmapf:float32t->float32t->unit="ml_stbi_mipmapf"letmipmapt1t2=validate_mipmapt1t2;mipmapt1t2letmipmapft1t2=validate_mipmapt1t2;mipmapft1t2externalvflip:int8t->unit="ml_stbi_vflip"externalvflipf:float32t->unit="ml_stbi_vflipf"externalexpblur:int8t->radius:float->unit="ml_stbi_expblur"(** Blur the image *)