Como redimensionar um bitmap no Android?

337

Eu tenho um bitmap obtido de uma String Base64 do meu banco de dados remoto ( encodedImageé a string que representa a imagem com 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 é o meu ImageView

Ok, mas preciso redimensionar esta imagem antes de mostrá-la no ImageViewmeu layout. Eu tenho que redimensioná-lo para 120x120.

Alguém pode me dizer o código para redimensioná-lo?

Os exemplos que encontrei não puderam ser aplicados a um bitmap obtido da string base64.

Null Pointer Exception
fonte
Possível duplicado de Resize Bitmap no Android
Sagar Pilkhwal

Respostas:

550

Mudança:

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

Para:

Bitmap b = BitmapFactory.decodeByteArray(imageAsBytes, 0, imageAsBytes.length)
profileImage.setImageBitmap(Bitmap.createScaledBitmap(b, 120, 120, false));
user432209
fonte
suponha que você tenha uma imagem de alta resolução, digamos 1200x1200, e quando você a exibir, ela estará cheia na visualização de imagens. Se reduzi-lo, digamos 75%, e a tela é para exibir também a imagem em escala na visualização de imagens, o que deve ser feito para essas telas?
jxgn
5
O createScaledBitmap lança uma exceção de falta de memória no meu Galaxy Tab2, o que é muito estranho para mim, pois há muita memória e nenhum outro aplicativo em particular está sendo executado. A solução Matrix funciona embora.
Ludovic
29
e se quisermos salvar a proporção?
Erros acontecem
3
E o dimensionamento de dpi para isso? Eu acho que o bitmap em escala deve se basear na altura e largura da tela do dispositivo?
Doug Ray
2
O uso de Bitmap.createScaledBitmap () para reduzir a escala de uma imagem mais da metade do tamanho original, pode produzir artefatos de alias. Você pode dar uma olhada em um post que escrevi, onde proponho algumas alternativas e comparo qualidade e desempenho.
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: como sugerido por @aveschini, eu adicionei bm.recycle();para vazamentos de memória. Observe que, se você estiver usando o objeto anterior para outros fins, manipule-o de acordo.

jeet.chanchawat
fonte
6
Eu tentei o bitmap.createscaledbitmap e essa abordagem de matriz. Acho que a imagem é muito mais clara com a abordagem matricial. Não sei se é comum ou apenas porque estou usando um simulador em vez de um telefone. Apenas uma dica para alguém que encontra o mesmo problema que eu.
Anson Yao
2
aqui também você tem que adicionar bm.recycle () para muito melhor performances de memória
aveschini
2
Obrigado pela solução, mas seria melhor se os parâmetros fossem reordenados; public Bitmap getResizedBitmap(Bitmap bm, int newWidth, int newHeight). Passei muito tempo tentando descobrir. ; P
Attacktive
1
Observe que a importação correta para Matrix é android.graphics.Matrix.
Lev
12
É o mesmo que chamar Bitmap.createScaledBitmap (). Veja android.googlesource.com/platform/frameworks/base/+/refs/heads/…
BamsBamx 7/17
122

Se você já possui um bitmap, poderá usar o seguinte código para redimensionar:

Bitmap originalBitmap = <original initialization>;
Bitmap resizedBitmap = Bitmap.createScaledBitmap(
    originalBitmap, newWidth, newHeight, false);
ZenBalance
fonte
1
@ iniciante, se você redimensionar a imagem, pode ser dimensionado com base em diferentes dimensões que transformam o bitmap em proporções incorretas ou removem algumas das informações do bitmap.
ZenBalance 4/16/16
Tentei redimensionar o bitmap com base nas proporções, mas estava recebendo esse erro. Causado por: java.lang.RuntimeException: Canvas: tentando usar um bitmap reciclado android.graphics.Bitmap@2291dd13
iniciante
@beginner toda vez que você redimensionar o bitmap, dependendo do que estiver fazendo, geralmente será necessário criar uma cópia com um novo tamanho, em vez de redimensionar o bitmap existente (já que, neste caso, parece que a referência ao bitmap era já reciclado na memória).
ZenBalance
1
correto .. tentei e funciona corretamente agora. obrigado
iniciante
39

Escala com base na proporção :

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

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

Para usar a altura como base em vez da largura, mude para:

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

Escale um bitmap com um tamanho e largura máximos de destino, mantendo a proporção:

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
fonte
7

tente este código:

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

Espero que seja útil.

Ravi Makvana
fonte
7

Alguém perguntou como manter a proporção nesta situação:

Calcule o fator que você está usando para dimensionar e use-o para ambas as dimensões. Digamos que você queira que uma imagem tenha 20% da tela em altura

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

para obter a resolução da tela, você tem esta solução: Obtenha as dimensões da tela em pixels

Taochok
fonte
3

Tente o seguinte: Esta função redimensiona um bitmap proporcionalmente. Quando o último parâmetro é definido como "X", ele newDimensionXorYé tratado como nova largura e, quando definido como "Y", uma nova altura.

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
fonte
3
profileImage.setImageBitmap(
    Bitmap.createScaledBitmap(
        BitmapFactory.decodeByteArray(imageAsBytes, 0, imageAsBytes.length), 
        80, 80, false
    )
);
Rajkamal
fonte
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
fonte
para mim funcionou depois de um pouco redigitar float excessSizeRatio = width> height? (float) ((float) largura / (float) ScaleSize): (float) ((float) altura / (float) ScaleSize);
Csábi
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
fonte
2

Redimensionamento de bitmap com base em qualquer tamanho de exibição

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
fonte
1

Embora a resposta aceita esteja correta, ela não é redimensionada Bitmapmantendo a mesma proporção . Se você estiver procurando por um método para redimensionar Bitmapmantendo a mesma proporção, você pode usar a seguinte função de utilitário. Os detalhes de uso e a explicação da função estão presentes neste 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;
       }
   }
Asad Ali Choudhry
fonte
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
fonte
0

Mantendo a proporção,

  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
fonte