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

Langage Delphi Discussion :

JPEG et champ BLOB


Sujet :

Langage Delphi

  1. #1
    Membre régulier
    Inscrit en
    Avril 2002
    Messages
    187
    Détails du profil
    Informations forums :
    Inscription : Avril 2002
    Messages : 187
    Points : 90
    Points
    90
    Par défaut JPEG et champ BLOB
    Ola,

    Après avoir passé la journée à éplucher tous les forums (anglais et français), après avoir essayé toutes les solutions proposées, aucune de celles-ci n'arrivent à solutionner le stockage d'un jpeg dans un champ blob ains que sa récupération et son affichage dans un form.

    Si vous avez une solution, je suis preneur. Merci de ne pas m'envoyer sur un lien qui prétend solutionner le problème, je les ai tous fait (y compris ceux de developpez), aucun ne tient la route.

    A savourer, en ayant pris soin de prendre un whisky bien tassé pour ne pas exploser, les prétendues solutions du genre :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    Try
      Voici ma solution : blabla...
    Except
      Afficher : heu... ben non, ça ne fonctionne pas !
    End
    Authentique !



    JJE

  2. #2
    Modérateur
    Avatar de Rayek
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Mars 2005
    Messages
    5 235
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 50
    Localisation : France, Haute Savoie (Rhône Alpes)

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Mars 2005
    Messages : 5 235
    Points : 8 504
    Points
    8 504
    Par défaut
    Certifié et fonctionnel

    J'ai écris cette QR à l'époque où j'ai eu besoin de mettre des documents de tout type dans une base de données et ca fonctionne très bien

  3. #3
    Expert éminent sénior
    Avatar de ShaiLeTroll
    Homme Profil pro
    Développeur C++\Delphi
    Inscrit en
    Juillet 2006
    Messages
    13 563
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 43
    Localisation : France, Seine Saint Denis (Île de France)

    Informations professionnelles :
    Activité : Développeur C++\Delphi
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Juillet 2006
    Messages : 13 563
    Points : 25 165
    Points
    25 165
    Par défaut
    Selon la Version de Delphi
    Avant 200x - il faut convertir le Blob via l'objet TJPEGImage pour l'afficher dans un TImage
    Après 200x - le TComposant TImage gère nativement le JPEG, on peut espérer que le TDBImage aussi ! A vérifier, l'ancienne méthode fonctionne aussi !

    200x = 2007 ou 2009, je ne sais pas exactement

    C'est un sujet largement débattu, et aussi qui a été taggé , c'est que cela fonctionne

    As-tu testé dans un projet minimal, sans rien d'autres ?
    Juste la connexion DB, Datasource, Query, et TIMage ? sans rien qui parasite ?

  4. #4
    Membre expérimenté
    Avatar de ouiouioui
    Homme Profil pro
    Administrateur systèmes et réseaux
    Inscrit en
    Août 2006
    Messages
    984
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 42
    Localisation : France, Rhône (Rhône Alpes)

    Informations professionnelles :
    Activité : Administrateur systèmes et réseaux
    Secteur : High Tech - Multimédia et Internet

    Informations forums :
    Inscription : Août 2006
    Messages : 984
    Points : 1 419
    Points
    1 419
    Par défaut
    moi je les enregistre comme sa:
    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
    Var
      MsImg: TMemoryStream;
    Begin
          With IBQuery Do
          Begin
            Close;
            SQL.Text                        :=
              'INSERT INTO MY_COMPANY (IMG) VALUES (:Img)';
     
            // logo
            MsImg := TMemoryStream.Create;
            try
                //img is tbitmap
                If Assigned(IMG) Then
                  IMG.SaveToStream(MsImg);
              MsImg.Seek(0, 0);
              If MsImg.Size > 0 Then
                ParamByName('Img').LoadFromStream(MsImg, FtBlob);
            finally
              msimg.Free;
            end;
     
            ExecSql;
    la lecture en sens inverse:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
                If FieldValues['IMG'] <> NULL Then
                Begin
                  (FieldByName('IMG') As TBlobField).SaveToStream(MsImg);
                  Msimg.Seek(0, 0);
                  img.LoadFromStream(MsImg);
                End;

  5. #5
    Membre régulier
    Inscrit en
    Avril 2002
    Messages
    187
    Détails du profil
    Informations forums :
    Inscription : Avril 2002
    Messages : 187
    Points : 90
    Points
    90
    Par défaut
    Citation Envoyé par Rayek Voir le message
    Certifié et fonctionnel

    J'ai écris cette QR à l'époque où j'ai eu besoin de mettre des documents de tout type dans une base de données et ca fonctionne très bien
    Merci à tous pour vos réponses. Je vais tester vos suggestions.

    Déjà une petite réponse pour Rayek : ta solution fonctionne pour des fichiers bmp mais pas pour des jpg. L'image bmp est bien sauvée dans le champs BLOB, mais elle refuse toutefois de s'afficher dans un TDBImage lorsqu'on se positionne sur l'enregistrement.



    JJE

  6. #6
    Expert éminent sénior
    Avatar de ShaiLeTroll
    Homme Profil pro
    Développeur C++\Delphi
    Inscrit en
    Juillet 2006
    Messages
    13 563
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 43
    Localisation : France, Seine Saint Denis (Île de France)

    Informations professionnelles :
    Activité : Développeur C++\Delphi
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Juillet 2006
    Messages : 13 563
    Points : 25 165
    Points
    25 165
    Par défaut
    Version de Delphi ?
    Pour le BMP, perso, cela fonctionne très bien, la preuve, le Projet de démo FishFactory livré depuis au moins depuis Delphi 3 en exemple !

    D7 : J'insiste sur la Conversion avec TJPEGImage de l'unité jpeg.pas + TImage
    D2009 : TDBImage théoriquement directement fonctionnel

  7. #7
    Membre régulier
    Inscrit en
    Avril 2002
    Messages
    187
    Détails du profil
    Informations forums :
    Inscription : Avril 2002
    Messages : 187
    Points : 90
    Points
    90
    Par défaut
    Hi ouiouioui,

    Idem, ta solution fonctionne pour des fichiers BMP mais pas pour des JPEG. Voici le message d'erreur :

    Exception EInvalidGraphic avec le message 'Image bitmap incorrecte'
    Voici mon code (le programme plante sur la commande LoadFromStream) :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
              ...
              Image:=TMemoryStream.Create;
              JPEG:=TJPEGImage.Create;
              JPEG.LoadFromFile(FichierJPEG);
              JPEG.SaveToStream(Image);
              if Image.Size>0 then begin
                (FieldByName('Logo') As TBlobField).LoadFromStream(Image);
              end;
              ...


    JJE

  8. #8
    Membre régulier
    Inscrit en
    Avril 2002
    Messages
    187
    Détails du profil
    Informations forums :
    Inscription : Avril 2002
    Messages : 187
    Points : 90
    Points
    90
    Par défaut
    Citation Envoyé par ShaiLeTroll Voir le message
    Version de Delphi ?
    Pour le BMP, perso, cela fonctionne très bien, la preuve, le Projet de démo FishFactory livré depuis au moins depuis Delphi 3 en exemple !

    D7 : J'insiste sur la Conversion avec TJPEGImage de l'unité jpeg.pas + TImage
    D2009 : TDBImage théoriquement directement fonctionnel
    Hi ShaiLeTroll,

    Delphi XE.

    Effectivement, tout à l'air de fonctionner avec des BMP. Encore que, le TDBImage ne m'affiche rien lorsque je me repositionne sur l'enregistrement. Mais là, il faut que je regarde de plus près les propriétés du TDBImage. Je merde peut-être quelque part à ce niveau.



    JJE

  9. #9
    Membre régulier
    Inscrit en
    Avril 2002
    Messages
    187
    Détails du profil
    Informations forums :
    Inscription : Avril 2002
    Messages : 187
    Points : 90
    Points
    90
    Par défaut
    Hi,

    J'ai trouvé une solution qui est vraiment simplicime :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    ...
    ImageJPG:=TJPEGImage.Create;
    ImageBMP:=TBitMap.Create;
     
    ImageJPG.LoadFromFile(FichierJPG);
    ImageBMP.Assign(ImageJPG);
     
    FieldByName('Logo').Assign(ImageBMP);
    ...
    Bon maintenant, reste à trouver pourquoi ce foutu TDBImage ne veut pas m'afficher mon logo !
    Je vais tester dans un EXE séparé selon les conseils de ShaiLeTroll.



    JJE

  10. #10
    Membre régulier
    Inscrit en
    Avril 2002
    Messages
    187
    Détails du profil
    Informations forums :
    Inscription : Avril 2002
    Messages : 187
    Points : 90
    Points
    90
    Par défaut
    Ça se précise :

    • Avec un form, un TSimpleDataSet, un TDataSource -> le TDBImage fonctionne
    • Avec un form, un TSQLConnection, TSQLDataSet, un TDataSetProvider, un TClientDataSet, un TDataSource -> le TDBImage fonctionne
    • En environnement multi-niveaux avec serveur DataSnap, un TSQLConnection, TSQLDataSet, un TDataSetProvider, un TClientDataSet, un TDataSource -> le TDBImage ne fonctionne plus




    JJE

  11. #11
    Membre régulier
    Inscrit en
    Avril 2002
    Messages
    187
    Détails du profil
    Informations forums :
    Inscription : Avril 2002
    Messages : 187
    Points : 90
    Points
    90
    Par défaut
    Problème résolu.

    Pour ceux que cela intéresse :

    1. Si on utilise des champs BLOB dans un environnement multi-niveaux, il faut déterminer en premier lieu la taille maximum des données que l'on stockera dans les champs BLOB (dans mon cas 64KB).
    2. A partir de là, au niveau du serveur DataSnap, dans l'unité ServerMethodUnit, au niveau du composant TSQLConnection, dans les paramètres (propriété Params), indiquer la valeur BlobSize=65535.
    3. Toujours au niveau du serveur DataSnap, dans l'unité ServerContainerUnit, au niveau du composant TDSTCPServerTransport, attribuer la valeur 64 à la propriété BufferKBSize.
    4. Dans la partie cliente, TSQLConnection, propriété Params, le BufferKBSize doit avoir la valeur 64.
    5. Toujours dans la partie cliente, le TSQLDataSet connecté au TSQLConnection doit avoir la propriété MaxBlobSize fixée à 65535.
    6. Vous ajoutez un peu de poudre de Perlimpinpin, vous dites trois fois Hocus Pocus et, avec un peu de chance, le TDBImage fonctionne.




    JJE

  12. #12
    Membre éprouvé
    Avatar de Montor
    Homme Profil pro
    Autre
    Inscrit en
    Avril 2008
    Messages
    879
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Autre

    Informations professionnelles :
    Activité : Autre

    Informations forums :
    Inscription : Avril 2008
    Messages : 879
    Points : 963
    Points
    963
    Par défaut
    On va change un peu la démarche
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    uses jpeg;
    Image:=TImage.Create(nil);
    Image.Picture.LoadFromFile('rrr');
    CreateBlobStream(FieldByName('Logo') ,bmWrite).WriteComponent(Image)
    à mediter

  13. #13
    Membre régulier
    Inscrit en
    Avril 2002
    Messages
    187
    Détails du profil
    Informations forums :
    Inscription : Avril 2002
    Messages : 187
    Points : 90
    Points
    90
    Par défaut
    Citation Envoyé par Montor Voir le message
    On va change un peu la démarche
    uses jpeg;
    Image:=TImage.Create(nil);
    Image.Picture.LoadFromFile('rrr');
    CreateBlobStream(FieldByName('Logo') ,bmWrite).WriteComponent(Image)

    à mediter
    Hi Montor,

    Chez moi cela ne fonctionne pas. Ça compile et s'exécute sans faute, mais le champ Logo n'est pas mis à jour. Il y a peut-être un souci dans mon code :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    procedure TForm2.Button1Click(Sender: TObject);
    var
      Image: TImage;
    begin
      Image:=TImage.Create(nil);
      Image.Picture.LoadFromFile('MonLogo.jpg');
      with SimpleDataSet1 do begin
        Edit;
        DataSet.CreateBlobStream(DataSet.FieldByName('Logo') As TBlobField,bmWrite).WriteComponent(Image);
        Post;
      end;
    end;


    JJE

  14. #14
    Expert éminent sénior
    Avatar de ShaiLeTroll
    Homme Profil pro
    Développeur C++\Delphi
    Inscrit en
    Juillet 2006
    Messages
    13 563
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 43
    Localisation : France, Seine Saint Denis (Île de France)

    Informations professionnelles :
    Activité : Développeur C++\Delphi
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Juillet 2006
    Messages : 13 563
    Points : 25 165
    Points
    25 165
    Par défaut
    Petite remarque, je me demande pourquoi personne n'est capable de recopier correctement la FAQ et enlève le Seek comme si c'était la pour décorer !
    OuiOuiOui avait pourtant bien mis le Seek ! il fallait juste pomper !

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
              Image:=TMemoryStream.Create;
              JPEG:=TJPEGImage.Create;
              JPEG.LoadFromFile(FichierJPEG);          
              JPEG.SaveToStream(Image);
              Image.Seek(0, soFromBeginning); //  il faut rembobinné le Stream (comme une  cassette, une fois écrite, faut revenir à zéro)
              if Image.Size>0 then begin
                (FieldByName('Logo') As TBlobField).LoadFromStream(Image);
              end;
    Pour WriteComponent, cela écrit le TImage sous forme de DFM ?
    Donc encodé en Base64 !
    Il n'y a rien à méditer, il faut juste connaitre la Gestion des Flux Delphi !

    Donc pour le relire, il faut utiliser ReadComponent !

    Montor, ne me dit pas que cela fonctionne avec tu TDBImage pour la relecture sans passer par ReadComponent !
    Il n'aurait pas osé faire une gestion du Assign d'un TImage vers un TDBImage !


    Pour le Assign, c'est pas comme si je me répétais au sujet de TInterfacedPersistent et IStreamPersist
    BCB6 Probleme pour afficher une image dans un DBGrid

    Pour la limite 64K, il faut parfois aussi modifier la configuration du SGBD, en MySQL par exemple, il faut penser à modifier la taille Maximale d'une requête !
    Il faut aussi penser qu'il existe BLOB, MEDIUM, LONGBLOB ... 64K, 16Mo, 4Go
    Normalement le MaxBufferSize est à zéro, la limite est fournie par le configuration ODBC ou dans dbxdrivers.ini \ dbxconnections.ini

    En même temps, en environnement multi-niveaux comme DataSnap envoyé des Images sérializés en Midas (binaire ou XML ???) c'est franchement pas la meilleure idée !
    Mieux vaut stocker (ou générer à la volée) une URL de l'image et avoir un serveur de fichier accessible en HTTP !
    L'image n'étant affichée et récupérée que si cela est utile (je triche perso, j'utilise directement un WebBrowser\ShellImageViewer au lieu d'un TDBImage surtout qu'en D7, le tiff par exemple n'était pas géré et forcément, j'avais du tif\tiff)

    tu aurais du précisé dès le début que tu utilsais DataSnap, c'est forcément plus limitatif, j'avais eu le problème similaire avec des WebServices qui limitait la réponse SOAP, dès qu'il y a du multi-niveaux, cela requièrent des limitations réseaux et donc de grattage de cerveau !

    Cela mériterait une petite FAQ !
    Ce qui est compliqué c'est que cela dépend du SGBD et du Driver, perso, Sybase et MySQL sont par défaut à -1 pour DBExpress !
    Oracle ou ACCESS c'est 1Mo Max par défaut

  15. #15
    Membre régulier
    Inscrit en
    Avril 2002
    Messages
    187
    Détails du profil
    Informations forums :
    Inscription : Avril 2002
    Messages : 187
    Points : 90
    Points
    90
    Par défaut
    Oh ShaiLeTroll, respire un peu ! Si on fréquente ce site, c'est pour apprendre aussi.
    De plus, même avec la commande Seek cela ne fonctionne pas. Message d'erreur à l'exécution sur la commande LoadFromStream :

    Le projet Project3.exe a déclenché la classe d'exception EInvalidGraphic avec le message 'Image bitmap incorrecte'.


    JJE

  16. #16
    Expert éminent sénior
    Avatar de ShaiLeTroll
    Homme Profil pro
    Développeur C++\Delphi
    Inscrit en
    Juillet 2006
    Messages
    13 563
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 43
    Localisation : France, Seine Saint Denis (Île de France)

    Informations professionnelles :
    Activité : Développeur C++\Delphi
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Juillet 2006
    Messages : 13 563
    Points : 25 165
    Points
    25 165
    Par défaut
    Je suis un Troll ! Ne l'oublie pas !

    N'oublie pas qu'avec TJPEGImage, il ne faut pas utiliser un TDBImage pour relire mais il faut repasser par des Stream, TJPEGImage puis TImage ...

    de plus 'Logo' doit être déclaré en TBlobField et pas en TGraphicField !
    Tout dépend de la DB derrière si cela gère le type IMAGE ou le type BLOB uniquement !

  17. #17
    Membre éprouvé
    Avatar de Montor
    Homme Profil pro
    Autre
    Inscrit en
    Avril 2008
    Messages
    879
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Autre

    Informations professionnelles :
    Activité : Autre

    Informations forums :
    Inscription : Avril 2008
    Messages : 879
    Points : 963
    Points
    963
    Par défaut
    Montor, ne me dit pas que cela fonctionne avec tu TDBImage pour la relecture sans passer par ReadComponent !
    Il n'aurait pas osé faire une gestion du Assign d'un TImage vers un TDBImage !
    je ne sais pas j'avais essayé avec simple TImage ...
    Voici un code fonctionne correctement

    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
     
    //Ecreture
    var
      S:string;
      img:TImage;
    begin
     if PromptForfilename(S,GraphicFilter(TGraphic)) then
     begin
       img := TImage.Create(nil);
       with Table1.CreateBlobStream(Table1.FieldByName('Picture'), bmWrite) do
       try
         img.Picture.LoadFromFile(S);
         Position:=0;
         WriteComponent(img);
         img.Picture.Graphic := nil;
       finally
         img.Free;
         Free;
       end;
      end;
    end;
     
    //Lecture
    var
      Stream : TStream;
       img:TImage;
    begin
      Image1.Picture.Graphic := nil;
     
       img := TImage.Create(nil);
       with Table1.CreateBlobStream(Table1.FieldByName('Picture'), bmRead) do
       try
         Position:=0;
         try
         ReadComponent(img);
         Image1.Picture.Assign(img.Picture);
         img.Picture.Graphic := nil;
         except
         end;
       finally
         img.Free;
         Free;
       end;
     
    end;

  18. #18
    Expert éminent sénior
    Avatar de ShaiLeTroll
    Homme Profil pro
    Développeur C++\Delphi
    Inscrit en
    Juillet 2006
    Messages
    13 563
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 43
    Localisation : France, Seine Saint Denis (Île de France)

    Informations professionnelles :
    Activité : Développeur C++\Delphi
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Juillet 2006
    Messages : 13 563
    Points : 25 165
    Points
    25 165
    Par défaut
    Ah tu me rassures Montor !
    Mais ce que tu stockes ce n'est plus une Image mais un TImage en format DFM qui doit être 4 fois plus volumineux qu'un BMP !

  19. #19
    Membre éprouvé
    Avatar de Montor
    Homme Profil pro
    Autre
    Inscrit en
    Avril 2008
    Messages
    879
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Autre

    Informations professionnelles :
    Activité : Autre

    Informations forums :
    Inscription : Avril 2008
    Messages : 879
    Points : 963
    Points
    963
    Par défaut
    Citation Envoyé par ShaiLeTroll Voir le message
    Ah tu me rassures Montor !
    Mais ce que tu stockes ce n'est plus une Image mais un TImage en format DFM qui doit être 4 fois plus volumineux qu'un BMP !
    Non le TImage est enregistré en format DFM binaire pas comme texte avec
    quelque dizaine d'octets de plus

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

Discussions similaires

  1. inserer un jpeg dans un champ blob
    Par colfire_dev dans le forum Bases de données
    Réponses: 14
    Dernier message: 01/11/2009, 07h32
  2. Réponses: 6
    Dernier message: 23/05/2006, 09h05
  3. [interbase] transferer un champ blob en par prog
    Par Harry dans le forum Bases de données
    Réponses: 4
    Dernier message: 26/02/2004, 10h39
  4. Update d'un champ BLOB
    Par ZeKlubb dans le forum Connexion aux bases de données
    Réponses: 4
    Dernier message: 17/01/2004, 16h04
  5. faire un insert pour un champ blob
    Par tripper.dim dans le forum InterBase
    Réponses: 10
    Dernier message: 02/05/2003, 16h56

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