## 本節引言:
> 在上一節中我們對Android中的13種類型的Drawable的類型進行了講解,有沒有應用到自己的 項目當中呢?而本節我們來探討的是Bitmap(位圖)的一些使用,而在開始本節的內容之前我們 先來區分幾個名詞的概念:
>
> * **Drawable**:通用的圖形對象,用于裝載常用格式的圖像,既可以是PNG,JPG這樣的圖像, 也是前面學的那13種Drawable類型的可視化對象!我們可以理解成一個用來放畫的——**畫框**!
> * **Bitmap(位圖)**:我們可以把他看作一個**畫架**,我們先把畫放到上面,然后我們可以 進行一些處理,比如獲取圖像文件信息,做旋轉切割,放大縮小等操作!
> * **Canvas(畫布)**:如其名,**畫布**,我們可以在上面作畫(繪制),你既可以用**Paint(畫筆)**, 來畫各種形狀或者寫字,又可以用**Path(路徑)**來繪制多個點,然后連接成各種圖形!
> * **Matrix(矩陣)**:用于圖形特效處理的,顏色矩陣(ColorMatrix),還有使用Matrix進行圖像的 平移,縮放,旋轉,傾斜等!
>
> 而上述的這些都是Android中的底層圖形類:**android.graphics**給我們提供的接口! 嗯,話不多說開始本節內容! PS:官方文檔:[Bitmap](http://androiddoc.qiniudn.com/reference/android/graphics/Bitmap.html)
* * *
## 1.了解Bitmap,BitmapFactory,BitmapFacotry.Options
> 如題,本來可以直接說著三個東東的關系的,但是我就是要**傲嬌**,就要看代碼!?如果你打開Bitmap類的源碼,你會看到Bitmap的構造方法上有這樣一段東東:
>
> 
>
> 大概想說的就是:Bitmap的構造方法是私有的,外面不能實例化,只能通過JNI實例化! 當然,肯定也會給我們提供一個接口給我們來創建Bitmap的,而這個接口類就是:**BitmapFactory**! 來來來,打開BitmapFactory類,我們點下左邊的Structure可以看到BitmapFactory給我們 提供了這些方法,大部分都是decodeXxx,通過各種形式來創建Bitmap的!
>
> 
>
> 接著我們又發現了,每一種方法,都會有一個Options類型的參數,點進去看看: 于是乎我們發現了這貨是一個靜態內部類:**BitmapFacotry.Options**! 而他是用來設置decode時的選項的!
>
> 
>
> 我們對這里的某些參數的值進行設置,比如inJustDecodeBounds設置為true避免OOM(內存溢出), 什么,不知道OOM,沒事,等下一點點跟你說清楚!最后回到我們的Bitmap!嗯,Bitmap中的 方法比較多,就不一一進行講解了,我們從中挑幾個用得較多的來講解! 中文文檔:[Android中文API(136) —— Bitmap](http://www.cnblogs.com/over140/archive/2011/11/21/2256727.html)
* * *
## 2.Bitmap常用方法
> **普通方法**
>
> * public boolean?**compress**?(Bitmap.CompressFormat format, int quality, OutputStream stream) 將位圖的壓縮到指定的OutputStream,可以理解成將Bitmap保存到文件中!?**format**:格式,PNG,JPG等;?**quality**:壓縮質量,0-100,0表示最低畫質壓縮,100最大質量(PNG無損,會忽略品質設定)?**stream**:輸出流 返回值代表是否成功壓縮到指定流!
> * void?**recycle**():回收位圖占用的內存空間,把位圖標記為Dead
> * boolean?**isRecycled**():判斷位圖內存是否已釋放
> * int?**getWidth**():獲取位圖的寬度
> * int?**getHeight**():獲取位圖的高度
> * boolean?**isMutable**():圖片是否可修改
> * int?**getScaledWidth**(Canvas canvas):獲取指定密度轉換后的圖像的寬度
> * int?**getScaledHeight**(Canvas canvas):獲取指定密度轉換后的圖像的高度
>
> **靜態方法**:
>
> * Bitmap?**createBitmap**(Bitmap src):以src為原圖生成不可變得新圖像
> * Bitmap?**createScaledBitmap**(Bitmap src, int dstWidth,int dstHeight, boolean filter):以src為原圖,創建新的圖像,指定新圖像的高寬以及是否變。
> * Bitmap?**createBitmap**(int width, int height, Config config):創建指定格式、大小的位圖
> * Bitmap?**createBitmap**(Bitmap source, int x, int y, int width, int height)以source為原圖,創建新的圖片,指定起始坐標以及新圖像的高寬。
> * public static Bitmap?**createBitmap**(Bitmap source, int x, int y, int width, int height, Matrix m, boolean filter)
**BitmapFactory.Option**可設置參數:
> * boolean?**inJustDecodeBounds**——如果設置為true,不獲取圖片,不分配內存,但會返回圖片的高寬度信息。
> * int?**inSampleSize**——圖片縮放的倍數。如果設為4,則寬和高都為原來的1/4,則圖是原來的1/16。
> * int?**outWidth**——獲取圖片的寬度值
> * int?**outHeight**——獲取圖片的高度值
> * int?**inDensity**——用于位圖的像素壓縮比
> * int?**inTargetDensity**——用于目標位圖的像素壓縮比(要生成的位圖)
> * boolean?**inScaled**——設置為true時進行圖片壓縮,從inDensity到inTargetDensity。
好吧,就貼這么多吧,要用自己查文檔~
* * *
## 3.獲取Bitmap位圖
> 從資源中獲取位圖的方式有兩種:通過BitmapDrawable或者BitmapFactory,下面演示下: 我們首先得獲得這個
**BitmapDrawable方法**:
你可以創建一個構造一個BitmapDrawable對象,比如通過流構建BitmapDrawable:
~~~
BitmapDrawable bmpMeizi = new BitmapDrawable(getAssets().open("pic_meizi.jpg"));
Bitmap mBitmap = bmpMeizi.getBitmap();
img_bg.setImageBitmap(mBitmap);
~~~
**BitmapFactory方法**:
都是靜態方法,直接調,可以通過資源ID、路徑、文件、數據流等方式來獲取位圖!
~~~
//通過資源ID
private Bitmap getBitmapFromResource(Resources res, int resId) {
return BitmapFactory.decodeResource(res, resId);
}
//文件
private Bitmap getBitmapFromFile(String pathName) {
return BitmapFactory.decodeFile(pathName);
}
//字節數組
public Bitmap Bytes2Bimap(byte[] b) {
if (b.length != 0) {
return BitmapFactory.decodeByteArray(b, 0, b.length);
} else {
return null;
}
}
//輸入流
private Bitmap getBitmapFromStream(InputStream inputStream) {
return BitmapFactory.decodeStream(inputStream);
}
~~~
* * *
## 4.獲取Bitmap的相關信息:
這個,只要我們獲取了Bitmap對象,就可以調用相關方法來獲取對應的參數了,getByteCount獲得大小, getHeight和getWidth這些~這里就不寫了,自己查文檔!
* * *
## 5.摳圖片上的某一角下來
有時,可能你想把圖片上的某一角扣下來,直接通過Bitmap的createBitmap()扣下來即可 參數依次為:處理的bitmap對象,起始x,y坐標,以及截取的寬高
~~~
Bitmap bitmap1 = BitmapFactory.decodeResource(getResources(), R.mipmap.pic_meizi);
Bitmap bitmap2 = Bitmap.createBitmap(bitmap1,100,100,200,200);
img_bg = (ImageView) findViewById(R.id.img_bg);
img_bg.setImageBitmap(bitmap2);
~~~
**運行效果圖**:
原圖:

切下來的一角:

* * *
## 6.對Bitmap進行縮放
我們這里不用Matrix來對Bitmap,而是直接使用Bitmap給我們提供的**createScaledBitmap**來實現, 參數依次是:處理的bitmap對象,縮放后的寬高,

* * *
## 7.使用Bitmap進行截屏
**運行效果圖**:

**實現代碼**:
~~~
public class MainActivity extends AppCompatActivity {
static ByteArrayOutputStream byteOut = null;
private Bitmap bitmap = null;
private Button btn_cut;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
btn_cut = (Button) findViewById(R.id.btn_cut);
btn_cut.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
captureScreen();
}
});
}
public void captureScreen() {
Runnable action = new Runnable() {
@Override
public void run() {
final View contentView = getWindow().getDecorView();
try{
Log.e("HEHE",contentView.getHeight()+":"+contentView.getWidth());
bitmap = Bitmap.createBitmap(contentView.getWidth(),
contentView.getHeight(), Bitmap.Config.ARGB_4444);
contentView.draw(new Canvas(bitmap));
ByteArrayOutputStream byteOut = new ByteArrayOutputStream();
bitmap.compress(Bitmap.CompressFormat.JPEG, 100, byteOut);
savePic(bitmap, "sdcard/short.png");
}catch (Exception e){e.printStackTrace();}
finally {
try{
if (null != byteOut)
byteOut.close();
if (null != bitmap && !bitmap.isRecycled()) {
// bitmap.recycle();
bitmap = null;
}
}catch (IOException e){e.printStackTrace();}
}
}
};
try {
action.run();
} catch (Exception e) {
e.printStackTrace();
}
}
private void savePic(Bitmap b, String strFileName) {
FileOutputStream fos = null;
try {
fos = new FileOutputStream(strFileName);
if (null != fos) {
boolean success= b.compress(Bitmap.CompressFormat.PNG, 100, fos);
fos.flush();
fos.close();
if(success)
Toast.makeText(MainActivity.this, "截屏成功", Toast.LENGTH_SHORT).show();
}
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
}
~~~
**代碼分析**:
> 代碼非常簡單,final View contentView = getWindow().getDecorView();這句代碼是獲取當前XML 根節點的View!然后設置截屏的大小,調用下contentView.draw(new Canvas(bitmap));好了,然后 bitmap轉換成流,接著寫入SD卡,沒了~當然從結果我們也可以看出,截圖截取的是改APP的內容而已! 如果要截全屏,自行谷歌~!
* * *
## 本節小結:
> 本節給大家講解下Bitmap,BitmapFactory和他的靜態內部類Options,以及BitmapDrawable的 基本使用,其實Bitmap我們知道怎么創建就好了,他的擴展一般是通過Matrix和Canvas來實現的, Bitmap,我們更多的時候關注的是OOM問題,下一節我們就來學習下如何避免Bitmap的OOM問題! 謝謝~
- 第一章——環境搭建和開發相關
- 1.0 Android基礎入門教程
- 1.1 背景相關與系統架構分析
- 1.2 開發環境搭建
- 1.2.1 使用Eclipse + ADT + SDK開發Android APP
- 1.2.2 使用Android Studio開發Android APP
- 1.3 SDK更新不了問題解決
- 1.4 Genymotion模擬器安裝
- 1.5 GIT教程
- 1.5.1 Git使用教程之本地倉庫的基本操作
- 1.5.2 Git之使用GitHub搭建遠程倉庫
- 1.6 .9(九妹)圖片怎么玩
- 1.7 界面原型設計
- 1.8 工程相關解析(各種文件,資源訪問)
- 1.9 Android程序簽名打包
- 1.11 反編譯APK獲取代碼&資源
- 第二章——Android中的UI組件的詳解
- 2.1 View與ViewGroup的概念
- 2.2 布局
- 2.2.1 LinearLayout(線性布局)
- 2.2.2 RelativeLayout(相對布局)
- 2.2.3 TableLayout(表格布局)
- 2.2.4 FrameLayout(幀布局)
- 2.2.5 GridLayout(網格布局)
- 2.2.6 AbsoluteLayout(絕對布局)
- 2.3 表單
- 2.3.1 TextView(文本框)詳解
- 2.3.2 EditText(輸入框)詳解
- 2.3.3 Button(按鈕)與ImageButton(圖像按鈕)
- 2.3.4 ImageView(圖像視圖)
- 2.3.5.RadioButton(單選按鈕)&Checkbox(復選框)
- 2.3.6 開關按鈕ToggleButton和開關Switch
- 2.3.7 ProgressBar(進度條)
- 2.3.8 SeekBar(拖動條)
- 2.3.9 RatingBar(星級評分條)
- 2.4 控件
- 2.4.1 ScrollView(滾動條)
- 2.4.2 Date & Time組件(上)
- 2.4.3 Date & Time組件(下)
- 2.4.4 Adapter基礎講解
- 2.4.5 ListView簡單實用
- 2.4.6 BaseAdapter優化
- 2.4.7ListView的焦點問題
- 2.4.8 ListView之checkbox錯位問題解決
- 2.4.9 ListView的數據更新問題
- 2.5 Adapter類控件
- 2.5.0 構建一個可復用的自定義BaseAdapter
- 2.5.1 ListView Item多布局的實現
- 2.5.2 GridView(網格視圖)的基本使用
- 2.5.3 Spinner(列表選項框)的基本使用
- 2.5.4 AutoCompleteTextView(自動完成文本框)的基本使用
- 2.5.5 ExpandableListView(可折疊列表)的基本使用
- 2.5.6 ViewFlipper(翻轉視圖)的基本使用
- 2.5.7 Toast(吐司)的基本使用
- 2.5.8 Notification(狀態欄通知)詳解
- 2.5.9 AlertDialog(對話框)詳解
- 2.6 對話框控件
- 2.6.0 其他幾種常用對話框基本使用
- 2.6.1 PopupWindow(懸浮框)的基本使用
- 2.6.2 菜單(Menu)
- 2.6.3 ViewPager的簡單使用
- 2.6.4 DrawerLayout(官方側滑菜單)的簡單使用
- 第三章——Android的事件處理機制
- 3.1.1 基于監聽的事件處理機制
- 3.2 基于回調的事件處理機制
- 3.3 Handler消息傳遞機制淺析
- 3.4 TouchListener PK OnTouchEvent + 多點觸碰
- 3.5 監聽EditText的內容變化
- 3.6 響應系統設置的事件(Configuration類)
- 3.7 AnsyncTask異步任務
- 3.8 Gestures(手勢)
- 第四章——Android的四大組件
- 4.1.1 Activity初學乍練
- 4.1.2 Activity初窺門徑
- 4.1.3 Activity登堂入室
- 4.2.1 Service初涉
- 4.2.2 Service進階
- 4.2.3 Service精通
- 4.3.1 BroadcastReceiver牛刀小試
- 4.3.2 BroadcastReceiver庖丁解牛
- 4.4.1 ContentProvider初探
- 4.4.2 ContentProvider再探——Document Provider
- 4.5.1 Intent的基本使用
- 4.5.2 Intent之復雜數據的傳遞
- 第五章——Fragment(碎片)
- 5.1 Fragment基本概述
- 5.2.1 Fragment實例精講——底部導航欄的實現(方法1)
- 5.2.2 Fragment實例精講——底部導航欄的實現(方法2)
- 5.2.3 Fragment實例精講——底部導航欄的實現(方法3)
- 5.2.4 Fragment實例精講——底部導航欄+ViewPager滑動切換頁面
- 5.2.5 Fragment實例精講——新聞(購物)類App列表Fragment的簡單實現
- 第六章——Android數據存儲與訪問
- 6.1 數據存儲與訪問之——文件存儲讀寫
- 6.2 數據存儲與訪問之——SharedPreferences保存用戶偏好參數
- 6.3.1 數據存儲與訪問之——初見SQLite數據庫
- 6.3.2 數據存儲與訪問之——又見SQLite數據庫
- 第七章——Android網絡編程
- 7.1.1 Android網絡編程要學的東西與Http協議學習
- 7.1.2 Android Http請求頭與響應頭的學習
- 7.1.3 Android HTTP請求方式:HttpURLConnection
- 7.1.4 Android HTTP請求方式:HttpClient
- 7.2.1 Android XML數據解析
- 7.2.2 Android JSON數據解析
- 7.3.1 Android 文件上傳
- 7.3.2 Android 文件下載(1)
- 7.3.3 Android 文件下載(2)
- 7.4 Android 調用 WebService
- 7.5.1 WebView(網頁視圖)基本用法
- 7.5.2 WebView和JavaScrip交互基礎
- 7.5.3 Android 4.4后WebView的一些注意事項
- 7.5.4 WebView文件下載
- 7.5.5 WebView緩存問題
- 7.5.6 WebView處理網頁返回的錯誤碼信息
- 7.6.1 Socket學習網絡基礎準備
- 7.6.2 基于TCP協議的Socket通信(1)
- 7.6.3 基于TCP協議的Socket通信(2)
- 7.6.4 基于UDP協議的Socket通信
- 第八章——Android繪圖與動畫基礎
- 8.1.1 Android中的13種Drawable小結 Part 1
- 8.1.2 Android中的13種Drawable小結 Part 2
- 8.1.3 Android中的13種Drawable小結 Part 3
- 8.2.1 Bitmap(位圖)全解析 Part 1
- 8.2.2 Bitmap引起的OOM問題
- 8.3.1 三個繪圖工具類詳解
- 8.3.2 繪圖類實戰示例
- 8.3.3 Paint API之—— MaskFilter(面具)
- 8.3.4 Paint API之—— Xfermode與PorterDuff詳解(一)
- 8.3.5 Paint API之—— Xfermode與PorterDuff詳解(二)
- 8.3.6 Paint API之—— Xfermode與PorterDuff詳解(三)
- 8.3.7 Paint API之—— Xfermode與PorterDuff詳解(四)
- 8.3.8 Paint API之—— Xfermode與PorterDuff詳解(五)
- 8.3.9 Paint API之—— ColorFilter(顏色過濾器)(1/3)
- 8.3.10 Paint API之—— ColorFilter(顏色過濾器)(2-3)
- 8.3.11 Paint API之—— ColorFilter(顏色過濾器)(3-3)
- 8.3.12 Paint API之—— PathEffect(路徑效果)
- 8.3.13 Paint API之—— Shader(圖像渲染)
- 8.3.14 Paint幾個枚舉/常量值以及ShadowLayer陰影效果
- 8.3.15 Paint API之——Typeface(字型)
- 8.3.16 Canvas API詳解(Part 1)
- 8.3.17 Canvas API詳解(Part 2)剪切方法合集
- 8.3.18 Canvas API詳解(Part 3)Matrix和drawBitmapMash
- 8.4.1 Android動畫合集之幀動畫
- 8.4.2 Android動畫合集之補間動畫
- 8.4.3 Android動畫合集之屬性動畫-初見
- 8.4.4 Android動畫合集之屬性動畫-又見
- 第九章——Android中的多媒體開發
- 9.1 使用SoundPool播放音效(Duang~)
- 9.2 MediaPlayer播放音頻與視頻
- 9.3 使用Camera拍照
- 9.4 使用MediaRecord錄音
- 第十章——系統服務
- 10.1 TelephonyManager(電話管理器)
- 10.2 SmsManager(短信管理器)
- 10.3 AudioManager(音頻管理器)
- 10.4 Vibrator(振動器)
- 10.5 AlarmManager(鬧鐘服務)
- 10.6 PowerManager(電源服務)
- 10.7 WindowManager(窗口管理服務)
- 10.8 LayoutInflater(布局服務)
- 10.9 WallpaperManager(壁紙管理器)
- 10.10 傳感器專題(1)——相關介紹
- 10.11 傳感器專題(2)——方向傳感器
- 10.12 傳感器專題(3)——加速度/陀螺儀傳感器
- 10.12 傳感器專題(4)——其他傳感器了解
- 10.14 Android GPS初涉
- 第十一章——由來、答疑和資源
- 11.0《2015最新Android基礎入門教程》完結散花~