Как получить растровое изображение от 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 года ни один из вышеупомянутых вариантов не работал, но вот что сработало для меня:
Если вы хотите сохранить растровое изображение в val и установить с ним imageView, используйте это:
val bitmap = BitmapFactory.decodeFile(currentPhotoPath).also { bitmap -> imageView.setImageBitmap(bitmap) }
Если вы просто хотите установить для растрового изображения и 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,
)