IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

Delphi Discussion :

chargement d'image à partir d'un stream


Sujet :

Delphi

  1. #1
    Membre actif
    Avatar de adaneels
    Homme Profil pro
    Chef de projet MOA
    Inscrit en
    Août 2006
    Messages
    236
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 45
    Localisation : France

    Informations professionnelles :
    Activité : Chef de projet MOA

    Informations forums :
    Inscription : Août 2006
    Messages : 236
    Points : 210
    Points
    210
    Par défaut chargement d'image à partir d'un stream
    Bonsoir,

    Je rencontre un problème lorsque je cherche à charger un TJpegImage à partir d'un TStream.

    exemple de code qui ne fonctionne pas :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    procedure TForm1.Button1Click(Sender: TObject);
    var
      HandleDLL: THandle;
      getJpeg : function(NomImg : ShortString) : TJpegImage; stdcall;
      jpg : TJpegImage;
    begin
      getJpeg:= LierFonction(HandleDLL, 'getJpg');
      if assigned(getJpeg) then begin
        jpg:= getJpeg('Clouds');
        Image1.Picture.Assign(jpg);
      end;
    end;
    Lors du "Image1.Picture.Assign(jpg);"
    Contexte du code : getJpeg est une fonction issue de ma dll. La dll prends le TJpegImage depuis un TCustomMemoryStream. Cela donne le même résultat si je charge directement depuis un TStream dans mon application.
    y'a pas de try ou quoi que ce soit parce que je l'ai enlevé pour faire moins de lecture

    exemple de code qui fonctionne :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    procedure TForm1.Button1Click(Sender: TObject);
    var
      HandleDLL: THandle;
      getJpeg : function(NomImg : ShortString) : TJpegImage; stdcall;
      jpg, jpg2 : TJpegImage;
    begin
      getJpeg:= LierFonction(HandleDLL, 'getJpg');
      if assigned(getJpeg) then begin
        jpg:= getJpeg('Clouds');
        jpg.SaveToFile('truc.jpg');
     
        jpg2:= TJpegImage.Create;
        jpg2.LoadFromFile('truc.jpg');
        Image1.Picture.Assign(jpg2);
      end;
    end;
    On peut donc conclure que l'objet TJpegImage récupéré depuis ma dll est bon. Le fichier 'truc.jpg' résultant est bien une belle image jpg sur le disque et j'ai bien le jpeg qui s'affiche dans Image1.

    C'est avec l'instance de jpg apparemment car même en faisant ça - même code qu'au-dessus mais avec le même TJPEGImage au lieu d'une nouvelle instance. -
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
      [...]if assigned....
        jpg:= getJpeg('Clouds');
        jpg.SaveToFile('truc.jpg');
     
        jpg.CleanUpInstance;
        jpg.LoadFromFile('truc.jpg');
        Image1.Picture.Assign(jpg);
      end;[...]
    L'erreur revient. Mais pourquoi donc ? Alors là...

    J'aimerai tout de même éviter de passer par l'extraction du fichier tout de même, c'est pas top

    Y'a-t-il des amateurs, des connaisseurs ou des idées dans la salle ?

  2. #2
    Membre actif
    Avatar de adaneels
    Homme Profil pro
    Chef de projet MOA
    Inscrit en
    Août 2006
    Messages
    236
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 45
    Localisation : France

    Informations professionnelles :
    Activité : Chef de projet MOA

    Informations forums :
    Inscription : Août 2006
    Messages : 236
    Points : 210
    Points
    210
    Par défaut
    un autre exemple avec l'erreur que je trouve très bizarre, en remplaçant ce qu'il y a dans le "if ... then" par ceci :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
      jpg2:= getJpeg('Clouds');
     
      jpg:= TJpegImage.Create;
      jpg.Assign(jpg2);
    J'obtiens l'erreur (au moment du Assign) : Classe d'exception EConvertError avec message 'Impossible d'affecter TJPEGImage à TJPEGImage'.


  3. #3
    Membre confirmé
    Avatar de Philippe Gormand
    Inscrit en
    Mars 2002
    Messages
    330
    Détails du profil
    Informations forums :
    Inscription : Mars 2002
    Messages : 330
    Points : 647
    Points
    647
    Par défaut
    Bonjour.

    Je pense que le problème viens d'une tentative d'assignation d'un objet créé à une déclaration d'objet (qui n'a pas été créer).

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    jpg2:= getJpeg('Clouds');
      
      jpg:= TJpegImage.Create;
    // Tentative de faire une copie intégrale de jpg2 dans jpg.
      jpg.Assign(jpg2);
    
    // pour pouvoir assigner jpg2 à jpg, il faut que jpg ai été créer. Qu'il existe en tant tant qu'objet.
    [...]if assigned....
        // jpg a t-il bien été créer ?
        jpg:= getJpeg('Clouds');
        jpg.SaveToFile('truc.jpg');
     
        jpg.CleanUpInstance;
        jpg.LoadFromFile('truc.jpg');
        Image1.Picture.Assign(jpg);
      end;[...]
    C'est dans cette voie que je chercherais.

    A+

  4. #4
    Membre actif
    Avatar de adaneels
    Homme Profil pro
    Chef de projet MOA
    Inscrit en
    Août 2006
    Messages
    236
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 45
    Localisation : France

    Informations professionnelles :
    Activité : Chef de projet MOA

    Informations forums :
    Inscription : Août 2006
    Messages : 236
    Points : 210
    Points
    210
    Par défaut
    J'ai reproduit ce que je fais sans passer par une dll, cela fonctionne impec.
    Voici ce que ça donne dans l'unité principale :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    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
    unit Unit1;
    
    interface
    
    uses
      Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
      Dialogs, StdCtrls, ExtCtrls,
      jpeg;
    
    type
      TForm1 = class(TForm)
        Image1: TImage;
        Panel1: TPanel;
        Button1: TButton;
        procedure Button1Click(Sender: TObject);
      private
        { Déclarations privées }
      public
        { Déclarations publiques }
      end;
    
    var
      Form1: TForm1;
    
    implementation
    
    {$R *.dfm}
    {$R imgs.RES}
    
    procedure TForm1.Button1Click(Sender: TObject);
    var
      jpg : TJPEGImage;
      Stream : TCustomMemoryStream;
    begin
      try
        Stream := TResourceStream.Create(hInstance, 'Clouds', RT_RCDATA);
        jpg:= TJPEGImage.Create;
        jpg.LoadFromStream(Stream);
        Image1.Picture.Assign(jpg);
      finally
        Stream.Free;
      end;
    end;
    
    end.
    Note : Le code qui est en vert est contenu dans la dll dans mon cas, puis elle renvoit le TJPEGImage résultant, que je récupère comme indiqué dans le premier message.

    Concernant la tentative de faire une copie intégrale de jpg2 dans jpg, j'ai déjà tenté comme indiqué dans mon second message mais ça lève une erreur "Impossible d'affecter un TJPEGImage à un TJPEGImage".

    Je pense aussi que cela doit provenir d'un Create mal fait.
    Pourtant le create est bien fait dans la dll et le jpg de la dll est tout à fait correct (il a un width, height, empty=false et je peux faire un saveToFile qui se passe bien).
    le TJPEGImage que récupère l'application est tout aussi bon : il a un width, height, etc., empty=false et je peux faire un saveToFile qui se passe bien.
    Mais suprise, je ne peux pas faire de Free dessus (cela fait une violation d'accès)!


    Résumé : Le code passe bien si est contenu dans une seule application donc cela provient du code "jpg:= getJpeg('Clouds');" ou du fait que la dll renvoie un TJPEGImage.
    Le jpg de la dll est bien créé et est fait comme dans le code exemple dans ce message.
    Le jpg récupéré supporte un SaveToFile, contient les mêmes propriétés qu'un TJPEGImage normal (vu au débug) mais impossible de faire un Free dessus (violation d'accès) ou d'affecter à un autre objet via Assign ou := (EConvertError : impossible d'affecter un TJPEGImage à un ...").

    J'avoue que je n'y comprends rien. Comme si l'action Create faite dans la dll n'avait plus d'effet en dehors de la dll.

  5. #5
    Membre confirmé
    Avatar de Philippe Gormand
    Inscrit en
    Mars 2002
    Messages
    330
    Détails du profil
    Informations forums :
    Inscription : Mars 2002
    Messages : 330
    Points : 647
    Points
    647
    Par défaut
    Je ne suis pas sur d'avoir tout compris, mais...

    Je pense aussi que cela doit provenir d'un Create mal fait.
    Pourtant le create est bien fait dans la dll et le jpg de la dll est tout à fait correct (il a un width, height, empty=false et je peux faire un saveToFile qui se passe bien).
    le TJPEGImage que récupère l'application est tout aussi bon : il a un width, height, etc., empty=false et je peux faire un saveToFile qui se passe bien.
    Mais suprise, je ne peux pas faire de Free dessus (cela fait une violation d'accès)!
    1- On ne peut pas exporter une variable d'une DLL.
    2- Si l'objet a été créé dans la mémoire allouée à la DLL (donc le code Create est dans la DLL) on ne peut évidament pas appeler Free sur l'objet.

    3- Il faut donc un objet local temporaire dans lequel on peut charger l'objet jpeg depuis la DLL.

    4- La methode SaveToFile fonctionne car il est fait référence à celle qui pointe sur l'objet jpeg contenu dans la DLL. Mais j'avoue ne pas être capable de mieux expliquer.

    A+

  6. #6
    Membre actif
    Avatar de adaneels
    Homme Profil pro
    Chef de projet MOA
    Inscrit en
    Août 2006
    Messages
    236
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 45
    Localisation : France

    Informations professionnelles :
    Activité : Chef de projet MOA

    Informations forums :
    Inscription : Août 2006
    Messages : 236
    Points : 210
    Points
    210
    Par défaut
    Citation Envoyé par Philippe Gormand
    Je ne suis pas sur d'avoir tout compris, mais...
    A force d'avoir testé plusieurs façon, c'est très certainement moi qui explique mal.

    Citation Envoyé par Philippe Gormand
    1- On ne peut pas exporter une variable d'une DLL.
    Justement, je me demandais - c'est ma première dll -. Merci, c'est bon à savoir.

    Citation Envoyé par Philippe Gormand
    2- Si l'objet a été créé dans la mémoire allouée à la DLL (donc le code Create est dans la DLL) on ne peut évidament pas appeler Free sur l'objet.
    Ca me semble évident maintenant que tu le dis. J'ai pourtant appris ça.... Réfléchir avant de coder... Prendre 2 sec. pour réfléchir.

    Citation Envoyé par Philippe Gormand
    3- Il faut donc un objet local temporaire dans lequel on peut charger l'objet jpeg depuis la DLL.
    J'ai créé un tel objet dans mon appli, avec référence passée en paramètre à la dll. Evidemment, ça passe mieux comme ça. Roulez jeunesse

    Citation Envoyé par Philippe Gormand
    4- La methode SaveToFile fonctionne car il est fait référence à celle qui pointe sur l'objet jpeg contenu dans la DLL. Mais j'avoue ne pas être capable de mieux expliquer.
    Je crois comprendre mais ça reste un peu flou pour moi. Tant mieux si ça passe comme ça du coup, mais je n'utilisais de toute façon pas la bonne façon de faire.

    Merci pour tes réponses et de m'avoir dans le droit chemin


    Si une personne passe par là et rentontre le même problème, à savoir comment retourner une variable dans une dll ?
    Réponse : on ne peut pas, passer la variable à modifier par référence comme suit :

    exemple dans la dll - variable que l'on veut récupérer = paramètre passé en référence - :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    function getJpg(var jpg : TJPEGImage) : Boolean; stdcall;
    begin
      Result:= False;
      // charger l'image dans variable jpg
      if tout_s_est_bien_passe then
        Result:= True;
    end;
    exemple dans le code de l'application qui appelle la dll :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    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
    procedure TForm1.Button1Click(Sender: TObject);
    var
      HandleDLL: THandle;
      getJpeg : function(var jpg : TJPEGImage) : Boolean; stdcall;
      jpg : TJpegImage;
    begin
      try
        // recup handle de la dll
        HandleDLL:= 0;
        HandleDLL:= LoadLibrary(pAnsiChar(nom_du_fichier_dll_avec_extension));
        if HandleDLL = 0 then // ca s'est mal passé
         exit; 
        // chargement de la fonction pour utilisation locale
        getJpeg:= GetProcAddress(HandleDLL, pAnsiChar('getJpg'));
     
        // initialisation objet ou on va récupérer le TJPEGImage voulu
        jpg:= TJPEGImage.Create;
        if assigned(getJpeg) then begin // si fonction bien affectée
          if getJpeg('Clouds', jpg) then // si TJPEGImage bien chargé dans variable
          Image1.Picture.Assign(jpg);  // mettre l'image dans mon TImage de l'application
        end;
      finally
        FreeLibrary(HandleDLL);
        FreeAndNil(jpg);
      end;
    end;
    Merci encore Philippe Gormand.

+ Répondre à la discussion
Cette discussion est résolue.

Discussions similaires

  1. Chargement d'image à partir du XML
    Par atha2 dans le forum Android
    Réponses: 4
    Dernier message: 10/04/2013, 16h58
  2. Chargement d'images à partir d'un dossier
    Par Trebor_ dans le forum Général JavaScript
    Réponses: 3
    Dernier message: 26/10/2012, 13h15
  3. [MySQL] erreur de chargement des images partir de ma base
    Par hela.sfar dans le forum PHP & Base de données
    Réponses: 5
    Dernier message: 06/04/2012, 19h57
  4. chargement d'images à partir d'un jar
    Par kimausoleil dans le forum Général Java
    Réponses: 2
    Dernier message: 03/03/2010, 17h18
  5. Problème de chargement d'images à partir de JARs
    Par MustOne dans le forum Entrée/Sortie
    Réponses: 3
    Dernier message: 05/05/2009, 11h54

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo