SRo*_*mes 6 delphi porting vcl bitmap c++builder
Delphi和C++ Builder有一个带有Scanline属性的TBitmap类,它返回位图像素的内存.当我查看BMP文件的十六进制编辑器时,这似乎有所不同.
我正在尝试将C++ Builder应用程序移植到Java,并希望了解Scanline中的算法.如果我有文件,我如何生成像Scanline那样的内存阵列?Scanline背后的确切规格是什么?
Clarifcation:BMP是Windows 24bit DIB.我在代码中没有提供任何其他信息; C++ Builder似乎将它加载到某种类型的内存结构中,但它不是逐字节的.想知道那个结构的规格是什么.
位图文件以a开头BITMAPFILEHEADER
,该bfOffBits
成员指定图像数据的起始地址.这是Dh的DWORD(11-14字节).Delphi VCL具有TBitmapFileHeader
'windows.pas'中定义的结构.
ScanLine
指向此图像数据的最后一行(自下而上).VCL bmBits
在dsBm
(a BITMAP
)成员或DIBSECTION
图像成员中具有此值.当请求扫描线时,VCL根据请求的行,一行中的像素数(图像的宽度)以及构成像素的位数计算偏移量,并返回指向添加此偏移量的地址的指针bmBits
.这是真正的逐字节图像数据.
下面的Delphi示例代码将24位位图读取到文件流,并将每个读取像素与对应的像素数据进行比较Bitmap.ScanLine
:
procedure TForm1.Button1Click(Sender: TObject);
var
BmpFile: string;
Bmp: TBitmap;
fs: TFileStream;
FileHeader: TBitmapFileHeader;
InfoHeader: TBitmapInfoHeader;
iHeight, iWidth, Padding: Longint;
ScanLine: Pointer;
RGBFile, RGBBitmap: TRGBTriple;
begin
BmpFile := ExtractFilePath(Application.ExeName) + 'Attention_128_24.bmp';
// laod bitmap to TBitmap
Bmp := TBitmap.Create;
Bmp.LoadFromFile(BmpFile);
Assert(Bmp.PixelFormat = pf24bit);
// read bitmap file with stream
fs := TFileStream.Create(BmpFile, fmOpenRead or fmShareDenyWrite);
// need to get the start of pixel array
fs.Read(FileHeader, SizeOf(FileHeader));
// need to get width and height of bitmap
fs.Read(InfoHeader, SizeOf(InfoHeader));
// just a general demo - no top-down image allowed
Assert(InfoHeader.biHeight > 0);
// size of each row is a multiple of the size of a DWORD
Padding := SizeOf(DWORD) -
(InfoHeader.biWidth * 3) mod SizeOf(DWORD); // pf24bit -> 3 bytes
// start of pixel array
fs.Seek(FileHeader.bfOffBits, soFromBeginning);
// compare reading from file stream with the value from scanline
for iHeight := InfoHeader.biHeight - 1 downto 0 do begin
// get the scanline, bottom first
ScanLine := Bmp.ScanLine[iHeight];
for iWidth := 0 to InfoHeader.biWidth - 1 do begin
// read RGB from file stream
fs.Read(RGBFile, SizeOf(RGBFile));
// read RGB from scan line
RGBBitmap := TRGBTriple(Pointer(
Longint(ScanLine) + (iWidth * SizeOf(TRGBTriple)))^);
// assert the two values are the same
Assert((RGBBitmap.rgbtBlue = RGBFile.rgbtBlue) and
(RGBBitmap.rgbtGreen = RGBFile.rgbtGreen) and
(RGBBitmap.rgbtRed = RGBFile.rgbtRed));
end;
// skip row padding
fs.Seek(Padding, soCurrent);
end;
end;
Run Code Online (Sandbox Code Playgroud)
关于在十六进制编辑器中查找位图文件的像素数据的图片: