把BMP图像读入到二维数组(200分属于谁)(200分)

  • 主题发起人 主题发起人 quickchop
  • 开始时间 开始时间
Q

quickchop

Unregistered / Unconfirmed
GUEST, unregistred user!
要求根据BMP的文件头来把各像素的信息读入到三个二维数组里(即r,g,b值)。为方便,
给出BMP的文件头:
type tbmphdr_def=record
BMPID:integer;
BFSize:longint;
BFreserver1:integer;
BFreserver2:integer;
Imagebegin:longint;
HeaderSize:longint;
Width:longint;
height:longint;
planes:integer;
bits:integer;
compress:longint;
imagesize:longint;
xpixelpermeter:longint;
ypixelpermeter:longint;
colorused:longint;
colorimport:longint;
end;
是不是应该以二进制的形式打开bmp文件,还要得到文件号?文件指针?有劳各位了。
要快。尽量详细一点,我delphi学得不好。
 
注意不能用loadfromfile,最后我要用读到信息的二维数组把图像现实出来。
 
如果要直接 读,首先你要知道Bmp文件头的每个数据的意义。这在一般的图象处理
或图象格式大全上都有。对于压缩格式的还必须解码才能使用。
流程为:
打开文件(bin)
读数据头,根据width&height定义一个二维数组
由colorused/colorimput知道图象的色彩数
把记录指针跳过HeaderSize的数据,然后可以按行或按字节读出来。
根据色彩数分解数据得到r g b值。

不过如果定义一个BMP的graphics对象后,loadfromfile,可以直接从canvas上得到
每个像素点的值,然后就可以得到RGB了,不用去分析bmp文件头。
 
24 位图用 ScanLine 非常容易(用 LoadFromFile 也无妨)

var
ab, ag, ar: array of array of byte;
bmp: TBitmap;
i, j: integer;
pb: PByteArray;
begin
bmp := TBitmap.Create;
bmp.LoadFromFile('图象.bmp');
setLength(ab, bmp.Height, bmp.Width);
setLength(ag, bmp.Height, bmp.Width);
setLength(ar, bmp.Height, bmp.Width);

for i := 0 to bmp.Height - 1 do
begin
p := bmp.ScanLine;
for j := 0 to bmp.Width - 1 do
begin
ab[i, j] := p[j];
ag[i, j] := p[j + 1];
ar[i, j] := p[j + 2];
end;
end;

bmp.Free;
end;

其它位数的位图类似
 
非常感谢二位。hawkfly您所阐述的思路正是我想要的,可是我不会编写代码,您能写代码给
我吗?cqbaobao我把您的代码试了一下,显示出来的图像并不正确。能否在考虑。我最后要用
image1.canvas.pixels[i,j]:=rgb(r[i,j],b[i,j],b[i,j])的语句把图像显示出来。也就是我要
通过bmp的文件头来获取各像素的r,g,b值。
 
呵呵,不好意思,没验证,这个应该可以了

procedure TForm1.Button1Click(Sender: TObject);
var
ab, ag, ar: array of array of byte;
bmp: TBitmap;
i, j: integer;
pb: PByteArray;
begin
bmp := TBitmap.Create;
bmp.LoadFromFile('d:/1.bmp');
Canvas.Draw(0, 0, bmp);

setLength(ab, bmp.Height, bmp.Width);
setLength(ag, bmp.Height, bmp.Width);
setLength(ar, bmp.Height, bmp.Width);

for i := 0 to bmp.Height - 1 do
begin
pb := bmp.ScanLine;
for j := 0 to bmp.Width - 1 do
begin
ab[i, j] := pb[j * 3];
ag[i, j] := pb[j * 3 + 1];
ar[i, j] := pb[j * 3 + 2];
end;
end;

image1.Width := bmp.Width;
image1.Height := bmp.Height;

for i := 0 to bmp.Height - 1 do
for j := 0 to bmp.Width - 1 do
image1.canvas.pixels[j, i] := rgb(ar[i, j], ag[i, j], ab[i, j]);
// 注意这里,pixel[j, i] 不是 [i, j]

bmp.Free;
end;

另外:我认为系统既然提供的功能,我们就尽可能利用!

 
非常感谢。cqbaobao还是不行,pb这里出问题。请问pb到底是个什么东西,动态数组吗?scanline又是什么
意思呢?刚开始时是i,j,后来又是j,i。能不能修正一下?麻烦。小弟愚笨。
另外,有没有哪位知道hawkfly的解法。这是我们老板布置的一个题目,他要求那样。拜托。
 
//全局变量
var
R, G, B: array of array of byte;

procedure BitmapPixle(FileName:String);
var
Bitmap:TBitmap;
i,j:Integer;
color:TColor;
begin
Bitmap := TBitmap.Create;
Bitmap.LoadFromFile(FileName);
setLength(R, Bitmap.Width, Bitmap.Height);
setLength(G, Bitmap.Width, Bitmap.Height);
setLength(B, Bitmap.Width, Bitmap.Height);
for i:=0 to Bitmap.Width-1 do
begin
for j:=0 to Bitmap.Height-1 do
begin
color:=Bitmap.Canvas.Pixels[i,j];
R[i,j]:=GetRValue(color);
G[i,j]:=GetGValue(color);
B[i,j]:=GetBValue(color);
end;
end;
end;
 
你用的不是 24 位图吧? 如果这样的话请你用 amakusa 的方法简单:)

pb 是个数组指针,ScanLine 是 BMP 文件每一行的内容

帮助里都有的
 
cqbaobao,还是不行。例如我的width=384,当j到128时就出错,好像是出界了,您再看看是怎么回事。
另外,您会hawkfly说的那种解法吗?感谢各位。
 
384 div 128 =3
 
amukusa的方法好像比较慢,对是对了。coilbaby你没有弄懂我的意思。pb会出界然后出错,我想
知道怎么修改。有没有哪位会hawkfly的方法。另外分数应该怎么分配?拜托各位
 
我倒
扫描线会很快 可我怕你看不懂
 
你用的是 256 色图吧,如果还用我的方法,就得操作调色板了,我也不会:(
 
cqbaobao,我用的是全彩色。可PB数组会出界。您试验一下就知道了。amukusa有什么好的方法
尽管说。我虚心向您请教。您的将各色素分解的办法是行得通的,就是慢了一点。
 
把我那个换成扫描线会提升速度。
 
cqbaobao我刚才又试验了一下。扫描线完成之后,就马上显示出图片来。这不符合我的要求
我要把各像素的组分色素rgb三个存放在二位数组里。因为以后我要对它们进行处理,如增强
线性变换等。可是您后面的代码好像也没有达到这个功能。
 
改自cqbaobao
var
ab, ag, ar: array of array of byte;

procedure TForm1.Button1Click(Sender: TObject);
bmp: TBitmap;
i, j: integer;
pb: PByteArray;
begin
bmp := TBitmap.Create;
bmp.LoadFromFile('d:/1.bmp');
Canvas.Draw(0, 0, bmp);

setLength(ab, bmp.Height, bmp.Width);
setLength(ag, bmp.Height, bmp.Width);
setLength(ar, bmp.Height, bmp.Width);

for i := 0 to bmp.Height - 1 do
begin
pb := bmp.ScanLine;
for j := 0 to bmp.Width - 1 do
begin
ab[i, j] := pb[j * 3];
ag[i, j] := pb[j * 3 + 1];
ar[i, j] := pb[j * 3 + 2];
end;
end;
bmp.Free;
end;
 
amukusa您是不是看错了,您的跟cqbaobao一模一样,还说“改自”。您上机试验一下,就
知道错在哪里了。麻烦改过后再给我。
另:您会不会hawkfly的读文件头的方法。
 
这个程序我当然验证过:)

你把你的图象E给我吧:szchengyu@163.com

另外你要对数组处理只需将我的程序分开,将 ag, ab, ar 定义为全局变量即可(amukusa所作的就是这一步)

另外我还对你对"如增强线性变换等"很感兴趣,能否交流交流:)
 

Similar threads

S
回复
0
查看
3K
SUNSTONE的Delphi笔记
S
S
回复
0
查看
2K
SUNSTONE的Delphi笔记
S
D
回复
0
查看
2K
DelphiTeacher的专栏
D
后退
顶部