要在服务器上存储图像以与Android应用一起使用的大小 [英] What size to store image on server to use with Android app

查看:57
本文介绍了要在服务器上存储图像以与Android应用一起使用的大小的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个Android应用程序,允许用户上传个人资料照片.它们存储在服务器上的300px X 300px.

在应用程序中,我将它们用于40dp X 40dp或有时用于100dp X 100dp.40dp的图像位于 ListView 的图像中.我实际上使用了非常流行的第三方 LazyList 将图像(使用 ImageLoader 类)存储在缓存中..它非常易于使用,并且很好地解决了ListView内部的图像加载问题.

要更直接地回答您的一些问题:

有很多事情时,处理这种情况的最佳方法是什么服务器中的图像大于您需要显示的图像?

您需要将位图子采样降低到目标大小.Google在所有此处上都写得很好.

首先,您必须对设置了 inJustDecodeBounds 布尔值的位图进行解码,以获取位图大小.

  BitmapFactory.Options选项=新的BitmapFactory.Options();options.inJustDecodeBounds = true;BitmapFactory.decodeResource(getResources(),R.id.myimage,选项);int imageHeight = options.outHeight;int imageWidth = options.outWidth;字符串imageType = options.outMimeType; 

然后,您可以根据目标高度和宽度计算样本量.

 公共静态int computeInSampleSize(BitmapFactory.Options选项,int reqWidth,int reqHeight){//图片的原始高度和宽度最终的int高度= options.outHeight;最终的int宽度= options.outWidth;int inSampleSize = 1;if(height> reqHeight || width> reqWidth){最终的int halfHeight =高度/2;最终的int halfWidth =宽度/2;//计算最大的inSampleSize值,该值为2的幂并保持两者//高度和宽度大于要求的高度和宽度.而(((halfHeight/inSampleSize)> reqHeight&&(halfWidth/inSampleSize)>reqWidth){inSampleSize * = 2;}}返回inSampleSize;} 

然后,您可以使用计算出的样本大小加载向下采样的位图.最终代码看起来像

 公共静态位图encodeSampledBitmapFromResource(资源res,int resId,int reqWidth,int reqHeight){//首先使用inJustDecodeBounds = true解码以检查尺寸最终的BitmapFactory.Options选项=新的BitmapFactory.Options();options.inJustDecodeBounds = true;BitmapFactory.decodeResource(res,resId,options);//计算inSampleSizeoptions.inSampleSize = CalculationInSampleSize(options,reqWidth,reqHeight);//解码设置了inSampleSize的位图options.inJustDecodeBounds = false;返回BitmapFactory.decodeResource(res,resId,options);} 

当图像来自服务器而不是资源文件夹时,我们如何考虑xxhdpi,xhdpi等的文件大小?

您可以使用以下代码段计算要缩小位图的目标像素大小:

 浮动像素= TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP,"10",context.getResources().getDisplayMetrics()); 

TL; DR

使用正方形的毕加索,它将解决您的所有问题.

I have an Android app that allows the user to upload profile pics. They are stored 300px X 300px on the server.

In the app, I use them in either 40dp X 40dp or sometimes 100dp X 100dp. The 40dp's images are in ListView's. I actually use a very popular third party LazyList to store the images (using an ImageLoader class) in a cache. Here is the exact library.

I simply show image in my adapter like this:

imageLoader.DisplayImage(profileUrl, holder.iv1);

I take the web URL and display it directly into the ImageView 40dp x 40dp.

Sometimes I notice image degradation. Where the image is partially loaded, then is corrupted.

One theory is that going from a large image on the server and trying to store it in a small area in the actual app, then doing this many times in a ListView, is causing some loading issues.

The question: What is the best way to handle this situation when you have a much larger image in the server than you need to display? I am assuming I may need to use BitMapFactory or a similar class to build a new image. But I am not sure. I feel like I am missing a step.

Here is an example of an image in a ListView that has become corrupted, notice this does not happen to all. (And yes that is Tobias from Arrested Development.)

Follow-up: And how do we take in consideration file size for xxhdpi, xhdpi, etc when the image is coming from server and not the resources folder?

解决方案

The library you are using looks like it is barely maintained anymore (last update is at least a year old). There are several newer and likely better libraries that solve the same problem. My favorite is Square's Picasso. It is very simple to use and solves the image loading inside a ListView problem very well.

To more directly answer some of your questions:

What is the best way to handle this situation when you have a much larger image in the server than you need to display?

You need to subsample the Bitmap down to the target size. Google has a pretty good write up on all of this here.

First you have to decode the bitmap setting the inJustDecodeBounds boolean to get the bitmap size.

BitmapFactory.Options options = new BitmapFactory.Options();
options.inJustDecodeBounds = true;
BitmapFactory.decodeResource(getResources(), R.id.myimage, options);
int imageHeight = options.outHeight;
int imageWidth = options.outWidth;
String imageType = options.outMimeType;

Then you can compute your sample size based on your target height and width.

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

Then you can use the computed sample size to load the down sampled Bitmap. The final code would look something like

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

And how do we take in consideration file size for xxhdpi, xhdpi, etc when the image is coming from server and not the resources folder?

You can compute the target pixel size you want to downsize your bitmap to using the following snippet:

float pixels = TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, "10", context.getResources().getDisplayMetrics());

TL;DR

Use Square's Picasso and it will solve all of your problems.

这篇关于要在服务器上存储图像以与Android应用一起使用的大小的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆