激情久久久_欧美视频区_成人av免费_不卡视频一二三区_欧美精品在欧美一区二区少妇_欧美一区二区三区的

服務器之家:專注于服務器技術及軟件下載分享
分類導航

PHP教程|ASP.NET教程|Java教程|ASP教程|編程技術|正則表達式|C/C++|IOS|C#|Swift|Android|VB|R語言|JavaScript|易語言|vb.net|

服務器之家 - 編程語言 - Android - 淺析KJFrameForAndroid框架如何高效加載Bitmap

淺析KJFrameForAndroid框架如何高效加載Bitmap

2021-03-04 13:13Android開發網 Android

Bitmap是Android系統中的圖像處理的最重要類之一。用它可以獲取圖像文件信息,進行圖像剪切、旋轉、縮放等操作,并可以指定格式保存圖像文件。本文主要是從KJFrameForAndroid框架中分析高效加載Bitmap的方法

我們在寫Android程序的時候,肯定會用到很多圖片。那么對于圖片的壓縮處理自然是必不可少。為什么要壓縮?我想這個問題不必在強調了,每個人在最初學習Android的時候肯定都會知道這么一個原因:我們編寫的應用程序都是有一個最大內存限制,其中JAVA程序和C程序(NDK調用時)共享這一塊內存大小,程序占用了過高的內存就容易出現OOM(OutOfMemory)異常。至于這個最大內存是多少,我們可以通過調用Runtime.getRuntime().maxMemory()方法驗證一下。

正因為受到內存大小限制這一關鍵原因(其實不止這個原因,我想一張1M的圖片和一張10k的圖片,載入的速度必然也是不同的吧)。 如果你的控件大小只有40*40像素的大小,只是為了顯示一張縮略圖,這時候把一張1024*768像素的圖片完全加載到內存中顯然是不值得的,因此我們都會對圖片做壓縮處理。

BitmapFactory這個類提供了多個方法(decodeByteArray, decodeFile, decodeResource等)用于創建Bitmap對象,我們可以根據圖片的來源選擇合適的方法。然而這些方法會為已經讀取的bitmap分配內存,這時如果是一張非常大的圖片就會導致OOM出現。為此,每一種解析方法都提供了一個BitmapFactory.Options參數,可以通過將這個參數的inJustDecodeBounds屬性設置為true就可以讓解析方法禁止為bitmap分配內存,但是如此設置后BitmapFactory的返回值也不再是一個Bitmap對象,而是null。雖然Bitmap是null了,但是BitmapFactory.Options的outWidth、outHeight和outMimeType屬性都會被賦值。使用這個技巧讓我們可以在加載圖片之前就獲取到圖片的長寬值和類型,從而根據情況對圖片進行壓縮。

?
1
2
3
4
5
6
BitmapFactory.Options options = new BitmapFactory.Options();
 options.inJustDecodeBounds = true;
 BitmapFactory.decodeFile(pathName, options);
 int h = options.outHeight;
 int w = options.outWidth;
 String type = options.outMimeType;

那么知道了圖片的寬高,要如何壓縮呢?BitmapFactory.Options有一個inSampleSize屬性,這個int值表示圖片的原寬高變為1/inSampleSize倍,如果原圖是1024*768,inSampleSize=2,那么壓縮后圖片就變成了512*384。 最后將BitmapFactory.Options設置合適的inSampleSize值,并且記得將inJustDecodeBounds設置回false,再調用一次BitmapFactory相應的創建Bitmap的方法,并把Options傳入,就可以得到壓縮后的圖片了。

這里有一個節選自開源Android應用開發框架KJFrameForAndroid中的一段代碼

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
/**
 * 圖片壓縮處理(使用Options的方法)
 *
 * @使用方法 首先你要將Options的inJustDecodeBounds屬性設置為true,BitmapFactory.decode一次圖片。
 *  然后將Options連同期望的寬度和高度一起傳遞到到本方法中。
 *  之后再使用本方法的返回值做參數調用BitmapFactory.decode創建圖片。
 *
 * @explain BitmapFactory創建bitmap會嘗試為已經構建的bitmap分配內存
 * ,這時就會很容易導致OOM出現。為此每一種創建方法都提供了一個可選的Options參數
 * ,將這個參數的inJustDecodeBounds屬性設置為true就可以讓解析方法禁止為bitmap分配內存
 * ,返回值也不再是一個Bitmap對象, 而是null。雖然Bitmap是null了,但是Options的outWidth、
 * outHeight和outMimeType屬性都會被賦值。
 * @param reqWidth
 *  目標寬度
 * @param reqHeight
 *  目標高度
 */
  public static BitmapFactory.Options calculateInSampleSize(
   final 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 heightRatio = Math.round((float) height
    / (float) reqHeight);
   final int widthRatio = Math.round((float) width / (float) reqWidth);
   // 選擇寬和高中最小的比率作為inSampleSize的值,這樣可以保證最終圖片的寬和高
   // 一定都會大于等于目標的寬和高。
   inSampleSize = heightRatio < widthRatio ? heightRatio : widthRatio;
   }
   // 設置壓縮比例
   options.inSampleSize = inSampleSize;
   options.inJustDecodeBounds = false;
   return options;
  }

以上的方法適合使用在讀取一個未知來源的圖片時使用,因為你不知道這個未知來源圖片的大小,那么還有一種方法是用在已經載入內存的圖片,對已經載入內存的圖片做壓縮以后重新保存到本地,從而可以把一張原本1M大小的圖片變成一張10K的圖片。

這種方法的核心思想是首先將圖片轉成一個輸出流,并記錄輸出流的byte數組大小,通過調用bitmap對象的compress方法,對圖片做一次壓縮以及格式化,并將byte數組大小與期望壓縮的目標大小比對,得出壓縮比率,并調用Bitmap的縮放方法,縮放計算出的壓縮比率,從而得到壓縮后的方法。

下面我們繼續來看KJFrameForAndroid框架中的另一段代碼:

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
/**
  * 圖片壓縮方法:(使用compress的方法)
  *
  * @explain 如果bitmap本身的大小小于maxSize,則不作處理
  * @param bitmap
  *  要壓縮的圖片
  * @param maxSize
  *  壓縮后的大小,單位kb
  */
 public static void imageZoom(Bitmap bitmap, double maxSize) {
  // 將bitmap放至數組中,意在獲得bitmap的大小(與實際讀取的原文件要大)
  ByteArrayOutputStream baos = new ByteArrayOutputStream();
  // 格式、質量、輸出流
  bitmap.compress(Bitmap.CompressFormat.JPEG, 100, baos);
  byte[] b = baos.toByteArray();
  // 將字節換成KB
  double mid = b.length / 1024;
  // 獲取bitmap大小 是允許最大大小的多少倍
  double i = mid / maxSize;
  // 判斷bitmap占用空間是否大于允許最大空間 如果大于則壓縮 小于則不壓縮
  if (i > 1) {
   // 縮放圖片 此處用到平方根 將寬帶和高度壓縮掉對應的平方根倍
   // (保持寬高不變,縮放后也達到了最大占用空間的大小)
   bitmap = scale(bitmap, bitmap.getWidth() / Math.sqrt(i),
     bitmap.getHeight() / Math.sqrt(i));
  }
 }
/***
  * 圖片的縮放方法
  *
  * @param src
  *  :源圖片資源
  * @param newWidth
  *  :縮放后寬度
  * @param newHeight
  *  :縮放后高度
  */
 public static Bitmap scale(Bitmap src, double newWidth, double newHeight) {
  // 記錄src的寬高
  float width = src.getWidth();
  float height = src.getHeight();
  // 創建一個matrix容器
  Matrix matrix = new Matrix();
  // 計算縮放比例
  float scaleWidth = ((float) newWidth) / width;
  float scaleHeight = ((float) newHeight) / height;
  // 開始縮放
  matrix.postScale(scaleWidth, scaleHeight);
  // 創建縮放后的圖片
  return Bitmap.createBitmap(src, 0, 0, (int) width, (int) height,
    matrix, true);
 }

另外附上KJFrameForAndroid框架項目地址: https://github.com/kymjs/KJFrameForAndroid

或備用地址 http://git.oschina.net/kymjs/KJFrameForAndroid

有這方面需要的朋友可以下載下來自己研究下

延伸 · 閱讀

精彩推薦
主站蜘蛛池模板: 久久国产精品久久久久久久久久 | 密室逃脱第一季免费观看完整在线 | 日本成人一区二区三区 | h视频免费在线观看 | 日韩黄在线 | 国外成人在线视频 | 91专区在线观看 | 毛片毛片免费看 | 久久91亚洲人成电影网站 | 欧美999 | 色黄小说| 在线播放黄色网址 | 久久精品国产清自在天天线 | 91九色视频在线播放 | 欧美福利视频一区二区三区 | 欧美一级做一a做片性视频 黄色网址免费进入 | 久久国产28 | 九九热在线视频观看 | 久久最新视频 | 亚洲影院在线观看 | 免费一级欧美大片视频 | 曰本三级日本三级日本三级 | 欧美成人精品一区 | 久久久久久久久久久国产精品 | 九一免费版在线观看 | 久久久一二三 | 国产亚洲欧美日韩高清 | 欧美成人精品一区二区三区 | 日本a大片 | xx53xx| 久久久综合视频 | 日本在线观看一区二区 | 369看片你懂的小视频在线观看 | 国产大片中文字幕在线观看 | 黄色av免费电影 | 九九精品在线观看视频 | av成人在线播放 | 午夜精品一区二区三区免费 | av在线等 | 亚洲第一综合 | 亚洲最黄视频 |