如何将已经得到的位图文件头、信息头、调色板、数据在内存中构建BMP位图?(200分)

  • 主题发起人 主题发起人 coolqiang
  • 开始时间 开始时间
C

coolqiang

Unregistered / Unconfirmed
GUEST, unregistred user!
我需要编程浏览一些特殊格式的图片,这些图片的格式同BMP查不多,我的处理方法是将此
文件转为位图格式的临时文件temp.bmp,然后再用Image1.Picture.LoadFromFile(...)。
我知道可以Bitmap:=TBitmap.Create在内存中创建一位图,那么如何将位图文件头、信息
头、调色板、数据传过去呢?这样我就不用每次都生成临时文件那么麻烦了,直接在内存
中构建,然后调用,会方便很多!
如果能在回答的同时附带一个小的演示程序最好,只要将一个BMP文件1.bmp显示出来就行,
但记住,是要分别将BMP文件的文件头、信息头、调色板、数据传过去的方式,不要告诉我
直接Image1.Picture.LoadFromFile(1.bmp)啊!
 
使用以下结构:
typedef struct tagBITMAP { /* bm */
int bmType;
int bmWidth;
int bmHeight;
int bmWidthBytes;
BYTE bmPlanes;
BYTE bmBitsPixel;
LPVOID bmBits;
} BITMAP;
另外,我总是觉得你的方法似乎太麻烦。为什么要存盘呢?你在内存中建立TBitmap
然后把你的图片格式画在此Bitmap上,再画在Image.Picture.Bitmap.Canvas上不可以吗?
等待再讨论。
 
你的图像是24bit颜色?
 
你既然可以将文件保存到硬盘的临时文件,为什么不能保存为内存里的临时文件?这样不就可以了吗?
 
to 吕雪松:画上去?你是指一个像素一个像素的画颜色?太慢了!不信你试试下面这样:
for i:=1 to 640
for j:=1 to 480
Form1.Canvas.Pixels[i,j]:=clRed;
你看看要多长时间!
to Reboot:无所谓多少色的,256色的话就有调色板,16bit、24bit色就没有调色板,这
些不成问题,我已经弄清楚了,我只是要知道如何在内存中弄出来!
to ypy:在内存里保存?具体如何做呢?我很想听一听!

另:或者有另外的思路也可以,只要能使图片显示的速度非常快就行!
 
使用Form1.Canvas.Pixels当然慢啦。
应该使用一临时TBitmap对象,用Bitmap.ScanLine,画完后Form1.Canvas.Draw(Bitmap)就快的多。
 
First,你所要的只是将已有的位图数据内容加上一个头信息,那很简单,利用
TBitmapFileHeader和TBitmapInfoHeader可以很容易填写头信息,然后,用
TMemoryStream,Seek(0,soFromBeginning),先把文件和信息头写进去,然后再
写数据,那就可以LoadFromStream.
Second,将图像画到Bitmap上去,未必要逐点赋值;即便要逐点赋值,也可以做得很
快,可以参考FastBmp的直接内存读写.
抄一段我写的有关的创建设备无关位图(DIB)直接内存读写点信息给你看:
...
const hSection = 0;
type
TFColor = record b,g,r:Byte end;
PFColor =^TFColor;
TLine = array[0..0]of TFColor;
PLine =^TLine;
TPLines = array[0..0]of PLine;
PPLines =^TPLines;
...
var
FFileHeader : TBitmapFileHeader;
FInfoHeader : TBitmapInfoHeader;
FInfo : TBitmapInfo;
FBits : Pointer;

Self.PixelFormat:=pf24bit; //设定你的Bitmap都为24位真彩,统一格式.

//Bitmap 文件头
with FFileHeader do
begin
bfType := $4D42;
bfSize := AWidth*AHeight*3+SizeOf(TBitmapFileHeader)+SizeOf(TBitmapInfoHeader);
bfReserved1 := 0;
bfReserved2 := 0;
bfOffBits := SizeOf(TBitmapFileHeader)+SizeOf(TBitmapInfoHeader);
end;

with FInfoHeader do
begin
biSize := SizeOf(TBitmapInfoHeader);
biWidth := AWidth;
biHeight := AHeight;
biPlanes := 1;
biBitCount := 24;
biCompression := BI_RGB;
biSizeImage := AWidth * AHeight * 3;
end;
FInfo.bmiHeader:=FInfoHeader;
FMyHandle:=CreateDIBSection(0,
FInfo,
DIB_RGB_COLORS,
FBits,
hSection,
0);
memDC:=GetDC(0);

GetDIBits(memDC,Self.Handle,0,AHeight,FBits,FInfo,DIB_RGB_COLORS);
ReleaseDC(memDC);
最重要是两个API,分别是创建一个内存DIB并给指针FBits分配内存,下一句则是
将该DIB的内容读入FBits所指的内存区域.以后的事就简单了,对每一个点,只要
让一个指针指向所需的内存区域:
GetMem(FPixels,AHeight * SizeOf(PLine)); //你自己定义的一个象素点指针
RowInc := (AWidth * 3 + AWidth mod 4); //每行都是4的整数倍个字节
XPointer := Integer(FBits);
for LoopI:=0 to AHeight - 1 do
begin
FPixels^[LoopI] := Pointer(XPointer);
Inc(XPointer,RowInc{ + AWidth mod 4});
end;
{下面这一段是为了让你可以用BitBlt和StretchBlt等直接对HDC进行图像操作
的API,也就是说可以象操作TCanvas那样进行操作,不过要记得,当所有的图像操作
完以后,要GdiFlush才能让对应的FBits内存刷新,切记切记 }
if FMyhDC<>0 then DeleteDC(FMyhDC);
FMyhDC:=CreateCompatibleDC(0);

SelectObject(FMyhDC,FMyHandle);

有什么地方不懂的话可以去看FastBmp的源码,上面一段基本是照抄,我是用在自己
定义的扩展TBitmap类中的.希望对你有帮助.
对了,想要FastBmp的话我可以mail你.
 
我想看fastbmp的源码,能否emai我吗?
 
你的信箱呢?
 
不好意思,让大家久等了,前几天我怎么都上不来,太慢了。

to JohnsonGuo:能说具体一些吗?最好是来个小程序!
to pomb:能把FastBmp的源码寄给我吗?我的信箱 huaqiang2@163.net
 
to pomb:为什么在将安装控件FastBMP、FastFX、FastRGB时报告FastBMP出错:
Handle:=CreateDIBSection(0,
bmInfo,
DIB_RGB_COLORS,
Bits,
hSection,
0);
系统提示hSection这一行Incompatible types:'Cardinal' and 'Pointer',该怎么办?
 
const hSection = 0;
其实C中的NULL就是0,nil是pascal中的空指针标志.
 
多人接受答案了。
 

Similar threads

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