![]() |
Problem mit Pointer auf dyn. Array
Hallo,
es handelt sich hier um eine Methode, die einen String in eine Bitmap schreiben soll. Funktioniert soweit ganz gut, mich stört aber, dass ich es nicht hinkrieg MyLine der Größe einer Zeile der Bitmap anzupassen. Wenn mans auf 32768 setzt reichts garantiert, ist dann aber wenn man ein 100x100 Bitmap verwendet wenig sinnvoll. Daher hätte ich das gern ein wenig adaptiver. Zum Gedanken: MyLine:^TDynRGB is ein Zeiger auf ein Dynamisches Array, eine Adresse. Wenn ich sie auflös, sollte ich mit SetLength doch eine Länge hinbringen können. Warum geht das nicht? Und noch ne Frage: Kann man die Methode noch 'effizienter' gestalten? (Speicher/Laufzeit/whatever..)
Delphi-Quellcode:
MfG nEmai
type
TRGBTripleArray = Array[0..3999] of TRGBTriple; TDynRGB = Array of TRGBTriple; function MergeTextToBitmap(aBitmap: TBitmap; aString: String): TBitmap; var iHeight, iWidth, iBitCount: Integer; MyLine: ^TRGBTripleArray;//^TDynRGB; begin iBitCount:= 0; //SetLength(MyLine^, aBitmap.Width); aString:= IntToStr(Length(aString)) + '/' + aString; aBitmap.PixelFormat:= pf24Bit; for iHeight:= 0 to aBitmap.Height - 1 do begin MyLine:= aBitmap.ScanLine[iHeight]; for iWidth:= 0 to aBitmap.Width - 1 do begin if not ((iBitCount + 1) > (Length(aString) * 8)) then MyLine[iWidth].rgbtRed:= (MyLine[iWidth].rgbtRed and $FE) or ((Ord(aString[(iBitCount div 8) + 1]) shr (iBitCount mod 8)) and $01); Inc(iBitCount); end; end; Result:= aBitmap; end; |
Re: Problem mit Pointer auf dyn. Array
Ein Pointer kostet vier Byte, demnach kostet dich MyLine auch nur vier Byte. Und der Grund, warum du SetLength nicht anwenden kannst: du hast keinen Speicher für das Array reserviert, das müsstest du erst mit New(MyLine) tun. Dann würde aber der Zugriff auf ScanLine nicht mehr richtig funktionieren. In solchen Fällen benutzt man aber meist keine Arrays, sondern typisierte Pointer:
Delphi-Quellcode:
function MergeTextToBitmap(aBitmap: TBitmap; aString: String): TBitmap;
var iHeight, iWidth, iBitCount: Integer; MyLine: ^TRGBTriple; begin iBitCount:= 0; aString:= IntToStr(Length(aString)) + '/' + aString; aBitmap.PixelFormat:= pf24Bit; for iHeight:= 0 to aBitmap.Height - 1 do begin MyLine:= aBitmap.ScanLine[iHeight]; for iWidth:= 0 to aBitmap.Width - 1 do begin if not ((iBitCount + 1) > (Length(aString) * 8)) then MyLine^.rgbtRed:= (MyLine^.rgbtRed and $FE) or ((Ord(aString[(iBitCount div 8) + 1]) shr (iBitCount mod 8)) and $01); Inc(iBitCount); Inc(MyLine); end; end; Result:= aBitmap; end; |
Re: Problem mit Pointer auf dyn. Array
Ich würde das aus meiner relativ bescheidenen Erfahrung nicht empfehlen, weil ich mit exakt diesem Sourcecode ziemlich auf die Nase gefallen bin. (Auch was die 1. Präsentation des Ganzen anging..)
Auf meinem PC funktioniert es anstandslos, auf 3 von 4 weiteren Access Violations ohne Ende. Auf Grund dieses 'schockierenden' Erlebnisses stufe ich es jetzt als gefährlich ein, Pointer zu inkrementieren. :mrgreen: Kann man das gar nich dynamisch machen? Zur Not lass ich es halt doch so. MfG nEmai |
Re: Problem mit Pointer auf dyn. Array
Hallo,
es gibt zwei grundsätzliche Wege zur Lösung deines Problems. Den einen mit der expliziten Pointer-Arithmetik hat dir Dax gezeigt. Die Alternative ist eine implizite Pointer-Arithmetik. Dabei musst du aber immer noch mit Zeigern arbeiten, da der von ScanLine gelieferte Speicherbereich ja nicht von dir kontrolliert wird. Bei ausgeschaltetem Range-Checking kannst du über dieses Pseudo-Array zugreifen
Delphi-Quellcode:
Freundliche Grüße
type
TRGBTripleArray = Array[0..0] of TRGBTriple; PRGBTripleArray = ^TRGBTripleArray; var myLine: PRGBTripleArray; |
Re: Problem mit Pointer auf dyn. Array
Interessant, das funktioniert.
Und lässt sich leicht auf konstant trimmen, sollte ich wieder AV-Probleme kriegen. Noch ne Frage zum Schluss: Was bedeutet ausgeschaltetes Range-Checking? Eben diese [0..0] Grenzangabe? MfG&Danke nEmai |
Re: Problem mit Pointer auf dyn. Array
Mit dem Compiler-Switch {$R+} kannst du Delphi zur Erzeugung von Prüfroutinen anweisen, die dir zur Laufzeit z.B. Bereichsüberschreitungen für Indexwerte melden. Der einzig gültige Indexwert im obigen Beispiel wäre dann 0, was dich nicht glücklich machen dürfte.
|
Alle Zeitangaben in WEZ +1. Es ist jetzt 17:04 Uhr. |
Powered by vBulletin® Copyright ©2000 - 2025, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024-2025 by Thomas Breitkreuz