delphi bitmap c++builder porting vcl

Entendiendo TBitmap.Scanline en Delphi & C++ Builder



c++builder porting (1)

Un archivo de mapa de bits comienza con un 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 de la ScanLine apunta a esta información de imagen (de abajo hacia arriba). El VCL tiene este valor en el miembro bmBits miembro dsBm (un 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.

El siguiente código de muestra Delphi lee un mapa de bits de 24 bits en una secuencia de archivos y compara cada píxel de lectura con los datos de píxel de la contraparte 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;



Una imagen sobre cómo encontrar el inicio de los datos de píxeles de un archivo de mapa de bits en un editor hexadecimal:

Delphi y C ++ Builder tienen una clase TBitmap con una propiedad Scanline que devuelve la memoria de los píxeles del mapa de bits. Esto parece ser diferente cuando miro en un editor hexadecimal del archivo BMP.

Estoy tratando de portar una aplicación C ++ Builder a Java, y me gustaría entender el algoritmo en Scanline. Si tengo el archivo, ¿cómo puedo generar la matriz de memoria como lo hace Scanline? ¿Cuál es la especificación exacta detrás de Scanline?

Clarificación: el BMP es un DIB de Windows de 24 bits. No proporciono ninguna otra información en el código; C ++ Builder parece cargarlo en algún tipo de estructura de memoria, pero no es byte por byte. Me gustaría saber cuál es la especificación de esa estructura.