Android 使用 Uri 和位图缩小图库中的图像
Android scaling down image from gallery with Uri and Bitmap
我在尝试将图像转换为位图以显着缩小图像时收到 FileNotFound 异常。
我正在像这样检索用户从图库中选择的图像
public static void GET_PICTURE_FROM_GALLERY (Activity activity)
{
Intent getIntent = new Intent(Intent.ACTION_GET_CONTENT);
getIntent.setType("image/*");
Intent pickIntent = new Intent(Intent.ACTION_PICK, android.provider.MediaStore.Images.Media.EXTERNAL_CONTENT_URI);
pickIntent.setType("image/*");
Intent chooserIntent = Intent.createChooser(getIntent, "Select Image");
chooserIntent.putExtra(Intent.EXTRA_INITIAL_INTENTS, new Intent[] {pickIntent});
activity.startActivityForResult(chooserIntent, REQUEST_SELECT_PHOTO);
}
然后,当用户完成选择时:
public void setChosenPicture (Activity activity, Intent data)
{
if(editingViewHelper != null)
{
String[] filePathColumn = {MediaStore.Images.Media.DATA};
Uri selectedImage = data.getData();
System.out.println("GOT URI: " + selectedImage.toString());
Cursor cursor = activity.getContentResolver().query(selectedImage, filePathColumn, null, null, null);
cursor.moveToFirst();
int columnIndex = cursor.getColumnIndex(filePathColumn[0]);
editingViewHelper.holder.tempUri = Uri.parse(cursor.getString(columnIndex));
System.out.println("SET URI: " + editingViewHelper.holder.tempUri.toString());
cursor.close();
editingViewHelper.holder.imageView.setImageURI(editingViewHelper.holder.tempUri);
}
}
这会输出以下内容:
GOT URI: content://media/external/images/media/110
SET URI: /storage/emulated/0/DIRECTORY/IMG_20170606_154512_1664512804.jpg
现在效果很好,但前提是我调用 imageView.setImageUri(uri);但是,我不能那样做,因为我必须按比例缩小图像,这样应用程序才不会使用大量的 ram。为此,我有这个方法
public static Bitmap decodeUri(Context c, Uri uri, final int requiredSize)
{
System.out.println("URI: " + uri.toString());
try
{
BitmapFactory.Options o = new BitmapFactory.Options();
o.inJustDecodeBounds = true;
//This line is where the error occurs.
BitmapFactory.decodeStream(c.getContentResolver().openInputStream(uri), null, o);
int width_tmp = o.outWidth;
int height_tmp = o.outHeight;
int scale = 1;
while(true)
{
if(width_tmp / 2 < requiredSize || height_tmp / 2 < requiredSize)
break;
width_tmp /= 2;
height_tmp /= 2;
scale *= 2;
}
BitmapFactory.Options o2 = new BitmapFactory.Options();
o2.inSampleSize = scale;
return BitmapFactory.decodeStream(c.getContentResolver().openInputStream(uri), null, o2);
}
catch (FileNotFoundException e)
{
e.printStackTrace();
return null;
}
}
最后,我有以下 .output FileNotFound 异常
URI: /storage/emulated/0/DIRECTORY/IMG_20170606_154512_1664512804.jpg
java.io.FileNotFoundException: No content provider: /storage/emulated/0/DIRECTORY/IMG_20170606_154512_1664512804.jpg
现在奇怪的是这个方法 确实 有效,但前提是它从我的应用程序中 taken 的图片传递 Uri .这是不抛出任何错误的最后一个方法的示例输出
Uri: content://com.subliroid.dinnerdecider.provider/external_files/Pictures/DIRECTORY/IMG_20170606_154512_1664512804.jpg
我可以用两种类型的 uris 调用 imageView.setImageUri(uri),但我无法缩小其中一种类型。我能够忽略这一点,直到我开始在真实设备上测试我的应用程序,这些设备拍摄 4k+ 照片与模拟器拍摄的小照片相比。
到目前为止,,最简单的做法是删除大部分代码并使用现有的 image-loading library. Google recommends Glide; I have used Picasso,还有很多其他代码。
Then, when the user is done picking:
query()
调用在很多情况下都会失败(图像在可移动存储上、用户选择您可能不希望响应您的 Intent
的应用程序等)。
And finally, I have the following .output FileNotFound exception
您不必要地创建了一个新的 Uri
,而您这样做是错误的,因为您传递给 Uri.parse()
的值没有方案。
如果您不打算使用现有的、已调试的代码(即图像加载库),请将在 onActivityResult()
中提供的 Uri
传递给您的位图缩放代码.然后,确定何时将大部分逻辑从主应用程序线程中移出,因为您正在冻结当前实现中的 UI。
我在尝试将图像转换为位图以显着缩小图像时收到 FileNotFound 异常。
我正在像这样检索用户从图库中选择的图像
public static void GET_PICTURE_FROM_GALLERY (Activity activity)
{
Intent getIntent = new Intent(Intent.ACTION_GET_CONTENT);
getIntent.setType("image/*");
Intent pickIntent = new Intent(Intent.ACTION_PICK, android.provider.MediaStore.Images.Media.EXTERNAL_CONTENT_URI);
pickIntent.setType("image/*");
Intent chooserIntent = Intent.createChooser(getIntent, "Select Image");
chooserIntent.putExtra(Intent.EXTRA_INITIAL_INTENTS, new Intent[] {pickIntent});
activity.startActivityForResult(chooserIntent, REQUEST_SELECT_PHOTO);
}
然后,当用户完成选择时:
public void setChosenPicture (Activity activity, Intent data)
{
if(editingViewHelper != null)
{
String[] filePathColumn = {MediaStore.Images.Media.DATA};
Uri selectedImage = data.getData();
System.out.println("GOT URI: " + selectedImage.toString());
Cursor cursor = activity.getContentResolver().query(selectedImage, filePathColumn, null, null, null);
cursor.moveToFirst();
int columnIndex = cursor.getColumnIndex(filePathColumn[0]);
editingViewHelper.holder.tempUri = Uri.parse(cursor.getString(columnIndex));
System.out.println("SET URI: " + editingViewHelper.holder.tempUri.toString());
cursor.close();
editingViewHelper.holder.imageView.setImageURI(editingViewHelper.holder.tempUri);
}
}
这会输出以下内容:
GOT URI: content://media/external/images/media/110
SET URI: /storage/emulated/0/DIRECTORY/IMG_20170606_154512_1664512804.jpg
现在效果很好,但前提是我调用 imageView.setImageUri(uri);但是,我不能那样做,因为我必须按比例缩小图像,这样应用程序才不会使用大量的 ram。为此,我有这个方法
public static Bitmap decodeUri(Context c, Uri uri, final int requiredSize)
{
System.out.println("URI: " + uri.toString());
try
{
BitmapFactory.Options o = new BitmapFactory.Options();
o.inJustDecodeBounds = true;
//This line is where the error occurs.
BitmapFactory.decodeStream(c.getContentResolver().openInputStream(uri), null, o);
int width_tmp = o.outWidth;
int height_tmp = o.outHeight;
int scale = 1;
while(true)
{
if(width_tmp / 2 < requiredSize || height_tmp / 2 < requiredSize)
break;
width_tmp /= 2;
height_tmp /= 2;
scale *= 2;
}
BitmapFactory.Options o2 = new BitmapFactory.Options();
o2.inSampleSize = scale;
return BitmapFactory.decodeStream(c.getContentResolver().openInputStream(uri), null, o2);
}
catch (FileNotFoundException e)
{
e.printStackTrace();
return null;
}
}
最后,我有以下 .output FileNotFound 异常
URI: /storage/emulated/0/DIRECTORY/IMG_20170606_154512_1664512804.jpg
java.io.FileNotFoundException: No content provider: /storage/emulated/0/DIRECTORY/IMG_20170606_154512_1664512804.jpg
现在奇怪的是这个方法 确实 有效,但前提是它从我的应用程序中 taken 的图片传递 Uri .这是不抛出任何错误的最后一个方法的示例输出
Uri: content://com.subliroid.dinnerdecider.provider/external_files/Pictures/DIRECTORY/IMG_20170606_154512_1664512804.jpg
我可以用两种类型的 uris 调用 imageView.setImageUri(uri),但我无法缩小其中一种类型。我能够忽略这一点,直到我开始在真实设备上测试我的应用程序,这些设备拍摄 4k+ 照片与模拟器拍摄的小照片相比。
到目前为止,,最简单的做法是删除大部分代码并使用现有的 image-loading library. Google recommends Glide; I have used Picasso,还有很多其他代码。
Then, when the user is done picking:
query()
调用在很多情况下都会失败(图像在可移动存储上、用户选择您可能不希望响应您的 Intent
的应用程序等)。
And finally, I have the following .output FileNotFound exception
您不必要地创建了一个新的 Uri
,而您这样做是错误的,因为您传递给 Uri.parse()
的值没有方案。
如果您不打算使用现有的、已调试的代码(即图像加载库),请将在 onActivityResult()
中提供的 Uri
传递给您的位图缩放代码.然后,确定何时将大部分逻辑从主应用程序线程中移出,因为您正在冻结当前实现中的 UI。