How to get Bitmap from an Uri?
How to get a Bitmap object from an Uri (if I succeed to store it in
/data/data/MYFOLDER/myimage.png
or file///data/data/MYFOLDER/myimage.png
) to use it in my ap开发者_运维技巧plication?
Does anyone have an idea on how to accomplish this?
Here's the correct way of doing it:
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);
}
}
If you need to load very large images, the following code will load it in in tiles (avoiding large memory allocations):
BitmapRegionDecoder decoder = BitmapRegionDecoder.newInstance(myStream, false);
Bitmap region = decoder.decodeRegion(new Rect(10, 10, 50, 50), null);
See the answer here
Here's the correct way of doing it, keeping tabs on memory usage as well:
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;
}
The getBitmap() call from Mark Ingram's post also calls the decodeStream(), so you don't lose any functionality.
References:
Android: Get thumbnail of image on SD card, given Uri of original image
Handling large Bitmaps
It seems that MediaStore.Images.Media.getBitmap
was deprecated in API 29
. The recommended way is to use ImageDecoder.createSource
which was added in API 28
.
Here's how getting the bitmap would be done:
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)
}
IMPORTANT: ImageDecoder.decodeBitmap
read EXIF orientation, Media.getBitmap
doesn't
try
{
Bitmap bitmap = MediaStore.Images.Media.getBitmap(c.getContentResolver() , Uri.parse(paths));
}
catch (Exception e)
{
//handle exception
}
and yes path must be in a format of like this
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();
}
}
This is the easiest solution:
Bitmap bitmap = MediaStore.Images.Media.getBitmap(this.getContentResolver(), uri);
Uri imgUri = data.getData();
Bitmap bitmap = MediaStore.Images.Media.getBitmap(this.getContentResolver(), imgUri);
You can retrieve bitmap from uri like this
Bitmap bitmap = null;
try {
bitmap = MediaStore.Images.Media.getBitmap(this.getContentResolver(), imageUri);
} catch (IOException e) {
e.printStackTrace();
}
private fun setImage(view: ImageView, uri: Uri) {
val stream = contentResolver.openInputStream(uri)
val bitmap = BitmapFactory.decodeStream(stream)
view.setImageBitmap(bitmap)
}
Inset of getBitmap
which is depricated now I use the following approach in Kotlin
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);
by using glide library you can get bitmap from uri
,
almost in samsung devices image rotated when and we have to check rotation using exifinterface
but using glide no need to check rotation, image always correctly received.
in kotlin you can get bitmap
as
CoroutineScope(Dispatchers.IO).launch {
var bitmap = Glide.with(context).asBitmap().load(imageUri).submit().get()//this is synchronous approach
}
I am using this dependency
api 'com.github.bumptech.glide:glide:4.12.0'
kapt 'com.github.bumptech.glide:compiler:4.12.0'
ContentResolver cr = context.getContentResolver();
try (InputStream input = cr.openInputStream(url)) {
Bitmap bitmap = BitmapFactory.decodeStream(input);
}
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();
}
Use startActivityForResult metod like below
startActivityForResult(new Intent(Intent.ACTION_PICK).setType("image/*"), PICK_IMAGE);
And you can get result like this:
@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;
}
}
I have try a lot of ways. this work for me perfectly.
If you choose pictrue from Gallery. You need to be ware of getting Uri
from intent.clipdata
or intent.data
, because one of them may be null in different version.
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 )
}
I don't see the right answer, so I'll put this extension here
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)
Example in code:
val bitmap = context.getBitmap(uri)
Tip: You can also update the extension for activity/fragment, so you don't need to write the context at all. A little more synth sugar)
you can do this structure:
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;
}
by this you can easily convert a uri to bitmap. hope help u.
(KOTLIN) So, as of April 7th, 2020 none of the above mentioned options worked, but here's what worked for me:
If you want to store the bitmap in a val and set an imageView with it, use this:
val bitmap = BitmapFactory.decodeFile(currentPhotoPath).also { bitmap -> imageView.setImageBitmap(bitmap) }
If you just want to set the bitmap to and imageView, use this:
BitmapFactory.decodeFile(currentPhotoPath).also { bitmap -> imageView.setImageBitmap(bitmap) }
* 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;
}
val bitmap = context.contentResolver.openInputStream(uri).use { data ->
BitmapFactory.decodeStream(data)
}
You need to open inputstream with
use
as it will automatically close the stream after operation complete.
Full method to get image uri from mobile gallery.
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();
}
}
}
Use coil libray for this purpose on 2022.
https://coil-kt.github.io/coil/compose/
for jetpack compose
AsyncImage(
model = uriOfImage,
contentDescription = null,
)
精彩评论