Un archivo de mapa de bits comienza con BITMAPFILEHEADER
, el miembro bfOffBits
especifica la dirección de inicio de los datos de imagen. Este es un DWORD en Dh (11-14th bytes). Delphi VCL tiene la estructura definida como TBitmapFileHeader
en 'windows.pas'.
La última fila del ScanLine
apunta a esta información de imagen (de abajo hacia arriba). El VCL tiene este valor en bmBits
miembro del miembro dsBm
(a BITMAP
) o DIBSECTION
de la imagen. Cuando se solicita una línea de escaneo, la VCL calcula una compensación en función de la fila solicitada, el número de píxeles en una fila (ancho de la imagen) y cuántos bits componen un píxel, y devuelve un puntero a una dirección que agrega esta compensación a bmBits
. En realidad, se trata de datos de imagen byte a byte.
La continuación código de ejemplo Delphi lee un mapa de bits de 24 bits a una secuencia de archivo y compara cada píxel de lectura con los datos de píxeles de la Bitmap.ScanLine
contraparte:
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;
Una imagen sobre la búsqueda de la puesta en marcha de los datos de píxeles de un archivo de mapa de bits en un editor hexadecimal:
el nombre "TBitmap" no necesariamente tiene nada que ver con el formato de archivo "mapa de bits" Microsoft, ya sabes ! La propiedad "scanline" en Delphi "TBitmap" es solo una línea de trama, nada más y nada menos. – paulsm4
¿cuál es el formato de píxel del archivo de mapa de bits y cómo lo carga en un TBitmap? ¿Está tu mapa de bits almacenado de arriba hacia abajo o de abajo hacia abajo? –
¿Qué parte de la estructura quieres entender? Los campos TBitmap o los datos de píxeles? –