tslediter/funcext/tvclib/t_img_op_api.tsf

362 lines
14 KiB
Plaintext

type t_img_op_api=class({$ifdef linux}t_cairo_api{$else}t_gdiplusflat_api{$endif})
{**
@explan(说明) 封装gdi+处理图片问题 %%
**}
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