Bonjour à tous,
J'aimerai savoir s'il existe un équivalent à la fonction CopyMemory() de Delphi sous Windows pour Lazarus sous Linux. Si non, quelle pourrait être la solution de remplacement ?
Bonne journée à tous,
Slander
Version imprimable
Bonjour à tous,
J'aimerai savoir s'il existe un équivalent à la fonction CopyMemory() de Delphi sous Windows pour Lazarus sous Linux. Si non, quelle pourrait être la solution de remplacement ?
Bonne journée à tous,
Slander
System.Move
Bonjour,
je remonte ce vieux topic parce que google me l'a remonté, malheureusement j'ai le don pour trouver des discussions moisies...
Qu'on en juge :
Déjà, avec une réponse aussi laconique, le pauvre OP a dû souffrir, et on constate que la discussion n'est pas résolue...
Essayons donc tous ensemble de trouver une solution (pas pour l'OP, ça a dû être résolu, vous pensez, 7 ans déjà...).
La doc MSDN indique pour le CopyMemory :
Méfiance avec l'utilisation de move car on trouve dans systemh.inc la ligne Procedure Move(const source; var dest; count:SizeInt);Code:
1
2
3
4
5 void CopyMemory( _In_ PVOID Destination, _In_ const VOID *Source, _In_ SIZE_T Length );
Bonjour les inversions source et destination, alors attention lors de l'écriture du code !
Bon, je mets ça en place dans mon code (System.Move(aPixels, SrcBmp.ScanLine[SrcBmp.Height -1], IMAGE_HEIGHT*IMAGE_WIDTH*SizeOf(TRGBQuad));, voir là pour les détails), évidemment je me prends un AV (sinon je ne serais pas là), je continue à fouiller, voilà que je trouve une discussion sympatoche :
J'essaye avec mon code, ça ne compile pas à cause des chapeaux ("illegal qualifier" sur la source)...Citation:
The code work well under Windows but under Linux I get an exception on Move instruction.Code:
1
2
3
4
5
6
7
8
9
10
11 var gbuff: Pointer; ... GetMem(gbuff, s); {$ifdef Win32} CopyMemory(gbuff, FImage.Bits, s); {$endif} {$ifdef Linux} Move(FImage.Bits, gbuff, s); {$endif}
[réponse :]
Move procedure from RTL takes dereferenced pointers as arguments, so you'll need to use it this way:
Move(FImage.Bits^, gbuff^, s);
Je les enlève tous les deux, ça compile mais AV à l'exécution.
Je ne remets que le second, ça compile mais AV à l'exécution.
Et cerise sur le gâteau, contrairement à ce que disait le posteur de cette discussion ("The code work well under Window"), j'ai testé et gagné les AV's sous.. Windows !
Voilà... Même pas j'essaye sous Linux.
Si quelqu'un a une idée, il est le bienvenu.
CopyMemory travaille avec des pointeurs, Move avec des instances
il ne faut pas lui donner l'adresse de la ScanLine mais la données pointéeCode:System.Move(aPixels, SrcBmp.ScanLine[SrcBmp.Height -1]^, IMAGE_HEIGHT*IMAGE_WIDTH*SizeOf(TRGBQuad))
(en supposant que aPixels est un tableau statique)
ceci dit, ça ne fonctionnera que si le bitmap est en 32bits
après j'ai envie de dire, quel est l'intérêt ?
si tu veux utiliser le ScanLine d'un Bitmap tu peux le faire directement
étrangement sous Lazarys c'est ScanLine[0] qui pointe sur le début du bitmap et non ScanLine[H - 1] comme sous Delphi (Bitmap avec la tête en bas)Code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33 const W = 256; H = 256; type TPixels = array[0..H - 1, 0..W - 1, 0..3] of Byte; PPixels = ^TPixels; var Bmp : TBitmap; Pixels: PPixels; x, y : Integer; begin Bmp := TBitmap.Create; Bmp.pixelFormat := pf32Bit; Bmp.SetSize(W, H); Bmp.BeginUpdate; Pixels := Bmp.ScanLine[0]; // manifestement sous Lazarus il faut prendre ScanLine[0] for x := 0 to W - 1 do begin for y := 0 to H - 1 do begin Pixels^[y, x, 0] := x + y; // blue Pixels^[y, x, 1] := x - y; // green Pixels^[y, x, 2] := x + x; // red Pixels^[y, x, 3] := 255; // alpha end; end; Bmp.EndUpdate(); Image1.Picture.Graphic := Bmp; Bmp.Free; end;
ce qui se confirme dans le code
Code:
1
2
3
4
5
6
7
8 function TRawImage.GetLineStart(ALine: Cardinal): PByte; begin Result := Data; if Result = nil then Exit; if ALine = 0 then Exit; Inc(Result, ALine * Description.BytesPerLine); end;
Coucou me revoilou !
C'est bien noté, surtout la seconde ligne !
Merci pour le bout de code, qui fonctionne tip-top, mais ne répond pas à ma problématique :
J'en vois deux :
- un général, qui est de répondre à la question du fil, "par quoi remplacer le CopyMemory de Windows ?" sous Lazarus où cette API n'a pas été traduite ; je croyais avoir trouvé, mais...
- un plus particulier et adapté au problème sur lequel je rame en ce moment, et pour lequel j'ai préparé, grâce au code de Cirec d'hier soir, un petit montage :
Pièce jointe 210694
À gauche l'image générée par son code directement sur la fiche, on voit en haut un bouton "btn_Go" qui va CopyMemoryer grâce au coup de main d'Andnotor de ce matin vers un TBitmap pour affichage dans un TImage, masqué par l'affichage du programme sous XP (bordure bleue) en cours d'avancement.
Je voudrais faire la même chose sous Linux et le premier écueil c'est que SetDIBitsToDevice n'y existe pas, pour voir avec mes yeux à quoi ressemblent les données calculées et pour vérifier que la recopie (même en mettant deux secondes) est bonne dans le TImage (ben vi, si je ne peux pas voir la source, je ne peux pas savoir si ce que je vois dans le TImage après la copie est juste).
Alors on va dire que j'y suis presque, puisque ce qu'on voit sur la partie droite de cette copie d'écran, c'est ce qui est généré par Lazarus dans XP (partie gauche = hier sous D7/w2k). Quand ça tournera correctement dans XP, je testerai sous Linux.
J'y suis presque, dis-je, car l'image devrait faire 640x480 (ne pas tenir compte de l'image "Cirec" qui a été faite en mode 480x480) : dans ce qu'on voit, les couleurs sont bonnes et en place, la grande question c'est : mais où est passé le reste ? Et comment faire pour tout faire afficher ?
Comment j'ai fait pour en arriver là ? Un bout du code de Cirec adapté par Andnotor :
Je ne sais plus trop quoi tenter... :(Code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20 with SrcBmp do begin SrcBmp.PixelFormat:=pf32bit; SrcBmp.Width := IMAGE_WIDTH; SrcBmp.Height:= IMAGE_HEIGHT; end; SrcBmp.BeginUpdate(); for y := 0 to IMAGE_HEIGHT -1 do System.Move(aPixels[y], SrcBmp.ScanLine[y]^, IMAGE_WIDTH*SizeOf(TRGBQuad)); SrcBmp.EndUpdate(); {//D7-w2k for y := 0 to IMAGE_HEIGHT -1 do CopyMemory(SrcBmp.ScanLine[y], @aPixels[y], IMAGE_WIDTH*SizeOf(TRGBQuad)); } Image123.Picture.Graphic := SrcBmp; finally SrcBmp.Free; end;
Ce soir, pour lâcher un peu le code, j'ai lu la traduction (trouvée par gogol mais disponible quelque part sur dvlp) faite par nono40 de l'excellent article d'efg sur cette mystérieuse Scanline...
Bien m'en a pris car à un moment je suis tombé sur un passage qui m'a obligé à relancer l'ide, à transformer l'horreur ci-dessus en tout simplement
et...Code:
1
2
3 SrcBmp.BeginUpdate(); Move(Pixels^[0], SrcBmp.ScanLine[0]^, IMAGE_WIDTH*IMAGE_HEIGHT*(SizeOf(Byte)*4)); SrcBmp.EndUpdate();
et......
et BINGO !
Mon TImage 640x480 s'est toute remplie de losanges bicolores en 1 toute petite milliseconde, et ce, aussi bien sous Linux que sous Windows (10 millisecondes pour les fenêtres -- le fait à la machine virtuelle ?) !
Les images demain, il faut encore que j'adapte çà au vieux couple D7/w2k, le seul qui me permette de voir le dessin sur la form et dans le TImage, car, mine de rien, le rendu des couleurs n'est pas le même entre XP et Debian :koi:
À chaque jour suffit sa peine, et ce soir le monsieur l'est bien content ! :zoubi:
On est demain, les images sont arrivées, les problèmes ont trouvé des solutions, tout est expliqué ici en suivant ce lien.
Bonne journée, dommage que je ne puisse pas cliquer sur :resolu:
Grand merci ! :ccool:
Même si je ne suis pas à l'initiative de cette discussion, si jamais un jour quelqu'un cherche...
J'en profite pour apporter une minuscule clarification à ça :
J'ai écrit SrcBmp et avec un nom pareil on pourrait croire que c'est la source des données, alors que c'est la destination du move ! (Bon ça sera la source pour le remplissage du TImage, ceci explique cela :D)