Converting image url to bitmap quickly

16,524

Solution 1

There is a library named Picasso. which can efficiently load images from url. it can also load image from the File. all you wanted to do , write a line of code.

example

Picasso.with(context) //Context
    .load("http://i.imgur.com/DvpvklR.png") //URL/FILE
    .into(imageView)//an ImageView Object to show the loaded image; 

It can also cache your image, so the loaded image could be able to load faster on the next time without wasting the data.

There are many more options available in Picasso. Here is the documentation

If you need rounded cornered bitmap

Picasso.with(mContext)
    .load("your-image-url-or-file-or-drawable")
    .transform(new RoundedTransformation(200, 0))
    .fit()
    .into(imageView);

RoundedTransformation.java

import android.graphics.Bitmap;
import android.graphics.Bitmap.Config;
import android.graphics.BitmapShader;
import android.graphics.Canvas;
import android.graphics.Paint;
import android.graphics.RectF;
import android.graphics.Shader;

// enables hardware accelerated rounded corners
// original idea here : http://www.curious-creature.org/2012/12/11/android-recipe-1-image-with-rounded-corners/
public class RoundedTransformation implements com.squareup.picasso.Transformation {
    private final int radius;
    private final int margin;  // dp

    // radius is corner radii in dp
    // margin is the board in dp
    public RoundedTransformation(final int radius, final int margin) {
        this.radius = radius;
        this.margin = margin;
    }

    @Override
    public Bitmap transform(final Bitmap source) {
        final Paint paint = new Paint();
        paint.setAntiAlias(true);
        paint.setShader(new BitmapShader(source, Shader.TileMode.CLAMP, Shader.TileMode.CLAMP));

        Bitmap output = Bitmap.createBitmap(source.getWidth(), source.getHeight(), Config.ARGB_8888);
        Canvas canvas = new Canvas(output);
        canvas.drawRoundRect(new RectF(margin, margin, source.getWidth() - margin, source.getHeight() - margin), radius, radius, paint);

        if (source != output) {
            source.recycle();
        }

        return output;
    }

    @Override
    public String key() {
        return "rounded";
    }
}

Solution 2

There are open-source libraries which focus on loading image into an ImageView. Take for example of universal-image-loader, it is very easy to use, like:

// Load image, decode it to Bitmap and display Bitmap in ImageView (or any other view 
//  which implements ImageAware interface)
imageLoader.displayImage(imageUri, imageView);

or:

// Load image, decode it to Bitmap and return Bitmap to callback
imageLoader.loadImage(imageUri, new SimpleImageLoadingListener() {
    @Override
    public void onLoadingComplete(String imageUri, View view, Bitmap loadedImage) {
        // Do whatever you want with Bitmap
    }
});

or:

// Load image, decode it to Bitmap and return Bitmap synchronously
Bitmap bmp = imageLoader.loadImageSync(imageUri);

Take example of Volley, you can use it like this:

public void displayImg(View view){
    ImageView imageView = (ImageView)this.findViewById(R.id.image_view);
    RequestQueue mQueue = Volley.newRequestQueue(getApplicationContext()); 

    ImageLoader imageLoader = new ImageLoader(mQueue, new BitmapCache());

    ImageListener listener = ImageLoader.getImageListener(imageView,R.drawable.default_image, R.drawable.default_image);
    imageLoader.get("http://developer.android.com/images/home/aw_dac.png", listener);
    //指定图片允许的最大宽度和高度
    //imageLoader.get("http://developer.android.com/images/home/aw_dac.png",listener, 200, 200);
}

These libraries are used broadly, and more importantly, they are open-sourced. No need to implement functions like this repeatedly.

Solution 3

Try this

Hope this should help you.
Share:
16,524
Booshan
Author by

Booshan

Updated on June 12, 2022

Comments

  • Booshan
    Booshan almost 2 years

    I need to display the list of images from api in the list page. For that i used two approaches.

    First Approach:
    By converting the url to byte array and then converting it into bitmap.Please find the below code..

    URL imageUrl = new URL(url);
    URLConnection ucon = imageUrl.openConnection();
    
    InputStream is = ucon.getInputStream();
    BufferedInputStream bis = new BufferedInputStream(is);
    
    ByteArrayBuffer baf = new ByteArrayBuffer(500);
    int current = 0;
    while ((current = bis.read()) != -1) {
         /* This approach slowdown the process*/
         baf.append((byte) current);
    }
    
    byte[] img_ary= baf.toByteArray();
    

    Converting byte array to bitmap:

    ByteArrayInputStream imageStream = new ByteArrayInputStream(
                        imgUrl);
    Bitmap theImage = BitmapFactory.decodeStream(imageStream);
    

    Second Approach:
    Image scaling based on height and width

    private static final String TAG_iamge = "Image";
    private static final int IO_BUFFER_SIZE = 4 * 1024;
    
    public static Bitmap loadBitmap(String url) {
        Bitmap bitmap = null;
        InputStream in = null;
        BufferedOutputStream out = null;
    
        try {
            in = new BufferedInputStream(new URL(url).openStream(),
                    IO_BUFFER_SIZE);
    
            final ByteArrayOutputStream dataStream = new ByteArrayOutputStream();
            out = new BufferedOutputStream(dataStream, IO_BUFFER_SIZE);
            copy(in, out);
            out.flush();
    
            final byte[] data = dataStream.toByteArray();
            BitmapFactory.Options options = new BitmapFactory.Options();
    
            options.inJustDecodeBounds = true;
            options.inDither = false;
            options.inPurgeable = true;
            options.inInputShareable = true;
    
            bitmap = BitmapFactory.decodeByteArray(data, 0, data.length,
                    options);
    
            final int height = options.outHeight;
            final int width = options.outWidth;
            int inSampleSize = 1;
            int reqHeight = 500;
            int reqWidth = 500;
    
            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;
                }
            }
    
            int scale = inSampleSize;
    
            BitmapFactory.Options o2 = new BitmapFactory.Options();
            o2.inSampleSize = scale;
            o2.inDither = false;
            o2.inPurgeable = true;
            o2.inInputShareable = true;
            return BitmapFactory.decodeByteArray(data, 0, data.length, o2);
        } catch (Exception e) {
            Log.e(TAG_iamge, "Could not load Bitmap from: " + url);
        } finally {
            closeStream(in);
            closeStream(out);
        }
    
        return bitmap;
    }
    
    private static void copy(InputStream in, OutputStream out)
            throws IOException {
        byte[] b = new byte[IO_BUFFER_SIZE];
        int read;
        while ((read = in.read(b)) != -1) {
            out.write(b, 0, read);
        }
    }
    
    private static void closeStream(Closeable stream) {
        if (stream != null) {
            try {
                stream.close();
            } catch (IOException e) {
                android.util.Log.e("", "Could not close stream", e);
            }
        }
    }
    

    Both approaches making the APP very slow. So here is my questions..

    1. How can i quickly convert the url into bitmap without making the app slow?

    2. How the other apps(like flipcart) displaying the 1000>s of images, without any slow or hang?

      Please guide to get the answer.

    • greenapps
      greenapps almost 9 years
      You forgot to describe what you do in the second aproach. Why?
    • greenapps
      greenapps almost 9 years
      converting the url to byte array. ?? One does not do such things. Please describe better what happens instead.
    • greenapps
      greenapps almost 9 years
      and then converting it into bitmap. You are not doing that in the first aproach.
    • Piyush
      Piyush almost 9 years
      They use layloading. For that you can use third party library.
    • Booshan
      Booshan almost 9 years
      please review my edited code
  • Booshan
    Booshan almost 9 years
    Hi, here i need one more clarification.. I want to display the image as rounded image. Initially i converted the url into bitmap and then converted that bitmap into rounded bitmap.. How can i accomplish this task using this library?
  • theapache64
    theapache64 almost 9 years
    This can be easily done with Picasso. wait a second, i'll get you the code.
  • Booshan
    Booshan almost 9 years
    Thanks a lot. You saved my time.
  • Booshan
    Booshan almost 9 years
    Hi i am going to implement this library in my app. Is this library is more advance compared with universal-image-loader?. Is this a best approach? Because i am going to give the baseline for our project.. If it is okay, I will move on it.. Kindly guide me.
  • theapache64
    theapache64 almost 9 years
    Everything has their own specialties, Check this answers stackoverflow.com/questions/29363321/… , stackoverflow.com/questions/19995007/… . I never used any imageHelper library other than Picasso, so i can't tell about them. Picasso always suits to me.
  • Booshan
    Booshan almost 9 years
    Finally i am going to picasso for my project. Thank you for your support and your great time.
  • theapache64
    theapache64 almost 9 years
    It's ok. and happy coding.
  • Haya Raed
    Haya Raed over 6 years
    Thank you for providing the documentation link. Truly useful and it worked for me! Saved my day