android Bitmap Subsampling of Image

868 views Asked by At

I have problems with out of memory errors when displaying images in a list view from the SD Card

I know its because I need to subsample the bitmap as they are large 8mp pictures and if I shrink them to 600x450 they load perfectly

I load them normally by using the following

Bitmap bmp = BitmapFactory.decodeFile("/storage/emulated/0/Pictures/" + text7[i]);
item_details.setImage(bmp);

As I said this crashes the app if I use the full size images

I have the following two methods which supposidly subsamples the bitmap

public static Bitmap decodeSampledBitmapFromResource(Resources res, int resId,
    int reqWidth, int reqHeight) {

    // First decode with inJustDecodeBounds=true to check dimensions
    final BitmapFactory.Options options = new BitmapFactory.Options();
    options.inJustDecodeBounds = true;
    BitmapFactory.decodeResource(res, resId, options);

    // Calculate inSampleSize
    options.inSampleSize = calculateInSampleSize(options, reqWidth, reqHeight);

    // Decode bitmap with inSampleSize set
    options.inJustDecodeBounds = false;
    return BitmapFactory.decodeResource(res, resId, options);
}
public static int calculateInSampleSize(BitmapFactory.Options options, int reqWidth, int reqHeight) {
    // Raw height and width of image
    final int height = options.outHeight;
    final int width = options.outWidth;
    int inSampleSize = 1;

    if (height > reqHeight || width > reqWidth) {

        final int halfHeight = height / 2;
        final int halfWidth = width / 2;

        // Calculate the largest inSampleSize value that is a power of 2 and keeps both
        // height and width larger than the requested height and width.
        while ((halfHeight / inSampleSize) > reqHeight
                && (halfWidth / inSampleSize) > reqWidth) {
            inSampleSize *= 2;
        }
    }

    return inSampleSize;
}

Problem is I dont know how to call it so it displays

This is my method for filling the listview

private ArrayList<ListItemDetails> GetSearchResults() {
    // TODO Auto-generated method stub
    ArrayList<ListItemDetails> results = new ArrayList<ListItemDetails>();
    ImageView imageview = (ImageView) findViewById(R.id.imageView1);
    DBAdapter db = new DBAdapter(this);
    db.open();
    Cursor c = db.getAsset3();
    String[] text1 = new String[c.getCount()];
    String[] text2 = new String[c.getCount()];
    String[] text3 = new String[c.getCount()];
    String[] text4 = new String[c.getCount()];
    String[] text5 = new String[c.getCount()];
    String[] text6 = new String[c.getCount()];
    String[] text7 = new String[c.getCount()];
    for(int i = 0; c.moveToNext(); ++i)
    {
        text1[i] = c.getString(0);
        text2[i] = c.getString(1);
        text3[i] = c.getString(2);
        text4[i] = c.getString(3);
        text5[i] = c.getString(4);
        text6[i] = c.getString(5);
        text7[i] = c.getString(6);
    }
    c.close();
    
    for(int i=0;i<text1.length;i++)
    {
        item_details= new ListItemDetails();
        item_details.setSR1("School: " + text1[i]);
        item_details.setSR2("Building: " + text2[i]);
        item_details.setSR3("Floor: " + text3[i]);
        item_details.setSR4("Room: " + text4[i]);
        item_details.setSR5("Drawing Ref: " + text5[i]);
        item_details.setSR6("Fault: " + text6[i]);
        item_details.setSR7("Picture Filename: " + text7[i]);
        String picFormat="Harris%d.jpg";
        String pic = String.format(picFormat, i+1);
           
        // Load bitmap
        imageview.setImageBitmap(decodeSampledBitmapFromResource(getResources(), R.id.imageView1, 100, 100));

        results.add(item_details);
    }
    return results;
}

It seems to work as the list view loads and all the text on each item is there but the image is blank

Any ideas where I am going wrong?

1

There are 1 answers

1
samgak On BEST ANSWER

You aren't passing in your image file name to decodeSampledBitmapFromResource, so how is it going to know which file to load? The resource id you are passing in is the resource id for your ImageView, not the resource id of an image resource.

If you want to load an image from a file given a filename instead of a resource, you need to change decodeSampledBitmapFromResource to load from a file using BitmapFactory.decodeFile() instead of BitmapFactory.decodeResource, like this:

public static Bitmap decodeSampledBitmapFromFile(String filename,
    int reqWidth, int reqHeight) {

    // First decode with inJustDecodeBounds=true to check dimensions
    final BitmapFactory.Options options = new BitmapFactory.Options();
    options.inJustDecodeBounds = true;
    BitmapFactory.decodeFile(filename, options);

    // Calculate inSampleSize
    options.inSampleSize = calculateInSampleSize(options, reqWidth, reqHeight);

    // Decode bitmap with inSampleSize set
    options.inJustDecodeBounds = false;
    return BitmapFactory.decodeFile(filename, options);
}

Then change your ArrayList code to pass in the filename to it:

item_details.setImageBitmap(decodeSampledBitmapFromFile("/storage/emulated/0/Pictures/" + text7[i], 100, 100));