Android load and scale a bitmap

Before I move onto the application itself, I was testing out loading in and scaling a bitmap, when I came across a very annoying Out Of Memory error. The image I was testing was ~4000 x ~3500 pixels and the test was running in the android emulator.

Initially, after using the android logging I found the image wasn’t being scaled and I couldn’t load it in and then scale it. And I didn’t want to up the memory on the emulator.

I know I needed an AsyncTask to do this, plus I needed to figure out how to implement them anyway as I’ve used Async’s in GWT extensively.

Eventually after a bit of digging around I eventually found out how to get everything done and it doesn’t waste any memory.

After this has been done, I want to figure out how to display a large image with a zoom option.

See below for the code…

package com.uiprojtest.wlgfx.uiprojecttest;

import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.os.AsyncTask;
import android.util.Log;
import android.widget.ImageView;

/**
 * Created by wlgfx on 02/09/16.
 */

public class GetImageFromServer extends AsyncTask<Void, Void, Bitmap> {

    private final String tag = "WLGFX-AsyncBitmap";

    private Context context;
    private ImageView imageView;
    private int width;
    private int height;

    GetImageFromServer(Context ctx, ImageView view) {
        context = ctx;
        imageView = view;
    }

    @Override
    protected void onPreExecute() {
        super.onPreExecute();
        imageView.setImageBitmap(null);
        width = imageView.getWidth();
        height = imageView.getHeight();
    }

    @Override
    protected void onPostExecute(Bitmap bitmap) {
        super.onPostExecute(bitmap);
        imageView.setImageBitmap(bitmap);

        Log.d(tag, "Bitmap: " +
        "(" + bitmap.getWidth() +
        "," + bitmap.getHeight() + ")" +
        " " + bitmap.getByteCount());
    }

    @Override
    protected Bitmap doInBackground(Void... voids) {
        BitmapFactory.Options options = new BitmapFactory.Options();

        options.inJustDecodeBounds = true; // just get image dimensions
        BitmapFactory.decodeResource(context.getResources(),
                R.drawable.bike, options);

        options.inSampleSize = Math.max(options.outWidth / width,
                options.outHeight / height);

        options.inJustDecodeBounds = false; // let's do this now
        options.inPreferredConfig = Bitmap.Config.RGB_565; // reduced memory footprint
        Bitmap bitmap = BitmapFactory.decodeResource(context.getResources(),
                R.drawable.bike, options);

        // could rescale here to exact required size but no need for this

        return bitmap;
    }
}




/*
 * And in the main activity I use it like this
 */
 
        FloatingActionButton fab = (FloatingActionButton) findViewById(R.id.fab);
        fab.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                Snackbar.make(view, "Grab image from server", Snackbar.LENGTH_LONG)
                        .setAction("Action", new View.OnClickListener() {
                            @Override
                            public void onClick(View view) {
                                GetImageFromServer task = new GetImageFromServer(context, imageView);
                                task.execute();
                            }
                        }).show();
            }
        });

Leave a Reply

Your email address will not be published.