วิธีรับวัตถุบิตแมปจาก Uri (หากฉันประสบความสำเร็จในการเก็บไว้ใน
/data/data/MYFOLDER/myimage.png
หรือfile///data/data/MYFOLDER/myimage.png
) เพื่อใช้ในแอปพลิเคชันของฉัน
ใครบ้างมีความคิดในการทำสิ่งนี้ให้สำเร็จ
วิธีรับวัตถุบิตแมปจาก Uri (หากฉันประสบความสำเร็จในการเก็บไว้ใน
/data/data/MYFOLDER/myimage.png
หรือfile///data/data/MYFOLDER/myimage.png
) เพื่อใช้ในแอปพลิเคชันของฉัน
ใครบ้างมีความคิดในการทำสิ่งนี้ให้สำเร็จ
คำตอบ:
. . สำคัญ: ดูคำตอบจาก @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 () จากการโพสต์ของ Mark Ingram เรียกว่า decodeStream () ดังนั้นคุณจะไม่สูญเสียฟังก์ชันการทำงานใด ๆ
อ้างอิง:
getPowerOfTwoForSampleRatio()
สามารถข้ามได้ ดู: developer.android.com/reference/android/graphics/ …
try
{
Bitmap bitmap = MediaStore.Images.Media.getBitmap(c.getContentResolver() , Uri.parse(paths));
}
catch (Exception e)
{
//handle exception
}
และเส้นทางที่ใช่จะต้องอยู่ในรูปแบบเช่นนี้
file:///mnt/sdcard/filename.jpg
นี่คือทางออกที่ง่ายที่สุด:
Bitmap bitmap = MediaStore.Images.Media.getBitmap(this.getContentResolver(), uri);
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(context.getContentResolver(), uri);
มันดูเหมือนว่าจะได้รับการยกเลิกใน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)
}
คุณสามารถดึงบิตแมปจาก 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);
ใช้ startActivityForResult metod เหมือนด้านล่าง
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;
}
}
ฉันได้ลองหลายวิธีแล้ว งานนี้สำหรับฉันอย่างสมบูรณ์แบบ
หากคุณเลือก 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 )
}
คุณสามารถทำโครงสร้างนี้:
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 เป็น bitmap ได้อย่างง่ายดาย หวังว่าจะช่วยคุณ
สิ่งที่ใส่เข้าไปgetBitmap
ซึ่งถูก depricated ตอนนี้ฉันใช้วิธีการต่อไปนี้ใน 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);
(KOTLIN) ดังนั้นเมื่อวันที่ 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();
}
}
}