Как получить растровое изображение от Uri?

209

Как получить растровый объект из Uri (если мне удастся сохранить его в /data/data/MYFOLDER/myimage.pngили file///data/data/MYFOLDER/myimage.png), чтобы использовать его в моем приложении?

У кого-нибудь есть идеи как это сделать?

ilredelweb
источник
30
Вы должны обновить свой принятый ответ на этот пост, так как есть лучшие ответы, чем мой.
Видар Вестнес
1
Второй ответ является правильным, то третий ответ является более полным.
IgniteCoders
@VidarVestnes Почему бы вам не удалить его?
Карлос Лопес Мари

Ответы:

-36

, , ВАЖНО: Смотрите ответ от @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 ()?
Видар Вестнес
7
@VidarVestnes приятель, как преобразовать путь к файлу в URL?
Дхарам
7
Я не понимаю, как это выбранный ответ
Ник Кардосо
11
Я согласен, этот ответ не следует принимать как лучший. Может быть, это было выбрано, потому что это был первый ответ. Это старый пост. Во всяком случае, ответы ниже для лучшего решения.
Видар Вестнес
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 (), очевидно, не принимает contentURI.
PJV
1
Смотрите ответ здесь: stackoverflow.com/questions/4753013/…
Марк Инграм
@MarkIngram Это работает с любым локальным изображением или только с изображением камеры?
Нарендра Сингх
@MarkIngram: что если у нас нет доступа к data.getData (), я имею в виду, если я просто открою какое-то изображение из галереи и все знаю, что это путь к нему, как я могу получить URI и растровое изображение?
Umair
@ Umair вы должны задать новый вопрос вместо того, чтобы задавать в комментариях ответ. Кстати: посмотрите здесь developer.android.com/reference/android/net/Uri.html
winklerrr
112

Вот правильный способ сделать это, а также следить за использованием памяти:

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 (), поэтому вы не теряете никакой функциональности.

Ссылки:

PJV
источник
1
Это действительно помогло мне, хотя я думаю, что стоит упомянуть, что ключевое слово this нельзя использовать в статическом контексте. Я передал его в метод getThumbnail в качестве аргумента, и он работает как шарм.
МакКинли Смит
8
Может ли кто-нибудь сказать мне, какое значение я должен придать THUMBNAILSIZE
Абид
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

DJP
источник
1
спасибо Итай, это просто, если у вас есть путь, вам просто нужно пройти этот путь и получить растровое изображение ... это работает для меня, надеюсь, вы тоже попробуете это ...
DjP
2
@Dhananjay Спасибо, ваш совет спасает мой день, и он работает для загрузки растрового изображения в виде провайдера контента.
Незнейка
2
Кроме того, Uri.parse () должен содержать формат URI, например: Uri.parse ("file: ///mnt/sdcard/filename.jpg") , в противном случае мы получим java.io.FileNotFoundException: нет содержимого поставщик .
Незнейка
Некоторая редакция была бы хорошей, но это хороший краткий ответ на вопрос ОП, который работает в большинстве случаев. Это хороший ответ, который можно найти на странице, чтобы выделить часть этих ответов, которые прямо отвечают на вопросы ОП.
umassthrower
1
@AndroidNewBee c является объектом Context.
DjP
17

Это самое простое решение:

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();
    }
}
DeltaCap019
источник
3
это работает на всех SDK .. Спасибо. это альтернативный способBitmap bitmap = MediaStore.Images.Media.getBitmap(context.getContentResolver(), uri);
Джигар Патель
самый искренний ответ всем SDK доволен
Ноаман Акрам
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)
}
Ika
источник
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

Я пробовал много способов. эта работа для меня отлично.

Если вы выбираете Pictrue из галереи. Вы должны быть посуда получения 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;
   }

этим вы можете легко конвертировать URI в растровое изображение. надеюсь помочь тебе

Сказал Мухаммед Амин Эмрани
источник
1
Это не работает в версии Android 7.1. Это extras.getParcelable ("data"); возвращается null
Developer_vaibhav
1

Вкладка из getBitmapкоторых ограничена, теперь я использую следующий подход в Kotlin

PICK_IMAGE_REQUEST ->
    data?.data?.let {
        val bitmap = BitmapFactory.decodeStream(contentResolver.openInputStream(it))
        imageView.setImageBitmap(bitmap)
    }
yaugenka
источник
1
  InputStream imageStream = null;
    try {
        imageStream = getContext().getContentResolver().openInputStream(uri);
    } catch (FileNotFoundException e) {
        e.printStackTrace();
    }
    final Bitmap selectedImage = BitmapFactory.decodeStream(imageStream);
Фавзи Нофал
источник
1

(КОТЛИН) Итак, по состоянию на 7 апреля 2020 года ни один из вышеупомянутых вариантов не работал, но вот что сработало для меня:

  1. Если вы хотите сохранить растровое изображение в val и установить для него imageView, используйте это:

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

  2. Если вы просто хотите установить растровое изображение и imageView, используйте это:

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

Адвайт Бансоде
источник
0

Полный способ получить изображение URI из мобильной галереи.

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
источник