Ich versuche, auf die Scanlinie einer Bitmap gemäß einer article on Embarcadero zuzugreifen. Mit Scanlinien wieWie kann der Scanline-Zugriff von TBitmap korrekt implementiert werden?
for y := 0 to n do
begin
line := bitmap.scanline [y];
for x := 0 to n do line [x] := value;
habe ich zuvor implementiert. Ich bemerkte, dass der Zugriff auf eine Scanline relativ viel Zeit in Anspruch nimmt und der oben genannte Artikel bietet eine Lösung dafür. Ich kann es nicht richtig implementieren. Mein Code ist:
unit SCTester;
interface
uses Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
ExtCtrls;
type
TRGBQuad = packed record
b: uInt8;
g: uInt8;
r: uInt8;
alpha: uInt8;
end; // Record: TQuad //
// Override the definitions in Graphics.pas
TRGBQuadArray = packed array [0..MaxInt div SizeOf (TRGBQuad) - 1] of TRGBQuad;
PRGBQuadArray = ^TRGBQuadArray;
TForm1 = class(TForm)
Image: TImage;
procedure ImageDblClick(Sender: TObject);
end;
var Form1: TForm1;
implementation
{$R *.dfm}
procedure TForm1.ImageDblClick(Sender: TObject);
var Bitmap: TBitmap;
q: TRGBQuad;
x, y: NativeInt;
FirstLine: PRGBQuadArray;
idx: NativeInt;
LineLength: NativeInt;
begin
q.r := 0; q.g := 0;
Bitmap := TBitmap.Create;
Bitmap.Height := Image.Height;
Bitmap.Width := Image.Width;
Bitmap.PixelFormat := pf32Bit;
FirstLine := Bitmap.ScanLine [0];
LineLength := (NativeInt (Bitmap.Scanline [1]) - NativeInt (FirstLine)) div SizeOf (TRGBQuad);
try
for y := Bitmap.Height - 1 downto 0 do
begin
for x := 0 to Bitmap.Width - 1 do
begin
q.b := (x xor y) mod 255;
idx := y * LineLength + x;
FirstLine [idx] := q;
end; // for
end; // for
Image.Picture.Assign (Bitmap);
finally
Bitmap.Free;
end; // try..finally
end;
end.
Und ich bekomme immer einen illegalen Zugang, wenn y = 1 und x = 0. LineLength ist negativ (die Breite der Bitmap), aber das könnte erwartet werden. Was mache ich falsch?
BEARBEITEN Sie: Der obige Code wird geändert, um die bis jetzt bearbeiteten Anmerkungen wiederzugeben.
'tun idx' als' NativeInt' erklärt werden sollte, so könnte Ihr Code als auch in x64 verwendet werden. 'LineLength' darf nicht negativ sein (daher der illegale Zugriff). Meine Schlussfolgerung ist, dass Sie diesen Code im 64-Bit-Modus ausführen. –
@LURD, Meine Gedanken genau - und jede LongInt (...) sollte durch NativeUInt ersetzt werden (...) – kobik
@LURD LineLength kann negativ sein (und ist normalerweise negativ), das ist kein Problem, das AV verursacht. – kludg