简体   繁体   English

快速将图片网址转换为位图

[英]Converting image url to bitmap quickly

I need to display the list of images from api in the list page. 我需要在列表页面中显示来自api的图像列表。 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转换为byte数组然后将其转换为bitmap。请找到以下代码..

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. 两种方法都使APP非常慢。 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? 其他应用程序(如flipcart)如何显示1000个图像,没有任何缓慢或挂起?

    Please guide to get the answer. 请指导以获得答案。

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 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";
    }
}

There are open-source libraries which focus on loading image into an ImageView . 有一些开源库专注于将图像加载到ImageView Take for example of universal-image-loader , it is very easy to use, like: Universal-image-loader为例,它非常易于使用,如:

// 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: Volley为例,您可以像这样使用它:

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. 不需要反复实现这样的功能。

Try this 试试这个

Hope this should help you. 希望这对你有帮助。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM