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


209

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

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


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

Ссылки:


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


1
спасибо Итай, это просто, если у вас есть путь, вам просто нужно пройти этот путь и получить растровое изображение ... это работает для меня, надеюсь, вы тоже попробуете это ...
— DjP

2
@Dhananjay Спасибо, ваш совет спасает мой день, и он работает для загрузки растрового изображения в виде провайдера контента.
— Незнейка

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

Некоторая редакция была бы хорошей, но это хороший краткий ответ на вопрос ОП, который работает в большинстве случаев. Это хороший ответ, который можно найти на странице, чтобы выделить часть этих ответов, которые прямо отвечают на вопросы ОП.
— umassthrower

1
@AndroidNewBee c является объектом Context.
— 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);
— Джигар Патель

самый искренний ответ всем 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)
}

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

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


   }
}
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.