Я бы создал на каждое пятно по региону (HRGN). А потом считал бы площадь региона. Функции накиданы на скорую руку, но рабочие:
1. Указываем битмап, точку, пустой регион и цвет - получите вместо пустого региона - регион пятна с указанным цветом.
Код:
procedure _Do(bmp: TBitMap; X, Y: Integer; c: TColor; var r: hRgn);
var
rg_T: HRgn;
begin
if (bmp.Canvas.Pixels[X, Y] <> c) or PtInRegion(r, X, Y) then Exit;
rg_T := CreateRectRgn(X, Y, X + 1 , Y + 1);
CombineRgn(r, r, rg_T, RGN_OR);
DeleteObject(rg_T);
if X > 0 then _DO(bmp, X - 1, Y, c, r);
if X < bmp.Width - 1 then _DO(bmp, X + 1, Y, c, r);
if Y > 0 then _DO(bmp, X, Y - 1, c, r);
if Y < bmp.Height - 1 then _DO(bmp, X, Y + 1, c, r);
end;
2. Передаем полученный выше регион и получаем его площадь в квадратных пикселях:
Код:
function RgnSquare(r: hRgn): Int64;
type
TRectArray = Array[0..9999] of TRect;
PRectArray = ^TRectArray;
var
i: Integer;
RgnData: PRgnData;
RgnDataSize: DWord;
RectArrayPtr: PRectArray;
begin
Result := 0;
RgnDataSize:= GetRegionData(r, 0, nil);
GetMem(RgnData, RgnDataSize);
GetRegionData(r, RgnDataSize, RgnData);
if RgnData^.rdh.nCount > 0 then
begin
RectArrayPtr:= @RgnData.Buffer;
for i := 0 to RgnData^.rdh.nCount - 1 do
with RectArrayPtr[i] do
Result := Result + (Bottom - Top) * (Right - Left);
end;
FreeMem(RgnData);
end;
3. Пример использования:
Код:
var
c: TColor;
rg_R: HRgn;
begin
c := Image1.Canvas.Pixels[0, 0];
rg_R := CreateRectRgn(0, 0, 0, 0);
//================
_Do(Image1.Picture.Bitmap, 0, 0, c, rg_R);
FillRgn(Canvas.Handle, rg_R, Canvas.Pen.Handle);
ShowMessage(IntToStr(RgnSquare(rg_R)));
//================
DeleteObject(rg_R);
end;
__________________
Грамотно поставленный вопрос содержит не менее 50% ответа.
Грамотно поставленная речь вызывает уважение, а у некоторых даже зависть.
|