Android 显示获取服务器的超大图片 <19>

最近看了网上面很多博客或者APP转发较多的一篇blog,说再也不用当心从服务器上面获取的图片有多大了,都能够轻松显示出来,不知道是不是没有仔细看那篇文章,还是什么,没有特别验证,感觉很奇怪,他不是通过压缩图片的方式显示,而是通过裁剪图片的方式然后显示出来,通过裁剪的方式压缩图片大小,个人觉得很奇怪,裁剪过的图片还有什么用呢?

个人结合前面的一篇博客,通过压缩的办法,然后在结合在网上面看了一些推荐的办法.

在没有去考虑DiskLruCache的方式,我粗略的操作如下:

首先提供一个MD5的工具类:DurianMD5.java

package org.durian.durianhttpresponsecache.bitmapcompress;

import java.security.MessageDigest;

/**
 * Project name : DurianHttpResponseCache
 * Created by zhibao.liu on 2016/1/29.
 * Time : 17:56
 * Email warden_sprite@foxmail.com
 * Action : durian
 */
public class DurianMD5 {

    /**
     * MD5加密
     * @param str 要加密的字符串
     * @return 加密后的字符串
     */
    public static String md5(String str) {
        MessageDigest md5 = null;
        try {
            md5 = MessageDigest.getInstance("MD5");
        } catch (Exception e) {
            e.printStackTrace();
            return "";
        }
        char[] charArray = str.toCharArray();
        byte[] byteArray = new byte[charArray.length];
        for (int i = 0; i < charArray.length; i++) {
            byteArray[i] = (byte) charArray[i];
        }
        byte[] md5Bytes = md5.digest(byteArray);
        StringBuffer hexValue = new StringBuffer();
        for (int i = 0; i < md5Bytes.length; i++) {
            int val = ((int) md5Bytes[i]) & 0xff;
            if (val < 16) {
                hexValue.append("0");
            }
            hexValue.append(Integer.toHexString(val));
        }
        return hexValue.toString();
    }

}

然后下面是一个DurianBitmapCompress.java

package org.durian.durianhttpresponsecache.bitmapcompress;

import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Rect;
import android.os.Environment;

import org.durian.durianhttpresponsecache.R;

import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileOutputStream;
import java.io.InputStream;
import java.text.SimpleDateFormat;
import java.util.Date;

/**
 * Project name : DurianHttpResponseCache
 * Created by zhibao.liu on 2016/1/29.
 * Time : 17:54
 * Email warden_sprite@foxmail.com
 * Action : durian
 */
public class DurianBitmapCompress {

    final String PATH = Environment.getExternalStorageDirectory()
            + "/durian.jpg";

    public static Bitmap getCompressNetBitmap(Bitmap bitmap, int bitmapMaxWidth) throws Exception {

        String imagePath=saveToLocal(bitmap);

        BitmapFactory.Options options = new BitmapFactory.Options();
        options.inJustDecodeBounds = true;
        BitmapFactory.decodeFile(imagePath, options);

        int height = options.outHeight;
        int width = options.outWidth;
        int reqHeight = 0;
        int reqWidth = bitmapMaxWidth;
        reqHeight = (reqWidth * height)/width;
        // 在内存中创建bitmap对象,这个对象按照缩放大小创建的
        options.inSampleSize = calculateInSampleSize(options, bitmapMaxWidth, reqHeight);
        options.inJustDecodeBounds = false;
        Bitmap map = BitmapFactory.decodeFile(imagePath, options);

        Bitmap retmap = compressImage(Bitmap.createScaledBitmap(map, bitmapMaxWidth, reqHeight, false));

        /*String timeStamp = new SimpleDateFormat("yyyyMMdd_HHmmss")
                .format(new Date());
        saveImg(bbb, DurianMD5.md5(timeStamp));*/

        return retmap;

    }
    /*
    * how to use following code :
    * getCompressBitmap(context,480);
    * */
    public static Bitmap getCompressBitmap(Context context,int bitmapMaxWidth,int resID) throws Exception {
        BitmapFactory.Options options = new BitmapFactory.Options();
        options.inJustDecodeBounds = true;
//        BitmapFactory.decodeFile(oldPath, options);
        BitmapFactory.decodeResource(context.getResources(),resID,options);

        int height = options.outHeight;
        int width = options.outWidth;
        int reqHeight = 0;
        int reqWidth = bitmapMaxWidth;
        reqHeight = (reqWidth * height)/width;
        // 在内存中创建bitmap对象,这个对象按照缩放大小创建的
        options.inSampleSize = calculateInSampleSize(options, bitmapMaxWidth, reqHeight);
        options.inJustDecodeBounds = false;
//        Bitmap bitmap = BitmapFactory.decodeFile(oldPath, options);
        Bitmap bitmap =BitmapFactory.decodeResource(context.getResources(),resID,options);
        //Log.e("asdasdas", "reqWidth->"+reqWidth+"---reqHeight->"+reqHeight);
        Bitmap retmap = compressImage(Bitmap.createScaledBitmap(bitmap, bitmapMaxWidth, reqHeight, false));

        String timeStamp = new SimpleDateFormat("yyyyMMdd_HHmmss")
                .format(new Date());

//        saveImg(bbb, DurianMD5.md5(timeStamp));

        return retmap;
    }

    private static String getThumbUpFromDrawable(Context context, int bitmapMaxWidth) throws Exception {
        BitmapFactory.Options options = new BitmapFactory.Options();
        options.inJustDecodeBounds = true;
//        BitmapFactory.decodeFile(oldPath, options);
        BitmapFactory.decodeResource(context.getResources(),R.drawable.large,options);

        int height = options.outHeight;
        int width = options.outWidth;
        int reqHeight = 0;
        int reqWidth = bitmapMaxWidth;
        reqHeight = (reqWidth * height)/width;
        // 在内存中创建bitmap对象,这个对象按照缩放大小创建的
        options.inSampleSize = calculateInSampleSize(options, bitmapMaxWidth, reqHeight);
        options.inJustDecodeBounds = false;
//        Bitmap bitmap = BitmapFactory.decodeFile(oldPath, options);
        Bitmap bitmap =BitmapFactory.decodeResource(context.getResources(),R.drawable.large,options);
        //Log.e("asdasdas", "reqWidth->"+reqWidth+"---reqHeight->"+reqHeight);
        Bitmap retmap = compressImage(Bitmap.createScaledBitmap(bitmap, bitmapMaxWidth, reqHeight, false));
        String timeStamp = new SimpleDateFormat("yyyyMMdd_HHmmss")
                .format(new Date());
        return saveImg(retmap, DurianMD5.md5(timeStamp));
    }

    /*
    * how to use following code :
    * getThumbUploadPath(PATH,480);
    * */

    private static String getThumbUploadPath(String oldPath,int bitmapMaxWidth) throws Exception {
        BitmapFactory.Options options = new BitmapFactory.Options();
        options.inJustDecodeBounds = true;
        BitmapFactory.decodeFile(oldPath, options);
        int height = options.outHeight;
        int width = options.outWidth;
        int reqHeight = 0;
        int reqWidth = bitmapMaxWidth;
        reqHeight = (reqWidth * height)/width;
        // 在内存中创建bitmap对象,这个对象按照缩放大小创建的
        options.inSampleSize = calculateInSampleSize(options, bitmapMaxWidth, reqHeight);
        options.inJustDecodeBounds = false;
        Bitmap bitmap = BitmapFactory.decodeFile(oldPath, options);
        //Log.e("asdasdas", "reqWidth->"+reqWidth+"---reqHeight->"+reqHeight);
        Bitmap retmap = compressImage(Bitmap.createScaledBitmap(bitmap, bitmapMaxWidth, reqHeight, false));
        String timeStamp = new SimpleDateFormat("yyyyMMdd_HHmmss")
                .format(new Date());
        return saveImg(retmap, DurianMD5.md5(timeStamp));
    }

    private 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) {
            if (width > height) {
                inSampleSize = Math.round((float) height / (float) reqHeight);
            } else {
                inSampleSize = Math.round((float) width / (float) reqWidth);
            }
        }
        return inSampleSize;
    }

    private static Bitmap compressImage(Bitmap image) {

        ByteArrayOutputStream baos = new ByteArrayOutputStream();
        image.compress(Bitmap.CompressFormat.JPEG, 80, baos);// 质量压缩方法,这里100表示不压缩,把压缩后的数据存放到baos中
        int options = 100;
        while (baos.toByteArray().length / 1024 > 100) { // 循环判断如果压缩后图片是否大于100kb,大于继续压缩
            options -= 10;// 每次都减少10
            baos.reset();// 重置baos即清空baos
            image.compress(Bitmap.CompressFormat.JPEG, options, baos);// 这里压缩options%,把压缩后的数据存放到baos中
        }
        ByteArrayInputStream isBm = new ByteArrayInputStream(baos.toByteArray());// 把压缩后的数据baos存放到ByteArrayInputStream中
        Bitmap bitmap = BitmapFactory.decodeStream(isBm, null, null);// 把ByteArrayInputStream数据生成图片
        return bitmap;
    }

    public static String saveToLocal(Bitmap map) throws Exception {
        String timeStamp = new SimpleDateFormat("yyyyMMdd_HHmmss")
                .format(new Date());
        return saveImg(map, DurianMD5.md5(timeStamp));
    }

    public static String saveImg(Bitmap b,String name) throws Exception{
        String path = Environment.getExternalStorageDirectory().getPath()+File.separator+"";
        File mediaFile = new File(path + File.separator + name + ".jpg");
        if(mediaFile.exists()){
            mediaFile.delete();

        }
        if(!new File(path).exists()){
            new File(path).mkdirs();
        }
        mediaFile.createNewFile();
        FileOutputStream fos = new FileOutputStream(mediaFile);
        b.compress(Bitmap.CompressFormat.PNG, 100, fos);
        fos.flush();
        fos.close();
        /*b.recycle();
        b = null;
        System.gc();*/
        return mediaFile.getPath();
    }

}

上面的程序提供了很多API接口以便适应不同的环境.上面的程序需要注意几个地方:

第一个: 在保存的地方,下面如果最后一步是保存,图片不用于显示和其他用,就不需要注释下面的,以便回收memory,防止内存泄露,但是如果保存后,后面还要使用图片切记要屏蔽掉.

/*b.recycle();
        b = null;
        System.gc();*/

第二个:下面的这个方式从服务器获取图片后,先保存在sdcard目录下,然后对其提出压缩并且返回作为显示的Bitmap.

public static Bitmap getCompressNetBitmap(Bitmap bitmap, int bitmapMaxWidth)


网络获取:

if(connection.getResponseCode()==HttpURLConnection.HTTP_OK){

                        InputStream is=connection.getInputStream();
                        bitmap= BitmapFactory.decodeStream(is);
                        try {
                            bitmap=DurianBitmapCompress.getCompressNetBitmap(bitmap,450);
                        } catch (Exception e) {
                            e.printStackTrace();
                        }

                    }

获取了以后通过发送一个Handler消息,更新图片.

刚才说了如果不考虑DiskLruCache,就直接保存在一个临时目录中,但是一般超大图片都会考虑使用DiskLruCache策略.DiskLruCache策略下一篇解释.








  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值