怎么样去读取一个BMP位图文件?也就是读取它的文件头、位图信息头、颜色信息和图形数据等信息?
解决方案 »
- implementation {$R *.dfm} 问题?
- 可以控制在RichEdit组件中显示多个字段的内容吗?
- 一个简单问题
- TTable 控件filter属性的设置问题———————在线等待!!!!!
- 玩过tsGrid(TopGrid)的朋友请进。
- ??图书馆管理系统??
- function AllocateHWnd(Method: TWndMethod): HWND; 有谁知道是干什么的吗?
- 请问如何实现变量的变量
- SQL Server中 的序号字段设了标识,那我做了无数次的删除添加等反复类似操作后,这个整型值的字段会不会溢出?
- to taidy():对不起,请来这里拿分!
- 获得DBGrid某行某字段的值,再传另一个窗体,怎么做?
- 请高手能给一个比较好的解决方案~~
BMP文件由文件头、位图信息头、颜色信息和图形数据四部分组成。
BMP文件头
BMP文件头数据结构含有BMP文件的类型、文件大小和位图起始位置等信息。
其结构定义如下:
typedef struct tagBITMAPFILEHEADER
{
WORDbfType; // 位图文件的类型,必须为BM
DWORD bfSize; // 位图文件的大小,以字节为单位
WORDbfReserved1; // 位图文件保留字,必须为0
WORDbfReserved2; // 位图文件保留字,必须为0
DWORD bfOffBits; // 位图数据的起始位置,以相对于位图
// 文件头的偏移量表示,以字节为单位
} BITMAPFILEHEADER;
位图信息头
BMP位图信息头数据用于说明位图的尺寸等信息。
typedef struct tagBITMAPINFOHEADER{
DWORD biSize; // 本结构所占用字节数
LONGbiWidth; // 位图的宽度,以像素为单位
LONGbiHeight; // 位图的高度,以像素为单位
WORD biPlanes; // 目标设备的级别,必须为1
WORD biBitCount// 每个像素所需的位数,必须是1(双色),
// 4(16色),8(256色),16(增强色),24(增强色)或32(真彩色)之一
DWORD biCompression; // 位图压缩类型,必须是 0(不压缩),
// 1(BI_RLE8压缩类型)或2(BI_RLE4压缩类型)之一
DWORD biSizeImage; // 位图的大小,以字节为单位
LONGbiXPelsPerMeter; // 位图水平分辨率,每米像素数
LONGbiYPelsPerMeter; // 位图垂直分辨率,每米像素数
DWORD biClrUsed;// 位图实际使用的颜色表中的颜色数
DWORD biClrImportant;// 位图显示过程中重要的颜色数
} BITMAPINFOHEADER;
颜色表 颜色表用于说明位图中的颜色,它有若干个表项,每一个表项是一个RGBQUAD类型的结构,定义一种颜色。RGBQUAD结构的定义如下:
typedef struct tagRGBQUAD {
BYTErgbBlue;// 蓝色的亮度(值范围为0-255)
BYTErgbGreen; // 绿色的亮度(值范围为0-255)
BYTErgbRed; // 红色的亮度(值范围为0-255)
BYTErgbReserved;// 保留,必须为0
} RGBQUAD;
颜色表中RGBQUAD结构数据的个数有biBitCount来确定:
当biBitCount=1,4,8时,分别有2,16,256个表项;
当biBitCount=16,24,32时,没有颜色表项。
位图信息头和颜色表组成位图信息,BITMAPINFO结构定义如下:
typedef struct tagBITMAPINFO {
BITMAPINFOHEADER bmiHeader; // 位图信息头
RGBQUAD bmiColors[1]; // 颜色表
} BITMAPINFO;
位图数据
位图数据记录了位图的每一个像素值,记录顺序是在扫描行内是从左到右,扫描行之间是从下到上。位图的一个像素值所占的字节数:
当biBitCount=1时,8个像素占1个字节(从左边的位算起:b7~b0);
当biBitCount=4时,2个像素占1个字节(从左边的位算起:b7-b4,b3-b0);
当biBitCount=8时,1个像素占1个字节;
当biBitCount=16时,1个像素占2个字节(BGR555格式);
当biBitCount=24时,1个像素占3个字节(BGR格式);
当biBitCount=32时,1个像素占4个字节(BGR-格式,-表示不处理的字节);
Windows规定一个扫描行所占的字节数必须是
4的倍数(即以long为单位),不足的以0填充,
一个扫描行所占的字节数计算方法:
DataSizePerLine= (biWidth* biBitCount+31)/8;
// 一个扫描行所占的字节数
DataSizePerLine= DataSizePerLine/4*4; // 字节数必须是4的倍数
位图数据的大小(不压缩情况下):
DataSize= DataSizePerLine* biHeight;
Delphi里也应该有类似的结构定义
var
Ori: TFileStream;
buffer:LongInt;
begin
buffer:=0;
Ori := TFileStream.Create(mpFilePath, fmOpenRead);
//读宽度
Ori.Seek(18, soFromBeginning);
Ori.Read(buffer,4);
mpWidth:= buffer;
//读高度
buffer:=0;
Ori.Seek(22, soFromBeginning);
Ori.Read(buffer,4);
mpHeight:=buffer;
//读bit数
buffer:=0;
Ori.Seek(28, soFromBeginning);
Ori.Read(buffer,2);
mpBitCount:=buffer; FreeAndNil(Ori);
end;我自己写的类的一部分, 其他的参考bmp文件结构,仿照写就可以了
TMyPicture = class(TObject)
mpImage:TImage;
mpOptionImage:TImage;
mpFilePath: String;
mpWidth, mpHeight: LongInt;
mpBitCount: Integer;
mpGray : Array [0..255] of longint;//直方图 先固定24位,以后修改为用户
private
{ Private declarations }
public
{ Public declarations }
constructor Create(AOwner: TComponent);
destructor Destroy; override; Procedure GetFileInfo();
procedure Histogram(StartX, StartY, Width, Height:Integer); end;constructor TMyPicture.Create(AOwner: TComponent);
begin
inherited Create();
mpImage:=TImage.Create(AOwner) ;
mpImage.Picture.Bitmap.PixelFormat:= pf24bit;
mpOptionImage :=TImage.Create(AOwner) ;
mpOptionImage.Picture.Bitmap.PixelFormat:= pf24bit;
mpFilePath:='';
mpWidth:=0;
mpHeight:=0;
mpBitCount:=0;
end;destructor TMyPicture.Destroy;
begin
mpImage.Free;
mpOptionImage.Free;
inherited;
end;
//----------------------------------------------------------//
procedure TMyPicture.Histogram(StartX, StartY, Width, Height:Integer);
var
i,j:integer;
C,YL,YH,YM : longint;
Y,R,G,B : integer;
all: longint;
begin
i:=0;
j:=0;
for i:=0 to 255 do
mpGray[i]:=0;
i:=0; While i<Width do
begin
j:=0;
While j<Height do
begin
C:=mpImage.Picture.Bitmap.Canvas.Pixels[StartX+i,StartY+j];
R := C and $FF;
G := ((C and $FF00) div $100);
B := ((C and $FF0000) div $10000);
Y :=ceil(0.299*R+0.578*G+0.114*B-0.5);
if Y<>0 then
mpGray[Y]:= mpGray[Y]+1;
j:=j+1;
end;
i:=i+1;
end;end;Procedure TMyPicture.GetFileInfo();
var
Ori: TFileStream;
buffer:LongInt;
begin
buffer:=0;
Ori := TFileStream.Create(mpFilePath, fmOpenRead);
//读宽度
Ori.Seek(18, soFromBeginning);
Ori.Read(buffer,4);
mpWidth:= buffer;
//读高度
buffer:=0;
Ori.Seek(22, soFromBeginning);
Ori.Read(buffer,4);
mpHeight:=buffer;
//读bit数
buffer:=0;
Ori.Seek(28, soFromBeginning);
Ori.Read(buffer,2);
mpBitCount:=buffer; FreeAndNil(Ori);
end;