scrapdog
asked on
Accessing pixels in Canvas
Maybe question can be applied particularly to the Pixels property of the TCanvas.
I understand the accessing Pixels requires Canvas to perform one of it methods, and accessing it from assembly language is not as simple as accessing a two dimensional array.
In other words:
mov esi,Canvas.Pixels
should not work. In order to access the array, do I have to go through its methods, or do I have to somehow find a way to sneak into Canvas's private variables? I want to do operations on the Canvas's pixels directly, without having to go through the overhead of the property's methods.
I understand the accessing Pixels requires Canvas to perform one of it methods, and accessing it from assembly language is not as simple as accessing a two dimensional array.
In other words:
mov esi,Canvas.Pixels
should not work. In order to access the array, do I have to go through its methods, or do I have to somehow find a way to sneak into Canvas's private variables? I want to do operations on the Canvas's pixels directly, without having to go through the overhead of the property's methods.
Hi scrapdog,
Isn't this good enough?
{read color}
procedure TForm1.CheckBox1Click(Send er: TObject);
begin
CheckBox1.Font.Color := Canvas.Pixels[10, 10];
end
{change color}
procedure TForm1.Button1Click(Sender : TObject);
begin
Canvas.Pixels[Random(Clien tWidth), Random(ClientHeight)] := clRed;
end;
Regards, Zif.
Isn't this good enough?
{read color}
procedure TForm1.CheckBox1Click(Send
begin
CheckBox1.Font.Color := Canvas.Pixels[10, 10];
end
{change color}
procedure TForm1.Button1Click(Sender
begin
Canvas.Pixels[Random(Clien
end;
Regards, Zif.
Perhaps you should look at CreateDIBSection. There you can give in an array of pixels. But the pixel format depends on the color depth. It's quite difficult...
Regards, Madshi.
Regards, Madshi.
Hello Guys!
What Kevin(scrapdog) is trying to say is that he needs code in assembler or at least how to pass a pixel from the screen or whatever to a register and then start to work w/ that pixel in assembler....The problem is that he is trying to get the X and Y values separately since in assembler the arrays don't work the way in Pascal work... Hope all this makes any sense... Hopefully I understood the question right...If I'm missing something please correct me Kevin :->
Cheers,
Viktor
What Kevin(scrapdog) is trying to say is that he needs code in assembler or at least how to pass a pixel from the screen or whatever to a register and then start to work w/ that pixel in assembler....The problem is that he is trying to get the X and Y values separately since in assembler the arrays don't work the way in Pascal work... Hope all this makes any sense... Hopefully I understood the question right...If I'm missing something please correct me Kevin :->
Cheers,
Viktor
ASKER
Actually, all I need to know is how to get the address of where the pixels are stored. I want to use this in an assembly routine. Once I know the address, I can easily operate on it by calculating X and Y into an offset.
If Pixels were a field rather than a property, I could do this easily. However that is not the case. In order to access Pixels (through assembly), would I have to access Canvas.FPixels (if there is one), or is this just not possible?
If Pixels were a field rather than a property, I could do this easily. However that is not the case. In order to access Pixels (through assembly), would I have to access Canvas.FPixels (if there is one), or is this just not possible?
Definitely look at createdibsection. This does give you a nice chunk of memory full of pixels. The downside is that you have to tailor your code to deal with the pixel depth but this is no major deal.
hey scrapdog !
I have some experience in assembler, since I used it to make libraries for
quickbasic. I'm not sure if this will work on windows too, but the video-card
memory address is located at A000h ( hex ) , In ms-dos programming,
( 16 bit ) it worked like this:
Address ( offset in the A000 segment ) = Y * ( horizontal resolution ) + X
Maybe in 32-bit it's:
Address = 40960*65536 + Y * ( horizontal resolution ) + X
( 40960 is A000 in decimal ) ( so, if each segment is 65536 bytes, it will be 40960*65536)
and if the address was higher than 65535 then u had to toggle the memory pages
of the video card. In 32-bit mode, I'm not sure on how to manage the memory.
I'm not sure if it will help, well, I tried.
Since I've never used assembler in a windows program, I can't tell you if
it's gonna work, but you should be able to read the video-card memory
at that address ( A000 hex ) or at B000 hex or B800 hex, but those 2 last ones,
where used by the text modes. and A000 for grapic modes.
A000 is 40960 in decimal, in the 1st Mb of memory.
bryan
I have some experience in assembler, since I used it to make libraries for
quickbasic. I'm not sure if this will work on windows too, but the video-card
memory address is located at A000h ( hex ) , In ms-dos programming,
( 16 bit ) it worked like this:
Address ( offset in the A000 segment ) = Y * ( horizontal resolution ) + X
Maybe in 32-bit it's:
Address = 40960*65536 + Y * ( horizontal resolution ) + X
( 40960 is A000 in decimal ) ( so, if each segment is 65536 bytes, it will be 40960*65536)
and if the address was higher than 65535 then u had to toggle the memory pages
of the video card. In 32-bit mode, I'm not sure on how to manage the memory.
I'm not sure if it will help, well, I tried.
Since I've never used assembler in a windows program, I can't tell you if
it's gonna work, but you should be able to read the video-card memory
at that address ( A000 hex ) or at B000 hex or B800 hex, but those 2 last ones,
where used by the text modes. and A000 for grapic modes.
A000 is 40960 in decimal, in the 1st Mb of memory.
bryan
Hello Kevin!
I think that even if you access the FPixels it will be of type
type Pix = array[0..MAXVALUE, 0..MAXVALUE];
var
FPixels : Pix;
so it will still an array that you'd have to access same way as the Canvas.Pixels
I think you need to look for FX, FY or X,Y so you could get the [x,y] value of the pixel...
Cheers,
Viktor
I think that even if you access the FPixels it will be of type
type Pix = array[0..MAXVALUE, 0..MAXVALUE];
var
FPixels : Pix;
so it will still an array that you'd have to access same way as the Canvas.Pixels
I think you need to look for FX, FY or X,Y so you could get the [x,y] value of the pixel...
Cheers,
Viktor
ASKER
Thanks, but I don't want to access video memory, nor do I want to create a new bitmap.
All I want to do is access the Pixels property of a Canvas (already created) in an assembly language routine. The only thing I need to know is how I can obtain the address of the *beginning* of the Pixels array. If Pixels were a regular array rather than a property, I could do this:
PixelPtr := @Canvas.Pixels;
But it is a property, so I can't!! (or is this legal AND valid???) The reason I want to access the FPixels array with assembly language is to speed it up a bit and bypass the property's methods.
All I want to do is access the Pixels property of a Canvas (already created) in an assembly language routine. The only thing I need to know is how I can obtain the address of the *beginning* of the Pixels array. If Pixels were a regular array rather than a property, I could do this:
PixelPtr := @Canvas.Pixels;
But it is a property, so I can't!! (or is this legal AND valid???) The reason I want to access the FPixels array with assembly language is to speed it up a bit and bypass the property's methods.
ASKER
Adjusted points to 30
The canvas.Pixels array is no array. Each and every call to this array ends in a method that extract the desired pixel from the canvas. This code is really very slow.
So if you want to have fast code (I think that's what you want) you'll have to work with the win32 API. Ok, you don't want to create a new bitmap. So don't use CreateDIBSection, but GetDIBits/SetDIBits.
Regards, Madshi.
So if you want to have fast code (I think that's what you want) you'll have to work with the win32 API. Ok, you don't want to create a new bitmap. So don't use CreateDIBSection, but GetDIBits/SetDIBits.
Regards, Madshi.
Mashdi is right
Thanx, Jacco. :-)
ASKER
Thanks. I will try using SetDIBits. One question though...what do you send as the Bitmap parameter? I am not aware that Canvas has a Bitmap property...
That's right. About what kind of canvas are we talking? A bitmap canvas or a form canvas or ...
ASKER
Any canvas that can be passed as a TCanvas parameter.
It is likely that I will be passing DrawGrid.Canvas into this parameter. I will not likely be using it for Bitmap.Canvas though.
It is likely that I will be passing DrawGrid.Canvas into this parameter. I will not likely be using it for Bitmap.Canvas though.
Ooops, that's a little bit more difficult than a bitmap.canvas. Perhaps you should create a temporary bitmap by using CreateDIBSection and then call a BitBlt to transfer the DrawGrid's pixels to the newly created bitmap. Then you can use GetDIBits and SetDIBits for the bitmap.
Make sure that the color format of the DrawGrid.canvas and the newly created bitmap is identical.
Haven't done something like this before. Hope it works...
Regards, Madshi.
Make sure that the color format of the DrawGrid.canvas and the newly created bitmap is identical.
Haven't done something like this before. Hope it works...
Regards, Madshi.
ASKER
This would entail copying the entire bitmap twice (I would have to copy the temporary bitmap back).
I think using Pixels would be faster!
Does Canvas have some kind of pointer to the bitmap that it manipulates? If it does, it is probably private so accessing it would be impossible.
Another application that I want to use this information for is do perform a fire algorithm on a Canvas (it could be on a paintbox, panel, etc.) I want to write an assembly language fire algorithm and apply it directly to the canvas.
Thanks for your help so far, by the way.
I think using Pixels would be faster!
Does Canvas have some kind of pointer to the bitmap that it manipulates? If it does, it is probably private so accessing it would be impossible.
Another application that I want to use this information for is do perform a fire algorithm on a Canvas (it could be on a paintbox, panel, etc.) I want to write an assembly language fire algorithm and apply it directly to the canvas.
Thanks for your help so far, by the way.
Directly reading/writing from/to a canvas is quite easy. You can just use BitBlt with the canvas.handle. But if you want to address specific pixels, it's getting more difficult. I think, copying the whole bitmap twice is still much faster then working with the canvas.pixels property.
I didn't work with the windows drawing API that much so far. So you'll have a look at it yourself. Perhaps you should begin with CreateDIBSection and BitBlt. Perhaps there are functions to access the pixels directly with a win API. But the canvas.pixels property is probably quite slow.
Do you have to Delphi sources? Perhaps you should look how the canvas.pixels methods are implemented...
Regards, Madshi.
I didn't work with the windows drawing API that much so far. So you'll have a look at it yourself. Perhaps you should begin with CreateDIBSection and BitBlt. Perhaps there are functions to access the pixels directly with a win API. But the canvas.pixels property is probably quite slow.
Do you have to Delphi sources? Perhaps you should look how the canvas.pixels methods are implemented...
Regards, Madshi.
ASKER
Madshi: for your noble attempts to help, propose an answer.
By the way, where can I get the Delphi source? Specifically the source code to Canvas? Is it somewhere in the source directory? Or do I have to pay Borland $$$?
(I have the source to the Windows unit, etc...)
By the way, where can I get the Delphi source? Specifically the source code to Canvas? Is it somewhere in the source directory? Or do I have to pay Borland $$$?
(I have the source to the Windows unit, etc...)
Here it is.... The original is in the Graphics.pas unit....
-------------------------
TCanvas = class(TPersistent)
private
FHandle: HDC;
State: TCanvasState;
FFont: TFont;
FPen: TPen;
FBrush: TBrush;
FPenPos: TPoint;
FCopyMode: TCopyMode;
FOnChange: TNotifyEvent;
FOnChanging: TNotifyEvent;
FLock: TRTLCriticalSection;
FLockCount: Integer;
FTextFlags: Longint;
procedure CreateBrush;
procedure CreateFont;
procedure CreatePen;
procedure BrushChanged(ABrush: TObject);
procedure DeselectHandles;
function GetCanvasOrientation: TCanvasOrientation;
function GetClipRect: TRect;
function GetHandle: HDC;
function GetPenPos: TPoint;
function GetPixel(X, Y: Integer): TColor;
procedure FontChanged(AFont: TObject);
procedure PenChanged(APen: TObject);
procedure SetBrush(Value: TBrush);
procedure SetFont(Value: TFont);
procedure SetHandle(Value: HDC);
procedure SetPen(Value: TPen);
procedure SetPenPos(Value: TPoint);
procedure SetPixel(X, Y: Integer; Value: TColor);
protected
procedure Changed; virtual;
procedure Changing; virtual;
procedure CreateHandle; virtual;
procedure RequiredState(ReqState: TCanvasState);
public
constructor Create;
destructor Destroy; override;
procedure Arc(X1, Y1, X2, Y2, X3, Y3, X4, Y4: Integer);
procedure BrushCopy(const Dest: TRect; Bitmap: TBitmap;
const Source: TRect; Color: TColor);
procedure Chord(X1, Y1, X2, Y2, X3, Y3, X4, Y4: Integer);
procedure CopyRect(const Dest: TRect; Canvas: TCanvas;
const Source: TRect);
procedure Draw(X, Y: Integer; Graphic: TGraphic);
procedure DrawFocusRect(const Rect: TRect);
procedure Ellipse(X1, Y1, X2, Y2: Integer);
procedure FillRect(const Rect: TRect);
procedure FloodFill(X, Y: Integer; Color: TColor; FillStyle: TFillStyle);
procedure FrameRect(const Rect: TRect);
procedure LineTo(X, Y: Integer);
procedure Lock;
procedure MoveTo(X, Y: Integer);
procedure Pie(X1, Y1, X2, Y2, X3, Y3, X4, Y4: Integer);
procedure Polygon(const Points: array of TPoint);
procedure Polyline(const Points: array of TPoint);
procedure PolyBezier(const Points: array of TPoint);
procedure PolyBezierTo(const Points: array of TPoint);
procedure Rectangle(X1, Y1, X2, Y2: Integer);
procedure Refresh;
procedure RoundRect(X1, Y1, X2, Y2, X3, Y3: Integer);
procedure StretchDraw(const Rect: TRect; Graphic: TGraphic);
function TextExtent(const Text: string): TSize;
function TextHeight(const Text: string): Integer;
procedure TextOut(X, Y: Integer; const Text: string);
procedure TextRect(Rect: TRect; X, Y: Integer; const Text: string);
function TextWidth(const Text: string): Integer;
function TryLock: Boolean;
procedure Unlock;
property ClipRect: TRect read GetClipRect;
property Handle: HDC read GetHandle write SetHandle;
property LockCount: Integer read FLockCount;
property CanvasOrientation: TCanvasOrientation read GetCanvasOrientation;
property PenPos: TPoint read GetPenPos write SetPenPos;
property Pixels[X, Y: Integer]: TColor read GetPixel write SetPixel;
property TextFlags: Longint read FTextFlags write FTextFlags;
property OnChange: TNotifyEvent read FOnChange write FOnChange;
property OnChanging: TNotifyEvent read FOnChanging write FOnChanging;
published
property Brush: TBrush read FBrush write SetBrush;
property CopyMode: TCopyMode read FCopyMode write FCopyMode default cmSrcCopy;
property Font: TFont read FFont write SetFont;
property Pen: TPen read FPen write SetPen;
end;
-----------------
Cheers,
Viktor
-------------------------
TCanvas = class(TPersistent)
private
FHandle: HDC;
State: TCanvasState;
FFont: TFont;
FPen: TPen;
FBrush: TBrush;
FPenPos: TPoint;
FCopyMode: TCopyMode;
FOnChange: TNotifyEvent;
FOnChanging: TNotifyEvent;
FLock: TRTLCriticalSection;
FLockCount: Integer;
FTextFlags: Longint;
procedure CreateBrush;
procedure CreateFont;
procedure CreatePen;
procedure BrushChanged(ABrush: TObject);
procedure DeselectHandles;
function GetCanvasOrientation: TCanvasOrientation;
function GetClipRect: TRect;
function GetHandle: HDC;
function GetPenPos: TPoint;
function GetPixel(X, Y: Integer): TColor;
procedure FontChanged(AFont: TObject);
procedure PenChanged(APen: TObject);
procedure SetBrush(Value: TBrush);
procedure SetFont(Value: TFont);
procedure SetHandle(Value: HDC);
procedure SetPen(Value: TPen);
procedure SetPenPos(Value: TPoint);
procedure SetPixel(X, Y: Integer; Value: TColor);
protected
procedure Changed; virtual;
procedure Changing; virtual;
procedure CreateHandle; virtual;
procedure RequiredState(ReqState: TCanvasState);
public
constructor Create;
destructor Destroy; override;
procedure Arc(X1, Y1, X2, Y2, X3, Y3, X4, Y4: Integer);
procedure BrushCopy(const Dest: TRect; Bitmap: TBitmap;
const Source: TRect; Color: TColor);
procedure Chord(X1, Y1, X2, Y2, X3, Y3, X4, Y4: Integer);
procedure CopyRect(const Dest: TRect; Canvas: TCanvas;
const Source: TRect);
procedure Draw(X, Y: Integer; Graphic: TGraphic);
procedure DrawFocusRect(const Rect: TRect);
procedure Ellipse(X1, Y1, X2, Y2: Integer);
procedure FillRect(const Rect: TRect);
procedure FloodFill(X, Y: Integer; Color: TColor; FillStyle: TFillStyle);
procedure FrameRect(const Rect: TRect);
procedure LineTo(X, Y: Integer);
procedure Lock;
procedure MoveTo(X, Y: Integer);
procedure Pie(X1, Y1, X2, Y2, X3, Y3, X4, Y4: Integer);
procedure Polygon(const Points: array of TPoint);
procedure Polyline(const Points: array of TPoint);
procedure PolyBezier(const Points: array of TPoint);
procedure PolyBezierTo(const Points: array of TPoint);
procedure Rectangle(X1, Y1, X2, Y2: Integer);
procedure Refresh;
procedure RoundRect(X1, Y1, X2, Y2, X3, Y3: Integer);
procedure StretchDraw(const Rect: TRect; Graphic: TGraphic);
function TextExtent(const Text: string): TSize;
function TextHeight(const Text: string): Integer;
procedure TextOut(X, Y: Integer; const Text: string);
procedure TextRect(Rect: TRect; X, Y: Integer; const Text: string);
function TextWidth(const Text: string): Integer;
function TryLock: Boolean;
procedure Unlock;
property ClipRect: TRect read GetClipRect;
property Handle: HDC read GetHandle write SetHandle;
property LockCount: Integer read FLockCount;
property CanvasOrientation: TCanvasOrientation read GetCanvasOrientation;
property PenPos: TPoint read GetPenPos write SetPenPos;
property Pixels[X, Y: Integer]: TColor read GetPixel write SetPixel;
property TextFlags: Longint read FTextFlags write FTextFlags;
property OnChange: TNotifyEvent read FOnChange write FOnChange;
property OnChanging: TNotifyEvent read FOnChanging write FOnChanging;
published
property Brush: TBrush read FBrush write SetBrush;
property CopyMode: TCopyMode read FCopyMode write FCopyMode default cmSrcCopy;
property Font: TFont read FFont write SetFont;
property Pen: TPen read FPen write SetPen;
end;
-----------------
Cheers,
Viktor
ASKER
Rock on! What subdirectory is it located in? I couldn't find it.
If you got D4 then there is a special feature that you just hold down Ctrl and click on TCanvas and the unit that it is in opens immediatelly, and it get's to the line where it is declared...
If you don't have D4 then here is what the path to the Graphics.pas might be...
C:\Program Files\Borland\Delphi3\Sour ce\VCL\Gra phics.pas
Take a look under that path and see what hapens...
If you don't have D4 then here is what the path to the Graphics.pas might be...
C:\Program Files\Borland\Delphi3\Sour
Take a look under that path and see what hapens...
ASKER
Don't have VCL Directory, only RTL :(
What version of Delphi R U using???
ASKER
2 (Gimp) don't rub it in :)
Ok, are you sure you don't have the sources for any of the VCLs...????
btw- Do you know in what unit is the code for the function Length()??? D4 shows it's in System.pas but I didn't find it there.. Any ideas???
Cheers,
Viktor
btw- Do you know in what unit is the code for the function Length()??? D4 shows it's in System.pas but I didn't find it there.. Any ideas???
Cheers,
Viktor
ASKER CERTIFIED SOLUTION
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
ASKER
Thanks Madshi.
Viktor already sent me the source for graphics.pas but thanks anyway.
Viktor already sent me the source for graphics.pas but thanks anyway.
10x Madshi.... The reason why I'm looking for the Length() function is that I wanted to see how it is created.. I mean I need the code if there is one.... I tried a few attempts to accomplish to built the same function but no joy.... If you want to see a few codes I found for Pascal(not Delphi) that determine the lenght of a string just check the question "To All of you" or something like that by Zif... The code is in ASsembler and that's what I need... I need to create it with assembler in Delphi though... When I try to transfer the code from Pascal to Delphi, and even make a few changes it still doesn't work.. PLease help.....
Cheers,
Viktor
Cheers,
Viktor
Viktor,
here comes my enhanced PosStr assembler function. You should be able to get from it how to get the string length in assembler.
function FindStr(const subStr,str: string; fromPos,toPos: cardinal) : cardinal; assembler
asm // EAX EDX ECX [ESP+8] EAX
TEST EAX,EAX // subStr empty ?
JE @@noWork
TEST EDX,EDX // str empty ?
JE @@fail4
TEST ECX,ECX // fromPos = 0 ?
JE @@fail4
PUSH EBX
MOV EBX,ECX // EBX = fromPos
MOV ECX,[ESP+12] // ECX = toPos (+4 w/ PUSH EBX)
TEST ECX,ECX // toPos = 0 ?
JE @@fail3
PUSH ESI
PUSH EDI
MOV ESI,EAX // ESI = substr
MOV EDI,EDX // EDI = str
CMP EBX,ECX // fromPos > toPos ?
JA @@backwards
@@forwards:
MOV EDX,[EDI-4] // EDX = Length(substr)
CMP EBX,EDX // fromPos > Length(str) ?
JA @@fail2
CMP ECX,EDX // toPos <= Length(str) ?
JNA @@toPosOk
MOV ECX,EDX // toPos = Length(str)
@@toPosOk:
MOV EDX,[ESI-4] // EDX = Length(substr)
DEC EDX // EDX = Length(substr) - 1
JS @@fail2 // EDX < 0 ?
PUSH EDI // remember str position to calculate index
DEC EBX // dec(fromPos)
ADD EDI,EBX // "Delete (str, 1, fromPos - 1)"
SUB ECX,EBX // toPos := toPos - fromPos + 1
SUB ECX,EDX // #positions in str to look at = Length(str) - Length(substr) + 1
JBE @@fail1 // #positions <= 0 ?
MOV AL,[ESI] // AL = first char of substr
INC ESI // Point ESI to 2'nd char of substr
@@fwLoop:
REPNE SCASB
JNE @@fail1
MOV EBX,ECX // save outer loop counter
PUSH ESI // save outer loop substr pointer
PUSH EDI // save outer loop str pointer
MOV ECX,EDX
REPE CMPSB
POP EDI // restore outer loop str pointer
POP ESI // restore outer loop substr pointer
JE @@fwFound
MOV ECX,EBX // restore outer loop counter
JMP @@fwLoop
@@fwFound:
POP EDX // restore pointer to first char of str
MOV EAX,EDI // EDI points of char after match
SUB EAX,EDX // the difference is the correct index
POP EDI
POP ESI
POP EBX
JMP @@noWork
@@backwards:
MOV EDX,[EDI-4] // EDX = Length(substr)
CMP ECX,EDX // toPos > Length(str) ?
JA @@fail2
CMP EBX,EDX // fromPos <= Length(str) ?
JNA @@fromPosOk
MOV EBX,EDX // fromPos = Length(str)
@@fromPosOk:
MOV EDX,[ESI-4] // EDX = Length(substr)
DEC EDX // EDX = Length(substr) - 1
JS @@fail2 // EDX < 0 ?
MOV EAX,EDI // remember str position to calculate index
ADD EAX,EDX // add backwards calculation
SUB EAX,2
PUSH EAX
DEC ECX // dec(toPos)
ADD EDI,ECX // "Delete (str, 1, toPos - 1)"
SUB EBX,ECX // fromPos := fromPos - toPos + 1
MOV ECX,EBX // swap (fromPos, lastPos)
ADD EDI,ECX
DEC EDI
ADD ESI,EDX
SUB ECX,EDX // #positions in str to look at = Length(str) - Length(substr) + 1
JBE @@fail1 // #positions <= 0 ?
MOV AL,[ESI] // AL = first char of substr
DEC ESI // Point ESI to 2'nd char of substr
STD
@@bwLoop:
REPNE SCASB
JNE @@fail0
MOV EBX,ECX // save outer loop counter
PUSH ESI // save outer loop substr pointer
PUSH EDI // save outer loop str pointer
MOV ECX,EDX
REPE CMPSB
POP EDI // restore outer loop str pointer
POP ESI // restore outer loop substr pointer
JE @@bwFound
MOV ECX,EBX // restore outer loop counter
JMP @@bwLoop
@@bwFound:
POP EDX // restore pointer to first char of str + backwards calculation
MOV EAX,EDI // EDI points of char after match
SUB EAX,EDX // the difference is the correct index
CLD
POP EDI
POP ESI
POP EBX
JMP @@noWork
@@fail0:
CLD
@@fail1:
POP EDX // get rid of saved str pointer
@@fail2:
POP EDI
POP ESI
@@fail3:
POP EBX
@@fail4:
XOR EAX,EAX
@@noWork:
end;
Regards, Madshi.
here comes my enhanced PosStr assembler function. You should be able to get from it how to get the string length in assembler.
function FindStr(const subStr,str: string; fromPos,toPos: cardinal) : cardinal; assembler
asm // EAX EDX ECX [ESP+8] EAX
TEST EAX,EAX // subStr empty ?
JE @@noWork
TEST EDX,EDX // str empty ?
JE @@fail4
TEST ECX,ECX // fromPos = 0 ?
JE @@fail4
PUSH EBX
MOV EBX,ECX // EBX = fromPos
MOV ECX,[ESP+12] // ECX = toPos (+4 w/ PUSH EBX)
TEST ECX,ECX // toPos = 0 ?
JE @@fail3
PUSH ESI
PUSH EDI
MOV ESI,EAX // ESI = substr
MOV EDI,EDX // EDI = str
CMP EBX,ECX // fromPos > toPos ?
JA @@backwards
@@forwards:
MOV EDX,[EDI-4] // EDX = Length(substr)
CMP EBX,EDX // fromPos > Length(str) ?
JA @@fail2
CMP ECX,EDX // toPos <= Length(str) ?
JNA @@toPosOk
MOV ECX,EDX // toPos = Length(str)
@@toPosOk:
MOV EDX,[ESI-4] // EDX = Length(substr)
DEC EDX // EDX = Length(substr) - 1
JS @@fail2 // EDX < 0 ?
PUSH EDI // remember str position to calculate index
DEC EBX // dec(fromPos)
ADD EDI,EBX // "Delete (str, 1, fromPos - 1)"
SUB ECX,EBX // toPos := toPos - fromPos + 1
SUB ECX,EDX // #positions in str to look at = Length(str) - Length(substr) + 1
JBE @@fail1 // #positions <= 0 ?
MOV AL,[ESI] // AL = first char of substr
INC ESI // Point ESI to 2'nd char of substr
@@fwLoop:
REPNE SCASB
JNE @@fail1
MOV EBX,ECX // save outer loop counter
PUSH ESI // save outer loop substr pointer
PUSH EDI // save outer loop str pointer
MOV ECX,EDX
REPE CMPSB
POP EDI // restore outer loop str pointer
POP ESI // restore outer loop substr pointer
JE @@fwFound
MOV ECX,EBX // restore outer loop counter
JMP @@fwLoop
@@fwFound:
POP EDX // restore pointer to first char of str
MOV EAX,EDI // EDI points of char after match
SUB EAX,EDX // the difference is the correct index
POP EDI
POP ESI
POP EBX
JMP @@noWork
@@backwards:
MOV EDX,[EDI-4] // EDX = Length(substr)
CMP ECX,EDX // toPos > Length(str) ?
JA @@fail2
CMP EBX,EDX // fromPos <= Length(str) ?
JNA @@fromPosOk
MOV EBX,EDX // fromPos = Length(str)
@@fromPosOk:
MOV EDX,[ESI-4] // EDX = Length(substr)
DEC EDX // EDX = Length(substr) - 1
JS @@fail2 // EDX < 0 ?
MOV EAX,EDI // remember str position to calculate index
ADD EAX,EDX // add backwards calculation
SUB EAX,2
PUSH EAX
DEC ECX // dec(toPos)
ADD EDI,ECX // "Delete (str, 1, toPos - 1)"
SUB EBX,ECX // fromPos := fromPos - toPos + 1
MOV ECX,EBX // swap (fromPos, lastPos)
ADD EDI,ECX
DEC EDI
ADD ESI,EDX
SUB ECX,EDX // #positions in str to look at = Length(str) - Length(substr) + 1
JBE @@fail1 // #positions <= 0 ?
MOV AL,[ESI] // AL = first char of substr
DEC ESI // Point ESI to 2'nd char of substr
STD
@@bwLoop:
REPNE SCASB
JNE @@fail0
MOV EBX,ECX // save outer loop counter
PUSH ESI // save outer loop substr pointer
PUSH EDI // save outer loop str pointer
MOV ECX,EDX
REPE CMPSB
POP EDI // restore outer loop str pointer
POP ESI // restore outer loop substr pointer
JE @@bwFound
MOV ECX,EBX // restore outer loop counter
JMP @@bwLoop
@@bwFound:
POP EDX // restore pointer to first char of str + backwards calculation
MOV EAX,EDI // EDI points of char after match
SUB EAX,EDX // the difference is the correct index
CLD
POP EDI
POP ESI
POP EBX
JMP @@noWork
@@fail0:
CLD
@@fail1:
POP EDX // get rid of saved str pointer
@@fail2:
POP EDI
POP ESI
@@fail3:
POP EBX
@@fail4:
XOR EAX,EAX
@@noWork:
end;
Regards, Madshi.
10x Madshi...but John helped me a whole lot.... Here is what he gave me and oit works perfectly...
function Str_Len(Str : String):Integer;
asm
MOV EAX, [EAX - 4]
end;
Cheers,
Viktor
function Str_Len(Str : String):Integer;
asm
MOV EAX, [EAX - 4]
end;
Cheers,
Viktor
ASKER
Maybe *this* question can be applied particularly to the Pixels property of the TCanvas.
I understand *that* accessing Pixels requires Canvas to perform one of its methods, and accessing it from assembly language is not as simple as accessing a two dimensional array.
In other words:
mov esi,Canvas.Pixels
should not work. In order to access the array, do I have to go through its methods, or do I have to somehow find a way to sneak into Canvas's private variables? I want to do operations on the Canvas's pixels directly, without having to go through the overhead of the property's methods.