Android: Cambiar el tamaño de un archivo de mapa de bits grande a un archivo de salida escalado

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

También no puedo leer el mapa de bits con, por ejemplo, BitmapFactory.decodeFile(file, options) , proporcionando un BitmapFactory.Options.inSampleSize , porque quiero cambiar el tamaño a una anchura y altura exactas. Usar inSampleSize cambiaría el tamaño del mapa de bits a 972×648 (si utilizo inSampleSize=4 ) oa 778×518 (si utilizo 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 el tamaño a exactamente 800×533 en un segundo paso, porque la calidad sería pobre en comparación con un redimensionamiento directo de la imagen original.

Para resumir mi pregunta: ¿Hay una 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 una nueva anchura y altura, sin obtener una excepción OutOfMemory?

También intenté BitmapFactory.decodeFile(file, options) y fijar los valores de Options.outHeight y de Options.outWidth manualmente a 800 y 533, pero no trabaja de esa manera.

No. Me encantaría que alguien me corrigiera, pero acepté el enfoque de carga / redimensionamiento que intentó como un compromiso.

Estos son los pasos para cualquiera que navegue:

  1. Calcular el máximo posible inSampleSize que todavía produce una imagen más grande que su objetivo.
  2. Cargue la imagen utilizando BitmapFactory.decodeFile(file, options) , pasando inSampleSize como una opción.
  3. Cambie el tamaño a las dimensiones deseadas usando Bitmap.createScaledBitmap() .

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

Se trata de las soluciones "combinadas" de Mojo Risin y Ofir. Esto le dará una imagen proporcionalmente redimensionada con los límites de la anchura máxima y de la altura máxima.

  1. Sólo lee los metadatos para obtener el tamaño original (options.inJustDecodeBounds)
  2. Utiliza un redimensionamiento para ahorrar memoria (itmap.createScaledBitmap)
  3. Utiliza una imagen redimensionada con precisión basada en Bitamp bruto creado anteriormente.

Para mí ha estado funcionando bien en imágenes de 5 megapíxeles 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 utilizar 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 respuesta excelente hasta ahora, el mejor código que he visto todavía para esto está en la documentación para la herramienta que toma de la foto.

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 redimensionada, a escala, como las otras aquí, pero es bastante ordenada.

He copiado el código de abajo 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 mapa de bits 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 mapas de bits grandes y quiero decodificarlos redimensionados, uso lo 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 alguien que esté mirando esta pregunta. Reescribí el código de Justin para permitir que el método recibiera el objeto de tamaño de destino requerido también. Esto funciona muy bien cuando se utiliza 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 eficaz para reducir la sobrecarga de trabajar con Bitmaps grandes.

No sé si mi solución es la mejor práctica, pero logré cargar un mapa de bits con la escala deseada usando las opciones inDensity e inTargetDensity . inDensity es 0 inicialmente cuando no se carga un recurso extraíble, por lo que este enfoque es para cargar imágenes sin recursos.

Las variables imageUri , maxImageSideLength y context son parámetros de mi método. Sólo publiqué la implementación del método sin el AsyncTask de ajuste 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 a tamaño exacto y desea mantener la calidad tanto como sea necesario creo que debe intentar esto.

  1. Averigüe el tamaño de la imagen redimensionada con la llamada de BitmapFactory.decodeFile y proporcionando el checkSizeOptions.inJustDecodeBounds
  2. Calcule el máximo posible inSampleSize que puede utilizar en su dispositivo para no exceder la memoria. BitmapSizeInBytes = 2 * width * height; Generalmente para su imagen inSampleSize = 2 estaría bien, ya que sólo necesitará 2 * 1944×1296) = 4.8Mbб que debería pies en la memoria
  3. Utilice BitmapFactory.decodeFile con inSampleSize para cargar el mapa de bits
  4. Escale el mapa de bits al tamaño exacto.

Motivación: la escala de varios pasos podría proporcionar una imagen de mayor calidad, sin embargo, no hay garantía de que funcione mejor que el uso de inSampleSize alto. En realidad, creo que también puede utilizar inSampleSize como 5 (no pow de 2) para tener escala directa en una operación. O simplemente usa 4 y entonces sólo puedes usar esa imagen en la interfaz de usuario. Si lo envía al servidor – de lo que puede hacer escala a tamaño exacto en el lado del servidor que le permiten utilizar técnicas avanzadas de escalado.

Notas: si el mapa de bits cargado en el paso 3 es al menos 4 veces mayor (por lo que el 4 * targetWidth <ancho) probablemente puede utilizar varios redimensionamiento para lograr una mejor calidad. Por lo menos que funciona en java genérico, en android usted no tiene la opción de especificar la interpolación utilizada para la escala http://today.java.net/pub/a/today/2007/04/03/perils-of- Image-getscaledinstance.html

He utilizado 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 conseguí el bitmap dice es 330 x 330.
Y si lo intentó 2590 x 3849, obtendré OutOfMemoryError.

Lo rastreé, todavía tira OutOfMemoryError en línea "BitmapFactory.decodeStream (es, nulo, opciones);", si el mapa de bits original es demasiado grande …

Por encima del código un poco más limpio. Los InputStreams finalmente tienen un envolvimiento cercano para asegurarse de que se cierran también:

*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 saltar ningún píxel, tendría que enganchar en el decodificador de la imagen para realizar la fila de abajo-el muestreo por fila. Android (y la biblioteca de Skia que lo subyace) no proporciona tales anzuelos, así que tendrías que rodar tu propio. Asumiendo que estás hablando de imágenes jpeg, lo mejor sería usar libjpeg directamente, en C.

Dadas las complejidades involucradas, el uso de la submuestra de dos etapas-entonces-rescale es probablemente mejor para las aplicaciones de tipo de vista previa de la imagen.

Aquí hay un artículo que tiene un enfoque diferente para cambiar el tamaño. Intentará cargar el mapa de bits más grande posible en la memoria basada en la memoria disponible en el proceso y luego realizar las transformaciones.

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

Si usted quiere absolutamente hacer un paso de volver a clasificar según el tamaño usted podría cargar probablemente el mapa de bits entero si androide: largeHeap = verdad pero como usted puede ver esto no es realmente recomendable.

From docs: android: largeHeap Si los procesos de su aplicación deben crearse con un montón grande de Dalvik. Esto se aplica a todos los procesos creados para la aplicación. Sólo se aplica a la primera aplicación cargada en un proceso; Si utiliza un ID de usuario compartido para permitir que varias aplicaciones utilicen un proceso, todos ellos deben utilizar esta opción de forma coherente o tendrán resultados impredecibles. La mayoría de las aplicaciones no deberían necesitar esto y deberían enfocarse en reducir el uso general de memoria para mejorar el rendimiento. Habilitar esto tampoco garantiza un aumento fijo en la memoria disponible, ya que algunos dispositivos están limitados por su memoria total disponible.

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

Esto funcionó para mí. La función obtiene una ruta de acceso a un archivo en la tarjeta sd y devuelve un mapa de bits en el tamaño máximo visualizable. El código es de Ofir con algunos cambios como archivo de imagen en sd en lugar de un recurso y el witdth y altura se obtienen desde el objeto de visualización.

 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 utilizo que no tiene problemas descodificando imágenes grandes en memoria en Android. He sido capaz de decodificar imágenes mayores de 20 MB, siempre y cuando mis parámetros de entrada son alrededor de 1024×1024. Puede guardar el bitmap devuelto a otro archivo. Debajo de este método es otro método que también uso para escalar imágenes a un nuevo mapa de bits. Siéntase libre de usar este código como 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 con los demás, excepto createScaledBitmap llamadas descodificar método anterior. El ancho y la altura de la nota pueden cambiar desde 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 mapa de bits utilizando el código siguiente

  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 la siguiente punta / truco

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

  • Android código de bits de código nativo - problema de enlace
  • Cómo dividir un mapa de bits en partes que son bitmaps también
  • ALPHA_8 bitmaps y getPixel
  • ¿Cómo recortar el mapa de bits del área seleccionada en el lienzo?
  • Android + cargador universal de imágenes: muestra marcador personalizado con imagen en google map
  • Rendimiento de mapa de bits escala android
  • Combinar imágenes en android
  • Cambiar el color del mapa de bits
  • Cómo crear un mapa de bits de un archivo de imagen en Android
  • ¿Cómo obtengo el mapa de bits resultante de una imagen después de haber sido redimensionado en una vista de imagen con picasso
  • Carga Android de mapas de bits grandes
  • FlipAndroid es un fan de Google para Android, Todo sobre Android Phones, Android Wear, Android Dev y Aplicaciones para Android Aplicaciones.