¿Cómo obtener Bitmap de un Uri?


209

¿Cómo obtener un objeto de mapa de bits de un Uri (si logro almacenarlo en /data/data/MYFOLDER/myimage.pngo file///data/data/MYFOLDER/myimage.png) para usarlo en mi aplicación?

¿Alguien tiene una idea sobre cómo lograr esto?


30
Debes actualizar tu respuesta aceptada en esta publicación, ya que hay mejores respuestas que la mía.
Vidar Vestnes

1
La segunda respuesta es la correcta, la tercera respuesta es más completa.
IgniteCoders

@VidarVestnes ¿Por qué no lo eliminas?
Carlos López Marí

Respuestas:


-36

. . IMPORTANTE: Vea la respuesta de @Mark Ingram a continuación y @pjv para una mejor solución. . .

Podrías probar esto:

public Bitmap loadBitmap(String url)
{
    Bitmap bm = null;
    InputStream is = null;
    BufferedInputStream bis = null;
    try 
    {
        URLConnection conn = new URL(url).openConnection();
        conn.connect();
        is = conn.getInputStream();
        bis = new BufferedInputStream(is, 8192);
        bm = BitmapFactory.decodeStream(bis);
    }
    catch (Exception e) 
    {
        e.printStackTrace();
    }
    finally {
        if (bis != null) 
        {
            try 
            {
                bis.close();
            }
            catch (IOException e) 
            {
                e.printStackTrace();
            }
        }
        if (is != null) 
        {
            try 
            {
                is.close();
            }
            catch (IOException e) 
            {
                e.printStackTrace();
            }
        }
    }
    return bm;
}

Pero recuerde, este método solo debe llamarse desde un hilo (no un hilo GUI). Soy una AsyncTask.


2
¿Qué hay de convertir el URI a una url, por ejemplo, usando yourUri.toURL ()?
Vidar Vestnes

77
@VidarVestnes amigo, ¿cómo se puede convertir la ruta del archivo en la URL?
dharam

77
No entiendo cómo esta es la respuesta seleccionada
Nick Cardoso

11
Estoy de acuerdo, esta respuesta no debe aceptarse como la mejor. Tal vez fue elegido porque fue la primera respuesta. Es una publicación antigua. De todos modos, vea las respuestas a continuación para obtener mejores soluciones.
Vidar Vestnes

8
@VidarVestnes simplemente borra tu respuesta
winklerrr

564

Aquí está la forma correcta de hacerlo:

protected void onActivityResult(int requestCode, int resultCode, Intent data)
{
    super.onActivityResult(requestCode, resultCode, data);
    if (resultCode == RESULT_OK)
    {
        Uri imageUri = data.getData();
        Bitmap bitmap = MediaStore.Images.Media.getBitmap(this.getContentResolver(), imageUri);
    }
}

Si necesita cargar imágenes muy grandes, el siguiente código lo cargará en mosaicos (evitando asignaciones de memoria grandes):

BitmapRegionDecoder decoder = BitmapRegionDecoder.newInstance(myStream, false);  
Bitmap region = decoder.decodeRegion(new Rect(10, 10, 50, 50), null);

Mira la respuesta aquí


3
Sin embargo, este código no trata con imágenes más grandes (básicamente cualquier tamaño de fondo de pantalla). getBitmap () llama a decodeStream () que falla con el error OOM de stackoverflow.com/questions/2220949/handling-large-bitmaps . ¿Algún otro consejo? MediaStore.Images.Thumbnails.getThumbnail () aparentemente no toma un contentURI.
pjv


@ MarkIngram ¿Funciona con alguna imagen local o solo con la imagen de la cámara?
Narendra Singh

@MarkIngram, ¿qué pasa si no tenemos acceso a data.getData (), es decir, si simplemente abro alguna imagen de la galería y sé que se trata de su ruta, ¿cómo puedo obtener uri y mapa de bits?
Umair

@Umair, debe hacer una nueva pregunta en lugar de preguntar en los comentarios de una respuesta. Por cierto: eche un vistazo aquí developer.android.com/reference/android/net/Uri.html
winklerrr

112

Aquí está la forma correcta de hacerlo, manteniendo un control del uso de la memoria también:

protected void onActivityResult(int requestCode, int resultCode, Intent data)
{
  super.onActivityResult(requestCode, resultCode, data);
  if (resultCode == RESULT_OK)
  {
    Uri imageUri = data.getData();
    Bitmap bitmap = getThumbnail(imageUri);
  }
}

public static Bitmap getThumbnail(Uri uri) throws FileNotFoundException, IOException{
  InputStream input = this.getContentResolver().openInputStream(uri);

  BitmapFactory.Options onlyBoundsOptions = new BitmapFactory.Options();
  onlyBoundsOptions.inJustDecodeBounds = true;
  onlyBoundsOptions.inDither=true;//optional
  onlyBoundsOptions.inPreferredConfig=Bitmap.Config.ARGB_8888;//optional
  BitmapFactory.decodeStream(input, null, onlyBoundsOptions);
  input.close();

  if ((onlyBoundsOptions.outWidth == -1) || (onlyBoundsOptions.outHeight == -1)) {
    return null;
  }

  int originalSize = (onlyBoundsOptions.outHeight > onlyBoundsOptions.outWidth) ? onlyBoundsOptions.outHeight : onlyBoundsOptions.outWidth;

  double ratio = (originalSize > THUMBNAIL_SIZE) ? (originalSize / THUMBNAIL_SIZE) : 1.0;

  BitmapFactory.Options bitmapOptions = new BitmapFactory.Options();
  bitmapOptions.inSampleSize = getPowerOfTwoForSampleRatio(ratio);
  bitmapOptions.inDither = true; //optional
  bitmapOptions.inPreferredConfig=Bitmap.Config.ARGB_8888;//
  input = this.getContentResolver().openInputStream(uri);
  Bitmap bitmap = BitmapFactory.decodeStream(input, null, bitmapOptions);
  input.close();
  return bitmap;
}

private static int getPowerOfTwoForSampleRatio(double ratio){
  int k = Integer.highestOneBit((int)Math.floor(ratio));
  if(k==0) return 1;
  else return k;
}

La llamada getBitmap () de la publicación de Mark Ingram también llama a decodeStream (), por lo que no pierde ninguna funcionalidad.

Referencias


1
Esto realmente me ayudó, aunque creo que vale la pena mencionar que esta palabra clave no se puede usar desde un contexto estático. Lo pasé al método getThumbnail como argumento y funciona de maravilla.
MacKinley Smith

8
¿Alguien puede decirme qué valor debo darle a THUMBNAILSIZE
Abid

2
Cerrar y volver a abrir InputStream es realmente necesario porque la primera llamada a BitmapFactory.decodeStream (...) establece la posición de lectura de la secuencia hasta el final, por lo que la segunda llamada del método ya no funcionaría sin volver a abrir la secuencia.
DominicM

3
por favor diga el valor de THUMBNAILSIZE
Mightian

3
No es necesario calcular la proporción como una potencia de dos usted mismo porque el decodificador se redondea al tamaño de la muestra a la potencia de dos más cercana. Por lo tanto, getPowerOfTwoForSampleRatio()se puede omitir la llamada al método . Ver: developer.android.com/reference/android/graphics/…
winklerrr

42
try
{
    Bitmap bitmap = MediaStore.Images.Media.getBitmap(c.getContentResolver() , Uri.parse(paths));
}
catch (Exception e) 
{
    //handle exception
}

y sí, la ruta debe estar en un formato como este

file:///mnt/sdcard/filename.jpg


1
gracias Itay, esto es simple, si tienes el camino solo tienes que pasar ese camino y obtener el mapa de bits ... está funcionando para mí, espero que también intentes esto ...
DjP

2
@Dhananjay Gracias, su sugerencia me salva el día y funciona para cargar el mapa de bits en miniatura desde el Proveedor de contenido.
Nezneika

2
Además, el Uri.parse () debe contener el formato URI, al igual que: Uri.parse ("file: ///mnt/sdcard/filename.jpg") , de lo contrario obtendremos java.io.FileNotFoundException: Sin contenido proveedor .
Nezneika

Alguna editorialización sería buena, pero esta es una buena respuesta concisa a la pregunta de OP que funciona en la mayoría de los casos. Esta es una buena respuesta para tener en la página en aras de destilar la parte de estas otras respuestas que responden directamente a las preguntas de los OP.
umassthrower

1
@AndroidNewBee c es un objeto de contexto.
DjP

17

Esta es la solución más fácil:

Bitmap bitmap = MediaStore.Images.Media.getBitmap(this.getContentResolver(), uri);

16
private void uriToBitmap(Uri selectedFileUri) {
    try {
        ParcelFileDescriptor parcelFileDescriptor =
                getContentResolver().openFileDescriptor(selectedFileUri, "r");
        FileDescriptor fileDescriptor = parcelFileDescriptor.getFileDescriptor();
        Bitmap image = BitmapFactory.decodeFileDescriptor(fileDescriptor);

        parcelFileDescriptor.close();
    } catch (IOException e) {
        e.printStackTrace();
    }
}

3
funciona en todos los sdk .. Gracias. es una forma alternativa deBitmap bitmap = MediaStore.Images.Media.getBitmap(context.getContentResolver(), uri);
Jigar Patel

la respuesta más genuina que todo SDK satisface
Noaman Akram

13

Parece que MediaStore.Images.Media.getBitmapfue obsoleto en API 29. La forma recomendada es usar el ImageDecoder.createSourceque se agregó API 28.

Así es como se haría el mapa de bits:

val bitmap = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.P) {
    ImageDecoder.decodeBitmap(ImageDecoder.createSource(requireContext().contentResolver, imageUri))
} else {
    MediaStore.Images.Media.getBitmap(requireContext().contentResolver, imageUri)
}

11

Puede recuperar el mapa de bits de uri como este

Bitmap bitmap = null;
try {
    bitmap = MediaStore.Images.Media.getBitmap(this.getContentResolver(), imageUri);
} catch (IOException e) {
    e.printStackTrace();
}

10
Uri imgUri = data.getData();
Bitmap bitmap = MediaStore.Images.Media.getBitmap(this.getContentResolver(), imgUri);

2
¿Podría explicar cómo funciona este código y cómo responde la pregunta?
Michael Dodd

2

Use el método startActivityForResult como se muestra a continuación

        startActivityForResult(new Intent(Intent.ACTION_PICK).setType("image/*"), PICK_IMAGE);

Y puede obtener un resultado como este:

@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
    if (resultCode != RESULT_OK) {
        return;
    }
    switch (requestCode) {
        case PICK_IMAGE:
            Uri imageUri = data.getData();
            try {
                Bitmap bitmap = MediaStore.Images.Media.getBitmap(this.getContentResolver(), imageUri);
            } catch (IOException e) {
                e.printStackTrace();
            }
         break;
    }
}

2

Lo he intentado de muchas maneras. Esto me funciona perfectamente.

Si elige pictrue de la galería. Tienes que ser utensilios de conseguir Uria partir de intent.clipdatao intent.data, debido a que uno de ellos puede ser nulo en versión diferente.

  private fun onChoosePicture(data: Intent?):Bitmap {
        data?.let {
            var fileUri:Uri? = null

              data.clipData?.let {clip->
                  if(clip.itemCount>0){
                      fileUri = clip.getItemAt(0).uri
                  }
              }
            it.data?.let {uri->
                fileUri = uri
            }


               return MediaStore.Images.Media.getBitmap(this.contentResolver, fileUri )
}

1

puedes hacer esta estructura:

protected void onActivityResult(int requestCode, int resultCode, Intent imageReturnedIntent) {
    super.onActivityResult(requestCode, resultCode, imageReturnedIntent);
    switch(requestCode) {
        case 0:
            if(resultCode == RESULT_OK){
                    Uri selectedImage = imageReturnedIntent.getData();
                    Bundle extras = imageReturnedIntent.getExtras();
                    bitmap = extras.getParcelable("data");
            }
            break;
   }

con esto puedes convertir fácilmente una uri a mapa de bits. Espero ayudarte.


1
Esto no funciona en la versión de Android turrón 7.1.1. Este extras.getParcelable ("datos"); está volviendo nulo
Developer_vaibhav

1

El recuadro del getBitmapcual está depricado ahora uso el siguiente enfoque en Kotlin

PICK_IMAGE_REQUEST ->
    data?.data?.let {
        val bitmap = BitmapFactory.decodeStream(contentResolver.openInputStream(it))
        imageView.setImageBitmap(bitmap)
    }

1
  InputStream imageStream = null;
    try {
        imageStream = getContext().getContentResolver().openInputStream(uri);
    } catch (FileNotFoundException e) {
        e.printStackTrace();
    }
    final Bitmap selectedImage = BitmapFactory.decodeStream(imageStream);

1

(KOTLIN) Entonces, a partir del 7 de abril de 2020, ninguna de las opciones mencionadas funcionó, pero esto es lo que funcionó para mí:

  1. Si desea almacenar el mapa de bits en un val y establecer una imagen con él, use esto:

    val bitmap = BitmapFactory.decodeFile(currentPhotoPath).also { bitmap -> imageView.setImageBitmap(bitmap) }

  2. Si solo desea establecer el mapa de bits e imageView, use esto:

    BitmapFactory.decodeFile(currentPhotoPath).also { bitmap -> imageView.setImageBitmap(bitmap) }


0

Método completo para obtener la imagen uri de la galería móvil.

protected void onActivityResult(int requestCode, int resultCode, Intent data) {
        super.onActivityResult(requestCode, resultCode, data);

  if (requestCode == PICK_IMAGE_REQUEST && resultCode == RESULT_OK && data != null && data.getData() != null) {
                Uri filePath = data.getData();

     try { //Getting the Bitmap from Gallery
           Bitmap bitmap = MediaStore.Images.Media.getBitmap(getContentResolver(), filePath);
           rbitmap = getResizedBitmap(bitmap, 250);//Setting the Bitmap to ImageView
           serImage = getStringImage(rbitmap);
           imageViewUserImage.setImageBitmap(rbitmap);
      } catch (IOException e) {
           e.printStackTrace();
      }


   }
}
Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.