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程序设计有所帮助。
上一篇: 蒸螃蟹的注意事项,这样做比蒸更加美味
下一篇: 春季炖汤食谱大全,滋补身体好功效