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

C# Discussion :

Affichage rapide d'images


Sujet :

C#

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  1. #1
    Membre éclairé
    Homme Profil pro
    autre
    Inscrit en
    Janvier 2015
    Messages
    212
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Morbihan (Bretagne)

    Informations professionnelles :
    Activité : autre

    Informations forums :
    Inscription : Janvier 2015
    Messages : 212
    Par défaut Affichage rapide d'images
    Bonjour,

    Je souhaite afficher rapidement un grand nombre d'images présentes dans un répertoire.
    Les images sont assez grosses. En moyenne 1200x800 px et 1 Mo.
    Il y en a 4000 dans le répertoire.

    C'est la troisième fois que je reprends à zéro ce projet, tant le problème du temps d'affichage des images dans une listview est rédhibitoire.
    Ça va jusqu'à plusieurs minutes d'attente pour tout charger (et je les redimensionne avant de charger l'ImageList).
    À chaque trie ou filtre ça recommence.

    Existe-t-il un package qui prendrait en charge l'affichage rapide d'un grand nombre d'images ?
    Je n'ai pas à les transformer, à les éditer etc... C'est une gestion de collection de tableaux de peintres.

    Mes recherches ne m'ont rien renvoyé de concluant ou d'adapté.
    J'ai uniquement besoin de les afficher rapidement en miniatures (environ 200x200).

    Un logiciel comme FastStone fait très bien cela, par exemple.

    Merci,

  2. #2
    Membre Expert
    Profil pro
    Inscrit en
    Septembre 2010
    Messages
    1 545
    Détails du profil
    Informations personnelles :
    Âge : 46
    Localisation : France

    Informations forums :
    Inscription : Septembre 2010
    Messages : 1 545
    Par défaut
    une demande à mon ami google sur c# .net miniature et hop, des pistes intéressantes (non testés):
    en winforms: https://learn.microsoft.com/fr-fr/do...orkdesktop-4.8
    en wpf: https://learn.microsoft.com/fr-fr/do...orkdesktop-4.8
    (comme on ne sait pas ce que tu as essayé)
    En tout cas, il faut éviter de refaire l'opération à chaque fois, c'est sûr.

  3. #3
    Membre éclairé
    Homme Profil pro
    autre
    Inscrit en
    Janvier 2015
    Messages
    212
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Morbihan (Bretagne)

    Informations professionnelles :
    Activité : autre

    Informations forums :
    Inscription : Janvier 2015
    Messages : 212
    Par défaut
    Bonjour umfred,

    Merci, je vais voir ce que cela donne avec tes liens.

    Cependant j'ai déjà une méthode pour créer des miniatures

    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
     
            public System.Drawing.Image Padding_Reduce_Image(System.Drawing.Image image, Color backColor, int height, int width)
            {
     
                //get the maximum size of the image dimensions
                int maxSize = Math.Max(image.Height, image.Width);
                Size squareSize = new Size(maxSize, maxSize);
     
                //create a new square image
                Bitmap squareImage = new Bitmap(squareSize.Width, squareSize.Height);
     
                using (Graphics graphics = Graphics.FromImage(squareImage))
                {
                    //fill the new square with a color
                    graphics.FillRectangle(new SolidBrush(backColor), 0, 0, squareSize.Width, squareSize.Height);
     
                    //put the original image on top of the new square
                    graphics.DrawImage(image, (squareSize.Width / 2) - (image.Width / 2), (squareSize.Height / 2) - (image.Height / 2), image.Width, image.Height);
                }
     
                try
                {
                    //Image image = Image.FromStream(resourceImage);
                    Image thumb = squareImage.GetThumbnailImage(width, height, () => false, IntPtr.Zero);
                    return thumb;
     
     
                }
                catch (Exception)
                {
                    return null;
                }
                //return the image
            }
    Je n'arrive pas à comprendre d'où vient le fait que cela prenne autant de temps dans mon code.
    Si c'est lié à un problème de structure de mon code, ou si c'est lié au temps intrinsèque des opérations successives que je lui fait réaliser.
    Accéder à chaque fichier image du répertoire > Convertir l'image en miniature > Charger ImageList > Afficher dans ListView

    Je me demandais si n'existait pas une solution "clé en main" Ou une approche plus économe genre Lazy Load

    Merci

  4. #4
    Membre éprouvé Avatar de WDKyle
    Homme Profil pro
    Analyste-Programmeur
    Inscrit en
    Septembre 2008
    Messages
    1 204
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Rhône (Rhône Alpes)

    Informations professionnelles :
    Activité : Analyste-Programmeur

    Informations forums :
    Inscription : Septembre 2008
    Messages : 1 204
    Par défaut
    Bonjour,

    Utilisez-vous du multithreading pour effectuer ses taches de façon parallélisées ?

  5. #5
    Expert éminent Avatar de Pol63
    Homme Profil pro
    .NET / SQL SERVER
    Inscrit en
    Avril 2007
    Messages
    14 197
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 43
    Localisation : France, Puy de Dôme (Auvergne)

    Informations professionnelles :
    Activité : .NET / SQL SERVER

    Informations forums :
    Inscription : Avril 2007
    Messages : 14 197
    Par défaut
    Tu n'affiches pas les 4000 images en même temps, donc pourquoi les charger toutes
    Il suffit de les charger au fur et à mesure du scroll (et en multithreadé surement)
    Cours complets, tutos et autres FAQ ici : C# - VB.NET

  6. #6
    Membre éclairé
    Homme Profil pro
    autre
    Inscrit en
    Janvier 2015
    Messages
    212
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Morbihan (Bretagne)

    Informations professionnelles :
    Activité : autre

    Informations forums :
    Inscription : Janvier 2015
    Messages : 212
    Par défaut
    Bonjour WDKyle,

    Oui j'utilise le multithread.

    J'ai aussi imaginé créer un sous-répertoire pour stocker les miniatures.
    Ce qui m'oblige à vérifier à chaque étapes la cohérence entre les images grand format, les miniatures, et la base de données.
    Opérations très contraignantes qui multiplient les sources et occasions d'erreurs.

    J'avoue que je reviens sur ce projet après des mois de pause.
    Je suis prêt à le reprendre entièrement après avoir bien identifié que mon problème principal est la lenteur d'affichage des images présentes dans le répertoire.

    D'où ma demande pour savoir s'il n'existait pas un package qui ferait déjà cela mieux que je pourrais le faire.

    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
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
    102
    103
    104
    105
    106
    107
    108
    109
    110
    111
    112
    113
    114
    115
    116
    117
    118
    119
    120
    121
    122
    123
    124
    125
    126
    127
    128
    129
    130
    131
    132
    133
    134
    135
    136
    137
    138
    139
     
            private void BackWorkerImage_DoWork(object sender, System.ComponentModel.DoWorkEventArgs e)
            {
                BackgroundWorker worker = sender as BackgroundWorker;
     
                List<object> genericlist = e.Argument as List<object>;
                string monPath = (string)genericlist[0];
                int Value1 = (int)genericlist[1]; // Nb d'images à charger
     
                if (ProgBarImg.InvokeRequired) //ProgBarImg.Maximum = Value1 + 10;
                    ProgBarImg.Invoke((MethodInvoker)delegate ()
                    {
                        ProgBar_Max(Value1 + 10);
                    });
                else ProgBarImg.Maximum = Value1 + 10;
     
     
                if (ChargerImagelist(monPath, worker, e) == false) // Pb filestream rencontré donc on essaie une deuxième fois
                {
                    if (ChargerImagelist(monPath, worker, e) == false)
                    {
                        string Message = "Un fichier est temporairement inaccessible.\n Veuillez relancer l'affichage des images ultérieurement en cliquant sur l'icône Rafraîchir";
                        string Caption = "Affichage des images du disque";
                        var result = FlexibleMessageBox.Show(Message, Caption, MessageBoxButtons.OK,
                                                             MessageBoxIcon.Information,
                                                             MessageBoxDefaultButton.Button1);
                        OeuvresImagesList.Images.Clear();
                        return;
                    }
                }
            }
            private bool ChargerImagelist(string directory, BackgroundWorker worker, System.ComponentModel.DoWorkEventArgs e)
            {
                Debug.WriteLine("ChargerImagelist");
                string NomFic;
                OeuvresImagesList.Images.Clear();
     
                try
                {
                    OeuvresListView.LargeImageList = OeuvresImagesList;
                    OeuvresListView.LargeImageList.ImageSize = new Size(150, 150);
                    OeuvresListView.LargeImageList.ColorDepth = ColorDepth.Depth16Bit;
                    OeuvresListView.View = View.LargeIcon;
                }
                catch (Exception ex)
                {
                    Debug.WriteLine(ex.Message);
                }
     
                if (Directory.Exists(directory + "\\Thumbs")) 
                {
                    // Si Thumbs existe on compare leur contenu
     
                    System.IO.DirectoryInfo dir1 = new System.IO.DirectoryInfo(directory);
                    System.IO.DirectoryInfo dir2 = new System.IO.DirectoryInfo(directory + "\\Thumbs");
     
                    // Take a snapshot of the file system.  
                    IEnumerable<System.IO.FileInfo> list1 = dir1.GetFiles("*.jpg", System.IO.SearchOption.TopDirectoryOnly);
                    IEnumerable<System.IO.FileInfo> list2 = dir2.GetFiles("*.jpg", System.IO.SearchOption.TopDirectoryOnly);
     
                    FileCompare myFileCompare = new FileCompare();
     
                    bool areIdentical = list1.SequenceEqual(list2, myFileCompare);
     
                    if (areIdentical == true) // Répertoires IDENTIQUES --> que des thumbnails 150 x 150 à charger
                    {
                        Debug.WriteLine("------------- Les répertoires sont identiques");
                        Remplis_ImageList(The_Directory + "\\Thumbs");
                    }
                    else // Répertoires DIFFERENTS
                    {
                        Debug.WriteLine("------------- Les répertoires sont différents");
     
                        Color CouleurFond = new Color();
                        CouleurFond = System.Drawing.Color.Transparent;
     
                        var queryCommonFiles = list1.Intersect(list2, myFileCompare);
     
                        if (queryCommonFiles.Any() == false)
                        {
                            Debug.WriteLine("------------- Il n'y a pas de fichier commun aux deux répertoires.");
     
                            Directory.Delete(directory + "\\Thumbs");// ---> Supp tous fichiers de Thumbs et le reconstruire
                            Create_THUMBS();
                        }
                        else // --> Seulement certains fichiers sont à traiter 
                        {
                            // Différences entre les deux répertoires  
                            //---------------------
                            var queryList1 = (from file in list1
                                              select file).Except(list2, myFileCompare);
     
                            Debug.WriteLine("------------- Les fichiers suivants sont dans The_Directory mais pas dans 'Thumbs' : ");
                            foreach (var v in queryList1)
                            {
                                Debug.WriteLine(" -- Création : " + v.Name);
     
                                FileStream fichier = new FileStream(v.FullName, FileMode.Open);
     
                                NomFic = v.Name;
                                string TargetFile = directory + "\\Thumbs\\" + NomFic;
     
                                Bitmap Image1 = new Bitmap(fichier);
                                Image newImage = Padding_Reduce_Image(Image1, CouleurFond, 150, 150);
                                newImage.Save(TargetFile, System.Drawing.Imaging.ImageFormat.Png);
     
                                fichier.Close();
                                fichier.Dispose();
                            }
                            //---------------------
                            var queryList2 = (from file in list2
                                              select file).Except(list1, myFileCompare);
     
                            Debug.WriteLine("------------- Les fichiers suivants sont dans 'Thumbs' mais absents de The_Directory : ");
                            foreach (var v in queryList2)
                            {
                                Debug.WriteLine(" -- Suppression : " + v.Name);
                                File.Delete(v.FullName);
                            }
     
                            Remplis_ImageList(The_Directory + "\\Thumbs"); // On rempli ensuite. !! le répertoire est trié 
                        }
                    }
                }
                else // Si Thumbs n'existe pas, on le crée avec des Thumnails de 150 x 150 px
                {
                    Create_THUMBS();
                }
     
                if (OeuvresListView.InvokeRequired)//OeuvresListView.Show();
                    OeuvresListView.Invoke((MethodInvoker)delegate ()
                    {
                        OeuvresListView_Show();
                    });
                else OeuvresListView.Show();
     
                Debug.WriteLine("Nb Images : " + OeuvresImagesList.Images.Count);
                return true;
            }

  7. #7
    Membre éclairé
    Homme Profil pro
    autre
    Inscrit en
    Janvier 2015
    Messages
    212
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Morbihan (Bretagne)

    Informations professionnelles :
    Activité : autre

    Informations forums :
    Inscription : Janvier 2015
    Messages : 212
    Par défaut
    Citation Envoyé par Pol63 Voir le message
    Tu n'affiches pas les 4000 images en même temps, donc pourquoi les charger toutes
    Il suffit de les charger au fur et à mesure du scroll (et en multithreadé surement)
    Bonjour Pol63,

    Oui, c'est aussi une idée. Un lazy Load. C'est évidemment la bonne façon de faire.
    Je n'ai pas creusé cette voie. J'imagine que l'on peut récupérer la liste des items visibles dans une ListView plus ou moins 10.
    Charger l'ImageList avec une miniature temporaire et remplacer les images au fur et à mesure de ce qui est demandé.
    Je dois tester ça.

Discussions similaires

  1. Capture d'images (rapide) et affichage (rapide)
    Par dtcSearch dans le forum Windows Presentation Foundation
    Réponses: 1
    Dernier message: 14/04/2011, 14h09
  2. Pbs d'affichage d'une image sur un panel
    Par ysr1 dans le forum C++Builder
    Réponses: 2
    Dernier message: 23/09/2004, 09h55
  3. [FLASH MX] Qualité d'affichage d'une image
    Par n_tony dans le forum Flash
    Réponses: 3
    Dernier message: 16/08/2004, 09h44
  4. [DirectDraw7] Affichage de plusieurs image bmp
    Par SteelBox dans le forum DirectX
    Réponses: 3
    Dernier message: 24/04/2004, 19h00
  5. Affichage d'une image sous linux
    Par Braim dans le forum x86 32-bits / 64-bits
    Réponses: 5
    Dernier message: 25/03/2003, 10h41

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