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 :

Affichage lent de TJPEGIMAGE


Sujet :

Langage Delphi

  1. #1
    Membre averti Avatar de zemeilleurofgreg
    Profil pro
    Inscrit en
    Mars 2006
    Messages
    515
    Détails du profil
    Informations personnelles :
    Âge : 48
    Localisation : Belgique

    Informations forums :
    Inscription : Mars 2006
    Messages : 515
    Points : 346
    Points
    346
    Par défaut Affichage lent de TJPEGIMAGE
    Bonjour à tous,

    le code ci-dessous fonctionne mais je trouve l'affichage lent lorsque le répertoire sélectionné contient beaucoup de photos.

    Auriez-vous quelque conseils pour gagner en performences ?

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    for i:=0 to Length(MyArray)-1 do //MyArray contient le chemin des fichiers images
        begin
            Application.ProcessMessages;
     
            MyJpg:=TJpegImage.Create;
            MyJpg.Performance:=jpBestSpeed;
            MyJpg.Scale:=jsEighth;
            MyJpg.PixelFormat:=jf24Bit;
            MyComponent:=self.FindComponent('MyImage'+inttostr(i));
            MyJpg.LoadFromFile(MyArray[i].Path);
            TImage(MyComponent).Canvas.StretchDraw(TImage(MyComponent).Canvas.ClipRect,MyJpg);
     
        end;//boucle for
    Merci d'avance
    [Il était une fois Delphi ....]


  2. #2
    Expert éminent sénior
    Avatar de ShaiLeTroll
    Homme Profil pro
    Développeur C++\Delphi
    Inscrit en
    Juillet 2006
    Messages
    13 459
    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 459
    Points : 24 873
    Points
    24 873
    Par défaut
    Tu pourrais réduire le nombre d'appel à ProcessMessages() !
    Cela doit probablement afficher les images au fur et à mesure !

    Je ne vois pas la libération des TJpegImage ?

    Tu utilises autant de TImage qu'il y a d'élément ?
    C'est archaïque comme méthode !

    Tu pourrais affecter les images dans une TImageList !
    La TListView étant attaché au TImageList affichera tes mignatures, cela sera proche du TShellListView !
    Je l'ai fait, cela fonctionne très bien !

    Tu savais que le TWebBrowser en faisant un Navigate sur un répertoire fonctionne comme le TShellListView (ou SysListView32) !


    Pourquoi charger toutes les images d'un coup ?
    Sur l'écran, tu ne peux afficher que 20 images par exemple, je suppose que tu as système de défilement pour voir les autres images
    Donc lors du Scrolling, tu charges les images suivantes !

    C'est comme ça que fonctionne le DBGrid, il affiche juste les enregistrements nécessaire pour l'affichage, puis lorsque l'on défile, il va charger juste la section d'enregistrement nécessaire, il ne balaye pas l'ensemble des données inutilement !

    Adapté de l'aide

    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
    function TMainForm.MakeImageList(const FileNames: array of String): TImageList;
    var
      ResBmp: TBitmap;
      MyJpg: TJpegImage;
      I: Integer;
    begin
      { Create an image list. }
      Result := TImageList.Create(Self);
     
      for I := 0 to Length(FileNames) - 1 do
      begin
        { Create a new bitmap image. }
        ResBmp := TBitmap.Create();
        try
          MyJpg := TJpegImage.Create;
          try
            MyJpg := TJpegImage.Create();
            MyJpg.Performance := jpBestSpeed;
            MyJpg.Scale := jsEighth;
            MyJpg.PixelFormat := jf24Bit;
            MyJpg.LoadFromFile(FileNames);
     
            ResBmp.Assign(MyJpg);
     
          finally
            MyJpgFree();    
          end;
        finally
          ResBmp.Free();    
        end;
     
        Result.Add(ResBmp, nil);
      end;
    end;



    Cette ImageList affecté à une TListView et le tour est joué !
    Aide via F1 - FAQ - Guide du développeur Delphi devant un problème - Pensez-y !
    Attention Troll Méchant !
    "Quand un homme a faim, mieux vaut lui apprendre à pêcher que de lui donner un poisson" Confucius
    Mieux vaut se taire et paraître idiot, Que l'ouvrir et de le confirmer !
    L'ignorance n'excuse pas la médiocrité !

    L'expérience, c'est le nom que chacun donne à ses erreurs. (Oscar Wilde)
    Il faut avoir le courage de se tromper et d'apprendre de ses erreurs

  3. #3
    Membre averti Avatar de zemeilleurofgreg
    Profil pro
    Inscrit en
    Mars 2006
    Messages
    515
    Détails du profil
    Informations personnelles :
    Âge : 48
    Localisation : Belgique

    Informations forums :
    Inscription : Mars 2006
    Messages : 515
    Points : 346
    Points
    346
    Par défaut
    Bonjour ShaiLeTroll,

    Comme je vois, tu n'es jamais très loin de ton PC et c'est tant mieux pour nous

    Je ne vois pas la libération des TJpegImage ?
    Il existe mais j'ai mis l'essentiel du code afin de clarifier la situation.

    Tu utilises autant de TImage qu'il y a d'élément !
    Effectivement, TImage qui sont placés sur des TPanel créés dynamiquements.

    Tu savais que le TWebBrowser en faisant un Navigate sur un répertoire fonctionne comme le TShellListView !
    Gain de performences avec TWebBrowser ?
    Actuellement j'utilise le TShellListView placé sur la gauche de l'écran et lors de la sélection d'un répertoire l'affichage des photos se fait sur le milieu de l'écran (comme dans l'explorateur windows).

    Pour charger toutes les images d'un coup !
    Sur l'écran, tu ne peux afficher que 20 images par exemple, je suppose que tu as système de défilement pour voir les autres images
    Donc lors du Scrolling, tu charges les images suivantes !
    c'est la prochaine étape de ma programmation
    Reste à définir quelle taille réelle fait la form. Le height me donne la taille totale avec le scroll.
    [Il était une fois Delphi ....]


  4. #4
    Expert éminent sénior
    Avatar de ShaiLeTroll
    Homme Profil pro
    Développeur C++\Delphi
    Inscrit en
    Juillet 2006
    Messages
    13 459
    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 459
    Points : 24 873
    Points
    24 873
    Par défaut
    Tu peux tricher !
    Laisse les TImage en position fixe !
    Au lieu d'avoir un ScrollBox tu utilises une ScrollBar !
    Dans ce cas, lors du défilement du ScrollBar, en réalité les TImage ne bouge pas, tu fais juste substituer l'image précédent par une nouvelle, on aura l'impression de défilement mais uniquement avec un nombre limité d'image présente en mémoire !

    Pense au TGridPanel ou TFlowPanel, si tu as 2007 ou plus, c'est bien pratique pour gérer le positionnement de panel créer à la volée !

    tu utilises un TShellListView ou TShellTreeView ???
    Dans le TShellListView, cherche un mode ViewStyle vsIcon !
    Cela existe bien dans le TListView, un comble que le TShellListView ne fournisse pas le mode Miniature !

    Je te joints l'image d'un TListView de Delphi 7 contenant trois images BMP (avec un léger strech) comparé au TWebBrowser !



    Je te laisse apprécié l'effet du code suivant sur le TWebBrowser (posé dans un TPanel PanelWebBrowser)

    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
    46
    47
    48
    49
    50
    51
    52
    53
    54
    procedure TFrmTestDivers.Button8Click(Sender: TObject);
    var
      Style: Longint;
      HandleList: HWND;
      i: Integer;
    const
       LVM_SETVIEW = $108E;
       LV_VIEW_TILE = 4;
    begin
       HandleList := FoundChild(PanelWebBrowser.Handle, 'SysListView32', 'FolderView');
     
       Style := GetWindowLong(HandleList, GWL_STYLE);
       Style := Style and (not LVS_TYPEMASK);
       Style := Style or LVS_LIST;
       // SetWindowLong(HandleList, GWL_STYLE, Style);
     
       SendMessage(HandleList, LVM_SETVIEW, LV_VIEW_TILE, 0);
    end;
     
    function FoundChild(Parent: THandle; const ClassName, WindowName: string; ChildIndex: Integer = 0): THandle;
    var
       HandleFound: THandle;
       lpRes : array[0..256] of Char;
       StrClass: string;
       StrCaption: string;
       iChild: Integer;
    begin
       Result := 0;
       iChild := -1;
     
       HandleFound := GetWindow(Parent, GW_CHILD);
       while HandleFound > 0 do
       begin
          GetClassName(HandleFound, lpRes, SizeOf(lpRes));
          StrClass := lpRes;
          GetWindowText(HandleFound, lpRes, SizeOf(lpRes));
          StrCaption := lpRes;
     
          if ((ClassName = '') or SameText(ClassName, StrClass)) and ((WindowName = '') or SameText(WindowName, StrCaption)) then
          begin
             Inc(iChild);
             if iChild >= ChildIndex then begin
                Result := HandleFound;
                Exit;
             end;
          end else
          begin
             Result := FoundChild(HandleFound, ClassName, WindowName, ChildIndex);
             if Result > 0 then Exit;
          end;
     
          HandleFound := GetWindow(HandleFound, GW_HWNDNEXT);
       end;
    end;
    Images attachées Images attachées  
    Aide via F1 - FAQ - Guide du développeur Delphi devant un problème - Pensez-y !
    Attention Troll Méchant !
    "Quand un homme a faim, mieux vaut lui apprendre à pêcher que de lui donner un poisson" Confucius
    Mieux vaut se taire et paraître idiot, Que l'ouvrir et de le confirmer !
    L'ignorance n'excuse pas la médiocrité !

    L'expérience, c'est le nom que chacun donne à ses erreurs. (Oscar Wilde)
    Il faut avoir le courage de se tromper et d'apprendre de ses erreurs

  5. #5
    Membre averti Avatar de zemeilleurofgreg
    Profil pro
    Inscrit en
    Mars 2006
    Messages
    515
    Détails du profil
    Informations personnelles :
    Âge : 48
    Localisation : Belgique

    Informations forums :
    Inscription : Mars 2006
    Messages : 515
    Points : 346
    Points
    346
    Par défaut
    J'ai tenté l'utilisation du TWebbrowser mais comment se passe le placement des images ? Je dois bien admettre que c'est un compo totalement inconnu pour moi.

    Encore merci
    [Il était une fois Delphi ....]


  6. #6
    Expert éminent sénior
    Avatar de ShaiLeTroll
    Homme Profil pro
    Développeur C++\Delphi
    Inscrit en
    Juillet 2006
    Messages
    13 459
    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 459
    Points : 24 873
    Points
    24 873
    Par défaut
    Le placement des images ?
    Le TWebBrowser affiche le contenu d'un répertoire comme le ferait l'explorateur !
    Il faut jouer avec le style !

    Mon exemple sur le TWebBrowser était plus "pédagogique" pour montrer ce qui existait, tu auras un manque de maîtrise dessus ! C'était purement démonstratif de la classe SysListView32 (équivalent au TShellListView )
    Normalement le TShellListView devrait pouvoir faire autant de chose que le TWebBrowser, c'est juste les API Windows !

    L'utilisation d'une TImageList + TListView devrait apporter un résultat similaire !

    En plus le comportement du TWebBrowser dépendra de la version de IE et de Windows ! C'est périlleux
    Aide via F1 - FAQ - Guide du développeur Delphi devant un problème - Pensez-y !
    Attention Troll Méchant !
    "Quand un homme a faim, mieux vaut lui apprendre à pêcher que de lui donner un poisson" Confucius
    Mieux vaut se taire et paraître idiot, Que l'ouvrir et de le confirmer !
    L'ignorance n'excuse pas la médiocrité !

    L'expérience, c'est le nom que chacun donne à ses erreurs. (Oscar Wilde)
    Il faut avoir le courage de se tromper et d'apprendre de ses erreurs

  7. #7
    Membre averti Avatar de zemeilleurofgreg
    Profil pro
    Inscrit en
    Mars 2006
    Messages
    515
    Détails du profil
    Informations personnelles :
    Âge : 48
    Localisation : Belgique

    Informations forums :
    Inscription : Mars 2006
    Messages : 515
    Points : 346
    Points
    346
    Par défaut
    Salut ShaiLeTroll,

    il y a bien un mode ViewStyle vsIcon dans le TShellListView mais ça ne m'interesse pas de voir l'icone associée à la photos. ou alors j'ai rien compris (ce qui n'est pas impossible )

    Ce que je veux faire (et que je fais) c'est afficher les PHOTOS en miniature mais j'aimerais que cela se fasse plus instantanément (comme quand on ouvre un répertoire photos dans l'explorateur). Ce qui prend des plombes, c'est le loadfromfile en boucle de chaque fichier image.

    quel est le rapport entre le code ci dessous et l'image jointe ?


    Sur quoi agit ce code ?
    oui je sais, je suis dur de comprendure

    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
    46
    47
    48
    49
    50
    51
    52
    53
    54
    procedure TFrmTestDivers.Button8Click(Sender: TObject);
    var
      Style: Longint;
      HandleList: HWND;
      i: Integer;
    const
       LVM_SETVIEW = $108E;
       LV_VIEW_TILE = 4;
    begin
       HandleList := FoundChild(PanelWebBrowser.Handle, 'SysListView32', 'FolderView');
     
       Style := GetWindowLong(HandleList, GWL_STYLE);
       Style := Style and (not LVS_TYPEMASK);
       Style := Style or LVS_LIST;
       // SetWindowLong(HandleList, GWL_STYLE, Style);
     
       SendMessage(HandleList, LVM_SETVIEW, LV_VIEW_TILE, 0);
    end;
     
    function FoundChild(Parent: THandle; const ClassName, WindowName: string; ChildIndex: Integer = 0): THandle;
    var
       HandleFound: THandle;
       lpRes : array[0..256] of Char;
       StrClass: string;
       StrCaption: string;
       iChild: Integer;
    begin
       Result := 0;
       iChild := -1;
     
       HandleFound := GetWindow(Parent, GW_CHILD);
       while HandleFound > 0 do
       begin
          GetClassName(HandleFound, lpRes, SizeOf(lpRes));
          StrClass := lpRes;
          GetWindowText(HandleFound, lpRes, SizeOf(lpRes));
          StrCaption := lpRes;
     
          if ((ClassName = '') or SameText(ClassName, StrClass)) and ((WindowName = '') or SameText(WindowName, StrCaption)) then
          begin
             Inc(iChild);
             if iChild >= ChildIndex then begin
                Result := HandleFound;
                Exit;
             end;
          end else
          begin
             Result := FoundChild(HandleFound, ClassName, WindowName, ChildIndex);
             if Result > 0 then Exit;
          end;
     
          HandleFound := GetWindow(HandleFound, GW_HWNDNEXT);
       end;
    end;
    Images attachées Images attachées  
    [Il était une fois Delphi ....]


  8. #8
    Expert éminent sénior
    Avatar de ShaiLeTroll
    Homme Profil pro
    Développeur C++\Delphi
    Inscrit en
    Juillet 2006
    Messages
    13 459
    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 459
    Points : 24 873
    Points
    24 873
    Par défaut
    Le code SendMessage LVM_SETVIEW, c'était pour te montrer comment manipuler le TWebBrowser, cela lui change son mode d'affichage !
    D'abord, je cherche avec FoundChild un contrôle du type SysListView32 car je sais que le TWebBrowser en contient un !
    Mais le TWebBrowser ne doit pas fournir son Handle de contrôle, je prends alors celui du parent pour trouver le SysListView32 à l'intérieur du TWebBrowser

    Si tu pars dans cette direction, il va te falloir éplucher le MSDN pour trouver les Message du ListView (en fait le code du TListView en contient massivement puisque c'est le même composant windows)

    Et cela reste de la grosse bidouille, pense que tu n'auras pas de OnClick dessus pour gérer la selection d'image !


    Pourquoi tu n'essaye pas avec MakeImageList de 13/01/2012 16h42
    Au lieu de Assign, tu utilises un StrechDraw pour faire une miniature dans la TImageList associé au TListView !
    Aide via F1 - FAQ - Guide du développeur Delphi devant un problème - Pensez-y !
    Attention Troll Méchant !
    "Quand un homme a faim, mieux vaut lui apprendre à pêcher que de lui donner un poisson" Confucius
    Mieux vaut se taire et paraître idiot, Que l'ouvrir et de le confirmer !
    L'ignorance n'excuse pas la médiocrité !

    L'expérience, c'est le nom que chacun donne à ses erreurs. (Oscar Wilde)
    Il faut avoir le courage de se tromper et d'apprendre de ses erreurs

  9. #9
    Membre averti Avatar de zemeilleurofgreg
    Profil pro
    Inscrit en
    Mars 2006
    Messages
    515
    Détails du profil
    Informations personnelles :
    Âge : 48
    Localisation : Belgique

    Informations forums :
    Inscription : Mars 2006
    Messages : 515
    Points : 346
    Points
    346
    Par défaut
    Et cela reste de la grosse bidouille, pense que tu n'auras pas de OnClick dessus pour gérer la selection d'image !
    Oui, c'est pour cela que je vais continuer dans ma direction actuelle parce que j'ai déja fais un gros travail au niveau des sélections de photos ou survol de la souris etc,...

    Je suis proche du résultat de l'explorateur, reste à résourdre le problème de lenteur d'affichage.

    Pourquoi tu n'essaye pas avec MakeImageList de 13/01/2012 16h42
    Je vais faire ça, je pense qu'il y a du potentiel.
    Je te tiens au courant.

    Merci de tes bons conseils
    [Il était une fois Delphi ....]


  10. #10
    Membre averti Avatar de zemeilleurofgreg
    Profil pro
    Inscrit en
    Mars 2006
    Messages
    515
    Détails du profil
    Informations personnelles :
    Âge : 48
    Localisation : Belgique

    Informations forums :
    Inscription : Mars 2006
    Messages : 515
    Points : 346
    Points
    346
    Par défaut
    je patauge, je patauge

    Pourquoi tu n'essaye pas avec MakeImageList de 13/01/2012 16h42
    Au lieu de Assign, tu utilises un StrechDraw pour faire une miniature dans la TImageList associé au TListView !
    concrètement ça devrait donner un truc de ce genre ?

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    ResBmp.Canvas.StretchDraw(ResBmp.Canvas.ClipRect,MyJpg);
         Result.Add(ResBmp,nil);
    si c'est ça, delphi me retourne un message "taille d'image incorrecte" !

    Et pour l'affichage !?

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    ListView1.LargeImages:=MakeImageList(MyArray);
      ctrImageList:=MakeImageList(MyArray).Count;
      for i:=0 to ctrImageList-1 do
      begin
        ListItem :=ListView1.Items.Add;
        Listitem.Caption :='Image'+IntToStr(I);
        ListItem.ImageIndex :=I;
      end;
    [Il était une fois Delphi ....]


  11. #11
    Expert éminent sénior
    Avatar de ShaiLeTroll
    Homme Profil pro
    Développeur C++\Delphi
    Inscrit en
    Juillet 2006
    Messages
    13 459
    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 459
    Points : 24 873
    Points
    24 873
    Par défaut
    L'exemple du Wiki avait quelques fuite mémoires que j'ai corrigé, mais j'ai bêtement laisse le Add après le finally, je suppose que tu l'avais corrigé

    C'est un petit peu plus compliqué car dans une TImageList, toutes les images doivent avoir la même taille !
    Pour un affichage de miniature, ce n'est pas un problème

    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
     
    function TMainForm.MakeImageList(const FileNames: array of String): TImageList;
    var
      ResBmp, StretchBmp: TBitmap;
      MyJpg: TJpegImage;
      I: Integer;
    begin
      { Create an image list. }
      Result := TImageList.Create(Self);
      Result.Height := 128;
      Result.Width := 128;
     
      for I := 0 to Length(FileNames) - 1 do
      begin
        { Create a new bitmap image. }
        ResBmp := TBitmap.Create();
        try
          MyJpg := TJpegImage.Create;
          try
            MyJpg := TJpegImage.Create();
            MyJpg.Performance := jpBestSpeed;
            MyJpg.Scale := jsEighth;
            MyJpg.PixelFormat := jf24Bit;
            MyJpg.LoadFromFile(FileNames);
     
            ResBmp.Height := Result.Height;
            ResBmp.Width := Result.Width;   
            ResBmp.Canvas.StretchDraw(Rect(0, 0, StretchBmp.Width, StretchBmp.Height), MyJpg);
            Result.Add(ResBmp, nil);
          finally
            MyJpg.Free();    
          end; 
     
        finally
          ResBmp.Free();    
        end; 
      end;
    end;
    Tu noteras une déformation de l'Image avec cet algo !
    Mais cela peut s'améliorer !

    Voici un exemple de code, je viens de le taper, je ne l'ai pas testé, je n'ai que C++Builder sur mon poste, c'est un peu pénible à tester !

    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
    46
    47
    48
    49
    50
    51
    52
    53
    function TMainForm.MakeImageList(const FileNames: array of String): TImageList;
    var
      ResBmp, StretchBmp: TBitmap;
      MyJpg: TJpegImage;
      I: Integer;
      RatioW, RatioH, Ratio: Double;
    begin
      { Create an image list. }
      Result := TImageList.Create(Self);
      Result.Height := 128;
      Result.Width := 128;
     
      for I := 0 to Length(FileNames) - 1 do
      begin
        { Create a new bitmap image. }
        ResBmp := TBitmap.Create();
        try
          MyJpg := TJpegImage.Create;
          try
            MyJpg := TJpegImage.Create();
            MyJpg.Performance := jpBestSpeed;
            MyJpg.Scale := jsEighth;
            MyJpg.PixelFormat := jf24Bit;
            MyJpg.LoadFromFile(FileNames);
     
     
            StretchBmp := TBitmap.Create();
            try 
              // Calcul du Ratio
              RatioH := MyJpg.Height / Result.Height;
              RatioW := MyJpg.Width / Result.Width;
              Ratio := IfThen(RatioH > RatioW, RatioH, RatioW);
     
              StretchBmp.Height := Trunc(MyJpg.Height / Ratio);
              StretchBmp.Width := Trunc(MyJpg.Width / Ratio);          
              StretchBmp.Canvas.StretchDraw(Rect(0, 0, StretchBmp.Width, StretchBmp.Height), MyJpg);
     
              ResBmp.Height := Result.Height;
              ResBmp.Width := Result.Width;   
              ResBmp.Canvas.Draw(0, 0, StretchBmp); // Ce qui n'aura pas été dessiné devrait blanc !
              Result.Add(ResBmp, nil); // The ImageList_Add function copies the bitmap to an internal data structure
     
            finally
              StretchBmp.Free();    
            end;        
          finally
            MyJpg.Free();    
          end; 
        finally
          ResBmp.Free();    
        end; 
      end;
    end;

    Pour l'affichage, ton code semble bien, tu peux aussi mettre le nom du fichier
    Attention n'appel pas plusieurs fois MakeImageList, cela récrée une liste à chaque fois !

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    ListView1.LargeImages:=MakeImageList(MyArray);
      for i:=0 to ListView1.LargeImages.Count - 1 do
      begin
        ListItem :=ListView1.Items.Add;
        Listitem.Caption :='Image'+IntToStr(I) + ' : ' + ExtractFileName(MyArray[i]);
        ListItem.ImageIndex :=I;
      end;
    Aide via F1 - FAQ - Guide du développeur Delphi devant un problème - Pensez-y !
    Attention Troll Méchant !
    "Quand un homme a faim, mieux vaut lui apprendre à pêcher que de lui donner un poisson" Confucius
    Mieux vaut se taire et paraître idiot, Que l'ouvrir et de le confirmer !
    L'ignorance n'excuse pas la médiocrité !

    L'expérience, c'est le nom que chacun donne à ses erreurs. (Oscar Wilde)
    Il faut avoir le courage de se tromper et d'apprendre de ses erreurs

  12. #12
    Membre averti Avatar de zemeilleurofgreg
    Profil pro
    Inscrit en
    Mars 2006
    Messages
    515
    Détails du profil
    Informations personnelles :
    Âge : 48
    Localisation : Belgique

    Informations forums :
    Inscription : Mars 2006
    Messages : 515
    Points : 346
    Points
    346
    Par défaut
    Salut ShaiLeTroll,

    ta technique fonctionne très bien et je l'adopte car moins casse tête.
    Cependant cela ne résoud pas la lenteur d'affichage.

    J'affiche les photos au fur et à mesure du scroll mais ce n'est pas encore comme je voudrais.

    Comment fait Windows à ce niveau pour que l'affichage soit aussi rapide ?

    N'existe t'il pas une autre technique que le LoadFromFile ?

    Merci de ta bienveillance
    [Il était une fois Delphi ....]


  13. #13
    Membre chevronné

    Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Août 2002
    Messages
    1 288
    Détails du profil
    Informations personnelles :
    Âge : 43
    Localisation : France, Rhône (Rhône Alpes)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels

    Informations forums :
    Inscription : Août 2002
    Messages : 1 288
    Points : 1 936
    Points
    1 936
    Par défaut
    Windows affiche des vignettes présentes dans Thumbs.db, par contre je ne sais pas comment récupérer les données (présence de multiples JFIF)
    Delphi 7/XE2/XE3
    C#
    Oracle 9i à 12c
    SQL Server 2008 à 2014

  14. #14
    Expert éminent sénior
    Avatar de ShaiLeTroll
    Homme Profil pro
    Développeur C++\Delphi
    Inscrit en
    Juillet 2006
    Messages
    13 459
    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 459
    Points : 24 873
    Points
    24 873
    Par défaut
    L'idée serait de créer la TListView comme ceci

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
      for I := Low(MyArray) to High(MyArray)  do
      begin
        ListItem :=ListView1.Items.Add();
        Listitem.Caption := MyArray[i];
      end;
    la TImageList, tu la pose via l'IDE sur la fenêtre, et tu l'associe avec LargeImages avec l'inspecteur d'objet
    Pense à définir Height et Width du TImageList, disons 128x128
    Tu noteras que même si la TImageList est vide, la TListView prévoit la place pour afficher les images (pour le moment, de grand zone blanche)

    Dans le TListView, dans OnDrawItem, tu vérifie l'ImageIndex de Item passé en paramètre, si -1 alors tu vas lire l'image avec LoadFromFile, tu l'ajoute à la TImageList et tu affectes à ImageIndex avec l'indice renvoyé par Add

    Tu peux aussi le faire dans OnAdvancedCustomDraw Stage cdPrePaint

    du coup, cela ne devrait charger l'image qu'au moment de l'affichage !
    Cela devrait améliorer les performances !

    Pense que tu vas tout de même occuper de la RAM, si cela se compte en milliers d'image, cela coutera plusieurs dizaines de Mo

    Voir OnData et OwnerData, mais cela risque d'être nettement plus complexe, mais je suppose que c'est la méthode utilisé par l'explorateur !

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    function TMainForm.ListViewDrawItem(Sender: TCustomListView; Item: TListItem; Rect TRect; State TOwnerDrawState);
    begin
      if Item.ImageIndex = - 1 then
        Item.ImageIndex := ImageListLoadFromFile((Sender as TListView).LargeImages, Item.Caption);
    end;
    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
    46
    47
    48
    49
     
    function TMainForm.LoadOneImageToImageListFromFile(AImageList: TImageList, const AFileName: String): Integer;
    var
      ResBmp, StretchBmp: TBitmap;
      MyJpg: TJpegImage;
      I: Integer;
      RatioW, RatioH, Ratio: Double;
    begin
      Result := -1;
      if Assigned(AImageList) then
      begin 
        { Create a new bitmap image. }
        ResBmp := TBitmap.Create();
        try
          MyJpg := TJpegImage.Create;
          try
            MyJpg := TJpegImage.Create();
            MyJpg.Performance := jpBestSpeed;
            MyJpg.Scale := jsEighth;
            MyJpg.PixelFormat := jf24Bit;
            MyJpg.LoadFromFile(AFileName);
     
            StretchBmp := TBitmap.Create();
            try 
              // Calcul du Ratio
              RatioH := MyJpg.Height / AImageList.Height;
              RatioW := MyJpg.Width / AImageList.Width;
              Ratio := IfThen(RatioH > RatioW, RatioH, RatioW);
     
              StretchBmp.Height := Trunc(MyJpg.Height / Ratio);
              StretchBmp.Width := Trunc(MyJpg.Width / Ratio);          
              StretchBmp.Canvas.StretchDraw(Rect(0, 0, StretchBmp.Width, StretchBmp.Height), MyJpg);
     
              ResBmp.Height := AImageList.Height;
              ResBmp.Width := AImageList.Width;   
              ResBmp.Canvas.Draw(0, 0, StretchBmp); // Ce qui n'aura pas été dessiné devrait blanc !
              Result := AImageList.Add(ResBmp, nil); // The ImageList_Add function copies the bitmap to an internal data structure
     
            finally
              StretchBmp.Free();    
            end;        
          finally
            MyJpg.Free();    
          end; 
        finally
          ResBmp.Free();    
        end; 
      end;
    end;
    Aide via F1 - FAQ - Guide du développeur Delphi devant un problème - Pensez-y !
    Attention Troll Méchant !
    "Quand un homme a faim, mieux vaut lui apprendre à pêcher que de lui donner un poisson" Confucius
    Mieux vaut se taire et paraître idiot, Que l'ouvrir et de le confirmer !
    L'ignorance n'excuse pas la médiocrité !

    L'expérience, c'est le nom que chacun donne à ses erreurs. (Oscar Wilde)
    Il faut avoir le courage de se tromper et d'apprendre de ses erreurs

  15. #15
    Membre averti Avatar de zemeilleurofgreg
    Profil pro
    Inscrit en
    Mars 2006
    Messages
    515
    Détails du profil
    Informations personnelles :
    Âge : 48
    Localisation : Belgique

    Informations forums :
    Inscription : Mars 2006
    Messages : 515
    Points : 346
    Points
    346
    Par défaut
    Salut à tous,

    voila, je cloture le sujet.
    Je n'ai pas atteint le niveau de performance souhaité mais c'est déja beaucoup mieux grâce à toi ShaiLeTroll

    Encore un tout grand merci

    @très bientôt.

    Greg
    [Il était une fois Delphi ....]


  16. #16
    Expert éminent sénior
    Avatar de Jipété
    Profil pro
    Inscrit en
    Juillet 2006
    Messages
    10 730
    Détails du profil
    Informations personnelles :
    Localisation : France, Hérault (Languedoc Roussillon)

    Informations forums :
    Inscription : Juillet 2006
    Messages : 10 730
    Points : 15 132
    Points
    15 132
    Par défaut
    Salut,
    Citation Envoyé par zemeilleurofgreg Voir le message
    (...) Je n'ai pas atteint le niveau de performance souhaité mais c'est déja beaucoup mieux grâce à toi ShaiLeTroll
    Si tes photos sont issues d'APN, le fichier .jpg inclut la photo en elle-même (plusieurs mégas...) mais aussi une miniature, d'une taille ridicule.
    Tu devrais peut-être jeter un œil de ce côté...
    Il a à vivre sa vie comme ça et il est mûr sur ce mur se creusant la tête : peutêtre qu'il peut être sûr, etc.
    Oui, je milite pour l'orthographe et le respect du trait d'union à l'impératif.
    Après avoir posté, relisez-vous ! Et en cas d'erreur ou d'oubli, il existe un bouton « Modifier », à utiliser sans modération
    On a des lois pour protéger les remboursements aux faiseurs d’argent. On n’en a pas pour empêcher un être humain de mourir de misère.
    Mes 2 cts,
    --
    jp

  17. #17
    Expert éminent sénior
    Avatar de ShaiLeTroll
    Homme Profil pro
    Développeur C++\Delphi
    Inscrit en
    Juillet 2006
    Messages
    13 459
    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 459
    Points : 24 873
    Points
    24 873
    Par défaut
    Citation Envoyé par zemeilleurofgreg Voir le message
    Je n'ai pas atteint le niveau de performance souhaité
    Même en déportant le LoadFromFile avec LoadOneImageToImageListFromFile dans OnDrawItem ?
    Ne me dit pas qu'il dessine toute la liste d'un coup pour rien ?
    J'aurais cru qu'il ne dessinait que les Item visible !
    Aide via F1 - FAQ - Guide du développeur Delphi devant un problème - Pensez-y !
    Attention Troll Méchant !
    "Quand un homme a faim, mieux vaut lui apprendre à pêcher que de lui donner un poisson" Confucius
    Mieux vaut se taire et paraître idiot, Que l'ouvrir et de le confirmer !
    L'ignorance n'excuse pas la médiocrité !

    L'expérience, c'est le nom que chacun donne à ses erreurs. (Oscar Wilde)
    Il faut avoir le courage de se tromper et d'apprendre de ses erreurs

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

Discussions similaires

  1. Affichage lent d'une image
    Par GJ-Albert dans le forum 2D
    Réponses: 3
    Dernier message: 16/12/2009, 23h26
  2. [MySQL] Optimisation requête, affichage lent
    Par Yann39 dans le forum Langage SQL
    Réponses: 9
    Dernier message: 10/10/2008, 11h23
  3. Image - PictureBox : affichage LENT
    Par johan3240 dans le forum Windows Forms
    Réponses: 1
    Dernier message: 10/06/2008, 10h50
  4. [WinForms]affichage lent en transparence et zone de click
    Par glebourg dans le forum Général Dotnet
    Réponses: 2
    Dernier message: 20/12/2006, 20h35
  5. [C#] Affichage lent avec la méthode DrawRectangle
    Par mr.saucisse dans le forum Windows Forms
    Réponses: 4
    Dernier message: 03/08/2006, 13h00

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