362 lines
14 KiB
Plaintext
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 |