Comment obtenir un bitmap à partir d'un Uri?

209

Comment obtenir un objet Bitmap à partir d'un Uri (si je réussis à le stocker dans /data/data/MYFOLDER/myimage.pngoufile///data/data/MYFOLDER/myimage.png ) pour l'utiliser dans mon application?

Quelqu'un at-il une idée sur la façon d'accomplir cela?

ilredelweb
la source
30
Vous devriez mettre à jour votre réponse acceptée sur ce post, car il y a de meilleures réponses que la mienne.
Vidar Vestnes
1
La deuxième réponse est la bonne, la troisième réponse est plus complète.
IgniteCoders
@VidarVestnes Pourquoi ne le supprimez-vous pas?
Carlos López Marí

Réponses:

-36

. . IMPORTANT: Voir la réponse de @Mark Ingram ci-dessous et @pjv pour une meilleure solution. . .

Vous pouvez essayer ceci:

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

Mais rappelez-vous, cette méthode ne doit être appelée qu'à partir d'un thread (pas GUI -thread). Je suis une AsyncTask.

Vidar Vestnes
la source
2
Qu'en est-il de la conversion de l'URI en une URL, par exemple en utilisant yourUri.toURL ()?
Vidar Vestnes
7
@VidarVestnes buddy, comment le chemin de fichier peut-il être converti sur URL?
dharam
7
Je ne comprends pas comment c'est la réponse choisie
Nick Cardoso
11
Je suis d'accord, cette réponse ne doit pas être acceptée comme la meilleure. Peut-être que cela a été choisi parce que c'était la première réponse. C'est un vieux poste. Quoi qu'il en soit, voir les réponses ci-dessous pour de meilleures solutions.
Vidar Vestnes
8
@VidarVestnes vient de supprimer votre réponse
winklerrr
564

Voici la bonne façon de procéder:

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 vous devez charger de très grandes images, le code suivant le chargera dans des tuiles (en évitant les allocations de mémoire importantes):

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

Voir la réponse ici

Mark Ingram
la source
3
Ce code ne traite cependant pas les images plus grandes (essentiellement n'importe quelle taille de fond d'écran). getBitmap () appelle decodeStream () qui échoue avec l'erreur OOM de stackoverflow.com/questions/2220949/handling-large-bitmaps . Un autre conseil? MediaStore.Images.Thumbnails.getThumbnail () ne prend apparemment pas d'URI content.
pjv
1
Voir la réponse ici: stackoverflow.com/questions/4753013/…
Mark Ingram
@MarkIngram Est-ce que cela fonctionne avec une image locale ou simplement l'image de la caméra?
Narendra Singh
@MarkIngram et si nous n'avons pas accès à data.getData (), je veux dire que si j'ouvre simplement une image de la galerie et que je sais que c'est sur son chemin, comment puis-je obtenir l'uri et le bitmap?
Umair
@Umair, vous devriez poser une nouvelle question au lieu de la poser dans les commentaires d'une réponse. Au fait: jetez un œil ici developer.android.com/reference/android/net/Uri.html
winklerrr
112

Voici la bonne façon de le faire, en gardant également un œil sur l'utilisation de la mémoire:

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

L'appel getBitmap () du post de Mark Ingram appelle également decodeStream (), donc vous ne perdez aucune fonctionnalité.

Références:

pjv
la source
1
Cela m'a vraiment aidé, même si je pense qu'il vaut la peine de mentionner que le mot-clé this ne peut pas être utilisé dans un contexte statique. Je l'ai passé dans la méthode getThumbnail comme argument et cela fonctionne comme un charme.
MacKinley Smith
8
Quelqu'un peut-il me dire quelle valeur dois-je donner à THUMBNAILSIZE
Abid
2
La fermeture et la réouverture de InputStream est en fait nécessaire car le premier appel BitmapFactory.decodeStream (...) définit la position de lecture du flux jusqu'à la fin, de sorte que le deuxième appel de la méthode ne fonctionnerait plus sans rouvrir le flux!
DominicM
3
veuillez indiquer la valeur de THUMBNAILSIZE
Mightian
3
Il n'est pas nécessaire de calculer le rapport en tant que puissance de deux par vous-même car le décodeur lui-même arrondit à la taille de l'échantillon à la puissance la plus proche de deux. Par conséquent, l'appel de méthode getPowerOfTwoForSampleRatio()peut être ignoré. Voir: 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
}

et oui le chemin doit être dans un format comme celui-ci

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

DjP
la source
1
merci Itay, c'est simple, si vous avez le chemin, il vous suffit de passer ce chemin et d'obtenir le bitmap .. cela fonctionne pour moi, j'espère que vous essayez également cela ..
DjP
2
@Dhananjay Merci, votre indice me sauve la journée et cela fonctionne pour charger la miniature bitmap à partir du fournisseur de contenu.
Nezneika
2
De plus, Uri.parse () doit contenir le format URI, tout comme: Uri.parse ("file: ///mnt/sdcard/filename.jpg") , sinon nous obtiendrons java.io.FileNotFoundException: aucun contenu fournisseur .
Nezneika
Une certaine rédaction serait bien, mais c'est une bonne réponse concise à la question des PO qui fonctionne dans la plupart des cas. C'est une belle réponse à avoir sur la page afin de distiller le morceau de ces autres réponses qui répondent directement aux questions des PO.
umassthrower
1
@AndroidNewBee c est un objet contextuel.
DjP
17

C'est la solution la plus simple:

Bitmap bitmap = MediaStore.Images.Media.getBitmap(this.getContentResolver(), uri);
Hasib Akter
la source
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
la source
3
ça marche sur tous les sdk .. Merci. c'est une façon alternative deBitmap bitmap = MediaStore.Images.Media.getBitmap(context.getContentResolver(), uri);
Jigar Patel
la réponse la plus authentique satisfaite par tous les SDK
Noaman Akram
13

Il semble que ce MediaStore.Images.Media.getBitmapsoit obsolète API 29. La méthode recommandée consiste à utiliser ImageDecoder.createSourcece qui a été ajouté dansAPI 28 .

Voici comment obtenir le bitmap:

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
la source
11

Vous pouvez récupérer le bitmap de l'URI comme ceci

Bitmap bitmap = null;
try {
    bitmap = MediaStore.Images.Media.getBitmap(this.getContentResolver(), imageUri);
} catch (IOException e) {
    e.printStackTrace();
}
Emre AYDIN
la source
10
Uri imgUri = data.getData();
Bitmap bitmap = MediaStore.Images.Media.getBitmap(this.getContentResolver(), imgUri);
Ahmed Sayed
la source
2
Pourriez-vous expliquer comment ce code fonctionne et comment il répond à la question?
Michael Dodd
2

Utilisez le métode startActivityForResult comme ci-dessous

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

Et vous pouvez obtenir un résultat comme celui-ci:

@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
la source
2

J'ai essayé de nombreuses façons. ce travail pour moi parfaitement.

Si vous choisissez pictrue dans Gallery. Vous devez être prêt à Uripartir de intent.clipdataou intent.data, car l'un d'eux peut être nul dans une version différente.

  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 )
}
Cyrus
la source
1

vous pouvez faire cette structure:

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

par cela, vous pouvez facilement convertir un uri en bitmap. j'espère vous aider.

Sayed Mohammad Amin Emrani
la source
1
Cela ne fonctionne pas dans la version Android nougat 7.1.1. Cette extras.getParcelable ("données"); retourne null
Developer_vaibhav
1

Encart de ce getBitmapqui est depricated maintenant j'utilise l'approche suivante dans Kotlin

PICK_IMAGE_REQUEST ->
    data?.data?.let {
        val bitmap = BitmapFactory.decodeStream(contentResolver.openInputStream(it))
        imageView.setImageBitmap(bitmap)
    }
yaugenka
la source
1
  InputStream imageStream = null;
    try {
        imageStream = getContext().getContentResolver().openInputStream(uri);
    } catch (FileNotFoundException e) {
        e.printStackTrace();
    }
    final Bitmap selectedImage = BitmapFactory.decodeStream(imageStream);
Fawzi Nofal
la source
1

(KOTLIN) Donc, au 7 avril 2020, aucune des options mentionnées ci-dessus ne fonctionnait, mais voici ce qui a fonctionné pour moi:

  1. Si vous souhaitez stocker le bitmap dans un val et définir une imageView avec, utilisez ceci:

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

  2. Si vous souhaitez simplement définir le bitmap sur et imageView, utilisez ceci:

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

Advait Bansode
la source
0

Méthode complète pour obtenir l'URI de l'image à partir de la galerie mobile.

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
la source