BitmapFactory.decodeFile 上的内存不足
Posted
技术标签:
【中文标题】BitmapFactory.decodeFile 上的内存不足【英文标题】:OutofMemory on BitmapFactory.decodeFile 【发布时间】:2015-06-29 10:06:14 【问题描述】:在我的应用程序中,我必须将选定的图像上传到 parse.com 以获取他们的 Printout 。 我必须保持图像质量,但我无法调整图像大小。 我必须在 parse.com 中上传图像 ..我不需要在设备屏幕上显示它们(图像来自图像库或来自 facebook 相册..或来自 sdcard)。我无法按要求缩小它们。
我在 BitmapFactory.decodeFile() 上遇到 OutOfMemory 错误。这个bug怎么解决?
正在使用 android:largeHeap="true" 可以解决我的问题吗?
我在三星 SM-G900T 上遇到了这个崩溃,但在模拟器上没有..
我试着放了
BitmapFactory.Options options = new BitmapFactory.Options();
options.inJustDecodeBounds = false;
options.inPreferredConfig = Config.RGB_565;
但它不起作用。 下面是我的 AsyncTask 类,用于将图像上传到 Parse.com
class UploadFileFromURL extends AsyncTask<String, String, String>
ProgressDialog dialog;
String albumId = "";
@Override
protected void onPreExecute()
super.onPreExecute();
@Override
protected String doInBackground(String... f_url)
try
for (int i = 0; i < arrListImgBean.size(); i++)
if (!isUploading || objAsyncUpload.isCancelled())
break;
try
if (arrListImgBean.get(i).imageStatus == 1)
continue;
else if (arrListImgBean.get(i).imageStatus == 2)
isPhotodeleted = true;
publishProgress("" + countUploaded);
deletePhoto(i);
else
isPhotodeleted = false;
try
Bitmap b = null;
InputStream is = null;
BitmapFactory.Options options = new BitmapFactory.Options();
options.inJustDecodeBounds = false;
options.inPreferredConfig = Config.RGB_565; // to
// reduce
// the
// memory
options.inDither = true;
if (arrListImgBean.get(i).imgURL
.startsWith("http"))
try
URL url = new URL(
arrListImgBean.get(i).imgURL);
is = url.openConnection()
.getInputStream();
catch (IOException e)
// TODO Auto-generated catch block
e.printStackTrace();
b = BitmapFactory.decodeStream(is, null,
options);
else
b = BitmapFactory.decodeFile(
arrListImgBean.get(i).imgURL,
options);
// Convert it to byte
ByteArrayOutputStream stream = new ByteArrayOutputStream();
// Bitmap out = Bitmap.createScaledBitmap(b,
// 1500, 2100, false);
b.compress(Bitmap.CompressFormat.PNG, 100,
stream);
byte[] image = stream.toByteArray();
ParseFile file = new ParseFile("Android.png",
image);
file.save();
String uploadedUrl = file.getUrl();
if (uploadedUrl != null)
ParseObject imgupload = new ParseObject(
"Photo");
imgupload.put("userName", ParseUser
.getCurrentUser().getEmail());
imgupload.put("photoURL", file);
imgupload.put("photoID",
arrListImgBean.get(i).imageId);
imgupload.put("count", 1);
imgupload.put("albumName", albumId);
imgupload.save();
String objId = imgupload.getObjectId();
if (objId != null && !objId.isEmpty())
countUploaded++;
publishProgress("" + countUploaded);
database.updateImageStatus(
arrListImgBean.get(i).imageId,
Constants.STATUS_UPLOADED,
objId, uploadedUrl);
catch (Exception e)
catch (Exception e)
isUploading = false;
e.printStackTrace();
catch (Exception e)
Log.e("Error: ", e.getMessage());
return null;
@Override
protected void onPostExecute(String file_url)
// dismissDialog(progress_bar_type);
isUploading = false;
btnUploadImages.setBackgroundResource(R.drawable.upload_photo);
vprogress.setCompoundDrawables(null, null, null, null);
// stopLoading();
setProgressMsg();
【问题讨论】:
在加载到内存时不能缩小图像吗?android:largeHeap="true"
不适用于这种情况。它是为资源丰富的应用程序(如照片编辑软件等)而设计的,这些应用程序使用大量内存。你需要做的是根据设备屏幕缩小图像。
SO中有>1k
这样的问题。
我正在寻找解决方案,您可以检查我的代码我已经采取了那些 >1k 问题中建议的所有预防措施@MD
我再问一遍,需要什么画质,需要多大的画质?
【参考方案1】:
android:largeHeap="true"
这行代码可以解决您的问题,但它是一个临时解决方案,但如果图像数量或图像大小增加,可能会再次发生崩溃。更好地使用 Picasso 库来处理图像
【讨论】:
【参考方案2】:假设您有一个 1024x1024dp 的图像和一个 512x512dp 的设备(这两个数字只是为了便于理解)。因此,在这种情况下,在较小规模的设备上加载全分辨率图像会浪费内存。您可以做的是缩小图像以使其适合设备屏幕。这样不仅可以节省大量内存,而且可以得到正确、清晰、锐利的图像。
我正在添加代码来缩放我目前在我的项目中使用的图像。
final FileInputStream streamIn = new FileInputStream(file);
final BitmapFactory.Options ops = new BitmapFactory.Options();
ops.inJustDecodeBounds = true;
// Find the correct scale value. It should be the power of 2.
final int REQUIRED_SIZE = 300;
int width_tmp = ops.outWidth, height_tmp = ops.outHeight;
int scale = 1;
while (true)
if (width_tmp / 2 < REQUIRED_SIZE || height_tmp / 2 < REQUIRED_SIZE)
break;
width_tmp /= 2;
height_tmp /= 2;
scale *= 2;
ops.inJustDecodeBounds = false;
ops.inSampleSize = scale;
bitmap = BitmapFactory.decodeStream(streamIn, null, ops); //This gets the image
streamIn.close();
根据设备的屏幕显示尺寸选择REQUIRED_SIZE
值。
【讨论】:
我必须在 parse.com 中上传图像 ..我不需要在设备屏幕上显示它们(图像来自图像库或来自 facebook 相册..)我无法按比例缩小它们根据要求。 什么是“按要求”?确定的尺寸?【参考方案3】: try
image = readInFile(path);
catch(Exception e)
e.printStackTrace();
// Create the ParseFile
ParseFile file = new ParseFile("picturePath", image);
// Upload the image into Parse Cloud
file.saveInBackground();
// Create a New Class called "ImageUpload" in Parse
ParseObject imgupload = new ParseObject("Image");
// Create a column named "ImageName" and set the string
imgupload.put("Image", "picturePath");
// Create a column named "ImageFile" and insert the image
imgupload.put("ImageFile", file);
// Create the class and the columns
imgupload.saveInBackground();
// Show a simple toast message
Toast.makeText(LoadImg.this, "Image Saved, Upload another one ",Toast.LENGTH_SHORT).show();
private byte[] readInFile(String path) throws IOException
// TODO Auto-generated method stub
byte[] data = null;
File file = new File(path);
InputStream input_stream = new BufferedInputStream(new FileInputStream(
file));
ByteArrayOutputStream buffer = new ByteArrayOutputStream();
data = new byte[16384]; // 16K
int bytes_read;
while ((bytes_read = input_stream.read(data, 0, data.length)) != -1)
buffer.write(data, 0, bytes_read);
input_stream.close();
return buffer.toByteArray();
【讨论】:
我无法调整图片大小,我的应用是上传它们以进行打印 @NibhaJain 检查我更新的答案,在 image= 这里你会直接得到 byte[],试试这个。以上是关于BitmapFactory.decodeFile 上的内存不足的主要内容,如果未能解决你的问题,请参考以下文章
BitmapFactory.decodeFile 上的内存不足
Android BitmapFactory.decodeFile(filePath, options) 返回 Null 6.0权限