Merci de continuer à réfléchir à mon problème !
J'ai installé la deuxième version de la fonction que tu as postée. Mais ça provoque une violation d'accès.
J'ai donc épuré le code, et je l'ai truffé de messages. Voilà ce que ça donne:
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 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49
| function GetPictureAddress(pic: TImage):integer; stdcall; export;
var
ms1: TMemoryStream;
Picture1 : TPicture ;
n: integer;
begin
showmessage('a1');
ms1 := TMemoryStream.Create ;
showmessage('a2');
pic.Picture.Graphic.SaveToStream(ms1);
showmessage('a3');
ms1.Position := 0 ;
showmessage('a4');
Picture1 := TPicture.Create ;
showmessage('a5');
Picture1.Bitmap := TBitmap.Create ;
showmessage('a6');
Picture1.Bitmap.PixelFormat := pic.Picture.Bitmap.PixelFormat ;
showmessage('a7');
Picture1.Graphic.LoadFromStream(ms1);
showmessage('a8');
ms1.Free ;
showmessage('a9 ' + pic.ClassName);
case Picture1.Bitmap.PixelFormat of
pf1bit:
showmessage('1 bits');
pf4bit:
showmessage('4 bits');
pf8bit:
showmessage('8 bits');
pf15bit:
showmessage('15 bits');
pf16bit:
showmessage('16 bits');
pf24bit:
showmessage('24 bits');
pf32bit:
showmessage('32 bits');
pfCustom:
showmessage('pfCustom');
pfDevice:
showmessage('pfDevice');
else
showmessage('? bits');
end;
n := Picture1.Bitmap.Height;
showmessage('a1 '+inttostr(n) + ' lignes');
result := integer(Picture1.Bitmap.Scanline[n-1]) ;
end; |
Le plantage a lieu après le message "A3", sur la ligne
pic.Picture.Graphic.SaveToStream(ms1);
Et ça s'explique parfaitement par l'argumentation de Paul Toth. On ne peut malheureusement pas utiliser les propriétés de TImage, sur un TImage passé en paramètre à une DLL. C'est fort dommage, mais c'est ainsi. J'avais fait de multiples essais, avant d'appeler ce forum à l'aide, et je me suis heurté à un mur. Et Paul l'explique parfaitement.
L'idée du Memory Stream est nouvelle, et séduisante. Cependant, la création du stream ne peut se faire que dans la DLL, à partir du TImage passé en paramètre. Et là, la propriété Picture du TImage ne marche plus. Dommage.
Et le voilà ramené à mon point de réflexion de mes deux posts précédents: j'interprète le TImage passé en paramètre comme un pointeur (ce que c'est, en réalité !) vers une zone en mémoire où se trouve la structure décrivant le TImage. Et là, je peux lire cette adresse et toutes les adresses suivantes, en déréférençant mon pointer de type pinteger et en l'incrémentant chaque fois. Je peux ainsi parcourir la structure (jusqu'où, en fait ?) et interpréter les différents éléments. J'en ai identifié un certain nombre, mais il me manque le pointeur sur le TPicture associé au TImage (celui référencé par le propriété Picture). Il est à quel offset ? Et à partir de là, je veux trouver le pointeur sur la TBitMap du TPicture (propriété BitMap de Image.Picture !). Et ainsi, j'aurai ce qu'il faut pour traiter les pixels.
Ce qu'il ne faut pas oublier, c'est que le veux traiter les pixels dans leur location mémoire d'origine, ce qui permettra de les remplacer. Travailler sur une copie revient à produire un "sens unique", une sorte de bitmap "read-only".
Donc, je pense que le but sera vraiment de trouver des informations sur la structure d'un TImage en mémoire, de sorte à en extraire le pointer nécessaire et de le suivre jusqu'à la bitmap. Là, au moins, je ne rentre pas en conflit avec les instances différentes entre programme princpal et DLL. Je sais bien que je resterai prisonnier d'une seule version de Delphi, mais dans mon contexte, cela ne me dérange absolument pas.
Partager