Comment redimensionner un bitmap dans Android?

337

J'ai une image bitmap prise d'une chaîne Base64 de ma base de données distante, ( encodedImageest la chaîne représentant l'image avec Base64):

profileImage = (ImageView)findViewById(R.id.profileImage);

byte[] imageAsBytes=null;
try {
    imageAsBytes = Base64.decode(encodedImage.getBytes());
} catch (IOException e) {e.printStackTrace();}

profileImage.setImageBitmap(
    BitmapFactory.decodeByteArray(imageAsBytes, 0, imageAsBytes.length)
);

profileImage est mon ImageView

D'accord, mais je dois redimensionner cette image avant de l'afficher sur ImageViewma mise en page. Je dois le redimensionner à 120x120.

Quelqu'un peut-il me dire le code pour le redimensionner?

Les exemples que j'ai trouvés n'ont pas pu être appliqués à un bitmap obtenu en chaîne base64.

NullPointerException
la source
Duplication possible de Resize Bitmap dans Android
Sagar Pilkhwal

Réponses:

550

Changement:

profileImage.setImageBitmap(
    BitmapFactory.decodeByteArray(imageAsBytes, 0, imageAsBytes.length)

À:

Bitmap b = BitmapFactory.decodeByteArray(imageAsBytes, 0, imageAsBytes.length)
profileImage.setImageBitmap(Bitmap.createScaledBitmap(b, 120, 120, false));
user432209
la source
supposons que vous ayez une image de grande résolution, disons 1200x1200 et lorsque vous l'afficherez, elle sera pleine dans l'image. Si je la réduis, disons 75% et que l'écran affiche de manière à ce que l'image à l'échelle soit également entièrement affichée, que faire pour ces écrans?
jxgn
5
Le createScaledBitmap lève une exception de mémoire insuffisante sur ma Galaxy Tab2, ce qui est très étrange pour moi car il y a beaucoup de mémoire et aucune autre application particulière n'est en cours d'exécution. La solution Matrix fonctionne cependant.
Ludovic
29
Et si nous voulons économiser les proportions ??
Bugs Happen
3
Qu'en est-il de la mise à l'échelle dpi pour cela? Je pense que le bitmap à l'échelle doit être basé sur la hauteur et la largeur de l'écran de l'appareil?
Doug Ray
2
L'utilisation de Bitmap.createScaledBitmap () pour réduire l'échelle d'une image de plus de la moitié de la taille d'origine, peut produire des artefacts d'alias. Vous pouvez jeter un oeil à un article que j'ai écrit où je propose des alternatives et comparer la qualité et les performances.
Petrakeas
288
import android.graphics.Matrix
public Bitmap getResizedBitmap(Bitmap bm, int newWidth, int newHeight) {
    int width = bm.getWidth();
    int height = bm.getHeight();
    float scaleWidth = ((float) newWidth) / width;
    float scaleHeight = ((float) newHeight) / height;
    // CREATE A MATRIX FOR THE MANIPULATION
    Matrix matrix = new Matrix();
    // RESIZE THE BIT MAP
    matrix.postScale(scaleWidth, scaleHeight);

    // "RECREATE" THE NEW BITMAP
    Bitmap resizedBitmap = Bitmap.createBitmap(
        bm, 0, 0, width, height, matrix, false);
    bm.recycle();
    return resizedBitmap;
}

EDIT: comme suggéré par @aveschini, j'ai ajouté bm.recycle();pour les fuites de mémoire. Veuillez noter que si vous utilisez l'objet précédent à d'autres fins, gérez-le en conséquence.

jeet.chanchawat
la source
6
J'ai essayé à la fois bitmap.createscaledbitmap et cette approche matricielle. Je trouve que l'image est beaucoup plus claire avec l'approche matricielle. Je ne sais pas si c'est courant ou simplement parce que j'utilise un simulateur au lieu d'un téléphone. Juste un indice pour quelqu'un qui rencontre le même problème que moi.
Anson Yao
2
ici aussi, vous devez ajouter bm.recycle () pour de bien meilleures performances de mémoire
aveschini
2
Merci pour la solution, mais il serait préférable que les paramètres soient réorganisés; public Bitmap getResizedBitmap(Bitmap bm, int newWidth, int newHeight). J'ai passé un temps fou à le comprendre. ; P
Attacktive
1
Notez que l'importation correcte pour Matrix est android.graphics.Matrix.
Lev
12
Cela revient à appeler Bitmap.createScaledBitmap (). Voir android.googlesource.com/platform/frameworks/base/+/refs/heads/…
BamsBamx
122

Si vous avez déjà un bitmap, vous pouvez utiliser le code suivant pour redimensionner:

Bitmap originalBitmap = <original initialization>;
Bitmap resizedBitmap = Bitmap.createScaledBitmap(
    originalBitmap, newWidth, newHeight, false);
ZenBalance
la source
1
@beginner si vous redimensionnez l'image, vous pouvez mettre à l'échelle en fonction de différentes dimensions qui transforment le bitmap en proportions incorrectes ou suppriment certaines des informations bitmap.
ZenBalance
J'ai essayé de redimensionner le bitmap en fonction des proportions, mais j'ai ensuite eu cette erreur. Causé par: java.lang.RuntimeException: Canvas: essayer d'utiliser un bitmap recyclé android.graphics.Bitmap@2291dd13
débutant
@beginner chaque fois que vous redimensionnez le bitmap, en fonction de ce que vous faites, vous devrez généralement créer une copie qui est une nouvelle taille, plutôt que de redimensionner le bitmap existant (car dans ce cas, il semble que la référence au bitmap était déjà recyclé en mémoire).
ZenBalance
1
correct .. je l'ai essayé et cela fonctionne correctement maintenant. merci
débutant
39

Échelle basée sur le rapport hauteur / largeur :

float aspectRatio = yourSelectedImage.getWidth() / 
    (float) yourSelectedImage.getHeight();
int width = 480;
int height = Math.round(width / aspectRatio);

yourSelectedImage = Bitmap.createScaledBitmap(
    yourSelectedImage, width, height, false);

Pour utiliser la hauteur comme base à l'intérieur de la largeur, changez en:

int height = 480;
int width = Math.round(height * aspectRatio);
sagits
la source
24

Mettez à l'échelle une image bitmap avec une taille et une largeur maximales cibles, tout en conservant les proportions:

int maxHeight = 2000;
int maxWidth = 2000;    
float scale = Math.min(((float)maxHeight / bitmap.getWidth()), ((float)maxWidth / bitmap.getHeight()));

Matrix matrix = new Matrix();
matrix.postScale(scale, scale);

bitmap = Bitmap.createBitmap(bitmap, 0, 0, bitmap.getWidth(), bitmap.getHeight(), matrix, true);
Kevin
la source
7

essayez ce code:

BitmapDrawable drawable = (BitmapDrawable) imgview.getDrawable();
Bitmap bmp = drawable.getBitmap();
Bitmap b = Bitmap.createScaledBitmap(bmp, 120, 120, false);

J'espère que c'est utile.

Ravi Makvana
la source
7

Quelqu'un a demandé comment conserver les proportions dans cette situation:

Calculez le facteur que vous utilisez pour la mise à l'échelle et utilisez-le pour les deux dimensions. Disons que vous voulez qu'une image soit à 20% de la hauteur de l'écran

int scaleToUse = 20; // this will be our percentage
Bitmap bmp = BitmapFactory.decodeResource(
    context.getResources(), R.drawable.mypng);
int sizeY = screenResolution.y * scaleToUse / 100;
int sizeX = bmp.getWidth() * sizeY / bmp.getHeight();
Bitmap scaled = Bitmap.createScaledBitmap(bmp, sizeX, sizeY, false);

pour obtenir la résolution d'écran, vous avez cette solution: Obtenez les dimensions de l'écran en pixels

Taochok
la source
3

Essayez ceci: cette fonction redimensionne un bitmap proportionnellement. Lorsque le dernier paramètre est défini sur "X", il newDimensionXorYest traité comme une nouvelle largeur s et lorsqu'il est défini sur "Y" une nouvelle hauteur.

public Bitmap getProportionalBitmap(Bitmap bitmap, 
                                    int newDimensionXorY, 
                                    String XorY) {
    if (bitmap == null) {
        return null;
    }

    float xyRatio = 0;
    int newWidth = 0;
    int newHeight = 0;

    if (XorY.toLowerCase().equals("x")) {
        xyRatio = (float) newDimensionXorY / bitmap.getWidth();
        newHeight = (int) (bitmap.getHeight() * xyRatio);
        bitmap = Bitmap.createScaledBitmap(
            bitmap, newDimensionXorY, newHeight, true);
    } else if (XorY.toLowerCase().equals("y")) {
        xyRatio = (float) newDimensionXorY / bitmap.getHeight();
        newWidth = (int) (bitmap.getWidth() * xyRatio);
        bitmap = Bitmap.createScaledBitmap(
            bitmap, newWidth, newDimensionXorY, true);
    }
    return bitmap;
}
user2288580
la source
3
profileImage.setImageBitmap(
    Bitmap.createScaledBitmap(
        BitmapFactory.decodeByteArray(imageAsBytes, 0, imageAsBytes.length), 
        80, 80, false
    )
);
Rajkamal
la source
3
  public Bitmap scaleBitmap(Bitmap mBitmap) {
        int ScaleSize = 250;//max Height or width to Scale
        int width = mBitmap.getWidth();
        int height = mBitmap.getHeight();
        float excessSizeRatio = width > height ? width / ScaleSize : height / ScaleSize;
         Bitmap bitmap = Bitmap.createBitmap(
                mBitmap, 0, 0,(int) (width/excessSizeRatio),(int) (height/excessSizeRatio));
        //mBitmap.recycle(); if you are not using mBitmap Obj
        return bitmap;
    }
Sandeep P
la source
pour moi, cela a fonctionné après un peu de retypage float excessSizeRatio = largeur> hauteur? (float) ((float) width / (float) ScaleSize): (float) ((float) height / (float) ScaleSize);
Csabi
3
public static Bitmap resizeBitmapByScale(
            Bitmap bitmap, float scale, boolean recycle) {
        int width = Math.round(bitmap.getWidth() * scale);
        int height = Math.round(bitmap.getHeight() * scale);
        if (width == bitmap.getWidth()
                && height == bitmap.getHeight()) return bitmap;
        Bitmap target = Bitmap.createBitmap(width, height, getConfig(bitmap));
        Canvas canvas = new Canvas(target);
        canvas.scale(scale, scale);
        Paint paint = new Paint(Paint.FILTER_BITMAP_FLAG | Paint.DITHER_FLAG);
        canvas.drawBitmap(bitmap, 0, 0, paint);
        if (recycle) bitmap.recycle();
        return target;
    }
    private static Bitmap.Config getConfig(Bitmap bitmap) {
        Bitmap.Config config = bitmap.getConfig();
        if (config == null) {
            config = Bitmap.Config.ARGB_8888;
        }
        return config;
    }
kakopappa
la source
2

Redimensionnement bitmap basé sur n'importe quelle taille d'affichage

public Bitmap bitmapResize(Bitmap imageBitmap) {

    Bitmap bitmap = imageBitmap;
    float heightbmp = bitmap.getHeight();
    float widthbmp = bitmap.getWidth();

    // Get Screen width
    DisplayMetrics displaymetrics = new DisplayMetrics();
    this.getWindowManager().getDefaultDisplay().getMetrics(displaymetrics);
    float height = displaymetrics.heightPixels / 3;
    float width = displaymetrics.widthPixels / 3;

    int convertHeight = (int) hight, convertWidth = (int) width;

    // higher
    if (heightbmp > height) {
        convertHeight = (int) height - 20;
        bitmap = Bitmap.createScaledBitmap(bitmap, convertWidth,
                convertHighet, true);
    }

    // wider
    if (widthbmp > width) {
        convertWidth = (int) width - 20;
        bitmap = Bitmap.createScaledBitmap(bitmap, convertWidth,
                convertHeight, true);
    }

    return bitmap;
}
Dat Nguyen Thanh
la source
1

Bien que la réponse acceptée soit correcte, elle ne se redimensionne pas Bitmapen conservant le même rapport hauteur / largeur . Si vous recherchez une méthode pour redimensionner Bitmapen conservant le même rapport d'aspect, vous pouvez utiliser la fonction utilitaire suivante. Les détails d'utilisation et l'explication de la fonction sont présents sur ce lien .

public static Bitmap resizeBitmap(Bitmap source, int maxLength) {
       try {
           if (source.getHeight() >= source.getWidth()) {
               int targetHeight = maxLength;
               if (source.getHeight() <= targetHeight) { // if image already smaller than the required height
                   return source;
               }

               double aspectRatio = (double) source.getWidth() / (double) source.getHeight();
               int targetWidth = (int) (targetHeight * aspectRatio);

               Bitmap result = Bitmap.createScaledBitmap(source, targetWidth, targetHeight, false);
               if (result != source) {
               }
               return result;
           } else {
               int targetWidth = maxLength;

               if (source.getWidth() <= targetWidth) { // if image already smaller than the required height
                   return source;
               }

               double aspectRatio = ((double) source.getHeight()) / ((double) source.getWidth());
               int targetHeight = (int) (targetWidth * aspectRatio);

               Bitmap result = Bitmap.createScaledBitmap(source, targetWidth, targetHeight, false);
               if (result != source) {
               }
               return result;

           }
       }
       catch (Exception e)
       {
           return source;
       }
   }
Asad Ali Choudhry
la source
0
/**
 * Kotlin method for Bitmap scaling
 * @param bitmap the bitmap to be scaled
 * @param pixel  the target pixel size
 * @param width  the width
 * @param height the height
 * @param max    the max(height, width)
 * @return the scaled bitmap
 */
fun scaleBitmap(bitmap:Bitmap, pixel:Float, width:Int, height:Int, max:Int):Bitmap {
    val scale = px / max
    val h = Math.round(scale * height)
    val w = Math.round(scale * width)
    return Bitmap.createScaledBitmap(bitmap, w, h, true)
  }
Faakhir
la source
0

Garder le rapport hauteur / largeur,

  public Bitmap resizeBitmap(Bitmap source, int width,int height) {
    if(source.getHeight() == height && source.getWidth() == width) return source;
    int maxLength=Math.min(width,height);
    try {
        source=source.copy(source.getConfig(),true);
        if (source.getHeight() <= source.getWidth()) {
            if (source.getHeight() <= maxLength) { // if image already smaller than the required height
                return source;
            }

            double aspectRatio = (double) source.getWidth() / (double) source.getHeight();
            int targetWidth = (int) (maxLength * aspectRatio);

            return Bitmap.createScaledBitmap(source, targetWidth, maxLength, false);
        } else {

            if (source.getWidth() <= maxLength) { // if image already smaller than the required height
                return source;
            }

            double aspectRatio = ((double) source.getHeight()) / ((double) source.getWidth());
            int targetHeight = (int) (maxLength * aspectRatio);

            return Bitmap.createScaledBitmap(source, maxLength, targetHeight, false);

        }
    }
    catch (Exception e)
    {
        return source;
    }
}
Tarasantan
la source