这里有现成的 procedure TfrmMain.setformit(han:thandle;src:timage); var data:prgndata; x,y:integer; size:integer; st,tnt,ye:integer; r1,r2:hrgn; begin st:=0; r1:=0; ye:=0; r2:=0; for y:=0 to src.Picture.Bitmap.Height-1 do begin x:=-1; repeat x:=x+1; tnt:=0; while (src.picture.bitmap.Canvas.Pixels[x,y]<>clblack) and (x<=src.Picture.Bitmap.Width) do begin if tnt=0 then begin tnt:=1; st:=x; end; x:=x+1; end; if tnt=1 then begin if ye=0 then begin ye:=1;r1:=createrectrgn(st,y,x-1,y+1); end else begin r2:=createrectrgn(st,y,x-1,y+1); if r2<>0 then combinergn(r1,r1,r2,RGN_OR); deleteobject(r2) end; end; until x>=src.Picture.Bitmap.Width; end; size:=getregiondata(r1,0,nil); getmem(data,size); getregiondata(r1,size,data); setwindowrgn(han,r1,true); end;
to laihecongxi(兴哥) : 这个算法太慢,我已试过。有没有更好的算法?
to cg1120: 那些组件要收钱吧?
to zwjchina(蒲石) : 是你以前恢复过,我今天试用了一下你的那个算法,太慢。
转贴: 现在有许多Delphi方面的书都有讲如何建立圆形、椭圆形、星形等等非标准形状的窗口,不过实用性并不大。因为如果是一个不规则图形的话,你要怎么才能画好呢?就算可以那又要用多少时间呢?所以啦,我介绍下面的建立任意图片形状窗口的方法!只是可惜是别人发明的非我原创 :( 回答: 下面的程序段是一个外国人的原算法!(我最早看到算法,可他是不是抄的我就不知道了)原来是一个控件,不过在我的电脑上不能用。由万重大侠改写了并且发布在他的网站上: http://mantousoft.51.net 注释是我写的。 function Tform1.CreateRegion(wMask: TBitmap; wColor: TColor; hControl: THandle): HRGN; var dc, dc_c : HDC; Rgn, TempRgn : HRGN; X, Y, BeginY : Integer; line : boolean; color : TColor; begin {代码风格不统一,因为有些是照抄那个外国人的。 dc := GetWindowDC(hControl); dc_c := CreateCompatibleDC(dc); SelectObject(dc_c, wMask.Handle); BeginY := 0;{这句可以不要,有了可以避免编译器警告。} Rgn := CreateRectRgn(0, 0, 0, 0); {先初始化一个空的区域给Rgn。} for X := 0 to wMask.Width - 1 do begin line := False; for Y := 0 to wMask.Height - 1 do begin color := GetPixel(dc_c, X, Y); if not (color = wColor) then begin if not line then begin line := True; BeginY := Y; end; end; if (color = wColor) or (Y = wMask.Height - 1) then begin if line then begin line := False; TempRgn := CreateRectRgn(X, BeginY, X + 1, Y); CombineRgn(Rgn, Rgn, TempRgn, RGN_OR); {把图形以连续得线段为单位生成区域,并且合并到总的区域中} end; end; end; end; ReleaseDC(hControl, dc); DeleteObject(dc); Result := Rgn; end;procedure TForm1.FormCreate(Sender: TObject); var w1 : TBitmap; w2 : TColor; rgn : HRGN; begin w1 := TBitmap.Create; w1.Assign(image1.Picture.Bitmap); w2 := w1.Canvas.Pixels[0, 0]; rgn := CreateRegion(w1, w2, Handle); if rgn <> 0 then begin SetWindowRgn(Handle, rgn, true); end; w1.Free; end;不过后来看到了罗云彬(http://asm.yeah.net)大侠给出了不同的算法,我以为更好些,源程序可是用100%的汇编写成的(厉害吧!)我改为了Delphi的样子!首先解释两个函数。 1、原形:function CreateRectRgn(p1, p2, p3, p4: Integer): HRGN; stdcall;创建一个由点p1,p2和p3,p4描述的矩形区域; 2、原形:function CombineRgn(p1, p2, p3: HRGN; p4: Integer): Integer; stdcall;把p2和p3区域合并为区域p1,p4是合并方式,p4取值如下:RGN_AND 交集合并,RGN_COPY拷贝p2的内容,RGN_DIFF合并p2和p3不相交的地方,RGN_OR并集合并,RGN_XOR不同时在p2和p3中的部分。 下面给出完整源程序: function Tform1.CreateRegion(wMask: TBitmap; wColor: TColor; hControl: THandle): HRGN; var dc, dc_c : HDC; rgn : HRGN; x, y : integer; coord : TPoint; line : boolean; color : TColor; begin dc := GetWindowDC(hControl); dc_c := CreateCompatibleDC(dc); {创建一个与特定设备场景一致的内存设备场景} SelectObject(dc_c, wMask.Handle); {把位图选入内存设备场景这样才可以操作!} BeginPath(dc); {启动一个路径分支。 在这个命令后执行的GDI绘图命令会自动成为路径的一部分。 对线段的连接会结合到一起。并且设备场景中任何现成的路径都会被清除。} for x := 0 to wMask.Width - 1 do begin line := false; for y := 0 to wMask.Height - 1 do begin color := GetPixel(dc_c, x, y); if not (color = wColor) then begin if not line then {如果这个不同颜色的线段开始了当然就不记录了!} begin line := true; {这是记录下这一列连续的不是背景颜色的颜色段的第一个位子。} coord.x := x; {其实这个X是不用的,因为coord.x是恒等于x的。但尊重源作者,保留!} coord.y := y; end; end; if (color = wColor) or (y = wMask.Height - 1) then {如果这个颜色段完了或者到了图片底部} begin if line then begin line := false; MoveToEx(dc, coord.x, coord.y, nil); {就把画线的起点移到这个列线段不同颜色的开始} LineTo(dc, coord.x, y); LineTo(dc, coord.x + 1, y); LineTo(dc, coord.x + 1, coord.y); {上面三个LineTo()语句就是画一个2×y的矩形。 一定要这样才可以画上每个点!并且连在一起的如果你查查Win32 SDK手册你还可以用Rectangle(dc, coord.x, coord.y, x + 2, y)等其他的画图函数代替从MoveToEx()开始的四个语句!也是一样的,只要记住要把点画完而且要重叠地画才可以把路径连在一起!} CloseFigure(dc); {描绘到一个路径时,关闭当前打开的图形。万重大侠说不可以少,我不理解,但是多了不错。} end; end; end; end; EndPath(dc); {结束画路径} rgn := PathToRegion(dc); {连接路径为区域的函数。} ReleaseDC(hControl, dc); {释放资源,公式化的必须使用。} Result := rgn;
我安装上述想法重新写了一个函数,使用更方便如下://此函数通过一张位图来创建一个区域,支持bmp格式和jpg格式 //位图中黑色的地方将不透明,非黑色的地方透明, //创建完毕后可以通过SetWindowRgn函数设置窗口或控件的形状,如: //setWindowRgn(handle,zjs_createImageRegion('c:\goomoo.bmp'),true); uses jpeg; function zjs_createImageRegion(imageFile:TFilename):HRGN; var bitmap:TBitmap; //位图对象 jpg:TJpegImage; hRegion,hTmpRegion:HRGN; //hRegion: 最终区域 hTmpRegion 临时区域 h,l,left,right:integer; //h:行 l:列 left:临时区域的左边 right:临时区域的右边 started:Boolean; //是否开始记录 ext:String; //图片扩展名 begin if not fileExists(imageFile) then begin result:=0; exit; //文件不存在则退出,并返回0 end; bitmap:=TBitmap.Create; try ext:=extractFileExt(imageFile); if (ext='.jpg') or (ext='.jpeg') then //如果是jpg图片 begin jpg:=TJpegImage.Create; try jpg.LoadFromFile(imageFile); bitmap.Assign(jpg); //从Jpg中把位图拷贝过来 finally jpg.Free; //及时释放jpg end; end else if ext='.bmp' then bitmap.LoadFromFile(imageFile) //载入位图 else begin result:=0; exit; end; hRegion:=createRectRgn(0,0,0,0); //创建一个初始的空的区域 //初始化变量,消除警告信息 left:=0; right:=0; //开始扫描图片的每个像素 for h:=0 to bitmap.Height-1 do begin started:=false; for l:=0 to bitmap.Width-1 do begin if bitmap.Canvas.Pixels[l,h]=clBlack then //黑色为不透明区域,其他颜色为透明区域 begin if not started then begin started:=true; //开始记录右边 left:=l; right:=l+1; end else //started begin right:=l; end; end else begin if started then //如果已经开始并且该点的颜色不是黑色 begin started:=false; //结束记录右边 hTmpRegion:=createRectRgn(left,h,right,h+1); combineRgn(hRegion,hRegion,hTmpRegion,RGN_OR); end; end; end; if started then //到了图片的右边还没有结束 begin if right>bitmap.Width-1 then right:=bitmap.Width-1; hTmpRegion:=createRectRgn(left,h,right,h+1); combineRgn(hRegion,hRegion,hTmpRegion,RGN_OR); end; end; finally bitmap.Free; end; Result:=hRegion; end;
这个算法因为没有搜索图片的所有像素,所以快很多。希望能起个抛砖引玉的作用。 //此函数通过Y轴无凹形的图片(比如葫芦形)来创建区域。 function zjs_CreateYProtrudeImageRgn(imageFile:TFilename):HRGN; label firstLineFounded,L_leftFound,L_rightFound; var hRegion,hTmpRegion:HRGN; //hRegion:最终区域 hTmpRegion:临时区域 bitmap:TBitmap; //位图对象 left,right,lastLeft,lastRight,row,col,currentRow:integer; started,leftFound,rightFound:boolean; //started:是否开始记录 begin //初始化变量 started:=false; currentRow:=0; left:=-1; right:=-1; hRegion:=createRectRgn(0,0,0,0); bitmap:=TBitmap.Create; try bitmap.LoadFromFile(imageFile); //找到第一行的left和right for row:=0 to bitmap.Height-1 do begin for col:=0 to bitmap.Width-1 do begin if bitmap.Canvas.Pixels[col,row]=clBlack then //找到第一个黑点 begin if not Started then begin started:=true; left:=col; right:=col+1; currentRow:=row; //记下当前是第几行 continue; end else right:=col; end; end; { for col} if started then begin hTmpRegion:=createRectRgn(left,row,right,row+1); combineRgn(hRegion,hRegion,hTmpRegion,RGN_OR); goto firstLineFounded; end; end; {for row} firstLineFounded: if (left<>-1) then //确认已经找到了第一条黑线 begin lastLeft:=left; lastRight:=right; for row:=currentRow+1 to bitmap.Height-1 do begin leftFound:=false; rightFound:=false; //找到本行的左边 if bitmap.Canvas.Pixels[0,row]=clBlack then begin left:=0; leftFound:=true; goto L_leftFound; end else begin col:=lastLeft; while col>=0 do //往左搜索 begin if (bitmap.Canvas.Pixels[col,row]<>clBlack) and (bitmap.Canvas.Pixels[col+1,row]=clBlack) then begin left:=col; leftFound:=true; goto L_leftFound; end; col:=col-1; end; col:=lastLeft; while col<lastRight do //往右搜索 begin if (bitmap.Canvas.Pixels[col,row]<>clBlack) and (bitmap.Canvas.Pixels[col+1,row]=clBlack) then begin left:=col; leftFound:=true; goto L_leftFound; //跳出循环 end; col:=col+1; end; end; L_leftFound:
//找到本行的右边 if bitmap.Canvas.Pixels[bitmap.Width-1,row]=clBlack then begin right:=bitmap.Width-1; rightFound:=true; goto L_rightFound; end else begin col:=lastRight; while col<bitmap.Width-1 do //往右搜索 begin if (bitmap.Canvas.Pixels[col,row]=clBlack) and (bitmap.Canvas.Pixels[col+1,row]<>clBlack) then begin right:=col+1; rightFound:=true; goto L_rightFound; end; col:=col+1; end; while col>lastLeft do //往左搜索 begin if (bitmap.Canvas.Pixels[col,row]=clBlack) and (bitmap.Canvas.Pixels[col+1,row]<>clBlack) then begin right:=col+1; rightFound:=true; goto L_rightFound; end; col:=col-1; end; end; L_rightFound: if leftFound and rightFound then begin lastLeft:=left; lastRight:=right; hTmpRegion:=createRectRgn(left,row,right,row+1); combineRgn(hRegion,hRegion,hTmpRegion,RGN_OR); end else break; end; {for row} end; finally bitmap.Free; end; result:=hRegion; end;
goomoo(古木) 说了这么多了,那位有通用的解决方案也让大家学习一下。
我上面写的一个是通用的函数 function zjs_createImageRegion(imageFile:TFilename):HRGN;只是速度不尽如人意。
www.51delphi.com
www.playicq.com
有下载
procedure TfrmMain.setformit(han:thandle;src:timage);
var
data:prgndata;
x,y:integer;
size:integer;
st,tnt,ye:integer;
r1,r2:hrgn;
begin st:=0;
r1:=0;
ye:=0;
r2:=0;
for y:=0 to src.Picture.Bitmap.Height-1 do
begin
x:=-1;
repeat
x:=x+1;
tnt:=0;
while (src.picture.bitmap.Canvas.Pixels[x,y]<>clblack)
and (x<=src.Picture.Bitmap.Width) do
begin
if tnt=0 then
begin
tnt:=1;
st:=x;
end;
x:=x+1;
end;
if tnt=1
then begin
if ye=0 then begin ye:=1;r1:=createrectrgn(st,y,x-1,y+1); end
else begin
r2:=createrectrgn(st,y,x-1,y+1);
if r2<>0 then combinergn(r1,r1,r2,RGN_OR);
deleteobject(r2)
end;
end;
until x>=src.Picture.Bitmap.Width;
end;
size:=getregiondata(r1,0,nil);
getmem(data,size);
getregiondata(r1,size,data);
setwindowrgn(han,r1,true);
end;
现在有许多Delphi方面的书都有讲如何建立圆形、椭圆形、星形等等非标准形状的窗口,不过实用性并不大。因为如果是一个不规则图形的话,你要怎么才能画好呢?就算可以那又要用多少时间呢?所以啦,我介绍下面的建立任意图片形状窗口的方法!只是可惜是别人发明的非我原创 :( 回答:
下面的程序段是一个外国人的原算法!(我最早看到算法,可他是不是抄的我就不知道了)原来是一个控件,不过在我的电脑上不能用。由万重大侠改写了并且发布在他的网站上:
http://mantousoft.51.net 注释是我写的。
function Tform1.CreateRegion(wMask: TBitmap; wColor: TColor; hControl: THandle): HRGN;
var
dc, dc_c : HDC;
Rgn, TempRgn : HRGN;
X, Y, BeginY : Integer;
line : boolean;
color : TColor;
begin {代码风格不统一,因为有些是照抄那个外国人的。
dc := GetWindowDC(hControl);
dc_c := CreateCompatibleDC(dc);
SelectObject(dc_c, wMask.Handle);
BeginY := 0;{这句可以不要,有了可以避免编译器警告。}
Rgn := CreateRectRgn(0, 0, 0, 0); {先初始化一个空的区域给Rgn。}
for X := 0 to wMask.Width - 1 do
begin
line := False;
for Y := 0 to wMask.Height - 1 do
begin
color := GetPixel(dc_c, X, Y);
if not (color = wColor) then
begin
if not line then
begin
line := True;
BeginY := Y;
end;
end;
if (color = wColor) or (Y = wMask.Height - 1) then
begin
if line then
begin
line := False;
TempRgn := CreateRectRgn(X, BeginY, X + 1, Y);
CombineRgn(Rgn, Rgn, TempRgn, RGN_OR);
{把图形以连续得线段为单位生成区域,并且合并到总的区域中}
end;
end;
end;
end;
ReleaseDC(hControl, dc);
DeleteObject(dc);
Result := Rgn;
end;procedure TForm1.FormCreate(Sender: TObject);
var
w1 : TBitmap;
w2 : TColor;
rgn : HRGN;
begin
w1 := TBitmap.Create;
w1.Assign(image1.Picture.Bitmap);
w2 := w1.Canvas.Pixels[0, 0];
rgn := CreateRegion(w1, w2, Handle);
if rgn <> 0 then
begin
SetWindowRgn(Handle, rgn, true);
end;
w1.Free;
end;不过后来看到了罗云彬(http://asm.yeah.net)大侠给出了不同的算法,我以为更好些,源程序可是用100%的汇编写成的(厉害吧!)我改为了Delphi的样子!首先解释两个函数。
1、原形:function CreateRectRgn(p1, p2, p3, p4: Integer): HRGN; stdcall;创建一个由点p1,p2和p3,p4描述的矩形区域;
2、原形:function CombineRgn(p1, p2, p3: HRGN; p4: Integer): Integer; stdcall;把p2和p3区域合并为区域p1,p4是合并方式,p4取值如下:RGN_AND 交集合并,RGN_COPY拷贝p2的内容,RGN_DIFF合并p2和p3不相交的地方,RGN_OR并集合并,RGN_XOR不同时在p2和p3中的部分。
下面给出完整源程序:
function Tform1.CreateRegion(wMask: TBitmap; wColor: TColor; hControl: THandle): HRGN;
var
dc, dc_c : HDC;
rgn : HRGN;
x, y : integer;
coord : TPoint;
line : boolean;
color : TColor;
begin
dc := GetWindowDC(hControl);
dc_c := CreateCompatibleDC(dc);
{创建一个与特定设备场景一致的内存设备场景}
SelectObject(dc_c, wMask.Handle);
{把位图选入内存设备场景这样才可以操作!}
BeginPath(dc);
{启动一个路径分支。
在这个命令后执行的GDI绘图命令会自动成为路径的一部分。
对线段的连接会结合到一起。并且设备场景中任何现成的路径都会被清除。}
for x := 0 to wMask.Width - 1 do
begin
line := false;
for y := 0 to wMask.Height - 1 do
begin
color := GetPixel(dc_c, x, y);
if not (color = wColor) then
begin
if not line then
{如果这个不同颜色的线段开始了当然就不记录了!}
begin
line := true; {这是记录下这一列连续的不是背景颜色的颜色段的第一个位子。}
coord.x := x; {其实这个X是不用的,因为coord.x是恒等于x的。但尊重源作者,保留!}
coord.y := y;
end;
end;
if (color = wColor) or (y = wMask.Height - 1) then {如果这个颜色段完了或者到了图片底部}
begin
if line then
begin
line := false;
MoveToEx(dc, coord.x, coord.y, nil); {就把画线的起点移到这个列线段不同颜色的开始}
LineTo(dc, coord.x, y);
LineTo(dc, coord.x + 1, y);
LineTo(dc, coord.x + 1, coord.y); {上面三个LineTo()语句就是画一个2×y的矩形。
一定要这样才可以画上每个点!并且连在一起的如果你查查Win32 SDK手册你还可以用Rectangle(dc, coord.x, coord.y, x + 2, y)等其他的画图函数代替从MoveToEx()开始的四个语句!也是一样的,只要记住要把点画完而且要重叠地画才可以把路径连在一起!}
CloseFigure(dc); {描绘到一个路径时,关闭当前打开的图形。万重大侠说不可以少,我不理解,但是多了不错。}
end;
end;
end;
end;
EndPath(dc); {结束画路径}
rgn := PathToRegion(dc); {连接路径为区域的函数。}
ReleaseDC(hControl, dc); {释放资源,公式化的必须使用。}
Result := rgn;
几秒钟,你的居然有2分钟?我的计算机赛扬1G,256内存。你内存多大。强烈强烈关注这方面的算法。
DeleteObject(Rg2); //我加上的。
指的是沿x轴(或y)轴画y轴的平行线,每条直线与形状的边界最多有两个交点,另一个轴可以不理会。
//位图中黑色的地方将不透明,非黑色的地方透明,
//创建完毕后可以通过SetWindowRgn函数设置窗口或控件的形状,如:
//setWindowRgn(handle,zjs_createImageRegion('c:\goomoo.bmp'),true);
uses jpeg;
function zjs_createImageRegion(imageFile:TFilename):HRGN;
var
bitmap:TBitmap; //位图对象
jpg:TJpegImage;
hRegion,hTmpRegion:HRGN; //hRegion: 最终区域 hTmpRegion 临时区域
h,l,left,right:integer; //h:行 l:列 left:临时区域的左边 right:临时区域的右边
started:Boolean; //是否开始记录
ext:String; //图片扩展名
begin
if not fileExists(imageFile) then
begin
result:=0;
exit; //文件不存在则退出,并返回0
end;
bitmap:=TBitmap.Create;
try
ext:=extractFileExt(imageFile);
if (ext='.jpg') or (ext='.jpeg') then //如果是jpg图片
begin
jpg:=TJpegImage.Create;
try
jpg.LoadFromFile(imageFile);
bitmap.Assign(jpg); //从Jpg中把位图拷贝过来
finally
jpg.Free; //及时释放jpg
end;
end
else if ext='.bmp' then
bitmap.LoadFromFile(imageFile) //载入位图
else
begin
result:=0;
exit;
end; hRegion:=createRectRgn(0,0,0,0); //创建一个初始的空的区域
//初始化变量,消除警告信息
left:=0; right:=0;
//开始扫描图片的每个像素
for h:=0 to bitmap.Height-1 do
begin
started:=false;
for l:=0 to bitmap.Width-1 do
begin
if bitmap.Canvas.Pixels[l,h]=clBlack then //黑色为不透明区域,其他颜色为透明区域
begin
if not started then
begin
started:=true; //开始记录右边
left:=l; right:=l+1;
end
else //started
begin
right:=l;
end;
end
else
begin
if started then //如果已经开始并且该点的颜色不是黑色
begin
started:=false; //结束记录右边
hTmpRegion:=createRectRgn(left,h,right,h+1);
combineRgn(hRegion,hRegion,hTmpRegion,RGN_OR);
end;
end;
end;
if started then //到了图片的右边还没有结束
begin
if right>bitmap.Width-1 then right:=bitmap.Width-1;
hTmpRegion:=createRectRgn(left,h,right,h+1);
combineRgn(hRegion,hRegion,hTmpRegion,RGN_OR);
end;
end;
finally
bitmap.Free;
end;
Result:=hRegion;
end;
思路如下:
1.找到开始有黑色的一行,并将行号存入currentRow中。并将该行中的左端点和右端点分别存放于 lastLeft 和 lastRight 变量中。然后跳出循环。
2.进入下一行。依据上一行的left和right来搜索本行的left和right。这样很快。找到后就合并区域。
3.循环直到有一行没有找到left和right(也就是没有黑色)就跳出。
这个算法因为没有搜索图片的所有像素,所以快很多。希望能起个抛砖引玉的作用。
//此函数通过Y轴无凹形的图片(比如葫芦形)来创建区域。
function zjs_CreateYProtrudeImageRgn(imageFile:TFilename):HRGN;
label
firstLineFounded,L_leftFound,L_rightFound;
var
hRegion,hTmpRegion:HRGN; //hRegion:最终区域 hTmpRegion:临时区域
bitmap:TBitmap; //位图对象
left,right,lastLeft,lastRight,row,col,currentRow:integer;
started,leftFound,rightFound:boolean; //started:是否开始记录
begin
//初始化变量
started:=false;
currentRow:=0;
left:=-1; right:=-1;
hRegion:=createRectRgn(0,0,0,0);
bitmap:=TBitmap.Create;
try
bitmap.LoadFromFile(imageFile);
//找到第一行的left和right
for row:=0 to bitmap.Height-1 do
begin
for col:=0 to bitmap.Width-1 do
begin
if bitmap.Canvas.Pixels[col,row]=clBlack then //找到第一个黑点
begin
if not Started then
begin
started:=true;
left:=col; right:=col+1;
currentRow:=row; //记下当前是第几行
continue;
end
else
right:=col;
end;
end; { for col}
if started then
begin
hTmpRegion:=createRectRgn(left,row,right,row+1);
combineRgn(hRegion,hRegion,hTmpRegion,RGN_OR);
goto firstLineFounded;
end;
end; {for row}
firstLineFounded:
if (left<>-1) then //确认已经找到了第一条黑线
begin
lastLeft:=left; lastRight:=right;
for row:=currentRow+1 to bitmap.Height-1 do
begin
leftFound:=false;
rightFound:=false; //找到本行的左边
if bitmap.Canvas.Pixels[0,row]=clBlack then
begin
left:=0;
leftFound:=true;
goto L_leftFound;
end
else
begin
col:=lastLeft;
while col>=0 do //往左搜索
begin
if (bitmap.Canvas.Pixels[col,row]<>clBlack) and (bitmap.Canvas.Pixels[col+1,row]=clBlack) then
begin
left:=col;
leftFound:=true;
goto L_leftFound;
end;
col:=col-1;
end;
col:=lastLeft;
while col<lastRight do //往右搜索
begin
if (bitmap.Canvas.Pixels[col,row]<>clBlack) and (bitmap.Canvas.Pixels[col+1,row]=clBlack) then
begin
left:=col;
leftFound:=true;
goto L_leftFound; //跳出循环
end;
col:=col+1;
end;
end;
L_leftFound:
//找到本行的右边
if bitmap.Canvas.Pixels[bitmap.Width-1,row]=clBlack then
begin
right:=bitmap.Width-1;
rightFound:=true;
goto L_rightFound;
end
else
begin
col:=lastRight;
while col<bitmap.Width-1 do //往右搜索
begin
if (bitmap.Canvas.Pixels[col,row]=clBlack) and (bitmap.Canvas.Pixels[col+1,row]<>clBlack) then
begin
right:=col+1;
rightFound:=true;
goto L_rightFound;
end;
col:=col+1;
end;
while col>lastLeft do //往左搜索
begin
if (bitmap.Canvas.Pixels[col,row]=clBlack) and (bitmap.Canvas.Pixels[col+1,row]<>clBlack) then
begin
right:=col+1;
rightFound:=true;
goto L_rightFound;
end;
col:=col-1;
end;
end;
L_rightFound: if leftFound and rightFound then
begin
lastLeft:=left; lastRight:=right;
hTmpRegion:=createRectRgn(left,row,right,row+1);
combineRgn(hRegion,hRegion,hTmpRegion,RGN_OR);
end
else
break;
end; {for row}
end;
finally
bitmap.Free;
end;
result:=hRegion;
end;
function zjs_createImageRegion(imageFile:TFilename):HRGN;只是速度不尽如人意。