如何转化256色图为灰度图;(100分)

  • 主题发起人 主题发起人 zrj
  • 开始时间 开始时间
Z

zrj

Unregistered / Unconfirmed
GUEST, unregistred user!
{-----------------------------------------------------------------------------
过程名称 :TBitmapProcess.Convert8BitBmpToGrayBmp
作者 :
日期 :09-五月-2003
参数描述 :None
返回值 :Boolean
函数功能 :转化256色图为灰度图;
-----------------------------------------------------------------------------}

function TBitmapProcess.Convert8BitBmpToGrayBmp: Boolean;
var
pal: array[0..255] of TPaletteEntry;
bMap : array[0..255] of Byte;
Rvalue, Gvalue, Bvalue: byte;
Gray: Double; //灰度
SourceBmp: TBitmap;
i, j :integer;
P :PByteArray;
begin
Result := False;

SourceBmp := Self.FCurbmp;

GetPaletteEntries(SourceBmp.Palette, 0, 256, pal);
for j:= 0 to 255 do
begin
Rvalue := Pal[j].peRed;
Gvalue := pal[j].peGreen;
Bvalue := pal[j].peBlue;
Gray := 0.299 * Rvalue + 0.587 * Gvalue + 0.114 * Bvalue;
bMap[j]:= Round(Gray);
Pal[j].peRed := j;
Pal[j].peGreen := j;
Pal[j].peBlue := j;
end;

for i := 0 to Self.FBitmapHeight - 1 do
begin
p := SourceBmp.ScanLine;
for j := 0 to Self.FBitmapWidth - 1 do
begin
P[j] := bMap[P[j]];
end;
end;
SetPaletteEntries(SourceBmp.Palette, 0, 256, pal);

Result := True;
end;

调用得过程如下;

begin
。。。
BitmapProcess.Convert8BitBmpToGrayBmp;
Self.Image1.Picture.Bitmap := BitmapProcess.Curbmp;

end;

转化结果不正确,至少显示不正确,我应该如何处理,修改系统调色板,或者是文件头?
请高手帮忙看看!

我看论坛都是24位图得例子,我是256色图,各位看看,这个问题困扰我很久了,谢谢!

 
简单的转换好像有问题。
转换的结果不是纯正的灰度图
 
调用时严格设定输入的位图是使用调色板的!否则不能得到需要的效果。
也不对啊,你没有在程序里修改调色板条目啊。是用真彩色的灰度转换。
 
是这样的,函数中:
begin
Rvalue := Pal[j].peRed;
Gvalue := pal[j].peGreen;
Bvalue := pal[j].peBlue;
Gray := 0.299 * Rvalue + 0.587 * Gvalue + 0.114 * Bvalue;
end;
是直接对彩色位图的像素作灰度转换,其中不需要涉及调色板。如果使用调色板,是
需要对系统调色板以外的其他调色板条目作灰度替换后,应用给位图就行。
 
具体该如何做呢??各位给个意见,谢谢!
 
先将图象转换成24位的,这样就不用考虑调色板了。
 
{功能:彩色图像转变成灰阶图像(即消彩色)的处理函数
参数: Image 消彩色的图像}
procedure GrayChange(var Image:TImage);
var
p :PByteArray;
x,y,p3 :Integer;
Bmp :TBitmap;
begin
Bmp :=TBitmap.Create; //把图像载入暂存图像
Bmp.Assign(Image.Picture.Bitmap);
bmp.pixelformat:=pf24bit; //这样保险,确保24位位图
for y:=0 to Bmp.Height-1 do
begin
p:=Bmp.scanline[y];
p3:=0;
for x:=0 to Bmp.Width-1 do //消彩处理
begin
if not ((p[p3]=p[p3+1]) and (p[p3+1]=p[p3+2])) then
begin
p[p3]:=(p[p3+2]*2 + p[p3+1]*5 + p[p3]) shr 3;
p[p3+1]:=p[p3];
p[p3+2]:=p[p3];
end;
inc(p3,3);
end;
end;
Image.Picture.Bitmap.Assign(bmp);
bmp.free;
end;
 
小雨的算法是求出灰度Gray,如果想在显示出来也很简单,让r=g=b=Gray就行了.
wjames的算法是抖动,但显示出来的效果可能不能接受,至少要把RGB各个分量分别算一下.
 
有人能给出正确的算法并讲明道理嘛?
另外不要考虑用24位图,一个3000*3000的图象 ,24位色就是30M,速度很慢的呀,内存。

所以各位还是考虑256色图转化的问题吧,

//获得调色板数据;
GetPaletteEntries(SourceBmp.Palette, 0, 256, pal);

for j:= 0 to 255 do
begin
//计算灰度
Rvalue := Pal[j].peRed;
Gvalue := pal[j].peGreen;
Bvalue := pal[j].peBlue;
Gray := 0.299 * Rvalue + 0.587 * Gvalue + 0.114 * Bvalue;

bMap[j]:= Round(Gray);
//修改调色板数据;
Pal[j].peRed := j;
Pal[j].peGreen := j;
Pal[j].peBlue := j;
end;

//设置位图调色板数据;
SetPaletteEntries(SourceBmp.Palette, 0, 256, pal);

哪儿有问题啊??
 
bMap[j]:= Round(Gray);
//修改调色板数据;
Pal[j].peRed := j;
Pal[j].peGreen := j;
Pal[j].peBlue := j;


这里应该是

bMap[j]:=j;
Pal[j].peRed := Round(Gray);
Pal[j].peGreen := Round(Gray);
Pal[j].peBlue := Round(Gray);

的样子吧,不然等于是设置调色板编号为i的颜色是RGB都等于i的颜色,
同时还打乱了原来图上的颜色阿。
 
to : Wiley_liu;
说的是,我 “设置调色板编号为i的颜色是RGB都等于i的颜色,
同时还打乱了原来图上的颜色”。
操作B 然后就找出用图在原来调色板的颜色编号a,把他赋值为b[a]就应该是新颜色了呀,
奇怪是,我掉用ScanLine就不用做操作B了,好像delphi自动转化,用FreeImage也可以,
我都能不请到底delphi的那个过程自动转化了,真是奇怪,

上边错误的原因是我调用ScanLine后,象素值已经由a变为b[a],所以不做操作b就正确了
可是究竟那个过程做了这个自动转化呢,希望高手说个明白
 
这个可以实现你的要求:
procedure TForm1.Button2Click(Sender: TObject);
var
pal: array[0..255] of TPaletteEntry;
Rvalue, Gvalue, Bvalue: byte;
Gray: Double; //灰度
SourceBmp: TBitmap;
j: integer;
begin
Image1.Picture.Bitmap.PixelFormat := pf8bit;
SourceBmp := Tbitmap.create;
SourceBmp.Assign(Image1.Picture.Bitmap);
GetPaletteEntries(SourceBmp.Palette, 0, 256, pal);
for j := 0 to 255 do
begin
Rvalue := Pal[j].peRed;
Gvalue := pal[j].peGreen;
Bvalue := pal[j].peBlue;
Gray := 0.299 * Rvalue + 0.587 * Gvalue + 0.114 * Bvalue;
Pal[j].peRed := Round(Gray);
Pal[j].peGreen := Round(Gray);
Pal[j].peBlue := Round(Gray);
end;
SetPaletteEntries(SourceBmp.Palette, 0, 256, pal);
{设置新的颜色到DIB调色板}
RealizePalette(SourceBmp.Canvas.Handle);
{射逻辑调色板到系统硬件调色板}
Image1.Picture.Bitmap.Assign(SourceBmp);
Image1.Invalidate;
SourceBmp.free;
end;
 
虽然我得问题没有解决,不过经过实验,huazai算法可行!
 
后退
顶部