¿Cómo cambiar el tamaño de un mapa de bits en Android?

337

Tengo un mapa de bits tomado de una cadena Base64 de mi base de datos remota, (encodedImage es la cadena que representa la imagen 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 es mi ImageView

Ok, pero tengo que cambiar el tamaño de esta imagen antes de mostrarla en mi ImageView mi diseño. Tengo que redimensionarlo a 120x120.

¿Alguien puede decirme el código para cambiar su tamaño?

Los ejemplos que encontré no se pudieron aplicar a un mapa de bits de cadena base64 obtenido.

Excepción de puntero nulo
fuente
Posible duplicado de Resize Bitmap en Android
Sagar Pilkhwal

Respuestas:

550

Cambio:

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

A:

Bitmap b = BitmapFactory.decodeByteArray(imageAsBytes, 0, imageAsBytes.length)
profileImage.setImageBitmap(Bitmap.createScaledBitmap(b, 120, 120, false));
user432209
fuente
supongamos que tiene una imagen de gran resolución, digamos 1200x1200, y cuando la muestre, estará llena en la vista de imagen. Si lo reduzco, digamos 75% y la pantalla es para que muestre la imagen a escala también completamente en la vista de imagen, ¿qué se debe hacer para tales pantallas?
jxgn
55
CreateScaledBitmap arroja una excepción de memoria insuficiente en mi Galaxy Tab2, lo cual es muy extraño para mí, ya que hay mucha memoria y no se está ejecutando ninguna otra aplicación en particular. Sin embargo, la solución Matrix funciona.
Ludovic
29
¿Qué pasa si queremos guardar la relación de aspecto?
errores suceden el
3
¿Qué pasa con la escala de dpi para esto? ¿Creo que el mapa de bits escalado debería basarse en la altura y el ancho de la pantalla del dispositivo?
Doug Ray
2
El uso de Bitmap.createScaledBitmap () para reducir la escala de una imagen a más de la mitad del tamaño original, puede producir artefactos de alias. Puedes echar un vistazo a una publicación que escribí donde propongo algunas alternativas y comparo calidad y rendimiento.
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;
}

EDITAR: según lo sugerido por @aveschini, he agregado bm.recycle();pérdidas de memoria. Tenga en cuenta que en caso de que esté utilizando el objeto anterior para algún otro propósito, maneje en consecuencia.

jeet.chanchawat
fuente
66
Probé tanto bitmap.createscaledbitmap como este enfoque matricial. Creo que la imagen es mucho más clara con el enfoque matricial. No sé si es común o simplemente porque estoy usando un simulador en lugar de un teléfono. Solo una pista para alguien que enfrenta los mismos problemas que yo.
Anson Yao
2
aquí también debe agregar bm.recycle () para obtener un rendimiento de memoria mucho mejor
aveschini
2
Gracias por la solución, pero sería mejor si los parámetros fueran reordenados; public Bitmap getResizedBitmap(Bitmap bm, int newWidth, int newHeight). Pasé mucho tiempo descubriéndolo. ; P
Ataque el
1
Tenga en cuenta que la importación correcta para Matrix es android.graphics.Matrix.
Lev
12
Esto es lo mismo que llamar a Bitmap.createScaledBitmap (). Ver android.googlesource.com/platform/frameworks/base/+/refs/heads/…
BamsBamx
122

Si ya tiene un mapa de bits, puede usar el siguiente código para cambiar el tamaño:

Bitmap originalBitmap = <original initialization>;
Bitmap resizedBitmap = Bitmap.createScaledBitmap(
    originalBitmap, newWidth, newHeight, false);
ZenBalance
fuente
1
@beginner si cambia el tamaño de la imagen, puede estar escalando en función de diferentes dimensiones que transforman el mapa de bits en proporciones incorrectas o eliminan parte de la información del mapa de bits.
ZenBalance
Intenté cambiar el tamaño del mapa de bits según las proporciones, pero luego recibí este error. Causado por: java.lang.RuntimeException: Canvas: tratando de usar un mapa de bits reciclado android.graphics.Bitmap@2291dd13
principiante
@beginner cada vez que cambie el tamaño del mapa de bits, dependiendo de lo que esté haciendo, generalmente necesitará crear una copia que tenga un nuevo tamaño, en lugar de cambiar el tamaño del mapa de bits existente (ya que en este caso parece que la referencia al mapa de bits era ya reciclado en memoria).
ZenBalance
1
correcto ... lo probé y funciona correctamente ahora. gracias
principiante
39

Escala basada en la relación de aspecto :

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 la altura como base de ancho, cambie a:

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

Escale un mapa de bits con un tamaño y ancho máximos de destino, mientras mantiene la relación de aspecto:

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

prueba este este código:

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

Espero que sea útil.

Ravi Makvana
fuente
7

Alguien preguntó cómo mantener la relación de aspecto en esta situación:

Calcule el factor que está utilizando para escalar y úselo para ambas dimensiones. Supongamos que desea que una imagen tenga el 20% de la altura de la pantalla

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 obtener la resolución de pantalla, tiene esta solución: obtenga las dimensiones de la pantalla en píxeles

Taochok
fuente
3

Pruebe esto: esta función cambia el tamaño de un mapa de bits proporcionalmente. Cuando el último parámetro se establece en "X", newDimensionXorYse trata como un nuevo ancho y cuando se establece en "Y" una nueva 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;
}
usuario2288580
fuente
3
profileImage.setImageBitmap(
    Bitmap.createScaledBitmap(
        BitmapFactory.decodeByteArray(imageAsBytes, 0, imageAsBytes.length), 
        80, 80, false
    )
);
Rajkamal
fuente
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
fuente
para mí funcionó después de volver a escribir un poco float excesoSizeRatio = ancho> altura? (flotante) ((flotante) ancho / (flotante) ScaleSize): (flotante) ((flotante) altura / (flotante) 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
fuente
2

Cambiar el tamaño del mapa de bits en función de cualquier tamaño de pantalla

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

Aunque la respuesta aceptada es correcta, no cambia el tamaño Bitmapmanteniendo la misma relación de aspecto . Si está buscando un método para cambiar el tamaño Bitmapmanteniendo la misma relación de aspecto, puede usar la siguiente función de utilidad. Los detalles de uso y la explicación de la función están presentes en este enlace .

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
fuente
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
fuente
0

Manteniendo la relación de aspecto,

  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
fuente