6

I am working on a code sample where I have to choose an image from gallery the code is working but after selection of image from gallery I get OutOfMemoryError in my OnActivityResult

I am able to get small images but large images are creating problem.

Here is my code:

try{
                    Uri selectedImageUri = data.getData();
                    String[] filePathColumn = {MediaStore.Images.Media.DATA};
                    Cursor cursor = getContentResolver().query(selectedImageUri, filePathColumn, null, null, null);
                    cursor.moveToFirst();
                    int columnIndex = cursor.getColumnIndex(filePathColumn[0]);
                    String filePath = cursor.getString(columnIndex);
                    cursor.close();
                    bitmap = BitmapFactory.decodeFile(filePath);
                    _profileImage.setImageBitmap(bitmap);
                    _profileImage.setScaleType(ScaleType.FIT_XY);
                    Constant._addPhotoBitmap=bitmap;
                    ByteArrayOutputStream baos = new ByteArrayOutputStream();
                    Bitmap resizedbitmap = Bitmap.createScaledBitmap(bitmap, 200, 200, true);
                    resizedbitmap.compress(Bitmap.CompressFormat.PNG, 100, baos);
                    byte [] _byteArray = baos.toByteArray();
                    String base64 = Base64.encodeToString(_byteArray,Base64.DEFAULT);
                    Constant._addPhotoBase64 = base64;
                }catch (OutOfMemoryError e) {
                    e.printStackTrace();
                    Constant.showAlertDialog(Constant.errorTitle,
                            "Image size is too large.Please upload small image.",
                            DriverProfileScreen.this, false);
                }   catch (Exception e) {
                    e.printStackTrace();
                }
4

6 回答 6

12

您正在根据其 uri 路径直接解码文件..这就是它抛出异常的原因..在加载图像之前设置一些选项..这将减少图像加载的内存..使用此方法加载您想要的任何大小的图像..

/**
 * returns the thumbnail image bitmap from the given url
 * 
 * @param path
 * @param thumbnailSize
 * @return
 */
private Bitmap getThumbnailBitmap(final String path, final int thumbnailSize) {
    Bitmap bitmap;
    BitmapFactory.Options bounds = new BitmapFactory.Options();
    bounds.inJustDecodeBounds = true;
    BitmapFactory.decodeFile(path, bounds);
    if ((bounds.outWidth == -1) || (bounds.outHeight == -1)) {
        bitmap = null;
    }
    int originalSize = (bounds.outHeight > bounds.outWidth) ? bounds.outHeight
            : bounds.outWidth;
    BitmapFactory.Options opts = new BitmapFactory.Options();
    opts.inSampleSize = originalSize / thumbnailSize;
    bitmap = BitmapFactory.decodeFile(path, opts);
    return bitmap;
}
于 2013-10-09T06:57:28.967 回答
2

在 Android Developer 文档中有一个名为

有效地显示位图

所以请通过它。

http://developer.android.com/training/displaying-bitmaps/index.html

希望这会帮助你。

于 2013-10-09T06:47:11.367 回答
0

一般 android 设备堆大小只有 16MB(因​​设备/操作系统而异,请参阅帖子堆大小),如果您正在加载图像并且超过 16MB 的大小,它将抛出内存异常,而不是使用 Bitmap 进行加载来自 SD 卡或资源甚至网络的图像尝试使用 getImageUri ,加载位图需要更多内存,或者如果您使用该位图完成工作,您可以将位图设置为空。

因此,您需要使用以下代码缩小图像:

public static Bitmap decodeFile(File f,int WIDTH,int HIGHT){
 try {
     //Decode image size
     BitmapFactory.Options o = new BitmapFactory.Options();
     o.inJustDecodeBounds = true;
     BitmapFactory.decodeStream(new FileInputStream(f),null,o);
     //The new size we want to scale to
     final int REQUIRED_WIDTH=WIDTH;
     final int REQUIRED_HIGHT=HIGHT;
     //Find the correct scale value. It should be the power of 2.
     int scale=1;
     while(o.outWidth/scale/2>=REQUIRED_WIDTH && o.outHeight/scale/2>=REQUIRED_HIGHT)
         scale*=2;
     //Decode with inSampleSize
     BitmapFactory.Options o2 = new BitmapFactory.Options();
     o2.inSampleSize=scale;
     return BitmapFactory.decodeStream(new FileInputStream(f), null, o2);
 } catch (FileNotFoundException e) {}
 return null;
 }
于 2013-10-09T06:49:21.630 回答
0

试试这个代码:

import java.io.InputStream;
import java.net.HttpURLConnection;
import java.net.URL;

import android.app.ActivityManager;
import android.content.ComponentCallbacks;
import android.content.Context;
import android.content.res.Configuration;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.os.AsyncTask;
import android.support.v4.util.LruCache;
import android.widget.ImageView;

public class UserImageLoaderWithCache implements ComponentCallbacks {
private KCLruCache cache;

public UserImageLoaderWithCache(Context context) {
ActivityManager am = (ActivityManager) context.getSystemService(Context.ACTIVITY_SERVICE);
int memoryClass = am.getMemoryClass() * 1024 * 1024;
cache = new KCLruCache(memoryClass);
}

public void display(String url, ImageView imageview, int defaultresource) {
imageview.setImageResource(defaultresource);
Bitmap image = cache.get(url);
if (image != null) {
imageview.setImageBitmap(image);
}
else {
new SetImageTask(imageview).execute(url);
}
}

private class KCLruCache extends LruCache<String, Bitmap> {

public KCLruCache(int maxSize) {
super(maxSize);
}
}

private class SetImageTask extends AsyncTask<String, Void, Integer> {
private ImageView imageview;
private Bitmap bmp;

public SetImageTask(ImageView imageview) {
this.imageview = imageview;
}

@Override
protected Integer doInBackground(String... params) {
String url = params[0];
try {
bmp = getBitmapFromURL(url);
if (bmp != null) {
cache.put(url, bmp);
} else {
return 0;
}
} catch (Exception e) {
e.printStackTrace();
return 0;
} catch (OutOfMemoryError o) {
o.printStackTrace();
return 0;
}
return 1;
}

@Override
protected void onPostExecute(Integer result) {
if (result == 1) {
imageview.setImageBitmap(bmp);
}
super.onPostExecute(result);
}

private Bitmap getBitmapFromURL(String src) {
try {
URL url = new URL(src);
HttpURLConnection connection = (HttpURLConnection) url.openConnection();
connection.setDoInput(true);
connection.connect();
InputStream input = connection.getInputStream();
Bitmap myBitmap = BitmapFactory.decodeStream(input);
return myBitmap;
} catch (Exception e) {
e.printStackTrace();
return null;
}catch (OutOfMemoryError o) {
o.printStackTrace();
return null;
}
}
}

public void onLowMemory() {
}

/*public void onTrimMemory(int level) {
if (level >= TRIM_MEMORY_MODERATE) {
cache.evictAll();
}
else if (level >= TRIM_MEMORY_BACKGROUND) {
cache.trimToSize(cache.size() / 2);
}
}*/

public void onConfigurationChanged(Configuration arg0) {
// TODO Auto-generated method stub

}
}
于 2014-01-18T09:16:54.733 回答
0

首先缩放位图,然后加载它。它将解决问题。

您可以使用以下方法来做到这一点。

private Bitmap getScaledBitmap(Uri uri){
        Bitmap thumb = null ;
        try {
            ContentResolver cr = getContentResolver();
            InputStream in = cr.openInputStream(uri);
            BitmapFactory.Options options = new BitmapFactory.Options();
            options.inSampleSize=8;
            thumb = BitmapFactory.decodeStream(in,null,options);
        } catch (FileNotFoundException e) {
            Toast.makeText(PhotoTake.this , "File not found" , Toast.LENGTH_SHORT).show();
        }
        return thumb ; 
    }

希望能帮助到你。

于 2013-10-09T07:03:35.283 回答
0

我使用了下面的代码并使用位图将调整后的大小存储Image在本地存储中,它就像魅力一样

final BitmapFactory.Options options = new BitmapFactory.Options();
        options.inSampleSize = 8;

        Bitmap b = BitmapFactory.decodeFile(path, options);

这里的路径是图像Uri路径String

于 2017-12-08T11:03:26.440 回答