android大圖、高清圖片處理
Android大圖、高清圖片處理
Android中,系統分配給手機app的記憶體是有限的,現階段根據不同的手機分配的最大記憶體也不一樣,少的只有幾十M。當我們以Bitmap的形式把高清的大圖載入到記憶體當中時,它佔用的記憶體會成倍數的增加。佔用的記憶體超過了系統能夠提供給app的記憶體時,會產生OOM。
1、圖片佔用記憶體的估計計算(並非實際值):
佔用的記憶體 = 圖片長度 * 圖片寬度 * 單位畫素佔用的位元組數
圖片格式:
ALPHA_8 : 1byte 只儲存alpha
ARGB_4444: 2byte 圖片有可能會被破壞,效果差
ARGB_8888: 4byte 主流的儲存方式
RGB_565: 2byte 不考慮alpha時推薦使用
2、png和jpg圖片的選擇
png:能用png最好是用png,32位的png顏色過渡平滑且支援透明。
jpg:是畫素化壓縮過的圖片,質量已經下降了,一般不拿來做.9path的平鋪拉伸的控制元件。
對於顏色繁雜的,比如照片牆紙,啟動頁面之類的圖片,可用jpg。如果儲存成png體積將是jpg的幾倍甚至幾十倍,嚴重浪費體積。其他的資原始檔使用png。
3、畫素壓縮法
可以按照當前view的大小進行壓縮,壓縮成縮圖顯示在view中,減少記憶體的消耗,防止OOM,同時保證圖片不失真。
設定opts.inJustDecodeBounds
/**
* 對資源中的大圖片進行解析度大小的壓縮
* @param context
* @param resourceId 資源的id
* @param view 顯示圖片的控制元件Imageview
*/
public static void setImageResource(Context context, int resourceId, ImageView view)
{
BitmapFactory.Options opts = new BitmapFactory.Options();
// 不讀取畫素陣列到記憶體中,僅讀取圖片的資訊
opts.inJustDecodeBounds = true;
BitmapFactory.decodeResource(context.getResources(), resourceId,opts);
// 從Options中獲取圖片的解析度
int imageHeight = opts.outHeight;
int imageWidth = opts.outWidth;
int scaleX;
int scaleY;
// 計算取樣率
if(view.getWidth() > 0 && view.getHeight() > 0)
{
//採用view的尺寸對應得大小進行壓縮
scaleX = imageWidth / view.getWidth();
scaleY = imageHeight / view.getHeight();
}
else
{
//view未初始化完成,獲得的寬高為0,採用螢幕的解析度尺寸來進行壓縮
WindowManager wm = (WindowManager) context.getSystemService(context.WINDOW_SERVICE);
scaleX = imageWidth / wm.getDefaultDisplay().getWidth();
scaleY = imageHeight / wm.getDefaultDisplay().getHeight();
}
int scale = 1;
// 取樣率依照最大的方向為準
if (scaleX > scaleY && scaleY >= 1) {
scale = scaleX;
}
if (scaleX < scaleY && scaleX >= 1) {
scale = scaleY;
}
Log.e("measure","scale = "+scale);
// false表示讀取圖片畫素陣列到記憶體中,依照設定的取樣率
opts.inJustDecodeBounds = false;
// 取樣率
opts.inSampleSize = scale;
opts.inPreferredConfig = Bitmap.Config.ARGB_8888;
Bitmap bitmap = BitmapFactory.decodeResource(context.getResources(),R.mipmap.larg,opts);
view.setImageBitmap(bitmap);
}
opts.inSampleSize= scale;為設定取樣率,scale的最終等級為2的n次方,如1,2,4,8....;如果是scale為2,3,最終系統都會取2作為取樣率;如果是4,5,6,7系統會自動取4作為取樣率....
如上圖所示,opts.inSampleSize設定為2則佔用記憶體約為未壓縮前的1/4,設定為4則為未壓縮前的1/16 ..... 對應的壓縮率最好是通過view在手機上的顯示大小進行計算,這樣可以更好的適配到手機上,不影響顯示效果。
2、質量壓縮法
用於壓縮後儲存在disk下,會破壞圖片的質量,不會改變圖片的大小尺寸。但佔用的記憶體不會減少,通常用於壓縮上傳伺服器的圖片。
/**
* 質量壓縮方法
*
* @param image
* @return
*/
private static Bitmap compressImage(Bitmap image) {
ByteArrayOutputStream baos = new ByteArrayOutputStream();
image.compress(Bitmap.CompressFormat.JPEG, 100, baos);
int options = 100;
while (baos.toByteArray().length / 1024 > 100 && options > 50) {
baos.reset();
image.compress(Bitmap.CompressFormat.JPEG, options, baos);
options -= 10;
}
ByteArrayInputStream isBm = new ByteArrayInputStream(baos.toByteArray());
Bitmap bitmap = BitmapFactory.decodeStream(isBm, null, null);
return bitmap;
}
圖片上傳伺服器:
1、圖片進行畫素壓縮
2、圖片進行質量壓縮
3、本地儲存
4、上傳伺服器
5、上傳成功後刪除本地圖片