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

Android Discussion :

Fuite de mémoire dû au rescaling d'image


Sujet :

Android

  1. #1
    Membre chevronné
    Profil pro
    Inscrit en
    Juillet 2012
    Messages
    476
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juillet 2012
    Messages : 476
    Par défaut Fuite de mémoire dû au rescaling d'image
    Bonjour,

    J'ai plusieurs petites questions dans cette discussion.

    J'ai voulu redimensionner des images pour qu'elles gardent toutes les mêmes proportions. Ainsi, une flèche aura la meme taille, qu'elle soit issue de grande ou d'une petite image. J'ai suivi cette solution qui marche très bien.

    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
    private void scaleImage()
    {
        // Get the ImageView and its bitmap
        ImageView view = (ImageView) findViewById(R.id.image_box);
        Drawable drawing = view.getDrawable();
        if (drawing == null) {
            return; // Checking for null & return, as suggested in comments
        }
        Bitmap bitmap = ((BitmapDrawable)drawing).getBitmap();
     
        // Get current dimensions AND the desired bounding box
        int width = bitmap.getWidth();
        int height = bitmap.getHeight();
        int bounding = dpToPx(250);
     
        // Determine how much to scale: the dimension requiring less scaling is
        // closer to the its side. This way the image always stays inside your
        // bounding box AND either x/y axis touches it.  
        float xScale = ((float) bounding) / width;
        float yScale = ((float) bounding) / height;
        float scale = (xScale <= yScale) ? xScale : yScale;
     
        // Create a matrix for the scaling and add the scaling data
        Matrix matrix = new Matrix();
        matrix.postScale(scale, scale);
     
        // Create a new bitmap and convert it to a format understood by the ImageView 
        Bitmap scaledBitmap = Bitmap.createBitmap(bitmap, 0, 0, width, height, matrix, true);
        width = scaledBitmap.getWidth(); // re-use
        height = scaledBitmap.getHeight(); // re-use
        BitmapDrawable result = new BitmapDrawable(scaledBitmap);
     
        // Apply the scaled bitmap
        view.setImageDrawable(result);
     
        // Now change ImageView's dimensions to match the scaled image
        LinearLayout.LayoutParams params = (LinearLayout.LayoutParams) view.getLayoutParams(); 
        params.width = width;
        params.height = height;
        view.setLayoutParams(params);
    }
     
    private int dpToPx(int dp)
    {
        float density = getApplicationContext().getResources().getDisplayMetrics().density;
        return Math.round((float)dp * density);
    }
    Mais après un grand nombre de manip de la listview, je peux avoir une OutOfMemoryError. J'ai vérifié le heap dans le DDMS et l'allocation augmente bien dès qu'on manipule la listview. Comme lu ailleurs, j'ai ajouté des bitmap.recycle(), mais ca a surtout mené à une erreur : "cannot draw recycled bitmaps".

    Donc 1ere question, auriez vous une proposition pour régler ce problème de mémoire ?

    J'ai aussi suivi le tuto officiel, mais là je dois dire que j'ai un peu de mal, et surtout, l'exemple téléchargé n'est pas du tout le meme que celui expliqué. D'ou ma 2e question : auriez vous le dossier d'exemple prévu par Google, avec les meme méthodes qu'ils expliquent ?

    C'est un problème mineur, mais j'aimerai bien lecomprendre correctement.
    Merci

  2. #2
    Modérateur
    Avatar de Hizin
    Homme Profil pro
    Développeur mobile
    Inscrit en
    Février 2010
    Messages
    2 180
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 36
    Localisation : France

    Informations professionnelles :
    Activité : Développeur mobile

    Informations forums :
    Inscription : Février 2010
    Messages : 2 180
    Par défaut
    Si tu as pris le code de SO tel quel, il est normal que ta mémoire explose.

    Je te suggère de modifier ainsi :
    Code java : 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
    private void scaleImage()
    {
        // Get the ImageView and its bitmap
        ImageView view = (ImageView) findViewById(R.id.image_box);
        Drawable drawing = view.getDrawable();
        if (drawing == null) {
            return; // Checking for null & return, as suggested in comments
        }
        Bitmap bitmap = ((BitmapDrawable)drawing).getBitmap();
     
        // Get current dimensions AND the desired bounding box
        int width = bitmap.getWidth();
        int height = bitmap.getHeight();
        int bounding = dpToPx(250);
        Log.i("Test", "original width = " + Integer.toString(width));
        Log.i("Test", "original height = " + Integer.toString(height));
        Log.i("Test", "bounding = " + Integer.toString(bounding));
     
        // Determine how much to scale: the dimension requiring less scaling is
        // closer to the its side. This way the image always stays inside your
        // bounding box AND either x/y axis touches it.  
        float xScale = ((float) bounding) / width;
        float yScale = ((float) bounding) / height;
        float scale = (xScale <= yScale) ? xScale : yScale;
        Log.i("Test", "xScale = " + Float.toString(xScale));
        Log.i("Test", "yScale = " + Float.toString(yScale));
        Log.i("Test", "scale = " + Float.toString(scale));
     
        // Create a matrix for the scaling and add the scaling data
        Matrix matrix = new Matrix();
        matrix.postScale(scale, scale);
     
        // Create a new bitmap and convert it to a format understood by the ImageView 
        Bitmap scaledBitmap = Bitmap.createBitmap(bitmap, 0, 0, width, height, matrix, true);
        width = scaledBitmap.getWidth(); // re-use
        height = scaledBitmap.getHeight(); // re-use
        BitmapDrawable result = new BitmapDrawable(scaledBitmap);
        Log.i("Test", "scaled width = " + Integer.toString(width));
        Log.i("Test", "scaled height = " + Integer.toString(height));
     
        // Apply the scaled bitmap
        view.setImageDrawable(result);
        bitmap.recycle();
        scaledBitmap.recycle(); // peut faire planter
     
        // Now change ImageView's dimensions to match the scaled image
        LinearLayout.LayoutParams params = (LinearLayout.LayoutParams) view.getLayoutParams(); 
        params.width = width;
        params.height = height;
        view.setLayoutParams(params);
     
        Log.i("Test", "done");
    }

    De plus, en voyant ce code, j'ai l'impression que l'on part d'une ImageView dont l'image a déjà été attribuée, puis on part de celle-ci pour changer la taille.
    Il serait beaucoup plus logique de faire la transformation dès réception de l'image initiale et avant son attribution à l'ImageView, non ?
    Par contre, au vu du code, il est possible que ça pose des soucis de dessins lors des calculs de tailles, à voir.
    C'est Android, PAS Androïd, ou Androïde didiou !
    Le premier est un OS, le second est la mauvaise orthographe du troisième, un mot français désignant un robot à forme humaine.

    Membre du comité contre la phrase "ça marche PAS" en titre et/ou explication de problème.

    N'oubliez pas de consulter les FAQ Android et les cours et tutoriels Android

  3. #3
    Membre chevronné
    Profil pro
    Inscrit en
    Juillet 2012
    Messages
    476
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juillet 2012
    Messages : 476
    Par défaut
    Je l'avais fait mettre des recycle, mais ca faisait planter l'appli.

    Je sais que c'est bizarre de récupérer le drawable l'imageview puis le transformer en bitmap.... seulement la seule méthode que j'ai trouvé qui permet de conserver les memes dimensions dans toutes les images.

    J'ai regardé les exemples officiels, mais ca m'a surtout embrouillé.

Discussions similaires

  1. Image de fond dans CSS => fuite de mémoire
    Par troumad dans le forum GTK+ avec C & C++
    Réponses: 9
    Dernier message: 25/02/2014, 09h29
  2. Fuite de mémoire sur des images
    Par soybenito dans le forum OpenCV
    Réponses: 3
    Dernier message: 24/06/2009, 16h03
  3. fuite de mémoire
    Par mamag dans le forum MFC
    Réponses: 17
    Dernier message: 19/08/2005, 10h42
  4. Fuite de mémoire en utilisant le template list
    Par schtroumpf_farceur dans le forum Langage
    Réponses: 9
    Dernier message: 18/07/2005, 20h44
  5. Réponses: 8
    Dernier message: 17/10/2002, 12h52

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