有效的處理較大的點陣圖
影象有各種形狀和大小。在許多情況下,他們往往比一個典型應用程式的使用者介面(UI)所需要的資源更大。例如,系統的Gallery程式展示使用Android裝置照相機所拍攝的照片通常要比你的裝置的螢幕密度更高的解析度下顯示。
既然你所使用的記憶體有限,理想狀況下你只想在記憶體中載入一個低版本的方案。低版本的方案應該匹配顯示它的UI元件的大小。一個更高的解決方案不提供任何可見的好處,但是仍然佔用以前的記憶體,由於額外的縮放會導致額外的效能開銷。
這節課將引導你在不超過記憶體限制的情況下通過解碼大點陣圖,在記憶體中載入一個較小的點陣圖子樣本。
BitmapFactory類提供了集中解碼的方法(decodeByteArray(),decodeFile(),decodeResource(),等等)從多種資源中來建立一個點陣圖。選擇最合適的解碼方法基於你的影象資料資源。這些方法試圖情去分配記憶體來構造點陣圖,因此很容易導致OutOfMemory異常。每種型別的解碼方法都有額外的特徵可以讓你通過BitMapFactory.Options類指定特定解碼方法。當解碼時避免記憶體分配可以設定inJustDecodeBounds屬性為true,點陣圖物件返回null除非設定outWidth,outHeight和outMimeType。這種技術允許你在建立點陣圖(分配記憶體)之前去讀取影象的維度和型別。
1 2 3 4 5 6 7 8 9 10 11 |
BitmapFactory.Options options = new BitmapFactory.Options();
options.inJustDecodeBounds = true;
BitmapFactory.decodeResource(getResources(), R.id.myimage, options);
int imageHeight = options.outHeight;
int imageWidth = options.outWidth;
String imageType = options.outMimeType;
|
為了避免java.lang.OutOfMemory異常,在解碼點陣圖之前請檢查它的維度,除非你十分確定資源提供給你的可預見的影象資料正好滿足你的記憶體。
現在的影象尺寸都是已知的,他們可以被用來決定是否應該載入到儲存器或者是否一個子樣本的版本被載入。以下是一些值得考慮的因素:
-
- 估計載入完整影象所需要的記憶體;
-
- 你承諾載入這個圖片所需空間帶給你的程式的其他記憶體需求;
-
- 準備載入影象的目標ImageView或UI組建尺寸;
-
- 當前裝置的螢幕尺寸和密度;
例如,如果1024* 768畫素的影象最終被縮略地顯示在一個128* 96畫素的ImageView中,就不值得載入到記憶體中去。
告訴解碼器去子樣本化影象,載入一個更小的版本到記憶體中,在你的BitmapFactory.Option物件中設定inSampleSize為true。例如,將一個解析度為2048* 1536的影象解碼為4個子版本大小為大約512* 384的點陣圖。載入這個到記憶體中僅使用0.75MB,而不是完整的12MB大小的影象(假設使用ARGB_8888點陣圖的配置)。這裡有一個方法在目標的寬度和高度的基礎上來計算一個樣本的大小。
```Java
public static int calculateInSampleSize(
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
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;
}
<p style="border-color: #258AAF; border-style: solid; border-width: 0 0 0 4px; padding: 0 0 0 10px;">
|
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 |
**NOTE:**使用2的冪數設定inSampleSize的值可以使解碼器更快,更有效。然而,如果你想在記憶體或硬碟中快取一個圖片調整後的版本,通常解碼到合適的影象尺寸更適合來節省空間。
要使用這種方法,首先解碼,將inJustDecodeBounds設定為true,將選項傳遞進去,然後再次解碼,在使用新的inSampleSize值並將inJustDecodeBounds設定為false:
```Java
public static Bitmap decodeSampledBitmapFromResource(Resources res, int resId,
int reqWidth, int reqHeight) {
// First decode with inJustDecodeBounds=true to check dimensions
final BitmapFactory.Options options = new BitmapFactory.Options();
options.inJustDecodeBounds = true;
BitmapFactory.decodeResource(res, resId, options);
// Calculate inSampleSize
options.inSampleSize = calculateInSampleSize(options, reqWidth, reqHeight);
// Decode bitmap with inSampleSize set
options.inJustDecodeBounds = false;
return BitmapFactory.decodeResource(res, resId, options);
}
|
這種方法可以很容易地載入任意大小的點陣圖到一個ImageView顯示一個100x100畫素的縮圖,如下面的示例程式碼所示:
```Java
1 2 3 |
mImageView.setImageBitmap(
decodeSampledBitmapFromResource(getResources(), R.id.myimage, 100, 100));
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 |
你可以按照類似的過程,用適當的BitmapFactory.decode* 中的方法去解碼一個從其他資源得到的點陣圖。影象有各種形狀和大小。在許多情況下,他們往往比一個典型應用程式的使用者介面(UI)所需要的資源更大。例如,系統的Gallery程式展示使用Android裝置照相機所拍攝的照片通常要比你的裝置的螢幕密度更高的解析度下顯示。
既然你所使用的記憶體有限,理想狀況下你只想在記憶體中載入一個低版本的方案。低版本的方案應該匹配顯示它的UI元件的大小。一個更高的解決方案不提供任何可見的好處,但是仍然佔用以前的記憶體,由於額外的縮放會導致額外的效能開銷。
這節課將引導你在不超過記憶體限制的情況下通過解碼大點陣圖,在記憶體中載入一個較小的點陣圖子樣本。
BitmapFactory類提供了集中解碼的方法(decodeByteArray(),decodeFile(),decodeResource(),等等)從多種資源中來建立一個點陣圖。選擇最合適的解碼方法基於你的影象資料資源。這些方法試圖情去分配記憶體來構造點陣圖,因此很容易導致OutOfMemory異常。每種型別的解碼方法都有額外的特徵可以讓你通過BitMapFactory.Options類指定特定解碼方法。當解碼時避免記憶體分配可以設定inJustDecodeBounds屬性為true,點陣圖物件返回null除非設定outWidth,outHeight和outMimeType。這種技術允許你在建立點陣圖(分配記憶體)之前去讀取影象的維度和型別。
```Java
BitmapFactory.Options options = new BitmapFactory.Options();
options.inJustDecodeBounds = true;
BitmapFactory.decodeResource(getResources(), R.id.myimage, options);
int imageHeight = options.outHeight;
int imageWidth = options.outWidth;
String imageType = options.outMimeType;
|
為了避免java.lang.OutOfMemory異常,在解碼點陣圖之前請檢查它的維度,除非你十分確定資源提供給你的可預見的影象資料正好滿足你的記憶體。
現在的影象尺寸都是已知的,他們可以被用來決定是否應該載入到儲存器或者是否一個子樣本的版本被載入。以下是一些值得考慮的因素:
-
- 估計載入完整影象所需要的記憶體;
-
- 你承諾載入這個圖片所需空間帶給你的程式的其他記憶體需求;
-
- 準備載入影象的目標ImageView或UI組建尺寸;
-
- 當前裝置的螢幕尺寸和密度;
例如,如果1024* 768畫素的影象最終被縮略地顯示在一個128* 96畫素的ImageView中,就不值得載入到記憶體中去。
告訴解碼器去子樣本化影象,載入一個更小的版本到記憶體中,在你的BitmapFactory.Option物件中設定inSampleSize為true。例如,將一個解析度為2048* 1536的影象解碼為4個子版本大小為大約512* 384的點陣圖。載入這個到記憶體中僅使用0.75MB,而不是完整的12MB大小的影象(假設使用ARGB_8888點陣圖的配置)。這裡有一個方法在目標的寬度和高度的基礎上來計算一個樣本的大小。
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 |
public static 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;
}
|
NOTE:使用2的冪數設定inSampleSize的值可以使解碼器更快,更有效。然而,如果你想在記憶體或硬碟中快取一個圖片調整後的版本,通常解碼到合適的影象尺寸更適合來節省空間。
要使用這種方法,首先解碼,將inJustDecodeBounds設定為true,將選項傳遞進去,然後再次解碼,在使用新的inSampleSize值並將inJustDecodeBounds設定為false:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 |
public static Bitmap decodeSampledBitmapFromResource(Resources res, int resId,
int reqWidth, int reqHeight) {
// First decode with inJustDecodeBounds=true to check dime
final BitmapFactory.Options options = new BitmapFactory.Options();
options.inJustDecodeBounds = true;
BitmapFactory.decodeResource(res, resId, options);
// Calculate inSampleSize
options.inSampleSize = calculateInSampleSize(options, reqWidth, reqHeight);
// Decode bitmap with inSampleSize set
options.inJustDecodeBounds = false;
return BitmapFactory.decodeResource(res, resId, options);
}
|
這種方法可以很容易地載入任意大小的點陣圖到一個ImageView顯示一個100x100畫素的縮圖,如下面的示例程式碼所示:
1 2 3 |
mImageView.setImageBitmap(
decodeSampledBitmapFromResource(getResources(), R.id.myimage, 100, 100));
|
你可以按照類似的過程,用適當的BitmapFactory.decode* 中的方法去解碼一個從其他資源得到的點陣圖。
相關文章
- Java-GUI程式設計之處理點陣圖JavaGUI程式設計
- 利用SQL Profiler處理開銷較大的查詢SQL
- thumbor:功能強大的圖片處理庫
- ZT:處理Oracle資料庫中一張有效的Drop大表Oracle資料庫
- 【索引】Bitmap點陣圖索引與普通的B-Tree索引鎖的比較索引
- 如何處理系統具有較大併發量?
- 圖片區域點選處理
- 20 個強大圖象處理功能的 SVG 工具SVG
- B-Tree索引與Bitmap點陣圖索引的鎖代價比較研究索引
- C++進階(點陣圖+布隆過濾器的概念和實現+海量資料處理)C++過濾器
- 點陣圖
- 如何高效的處理陣列對映陣列
- 當 Vue 處理陣列與處理純物件的方式一樣Vue陣列物件
- Oracle審計--AUD$佔用空間較大處理方案Oracle
- 點陣圖索引的工作原理 - Richard索引
- SELECT大表的處理
- 陣列的操作處理與陣列元素的氣泡排序 (轉)陣列排序
- 【Bitmap Index】B-Tree索引與Bitmap點陣圖索引的鎖代價比較研究Index索引
- 頭像點選檢視大圖和儲存功能實現(儲存的細節處理)
- C++雜湊應用-點陣圖/布隆過濾器/海量資料處理C++過濾器
- 使用點陣圖選單項——建立點陣圖 (轉)
- Go 處理大陣列:使用 for range 還是 for 迴圈?Go陣列
- 【筆記】Oracle B-tree、點陣圖、全文索引三大索引效能比較及優缺點彙總筆記Oracle索引
- 點陣圖排序排序
- 【點陣圖索引】在點陣圖索引列上進行更新操作的鎖代價研究索引
- VC 點陣圖按鈕CBitmapButton的使用
- hash join構建點陣圖的理解
- 走近webpack(3)–圖片的處理Web
- 大資料處理的基本流程大資料
- 關於大資料量的處理大資料
- 資料處理,會“說話”的大機器——資料資訊圖
- 陣列處理函式陣列函式
- PHP 陣列 & 字串處理PHP陣列字串
- 有沒有好的圖片處理包,能實現大圖中尋找小圖
- 深入瞭解如何對IPA包進行有效的混淆處理
- 【16位RAW影像處理三】直方圖均衡化及區域性直方圖均衡用於16點陣圖像的細節增強。直方圖
- 9個必須掌握的Javascript處理陣列的方法JavaScript陣列
- 點贊處理的一些小技巧