Come ridimensionare una bitmap in Android?


337

Ho una bitmap presa da una stringa Base64 dal mio database remoto, ( encodedImageè la stringa che rappresenta l'immagine con 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 è il mio ImageView

Ok, ma devo ridimensionare questa immagine prima di mostrarla sul ImageViewmio layout. Devo ridimensionarlo a 120x120.

Qualcuno può dirmi il codice per ridimensionarlo?

Gli esempi che ho trovato non possono essere applicati a una stringa base64 ottenuta bitmap.


Risposte:


550

Modificare:

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

Per:

Bitmap b = BitmapFactory.decodeByteArray(imageAsBytes, 0, imageAsBytes.length)
profileImage.setImageBitmap(Bitmap.createScaledBitmap(b, 120, 120, false));

supponiamo di avere un'immagine ad alta risoluzione di 1200x1200 e quando la visualizzi, sarà piena nella visualizzazione dell'immagine. Se lo ridimensiono, dico 75% e lo schermo è in modo tale da visualizzare l'immagine ridimensionata anche completamente in imageview, cosa si dovrebbe fare per tali schermi?
jxgn,

5
CreateScaledBitmap genera un'eccezione di memoria insufficiente sul mio Galaxy Tab2, il che è molto strano per me poiché c'è molta memoria e nessuna altra app particolare è in esecuzione. La soluzione Matrix funziona però.
Ludovic,

29
cosa succede se vogliamo salvare le proporzioni ??
Bugs Happen

3
Che dire del ridimensionamento dpi per questo? Penso che la bitmap in scala dovrebbe essere basata sull'altezza e sulla larghezza dello schermo del dispositivo?
Doug Ray,

2
L'uso di Bitmap.createScaledBitmap () per ridimensionare un'immagine di oltre la metà della dimensione originale, può produrre artefatti di aliasing. Puoi dare un'occhiata a un post che ho scritto dove propongo alcune alternative e confrontare qualità e prestazioni.
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: come suggerito da @aveschini, ho aggiunto bm.recycle();delle perdite di memoria. Si noti che nel caso in cui si utilizzi l'oggetto precedente per altri scopi, gestirlo di conseguenza.


6
Ho provato sia bitmap.createscaledbitmap che questo approccio a matrice. Trovo che l'immagine sia molto più chiara con l'approccio a matrice. Non so se sia comune o solo perché sto usando un simulatore anziché un telefono. Solo un suggerimento per qualcuno che incontra gli stessi problemi come me.
Anson Yao,

2
anche qui devi aggiungere bm.recycle () per prestazioni di memoria molto migliori
aveschini

2
Grazie per la soluzione, ma sarebbe meglio se i parametri fossero riordinati; public Bitmap getResizedBitmap(Bitmap bm, int newWidth, int newHeight). Ho passato un sacco di tempo a capirlo. ; P
Attacco

1
Nota che l'importazione corretta per Matrix è android.graphics.Matrix.
Lev

12
È lo stesso che chiamare Bitmap.createScaledBitmap (). Vedi android.googlesource.com/platform/frameworks/base/+/refs/heads/…
BamsBamx

122

Se disponi già di una bitmap, puoi utilizzare il seguente codice per ridimensionare:

Bitmap originalBitmap = <original initialization>;
Bitmap resizedBitmap = Bitmap.createScaledBitmap(
    originalBitmap, newWidth, newHeight, false);

1
@beginner se ridimensioni l'immagine, potresti ridimensionare in base a dimensioni diverse che trasformano la bitmap in proporzioni errate o rimuovono alcune delle informazioni bitmap.
ZenBalance,

Ho provato a ridimensionare la bitmap in base alle proporzioni, ma ho riscontrato questo errore. Causato da: java.lang.RuntimeException: Canvas: tentativo di utilizzare una bitmap riciclata android.graphics.Bitmap@2291dd13
principiante

@beginner ogni volta che ridimensioni la bitmap, a seconda di ciò che stai facendo, di solito dovrai creare una copia di nuova dimensione, piuttosto che ridimensionare la bitmap esistente (poiché in questo caso sembra che il riferimento alla bitmap fosse già riciclato in memoria).
ZenBalance,

1
corretto .. l'ho provato e ora funziona correttamente. grazie
principiante

39

Scala in base alle proporzioni :

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

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

Per usare l'altezza come base anziché la larghezza, cambia in:

int height = 480;
int width = Math.round(height * aspectRatio);

24

Ridimensionare una bitmap con una dimensione e una larghezza massime di destinazione, mantenendo le proporzioni:

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);

7

prova questo codice:

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

Spero sia utile


7

Qualcuno ha chiesto come mantenere le proporzioni in questa situazione:

Calcola il fattore che stai utilizzando per il ridimensionamento e utilizzalo per entrambe le dimensioni. Diciamo che vuoi che un'immagine sia il 20% dello schermo in altezza

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);

per ottenere la risoluzione dello schermo hai questa soluzione: Ottieni le dimensioni dello schermo in pixel


3

Prova questo: questa funzione ridimensiona una bitmap in modo proporzionale. Quando l'ultimo parametro è impostato su "X" newDimensionXorYviene trattato come nuova larghezza e quando impostato su "Y" una nuova altezza.

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;
}

3
profileImage.setImageBitmap(
    Bitmap.createScaledBitmap(
        BitmapFactory.decodeByteArray(imageAsBytes, 0, imageAsBytes.length), 
        80, 80, false
    )
);

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;
    }

per me ha funzionato dopo un po 'di riscrittura float eccessoSizeRatio = larghezza> altezza? (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;
    }


2

Ridimensionamento bitmap basato su qualsiasi dimensione di visualizzazione

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;
}

1

Sebbene la risposta accettata sia corretta, non viene ridimensionata Bitmapmantenendo lo stesso rapporto di aspetto . Se stai cercando un metodo per ridimensionare Bitmapmantenendo le stesse proporzioni, puoi utilizzare la seguente funzione di utilità. I dettagli di utilizzo e la spiegazione della funzione sono presenti a questo link .

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;
       }
   }

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)
  }

0

Mantenere le proporzioni,

  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;
    }
}
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.