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

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

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

27 ответов

Решение

,,ВАЖНО: См. Ответ @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.

Вот правильный способ сделать это:

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

Смотрите ответ здесь

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

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

Рекомендации:

Кажется, что 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)
}
try
{
    Bitmap bitmap = MediaStore.Images.Media.getBitmap(c.getContentResolver() , Uri.parse(paths));
}
catch (Exception e) 
{
    //handle exception
}

и да путь должен быть в таком формате

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

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

Решение слишком простое:

Bitmap bitmap = MediaStore.Images.Media.getBitmap(this.getContentResolver(), uri);

Вы можете получить растровое изображение из URI, как это

Bitmap bitmap = null;
try {
    bitmap = MediaStore.Images.Media.getBitmap(this.getContentResolver(), imageUri);
} catch (IOException e) {
    e.printStackTrace();
}
Uri imgUri = data.getData();
Bitmap bitmap = MediaStore.Images.Media.getBitmap(this.getContentResolver(), imgUri);
      Bitmap bitmap = null;
ContentResolver contentResolver = getContentResolver(); 
try {
    if(Build.VERSION.SDK_INT < 28) {
        bitmap = MediaStore.Images.Media.getBitmap(contentResolver, imageUri);
    } else {
        ImageDecoder.Source source = ImageDecoder.createSource(contentResolver, imageUri);
        bitmap = ImageDecoder.decodeBitmap(source);
    }
} catch (Exception e) {
    e.printStackTrace();
}
      private fun setImage(view: ImageView, uri: Uri) {
        val stream = contentResolver.openInputStream(uri)
        val bitmap = BitmapFactory.decodeStream(stream)
        view.setImageBitmap(bitmap)
}

используя библиотеку скольжения, вы можете получить растровое изображение из uri,

почти в устройствах Samsung изображение поворачивается, когда мы должны проверять поворот, используя exifinterface

но при использовании скольжения нет необходимости проверять вращение, изображение всегда принимается правильно.

в котлине вы можете получить bitmap в виде

      CoroutineScope(Dispatchers.IO).launch {
   var bitmap = Glide.with(context).asBitmap().load(imageUri).submit().get()//this is synchronous approach                  
}

Я использую эту зависимость

      api 'com.github.bumptech.glide:glide:4.12.0'
kapt 'com.github.bumptech.glide:compiler:4.12.0'

InputStream input = cr.openInputStream(url);

Bitmap bitmap = BitmapFactory.decodeStream(ввод);

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

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

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

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

Не вижу правильного ответа, поэтому добавлю это расширение сюда

      fun Context.getBitmap(uri: Uri): Bitmap =
    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.P) ImageDecoder.decodeBitmap(ImageDecoder.createSource(this.contentResolver, uri))
    else MediaStore.Images.Media.getBitmap(this.contentResolver, uri)

Пример в коде:

      val bitmap = context.getBitmap(uri)

Совет: вы также можете обновить расширение для действия/фрагмента, поэтому вам вообще не нужно писать контекст. Еще немного синтетического сахара)

Это сработало для меня

Uri uri = data.getData();Bitmap bitmap = MediaStore.Images.Media.getBitmap(this.getContentResolver(), uri);

      val bitmap = context.contentResolver.openInputStream(uri).use { data ->
        BitmapFactory.decodeStream(data)
    }

Вам нужно открыть входной поток с помощью

использовать

так как он автоматически закроет поток после завершения операции.

Вы можете сделать эту структуру:

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 в растровое изображение. надеюсь помочь тебе

Используйте метод 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;
    }
}

(КОТЛИН) Итак, по состоянию на 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) }

Полный способ получить изображение 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();
      }


   }
}
      * For getting bitmap from uri. Work for me perfectly.
    
    
    public static Bitmap decodeUriToBitmap(Context mContext, Uri sendUri) {
          Bitmap getBitmap = null;
          try {
            InputStream image_stream;
            try {
              image_stream = mContext.getContentResolver().openInputStream(sendUri);
              getBitmap = BitmapFactory.decodeStream(image_stream);
            } catch (FileNotFoundException e) {
              e.printStackTrace();
            }
          } catch (Exception e) {
            e.printStackTrace();
          }
          return getBitmap;
        }

Bitmap imgbitmap = MediaStore.Images.Media.getBitmap(this.getContentResolver(), selectedImageUri);

Повторяющаяся проблема, с которой я столкнулся при использовании представленных здесь решений, заключается в следующем:

Не удалось найти информацию о провайдере для com.samsung.systemui.navillera.navilleraprovider.

Это предотвратит загрузку вашего растрового изображения.

Вместо этого я попробовал это, и это работает! Слава Богу.

Объяснение заключается в том, что предоставленный uri необходимо преобразовать в путь к файлу.

      Bitmap b1 = MediaStore.Images.Media.getBitmap(this.getContentResolver(), Uri.fromFile(new File(uri1.toString())));

Используйте для этой цели библиотеку катушек в 2022 году.

https://coil-kt.github.io/coil/compose/

для реактивного ранца

                  AsyncImage(
                model = uriOfImage,
                contentDescription = null,
            )
Другие вопросы по тегам