¿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?

ilredelweb
fuente
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.

Vidar Vestnes
fuente
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í

Mark Ingram
fuente
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
1
Vea la respuesta aquí: stackoverflow.com/questions/4753013/…
Mark Ingram
@ 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

pjv
fuente
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

DjP
fuente
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);
Hasib Akter
fuente
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();
    }
}
DeltaCap019
fuente
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)
}
Ika
fuente
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();
}
Emre AYDIN
fuente
10
Uri imgUri = data.getData();
Bitmap bitmap = MediaStore.Images.Media.getBitmap(this.getContentResolver(), imgUri);
Ahmed Sayed
fuente
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;
    }
}
Faxriddin Abdullayev
fuente
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 )
}
Ciro
fuente
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.

Sayed Mohammad Amin Emrani
fuente
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)
    }
yaugenka
fuente
1
  InputStream imageStream = null;
    try {
        imageStream = getContext().getContentResolver().openInputStream(uri);
    } catch (FileNotFoundException e) {
        e.printStackTrace();
    }
    final Bitmap selectedImage = BitmapFactory.decodeStream(imageStream);
Fawzi Nofal
fuente
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) }

Advance Bansode
fuente
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();
      }


   }
}
Zzmilanzz Zzmadubashazz
fuente