我倒是经常使用bmp->rgn, 不过您的要求我不知道答案.
我是直接将bmp转成rgn的. 我也一直想知道如何取得边界点的坐标. 可
想不出算法. 呵呵
如果您只是需要bmp->rgn(也就是说那个array纯粹只是作为中间步骤, 别无
他用), 那我这里有个完整的例子(我写的一个图象工具库中的一个函数):
思路:
扫描图象的scanline, 取不是背景色的连续坐标, 认为是一个height=1的rect,
用CreateRectRgn生成region, 再用CombineRgn(.....RGN_OR)与先前生成
的region合并生成新的region.
重复扫描完所有扫描线后就得到一个region了.
function CreateRgnFromBmp(ABmp: TBitmap;
ARect: TRect;
TransColor: TColor): HRGN;
var
b, e: Integer;
i, j: Integer;
p: PChar;
rg: HRGN;
rgbcolor: longint;
begin
result := 0;
if not assigned(ABmp) or ABmp.Empty then
exit;
// 返回空region
rgbcolor := ColorToRGB(transcolor);
rgbcolor := (
rgbcolor and $0000ff00
or (rgbcolor shr 16)
or (rgbcolor shl 16)
) and $00ffffff;
// 交换RGB颜色值中的R与B, 使之与scanline中顺序相同
if IsRectEmpty(ARect) then
ARect := bounds(0, 0, abmp.width, abmp.height)
else
IntersectRect(arect, arect, bounds(0, 0, abmp.width, abmp.height));
if IsRectEmpty(arect) then
exit;
ABmp.PixelFormat := pf24Bit;
// 转换图象成24bit
for i := ARect.Top to ARect.Bottom - 1do
begin
b := ARect.Left;
e := b - 1;
p := Pointer(Integer(ABmp.ScanLine) + ARect.Left * 3);
// scanline中起始位置
for j := ARect.Left to ARect.Right - 1do
begin
if CompareMem(p, @rgbcolor, 3) then
// 透明色
if b >= e then
Inc(b)
else
begin
if result = 0 then
result := CreateRectRgn(b, i, e, i+1)
else
begin
rg := CreateRectRgn(b, i, e, i+1);
CombineRgn(result, result, rg, RGN_OR);
DeleteObject(rg);
end;
b := e;
end
else
if b >=e then
e := b + 1
else
Inc(e);
p := p + 3;
end;
if b < e then
if result = 0 then
result := CreateRectRgn(b, i, e, i+1)
else
begin
rg := CreateRectRgn(b, i, e, i+1);
CombineRgn(result, result, rg, RGN_OR);
DeleteObject(rg);
end;
end;
if result <> 0 then
// 将region定到(0,0)坐标
OffsetRgn(result, -arect.left, -arect.top);
end;