java.lang.OutOfMemoryError
OOM就是內存溢出,即Out Of Memory。也就是說內存佔有量超過了VM所分配的最大。
現在的手機照相功能強大圖片的大小往往達到好幾兆,並且。android中處理圖片的基礎類是Bitmap,顧名思義,就是位圖。佔用內存的算法如:圖片的width*height*Config。 如果Config設置爲ARGB_8888,那麼上面的Config就是4。一張480*320的圖片佔用的內存就是480*320*4 byte。 在默認情況下android進程的內存佔用量爲16M,所以導致了內存溢出,
在手機應用中 如果單獨將一張圖片加載顯示,比如說微信發送圖片時可以預覽圖片,這種情況下直接加載圖片也就是用BItMap
BitmapFactory.decodeFile(pathName);不進行壓縮一般不會出現內存溢出,但是在多張圖片展示時,會出現oom導致程序崩潰這時我們要進行圖片壓縮,這部分代碼大家都應該很熟悉了,
public Bitmap revitionImageSize(String path) throws IOException {
BufferedInputStream in = null;
try {
<span style="white-space:pre"> </span>//根據地址轉換爲 文件輸入流對象 也可以把File轉換成輸入對象
in = new BufferedInputStream(new FileInputStream(path));
BitmapFactory.Options options = new BitmapFactory.Options();
//<span style="font-family: 'Microsoft YaHei', Verdana, sans-serif, 宋體;">Options 設置圖片屬性</span>
options.inJustDecodeBounds = true;//這個屬性是重點這樣設置之後
BitmapFactory.decodeStream(in, null, options);// 調用這個方法可以不把圖片加載到內存中,但可以獲取圖片的寬高大小
in.close();
in = null;
int i = 0;
Bitmap bitmap = null;
while (true) {
if ((options.outWidth >> i <= 256)
&& (options.outHeight >> i <= 256)) {
in = new BufferedInputStream(new FileInputStream(new File(
path)));
//調整圖片大小
options.inSampleSize = calculateInSampleSize(options,
CommonUtil.dip2px(this, 80),
CommonUtil.dip2px(this, 80));
options.inJustDecodeBounds = false;//設置加載到內存中
bitmap = BitmapFactory.decodeStream(in, null, options); //創建圖片
break;
}
i += 1;
}
return bitmap;
} catch (Exception e) {
Log.e("System.out", e.getMessage());
return null;
} finally {
if (null != in) {//關閉流
in.close();
in = null;
}
}
}
// 按照寬高中 短的壓縮
public int calculateInSampleSize(BitmapFactory.Options options,
int reqWidth, int reqHeight) {
// Raw height and width of image
final int height = options.outHeight;
final int width = options.outWidth;
int inSampleSize = 1;
if (height > reqHeight || width > reqWidth) {//判斷實際大小是不是不要求大小 大
if (width > height) { //如果 寬度筆高地長的話 安短的一邊 計算壓縮比
inSampleSize = Math.round((float) height / (float) reqHeight);
} else {
inSampleSize = Math.round((float) width / (float) reqWidth);
}
}
return inSampleSize;
}
這樣返回壓縮好的圖片,這樣只是單純的壓縮了一張圖片
顯示一張圖片,做圖片相冊類的activity時還涉及到遍歷手機sd卡里的所有圖片這裏就不到說了,
壓縮圖片上傳
圖片壓縮的部分跟
上面也是差不多的
private void setUpImageFile() {
FileInputStream is = null;
File f = null, imageFile; //f壓縮後的圖片 壓縮前的圖片文件
Bitmap image = null;
try {
imageFile = new File(path);
if (imageFile.length() <= 800 * 1024) { // 判端文件大小 800k以內直接上傳
this.upPath = path;
return;
}
is = new FileInputStream(imageFile);
// 定義一個file,爲壓縮後的圖片
SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:sss");
//創建個文件
f = new File(Environment.getExternalStorageDirectory() + “/image”, simpleDateFormat.format(new Date()) + "上傳.jpeg");
if (!f.getParentFile().exists())//創建目錄
f.getParentFile().mkdirs();
int size = (int) (imageFile.length() / (1024 * 1024) * 10);// 計算目標文件的大小 大於1024K壓縮到1024k以內
size = (int) Math.rint(size / 10);
Options options = new Options();
options.inSampleSize = size;
// 將圖片縮小爲原來的 1/size ,上傳
image = BitmapFactory.decodeStream(is, null, options);
is.close();
} catch (Exception e1) {
e1.printStackTrace();
return;
}
// 把bitmap創建處理 再次壓縮
ByteArrayOutputStream baos = new ByteArrayOutputStream();
image.compress(Bitmap.CompressFormat.JPEG, 100, baos);// 這裏100表示不壓縮,將不壓縮的數據存放到baos中
int per = 100;
while (baos.toByteArray().length / 1024 > 1024) { // 循環判斷如果壓縮後圖片是否大於1024kb,大於繼續壓縮
baos.reset();// 重置baos即清空baos
image.compress(Bitmap.CompressFormat.JPEG, per, baos);// 將圖片壓縮爲原來的(100-per)%,把壓縮後的數據存放到baos中
per -= 5;// 每次都減少10
}
// 回收圖片,清理內存
if (image != null && !image.isRecycled()) {
image.recycle();
image = null;
System.gc();
}
//把內存中的 image 寫到文件中
ByteArrayInputStream isBm = new ByteArrayInputStream(baos.toByteArray());// 把壓縮後的數據baos存放到ByteArrayInputStream中
try {
baos.close();
FileOutputStream os;
os = new FileOutputStream(f);
// 將輸入流複製到輸出流中
CopyStream(isBm, os);
isBm.close();
os.close();
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
this.upPath = f.getAbsolutePath();
}
private void CopyStream(ByteArrayInputStream isBm, FileOutputStream os) {
byte[] buff = new byte[1024];
int length = 0;
try {
while ((length = isBm.read(buff)) != -1) {
os.write(buff, 0, length);
}
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
這樣在sd的/image目錄下創建了等待上傳的壓縮後的文件