type t_img_op_api=class({$ifdef linux}t_cairo_api{$else}t_gdiplusflat_api{$endif}) {** @explan(说明)gdi+ 的c接口函数 %% **} function create(); begin api_init(); end {$ifdef linux} //20241021 分离出gid+ //20210827 需要添加gdi功能 { class procedure cairo_pattern_destroy(p:pointer);cdecl;external 'libgtk-3.so'; class function cairo_image_surface_create_from_png(f:string):pointer;cdecl;external 'libgtk-3.so'; class function cairo_pattern_create_for_surface(f:pointer):pointer;cdecl;external 'libgtk-3.so'; class function cairo_image_surface_get_width(sf:pointer):integer;cdecl;external 'libgtk-3.so'; class function cairo_image_surface_get_height(sf:pointer):integer;cdecl;external 'libgtk-3.so'; class function gdk_pixbuf_new_from_file(f:string;er:pointer):pointer;cdecl;external 'libgtk-3.so'; class function gdk_pixbuf_save(pixbuf:pointer;p:string;tp:string;gerr:string;p1:string; p2:string;p3:string;p4:string;p5:string):integer;cdecl;external 'libgtk-3.so'; class procedure gdk_pixbuf_unref(pixbuf);cdecl;external 'libgtk-3.so'; class procedure gdk_pixbuf_ref(pixbuf);cdecl;external 'libgtk-3.so'; class function g_object_ref(g:pointer):pointer;cdecl;external 'libgtk-3.so'; class procedure g_object_unref(g:pointer);cdecl;external 'libgtk-3.so'; } type TTempFile = class static fobj_count; function Create(); begin fobj_count++; bp := "/tmp/tinysoft/tslvcl/"; FPath := bp+inttostr(systhreadid())+"_"+tostn(fobj_count); end function GetData(buf,f); begin if not ifstring(f) then f := FPath; if fileexists("", f) then begin sz := filesize("",f); return readfile(rwraw(),"",f,0,sz,buf); end end function writedata(buf,f); begin if not ifstring(buf) then return 0; if not ifstring(f) then f := FPath; if fileexists("",f) then filedelete("",f); unit(tslvcl).CreateDirWithFileName(f); return 1=writefile(rwraw(),"",f,0,length(buf),buf); end function Destroy(); begin filedelete("",FPath); end property path read FPath ; private FPath; end function gdk_pixbuf_new_from_file(f:string;er:pointer):pointer; begin _f_ := static function(f:string;er:pointer):pointer;cdecl;external get_cairo_func(functionname()); return ##_f_(f,er); end function gdk_pixbuf_save(pixbuf:pointer;p:string;tp:string;gerr:string;p1:string; p2:string;p3:string;p4:string;p5:string):integer; begin _f_ := static function(pixbuf:pointer;p:string;tp:string;gerr:string;p1:string; p2:string;p3:string;p4:string;p5:string):integer;cdecl;external get_cairo_func(functionname()); return ##_f_(pixbuf,p,tp,gerr,p1,p2,p3,p4,p5); end procedure gdk_pixbuf_unref(pixbuf); begin _f_ := static procedure(pixbuf);cdecl;external get_cairo_func(functionname()); return ##_f_(); end procedure gdk_pixbuf_ref(pixbuf); begin _f_ := static procedure(pixbuf);cdecl;externalget_cairo_func(functionname()); return ##_f_(); end function g_object_ref(g:pointer):pointer; begin _f_ := static function(g:pointer):pointer;cdecl;external get_cairo_func(functionname()); return ##_f_(g); end procedure g_object_unref(g:pointer); begin _f_ := static procedure(g:pointer);cdecl;external get_cairo_func(functionname()); return ##_f_(g); end function GdipSaveImageToStream(image:pointer;var imgestr:string); //无用到 function GdipLoadImageFromFile(filename:string;var image:pointer); //无用到 begin r := gdk_pixbuf_new_from_file(filename,0); if r<>0 then begin image := r; r := 1; end return r; end function GdipDisposeImage(img); //销毁image begin imageunref(img); end function GdipSaveImageToFile(image:pointer;filename:string;clsidEncoder:pointer;encoderParams:pointer); //保存 begin s := unit(cstructurelib).ReadStringFromPtr(clsidEncoder); //"png","jpeg","bmp","gif","tiff" case s of "image/png": begin return gdk_pixbuf_save(image,filename,"png",nil,nil,nil,nil,nil,nil) end "image/jpeg": begin ps := array("quality":"100"); if ifarray(conf) and conf["quality"]>0 and conf["quality"]<=100 then ps["quality"] := inttostr(conf["quality"]); return gdk_pixbuf_save(image,filename,"jpeg",nil,"quality",ps["quality"],nil,nil,nil); end "image/bmp": begin return gdk_pixbuf_save(image,filename,"bmp",nil,nil,nil,nil,nil,nil); end end return 0; end function GdipCreateHBITMAPFromBitmap(bitmap:pointer;var hbmReturn:pointer;background:integer); //bitmap to hbitmap begin hbmReturn := bitmap; imageref(hbmReturn); return 1; end function GdipCreateBitmapFromHBITMAP(hbm:pointer;hpal:pointer;var bitmap:pointer); // hbitmap to bitmap begin bitmap := hbm; imageref(bitmap); return 1; end function GdipCreateBitmapFromHICON(hicon:pointer;var bitmap:pointer); //bitmap to icon begin bitmap := hicon; imageref(bitmap); return 1; end function GdipCreateHICONFromBitmap(bitmap:pointer;var hbmReturn:pointer); // icon to bitmap begin hbmReturn := bitmap; imageref(hbmReturn); return 1; end function GdipGetbmpSurface(h); begin s := GetImageProperty(h,"surface"); if s then return s; p := GetImageProperty(h,"file"); s := cairo_image_surface_create_from_png(p); SetImageProperty(h,"surface",s); return s ; end function GdipGetbmppattern(h); begin r := GetImageProperty(h,"pattern"); if r then return r; s := GdipGetbmpSurface(h); r := cairo_pattern_create_for_surface(s); SetImageProperty(h,"pattern",r); return r; end function imagetostring(h,vp,conf); //bitamp to str begin t := unit(cstructurelib).ReadStringFromPtr(vp._getptr_()); //"png","jpeg","bmp","gif","tiff" case t of "image/png": begin s := GetImageProperty(h,"pngdata"); if s and ifstring(s) then return s; tf := new TTempFile(); p := GetImageProperty(h,"file"); tf.GetData(s,p); SetImageProperty(h,"pngdata",s); end "image/jpeg": begin s := GetImageProperty(h,"jpegdata"); if s and ifstring(s) then return s; tf := new TTempFile(p); p := tf.path; ps := array("quality":"100"); if ifarray(conf) and conf["quality"]>0 and conf["quality"]<=100 then ps["quality"] := inttostr(conf["quality"]); if 1<> gdk_pixbuf_save(pixbuf,p,"jpeg",nil,"quality",ps["quality"],nil,nil,nil) then return 0; tf.GetData(s); SetImageProperty(h,"jpegdata",s); end "image/ico": begin s := GetImageProperty(h,"icodata"); if s and ifstring(s) then return s; tf := new TTempFile(p); p := tf.path; ps := array("depth":"32","x_hot":"16","y_hot":"16"); if ifarray(conf) and conf["depth"]>0 and conf["depth"]<=512 then ps["depth"] := inttostr(conf["depth"]); if ifarray(conf) and conf["x_hot"]>0 and conf["x_hot"]<=128 then ps["x_hot"] := inttostr(conf["x_hot"]); if ifarray(conf) and conf["y_hot"]>0 and conf["y_hot"]<=128 then ps["y_hot"] := inttostr(conf["y_hot"]); if 1<> gdk_pixbuf_save(pixbuf,p,"ico","depth",ps["depth"],"x_hot",ps["x_hot"],"y_hot",ps["y_hot"]) then return 0; tf.GetData(s); SetImageProperty(h,"icogdata",s); end "image/bmp": begin s := GetImageProperty(h,"bmpdata"); if s and ifstring(s) then return s; tf := new TTempFile(p); p := tf.path; if 1<> gdk_pixbuf_save(pixbuf,p,"bmp",nil,nil,nil,nil,nil,nil) then return 0; tf.GetData(s); SetImageProperty(h,"bmpdata",s); end end return s; end function stringtoimage(b,hd); //string to bitmap begin tf := new TTempFile(p); p := tf.path; if 1<>writefile(rwraw(),"",p,0,length(b),b) then return 0; hd := gdk_pixbuf_new_from_file(p,0); if hd then r := 0; else return -1; np := getmsgd_Crc32(p); nnp := "/tmp/tinysoft/tslvcl/"+np[1]+"/"+np[2]+"/"+np+".png"; imageref(hd); SetImageProperty(hd,"file",nnp); unit(tslvcl).CreateDirWithFileName(nnp); gdk_pixbuf_save(hd,nnp,"png",nil,nil,nil,nil,nil,nil); return r; end private function SetImageProperty(img,p,pv); //保存属性 begin global g_gtk_images_propertys; if not ifarray(g_gtk_images_propertys) then g_gtk_images_propertys := array(); return g_gtk_images_propertys[inttostr(img),p] := pv; end function GetImageProperty(img,p); //获得属性 begin global g_gtk_images_propertys; if not ifarray(g_gtk_images_propertys) then g_gtk_images_propertys := array(); return g_gtk_images_propertys[inttostr(img),p]; end function imageref(img); // 引用 begin rf := GetImageProperty(img,"ref"); SetImageProperty(img,"ref",((rf>0)?(rf+1):(1))); g_object_ref(img); end function imageunref(img); //反引用 begin rf := GetImageProperty(img,"ref"); if ifnil(rf) then return ; if rf<=1 then begin return DeleteImages(img); end else SetImageProperty(img,"ref",rf-1); end function DeleteImages(img); //删除 begin global g_gtk_images_propertys; if not ifarray(g_gtk_images_propertys) then return ; id := inttostr(img); idfile := g_gtk_images_propertys[id,"file"]; if not idfile then return ; if fileexists("",idfile) then //删除文件 begin filedelete("",idfile); end pt := GetImageProperty(img,"pattern"); if pt then begin cairo_pattern_destroy(pt); //移除pattern end sf := GetImageProperty(img,"surface"); if sf then begin //cairo_surface_destroy(sf); //移除surface end reindex(g_gtk_images_propertys,array(id:nil)); g_object_unref(img); end {$else} //stream 处理 type inukownvtb = class(tslcstructureobj) uses cstructurelib; function create(ptr); begin p := get_mem_mgr().readptr(ptr); struct := MemoryAlignmentCalculate(get_vtb_struct()); inherited create(struct,p); end function Release(s); begin ptr := _getvalue_("Release"); _f_ := function (s:pointer):integer;stdcall; external ptr; r := ##_f_(s); return r; end protected function get_vtb_struct();virtual; begin return array( ("QueryInterface","intptr",0), ("AddRef","intptr",0), ("Release","intptr",0) ); end end function imagetostring(h,vp,conf); begin CreateStreamOnHGlobal(0,true,st); r := GdipSaveImageToStream(h,st,vp._getptr_,0); if r<>0 then exit; GetHGlobalFromStream(st,memo); len := GlobalSize(memo); s := ""; lm := GlobalLock(memo); setlength(s,len); memcpy2(s,lm,len); tuicloseistream(st); return s; end function stringtoimage(b,hd); begin len := length(b); hm := GlobalAlloc(2,len+1);//分配内容 lm := GlobalLock(hm);//枷锁 if lm <> 0 then begin memcpy(lm,b,len);//内存拷贝 GlobalUnlock(hm);//解锁 end CreateStreamOnHGlobal(hm,true,st); r := GdipLoadImageFromStream(st,hd); tuicloseistream(st); return r; end function CreateStreamOnHGlobal(hGlobal:pointer;fDeleteOnRelease:integer; var ppstm:pointer):pointer;stdcall;external "Ole32.dll" name "CreateStreamOnHGlobal"; function GetHGlobalFromStream(pstm:pointer; var phglobal:pointer):pointer;stdcall;external "Ole32.dll" name "GetHGlobalFromStream"; function GlobalLock(mem :pointer):pointer;stdcall;external "Kernel32.dll" name "GlobalLock"; function GlobalUnlock(mem :pointer):integer;stdcall;external "Kernel32.dll" name "GlobalUnlock"; function GlobalSize(menm:pointer):integer;stdcall;external "Kernel32.dll" name "GlobalSize"; function memcpy(dst:pointer;src:string;size_t:integer):pointer;cdecl;external "msvcrt.dll" name "memcpy"; function memcpy2(var dst:string;src:pointer;size_t:integer):pointer;cdecl;external "msvcrt.dll" name "memcpy"; function tuicloseistream(sm:pointer); begin o := new inukownvtb(sm); return o.release(sm); end function GlobalAlloc(uFlags :integer;dwBytes:integer):pointer;stdcall;external "Kernel32.dll" name "GlobalAlloc"; {$endif} end