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

AWT/Swing Java Discussion :

[Optimisation] Mémoire occupée par des images


Sujet :

AWT/Swing Java

  1. #1
    Membre du Club
    Profil pro
    Inscrit en
    Avril 2007
    Messages
    64
    Détails du profil
    Informations personnelles :
    Âge : 39
    Localisation : France, Puy de Dôme (Auvergne)

    Informations forums :
    Inscription : Avril 2007
    Messages : 64
    Points : 58
    Points
    58
    Par défaut [Optimisation] Mémoire occupée par des images
    Bonjour,
    pour une application je suis en train d'effectuer un travail d'optimisation, je me sers de Netbeans 5.5 avec le profiler et la JDK employée est la 1.6. J'ai pu remarquer lors d'un test sur l'occupation mémoire que lorsque je chargeais des images mon application explosait apres 15-20 images. Petite précision le -Xmx est a 256Mo.
    Une fois l'application chargée et "au repos" elle occupe environ 170Mo, il reste donc environ 80-90Mo de libre. Les images sont au format png et jpg, elles ont une taille moyenne de 100ko... soit sur disque environ 2Mo...et ces 20 images prennent dans la JVM plus de 100Mo...ouille.
    Voici comment je chargeais mes images :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    image_temp = ImageIO.read(new File(this.imagePath));
    Toutefois j'ai recherché sur le forum et j'ai vu ce post : http://www.developpez.net/forums/sho...isation+images

    j'ai donc changé mon code pour celui-ci :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
       image_temp = GraphicsUtil.toCompatibleImage(ImageIO.read(new File(this.imagePath)));
    Le problème est toujours le même.
    J'ai aussi pensé à utiliser des SoftRefeferences sur les images mais cette solution, complexe à mettre en oeuvre compte tenu de mon expérience et de la richesse de l'application, n'a pas abouti (~450 classes tout de même).

    Bref je sollicite votre aide pour m'aider à diminuer l'espace mémoire occupée par les images dans la JVM.
    D'avance merci et je suis prêt à donner des infos complémentaires voire des extraits de code.

    [edit] J'édite pour poser une petite question : pour étudier plus en profondeur l'application, je souhaiterais voir à un instant t, pendant que mon application tourne, les variables instanciées et leur valeur. Quelle fonctionnalité (ou plugin) de Netbeans ou Eclipse me permettrait de faire cela s'il vous plait? [/edit]

  2. #2
    Membre confirmé

    Profil pro
    Inscrit en
    Novembre 2005
    Messages
    159
    Détails du profil
    Informations personnelles :
    Âge : 41
    Localisation : France, Ille et Vilaine (Bretagne)

    Informations forums :
    Inscription : Novembre 2005
    Messages : 159
    Points : 467
    Points
    467
    Par défaut
    J'édite pour poser une petite question : pour étudier plus en profondeur l'application, je souhaiterais voir à un instant t, pendant que mon application tourne, les variables instanciées et leur valeur. Quelle fonctionnalité (ou plugin) de Netbeans ou Eclipse me permettrait de faire cela s'il vous plait?
    Avec NetBeans 5.5 tu peux utiliser le debugger qui te permet définir des points d'arrêt et de connaître les instances.

  3. #3
    Membre du Club
    Profil pro
    Inscrit en
    Avril 2007
    Messages
    64
    Détails du profil
    Informations personnelles :
    Âge : 39
    Localisation : France, Puy de Dôme (Auvergne)

    Informations forums :
    Inscription : Avril 2007
    Messages : 64
    Points : 58
    Points
    58
    Par défaut
    Je te remercie yannart pour cette réponse, et je remonte par la même ce post pour voir si personne ne peut m'aider sur le problème principal d'occupation mémoire de mes images.
    Je réitère : merci d'avance ^^

  4. #4
    Membre éclairé
    Profil pro
    Inscrit en
    Février 2007
    Messages
    572
    Détails du profil
    Informations personnelles :
    Localisation : France, Ille et Vilaine (Bretagne)

    Informations forums :
    Inscription : Février 2007
    Messages : 572
    Points : 675
    Points
    675
    Par défaut
    C'est normal que les images occupent moins de place sur le disque qu'en memoire. Sur le disque les images sont compressées. En mémoire, elles sont decompressées, ce qui veut dire que chaque pixel de l'image occupe de la mémoire.
    Un pixel occupe en general 4 octets (l'affichage est sur la plupart des platformes en truecolor 32 bits/pixel). Donc une image de 1000x1000 occupe 4Mo en mémoire, quelque soit son contenu.
    Sur le disque, ca depend de son contenu. Une image qui n'est en fait qu'un rectangle uniforme ne prendra que qqs Ko sur le disque une fois compressée.
    Ca n'est pas spécifique au java. Dans n'importe quel langage, tu auras le meme probleme.

    Par contre, puisqu'une image prend de la mémoire, il faut faire attention a bien liberer toutes les references sur l'image quand tu n'en as plus besoin, pour que le gc puisse recuperer la memoire

  5. #5
    Membre habitué
    Homme Profil pro
    Consultant informatique
    Inscrit en
    Mars 2004
    Messages
    102
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 54
    Localisation : France, Hauts de Seine (Île de France)

    Informations professionnelles :
    Activité : Consultant informatique
    Secteur : Finance

    Informations forums :
    Inscription : Mars 2004
    Messages : 102
    Points : 156
    Points
    156
    Par défaut
    Bonjour,
    j'ai eu la même problématique que toi puisque j'ai eu à développer un logiciel d'archivage et de gestion d'images en java.
    La solution que j'ai retenue est de redefinir la class BufferedImage en surchargeant les méthodes concernant les rasters, car c'est dans un raster qu'est stocké un tableau d'octets ou d'entiers contenant les pixels de ton image.
    Je peux alors gérer ces tableaux dans un pool de tableaux ( et tant pis pour sun qui recommande de ne pas le faire ).
    Certains "ImageReader" permettent de passer en paramètre une image créée par l'utilisateur, image qui va être mise à jour avec les données contenues dans le fichier .jpeg ou .png. J'utilise cela pour créer ma propre image avec un tableau d'entiers alloué à partir d'un des pools.
    Dans le finalize de ma classe, je désalloue alors le tableau.
    Evidemment, ce finalize n'est appelé que si l'objet n'est plus référencé. Donc, lorsque j'affiche une image, je relis le fichier dans lequel elle est stockée et l'objet image appartient à un autre objet qui contient les références de l'image ( nom du fichier ) et possède une soft référence sur l'objet image.
    Lorsque je veux afficher l'image, je teste si la soft référence est nulle : si oui, je recrée l'image, sinon, j'utilise celle qui existe.

    C'est un peu compliqué, cela va te prendre du temps à faire tout cela mais cela marche.
    A+
    H.

  6. #6
    Membre du Club
    Profil pro
    Inscrit en
    Avril 2007
    Messages
    64
    Détails du profil
    Informations personnelles :
    Âge : 39
    Localisation : France, Puy de Dôme (Auvergne)

    Informations forums :
    Inscription : Avril 2007
    Messages : 64
    Points : 58
    Points
    58
    Par défaut
    Merci pour les deux dernières réponses qui m'ont bien éclaire, d'une part sur la réalité d'une image java...moi qui essayait de charger (pour test) une image de 8000 x 4000 je ne me rendais pas compte qu'en mémoire elle occuperait...128Mo.

    J'ai du mal à saisir toutes les notions que tu as énoncé Hedes mais je vois au moins de quel coté chercher. Si tu as un quelconque lien sur ce genre de manip (pool de tableaux d'octets définissants les images, tuto sur les raster (j'ai lu la javadoc quand même), etc je suis preneur.

    En tout cas merci pour ces réponses c'est très instructif.

  7. #7
    Membre habitué
    Homme Profil pro
    Consultant informatique
    Inscrit en
    Mars 2004
    Messages
    102
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 54
    Localisation : France, Hauts de Seine (Île de France)

    Informations professionnelles :
    Activité : Consultant informatique
    Secteur : Finance

    Informations forums :
    Inscription : Mars 2004
    Messages : 102
    Points : 156
    Points
    156
    Par défaut
    Non pas de tuto là dessus : tout cela a été développé au sein de ma société.

    Si tu as des images aussi grosses, alors il faut que tu couples la solution que je t'ai présentée avec la gestion des tiles.
    L'idée est de ne pas charger l'image d'un coup, mais de la découper en blocs ( un bloc = un tile ) chaque bloc étant vu comme une image. Va voir les méthodes getNumXTiles() et getNumYTiles() de BufferedImage ou de RenderedImage.

    Attention, cela peut être lent à l'affichage, et, par ailleurs, il faut faire attention lorsqu'on utilises les opérations ( rotation, mirroir ) sur une image.
    A+

  8. #8
    Membre du Club
    Profil pro
    Inscrit en
    Avril 2007
    Messages
    64
    Détails du profil
    Informations personnelles :
    Âge : 39
    Localisation : France, Puy de Dôme (Auvergne)

    Informations forums :
    Inscription : Avril 2007
    Messages : 64
    Points : 58
    Points
    58
    Par défaut
    Non non j'ai utilisé des grosses images en méconnaissance de ce qu'elles pouvaient représenter en mémoire, juste pour voir les limites de l'application.
    En pratique, quelques images de résolution 800x600 ou 1024x748 et la plupart ne faisant que quelques pixel...genre 30x30 mais en grande quantité (quelques centaines).
    Le fait est qu'à un instant t on n'a pas besoin d'avoir toutes les images de chargées, la solution est de gérer un cache d'objets grâce aux soft references, là où j'ai encore du mal à saisir c'est sur l'utilisation de BufferedImage avec ses méthodes raster, puisque j'utilisais jusqu'alors la classe Image img (instanciée par ImageIo(File...) ).

  9. #9
    Membre habitué
    Homme Profil pro
    Consultant informatique
    Inscrit en
    Mars 2004
    Messages
    102
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 54
    Localisation : France, Hauts de Seine (Île de France)

    Informations professionnelles :
    Activité : Consultant informatique
    Secteur : Finance

    Informations forums :
    Inscription : Mars 2004
    Messages : 102
    Points : 156
    Points
    156
    Par défaut
    BufferedImage est utilisé par javax.imageio.ImageReader pour lire une image.
    Va voir javax.imageio.ImageIO.getImageReadersByFormatName(String formatName) qui va te retouner une liste d'ImageReader.
    Tu vas alors appeler read(0, ImageReadParam) et dans ImageReadParam, tu auras placé l'image que tu as précédemment créée avec setDestination.

    Pour résumer :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
     
    ImageReader ir = ImageIO.getImageReadersByFormatName(fileExtension).next();
    int w = ir.getWidth(0);
    int h = ir.getHeight(0);
    ImageTypeSpecifier its = ir.getRawImageType(0);
    BufferedImage bi = createMyBufferedImage(w,r,its);
    ImageReadParam param = new ImageReadParam ();
    param.setDestination(bi);
    bi = ir.read(0,param);
    le plus dur est évidemment d'écrire createMyBufferedImage...

Discussions similaires

  1. remplacer les boutons par des images
    Par sotfage dans le forum Interfaces Graphiques en Java
    Réponses: 2
    Dernier message: 18/06/2007, 17h41
  2. [Tableaux] remplacer du texte par des images
    Par elti69 dans le forum Langage
    Réponses: 2
    Dernier message: 12/06/2007, 10h14
  3. Substitution de textes par des images dans Word
    Par Unusual dans le forum Delphi
    Réponses: 2
    Dernier message: 19/03/2007, 17h31
  4. Réponses: 3
    Dernier message: 09/03/2007, 14h32
  5. Réponses: 9
    Dernier message: 26/08/2006, 19h35

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