下面的程序暂时只能检测单色位图,彩色位图要等一阵子。
procedure Calc(Bmp, Res: TBitmap; x, y: Integer);
var
Value: Integer;
function Pixels(x, y: Integer): Integer;
begin
if (x < 0) or (x >= Bmp.Width) or
(y < 0) or (y >= Bmp.Height) then
Result := 0
else
Result := Integer(PByteArray(Bmp.ScanLine[y])[x]);
end;
procedure SetPixels(Value: Byte);
begin
PByteArray(Res.ScanLine[y])[x] := Value;
end;
begin
//对图象边缘化
Value := 20 * Pixels(x, y)
- 2 * (Pixels(x - 1, y - 1) + Pixels(x + 1, y - 1)
+ Pixels(x - 1, y + 1) + Pixels(x + 1, y + 1))
- 3 * (Pixels(x, y - 1) + Pixels(x - 1, y)
+ Pixels(x + 1, y) + Pixels(x, y + 1));
if Value < 57 then SetPixels(0)
else SetPixels(1);
end;
function GetBorder(Bmp: TBitmap; x, y: Integer): String;
const
dx: array [1..8] of Integer = ( 0, 0, 1,-1, 1,-1,-1, 1);
dy: array [1..8] of Integer = (-1, 1, 0, 0, 1, 1,-1,-1);
var
Ptr: PByteArray;
nx, ny, i: Integer;
begin
//采用递归跟踪方式获得边缘点序列
Result := Format('(%d,%d) ', [x, y]);
Ptr := Bmp.ScanLine[y];
Ptr[x] := 0;
for i := 1 to 8 do begin
nx := x + dx;
ny := y + dy;
if (nx >= 0) and (nx < Bmp.Width) and
(ny >= 0) and (ny < Bmp.Height) then begin
Ptr := Bmp.ScanLine[ny];
if Ptr[nx] = 1 then begin
AppendStr(Result, GetBorder(Bmp, nx, ny));
Break;
end;
end;
end;
end;
procedure TForm1.Button1Click(Sender: TObject);
var
Res, Bmp: TBitmap;
i, j: Integer;
Ptr: PByteArray;
begin
if OpenPictureDialog1.Execute then begin
Bmp := TBitmap.Create;
Res := TBitmap.Create;
try
Bmp.LoadFromFile(OpenPictureDialog1.FileName);
if Bmp.PixelFormat <> pf1Bit then begin
ShowMessage('此位图不是单色位图!');
Exit;
end;
Bmp.PixelFormat := pf8Bit;
//首先把图形边缘化
Res.Width := Bmp.Width;
Res.Height := Bmp.Height;
Res.PixelFormat := pf8Bit;
for j := 0 to Bmp.Height - 1 do
for i := 0 to Bmp.Width - 1 do
Calc(Bmp, Res, i, j);
//保存文件以观察边缘化结果
Res.SaveToFile('c:/a.bmp');
//跟踪边缘获得各颗粒边缘序列
Memo1.Clear;
for j := 0 to Res.Height - 1 do begin
Ptr := Res.ScanLine[j];
for i := 0 to Res.Width - 1 do
if Ptr <> 0 then begin
Memo1.Lines.Add(GetBorder(Res, i, j));
Memo1.Lines.Add('');
end;
end;
finally
Res.Free;
Bmp.Free;
end;
end;
end;