最近开发的一个项目使用到了图片加载上传和保存,由于是接受别人的做,也基本上做完了。但是程序已启动到需要加载图片上传到服务器的界面的时候内存就暴涨,虽然也没有oom,估计旧点的手机肯定会爆,只要不启动到图片加载的页面,内存基本上占用只用20+mb,选择图片后达到了80兆。这肯定是不行的,随后自己研究了几天,把有关上传和加载图片的代码全部推翻了,自己重写了一遍,现在基本上不管怎么加载图片也不会超过30MB了,不加载图片20多MB.加载的方式和逻辑就不说明了,这里主要提供一个核心类,图片压缩。
Android涉及到图片肯定会用到Bitmap,然而Bitmap的占内存的方式也不是我们想的那么简单,具体一张Bitmap图片占用内存的方式为多大,自行谷歌去。
好了提供一套从压缩到保存,到上传的工具类;保证好用;
/**
* 图片处理类
*
* @author Ricko
*/
public class BitmpUtils {
/**
* 采样率压缩 按照图片宽高自动计算缩放比,图片质量有保障
*
* @param filePath 设置宽高并不是设置图片实际宽高,而是根据宽高自动计算缩放比,压缩后图片不会变形,宽高会根据计算的缩放比同时缩放,
* 宽高建议都设置300 设置300后图片大小为100-200KB,图片质量能接受;设置为400到500,图片大小为500-600kb,上传偏大,可自行设置
* @param reqHeight
* @param reqWidth
* @return
*/
public static Bitmap getSmallBitmap(String filePath, int reqHeight, int reqWidth) {
final BitmapFactory.Options options = new BitmapFactory.Options();
options.inJustDecodeBounds = true;
BitmapFactory.decodeFile(filePath, options);
//计算图片的缩放值
final int height = options.outHeight;
final int width = options.outWidth;
int inSampleSize = 1;
if (height > reqHeight || width > reqWidth) {
final int heightRatio = Math.round((float) height / (float) reqHeight);
final int widthRatio = Math.round((float) width / (float) reqWidth);
inSampleSize = heightRatio < widthRatio ? heightRatio : widthRatio;
}
options.inSampleSize = inSampleSize;
options.inJustDecodeBounds = false;
return BitmapFactory.decodeFile(filePath, options);
}
/**
*这个可以压缩到指定的宽,但是图片大小可能达不到预期,图片本身较小的可以使用,图片较大的建议使用上一个压缩方式
* 根据自定义宽度设置图片大小,高度自适应 0不压缩
*
* @param path
* @param width
* @return
*/
public static Bitmap createScaledBitemap(String path, int width) {
Bitmap bit = BitmapFactory.decodeFile(path);
int bitWidth = bit.getWidth();//得到图片宽
float scaleWidth = ((float) width) / ((float) bitWidth);//计算宽度缩放比例
if (width == 0) {
return bit;
} else {
int height = (int) (bit.getHeight() * scaleWidth);//根据宽度缩放比例设置高度
Bitmap bitmap = Bitmap.createScaledBitmap(bit, width, height, true);
return bitmap;
}
}
/**
*这是个保存Bitmap到sd卡中的方法,可以返回保存图片的路径
* 保存Bitmap到sd
*
* @param mBitmap
* @param bitName 图片保存的名称,返回存储图片的路径
*/
public static String saveBitmap(Bitmap mBitmap, String bitName) {
File f;
//判断是否有sd卡 有就保存到sd卡,没有就保存到app缓存目录
if (isStorage()) {
File file = new File("/data/data/name");//保存的路径
if (!file.exists()) {//判断目录是否存在
file.mkdir();//不存在就创建目录
}
f = new File(file, bitName + ".jpg");
} else {
File file = new File(AppContext.getContext().getCacheDir().toString());
if (!file.exists()) {//判断目录是否存在
file.mkdir();
}
f = new File(file, bitName + ".jpg");
}
FileOutputStream fOut = null;
try {
fOut = new FileOutputStream(f);
} catch (FileNotFoundException e) {
e.printStackTrace();
}
if (fOut != null) {
mBitmap.compress(Bitmap.CompressFormat.JPEG, 100, fOut);
try {
fOut.flush();
fOut.close();
} catch (IOException e) {
e.printStackTrace();
}
}
return f.toString();
}
/**
* 判断是否有sd卡
*
* @return
*/
public static boolean isStorage() {
boolean isstorage = Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED);
return isstorage;
}
/**
*把Bimtmap转成Base64,用于上传图片到服务器,一般是先压缩然后转成Base64,在上传
*
*
*/
public static String getBitmapStrBase64(Bitmap bitmap) {
ByteArrayOutputStream baos = new ByteArrayOutputStream();
bitmap.compress(Bitmap.CompressFormat.PNG, 100, baos);
byte[] bytes = baos.toByteArray();
return Base64.encodeToString(bytes, Base64.NO_WRAP);
}
public static String bitmapToBase64(Bitmap bitmap) {
String result = null;
ByteArrayOutputStream baos = null;
try {
if (bitmap != null) {
baos = new ByteArrayOutputStream();
bitmap.compress(Bitmap.CompressFormat.JPEG, 100, baos);
baos.flush();
baos.close();
byte[] bitmapBytes = baos.toByteArray();
result = Base64.encodeToString(bitmapBytes, Base64.NO_WRAP);
}
} catch (IOException e) {
e.printStackTrace();
} finally {
try {
if (baos != null) {
baos.flush();
baos.close();
}
} catch (IOException e) {
e.printStackTrace();
}
}
return result;
}
// 把Base64转换成Bitmap
public static Bitmap getBitmapFromBase64(String iconBase64) {
byte[] bitmapArray = Base64.decode(iconBase64, Base64.DEFAULT);
return BitmapFactory.decodeByteArray(bitmapArray, 0, bitmapArray.length);
}
}