Cambiar el tamaño de un archivo de bitmap grande a un archivo de salida escalado en Android

Tengo un bitmap grande (digamos 3888×2592) en un archivo. Ahora, quiero cambiar el tamaño de ese bitmap a 800×533 y guardarlo en otro archivo. Normalmente Bitmap.createBitmap el bitmap llamando Bitmap.createBitmap método Bitmap.createBitmap , pero necesita un bitmap de origen como primer argumento, que no puedo proporcionar porque la carga de la imagen original en un objeto Bitmap excedería la memoria (ver aquí , por ejemplo) )

Tampoco puedo leer el bitmap con, por ejemplo, BitmapFactory.decodeFile(file, options) , proporcionando un BitmapFactory.Options.inSampleSize , porque quiero redimensionarlo a un ancho y alto exactos. Usar inSampleSize redimensionaría el bitmap a 972×648 (si uso inSampleSize=4 ) o a 778×518 (si uso inSampleSize=5 , que ni siquiera es una potencia de 2).

También me gustaría evitar leer la imagen usando inSampleSize con, por ejemplo, 972×648 en un primer paso y luego cambiar su tamaño a exactamente 800×533 en un segundo paso, porque la calidad sería pobre en comparación con un cambio de tamaño directo de la imagen original.

Para resumir mi pregunta: ¿Hay alguna manera de leer un archivo de imagen grande con 10MP o más y guardarlo en un nuevo archivo de imagen, cambiar el tamaño a un nuevo ancho y alto específicos, sin obtener una excepción de OutOfMemory?

También probé BitmapFactory.decodeFile(file, options) y establecí los valores de Options.outHeight y Options.outWidth manualmente en 800 y 533, pero no funciona de esa manera.

No. Me encantaría que alguien me corrigiera, pero acepté el enfoque de carga / cambio de tamaño que probó como un compromiso.

Estos son los pasos para cualquier persona que navega:

  1. Calcule el máximo posible en inSampleSize que aún produzca una imagen más grande que su objective.
  2. Cargue la imagen usando BitmapFactory.decodeFile(file, options) , pasando inSampleSize como una opción.
  3. Cambie el tamaño de las dimensiones deseadas utilizando Bitmap.createScaledBitmap() .

Justin responde traducido al código (funciona perfecto para mí):

 private Bitmap getBitmap(String path) { Uri uri = getImageUri(path); InputStream in = null; try { final int IMAGE_MAX_SIZE = 1200000; // 1.2MP in = mContentResolver.openInputStream(uri); // Decode image size BitmapFactory.Options options = new BitmapFactory.Options(); options.inJustDecodeBounds = true; BitmapFactory.decodeStream(in, null, options); in.close(); int scale = 1; while ((options.outWidth * options.outHeight) * (1 / Math.pow(scale, 2)) > IMAGE_MAX_SIZE) { scale++; } Log.d(TAG, "scale = " + scale + ", orig-width: " + options.outWidth + ", orig-height: " + options.outHeight); Bitmap resultBitmap = null; in = mContentResolver.openInputStream(uri); if (scale > 1) { scale--; // scale to max possible inSampleSize that still yields an image // larger than target options = new BitmapFactory.Options(); options.inSampleSize = scale; resultBitmap = BitmapFactory.decodeStream(in, null, options); // resize to desired dimensions int height = resultBitmap.getHeight(); int width = resultBitmap.getWidth(); Log.d(TAG, "1th scale operation dimenions - width: " + width + ", height: " + height); double y = Math.sqrt(IMAGE_MAX_SIZE / (((double) width) / height)); double x = (y / height) * width; Bitmap scaledBitmap = Bitmap.createScaledBitmap(resultBitmap, (int) x, (int) y, true); resultBitmap.recycle(); resultBitmap = scaledBitmap; System.gc(); } else { resultBitmap = BitmapFactory.decodeStream(in); } in.close(); Log.d(TAG, "bitmap size - width: " +resultBitmap.getWidth() + ", height: " + resultBitmap.getHeight()); return resultBitmap; } catch (IOException e) { Log.e(TAG, e.getMessage(),e); return null; } 

Esto es ‘soluciones combinadas’ de ‘Mojo Risin y’ Ofir ‘. Esto le dará una imagen de tamaño proporcional con los límites del ancho máximo y la altura máxima.

  1. Solo lee metadatos para obtener el tamaño original (options.inJustDecodeBounds)
  2. Utiliza un cambio de tamaño para ahorrar memoria (itmap.createScaledBitmap)
  3. Utiliza una imagen ajustada con precisión según el Bitamp rugoso creado anteriormente.

Para mí ha estado funcionando bien en 5 imágenes de MegaPixel a continuación.

 try { int inWidth = 0; int inHeight = 0; InputStream in = new FileInputStream(pathOfInputImage); // decode image size (decode metadata only, not the whole image) BitmapFactory.Options options = new BitmapFactory.Options(); options.inJustDecodeBounds = true; BitmapFactory.decodeStream(in, null, options); in.close(); in = null; // save width and height inWidth = options.outWidth; inHeight = options.outHeight; // decode full image pre-resized in = new FileInputStream(pathOfInputImage); options = new BitmapFactory.Options(); // calc rought re-size (this is no exact resize) options.inSampleSize = Math.max(inWidth/dstWidth, inHeight/dstHeight); // decode full image Bitmap roughBitmap = BitmapFactory.decodeStream(in, null, options); // calc exact destination size Matrix m = new Matrix(); RectF inRect = new RectF(0, 0, roughBitmap.getWidth(), roughBitmap.getHeight()); RectF outRect = new RectF(0, 0, dstWidth, dstHeight); m.setRectToRect(inRect, outRect, Matrix.ScaleToFit.CENTER); float[] values = new float[9]; m.getValues(values); // resize bitmap Bitmap resizedBitmap = Bitmap.createScaledBitmap(roughBitmap, (int) (roughBitmap.getWidth() * values[0]), (int) (roughBitmap.getHeight() * values[4]), true); // save image try { FileOutputStream out = new FileOutputStream(pathOfOutputImage); resizedBitmap.compress(Bitmap.CompressFormat.JPEG, 80, out); } catch (Exception e) { Log.e("Image", e.getMessage(), e); } } catch (IOException e) { Log.e("Image", e.getMessage(), e); } 

¿Por qué no usar la API?

 int h = 48; // height in pixels int w = 48; // width in pixels Bitmap scaled = Bitmap.createScaledBitmap(largeBitmap, w, h, true); 

Reconociendo la otra excelente respuesta hasta ahora, el mejor código que he visto hasta ahora es la documentación para la herramienta para tomar fotos.

Consulte la sección titulada “Decodificar una imagen escalada”.

http://developer.android.com/training/camera/photobasics.html

La solución que propone es una solución de cambio de tamaño y escala, como las otras aquí, pero es bastante ordenada.

He copiado el código siguiente como una función lista para usar por conveniencia.

 private void setPic(String imagePath, ImageView destination) { int targetW = destination.getWidth(); int targetH = destination.getHeight(); // Get the dimensions of the bitmap BitmapFactory.Options bmOptions = new BitmapFactory.Options(); bmOptions.inJustDecodeBounds = true; BitmapFactory.decodeFile(imagePath, bmOptions); int photoW = bmOptions.outWidth; int photoH = bmOptions.outHeight; // Determine how much to scale down the image int scaleFactor = Math.min(photoW/targetW, photoH/targetH); // Decode the image file into a Bitmap sized to fill the View bmOptions.inJustDecodeBounds = false; bmOptions.inSampleSize = scaleFactor; bmOptions.inPurgeable = true; Bitmap bitmap = BitmapFactory.decodeFile(imagePath, bmOptions); destination.setImageBitmap(bitmap); } 

Después de leer estas respuestas y la documentación de Android, aquí está el código para cambiar el tamaño del bitmap sin cargarlo en la memoria:

 public Bitmap getResizedBitmap(int targetW, int targetH, String imagePath) { // Get the dimensions of the bitmap BitmapFactory.Options bmOptions = new BitmapFactory.Options(); //inJustDecodeBounds = true < -- will not load the bitmap into memory bmOptions.inJustDecodeBounds = true; BitmapFactory.decodeFile(imagePath, bmOptions); int photoW = bmOptions.outWidth; int photoH = bmOptions.outHeight; // Determine how much to scale down the image int scaleFactor = Math.min(photoW/targetW, photoH/targetH); // Decode the image file into a Bitmap sized to fill the View bmOptions.inJustDecodeBounds = false; bmOptions.inSampleSize = scaleFactor; bmOptions.inPurgeable = true; Bitmap bitmap = BitmapFactory.decodeFile(imagePath, bmOptions); return(bitmap); } 

Cuando tengo grandes mapas de bits y quiero decodificarlos, uso el siguiente

 BitmapFactory.Options options = new BitmapFactory.Options(); InputStream is = null; is = new FileInputStream(path_to_file); BitmapFactory.decodeStream(is,null,options); is.close(); is = new FileInputStream(path_to_file); // here w and h are the desired width and height options.inSampleSize = Math.max(options.outWidth/w, options.outHeight/h); // bitmap is the resized bitmap Bitmap bitmap = BitmapFactory.decodeStream(is,null,options); 

Esto puede ser útil para otra persona que vea esta pregunta. Reescribí el código de Justin para permitir que el método reciba también el objeto de tamaño objective requerido. Esto funciona muy bien cuando se usa Canvas. Todo el crédito debe ir a JUSTIN por su gran código inicial.

  private Bitmap getBitmap(int path, Canvas canvas) { Resources resource = null; try { final int IMAGE_MAX_SIZE = 1200000; // 1.2MP resource = getResources(); // Decode image size BitmapFactory.Options options = new BitmapFactory.Options(); options.inJustDecodeBounds = true; BitmapFactory.decodeResource(resource, path, options); int scale = 1; while ((options.outWidth * options.outHeight) * (1 / Math.pow(scale, 2)) > IMAGE_MAX_SIZE) { scale++; } Log.d("TAG", "scale = " + scale + ", orig-width: " + options.outWidth + ", orig-height: " + options.outHeight); Bitmap pic = null; if (scale > 1) { scale--; // scale to max possible inSampleSize that still yields an image // larger than target options = new BitmapFactory.Options(); options.inSampleSize = scale; pic = BitmapFactory.decodeResource(resource, path, options); // resize to desired dimensions int height = canvas.getHeight(); int width = canvas.getWidth(); Log.d("TAG", "1th scale operation dimenions - width: " + width + ", height: " + height); double y = Math.sqrt(IMAGE_MAX_SIZE / (((double) width) / height)); double x = (y / height) * width; Bitmap scaledBitmap = Bitmap.createScaledBitmap(pic, (int) x, (int) y, true); pic.recycle(); pic = scaledBitmap; System.gc(); } else { pic = BitmapFactory.decodeResource(resource, path); } Log.d("TAG", "bitmap size - width: " +pic.getWidth() + ", height: " + pic.getHeight()); return pic; } catch (Exception e) { Log.e("TAG", e.getMessage(),e); return null; } } 

El código de Justin es MUY efectivo para reducir la sobrecarga de trabajar con grandes mapas de bits.

No sé si mi solución es la mejor práctica, pero logré cargar un bitmap con la escala deseada usando las opciones inDensity e inTargetDensity . inDensity es 0 inicialmente cuando no está cargando un recurso dibujable, por lo que este enfoque es para cargar imágenes que no sean de recursos.

Las variables imageUri , maxImageSideLength y context son parámetros de mi método. Publiqué solo la implementación del método sin la envoltura de AsyncTask para mayor claridad.

  ContentResolver resolver = context.getContentResolver(); InputStream is; try { is = resolver.openInputStream(imageUri); } catch (FileNotFoundException e) { Log.e(TAG, "Image not found.", e); return null; } Options opts = new Options(); opts.inJustDecodeBounds = true; BitmapFactory.decodeStream(is, null, opts); // scale the image float maxSideLength = maxImageSideLength; float scaleFactor = Math.min(maxSideLength / opts.outWidth, maxSideLength / opts.outHeight); // do not upscale! if (scaleFactor < 1) { opts.inDensity = 10000; opts.inTargetDensity = (int) ((float) opts.inDensity * scaleFactor); } opts.inJustDecodeBounds = false; try { is.close(); } catch (IOException e) { // ignore } try { is = resolver.openInputStream(imageUri); } catch (FileNotFoundException e) { Log.e(TAG, "Image not found.", e); return null; } Bitmap bitmap = BitmapFactory.decodeStream(is, null, opts); try { is.close(); } catch (IOException e) { // ignore } return bitmap; 

Teniendo en cuenta que desea cambiar el tamaño al tamaño exacto y desea mantener la calidad necesaria, creo que debería intentarlo.

  1. Averigüe el tamaño de la imagen redimensionada con la llamada de BitmapFactory.decodeFile y proporcione el checkSizeOptions.inJustDecodeBounds
  2. Calcule el máximo posible en SampleSize que puede usar en su dispositivo para no exceder la memoria. bitmapSizeInBytes = 2 * ancho * alto; En general, para su imagen en SampleSize = 2 estaría bien, ya que solo necesitará 2 * 1944×1296) = 4.8Mbб que debe tener pies en la memoria
  3. Utilice BitmapFactory.decodeFile con inSampleSize para cargar el bitmap
  4. Escala el bitmap al tamaño exacto.

Motivación: el escalado en varios pasos puede brindarle una imagen de mayor calidad, sin embargo, no hay garantía de que funcione mejor que el uso de alto en Tamaño de la muestra. En realidad, creo que también puedes usar inSampleSize como 5 (no pow de 2) para tener escalado directo en una sola operación. O simplemente usa 4 y luego puedes usar esa imagen en la interfaz de usuario. si lo envía al servidor, entonces puede escalar al tamaño exacto en el lado del servidor, lo que le permite usar técnicas avanzadas de escalado.

Notas: si el bitmap cargado en el paso 3 es al menos 4 veces más grande (por lo que el 4 * targetWidth http://today.java.net/pub/a/today/2007/04/03/perils-of- image-getscaledinstance.html

Usé un código como este:

  String filePath=Environment.getExternalStorageDirectory()+"/test_image.jpg"; BitmapFactory.Options options=new BitmapFactory.Options(); InputStream is=new FileInputStream(filePath); BitmapFactory.decodeStream(is, null, options); is.close(); is=new FileInputStream(filePath); // here w and h are the desired width and height options.inSampleSize=Math.max(options.outWidth/460, options.outHeight/288); //Max 460 x 288 is my desired... // bmp is the resized bitmap Bitmap bmp=BitmapFactory.decodeStream(is, null, options); is.close(); Log.d(Constants.TAG, "Scaled bitmap bytes, "+bmp.getRowBytes()+", width:"+bmp.getWidth()+", height:"+bmp.getHeight()); 

Intenté la imagen original es 1230 x 1230, y tengo bitmap dice es 330 x 330.
Y si lo intenté con 2590 x 3849, obtendré OutOfMemoryError.

Lo rastreé, todavía arroja OutOfMemoryError en línea “BitmapFactory.decodeStream (es, nulo, opciones);”, si el bitmap original es demasiado grande …

Por encima del código hizo un poco más limpio. InputStreams finalmente han cerrado el ajuste para garantizar que también se cierren:

*Nota
Entrada: InputStream es, int w, int h
Salida: bitmap

  try { final int inWidth; final int inHeight; final File tempFile = new File(temp, System.currentTimeMillis() + is.toString() + ".temp"); { final FileOutputStream tempOut = new FileOutputStream(tempFile); StreamUtil.copyTo(is, tempOut); tempOut.close(); } { final InputStream in = new FileInputStream(tempFile); final BitmapFactory.Options options = new BitmapFactory.Options(); try { // decode image size (decode metadata only, not the whole image) options.inJustDecodeBounds = true; BitmapFactory.decodeStream(in, null, options); } finally { in.close(); } // save width and height inWidth = options.outWidth; inHeight = options.outHeight; } final Bitmap roughBitmap; { // decode full image pre-resized final InputStream in = new FileInputStream(tempFile); try { final BitmapFactory.Options options = new BitmapFactory.Options(); // calc rought re-size (this is no exact resize) options.inSampleSize = Math.max(inWidth/w, inHeight/h); // decode full image roughBitmap = BitmapFactory.decodeStream(in, null, options); } finally { in.close(); } tempFile.delete(); } float[] values = new float[9]; { // calc exact destination size Matrix m = new Matrix(); RectF inRect = new RectF(0, 0, roughBitmap.getWidth(), roughBitmap.getHeight()); RectF outRect = new RectF(0, 0, w, h); m.setRectToRect(inRect, outRect, Matrix.ScaleToFit.CENTER); m.getValues(values); } // resize bitmap final Bitmap resizedBitmap = Bitmap.createScaledBitmap(roughBitmap, (int) (roughBitmap.getWidth() * values[0]), (int) (roughBitmap.getHeight() * values[4]), true); return resizedBitmap; } catch (IOException e) { logger.error("Error:" , e); throw new ResourceException("could not create bitmap"); } 

Para escalar la imagen de la manera “correcta”, sin saltear ningún pixel, tendría que enganchar en el decodificador de imagen para realizar el muestreo hacia abajo fila por fila. Android (y la biblioteca de Skia que lo subyace) no ofrece tales enganches, por lo que tendrá que hacer su propio. Suponiendo que está hablando de imágenes JPEG, su mejor opción sería usar libjpeg directamente, en C.

Dadas las complejidades involucradas, el uso de la submuestra de dos pasos-luego-reescalar es probablemente la mejor opción para aplicaciones de vista previa de imágenes.

Aquí hay un artículo que toma un enfoque diferente para cambiar el tamaño. Intentará cargar el bitmap más grande posible en la memoria en función de la memoria disponible en el proceso y luego realizar las transformaciones.

http://bricolsoftconsulting.com/2012/12/07/handling-large-images-on-android/

Si quieres cambiar el tamaño de un paso, probablemente puedas cargar todo el bitmap si android: largeHeap = true, pero como puedes ver, esto no es realmente recomendable.

From docs: android: largeHeap Si los procesos de su aplicación se deben crear con un gran montón de Dalvik. Esto se aplica a todos los procesos creados para la aplicación. Solo se aplica a la primera aplicación cargada en un proceso; si está usando una identificación de usuario compartida para permitir que varias aplicaciones utilicen un proceso, todas deben usar esta opción de manera consistente o tendrán resultados imprevisibles. La mayoría de las aplicaciones no deberían necesitar esto y deberían enfocarse en reducir el uso general de memoria para un mejor rendimiento. Habilitar esto tampoco garantiza un aumento fijo en la memoria disponible, porque algunos dispositivos están limitados por su memoria total disponible.

Hay un excelente artículo sobre este problema exacto en el sitio web para desarrolladores de Android: Carga de mapas de bits de manera eficiente

Esto funcionó para mí. La función obtiene una ruta a un archivo en la tarjeta SD y devuelve un bitmap en el tamaño máximo que se puede visualizar. El código es de Ofir con algunos cambios como el archivo de imagen en sd en lugar de un Ressource y el witdth y heigth se obtienen del Display Object.

 private Bitmap makeBitmap(String path) { try { final int IMAGE_MAX_SIZE = 1200000; // 1.2MP //resource = getResources(); // Decode image size BitmapFactory.Options options = new BitmapFactory.Options(); options.inJustDecodeBounds = true; BitmapFactory.decodeFile(path, options); int scale = 1; while ((options.outWidth * options.outHeight) * (1 / Math.pow(scale, 2)) > IMAGE_MAX_SIZE) { scale++; } Log.d("TAG", "scale = " + scale + ", orig-width: " + options.outWidth + ", orig-height: " + options.outHeight); Bitmap pic = null; if (scale > 1) { scale--; // scale to max possible inSampleSize that still yields an image // larger than target options = new BitmapFactory.Options(); options.inSampleSize = scale; pic = BitmapFactory.decodeFile(path, options); // resize to desired dimensions Display display = getWindowManager().getDefaultDisplay(); Point size = new Point(); display.getSize(size); int width = size.y; int height = size.x; //int height = imageView.getHeight(); //int width = imageView.getWidth(); Log.d("TAG", "1th scale operation dimenions - width: " + width + ", height: " + height); double y = Math.sqrt(IMAGE_MAX_SIZE / (((double) width) / height)); double x = (y / height) * width; Bitmap scaledBitmap = Bitmap.createScaledBitmap(pic, (int) x, (int) y, true); pic.recycle(); pic = scaledBitmap; System.gc(); } else { pic = BitmapFactory.decodeFile(path); } Log.d("TAG", "bitmap size - width: " +pic.getWidth() + ", height: " + pic.getHeight()); return pic; } catch (Exception e) { Log.e("TAG", e.getMessage(),e); return null; } } 
  Bitmap yourBitmap; Bitmap resized = Bitmap.createScaledBitmap(yourBitmap, newWidth, newHeight, true); 

o:

  resized = Bitmap.createScaledBitmap(yourBitmap,(int)(yourBitmap.getWidth()*0.8), (int)(yourBitmap.getHeight()*0.8), true); 

Aquí está el código que uso, que no tiene problemas para decodificar imágenes grandes en la memoria en Android. Pude decodificar imágenes de más de 20 MB siempre que mis parámetros de entrada sean de alrededor de 1024×1024. Puede guardar el bitmap devuelto en otro archivo. Debajo de este método hay otro método que también uso para escalar imágenes a un nuevo bitmap. Siéntase libre de usar este código como lo desee.

 /***************************************************************************** * public decode - decode the image into a Bitmap * * @param xyDimension * - The max XY Dimension before the image is scaled down - XY = * 1080x1080 and Image = 2000x2000 image will be scaled down to a * value equal or less then set value. * @param bitmapConfig * - Bitmap.Config Valid values = ( Bitmap.Config.ARGB_4444, * Bitmap.Config.RGB_565, Bitmap.Config.ARGB_8888 ) * * @return Bitmap - Image - a value of "null" if there is an issue decoding * image dimension * * @throws FileNotFoundException * - If the image has been removed while this operation is * taking place */ public Bitmap decode( int xyDimension, Bitmap.Config bitmapConfig ) throws FileNotFoundException { // The Bitmap to return given a Uri to a file Bitmap bitmap = null; File file = null; FileInputStream fis = null; InputStream in = null; // Try to decode the Uri try { // Initialize scale to no real scaling factor double scale = 1; // Get FileInputStream to get a FileDescriptor file = new File( this.imageUri.getPath() ); fis = new FileInputStream( file ); FileDescriptor fd = fis.getFD(); // Get a BitmapFactory Options object BitmapFactory.Options o = new BitmapFactory.Options(); // Decode only the image size o.inJustDecodeBounds = true; o.inPreferredConfig = bitmapConfig; // Decode to get Width & Height of image only BitmapFactory.decodeFileDescriptor( fd, null, o ); BitmapFactory.decodeStream( null ); if( o.outHeight > xyDimension || o.outWidth > xyDimension ) { // Change the scale if the image is larger then desired image // max size scale = Math.pow( 2, (int) Math.round( Math.log( xyDimension / (double) Math.max( o.outHeight, o.outWidth ) ) / Math.log( 0.5 ) ) ); } // Decode with inSampleSize scale will either be 1 or calculated value o.inJustDecodeBounds = false; o.inSampleSize = (int) scale; // Decode the Uri for real with the inSampleSize in = new BufferedInputStream( fis ); bitmap = BitmapFactory.decodeStream( in, null, o ); } catch( OutOfMemoryError e ) { Log.e( DEBUG_TAG, "decode : OutOfMemoryError" ); e.printStackTrace(); } catch( NullPointerException e ) { Log.e( DEBUG_TAG, "decode : NullPointerException" ); e.printStackTrace(); } catch( RuntimeException e ) { Log.e( DEBUG_TAG, "decode : RuntimeException" ); e.printStackTrace(); } catch( FileNotFoundException e ) { Log.e( DEBUG_TAG, "decode : FileNotFoundException" ); e.printStackTrace(); } catch( IOException e ) { Log.e( DEBUG_TAG, "decode : IOException" ); e.printStackTrace(); } // Save memory file = null; fis = null; in = null; return bitmap; } // decode 

NOTA: Los métodos no tienen nada que ver entre sí, excepto createScaledBitmap llama al método de deencoding anterior. El ancho y el alto de la nota pueden cambiar de la imagen original.

 /***************************************************************************** * public createScaledBitmap - Creates a new bitmap, scaled from an existing * bitmap. * * @param dstWidth * - Scale the width to this dimension * @param dstHeight * - Scale the height to this dimension * @param xyDimension * - The max XY Dimension before the original image is scaled * down - XY = 1080x1080 and Image = 2000x2000 image will be * scaled down to a value equal or less then set value. * @param bitmapConfig * - Bitmap.Config Valid values = ( Bitmap.Config.ARGB_4444, * Bitmap.Config.RGB_565, Bitmap.Config.ARGB_8888 ) * * @return Bitmap - Image scaled - a value of "null" if there is an issue * */ public Bitmap createScaledBitmap( int dstWidth, int dstHeight, int xyDimension, Bitmap.Config bitmapConfig ) { Bitmap scaledBitmap = null; try { Bitmap bitmap = this.decode( xyDimension, bitmapConfig ); // Create an empty Bitmap which will contain the new scaled bitmap // This scaled bitmap should be the size we want to scale the // original bitmap too scaledBitmap = Bitmap.createBitmap( dstWidth, dstHeight, bitmapConfig ); float ratioX = dstWidth / (float) bitmap.getWidth(); float ratioY = dstHeight / (float) bitmap.getHeight(); float middleX = dstWidth / 2.0f; float middleY = dstHeight / 2.0f; // Used to for scaling the image Matrix scaleMatrix = new Matrix(); scaleMatrix.setScale( ratioX, ratioY, middleX, middleY ); // Used to do the work of scaling Canvas canvas = new Canvas( scaledBitmap ); canvas.setMatrix( scaleMatrix ); canvas.drawBitmap( bitmap, middleX - bitmap.getWidth() / 2, middleY - bitmap.getHeight() / 2, new Paint( Paint.FILTER_BITMAP_FLAG ) ); } catch( IllegalArgumentException e ) { Log.e( DEBUG_TAG, "createScaledBitmap : IllegalArgumentException" ); e.printStackTrace(); } catch( NullPointerException e ) { Log.e( DEBUG_TAG, "createScaledBitmap : NullPointerException" ); e.printStackTrace(); } catch( FileNotFoundException e ) { Log.e( DEBUG_TAG, "createScaledBitmap : FileNotFoundException" ); e.printStackTrace(); } return scaledBitmap; } // End createScaledBitmap 

Cambiar el tamaño del bitmap utilizando el siguiente código

  public static Bitmap decodeFile(File file, int reqWidth, int reqHeight){ // First decode with inJustDecodeBounds=true to check dimensions final BitmapFactory.Options options = new BitmapFactory.Options(); options.inJustDecodeBounds = true; BitmapFactory.decodeFile(file.getPath(), options); // Calculate inSampleSize options.inSampleSize = calculateInSampleSize(options, reqWidth, reqHeight); // Decode bitmap with inSampleSize set options.inJustDecodeBounds = false; return BitmapFactory.decodeFile(file.getPath(), options); } private static int calculateInSampleSize( BitmapFactory.Options options, int reqWidth, int reqHeight) { // Raw height and width of image final int height = options.outHeight; final int width = options.outWidth; int inSampleSize = 1; if (height > reqHeight || width > reqWidth) { // Calculate ratios of height and width to requested height and width final int heightRatio = Math.round((float) height / (float) reqHeight); final int widthRatio = Math.round((float) width / (float) reqWidth); // Choose the smallest ratio as inSampleSize value, this will guarantee // a final image with both dimensions larger than or equal to the // requested height and width. inSampleSize = heightRatio < widthRatio ? heightRatio : widthRatio; } return inSampleSize; } 

Lo mismo también se explica en el siguiente truco / truco

http://www.codeproject.com/Tips/625810/Android-Image-Operations-Using-BitmapFactory