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?


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.


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


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


@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:


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


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

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
ç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)
}

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

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

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

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

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.


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

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

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


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


   }
}
En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.