"Bitmap demasiado grande para ser cargado en una textura"

Estoy cargando un mapa de bits en un ImageView, y viendo este error. Creo que este límite se refiere a un límite de tamaño para las texturas de hardware OpenGL (2048×2048). La imagen que necesito cargar es una imagen pinch-zoom de unos 4.000 píxeles de alto.

He intentado desactivar la aceleración de hardware en el manifiesto, pero no alegría.

<application android:hardwareAccelerated="false" .... > 

¿Es posible cargar una imagen de más de 2048 píxeles en un ImageView?

Todas las renderizaciones se basan en OpenGL, por lo que no se puede superar este límite (GL_MAX_TEXTURE_SIZE depende del dispositivo, pero el mínimo es 2048×2048, por lo que cualquier imagen inferior a 2048×2048 encaja).

Con imágenes tan grandes, si desea ampliar el zoom, y en un móvil, debe configurar un sistema similar a lo que se ve en google maps por ejemplo. Con la imagen dividida en varias piezas, y varias definiciones.

O puede reducir la imagen antes de mostrarla (vea la respuesta de user1352407 en esta pregunta).

Además, tenga cuidado con la carpeta en la que coloca la imagen, Android puede escalar automáticamente las imágenes. Echa un vistazo a la respuesta de Pilot_51 a continuación sobre esta cuestión.

Esto no es una respuesta directa a la pregunta (cargando imágenes> 2048), sino una posible solución para cualquier persona que experimente el error.

En mi caso, la imagen era más pequeña que 2048 en ambas dimensiones (1280×727 para ser exactos) y el problema fue experimentado específicamente en un Galaxy Nexus. La imagen estaba en la carpeta drawable y ninguna de las carpetas calificadas. Android supone drawables sin un calificador de densidad son mdpi y las escalas hacia arriba o hacia abajo para otras densidades, en este caso escalado 2x para xhdpi. Mover la imagen culpable a drawable-nodpi para evitar la escalada resolvió el problema.

He reducido la imagen de esta manera:

 ImageView iv = (ImageView)waypointListView.findViewById(R.id.waypoint_picker_photo); Bitmap d = new BitmapDrawable(ctx.getResources() , w.photo.getAbsolutePath()).getBitmap(); int nh = (int) ( d.getHeight() * (512.0 / d.getWidth()) ); Bitmap scaled = Bitmap.createScaledBitmap(d, 512, nh, true); iv.setImageBitmap(scaled); 

En lugar de pasar horas y horas tratando de escribir / depurar todo este código de downsampling manualmente, ¿por qué no usar Picasso? Se hizo para tratar mapas de bits de todos los tipos y / o tamaños.
He utilizado esta sola línea de código para quitar mi "mapa de bits demasiado grande …." problema:

 Picasso.with(context).load(resourceId).fit().centerCrop().into(imageView); 

Cambiar el archivo de la imagen a la carpeta drawable-nodpi carpeta drawable-nodpi trabajó para mí.

Utilicé Picasso y tuve el mismo problema. La imagen era demasiado grande al menos en tamaño, anchura o altura. Finalmente encontré la solución aquí. Puede escalar la imagen grande hacia abajo según el tamaño de la pantalla y también mantener la relación de aspecto:

  public Point getDisplaySize(Display display) { Point size = new Point(); if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB_MR2) { display.getSize(size); } else { int width = display.getWidth(); int height = display.getHeight(); size = new Point(width, height); } return size; } 

Y utilice este método para cargar imágenes por Picasso:

  final Point displySize = getDisplaySize(getWindowManager().getDefaultDisplay()); final int size = (int) Math.ceil(Math.sqrt(displySize.x * displySize.y)); Picasso.with(this) .load(urlSource) .resize(size, size) .centerInside() .into(imageViewd); 

También para un mejor rendimiento se puede descargar la imagen de acuerdo a la anchura y la altura de la pantalla, no toda la imagen:

  public String reviseImageUrl(final Integer displayWidth, final Integer displayHeight, final String originalImageUrl) { final String revisedImageUrl; if (displayWidth == null && displayHeight == null) { revisedImageUrl = originalImageUrl; } else { final Uri.Builder uriBuilder = Uri.parse(originalImageUrl).buildUpon(); if (displayWidth != null && displayWidth > 0) { uriBuilder.appendQueryParameter(QUERY_KEY_DISPLAY_WIDTH, String.valueOf(displayWidth)); } if (displayHeight != null && displayHeight > 0) { uriBuilder.appendQueryParameter(QUERY_KEY_DISPLAY_HEIGHT, String.valueOf(displayHeight)); } revisedImageUrl = uriBuilder.toString(); } return revisedImageUrl; } final String newImageUlr = reviseImageUrl(displySize.x, displySize.y, urlSource); 

y entonces:

  Picasso.with(this) .load(newImageUlr) .resize(size, size) .centerInside() .into(imageViewd); 

EDIT: getDisplaySize ()

display.getWidth()/getHeight() está obsoleto. En lugar de Display use DisplayMetrics .

 public Point getDisplaySize(DisplayMetrics displayMetrics) { int width = displayMetrics.widthPixels; int height = displayMetrics.heightPixels; return new Point(width, height); } 

BitmapRegionDecoder hace el truco.

Puede sobrescribir onDraw (Lienzo lienzo), iniciar un nuevo subproceso y decodificar el son visibles para el usuario.

Como señala Larcho, a partir del nivel 10 de API, puede utilizar BitmapRegionDecoder para cargar regiones específicas de una imagen y con eso, puede lograr mostrar una imagen grande en alta resolución asignando en memoria sólo las regiones necesarias. Recientemente he desarrollado una lib que proporciona la visualización de imágenes grandes con el manejo de gestos táctiles. El código fuente y las muestras están disponibles aquí .

La adición de los siguientes 2 atributos en (AndroidManifest.xml) funcionó para mí:

  • Android: largeHeap = "true"
  • Android: hardwareAccelerated = "false"

Corrí a través del mismo problema, aquí está mi solución. Establecer el ancho de la imagen igual que el ancho de la pantalla de Android y, a continuación, escala la altura

 Bitmap myBitmap = BitmapFactory.decodeFile(image.getAbsolutePath()); Display display = getWindowManager().getDefaultDisplay(); Point size = new Point(); display.getSize(size); int width = size.x; int height = size.y; Log.e("Screen width ", " "+width); Log.e("Screen height ", " "+height); Log.e("img width ", " "+myBitmap.getWidth()); Log.e("img height ", " "+myBitmap.getHeight()); float scaleHt =(float) width/myBitmap.getWidth(); Log.e("Scaled percent ", " "+scaleHt); Bitmap scaled = Bitmap.createScaledBitmap(myBitmap, width, (int)(myBitmap.getWidth()*scaleHt), true); myImage.setImageBitmap(scaled); 

Esto es mejor para cualquier tamaño de pantalla de Android. Hágamelo saber si funciona para usted.

Escala abajo de la imagen:

 BitmapFactory.Options options = new BitmapFactory.Options(); options.inJustDecodeBounds = true; // Set height and width in options, does not return an image and no resource taken BitmapFactory.decodeStream(imagefile, null, options); int pow = 0; while (options.outHeight >> pow > reqHeight || options.outWidth >> pow > reqWidth) pow += 1; options.inSampleSize = 1 << pow; options.inJustDecodeBounds = false; image = BitmapFactory.decodeStream(imagefile, null, options); 

La imagen se reducirá al tamaño de reqHeight y reqWidth. Como entiendo inSampleSize solo toma una potencia de 2 valores.

Gracias a todos los colaboradores aquí, pero he probado todas las soluciones anteriores, una después de la otra, durante muchas horas, y ninguno parecía funcionar! Por último, decidí mirar alrededor de un ejemplo oficial sobre la captura de imágenes con la cámara de Android, y mostrarlos. El ejemplo oficial ( aquí ), finalmente me dio el único método que funcionó. A continuación se presenta la solución que encontré en ese ejemplo de aplicación:

 public void setThumbnailImageAndSave(final ImageView imgView, File imgFile) { /* There isn't enough memory to open up more than a couple camera photos */ /* So pre-scale the target bitmap into which the file is decoded */ /* Get the size of the ImageView */ int targetW = imgView.getWidth(); int targetH = imgView.getHeight(); /* Get the size of the image */ BitmapFactory.Options bmOptions = new BitmapFactory.Options(); bmOptions.inJustDecodeBounds = true; BitmapFactory.decodeFile(imgFile.getAbsolutePath(), bmOptions); int photoW = bmOptions.outWidth; int photoH = bmOptions.outHeight; /* Figure out which way needs to be reduced less */ int scaleFactor = 1; if ((targetW > 0) || (targetH > 0)) { scaleFactor = Math.min(photoW/targetW, photoH/targetH); } /* Set bitmap options to scale the image decode target */ bmOptions.inJustDecodeBounds = false; bmOptions.inSampleSize = scaleFactor; bmOptions.inPurgeable = true; /* Decode the JPEG file into a Bitmap */ Bitmap bitmap = BitmapFactory.decodeFile(imgFile.getAbsolutePath(), bmOptions); /* Associate the Bitmap to the ImageView */ imgView.setImageBitmap(bitmap); imgView.setVisibility(View.VISIBLE); } 

Ojalá hubiera conocido este antes en … todas esas horas: D

Nivel de visualización

Puede desactivar la aceleración de hardware para una vista individual en tiempo de ejecución con el código siguiente:

MyView.setLayerType (View.LAYER_TYPE_SOFTWARE, null);

NOTA PARA LOS QUE QUIEREN PONER IMÁGENES DE TAMAÑO PEQUEÑO:

La solución de Pilot_51 (mover las imágenes a la carpeta de drawable-nodpi ) funciona, pero tiene otro problema: Hace que las imágenes DEMASIADO PEQUEÑAS en la pantalla a menos que las imágenes sean redimensionadas a una resolución muy grande (como 2000 x 3800) para adaptarse a la pantalla. Tu aplicación más pesada.

SOLUCIÓN : poner sus archivos de imagen en drawable-hdpi – Funcionó como un encanto para mí.

El uso de la subcarpeta dibujable correcta resuelto para mí. Mi solución fue poner mi imagen de resolución completa (1920×1200) en la carpeta drawable-xhdpi , en lugar de la carpeta dibujable .

También puse una imagen reducida (1280×800) en la carpeta drawable-hdpi .

Estas dos resoluciones coinciden con las tablets 2013 y 2012 de Nexus 7 que estoy programando. También probé la solución en algunas otras tabletas.

 @Override protected void onActivityResult(int requestCode, int resultCode, Intent data) { super.onActivityResult(requestCode, resultCode, data); ///* if (requestCode == PICK_FROM_FILE && resultCode == RESULT_OK && null != data){ uri = data.getData(); String[] prjection ={MediaStore.Images.Media.DATA}; Cursor cursor = getContentResolver().query(uri,prjection,null,null,null); cursor.moveToFirst(); int columnIndex = cursor.getColumnIndex(prjection[0]); ImagePath = cursor.getString(columnIndex); cursor.close(); FixBitmap = BitmapFactory.decodeFile(ImagePath); ShowSelectedImage = (ImageView)findViewById(R.id.imageView); // FixBitmap = new BitmapDrawable(ImagePath); int nh = (int) ( FixBitmap.getHeight() * (512.0 / FixBitmap.getWidth()) ); FixBitmap = Bitmap.createScaledBitmap(FixBitmap, 512, nh, true); // ShowSelectedImage.setImageBitmap(BitmapFactory.decodeFile(ImagePath)); ShowSelectedImage.setImageBitmap(FixBitmap); } } 

Este código es trabajo

Uso webview para una resolución demasiado grande.

1-) Crear un archivo html sensible como el siguiente.

 <!DOCTYPE html> <html> <head> <meta charset="utf-8"> <title></title> <style> html, body, img { margin: 0; padding: 0; height: 100%; display: block; } </style> </head> <body> <img src="img/program_first.png"> </body> </html> 

2-) Utilizo la imagen 5708×1634 en la carpeta "img" que es muy grande horizontalmente. 3-) Añadir "webview" su diseño y establecer la carga de esta manera. "Program1" es el nombre de la variable WebView.

 program1.loadUrl("file:///android_asset/program/content.html"); 
  • Definir IDs dentro del estilo, ¿es seguro o es un desastre?
  • Google Maps Android API V2 ennegrece parte del diseño
  • Crear vista sobre cardview en android
  • Cómo escalar la imagen en Android CollapsingToolbarLayout como WunderList hace
  • Error al obtener el tamaño de la ventana en android: "El método getWindowManager no está definido"
  • Cambiar el estilo de ListPreference
  • RecyclerView autofit LayoutManager
  • Vista previa de enlaces en android
  • El atributo namespace de herramientas para mostrar el diseño en ViewPager en tiempo de diseño
  • Cómo hacer que un EditText tenga un ancho máximo pero todavía llene el ancho del padre
  • Valores de Android a diferentes tamaños de pantalla
  • FlipAndroid es un fan de Google para Android, Todo sobre Android Phones, Android Wear, Android Dev y Aplicaciones para Android Aplicaciones.