图片处理(防止内存溢出)
来源:互联网 发布:汉密尔顿 知乎 喜剧 编辑:程序博客网 时间:2024/05/21 06:40
导读
本篇承接 内存泄漏与内存溢出总结
图片处理(防止内存溢出)
三要素(缩放比例、解码格式、局部加载)
配合软引用BitmapCache类,或Lru算法 BitmapLruCache 优化效果更好
除此以外,还可以使用第三方图片压缩工具
TinyPNG
package zs.xmx.todo;/* * @创建者 默小铭 * @博客 http://blog.csdn.net/u012792686 * @创建时间 2017/4/7 * @本类描述 图片处理(防止内存溢出) * @内容说明 * 三要素: * 缩放比例、解码格式、局部加载 * 配合软引用BitmapCache类,或Lru算法 BitmapLruCache 优化效果更好 * @补充内容 * //todo 这里总结归类到BitmapUtils */public class BitmapHandleDemo extends Activity { private ImageView mImageView; private Bitmap mBitmap = null; private File mFile = null; private int SCREEN_WIDTH, SCREEN_HEIGHT; private int shiftpx = 0; //偏移量 private Button mBtn_choosepic; private Button mBtn_change_option; private Button mBtn_change_rgb; private Button mBtn_partload; private Button mBtn_offset; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_bitmap_handle); initView(); initEvent(); } private void initEvent() { DisplayMetrics dm = new DisplayMetrics(); dm = getApplicationContext().getResources().getDisplayMetrics(); //这里其实要转dp SCREEN_WIDTH = dm.widthPixels; SCREEN_HEIGHT = dm.heightPixels; } private void initView() { mImageView = (ImageView) findViewById(iv); mBtn_choosepic = (Button) findViewById(R.id.choosepic); mBtn_change_option = (Button) findViewById(R.id.change_option); mBtn_change_rgb = (Button) findViewById(R.id.change_rgb); mBtn_partload = (Button) findViewById(partload); mBtn_offset = (Button) findViewById(R.id.offset); } /** * URI方式打开相册获取图片 */ private void getPic() { Intent intent = new Intent(Intent.ACTION_PICK, null); intent.setDataAndType(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, "image/*"); startActivityForResult(intent, 1); } @Override protected void onActivityResult(int requestCode, int resultCode, Intent data) { try { String path = getRealPathFromURL(data.getData()); mFile = new File(path); if (mFile == null) return; if (mFile.length() == 0) { mFile.delete(); return; } Log.i("xmx", "file:" + mFile.getName() + ",原图大小length:" + mFile.length()); FileInputStream fis = new FileInputStream(mFile); mBitmap = BitmapFactory.decodeStream(fis); Log.i("xmx", "bitmap,Bitmap解析图片后大小length:" + mBitmap.getByteCount()); mImageView.setImageBitmap(mBitmap); } catch (Exception e) { e.printStackTrace(); Log.i("xmx", "bitmap,load error:" + e.getMessage()); } } /** * 根据URI获得File文件路径 * * @param contentUri * @return */ private String getRealPathFromURL(Uri contentUri) { String res = null; String[] proj = {MediaStore.Images.Media.DATA}; Cursor cursor = getApplicationContext().getContentResolver().query(contentUri, proj, null, null, null); if (cursor.moveToFirst()) { int column_index = cursor.getColumnIndexOrThrow(MediaStore.Images.Media.DATA); res = cursor.getString(column_index); } cursor.close(); return res; } /** * 点击原图按钮 * * @param view */ public void choosepic(View view) { getPic(); } /** * 点击缩放比例按钮 * * @param view */ public void change_option(View view) { if (mFile == null) { return; } try { BitmapFactory.Options options = new BitmapFactory.Options(); options.inJustDecodeBounds = true; //只获取边界不加载 BitmapFactory.decodeStream(new FileInputStream(mFile), null, options); int width_tmp = options.outWidth, height_tmp = options.outHeight; int scale = 2; while (true) { if (width_tmp / scale < SCREEN_WIDTH) break; scale += 2; } scale /= 2; BitmapFactory.Options options2 = new BitmapFactory.Options(); options2.inSampleSize = scale; //上述操作得到抽样比之后,在赋给inSampleSize Log.i("xmx", "bitmap,缩放比例scale:" + scale); FileInputStream fis = new FileInputStream(mFile); mBitmap = BitmapFactory.decodeStream(fis, null, options2); Log.i("xmx", "scale-bitmap,缩放比例后的图片大小legth:" + mBitmap.getByteCount()); mImageView.setImageBitmap(mBitmap); } catch (Exception e) { e.printStackTrace(); } } /** * 点击更改解码格式按钮 * * @param view */ public void change_rgb(View view) { if (mFile == null) { return; } try { BitmapFactory.Options options = new BitmapFactory.Options(); options.inPreferredConfig = Bitmap.Config.RGB_565; FileInputStream fis = new FileInputStream(mFile); mBitmap = BitmapFactory.decodeStream(fis, null, options); Log.i("xmx", "RGB_565-bitmap,更换解码格式后的图片大小legth:" + mBitmap.getByteCount()); mImageView.setImageBitmap(mBitmap); } catch (Exception e) { e.printStackTrace(); } } /** * 点击局部加载按钮 * * @param view */ public void partload(View view) { partload_offset(); } private void partload_offset() { if (mFile == null) { return; } try { FileInputStream fis = new FileInputStream(mFile); //获取图片的宽高 BitmapFactory.Options options = new BitmapFactory.Options(); options.inJustDecodeBounds = true; //只获取边界不加载 BitmapFactory.decodeStream(new FileInputStream(mFile), null, options); int width = options.outWidth, height = options.outHeight; //设置显示图片的中心区域 BitmapRegionDecoder bitmapRegionDecoder = BitmapRegionDecoder.newInstance(fis, false);//部分图片解析API BitmapFactory.Options options2 = new BitmapFactory.Options(); mBitmap = bitmapRegionDecoder.decodeRegion(new Rect(width / 2 - SCREEN_WIDTH / 2 + shiftpx, height / 2 - SCREEN_HEIGHT / 2, width / 2 + SCREEN_WIDTH / 2 + shiftpx, height / 2 + SCREEN_HEIGHT / 2), options2); mImageView.setImageBitmap(mBitmap); Log.i("xmx", "PartLoad-bitmap,局部加载图片的大小legth:" + mBitmap.getByteCount()); } catch (Exception e) { e.printStackTrace(); } } public void offset(View view) { shiftpx += 10; partload_offset(); }}
BitmapCache 软应用管理多张图片
package zs.xmx.todo;/* * @创建者 默小铭 * @博客 http://blog.csdn.net/u012792686 * @创建时间 2017/4/8 * @本类描述 软引用方式管理多张图片 * @内容说明 //TODO 归类到BitmapUtils * @补充内容 * * --------------------------------- * @更新时间 * @新增内容 * */import android.graphics.Bitmap;import android.os.Build;import android.util.ArrayMap;import java.lang.ref.ReferenceQueue;import java.lang.ref.SoftReference;public class BitmapCache { static private BitmapCache cache; private ArrayMap<String, MySoftRef> hashRefs; //垃圾引用的队列(所引用的对象已经被回收,则将该引用存入队列) private ReferenceQueue<Bitmap> mBitmapReferenceQueue; /** * 继承SoftReference,是的每一个实例都具有可识别的标识 */ private class MySoftRef extends SoftReference<Bitmap> { private String _key = ""; public MySoftRef(Bitmap referent, ReferenceQueue<Bitmap> q, String key) { super(referent, q); _key = key; } } private BitmapCache() { if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) { hashRefs = new ArrayMap<String, MySoftRef>(); } mBitmapReferenceQueue = new ReferenceQueue<Bitmap>(); } public static BitmapCache getInstance() { if (cache == null) { cache = new BitmapCache(); } return cache; } /** * 以软引用的方式对一个Bitmap对象的实例进行引用并保存该引用 */ public void addCacheBitmap(Bitmap bmp, String key) { cleanCache();//清除垃圾引用 MySoftRef ref = new MySoftRef(bmp, mBitmapReferenceQueue, key); hashRefs.put(key, ref); } /** * 依据所指定的drawable下的图片资源ID号, * (可以按需求从网络或本地获取), * 重新获取相应Bitmap对象的实例 */ //public Bitmap getBitmap(int resId, Context context) public Bitmap getBitmap(int resId) { Bitmap bmp = null; //缓存中是否有该Bitmap实例的引用,如果用,从软引用中取 try { if (hashRefs.containsKey(resId)) { MySoftRef ref = (MySoftRef) hashRefs.get(resId); bmp = (Bitmap) ref.get(); } return bmp; } catch (NullPointerException e) { return null; } } private void cleanCache() { MySoftRef ref = null; while ((ref = (MySoftRef) mBitmapReferenceQueue.poll()) != null) { hashRefs.remove(ref._key); } } /** * 清除Cache内的全部内容 */ public void clearCach() { cleanCache(); hashRefs.clear(); System.gc(); System.runFinalization(); }}
BitmapLruCache Lru算法管理多张图片
package zs.xmx.todo;/* * @创建者 默小铭 * @博客 http://blog.csdn.net/u012792686 * @创建时间 2017/4/8 * @本类描述 Lru算法管理多张图片 * @内容说明 //TODO 归类到BitmapUtils * @补充内容 * * --------------------------------- * @更新时间 * @新增内容 * */import android.graphics.Bitmap;import android.util.Log;import java.util.Collections;import java.util.Iterator;import java.util.LinkedHashMap;import java.util.Map;public class BitmapLruCache { private static final String TAG = "xmx"; //容量8bit,填充比0.75,true表示使用LRU算法 //LinkedHashMap线程不安全,因此要在外部加个同步 private Map<String, Bitmap> cache = Collections.synchronizedMap( new LinkedHashMap<String, Bitmap>(8, 0.75f, true)); private long size = 0; //存 当前内存大小 private long limit = 1000000; //限制最后内存 bytes public BitmapLruCache() { //使用App允许的 25% 可用内存大小 setLimit(Runtime.getRuntime().maxMemory() / 4); } private void setLimit(long new_limit) { limit = new_limit; Log.i(TAG, "MemoryCache will use up to" + limit / 1024. / 1024. + "MB"); } /** * 获取图片 */ public Bitmap get(String id) { try { if (!cache.containsKey(id)) return null; return cache.get(id); } catch (NullPointerException e) { return null; } } public void put(String id, Bitmap bitmap) { try { if (cache.containsKey(id)) size -= getSizeInBytes(cache.get(id));//- 就是将原来的图片删掉 cache.put(id, bitmap); size += getSizeInBytes(bitmap);//+ 将新的图片输入 checkSize(); } catch (Throwable th) { th.printStackTrace(); } } private long getSizeInBytes(Bitmap bitmap) { if (bitmap == null) return 0; //行子节*高度(低版本) //高版本 bitmap.getByteCount(); return bitmap.getRowBytes() * bitmap.getHeight(); } /** * 拿到使用最少的图片对象,然后remove掉 */ private void checkSize() { Log.i(TAG, "Cache size=" + size + "length=" + cache.size()); if (size > limit) { Iterator<Map.Entry<String, Bitmap>> iterator = cache.entrySet().iterator(); while (iterator.hasNext()) { Map.Entry<String, Bitmap> entry = iterator.next(); size -= getSizeInBytes(entry.getValue()); iterator.remove(); if (size <= limit) break; } Log.i(TAG, "Clean size,New size" + cache.size()); } } public void clear() { cache.clear(); }}
总结:
- 如果觉得文章对您有用,点击一个关注憋
0 0
- 图片处理(防止内存溢出)
- Android Bitmap图片处理,防止内存溢出
- 图片内存溢出处理
- 打开系统的图库,返回图片并处理图片以防止内存溢出。
- 防止加载图片内存溢出的方法
- android 加载图片防止内存溢出
- Android加载图片,防止内存溢出
- 防止图片decode时候(内存溢出)oom
- Android图片处理内存溢出
- Android图片处理内存溢出学习
- Android图片处理内存溢出学习
- (转)Android图片处理内存溢出学习
- android 下的图片内存溢出处理
- Android图片处理内存溢出学习
- Android图片处理内存溢出学习
- Android 图片内存溢出处理笔记
- 安卓图片处理内存溢出问题
- 图片内存溢出时的处理
- day11-cookie&session
- Android View 基础知识
- opencv︱opencv中实现行人检测:HOG+SVM(二)
- 机器翻译第一步--词向量的生成与保存
- eclipse中关于SVN插件的安装和配置方法
- 图片处理(防止内存溢出)
- 项目的访问路径问题
- 【C++primer学习日记】2.1基本内置类型
- LeetCode 547 Friend Circles(并查集)
- maven依赖中的scope使用
- 1016. Phone Bills (25)
- 计算机网络2-网络应用
- 主流浏览器内核介绍
- 关于percona-xtrabackup 安装的小纠结