Come ottenere Bitmap da un Uri?


209

Come ottenere un oggetto Bitmap da un Uri (se riesco a memorizzarlo in /data/data/MYFOLDER/myimage.pngo file///data/data/MYFOLDER/myimage.png) per usarlo nella mia applicazione?

Qualcuno ha un'idea su come realizzare questo?


30
Dovresti aggiornare la tua risposta accettata su questo post, poiché ci sono risposte migliori della mia.
Vidar Vestnes,

1
La seconda risposta è quella giusta, la terza risposta è più completa.
IgniteCoders,

@VidarVestnes Perché non lo elimini?
Carlos López Marí,

Risposte:


-36

. . IMPORTANTE: vedere la risposta da @Mark Ingram di seguito e @pjv per una soluzione migliore. . .

Puoi provare questo:

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

Ma ricorda, questo metodo dovrebbe essere chiamato solo da un thread (non dalla GUI -thread). Ho un AsyncTask.


2
Che ne dici di convertire l'URI in un url, ad esempio usando yourUri.toURL ()?
Vidar Vestnes,

7
@VidarVestnes amico, come può il percorso del file convertito su Url?
Dharam,

7
Non capisco come questa sia la risposta selezionata
Nick Cardoso,

11
Sono d'accordo, questa risposta non dovrebbe essere accettata come la migliore. Forse è stato scelto perché era la prima risposta. È un vecchio post. Ad ogni modo, vedi le risposte sotto per soluzioni migliori.
Vidar Vestnes,

8
@VidarVestnes cancella semplicemente la tua risposta
winklerrr

564

Ecco il modo corretto di farlo:

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

Se è necessario caricare immagini molto grandi, il codice seguente lo caricherà in riquadri (evitando allocazioni di memoria di grandi dimensioni):

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

Vedi la risposta qui


3
Questo codice non tratta però di immagini più grandi (praticamente qualsiasi dimensione dello sfondo). getBitmap () chiama decodeStream () che non riesce con l'errore OOM da stackoverflow.com/questions/2220949/handling-large-bitmaps . Qualche altro consiglio? MediaStore.Images.Thumbnails.getThumbnail () apparentemente non accetta un contenutoURI.
pjv,


@MarkIngram Funziona con qualsiasi immagine locale o solo l'immagine della telecamera?
Narendra Singh,

@MarkIngram cosa succede se non abbiamo accesso a data.getData (), voglio dire se apro semplicemente un'immagine dalla galleria e so tutti che riguarda il suo percorso, come posso ottenere uri e bitmap?
Umair,

@Umair dovresti fare una nuova domanda invece di porre nei commenti di una risposta. A proposito: dai un'occhiata qui developer.android.com/reference/android/net/Uri.html
winklerrr

112

Ecco il modo corretto di farlo, tenendo sotto controllo anche l'utilizzo della memoria:

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 chiamata getBitmap () dal post di Mark Ingram chiama anche decodeStream (), quindi non perdi alcuna funzionalità.

Riferimenti:


1
Questo mi ha davvero aiutato, anche se penso che valga la pena ricordare che questa parola chiave non può essere utilizzata in un contesto statico. L'ho passato al metodo getThumbnail come argomento e funziona come un incantesimo.
MacKinley Smith,

8
Qualcuno può dirmi quale valore dovrei dare a THUMBNAILSIZE
Abid

2
Chiudere e riaprire InputStream è effettivamente necessario perché la prima chiamata BitmapFactory.decodeStream (...) imposta la posizione di lettura dello stream alla fine, quindi la seconda chiamata del metodo non funzionerebbe più senza riaprire lo stream!
DominicM

3
si prega di dire il valore di THUMBNAILSIZE
Mightian

3
Non è necessario calcolare il rapporto come una potenza di due da soli perché il decodificatore stesso arrotonda per campionare la dimensione fino alla potenza più vicina di due. Pertanto la chiamata del metodo getPowerOfTwoForSampleRatio()può essere ignorata. Vedi: 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
}

e sì, il percorso deve essere in un formato simile a questo

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


1
grazie Itay, questo è semplice, se hai il percorso devi solo passare quel percorso e ottenere il Bitmap .. funziona per me, spero di provare anche questo ..
DjP

2
@Dhananjay Grazie, il tuo suggerimento mi salva la giornata e funziona per caricare la bitmap in miniatura dal provider di contenuti.
Nezneika,

2
Inoltre, Uri.parse () deve contenere il formato URI, proprio come: Uri.parse ("file: ///mnt/sdcard/filename.jpg") , in caso contrario avremo java.io.FileNotFoundException: nessun contenuto fornitore .
Nezneika,

Una certa editorializzazione sarebbe buona, ma questa è una buona risposta concisa alla domanda dei PO che funziona nella maggior parte dei casi. Questa è una bella risposta da avere sulla pagina per distillare il pezzo di queste altre risposte che rispondono direttamente alle domande dei PO.
umassthrower

1
@AndroidNewBee c è oggetto Context.
DjP,

17

Questa è la soluzione più semplice:

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
funziona su tutti gli sdk .. Grazie. è un modo alternativo diBitmap bitmap = MediaStore.Images.Media.getBitmap(context.getContentResolver(), uri);
Jigar Patel,

la risposta più autentica soddisfatta da tutti gli SDK
Noaman Akram,

13

Sembra che sia MediaStore.Images.Media.getBitmapstato deprecato in API 29. Il modo consigliato è usare quello ImageDecoder.createSourceche è stato aggiunto API 28.

Ecco come sarebbe ottenere la 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

Puoi recuperare bitmap da uri in questo modo

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
Potresti per favore approfondire come funziona questo codice e come risponde alla domanda?
Michael Dodd,

2

Utilizzare il metodo startActivityForResult come di seguito

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

E puoi ottenere risultati in questo modo:

@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

Ho provato molti modi. questo lavoro per me perfettamente.

Se scegli pictrue dalla Galleria. Devi essere informato di ottenere Urida intent.clipdatao intent.data, perché uno di essi potrebbe essere nullo in una versione diversa.

  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

puoi fare questa struttura:

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 questo puoi facilmente convertire un uri in bitmap. spero ti aiuti.


1
Questo non funziona nella versione di Android Nougat 7.1.1. Questo extras.getParcelable ("dati"); restituisce null
Developer_vaibhav

1

Il getBitmapcui riquadro è deprecato ora utilizzo il seguente approccio in 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) Quindi, dal 7 aprile 2020 nessuna delle opzioni sopra menzionate ha funzionato, ma ecco cosa ha funzionato per me:

  1. Se si desidera archiviare la bitmap in un val e impostare un'immagine con essa, utilizzare questo:

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

  2. Se vuoi solo impostare bitmap e imageView, usa questo:

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


0

Metodo completo per ottenere immagini uri dalla galleria 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();
      }


   }
}
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.