求教:一个关于图象处理的难题(200分)

  • 主题发起人 主题发起人 wzhiwei
  • 开始时间 开始时间
W

wzhiwei

Unregistered / Unconfirmed
GUEST, unregistred user!
呵呵,最近小弟遇到了一个图象处理的难题:如何读取位图的象素值。好像说法不是很正确
就是图象的灰度值,比如一副图片,黑白两种颜色,把它从头到尾逐点读取。如何读出并且得到
该图象白色或者黑色部分的信息。谁有源代码给我一份,或者相关的控件什么的
小弟顿首百谢,现在急用。谢谢各位大侠了
 
写过一段将图片转成region的程序, 希望能帮你:
定义:
{从tbitmap中获取region}
function CreateRgnFromBmp(Bmp: TBitmap; TransColor: TColor; x:Integer=0; y: Integer=0): HRGN;
{从单色图中获取region}
function CreateRgnFromMask(Msk: HBITMAP; x: Integer = 0 y: Integer=0): HRGN;

实现:

function CreateRgnFromBmpBits(Bits: Pointer; Left, Top, Width, height, gap: Integer): HRGN;
var
Rct: TRect;
i, l: Integer;
RgnH: PRgnDataHeader;
MaxLen: Integer;
p, p1: PByte;
b, e: Byte;
LineP, LastP: PRect;

procedure ResizeRects;
var
p: PRect;
begin
p := LineP;
while Integer(p) < Integer(LastP) do
begin
Inc(p^.Bottom);
Inc(p);
end;
Inc(RgnH^.rcBound.Bottom);
end;

procedure NewRectInStruct(x, y: Integer);
var
i, j: Integer;
begin
if Integer(LastP) >= Integer(RgnH) + MaxLen then
begin
i := Integer(LastP) - Integer(RgnH);
j := Integer(LineP) - Integer(RgnH);
Inc(maxLen, 4096);
ReAllocMem(RgnH, MaxLen);
LastP := Pointer(Integer(RgnH) + i);
LineP := Pointer(Integer(RgnH) + j);
end;
Inc(RgnH^.nCount);
with LastP^ do
begin
Left := x;
Top := y;
Right := x + 1;
Bottom := y + 1;
if Left < RgnH^.rcBound.Left then
RgnH^.rcBound.Left := Left;
if Top < RgnH^.rcBound.Top then
RgnH^.rcBound.Top := Top;
if Right > RgnH^.rcBound.Right then
RgnH^.rcBound.Right := Right;
if Bottom > RgnH^.rcBound.Bottom then
RgnH^.rcBound.Bottom := Bottom;
end;
end;

function IsScanLineEmpty(v: PByte): Boolean;
var
i: Integer;
begin
if l < 0 then
Result := (v^ or b) = $ff
else begin
Result := v^ or b = $ff;
if not Result then Exit;
Inc(v);
for i := 0 to l - 1 do
begin
Result := Result and (v^ = $ff);
if not Result then Exit;
Inc(v);
end;
Result := v^ or e = $ff;
end;
end;

function SameScanLine(v, v1: PByte): Boolean;
begin
Result := (v^ or b) = (v1^ or b);
if not Result then Exit;
if l < 0 then Exit;
Inc(v);
Inc(v1);
if l > 0 then
Result := CompareMem(v, v1, l);
if not Result then Exit;
Inc(v, l);
Inc(v1, l);
Result := v^ or e = v1^ or e;
end;

procedure ScanLineToRects(n: Integer; v: PByte);
var
i, j, x: Integer;
f: Boolean;
begin
LineP := LastP;
f := False;
x := Rct.Left and $fffffff8;
for i := 0 to 7 do
if $80 shr i and (v^ or b) = 0 then
if f then Inc(LastP^.Right)
else begin
NewRectInStruct(x + i, n);
f := True;
end
else if f then
begin
f := False;
Inc(LastP);
end;
if l >= 0 then
begin
Inc(v);
Inc(x, 8);
for i := 0 to l-1 do
begin
if v^ and $ff = $ff then
if f then begin
f := False;
Inc(LastP);
end
else
else if v^ and $ff = 0 then
if f then
Inc(LastP^.Right, 8)
else begin
f := True;
NewRectInStruct(x, n);
Inc(LastP^.Right, 7);
end
else
for j := 0 to 7 do
if ($80 shr j) and v^ = 0 then
if f then
Inc(LastP^.Right)
else begin
f := True;
NewRectInStruct(x + j, n);
end
else if f then
begin
f := False;
Inc(LastP);
end;
Inc(v);
Inc(x, 8);
end;
for i := 0 to 7 do
if $80 shr i and (v^ or e) = 0 then
if f then Inc(LastP^.Right)
else begin
NewRectInStruct(x + i, n);
f := True;
end
else if f then
begin
f := False;
Inc(LastP);
end;
end;
if f then Inc(LastP);
if Integer(LastP) > Integer(LineP) then
with PRect(Integer(LastP)-16)^ do
if Right > RgnH^.rcBound.Right then
RgnH^.rcBound.Right := Right;
end;

begin
Rct := Rect(0,0,Width, abs(Height));
if IsRectEmpty(Rct) then
begin
Result := CreateRectRgn(-2, -2, -1, -1);
Exit;
end;
MaxLen := SizeOf(_RGNDATAHEADER);
GetMem(RgnH, MaxLen);
LastP := Pointer(Integer(RgnH) + MaxLen);
RgnH^.dwSize := MaxLen;
RgnH^.iType := RDH_RECTANGLES;
RgnH^.nCount := 0;
with RgnH^.rcBound do
begin
Left := Rct.Right + 1;
Top := Rct.Bottom + 1;
Right := Rct.Left - 1;
Bottom := Rct.Top - 1;
end;
l := (Rct.Right - Rct.Left) shr 3;
if Rct.Left mod 8 <> 0 then Inc(l);
if Rct.Right mod 8 <> 0 then Inc(l);
Dec(l, 2);
if height > 0 then
begin
p := pointer(integer(bits)+(height-1)*gap);
gap := -gap;
end
else
p := bits;
p1 := p;
b := $ff shl (8 - Rct.Left mod 8);
e := $ff shr ((Rct.Right-1) mod 8 + 1);
if l < 0 then
b := b or e;
ScanLineToRects(Rct.Top, p);
p := Pointer(Integer(p) + gap);
for i := Rct.Top + 1 to Rct.Bottom - 1 do
begin
if not IsScanLineEmpty(p) then
if SameScanLine(p, p1) then
ResizeRects
else
ScanLineToRects(i, p);
p := Pointer(Integer(p) + gap);
p1 := Pointer(Integer(p1) + gap);
end;
if IsRectEmpty(RgnH^.rcBound) then
Result := CreateRectRgn(-2, -2, -1, -1)
else begin
RgnH^.nRgnSize := RgnH^.nCount * 16;
Result := ExtCreateRegion(nil, RgnH^.nRgnSize + SizeOf(_RGNDATAHEADER),
PRgnData(Integer(RgnH))^);
offsetrgn(result, left, top);
end;
FreeMem(RgnH, MaxLen);
end;

function CreateRgnFromMask(Msk: HBITMAP; x, y: Integer): HRGN;
var
Info: PBitmapInfo;
Bits: Pointer;
InfoSize, ImgSize: DWORD;
DS: TDIBSection;
DC: HDC;
Gap: Integer;
begin
infosize := sizeof(TBitmapInfo)+256*sizeof(TRGBQuad);
GetObject(Msk, sizeof(ds), @ds);
info := allocmem(infosize);
fillchar(info^, sizeof(TBitmapInfo), #0);
with info^.bmiHeader do
begin
bisize := sizeof(TBitmapInfoHeader);
biWidth := ds.dsBm.bmWidth;
biheight := ds.dsBm.bmHeight;
biplanes := 1;
bibitcount := 1;
gap := bytesperscanline(biwidth, 1, 32);
imgsize := gap * abs(biheight);
bits := allocmem(imgsize);
dc := createcompatibledc(0);
getdibits(dc, msk, 0, biheight, bits, info^, DIB_RGB_COLORS);
deletedc(dc);
result := creatergnfromBmpbits(bits, x, y, biwidth, biheight, Gap);
end;
freemem(info, infosize);
freemem(bits, imgsize);
end;

function CreateRgnFromBmp(Bmp: TBitmap; TransColor: TColor; x, y: Integer): HRGN;
var
monoDC, ScreenDC: HDC;
MonoImg: HBITMAP;
sav: THandle;
begin
screendc := getdc(0);
monodc := createcompatibledc(screendc);
monoimg := createbitmap(bmp.width, bmp.height, 1, 1, nil);
sav := selectobject(monodc, monoimg);
setbkcolor(bmp.canvas.handle, colortorgb(transcolor));
bitblt(monodc, 0, 0, bmp.width, bmp.height, bmp.canvas.handle, 0, 0, SRCCOPY);
selectobject(monodc, sav);
deletedc(monodc);
releasedc(0, screendc);
result := creatergnfrommask(monoimg, x, y);
deleteobject(monoimg);
end;



 
多谢了

wzhiwei99@etang.com
 
呵呵,比如一副图片,黑白两种颜色,把它从头到尾逐点读取。如何读出并且得到
该图象白色或者黑色部分的信息。
<img>http://wzhiwei_1.home.chinaren.com/star-pap.gif</img>
比如上面图象,我想区分出哪一颗星星的在这副图象的位置,这个怎么完成啊
 
star-pap.gif

图片没有显示出
 
管理一份 PointList .
 
我可以把PHOTOSHOP里的直方图画出来。这个看行不行,要是行的话,我下次给你这个代码。
 
Another_eYes大侠的太复杂了,简单一点就可以实现啊,看看Scanline的帮助,你就知道怎么处理了
 
后退
顶部