unit Unit2; interface uses Windows, Classes, Graphics, OpenGL; type PPixel32 = ^TPixel32; TPixel32 = packed record R: byte; G: byte; B: byte; A: byte; end; PPixel32Array = ^TPixel32Array; TPixel32Array = array[0..MaxInt shr 3] of TPixel32; type TBitmap32 = class private FData: PPixel32Array; FWidth: integer; FHeight: integer; FDataSize: integer; function GetScanLine(Row: integer): PPixel32Array; procedure SetHeight(const Value: integer); procedure SetWidth(Value: integer); public procedure AssignFromBitmap(const Source: TBitmap); constructor Create; destructor Destroy; override; function IsEmpty: boolean; procedure UploadOpenGLTexture(Target: GLEnum; TextureFormat: GLInt); property Data: PPixel32Array read FData; property DataSize: integer read FDataSize; property Height: integer read FHeight write SetHeight; property ScanLine[Row: integer]: PPixel32Array read GetScanLine; property Width: integer read FWidth write SetWidth; end; implementation procedure BGR24ToRGBA32(Source, Dest: pointer; PixelCount: integer); begin while PixelCount > 0 do begin PChar(Dest)[0] := PChar(Source)[2]; PChar(Dest)[1] := PChar(Source)[1]; PChar(Dest)[2] := PChar(Source)[0]; PChar(Dest)[3] := #255; dest := Pointer(Integer(Dest) + 4); Source := Pointer(Integer(Source) + 3); Dec(PixelCount); end; end; procedure TBitmap32.AssignFromBitmap(const Source: TBitmap); var iRow: integer; iRowOffset: integer; pSource: PChar; pDest: PChar; begin Assert(Source.PixelFormat = pf24bit); Assert((Source.Width and 3) = 0); FWidth := Source.Width; FHeight := Source.Height; FDataSize := FWidth * FHeight * 4; ReAllocMem(FData, FDataSize); if Height > 0 then begin pDest := @PChar(FData)[Width * 4 * (Height - 1)]; if Height = 1 then begin BGR24ToRGBA32(Source.ScanLine[0], pDest, Width); end else begin pSource := Source.ScanLine[0]; iRowOffset := Integer(Source.ScanLine[1]) - Integer(pSource); for iRow := 0 to Height - 1 do begin BGR24ToRGBA32(pSource, pDest, Width); Dec(pDest, Width * 4); Inc(pSource, iRowOffset); end; end; end; end; constructor TBitmap32.Create; begin inherited Create; end; destructor TBitmap32.Destroy; begin FreeMem(FData); inherited Destroy; end; function TBitmap32.GetScanLine(Row: integer): PPixel32Array; begin Result := PPixel32Array(@FData[Row * Width]); end; function TBitmap32.IsEmpty: boolean; begin Result := (Width = 0) or (Height = 0); end; procedure TBitmap32.UploadOpenGLTexture(Target: GLEnum; TextureFormat: GLInt); var pBuffer: pointer; begin pBuffer := Pointer(FData); glTexImage2d(Target, 0, TextureFormat, Width, Height, 0, GL_RGBA, GL_UNSIGNED_BYTE, pBuffer); FreeMem(pBuffer); end; procedure TBitmap32.SetHeight(const Value: integer); begin if FHeight <> Value then begin Assert(Value >= 0); FHeight := Value; FDataSize := FWidth * FHeight * 4; ReallocMem(FData, FDataSize); end; end; procedure TBitmap32.SetWidth(Value: integer); begin if (Value and 3) > 0 then Value := (Value and $FFFC) + 4; if FWidth <> Value then begin Assert(Value >= 0); FWidth := Value; FDataSize := FWidth * FHeight * 4; ReallocMem(FData, FDataSize); end; end; end.