Un file bitmap inizia con un BITMAPFILEHEADER
, il membro bfOffBits
specifica l'indirizzo iniziale dei dati dell'immagine. Questo è un DWORD a Dh (11-14th byte). Delphi VCL ha la struttura definita come TBitmapFileHeader
in "windows.pas".
L'ultima riga del ScanLine
punta a questi dati immagine (dal basso verso l'alto). Il VCL ha questo valore nel membro bmBits
del membro dsBm
(a BITMAP
) o nello DIBSECTION
dell'immagine. Quando viene richiesta una linea di scansione, il VCL calcola un offset in base alla riga richiesta, al numero di pixel di una riga (larghezza dell'immagine) e al numero di bit che costituiscono un pixel e restituisce un puntatore a un indirizzo aggiungendo questo offset a bmBits
. Sono davvero dati di immagine byte per byte.
Il sotto Delphi codice di esempio si legge in una bitmap 24 bit ad un flusso di file e lo confronta ogni pixel di lettura con i dati dei pixel del Bitmap.ScanLine
controparte:
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;
Un'immagine di trovare la partenza dei dati pixel di un file bitmap in un editor esadecimale:
fonte
2011-09-19 15:47:29
il nome "TBitmap" non significa necessariamente avere a che fare con il formato di file "bitmap" Microsoft, sai ! La proprietà "scanline" in una "TBitmap" di Delphi è solo una linea raster - niente di più, niente di meno. – paulsm4
qual è il formato pixel del file bitmap e come lo si carica in un TBitmap? La tua bitmap è memorizzata in alto o in basso? –
Quale parte della struttura vuoi capire? I campi TBitmap o i dati dei pixel? –