Wie bekomme ich Bitmap von einem Uri?

209

Wie erhalte ich ein Bitmap-Objekt von einem Uri (wenn es mir gelingt, es in /data/data/MYFOLDER/myimage.pngoder zu speichern file///data/data/MYFOLDER/myimage.png), um es in meiner Anwendung zu verwenden?

Hat jemand eine Idee, wie dies erreicht werden kann?

ilredelweb
quelle
30
Sie sollten Ihre akzeptierte Antwort in diesem Beitrag aktualisieren, da es bessere Antworten als meine gibt.
Vidar Vestnes
1
Die zweite Antwort ist die richtige, die dritte Antwort ist vollständiger.
IgniteCoders
@VidarVestnes Warum löschst du es nicht?
Carlos López Marí

Antworten:

-35

. . WICHTIG: Siehe Antwort von @Mark Ingram unten und @pjv für eine bessere Lösung. . .

Sie könnten dies versuchen:

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

Denken Sie jedoch daran, dass diese Methode nur innerhalb eines Threads aufgerufen werden sollte (nicht GUI-Thread). Ich bin eine AsyncTask.

Vidar Vestnes
quelle
2
Was ist mit der Konvertierung des URI in eine URL, z. B. mithilfe von yourUri.toURL ()?
Vidar Vestnes
7
@VidarVestnes Kumpel, wie kann der Dateipfad auf URL konvertiert werden?
Dharam
7
Ich verstehe nicht, wie dies die ausgewählte Antwort ist
Nick Cardoso
11
Ich stimme zu, diese Antwort sollte nicht als die beste akzeptiert werden. Vielleicht wurde es gewählt, weil es die erste Antwort war. Es ist ein alter Beitrag. Wie auch immer, siehe Antworten unten für bessere Lösungen.
Vidar Vestnes
8
@VidarVestnes löschen Sie einfach Ihre Antwort
winklerrr
564

Hier ist die richtige Vorgehensweise:

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

Wenn Sie sehr große Bilder laden müssen, wird sie mit dem folgenden Code in Kacheln geladen (wobei große Speicherzuordnungen vermieden werden):

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

Siehe die Antwort hier

Mark Ingram
quelle
3
Dieser Code behandelt jedoch keine größeren Bilder (im Grunde alles, was das Hintergrundbild betrifft). getBitmap () ruft decodeStream () auf, was mit dem OOM-Fehler von stackoverflow.com/questions/2220949/handling-large-bitmaps fehlschlägt . Irgendwelche anderen Ratschläge? MediaStore.Images.Thumbnails.getThumbnail () nimmt anscheinend keine contentURI an.
pjv
1
Die Antwort finden Sie hier: stackoverflow.com/questions/4753013/…
Mark Ingram
@MarkIngram Funktioniert dies mit einem lokalen Bild oder nur mit dem Kamerabild?
Narendra Singh
@MarkIngram Was ist, wenn wir keinen Zugriff auf data.getData () haben? Ich meine, wenn ich einfach ein Bild aus der Galerie öffne und weiß, dass es sich um den Pfad handelt, wie kann ich dann Uri und Bitmap erhalten?
Umair
@Umair sollten Sie eine neue Frage stellen, anstatt in den Kommentaren einer Antwort zu fragen. Übrigens: Schauen Sie hier unter developer.android.com/reference/android/net/Uri.html
winklerrr
111

Hier ist die richtige Vorgehensweise, bei der auch die Speichernutzung im Auge behalten wird:

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

Der Aufruf von getBitmap () aus Mark Ingrams Beitrag ruft auch decodeStream () auf, sodass Sie keine Funktionalität verlieren.

Verweise:

pjv
quelle
1
Dies hat mir wirklich geholfen, obwohl ich denke, dass es erwähnenswert ist, dass das Schlüsselwort this nicht in einem statischen Kontext verwendet werden kann. Ich habe es als Argument an die getThumbnail-Methode übergeben und es funktioniert wie ein Zauber.
MacKinley Smith
8
Kann mir jemand sagen, welchen Wert ich THUMBNAILSIZE geben soll
Abid
2
Das Schließen und erneute Öffnen des InputStream ist tatsächlich erforderlich, da der erste Aufruf von BitmapFactory.decodeStream (...) die Leseposition des Streams auf das Ende setzt, sodass der zweite Aufruf der Methode ohne erneutes Öffnen des Streams nicht mehr funktioniert!
DominicM
3
Bitte teilen Sie den Wert von THUMBNAILSIZE
Mightian
3
Es ist nicht erforderlich, das Verhältnis selbst als Zweierpotenz zu berechnen, da der Decoder selbst auf die Abtastgröße auf die nächste Zweierpotenz rundet. Daher kann der Methodenaufruf getPowerOfTwoForSampleRatio()übersprungen werden. Siehe: 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
}

und ja Pfad muss in einem Format wie diesem sein

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

DjP
quelle
1
danke Itay, das ist einfach, wenn du den Pfad hast, musst du nur diesen Pfad passieren und die Bitmap bekommen. Es funktioniert für mich. Ich hoffe, du versuchst es auch.
DjP
2
@Dhananjay Vielen Dank, Ihr Hinweis rettet meinen Tag und es funktioniert, um die Miniaturbild-Bitmap von Content Provider zu laden.
Nezneika
2
Außerdem muss Uri.parse () das URI-Format enthalten, genau wie: Uri.parse ("file: ///mnt/sdcard/filename.jpg") , andernfalls erhalten wir java.io.FileNotFoundException: Kein Inhalt Anbieter .
Nezneika
Eine gewisse Redaktion wäre nett, aber dies ist eine gute, präzise Antwort auf die OP-Frage, die in den meisten Fällen funktioniert. Dies ist eine nette Antwort auf der Seite, um den Teil dieser anderen Antworten herauszuarbeiten, die die Fragen des OP direkt beantworten.
umassthrower
1
@AndroidNewBee c ist ein Kontextobjekt.
DjP
17

Dies ist die einfachste Lösung:

Bitmap bitmap = MediaStore.Images.Media.getBitmap(this.getContentResolver(), uri);
Hasib Akter
quelle
15
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
quelle
3
es funktioniert auf allen sdk .. Danke. Es ist eine alternative Art vonBitmap bitmap = MediaStore.Images.Media.getBitmap(context.getContentResolver(), uri);
Jigar Patel
Die echteste Antwort, die alle SDK zufrieden waren
Noaman Akram
13

Es scheint, dass MediaStore.Images.Media.getBitmapin veraltet war API 29. Die empfohlene Methode ist die Verwendung, ImageDecoder.createSourcedie hinzugefügt wurde API 28.

So erhalten Sie die 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
quelle
11

Sie können Bitmap wie folgt von uri abrufen

Bitmap bitmap = null;
try {
    bitmap = MediaStore.Images.Media.getBitmap(this.getContentResolver(), imageUri);
} catch (IOException e) {
    e.printStackTrace();
}
Emre AYDIN
quelle
10
Uri imgUri = data.getData();
Bitmap bitmap = MediaStore.Images.Media.getBitmap(this.getContentResolver(), imgUri);
Ahmed sagte
quelle
2
Könnten Sie bitte näher erläutern, wie dieser Code funktioniert und wie er die Frage beantwortet?
Michael Dodd
2

Verwenden Sie die metA startActivityForResult wie unten

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

Und Sie können Ergebnis wie folgt erhalten:

@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
quelle
2

Ich habe viele Möglichkeiten ausprobiert. diese Arbeit für mich perfekt.

Wenn Sie Pictrue aus der Galerie auswählen. Sie müssen vorsichtig sein, wenn Sie Urivon intent.clipdataoder kommen intent.data, da einer von ihnen in einer anderen Version möglicherweise null ist.

  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
quelle
1

Sie können diese Struktur tun:

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

Auf diese Weise können Sie eine Uri einfach in eine Bitmap konvertieren. hoffe hilf dir

Sagte Mohammad Amin Emrani
quelle
1
Dies funktioniert nicht in Android Nougat 7.1.1 Version. Diese extras.getParcelable ("Daten"); gibt null zurück
Developer_vaibhav
1

Ein Teil getBitmapdavon ist jetzt beraubt. Ich verwende den folgenden Ansatz in Kotlin

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

Vollständige Methode, um Bild-Uri aus der mobilen Galerie zu erhalten.

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
quelle
0

(KOTLIN) Ab dem 7. April 2020 hat keine der oben genannten Optionen funktioniert, aber hier ist, was für mich funktioniert hat:

  1. Wenn Sie die Bitmap in einem Wert speichern und damit eine Bildansicht festlegen möchten, verwenden Sie Folgendes:

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

  2. Wenn Sie nur die Bitmap und imageView festlegen möchten, verwenden Sie Folgendes:

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

Advait Bansode
quelle