欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  移动技术

Android开发之超强图片工具类BitmapUtil完整实例

程序员文章站 2023-01-01 16:06:54
本文实例讲述了android开发之超强图片工具类bitmaputil。分享给大家供大家参考,具体如下: 说明:为了方便大家使用,本人把大家常用的图片处理代码集中到这个类里...

本文实例讲述了android开发之超强图片工具类bitmaputil。分享给大家供大家参考,具体如下:

说明:为了方便大家使用,本人把大家常用的图片处理代码集中到这个类里

使用了lrucache与softreference

/**
 * 图片加载及转化工具 ----------------------------------------------------------------------- 延伸:一个bitmap到底占用多大内存?系统给每个应用程序分配多大内存? bitmap占用的内存为:像素总数
 * * 每个像素占用的内存。在android中, bitmap有四种像素类型:argb_8888、argb_4444、argb_565、alpha_8, 他们每个像素占用的字节数分别为4、2、2、1。因此,一个2000*1000的argb_8888
 * 类型的bitmap占用的内存为2000*1000*4=8000000b=8mb。
 * 
 * @author chen.lin
 *
 */
public class bitmaputil {
 /**
  * 1)软引用 ,已经不适合缓存图片信息,加载图片时会出现重叠的现象
  * 2)android 3.0 (api level 11)中,图片的数据会存储在本地的内存当中
  * 因而无法用一种可预见的方式将其释放,这就有潜在的风险造成应用程序的内存溢出并崩溃,
  * 3)因为从 android 2.3 (api level 9)开始,垃圾回收器会更倾向于回收持有软引用或弱引用的对象,
   这让软引用和弱引用变得不再可靠。
  * 
  */
 private static map<string, softreference<bitmap>> imagecache = new hashmap<string, softreference<bitmap>>();
 /**
  * 初始化lrucache,最少使用最先移除,lrucache来缓存图片,
  * 当存储image的大小大于lrucache设定的值,系统自动释放内存,
  */
 private static lrucache<string, bitmap> mmemorycache;
 static {
  final int memory = (int) (runtime.getruntime().maxmemory() / 1024);
  final int cachesize = memory / 8;
  mmemorycache = new lrucache<string, bitmap>(cachesize) {
   protected int sizeof(string key, bitmap value) {
    // return value.getbytecount() / 1024;
    return value.getheight() * value.getrowbytes();
   }
  };
 }
 // ---lrucache----------------------------------------------------
 /**
  * 添加图片到lrucache
  * 
  * @param key
  * @param bitmap
  */
 public synchronized void addbitmaptomemcache(string key, bitmap bitmap) {
  if (getbitmapfrommemcache(key) == null) {
   if (key != null & bitmap != null) {
    mmemorycache.put(key, bitmap);
   }
  }
 }
 /**
  * 清除缓存
  */
 public void clearmemcache() {
  if (mmemorycache != null) {
   if (mmemorycache.size() > 0) {
    mmemorycache.evictall();
   }
   mmemorycache = null;
  }
 }
 /**
  * 移除缓存
  */
 public synchronized void removememcache(string key) {
  if (key != null) {
   if (mmemorycache != null) {
    bitmap bm = mmemorycache.remove(key);
    if (bm != null)
     bm.recycle();
   }
  }
 }
 /**
  * 从lrucache里读取图片
  * 
  * @param key
  * @return
  */
 public bitmap getbitmapfrommemcache(string key) {
  if (key != null) {
   return mmemorycache.get(key);
  }
  return null;
 }
 /**
  * 加载图片
  * 
  * @param context
  * @param resid
  * @param imageview
  */
 public void loadbitmap(context context, int resid, imageview imageview) {
  final string imagekey = string.valueof(resid);
  final bitmap bitmap = getbitmapfrommemcache(imagekey);
  if (bitmap != null) {
   imageview.setimagebitmap(bitmap);
  } else {
   imageview.setimageresource(resid);
   bitmapworkertask task = new bitmapworkertask(context);
   task.execute(resid);
  }
 }
 /**
  * 任务类
  * 
  * @project app_view
  * @package com.android.view.tool
  * @author chenlin
  * @version 1.0
  * @date 2014年5月10日
  */
 class bitmapworkertask extends asynctask<integer, void, bitmap> {
  private context mcontext;
  public bitmapworkertask(context context) {
   mcontext = context;
  }
  // 在后台加载图片。
  @override
  protected bitmap doinbackground(integer... params) {
   final bitmap bitmap = decodesampledbitmapfromresource(mcontext.getresources(), params[0], 100, 100);
   addbitmaptomemcache(string.valueof(params[0]), bitmap);
   return bitmap;
  }
 }
 // --软引用---------------------------------------------------------
 public static void addbitmaptocache(string path) {
  // 强引用的bitmap对象
  bitmap bitmap = bitmapfactory.decodefile(path);
  // 软引用的bitmap对象
  softreference<bitmap> softbitmap = new softreference<bitmap>(bitmap);
  // 添加该对象到map中使其缓存
  imagecache.put(path, softbitmap);
 }
 public static bitmap getbitmapbypath(string path) {
  // 从缓存中取软引用的bitmap对象
  softreference<bitmap> softbitmap = imagecache.get(path);
  // 判断是否存在软引用
  if (softbitmap == null) {
   return null;
  }
  // 取出bitmap对象,如果由于内存不足bitmap被回收,将取得空
  bitmap bitmap = softbitmap.get();
  return bitmap;
 }
 public bitmap loadbitmap(final string imageurl, final imagecallback imagecallback) {
  softreference<bitmap> reference = imagecache.get(imageurl);
  if (reference != null) {
   if (reference.get() != null) {
    return reference.get();
   }
  }
  final handler handler = new handler() {
   public void handlemessage(final android.os.message msg) {
    // 加入到缓存中
    bitmap bitmap = (bitmap) msg.obj;
    imagecache.put(imageurl, new softreference<bitmap>(bitmap));
    if (imagecallback != null) {
     imagecallback.getbitmap(bitmap);
    }
   }
  };
  new thread() {
   public void run() {
    message message = handler.obtainmessage();
    message.obj = downloadbitmap(imageurl);
    handler.sendmessage(message);
   }
  }.start();
  return null;
 }
 public interface imagecallback {
  void getbitmap(bitmap bitmap);
 }
 // ----其它工具----------------------------------------------------------------------------------
 /**
  * 从网上下载图片
  * 
  * @param imageurl
  * @return
  */
 private bitmap downloadbitmap(string imageurl) {
  bitmap bitmap = null;
  try {
   bitmap = bitmapfactory.decodestream(new url(imageurl).openstream());
   return bitmap;
  } catch (exception e) {
   e.printstacktrace();
   return null;
  }
 }
 /**
  * drawable 转bitmap
  * 
  * @param drawable
  * @return
  */
 public static bitmap drawable2bitmap(drawable drawable) {
  bitmap bitmap = bitmap.createbitmap(drawable.getintrinsicwidth(), drawable.getintrinsicheight(),
    drawable.getopacity() != pixelformat.opaque ? bitmap.config.argb_8888 : bitmap.config.rgb_565);
  canvas canvas = new canvas(bitmap);
  // canvas.setbitmap(bitmap);
  drawable.setbounds(0, 0, drawable.getintrinsicwidth(), drawable.getintrinsicheight());
  drawable.draw(canvas);
  return bitmap;
 }
 /**
  * bitmap 转 drawable
  * 
  * @param bm
  * @return
  */
 public static drawable bitmap2drable(bitmap bm) {
  return new bitmapdrawable(bm);
 }
 /**
  * 把字节数组通过base64encoder转换成字符串
  * 
  * @param image
  * @return
  */
 public static string getbase64(byte[] image) {
  string string = "";
  try {
   base64encoder encoder = new base64encoder();
   string = encoder.encodebuffer(image).trim();
  } catch (exception e) {
   e.printstacktrace();
  }
  return string;
 }
 /**
  * 把字节数据转换成drawable
  * 
  * @param imgbyte
  *   字节数据
  * @return
  */
 @suppresswarnings("deprecation")
 public static drawable byte2drawable(byte[] imgbyte) {
  bitmap bitmap;
  if (imgbyte != null) {
   bitmap = bitmapfactory.decodebytearray(imgbyte, 0, imgbyte.length);
   drawable drawable = new bitmapdrawable(bitmap);
   return drawable;
  }
  return null;
 }
 /**
  * 把图片转换成字节数组
  * 
  * @param bmp
  * @return
  */
 public static byte[] bitmap2byte(bitmap bm) {
  bitmap outbitmap = bitmap.createscaledbitmap(bm, 150, bm.getheight() * 150 / bm.getwidth(), true);
  if (bm != outbitmap) {
   bm.recycle();
   bm = null;
  }
  byte[] compressdata = null;
  bytearrayoutputstream baos = new bytearrayoutputstream();
  try {
   try {
    outbitmap.compress(bitmap.compressformat.png, 100, baos);
   } catch (exception e) {
    e.printstacktrace();
   }
   compressdata = baos.tobytearray();
   baos.close();
  } catch (ioexception e) {
   e.printstacktrace();
  }
  return compressdata;
 }
 /**
  * 缩放图片
  * 
  * @param bitmap
  *   原图片
  * @param newwidth
  * @param newheight
  * @return
  */
 public static bitmap setbitmapsize(bitmap bitmap, int newwidth, int newheight) {
  int width = bitmap.getwidth();
  int height = bitmap.getheight();
  float scalewidth = (newwidth * 1.0f) / width;
  float scaleheight = (newheight * 1.0f) / height;
  matrix matrix = new matrix();
  matrix.postscale(scalewidth, scaleheight);
  return bitmap.createbitmap(bitmap, 0, 0, width, height, matrix, true);
 }
 /**
  * 缩放图片
  * 
  * @param bitmappath
  *   图片路径
  * @return
  */
 public static bitmap setbitmapsize(string bitmappath, float newwidth, float newheight) {
  bitmap bitmap = bitmapfactory.decodefile(bitmappath);
  if (bitmap == null) {
   logger.i("bitmap", "bitmap------------>发生未知异常!");
   return null;
  }
  int width = bitmap.getwidth();
  int height = bitmap.getheight();
  float scalewidth = newwidth / width;
  float scaleheight = newheight / height;
  matrix matrix = new matrix();
  matrix.postscale(scalewidth, scaleheight);
  return bitmap.createbitmap(bitmap, 0, 0, width, height, matrix, true);
 }
 /**
  * 计算图片的缩放大小 如果==1,表示没变化,==2,表示宽高都缩小一倍 ----------------------------------------------------------------------------
  * insamplesize是bitmapfactory.options类的一个参数,该参数为int型, 他的值指示了在解析图片为bitmap时在长宽两个方向上像素缩小的倍数。insamplesize的默认值和最小值为1(当小于1时,解码器将该值当做1来处理),
  * 且在大于1时,该值只能为2的幂(当不为2的幂时,解码器会取与该值最接近的2的幂)。 例如,当insamplesize为2时,一个2000*1000的图片,将被缩小为1000*500,相应地, 它的像素数和内存占用都被缩小为了原来的1/4:
  * 
  * @param options
  * @param reqwidth
  * @param reqheight
  * @return
  */
 public static int calculateinsamplesize(bitmapfactory.options options, int reqwidth, int reqheight) {
  // 原始图片的宽高
  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;
   // 在保证解析出的bitmap宽高分别大于目标尺寸宽高的前提下,取可能的insamplesize的最大值
   while ((halfheight / insamplesize) > reqheight && (halfwidth / insamplesize) > reqwidth) {
    insamplesize *= 2;
   }
  }
  return insamplesize;
 }
 /**
  * 根据计算出的insamplesize生成bitmap(此时的bitmap是经过缩放的图片)
  * 
  * @param res
  * @param resid
  * @param reqwidth
  * @param reqheight
  * @return
  */
 public static bitmap decodesampledbitmapfromresource(resources res, int resid, int reqwidth, int reqheight) {
  // 首先设置 injustdecodebounds=true 来获取图片尺寸
  final bitmapfactory.options options = new bitmapfactory.options();
  /**
   * injustdecodebounds属性设置为true,decoderesource()方法就不会生成bitmap对象,而仅仅是读取该图片的尺寸和类型信息:
   */
  options.injustdecodebounds = true;
  bitmapfactory.decoderesource(res, resid, options);
  // 计算 insamplesize 的值
  options.insamplesize = calculateinsamplesize(options, reqwidth, reqheight);
  // 根据计算出的 insamplesize 来解码图片生成bitmap
  options.injustdecodebounds = false;
  return bitmapfactory.decoderesource(res, resid, options);
 }
 /**
  * 将图片保存到本地时进行压缩, 即将图片从bitmap形式变为file形式时进行压缩, 
  * 特点是: file形式的图片确实被压缩了, 但是当你重新读取压缩后的file为 bitmap是,它占用的内存并没有改变
  * 
  * @param bmp
  * @param file
  */
 public static void compressbmptofile(bitmap bmp, file file) {
  bytearrayoutputstream baos = new bytearrayoutputstream();
  int options = 80;// 个人喜欢从80开始,
  bmp.compress(bitmap.compressformat.jpeg, options, baos);
  while (baos.tobytearray().length / 1024 > 100) {
   baos.reset();
   options -= 10;
   bmp.compress(bitmap.compressformat.jpeg, options, baos);
  }
  try {
   fileoutputstream fos = new fileoutputstream(file);
   fos.write(baos.tobytearray());
   fos.flush();
   fos.close();
  } catch (exception e) {
   e.printstacktrace();
  }
 }
 /**
  * 将图片从本地读到内存时,进行压缩 ,即图片从file形式变为bitmap形式
  * 特点: 通过设置采样率, 减少图片的像素, 达到对内存中的bitmap进行压缩
  * @param srcpath
  * @return
  */
 public static bitmap compressimagefromfile(string srcpath, float pixwidth, float pixheight) {
  bitmapfactory.options options = new bitmapfactory.options();
  options.injustdecodebounds = true;// 只读边,不读内容
  bitmap bitmap = bitmapfactory.decodefile(srcpath, options);
  options.injustdecodebounds = false;
  int w = options.outwidth;
  int h = options.outheight;
  int scale = 1;
  if (w > h && w > pixwidth) {
   scale = (int) (options.outwidth / pixwidth);
  } else if (w < h && h > pixheight) {
   scale = (int) (options.outheight / pixheight);
  }
  if (scale <= 0)
   scale = 1;
  options.insamplesize = scale;// 设置采样率
  options.inpreferredconfig = config.argb_8888;// 该模式是默认的,可不设
  options.inpurgeable = true;// 同时设置才会有效
  options.ininputshareable = true;// 。当系统内存不够时候图片自动被回收
  bitmap = bitmapfactory.decodefile(srcpath, options);
  // return compressbmpfrombmp(bitmap);//原来的方法调用了这个方法企图进行二次压缩
  // 其实是无效的,大家尽管尝试
  return bitmap;
 }
 /**
  * 判断照片的角度
  * @param path
  * @return
  */
 public static int readpicturedegree(string path) { 
  int degree = 0; 
  try { 
   exifinterface exifinterface = new exifinterface(path); 
   int orientation = exifinterface.getattributeint( 
     exifinterface.tag_orientation, 
     exifinterface.orientation_normal); 
   switch (orientation) { 
   case exifinterface.orientation_rotate_90: 
    degree = 90; 
    break; 
   case exifinterface.orientation_rotate_180: 
    degree = 180; 
    break; 
   case exifinterface.orientation_rotate_270: 
    degree = 270; 
    break; 
   } 
  } catch (ioexception e) { 
   e.printstacktrace(); 
  } 
  return degree; 
 } 
 /**
  * android根据设备屏幕尺寸和dpi的不同,给系统分配的单应用程序内存大小也不同,具体如下表
  * 
  * 屏幕尺寸 dpi 应用内存 
  * small / normal / large ldpi / mdpi 16mb 
  * small / normal / large tvdpi / hdpi 32mb 
  * small / normal / large xhdpi 64mb
  * small / normal / large 400dpi 96mb 
  * small / normal / large xxhdpi 128mb 
  * ------------------------------------------------------- 
  * xlarge mdpi 32mb 
  * xlarge tvdpi / hdpi 64mb 
  * xlarge xhdpi 128mb 
  * xlarge 400dpi 192mb 
  * xlarge xxhdpi 256mb
  */
}

更多关于android相关内容感兴趣的读者可查看本站专题:《android图形与图像处理技巧总结》、《android开发入门与进阶教程》、《android调试技巧与常见问题解决方法汇总》、《android基本组件用法总结》、《android视图view技巧总结》、《android布局layout技巧总结》及《android控件用法总结

希望本文所述对大家android程序设计有所帮助。