Bagaimana cara mendapatkan Bitmap dari Uri?

209

Cara mendapatkan objek Bitmap dari Uri (jika saya berhasil menyimpannya di /data/data/MYFOLDER/myimage.pngataufile///data/data/MYFOLDER/myimage.png ) menggunakannya di aplikasi saya?

Adakah yang punya ide tentang bagaimana mencapainya?

ilredelweb
sumber
30
Anda harus memperbarui jawaban yang Anda terima pada pos ini, karena ada jawaban yang lebih baik daripada saya.
Vidar Vestnes
1
The Jawaban kedua adalah yang benar, yang jawaban ketiga lebih lengkap.
IgniteCoders
@VidarVestnes Mengapa Anda tidak menghapusnya?
Carlos López Marí

Jawaban:

-35

. . PENTING: Lihat jawaban dari @Mark Ingram di bawah ini dan @pjv untuk solusi yang lebih baik. . .

Anda bisa mencoba ini:

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

Tapi ingat, metode ini seharusnya hanya dipanggil dari dalam utas (bukan GUI -baca). Saya seorang AsyncTask.

Vidar Vestnes
sumber
2
Bagaimana dengan mengonversi URI ke url, mis. Dengan menggunakanUri.toURL () Anda?
Vidar Vestnes
7
@VidarVestnes sobat, bagaimana jalur file dapat dikonversi pada Url?
dharam
7
Saya tidak mengerti bagaimana ini adalah jawaban yang dipilih
Nick Cardoso
11
Saya setuju, jawaban ini tidak boleh diterima sebagai yang terbaik. Mungkin itu dipilih karena itu adalah jawaban pertama. Ini adalah pos lama. Anyway, se jawaban di bawah ini untuk solusi yang lebih baik.
Vidar Vestnes
8
@VidarVestnes cukup hapus jawaban Anda
winklerrr
564

Inilah cara yang benar untuk melakukannya:

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

Jika Anda perlu memuat gambar yang sangat besar, kode berikut akan memuatnya dalam ubin (menghindari alokasi memori yang besar):

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

Lihat jawabannya di sini

Tandai Ingram
sumber
3
Kode ini tidak berurusan dengan gambar yang lebih besar (pada dasarnya ukuran wallpaper apa pun). getBitmap () memanggil decodeStream () yang gagal dengan kesalahan OOM dari stackoverflow.com/questions/2220949/handling-large-bitmaps . Ada saran lain? MediaStore.Images.Thumbnails.getThumbnail () ternyata tidak mengambil kontenURI.
pjv
1
Lihat jawabannya di sini: stackoverflow.com/questions/4753013/…
Mark Ingram
@MarkIngram Apakah ini berfungsi dengan gambar lokal atau hanya gambar kamera?
Narendra Singh
@MarkIngram bagaimana jika kita tidak memiliki akses ke data.getData (), maksud saya jika saya hanya membuka beberapa gambar dari galeri dan saya semua tahu tentang jalurnya, bagaimana saya bisa mendapatkan uri dan bitmap?
Umair
@Umair, Anda harus mengajukan pertanyaan baru alih-alih bertanya dalam komentar atas jawaban. Omong-omong: lihat di sini developer.android.com/reference/android/net/Uri.html
winklerrr
112

Inilah cara yang benar untuk melakukannya, mengawasi penggunaan memori juga:

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

Panggilan getBitmap () dari pos Mark Ingram juga memanggil decodeStream (), sehingga Anda tidak kehilangan fungsionalitas apa pun.

Referensi:

pjv
sumber
1
Ini benar-benar membantu saya, walaupun saya pikir perlu disebutkan bahwa kata kunci ini tidak dapat digunakan dalam konteks statis. Saya meneruskannya ke metode getThumbnail sebagai argumen dan itu berfungsi seperti pesona.
MacKinley Smith
8
Adakah yang bisa memberi tahu saya nilai apa yang harus saya berikan kepada THUMBNAILSIZE
Abid
2
Menutup dan membuka kembali InputStream sebenarnya diperlukan karena panggilan BitmapFactory.decodeStream (...) pertama mengatur posisi pembacaan aliran ke akhir, sehingga panggilan kedua metode ini tidak akan berfungsi lagi tanpa membuka kembali aliran!
DominicM
3
tolong beri tahu nilai
THUMBNAILSIZE
3
Tidak perlu menghitung rasio sebagai kekuatan dua sendiri karena dekoder sendiri membulatkan ukuran sampel ke kekuatan terdekat dua. Oleh karena itu pemanggilan metode getPowerOfTwoForSampleRatio()dapat dilewati. Lihat: 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
}

dan ya path harus dalam format seperti ini

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

DjP
sumber
1
terima kasih Itay, ini sederhana, jika kamu memiliki path kamu hanya harus melewati path itu dan mendapatkan Bitmap .. itu bekerja untukku, harap untuk kamu juga coba ini ..
DjP
2
@ Dhananjay Terima kasih, petunjuk Anda menghemat hari saya, dan berfungsi untuk memuat bitmap thumbnail dari Penyedia Konten.
Nezneika
2
Selain itu, Uri.parse () harus berisi format URI, seperti: Uri.parse ("file: ///mnt/sdcard/filename.jpg") , jika tidak kita akan mendapatkan java.io.FileNotFoundException: Tidak ada konten penyedia .
Nezneika
Beberapa editorialisasi akan bagus, tetapi ini adalah jawaban singkat yang bagus untuk pertanyaan OP yang berfungsi dalam banyak kasus. Ini adalah jawaban yang bagus untuk ada di halaman demi menyaring bagian dari jawaban lain yang secara langsung menjawab pertanyaan OP.
umassthrower
1
@AndroidNewBee c adalah objek Konteks.
DjP
17

Ini adalah solusi termudah:

Bitmap bitmap = MediaStore.Images.Media.getBitmap(this.getContentResolver(), uri);
Hasib Akter
sumber
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
sumber
3
itu berfungsi pada semua SDK .. Terima kasih. itu cara alternatifBitmap bitmap = MediaStore.Images.Media.getBitmap(context.getContentResolver(), uri);
Jigar Patel
jawaban paling tulus yang
diterima
13

Tampaknya MediaStore.Images.Media.getBitmapsudah usang di API 29. Cara yang disarankan adalah menggunakan ImageDecoder.createSourceyang ditambahkanAPI 28 .

Berikut cara menyelesaikan 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
sumber
11

Anda dapat mengambil bitmap dari uri seperti ini

Bitmap bitmap = null;
try {
    bitmap = MediaStore.Images.Media.getBitmap(this.getContentResolver(), imageUri);
} catch (IOException e) {
    e.printStackTrace();
}
Emre AYDIN
sumber
10
Uri imgUri = data.getData();
Bitmap bitmap = MediaStore.Images.Media.getBitmap(this.getContentResolver(), imgUri);
Ahmed Sayed
sumber
2
Bisakah Anda menjelaskan bagaimana kode ini bekerja dan bagaimana ia menjawab pertanyaan?
Michael Dodd
2

Gunakan metod startActivityForResult seperti di bawah ini

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

Dan Anda bisa mendapatkan hasil seperti ini:

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

Saya sudah mencoba banyak cara. ini bekerja untuk saya dengan sempurna.

Jika Anda memilih pictrue dari Galeri. Anda harus siap untuk mendapatkan Uridari intent.clipdataatau intent.data, karena salah satunya mungkin nol dalam versi yang berbeda.

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

Anda dapat melakukan struktur ini:

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

dengan ini Anda dapat dengan mudah mengonversi uri menjadi bitmap. semoga membantu kamu.

Sayed Mohammad Amin Emrani
sumber
1
Ini tidak berfungsi di versi nougat 7.1.1 android. Extras.getParcelable ("data") ini; mengembalikan null
Developer_vaibhav
1

Bagian awal getBitmapyang sekarang saya gunakan adalah pendekatan berikut di Kotlin

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

(KOTLIN) Jadi, pada 7 April 2020, tidak ada opsi yang disebutkan di atas yang berfungsi, tetapi inilah yang bekerja untuk saya:

  1. Jika Anda ingin menyimpan bitmap dalam val dan mengatur imageView dengannya, gunakan ini:

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

  2. Jika Anda hanya ingin mengatur bitmap dan imageView, gunakan ini:

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

Advait Bansode
sumber
0

Metode lengkap untuk mendapatkan gambar uri dari galeri seluler.

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
sumber