怎样将一幅图片转化成灰度图?(100分)

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

windy

Unregistered / Unconfirmed
GUEST, unregistred user!
如何将一幅图片转化成灰度图,我用的方法是提取图片的每一个象素然后改变
他的值,但是非常的慢,希望寻求一种高效率的方法,并具体一点,多谢!
 
改变palette的颜色值.
然后将图片格式转成pf8bit.
 
将一幅图片转化成灰度图,具体来说应该分为以下几步:
1.提取图片的每一个象素的值,然后建立三个数据表,1->G 2->R 3->B.
2.为每一种颜色值建立一附图.
方法如下:
若源图一点为 (R100,G200,B210),这相应的三附图的点颜色为1_(100,100,100), 2_(200,200,200),3_(210,210,210).
3. 你说希望寻求一种高效率的方法,但我个人认为什么方法可能都需要提取图片的每一个象素,你也不可能只是要将一幅图片转化成灰度图(否则这可用专门的software),往后来还是要知道每一个象素的数据.我做过这个程序,速度还可以(在386上).


上面是基于图片在屏幕上的方法,如果你的图片是文件就简单多了,在读文件时只分别读RGB,再写屏就可以了.

 
改palette最快, 灰度只有256阶, 用256色位图, 改掉palette就改变全图了.(只要循环256次).
 
你看这样行不行,速度比不上Another_eYes的方法快.但可以满足我的要求.



type
TFColor = record
b,g,r:Byte
end;

PFColor =^TFColor;

procedure Gray(srcBmp,DstBmp:TBitMap);
var
x,y: Integer;
Gr: Byte;
incRow,Gap: integer;
DstTmp,SrcTmp: PFColor;
SrcBmInfo,DstBmInfo: TBitmapInfo;
SrcBmHeader,DstBmHeader: TBitmapInfoHeader;
width,height,Size: integer;
SrcBits,DstBits: pointer;
mDC: Integer;
begin
Width:=SrcBmp.Width;
Height:=SrcBmp.Height;
Size:=((Width*3)+(Width mod 4))*Height;
incRow:=((Width*3)+(Width mod 4));
Gap:=Width mod 4;
DstBmp.Assign(SrcBmp);//这句可要可不要,看情况定
getMem(srcBits,size);
getMem(DstBits,size);
with SrcbmHeader do begin
biSize:=SizeOf(SrcbmHeader);
biWidth:=Width;
biHeight:=-Height;
biPlanes:=1;
biBitCount:=24;
biCompression:=BI_RGB;
end;
SrcbmInfo.bmiHeader:=srcbmHeader;

with DstbmHeader do begin
biSize:=SizeOf(DstbmHeader);
biWidth:=Width;
biHeight:=-Height;
biPlanes:=1;
biBitCount:=24;
biCompression:=BI_RGB;
end;
DstbmInfo.bmiHeader:=DstbmHeader;

try
mDC:=GetDC(0);
GetDIBits(mDC,srcBmp.Handle,0,Height,srcBits,srcbmInfo,DIB_RGB_COLORS);

DstTmp:=DstBits;
for y:=0 to Height-1 do begin
for x:=0 to Width-1 do begin
SrcTmp:=pointer(integer(SrcBits)+(y*IncRow+x*3));
Gr := HiByte(SrcTmp^.r * 77 + SrcTmp^.g * 151 + SrcTmp^.b * 28);
DstTmp^.r:=Gr;
DstTmp^.g:=Gr;
DstTmp^.b:=Gr;
Inc(DstTmp);
end;
DstTmp:=Pointer(Integer(DstTmp)+Gap);
end;
SetDIBits(mDC,DstBmp.Handle,0,Height,DstBits,DstbmInfo,DIB_RGB_COLORS);
ReleaseDC(0,mDC);
finally
freemem(SrcBits);
freemem(DstBits);
end;
end;

其中GetDIBBits和SetDIBBits函数可以看API帮助.这个方法与显存有关,
如果你的显存不够大,大图象就处理不,600X600的图象需要
600x600x3=1080000Bytes的显存.
 
DIB不是device independant bitmap吗?
和设备无关的, 在内存中.
DDB才和显存有关.
不用palette的话:
onedolphi的程序稍微修改了一下:
procedure Gray(bmp: TBitmap);
var
p: PByteArray;
w: Integer;
i, j: Integer;
begin
bmp.pixelformat := pf24bit;
for i := 0 to bmp.height - 1 do
begin
p := bmp.scanline;
j := 0;
while j < (bmp.width-1) * 3 do
begin
w :=(p[j] * 28 + p[j+1] * 151 + p[j+2]*77);
w := w shr 8;
p[j] := byte(w);
p[j+1] := byte(w);
p[j+2] := byte(w);
inc(j, 3)
end;
end;
end;

速度也够快了(800*600 < 0.5s).
 
to Another_eYes:
如果位图原来是256色的,改变了pixelformat后,如果要保存处理过的位图,如何?
 
直接保存即可.
如果一定要256色, 处理完了再改回来, 然后保存.
 
多人接受答案了。
 

Similar threads

S
回复
0
查看
1K
SUNSTONE的Delphi笔记
S
S
回复
0
查看
900
SUNSTONE的Delphi笔记
S
S
回复
0
查看
3K
SUNSTONE的Delphi笔记
S
S
回复
0
查看
2K
SUNSTONE的Delphi笔记
S
后退
顶部