图片处理的一些方法

在请求网络时。我们经常会从服务端获取图片,下面我总结了一些图片的处理方法,希望能够帮助其他人

防止批量加载图片时出现OOM(OutOfMemory)

压缩图片

BitmapUtils 图片操作的工具类

//width 图片显示的宽度 height图片显示的高度

Bitmap loadBitmap(is, width, height){

}

Android中图片缓存的实现

Java中的引用

1>强引用 Strong References

就算出现OOM,Java虚拟机都不会销毁该引用。

2>软引用 Soft References

如果Java管理的内存趋于阈值时,GC将会销毁

一部分软引用,释放内存。

3>弱引用 Weak References

比软引用还要弱。

4>虚引用 ………..

不做了解。

SoftReference 软引用对象

SoftReference ref = new SoftReference(bitmap);
Bitmap bitmap=ref.get();

内存缓存(把图片存入内存中)

存图片 (当图片从服务端下载成功后需要存)

Map <String,SoftReference<Bitmap>> cache;
cache.put(path, new SoftReference(bitmap) );

内存中取图片

SoftReference ref=cache.get(path);
if(ref!=null){
  Bitmap b=ref.get();
  if(b!=null){
    设置...
  }
}

文件缓存(把图片存在文件里)

向文件中存图片BitmapUtils.save(bitmap, path);

从文件中读取图片

//path 文件存储路径

Bitmap BitmapUtils.loadBitmap(path);

package cn.tedu.music_player_v4.util;

import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;

import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.Bitmap.CompressFormat;
import android.graphics.BitmapFactory;
import android.graphics.BitmapFactory.Options;
import android.os.AsyncTask;

/**
 * 图片相关工具方法
 */
public class BitmapUtils {

    /**
     * 异步在工作线程中执行图片模糊化处理
     *
     * @param bitmap
     * @param r
     * @param callback
     */
    public static void loadBluredBitmap(final Bitmap bitmap, final int r,
            final BitmapCallback callback) {
        new AsyncTask<String, String, Bitmap>() {
            protected Bitmap doInBackground(String... params) {
                Bitmap b = createBlurBitmap(bitmap, r);
                return b;
            }

            protected void onPostExecute(Bitmap b) {
                callback.onBitmapLoaded(b);
            }
        }.execute();
    }

    /**
     * 传递bitmap 传递模糊半径 返回一个被模糊的bitmap
     *
     * @param sentBitmap
     * @param radius
     * @return
     */
    public static Bitmap createBlurBitmap(Bitmap sentBitmap, int radius) {
        Bitmap bitmap = sentBitmap.copy(sentBitmap.getConfig(), true);
        if (radius < 1) {
            return (null);
        }
        int w = bitmap.getWidth();
        int h = bitmap.getHeight();
        int[] pix = new int[w * h];
        bitmap.getPixels(pix, 0, w, 0, 0, w, h);
        int wm = w - 1;
        int hm = h - 1;
        int wh = w * h;
        int div = radius + radius + 1;
        int r[] = new int[wh];
        int g[] = new int[wh];
        int b[] = new int[wh];
        int rsum, gsum, bsum, x, y, i, p, yp, yi, yw;
        int vmin[] = new int[Math.max(w, h)];
        int divsum = (div + 1) >> 1;
        divsum *= divsum;
        int dv[] = new int[256 * divsum];
        for (i = 0; i < 256 * divsum; i++) {
            dv[i] = (i / divsum);

        }
        yw = yi = 0;
        int[][] stack = new int[div][3];
        int stackpointer;
        int stackstart;
        int[] sir;
        int rbs;
        int r1 = radius + 1;
        int routsum, goutsum, boutsum;
        int rinsum, ginsum, binsum;
        for (y = 0; y < h; y++) {
            rinsum = ginsum = binsum = routsum = goutsum = boutsum = rsum = gsum = bsum = 0;
            for (i = -radius; i <= radius; i++) {
                p = pix[yi + Math.min(wm, Math.max(i, 0))];
                sir = stack[i + radius];
                sir[0] = (p & 0xff0000) >> 16;
                sir[1] = (p & 0x00ff00) >> 8;
                sir[2] = (p & 0x0000ff);
                rbs = r1 - Math.abs(i);
                rsum += sir[0] * rbs;
                gsum += sir[1] * rbs;
                bsum += sir[2] * rbs;
                if (i > 0) {
                    rinsum += sir[0];
                    ginsum += sir[1];
                    binsum += sir[2];

                } else {
                    routsum += sir[0];
                    goutsum += sir[1];
                    boutsum += sir[2];

                }

            }
            stackpointer = radius;
            for (x = 0; x < w; x++) {
                r[yi] = dv[rsum];
                g[yi] = dv[gsum];
                b[yi] = dv[bsum];
                rsum -= routsum;
                gsum -= goutsum;
                bsum -= boutsum;
                stackstart = stackpointer - radius + div;
                sir = stack[stackstart % div];
                routsum -= sir[0];
                goutsum -= sir[1];
                boutsum -= sir[2];
                if (y == 0) {
                    vmin[x] = Math.min(x + radius + 1, wm);

                }
                p = pix[yw + vmin[x]];
                sir[0] = (p & 0xff0000) >> 16;
                sir[1] = (p & 0x00ff00) >> 8;
                sir[2] = (p & 0x0000ff);
                rinsum += sir[0];
                ginsum += sir[1];
                binsum += sir[2];
                rsum += rinsum;
                gsum += ginsum;
                bsum += binsum;
                stackpointer = (stackpointer + 1) % div;
                sir = stack[(stackpointer) % div];
                routsum += sir[0];
                goutsum += sir[1];
                boutsum += sir[2];
                rinsum -= sir[0];
                ginsum -= sir[1];
                binsum -= sir[2];
                yi++;

            }
            yw += w;

        }
        for (x = 0; x < w; x++) {
            rinsum = ginsum = binsum = routsum = goutsum = boutsum = rsum = gsum = bsum = 0;
            yp = -radius * w;
            for (i = -radius; i <= radius; i++) {
                yi = Math.max(0, yp) + x;
                sir = stack[i + radius];
                sir[0] = r[yi];
                sir[1] = g[yi];
                sir[2] = b[yi];
                rbs = r1 - Math.abs(i);
                rsum += r[yi] * rbs;
                gsum += g[yi] * rbs;
                bsum += b[yi] * rbs;
                if (i > 0) {
                    rinsum += sir[0];
                    ginsum += sir[1];
                    binsum += sir[2];

                } else {
                    routsum += sir[0];
                    goutsum += sir[1];
                    boutsum += sir[2];

                }
                if (i < hm) {
                    yp += w;
                }
            }
            yi = x;
            stackpointer = radius;
            for (y = 0; y < h; y++) {
                pix[yi] = (0xff000000 & pix[yi]) | (dv[rsum] << 16)
                        | (dv[gsum] << 8) | dv[bsum];
                rsum -= routsum;
                gsum -= goutsum;
                bsum -= boutsum;
                stackstart = stackpointer - radius + div;
                sir = stack[stackstart % div];
                routsum -= sir[0];
                goutsum -= sir[1];
                boutsum -= sir[2];
                if (x == 0) {
                    vmin[y] = Math.min(y + r1, hm) * w;

                }
                p = x + vmin[y];
                sir[0] = r[p];
                sir[1] = g[p];
                sir[2] = b[p];
                rinsum += sir[0];
                ginsum += sir[1];
                binsum += sir[2];
                rsum += rinsum;
                gsum += ginsum;
                bsum += binsum;
                stackpointer = (stackpointer + 1) % div;
                sir = stack[stackpointer];
                routsum += sir[0];
                goutsum += sir[1];
                boutsum += sir[2];
                rinsum -= sir[0];
                ginsum -= sir[1];
                binsum -= sir[2];
                yi += w;

            }

        }
        bitmap.setPixels(pix, 0, w, 0, 0, w, h);
        return (bitmap);
    }

    /**
     * 通过一个网络的路径加载一张图片
     *
     * @param path
     */
    public static void loadBitmap(Context context, final String path,
            final int width, final int height, final BitmapCallback callback) {
        if(path == null || path.equals("")){
            callback.onBitmapLoaded(null);
            return;
        }
        // 先去文件中找找 看看有没有下载过
        String filename = path.substring(path.lastIndexOf("/") + 1);
        final File file = new File(context.getCacheDir(), filename);
        Bitmap bitmap = loadBitmap(file.getAbsolutePath());
        if (bitmap != null) {
            callback.onBitmapLoaded(bitmap);
            return;
        }
        // 文件中没有图片 则去下载
        new AsyncTask<String, String, Bitmap>() {
            protected Bitmap doInBackground(String... params) {
                try {
                    InputStream is = HttpUtils.get(path);
                    Bitmap b = null;
                    if (width == 0 && height == 0) {
                        b = BitmapFactory.decodeStream(is);
                    } else {
                        b = loadBitmap(is, width, height);
                    }
                    // 图片一旦下载成功 需要存入文件
                    save(b, file.getAbsolutePath());
                    return b;
                } catch (IOException e) {
                    e.printStackTrace();
                }
                return null;
            }

            protected void onPostExecute(Bitmap bitmap) {
                callback.onBitmapLoaded(bitmap);
            }
        }.execute();
    }

    /**
     * 从某个路径下读取一个bitmap
     *
     * @param path
     * @return
     */
    public static Bitmap loadBitmap(String path) {
        File file = new File(path);
        if (!file.exists()) {
            return null;
        }
        return BitmapFactory.decodeFile(path);
    }

    /**
     * 保存图片
     *
     * @param bitmap
     * @param path
     *            图片的目标路径
     */
    public static void save(Bitmap bitmap, String path) throws IOException {
        File file = new File(path);
        if (!file.getParentFile().exists()) { // 父目录不存在
            file.getParentFile().mkdirs(); // 创建父目录
        }
        FileOutputStream os = new FileOutputStream(file);
        bitmap.compress(CompressFormat.JPEG, 100, os);
    }

    /**
     * @param is
     *            数据源
     * @param width
     *            图片的目标宽度
     * @param height
     *            图片的目标高度
     * @return 压缩过后的图片
     */
    public static Bitmap loadBitmap(InputStream is, int width, int height)
            throws IOException {
        // 通过is 读取 到一个 byte[]
        ByteArrayOutputStream bos = new ByteArrayOutputStream();
        byte[] buffer = new byte[1024];
        int length = 0;
        while ((length = is.read(buffer)) != -1) {
            bos.write(buffer, 0, length);
            bos.flush();
        }
        byte[] bytes = bos.toByteArray();
        // 使用BitmapFactory获取图片的原始宽和高
        Options opts = new Options();
        // 仅仅加载图片的边界属性
        opts.inJustDecodeBounds = true;
        BitmapFactory.decodeByteArray(bytes, 0, bytes.length, opts);
        // 通过目标宽和高计算图片的压缩比例
        int w = opts.outWidth / width;
        int h = opts.outHeight / height;
        int scale = w > h ? h : w;
        // 给Options属性设置压缩比例
        opts.inJustDecodeBounds = false;
        opts.inSampleSize = scale;
        // 重新解析byte[] 获取Bitmap
        return BitmapFactory.decodeByteArray(bytes, 0, bytes.length, opts);
    }

    public interface BitmapCallback {
        void onBitmapLoaded(Bitmap bitmap);
    }

}
package cn.tedu.music_player_v4.util;

import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.lang.ref.SoftReference;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import cn.tedu.music_player_v4.R;
import android.content.Context;
import android.graphics.Bitmap;
import android.os.Handler;
import android.os.Message;
import android.widget.ImageView;
import android.widget.ListView;

/**
 * 图片异步批量加载的工具类
 * 自动完成 单线程下载图片
 * 内存缓存   文件缓存
 * @author pjy
 *
 */
public class ImageLoader {
    //声明用于实现内存缓存的map
    private Map<String, SoftReference<Bitmap>> cache = new HashMap<String, SoftReference<Bitmap>>();
    private Context context;
    //声明图片下载任务集合
    private List<ImageLoadTask> tasks=new ArrayList<ImageLoadTask>();
    //声明用于轮循任务队列的工作线程
    private Thread workThread;
    private boolean isLoop=true;
    private ListView listView;
    // 声明handler 显示图片
    private Handler handler = new Handler() {
        public void handleMessage(android.os.Message msg) {
            switch (msg.what) {
            case HANDLER_LOAD_IMAGE_SUCCESS: // 图片下载成功
                ImageLoadTask task = (ImageLoadTask) msg.obj;
                Bitmap bitmap = task.bitmap;
                // 通过listView.findViewWithTag()方法获取相应的imageView
                ImageView imageView = (ImageView) listView
                        .findViewWithTag(task.path);
                if (imageView != null) {
                    if (bitmap != null) {
                        imageView.setImageBitmap(bitmap);
                    } else {
                        imageView.setImageResource(R.drawable.ic_launcher);
                    }
                }
                break;
            }
        }
    };

    public static final int HANDLER_LOAD_IMAGE_SUCCESS = 1;

    public ImageLoader(Context context, ListView listView) {
        this.context = context;
        this.listView = listView;
        //初始化并且启动workThread
        workThread = new Thread(){
            public void run() {
                //不断轮循任务集合  一旦有任务  则获取然后执行下载操作
                while(isLoop){
                    if(!tasks.isEmpty()){ //有任务
                        ImageLoadTask task=tasks.remove(0);
                        String path = task.path;
                        //下载图片
                        Bitmap bitmap = loadBitmap(path);
                        task.bitmap = bitmap;
                        //给imageView 设置 Bitmap
                        Message msg = new Message();
                        msg.what = HANDLER_LOAD_IMAGE_SUCCESS;
                        msg.obj = task;
                        handler.sendMessage(msg);

                    }else{ //没有任务  工作线程等待
                        try {
                            synchronized (workThread) {
                                workThread.wait();
                            }
                        } catch (InterruptedException e) {
                            e.printStackTrace();
                        }
                    }
                }
            }
        };
        workThread.start();
    }

    /**
     * 通过path 下载图片
     *
     * @param path
     * @return
     */
    public Bitmap loadBitmap(String path) {
        try {
            InputStream is = HttpUtils.get(path);
            Bitmap b = BitmapUtils.loadBitmap(is, 50, 50);
            // 下载成功 把b存入内存缓存中
            cache.put(path, new SoftReference<Bitmap>(b));
            // 存入文件缓存目录中
            String filename = path.substring(path.lastIndexOf("/") + 1);
            // f --> /data/data/cn.tedu.music/cache/xxxxx.jpg
            File f = new File(context.getCacheDir(), filename);
            BitmapUtils.save(b, f.getAbsolutePath());
            return b;
        } catch (IOException e) {
            e.printStackTrace();
        }
        return null;
    }

    /**
     * 通过path 下载图片 并且把图片显示在相应的ImageView中
     * @param imageView
     * @param path
     */
    public void displayImage(ImageView imageView, String imagePath){

        //设置图片  从缓存中读取图片
        SoftReference<Bitmap> ref=cache.get(imagePath);
        if(ref!=null){
            Bitmap bitmap=ref.get();
            if(bitmap!=null){ //图片还没有被销毁
                imageView.setImageBitmap(bitmap);
                return;
            }
        }
        //内存缓存中没有图片  则去文件缓存中读取
        String filename = imagePath.substring(imagePath.lastIndexOf("/")+1);
        File f = new File(context.getCacheDir(), filename);
        Bitmap bitmap=BitmapUtils.loadBitmap(f.getAbsolutePath());
        if(bitmap!=null){
            imageView.setImageBitmap(bitmap);
            //向内存缓存中再存一次
            cache.put(imagePath, new SoftReference<Bitmap>(bitmap));
            return;
        }
        // 向任务集合中添加一个图片下载任务
        //给imageView设置一个tag值  用于handler中通过tag值找到imageView
        imageView.setTag(imagePath);
        ImageLoadTask task = new ImageLoadTask();
        task.path = imagePath;
        tasks.add(task);
        //唤醒工作线程  赶紧起来干活
        synchronized (workThread) {
            workThread.notify();
        }
    }

    /**
     * 封装一个图片下载任务
     */
    class ImageLoadTask {
        String path;   //图片路径
        Bitmap bitmap;  //通过路径下载成功的bitmap
    }

    /**
     * 停止线程
     */
    public void stopThread() {
        isLoop = false;
        synchronized (workThread) {
            // 唤醒工作线程
            workThread.notify();
        }
    }

}

时间: 2024-10-14 21:21:44

图片处理的一些方法的相关文章

ios图片拉伸两种方法

ios图片拉伸两种方法 UIImage *image = [UIImage imageNamed:@"qq"]; 第一种: // 左端盖宽度 NSInteger leftCapWidth = image.size.width * 0.5f; // 顶端盖高度 NSInteger topCapHeight = image.size.height * 0.5f; // 重新赋值 image = [image stretchableImageWithLeftCapWidth:leftCapW

Android TextView里直接显示图片的三种方法

方法一:重写TextView的onDraw方法,也挺直观就是不太好控制显示完图片后再显示字体所占空间的位置关系.一般如果字体是在图片上重叠的推荐这样写.时间关系,这个不付源码了. 方法二:利用TextView支持部分Html的特性,直接用api赋图片.代码如下: //第一种方法在TextView中显示图片 String html = "<img src='" + R.drawable.circle + "'/>"; ImageGetter imgGett

DISCUZ论坛添加页头及页尾背景图片的几种方法

先给大家分享页头添加背景图片的两种方法: 1. 第一种效果,是给discuz的整体框架添加背景图片,见图示: 添加方法如下:找到你现在使用模板common文件下的header.html文件,在<head></head>部分添加以下代码: <style>body { background-image:url(你的背景图片地址,如http://abc.com/imgs/bg.jpg); background-repeat:no-repeat; background-posi

在数据库中 存储图片 以及 在界面中显示图片(存储图片路径)- 这种方法相对与存储二进制文件好

花了一下午时间,终于学会了在数据库中存储图片,以及在界面中显示图片了. 存储图片有两种方法: 一种是:直接把图片转换成二进制文件存储在数据库中. 一种是:存储图片的路径到数据库,用的时候直接调用路径给image等图像控件即可. 两种方法,有利有弊,第一种方法适合存储量少且重要的图片信息.第二种方法适合存储量大但不是太重要的图片. 我使用的是第二种方法,简单,实用. 下面就是我具体的实现过程: 首先我新建了两个网页文件,insert_photo.aspx / select_photo.apsx 第

图片轮播 z-index方法

<!DOCTYPE html><html><head> <meta charset="UTF-8"> <title>图片轮播 z-index方法</title> <style type="text/css">*{margin: 0;padding: 0;text-decoration: none;}#container{width: 600px; height: 400px; bor

Android 中对于图片的内存优化方法

Android 中对于图片的内存优化方法,需要的朋友可以参考一下 1. 对图片本身进行操作 尽量不要使用 setImageBitmap.setImageResource. BitmapFactory.decodeResource 来设置一张大图,因为这些方法在完成 decode 后,最终都是通过 Java 层的 createBitmap 来完成的,需要消耗更多内存.因此,改用先通过 BitmapFactory.decodeStream 方法,创建出一个 bitmap,再将其设为 ImageVie

UIButton上同时显示图片和文字的方法

参考:http://blog.csdn.net/qijianli/article/details/8152726 不过有个问题,就是我使用时不能改变文字的颜色,后来修改了一下方法,如下: 定义一个UIButton+Manager文件,在.h #import <UIKit/UIKit.h> @interface UIButton (UIButtonImageWithLable) - (void) setImage:(UIImage *)image withTitle:(NSString *)ti

JS快速获取图片宽高的方法

快速获取图片的宽高其实是为了预先做好排版样式布局做准备,通过快速获取图片宽高的方法比onload方法要节省很多时间,甚至一分钟以上都有可能,并且这种方法适用主流浏览器包括IE低版本浏览器.一.简陋的获取图片方式 // 图片地址 后面加时间戳是为了避免缓存 var img_url = 'http://www.qttc.net/static/upload/2013/13643608813441.jpg?'+Date.parse(new Date()); // 创建对象 var img = new I

PHP网站验证码图片不显示解决方法

找到php.ini配置文件之后,双击打开,hp_gd2.dll,找到如下图1-2所示.查看extension=php_gd2.dll前面是否有;号,如果有的话,去除,保存.编者注:如果php.ini是在系统目录下的话,保存之后重起电脑才生效,如果是系统变量里直接指定的话,重起IIS服务器或者重起apache服务器即可生效(不用重起服务器电脑). 如果找不到php.ini文件,在别的电脑拷贝一个即可. PHP网站验证码图片不显示解决方法

手机图片转换文字识别方法

手机图片转换文字识别方法 iPhone6这款设计图出自设计师卡萨巴-纳吉之手,而在他眼中的iPhone6应该朝着透明的方向靠拢.因而,他将该设备打造成了一款极薄.透明,且内置有可互动玻璃外观的"神机".据悉,设计图中的iPhone6拥有一个内置有LED灯的HOME键,只有在用户按下时才会亮起.而且,该手机还具备有全息投影功能,可以将手机画面投射到一块相对更宽的背景中.最炫酷的就是拍照技术,FaceTime 摄像头提供与 iSight 摄像头相同的曝光控制功能,想要调节照片或视频的明暗,