2012-05-18 14 views
6

Tengo un archivo con una imagen muy grande: por ejemplo, 9000x9000.Decodificar una parte del mapa de bits del archivo en Android

No puedo cargar el mapa de bits en la memoria debido al tamaño del montón. Pero solo necesito mostrar una pequeña parte de este mapa de bits, por ejemplo, el ancho rect = 100-200 y height = 200-400 (tamaño resultante del sub-bitmap = 100x200)

¿Cómo puedo recuperar este mapa de bits del ¿archivo?

Nota: No quiero perder calidad en la imagen de 100x200

Gracias

Respuesta

12

es posible que hay una solución para esto?

por ejemplo, BitmapRegionDecoder.

Se debe trabajar para API10 y por encima ...

+0

aparentemente esa sería la respuesta correcta. – njzk2

+0

Gracias, acabo de usarlo. Funciona. –

0

no creo que pueda. Ni siquiera en una PC, no veo cómo podría hacerlo sin cargar toda la imagen: la mayoría de los formatos de imagen, por ejemplo PNG, tienen los datos de píxeles comprimidos, por lo que necesita al menos descomprimir el fragmento IDAT antes de poder comenzar a hacer cualquier otra cosa y eso básicamente decodificará toda la imagen.

En sus zapatos, trataría de hacer que un servidor lo haga por mí. ¿De dónde sacas la imagen de todos modos? No de un servidor? Luego intente realizar una solicitud de WS que le proporcione la parte adecuada de la imagen. Si la imagen NO proviene del servidor, puede enviarla a su servidor para obtener solo la parte de la imagen que desea.

+0

Gracias por su respuesta. Lo que estoy tratando de hacer es implementar un MultiTouchImageView y eso es para cargar solo la parte de la imagen visible debido al zoom y la posición de desplazamiento, lo que permite cargar imágenes grandes sin perder calidad y sin fallos de memoria. ¿Cómo puedo hacer eso? – Addev

+0

En ese caso, creo que lo que estás tratando de hacer es simplemente imposible desde el punto de vista técnico con las limitaciones de un dispositivo móvil: simplemente no puedes ofrecer al usuario una buena experiencia sin cargar toda la imagen en la memoria y simplemente mostrar la parte que necesitas . Incluso si pudieras cargar solo una parte de la imagen, tendrías que hacerlo cada vez que el usuario moviera o ampliara un poco el zoom ... dado que la operación sería lenta, la experiencia del usuario sería horrible de todos modos. La única forma de hacerlo es poner un límite superior al tamaño de la imagen. De lo contrario, simplemente no puede hacerlo en mi humilde opinión. –

+0

Hmmm lo que dices es muy lógico, pero ¿cómo carga la Galería de Android esas imágenes grandes que permiten acercarse con la misma calidad? – Addev

2

Creo que puede usar el método BitmapFactory que le permite especificar el Rect que desea decodificar.

public static Bitmap decodeStream (InputStream is, Rect outPadding, BitmapFactory.Options opts) 
+0

OutPadding es un parámetro de salida – Addev

+0

@Addev. Soy muy interesante. ¿No crees que solo se puede tomar? algunos rect de mapas de bits antes de importarlo? :) –

+0

¿en qué casos se llena el outPadding? cuando es 9-parche? ¿Hay otros casos? Además, incluso si es de 9 parches, ¿qué significa y qué se llenaría? –

0

prueba este código:

private Bitmap decodeFile(File f) { 
    Bitmap b = null; 
    try { 
     BitmapFactory.Options o = new BitmapFactory.Options(); 
     o.inJustDecodeBounds = true; 
     FileInputStream fis = new FileInputStream(f); 
     b=Bitmap.createBitmap(BitmapFactory.decodeStream(fis, null, o), 100, 200, 200, 400, null, null); 
     fis.close(); 
    } catch (IOException e) { 
    } 
    return b; 
} 

no estoy seguro, pero esto puede dar una idea de que

+0

Da un error de falta de memoria porque el BitmapFactory.decodeStream (fis, null, o) no regresa hasta que se recupera todo el mapa de bits – Addev

4

Se puede hacer fácilmente usando RapidDecoder.

En realidad, generé un png de 9000x9000 cuyo tamaño de archivo es de aproximadamente 80 MB y la región de tamaño 200x400 se cargó correctamente.

import rapid.decoder.BitmapDecoder; 

Bitmap bitmap = BitmapDecoder.from("big-image.png") 
          .region(145, 192, 145 + 200, 192 + 400) 
          .decode(); 
imageView.setImageBitmap(bitmap); 

Funciona para Android 2.2 y superior.

+0

Guau, esto suena prometedor. se hace la decodificación completa en JNI? ¿Qué formatos de archivo son compatibles? ¿Incluso es compatible con WebP? ¿incluye la detección de rostros? –

+0

+1 biblioteca muy buena, también la calidad de la imagen es 80% mantenida ... y funciona en casi todos los dispositivos –

1

probar este código:

public static Bitmap decodeSampledBitmapFromFile(String path, int reqWidth, int reqHeight) { 
     final BitmapFactory.Options options = new BitmapFactory.Options(); 
     options.inJustDecodeBounds = true; 
     BitmapFactory.decodeFile(path, options); 

     final int height = options.outHeight; 
     final int width = options.outWidth; 
     options.inPreferredConfig = Bitmap.Config.RGB_565; 
     int inSampleSize = 1; 
     if (height > reqHeight) { 
      inSampleSize = Math.round((float) height/(float) reqHeight); 
     } 
     int expectedWidth = width/inSampleSize; 
     if (expectedWidth > reqWidth) { 
      inSampleSize = Math.round((float) width/(float) reqWidth); 
     } 
     options.inSampleSize = inSampleSize; 
     options.inJustDecodeBounds = false; 
     return BitmapFactory.decodeFile(path, options); 
    } 
Cuestiones relacionadas