Як отримати Bitmap з Uri?


209

Як отримати об’єкт Bitmap з Uri (якщо мені вдасться його зберегти в /data/data/MYFOLDER/myimage.pngабо file///data/data/MYFOLDER/myimage.png), щоб використовувати його у своїй програмі?

Хтось має уявлення про те, як це досягти?


30
Ви повинні оновити прийняту відповідь у цій публікації, оскільки є кращі відповіді, ніж моя.
Vidar Vestnes

1
Друга відповідь є правильним, то третя відповідь є більш повним.
IgniteCoders

@VidarVestnes Чому ви не видалите його?
Карлос Лопес Марі

Відповіді:


-35

. . ВАЖЛИВО: Дивіться відповідь від @Mark Ingram нижче та @pjv для кращого рішення. . .

Ви можете спробувати це:

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

Але пам’ятайте, що цей метод слід викликати лише з потоку (а не GUI-Thread). Я AsyncTask.


2
Що з перетворенням URI в URL, наприклад, за допомогою yourUri.toURL ()?
Vidar Vestnes

7
@VidarVestnes приятель, як можна конвертувати шлях до Url?
дхарам

7
Я не розумію, як це обрана відповідь
Нік Кардосо,

11
Я згоден, цю відповідь не слід сприймати як найкращу. Можливо, його обрали, бо це була перша відповідь. Це старий пост. У будь-якому випадку, ви знайдете відповіді нижче для кращих рішень.
Vidar Vestnes

8
@VidarVestnes просто видаліть свою відповідь
winklerrr

564

Ось правильний спосіб зробити це:

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

Якщо вам потрібно завантажити дуже великі зображення, наступний код завантажить його в плитки (уникаючи великих розмірів пам'яті):

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

Дивіться відповідь тут


3
Цей код, однак, не стосується великих зображень (в основному будь-якого розміру шпалер). getBitmap () викликає decodeStream (), який не вдається з помилкою OOM з stackoverflow.com/questions/2220949/handling-large-bitmaps . Будь-яка інша порада? MediaStore.Images.Thumbnails.getThumbnail (), мабуть, не містить контентURI.
pjv

1
Дивіться відповідь тут: stackoverflow.com/questions/4753013/…
Позначте Інграма

@MarkIngram Це працює з будь-яким місцевим зображенням або лише зображенням камери?
Нарендра Сінгх

@MarkIngram, що, якщо у нас немає доступу до data.getData (), я маю на увазі, якщо я просто відкрию якесь зображення з галереї, і я все знаю, що стосується його шляху, як я можу отримати урі та растрову карту?
Умаїр

@Umair вам слід задати нове запитання, а не запитувати у коментарях відповіді. До речі: подивіться тут developer.android.com/reference/android/net/Uri.html
winklerrr

111

Ось правильний спосіб зробити це, зберігаючи вкладки і щодо використання пам'яті:

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

Виклик getBitmap () з поста Марка Інграма також викликає decodeStream (), так що ви не втрачаєте жодної функціональності.

Список літератури:


1
Це мені справді допомогло, хоча я думаю, що варто згадати, що це ключове слово не можна використовувати із статичного контексту. Я передав його в метод getThumbnail як аргумент, і він працює як шарм.
MacKinley Smith

8
Хто-небудь може сказати мені, яке значення я повинен дати THUMBNAILSIZE
Abid

2
Закриття та повторне відкриття InputStream насправді необхідне, оскільки перший виклик BitmapFactory.decodeStream (...) встановлює кінцеву позицію потоку до кінця, тому другий виклик методу більше не працюватиме без повторного відкриття потоку!
DominicM

3
скажіть, будь ласка, значення THUMBNAILSIZE
Mightian

3
Зайве не розраховувати співвідношення як потужність двох самостійно, оскільки сам декодер округляє розмір вибірки до найближчої потужності двох. Тому виклик методу getPowerOfTwoForSampleRatio()можна пропустити. Дивіться: 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
}

і так, шлях повинен бути у такому форматі

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


1
спасибі Itay, це просто, якщо у тебе є шлях u, просто треба пройти цей шлях і отримати Bitmap .. він працює для мене, сподіваюся, що ти також спробуй це ..
DjP

2
@Dhananjay Дякую, ваш натяк врятує мій день, і він працює для завантаження растрового зображення мініатюр від постачальника вмісту.
Незнейка

2
Крім того, Uri.parse () повинен містити формат URI, як і: Uri.parse ("файл: ///mnt/sdcard/filename.jpg") , якщо ні, ми отримаємо java.io.FileNotFoundException: Немає вмісту постачальник .
Незнейка

Деяка редакція була б непоганою, але це хороша стисла відповідь на питання ОП, яке працює в більшості випадків. Це гарна відповідь, яку ви маєте на сторінці заради відгонки частини цих інших відповідей, які безпосередньо відповідають на питання ОП.
umassthrower

1
@AndroidNewBee c - об'єкт контексту.
DjP


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
це працює на всіх SDK .. Дякую. це альтернативний спосібBitmap bitmap = MediaStore.Images.Media.getBitmap(context.getContentResolver(), uri);
Jigar Patel


13

Здається, це MediaStore.Images.Media.getBitmapбуло застаріло в Росії API 29. Рекомендований спосіб - це використання, ImageDecoder.createSourceяке було додано в API 28.

Ось як зробити растрову карту:

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

Ви можете отримати растрову карту з цього типу uri

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
Чи можете ви детальніше розказати, як працює цей код і як він відповідає на це питання?
Майкл Додд

2

Використовуйте метод startActivityForResult, як показано нижче

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

І ви можете отримати результат таким:

@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

Я спробував багато способів. ця робота для мене ідеально.

Якщо ви вибрали зображення з Галереї. Ви повинні бути посуд отримання Uriвід intent.clipdataабо intent.data, тому що один з них може бути порожнім в інший версії.

  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

Ви можете зробити цю структуру:

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

завдяки цьому ви можете легко перетворити урі в растрові карти. сподіваюсь, допоможе ти.


1
Це не працює у версії Android Nougat 7.1.1. Це extras.getParcelable ("дані"); повертається null
Developer_vaibhav

1

Вставки з getBitmapяких depricated тепер я використовую наступний підхід в Котлин

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) Отже, станом на 7 квітня 2020 року жоден із згаданих варіантів не працював, але ось що для мене спрацювало:

  1. Якщо ви хочете зберегти растрову карту у валі та встановити з нею imageView, скористайтеся цим:

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

  2. Якщо ви просто хочете встановити растрове зображення та imageView, скористайтеся цим:

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


0

Повний метод отримання урі зображення з мобільної галереї.

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


   }
}
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.