了解Delphi和C Builder中的TBitmap.Scanline

德尔福& C Builder有一个带有Scanline属性的TBitmap类,它返回位图像素的内存.当我查看BMP文件的十六进制编辑器时,这似乎有所不同.

我正在尝试将C Builder应用程序移植到Java,并希望了解Scanline中的算法.如果我有文件,我如何生成像Scanline那样的内存阵列? Scanline背后的确切规格是什么?

Clarifcation:BMP是Windows 24bit DIB.我在代码中没有提供任何其他信息; C Builder似乎将它加载到某种类型的内存结构中,但它不是逐字节的.想知道那个结构的规格是什么.

解决方法

位图文件BITMAPFILEHEADER开头,bfOffBits成员指定图像数据的起始地址.这是Dh的DWORD(11-14字节). Delphi VCL的结构在’windows.pas’中定义为TBitmapFileHeader.

ScanLine的最后一行指向此图像数据(自下而上). VCL在dsBm(a BITMAP)成员的bmBits成员或映像的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;

关于在十六进制编辑器中查找位图文件的像素数据的图片

相关文章

 从网上看到《Delphi API HOOK完全说明》这篇文章,基本上都...
  从网上看到《Delphi API HOOK完全说明》这篇文章,基本上...
ffmpeg 是一套强大的开源的多媒体库 一般都是用 c/c+&#x...
32位CPU所含有的寄存器有:4个数据寄存器(EAX、EBX、ECX和ED...
1 mov dst, src dst是目的操作数,src是源操作数,指令实现的...