文檔處理控制欄:
* [x] 選題收集:
* [ ] 初稿整理:
* [ ] 補充校對:
* [ ] 入庫存檔:
---
版權信息
原文鏈接:[Android Bitmap最全面詳解](http://www.jianshu.com/p/ade293a49cd7)
---
## 1.Bitmap類
> Bitmap圖像處理的最重要類之一。用它可以獲取圖像文件信息,進行圖像顏色變換、剪切、旋轉、縮放等操作,并可以指定格式保存圖像文件
#### 1.1Bitmap常用的方法


#### 1.2Bitmap的顏色配置信息與壓縮方式信息
Bitmap中有兩個內部枚舉類:Config和CompressFormat,
Config是用來設置顏色配置信息的,
CompressFormat是用來設置壓縮方式的。

**Config解析:**
* Bitmap.Config.ALPHA_8:顏色信息只由透明度組成,占8位。
* Bitmap.Config.ARGB_4444:顏色信息由透明度與R(Red),G(Green),B(Blue)四部分組成,每個部分都占4位,總共占16位。
* Bitmap.Config.ARGB_8888:顏色信息由透明度與R(Red),G(Green),B(Blue)四部分組成,每個部分都占8位,總共占32位。是Bitmap默認的顏色配置信息,也是最占空間的一種配置。
* Bitmap.Config.RGB_565:顏色信息由R(Red),G(Green),B(Blue)三部分組成,R占5位,G占6位,B占5位,總共占16位。
> 通常我們優化Bitmap時,當需要做性能優化或者防止OOM(Out Of Memory),我們通常會使用Bitmap.Config.RGB_565這個配置,因為Bitmap.Config.ALPHA_8只有透明度,顯示一般圖片沒有意義,Bitmap.Config.ARGB_4444顯示圖片不清楚,Bitmap.Config.ARGB_8888占用內存最多。
**CompressFormat解析:**
* Bitmap.CompressFormat.JPEG:表示以JPEG壓縮算法進行圖像壓縮,壓縮后的格式可以是".jpg"或者".jpeg",是一種有損壓縮。
* Bitmap.CompressFormat.PNG:表示以PNG壓縮算法進行圖像壓縮,壓縮后的格式可以是".png",是一種無損壓縮。
* Bitmap.CompressFormat.WEBP:表示以WebP壓縮算法進行圖像壓縮,壓縮后的格式可以是".webp",是一種有損壓縮,質量相同的情況下,WebP格式圖像的體積要比JPEG格式圖像小40%。美中不足的是,WebP格式圖像的編碼時間“比JPEG格式圖像長8倍”。
#### 1.3Bitmap對圖像進行操作
###### 1)Bitmap裁剪圖像
`itmap.createBitmap(Bitmap source, int x, int y, int width, int height)`
根據源Bitmap對象source,創建出source對象裁剪后的圖像的Bitmap。x,y分別代表裁剪時,x軸和y軸的第一個像素,width,height分別表示裁剪后的圖像的寬度和高度。
注意:x+width要小于等于source的寬度,y+height要小于等于source的高度。
`Bitmap.createBitmap(Bitmap source, int x, int y, int width, int height,Matrix m, boolean filter)`
這個方法只比上面的方法多了m和filter這兩個參數,m是一個Matrix(矩陣)對象,可以進行縮放,旋轉,移動等動作,filter為true時表示source會被過濾,僅僅當m操作不僅包含移動操作,還包含別的操作時才適用。其實上面的方法本質上就是調用這個方法而已。
~~~
public static Bitmap createBitmap(Bitmap source, int x, int y, int width, int height) {
return createBitmap(source, x, y, width, height, null, false);
}
~~~
###### 2 )Bitmap縮放,旋轉,移動圖像
Bitmap縮放,旋轉,移動,傾斜圖像其實就是通過`Bitmap.createBitmap(Bitmap source, int x, int y, int width, int height,Matrix m, boolean filter)`方法實現的,只是在實現這些功能的同時還可以實現圖像的裁剪。
~~~
// 定義矩陣對象
Matrix matrix = new Matrix();
// 縮放圖像
matrix.postScale(0.8f, 0.9f);
// 向左旋轉(逆時針旋轉)45度,參數為正則向右旋轉(順時針旋轉)
matrix.postRotate(-45);
//移動圖像
//matrix.postTranslate(100,80);
Bitmap bitmap = Bitmap.createBitmap(source, 0, 0, source.getWidth(), source.getHeight(),
matrix, true);
~~~
Matrix的postScale和postRotate方法還有多帶兩個參數的重載方法postScale(float sx, float sy, float px, float py)和postRotate(float degrees, float px, float py),后兩個參數px和py都表示以該點為中心進行操作。
**注意:雖然Matrix還可以調用postSkew方法進行傾斜操作,但是卻不可以在此時創建Bitmap時使用。**
###### 3) Bitmap保存圖像與釋放資源
~~~
bitmap=BitmapFactory.decodeResource(getResources(),R.drawable.feng);
File file=new File(getFilesDir(),"lavor.jpg");
if(file.exists()){
file.delete();
}
try {
FileOutputStream outputStream=new FileOutputStream(file);
bitmap.compress(Bitmap.CompressFormat.JPEG,90,outputStream);
outputStream.flush();
outputStream.close();
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
bitmap.recycle();//釋放bitmap的資源,這是一個不可逆轉的操作
~~~
###### 3)Matrix拓展類
| 方法 | 介紹 |
| --- | --- |
| setRotate(float degrees, float px, float py) | 對圖片進行旋轉 |
| setScale(float sx, float sy) | 對圖片進行縮放 |
| setTranslate(float dx, float dy) | 對圖片進行平移 |
| postTranslate(centerX, centerY) | 在上一次修改的基礎上進行再次修改 set 每次操作都是最新的 會覆蓋上次的操作 |
~~~
//顯示原圖
ImageView iv_src = (ImageView) findViewById(R.id.iv_src);
//顯示副本
ImageView iv_copy = (ImageView) findViewById(R.id.iv_copy);
//[1]先把tomcat.png 圖片轉換成bitmap 顯示到iv_src
Bitmap srcBitmap = BitmapFactory.decodeResource(getResources(), R.drawable.tomcat);
//[1.1]操作圖片
// srcBitmap.setPixel(20, 30, Color.RED);
iv_src.setImageBitmap(srcBitmap);
//[2]創建原圖的副本
//[2.1]創建一個模板 相當于 創建了一個大小和原圖一樣的 空白的白紙
Bitmap copybiBitmap = Bitmap.createBitmap(srcBitmap.getWidth(), srcBitmap.getHeight(), srcBitmap.getConfig());
//[2.2]想作畫需要一個畫筆
Paint paint = new Paint();
//[2.3]創建一個畫布 把白紙鋪到畫布上
Canvas canvas = new Canvas(copybiBitmap);
//[2.4]開始作畫
Matrix matrix = new Matrix();
//[2.5]對圖片進行旋轉
//matrix.setRotate(20, srcBitmap.getWidth()/2, srcBitmap.getHeight()/2);
//[2.5]對圖片進行
// matrix.setScale(0.5f, 0.5f);
//[2.6]對圖片進行平移
// matrix.setTranslate(30, 0);
//[2.7]鏡面效果 如果2個方法一起用
// matrix.setScale(-1.0f, 1);
//post是在上一次修改的基礎上進行再次修改 set 每次操作都是最新的 會覆蓋上次的操作
// matrix.postTranslate(srcBitmap.getWidth(), 0);
//[2,7]倒影效果
matrix.setScale(1.0f, -1);
//post是在上一次修改的基礎上進行再次修改 set 每次操作都是最新的 會覆蓋上次的操作
matrix.postTranslate(0, srcBitmap.getHeight());
canvas.drawBitmap(srcBitmap,matrix , paint);
//[3]把copybimap顯示到iv_copy上
iv_copy.setImageBitmap(copybiBitmap);
~~~
## 2.BitmapFactory類
> 創建位圖對象從不同的來源,包括文件、流, 和字節數組。
###### 2.1BitmapFactory常用方法
| 方法 | 說明 |
| --- | --- |
| decodeFile(String pathName, Options opts) | 從文件讀取圖片 |
| decodeFile(String pathName) | 從文件讀取圖片 |
| decodeFileDescriptor(FileDescriptor fd) | 從文件讀取文件 與decodeFile不同的是這個直接調用JNI函數進行讀取 效率比較高 |
| decodeFileDescriptor(FileDescriptor fd, Rect outPadding, Options opts) | 同上 |
| decodeStream(InputStream is) | 從輸入流讀取圖片 |
| decodeStream(InputStream is, Rect outPadding, Options opts) | 從輸入流讀取圖片 |
| decodeStream(InputStream is, Rect outPadding, Options opts) | 從資源文件讀取圖片 |
| decodeResource(Resources res, int id) | 從資源文件讀取圖片 |
| decodeResource(Resources res, int id, Options opts) | 從資源文件讀取圖片 |
| decodeByteArray(byte[] data, int offset, int length) | 從數組讀取圖片 |
| decodeByteArray(byte[] data, int offset, int length, Options opts) | 從數組讀取圖片 |
> BitmapFactory.decodeResource 加載的圖片可能會經過縮放,該縮放目前是放在 java 層做的,效率比較低,而且需要消耗 java 層的內存。因此,如果大量使用該接口加載圖片,容易導致OOM錯誤
> BitmapFactory.decodeStream 不會對所加載的圖片進行縮放,相比之下占用內存少,效率更高。
> 這兩個接口各有用處,如果對性能要求較高,則應該使用 decodeStream;如果對性能要求不高,且需要 Android 自帶的圖片自適應縮放功能,則可以使用 decodeResource。
#### 2.2BitmapFactory三種加載圖片
* 1)從資源文件讀取圖片
~~~
Bitmap bitmap= BitmapFactory.decodeResource(getResources(),R.drawable.after19);
iv.setImageBitmap(bitmap);
~~~
* 2)從輸入流中讀取圖片
~~~
FileInputStream fis=new FileInputStream(new File(getFilesDir()+"/psb.jpg"));
Bitmap bitmap= BitmapFactory.decodeStream(fis);
iv.setImageBitmap(bitmap);
~~~
* 3)從數組中讀取圖片
~~~
public static Bitmap readBitmapFromByteArray(byte[] data, int width, int height) {
BitmapFactory.Options options = new BitmapFactory.Options();
options.inJustDecodeBounds = true;
BitmapFactory.decodeByteArray(data, 0, data.length, options);
float srcWidth = options.outWidth;
float srcHeight = options.outHeight;
int inSampleSize = 1;
if (srcHeight > height || srcWidth > width) {
if (srcWidth > srcHeight) {
inSampleSize = Math.round(srcHeight / height);
} else {
inSampleSize = Math.round(srcWidth / width);
}
}
options.inJustDecodeBounds = false;
options.inSampleSize = inSampleSize;
return BitmapFactory.decodeByteArray(data, 0, data.length, options);
}
~~~
#### 2.3BitmapFactory常用操作
* 1)保存本地圖片
~~~
public static void writeBitmapToFile(String filePath, Bitmap b, int quality) {
try {
File desFile = new File(filePath);
FileOutputStream fos = new FileOutputStream(desFile);
BufferedOutputStream bos = new BufferedOutputStream(fos);
b.compress(Bitmap.CompressFormat.JPEG, quality, bos);
bos.flush();
bos.close();
} catch (IOException e) {
e.printStackTrace();
}
}
~~~
* 2)圖片縮放
~~~
public static Bitmap bitmapScale(Bitmap bitmap, float scale) {
Matrix matrix = new Matrix();
matrix.postScale(scale, scale); // 長和寬放大縮小的比例
Bitmap resizeBmp = Bitmap.createBitmap(bitmap, 0, 0, bitmap.getWidth(), bitmap.getHeight(), matrix, true);
return resizeBmp;
}
~~~
* 3)對 bitmap 進行裁剪
~~~
public Bitmap bitmapClip(Context context , int id , int x , int y){
Bitmap map = BitmapFactory.decodeResource(context.getResources(), id);
map = Bitmap.createBitmap(map, x, y, 120, 120);
return map;
}
~~~
## 3.BitmapFactory.option常用方法
| Option參數類方法 | 說明 |
| --- | --- |
| public boolean inJustDecodeBounds | 如果設置為true,不獲取圖片,不分配內存,但會返回圖片的高度寬度信息 |
| public int inSampleSize | 圖片縮放的倍數 |
| public int outWidth | 獲取圖片的寬度值 |
| public int outHeight | 獲取圖片的高度值 |
| public int inDensity | 用于位圖的像素壓縮比 |
| public int inTargetDensity | 用于目標位圖的像素壓縮比(要生成的位圖) |
| public byte[] inTempStorage | 創建臨時文件,將圖片存儲 |
| public boolean inScaled | 設置為true時進行圖片壓縮,從inDensity到inTargetDensity |
| public boolean inDither | 如果為true,解碼器嘗試抖動解碼 |
| public Bitmap.Config inPreferredConfig | 設置解碼器這個值是設置色彩模式,默認值是ARGB_8888,在這個模式下,一個像素點占用4bytes空間,一般對透明度不做要求的話,一般采用RGB_565模式,這個模式下一個像素點占用2bytes |
| public String outMimeType | 設置解碼圖像 |
| public boolean inPurgeable | 當存儲Pixel的內存空間在系統內存不足時是否可以被回收 |
| public boolean inInputShareable | inPurgeable為true情況下才生效,是否可以共享一個InputStream |
| public boolean inPreferQualityOverSpeed | 為true則優先保證Bitmap質量其次是解碼速度 |
| public boolean inMutable | 配置Bitmap是否可以更改,比如:在Bitmap上隔幾個像素加一條線段 |
| public int inScreenDensity | 當前屏幕的像素密度 |
- 0-發現
- AndroidInterview-Q-A
- Android能讓你少走彎路的干貨整理
- LearningNotes
- temp
- temp11
- 部分地址
- 0-待辦任務
- 待補充列表
- 0-未分類
- AndroidView事件分發與滑動沖突處理
- Spannable
- 事件分發機制詳解
- 1-Java
- 1-Java-01基礎
- 未歸檔
- 你應該知道的JDK知識
- 集合框架
- 1-Java-04合集
- Java之旅0
- Java之旅
- JAVA之旅01
- JAVA之旅02
- JAVA之旅03
- JAVA之旅04
- JAVA之旅05
- JAVA之旅06
- JAVA之旅07
- JAVA之旅08
- JAVA之旅09
- java之旅1
- JAVA之旅10
- JAVA之旅11
- JAVA之旅12
- JAVA之旅13
- JAVA之旅14
- JAVA之旅15
- JAVA之旅16
- JAVA之旅17
- JAVA之旅18
- JAVA之旅19
- java之旅2
- JAVA之旅20
- JAVA之旅21
- JAVA之旅22
- JAVA之旅23
- JAVA之旅24
- JAVA之旅25
- JAVA之旅26
- JAVA之旅27
- JAVA之旅28
- JAVA之旅29
- java之旅3
- JAVA之旅30
- JAVA之旅31
- JAVA之旅32
- JAVA之旅33
- JAVA之旅34
- JAVA之旅35
- 1-Java-05辨析
- HashMapArrayMap
- Java8新特性
- Java8接口默認方法
- 圖解HashMap(1)
- 圖解HashMap(2)
- 2-Android
- 2-Android-1-基礎
- View繪制流程
- 事件分發
- AndroidView的事件分發機制和滑動沖突解決
- 自定義View基礎
- 1-安卓自定義View基礎-坐標系
- 2-安卓自定義View基礎-角度弧度
- 3-安卓自定義View基礎-顏色
- 自定義View進階
- 1-安卓自定義View進階-分類和流程
- 10-安卓自定義View進階-Matrix詳解
- 11-安卓自定義View進階-MatrixCamera
- 12-安卓自定義View進階-事件分發機制原理
- 13-安卓自定義View進階-事件分發機制詳解
- 14-安卓自定義View進階-MotionEvent詳解
- 15-安卓自定義View進階-特殊形狀控件事件處理方案
- 16-安卓自定義View進階-多點觸控詳解
- 17-安卓自定義View進階-手勢檢測GestureDetector
- 2-安卓自定義View進階-繪制基本圖形
- 3-安卓自定義View進階-畫布操作
- 4-安卓自定義View進階-圖片文字
- 5-安卓自定義View進階-Path基本操作
- 6-安卓自定義View進階-貝塞爾曲線
- 7-安卓自定義View進階-Path完結篇偽
- 8-安卓自定義View進階-Path玩出花樣PathMeasure
- 9-安卓自定義View進階-Matrix原理
- 通用類介紹
- Application
- 2-Android-2-使用
- 2-Android-02控件
- ViewGroup
- ConstraintLayout
- CoordinatorLayout
- 2-Android-03三方使用
- Dagger2
- Dagger2圖文完全教程
- Dagger2最清晰的使用教程
- Dagger2讓你愛不釋手-終結篇
- Dagger2讓你愛不釋手-重點概念講解、融合篇
- dagger2讓你愛不釋手:基礎依賴注入框架篇
- 閱讀筆記
- Glide
- Google推薦的圖片加載庫Glide:最新版使用指南(含新特性)
- rxjava
- 這可能是最好的RxJava2.x入門教程完結版
- 這可能是最好的RxJava2.x入門教程(一)
- 這可能是最好的RxJava2.x入門教程(三)
- 這可能是最好的RxJava2.x入門教程(二)
- 這可能是最好的RxJava2.x入門教程(五)
- 這可能是最好的RxJava2.x入門教程(四)
- 2-Android-3-優化
- 優化概況
- 各種優化
- Android端秒開優化
- apk大小優化
- 內存分析
- 混淆
- 2-Android-4-工具
- adb命令
- 一鍵分析Android的BugReport
- 版本控制
- git
- git章節簡述
- 2-Android-5-源碼
- HandlerThread 源碼分析
- IntentService的使用和源碼分析
- 2-Android-9-辨析
- LRU算法
- 什么是Bitmap
- 常見圖片壓縮方式
- 3-Kotlin
- Kotlin使用筆記1-草稿
- Kotlin使用筆記2
- kotlin特性草稿
- Kotlin草稿-Delegation
- Kotlin草稿-Field
- Kotlin草稿-object
- 4-JavaScript
- 5-Python
- 6-Other
- Git
- Gradle
- Android中ProGuard配置和總結
- gradle使用筆記
- Nexus私服搭建
- 編譯提速最佳實踐
- 7-設計模式與架構
- 組件化
- 組件化探索(OKR)
- 1-參考列表
- 2-1-組件化概述
- 2-2-gradle配置
- 2-3-代碼編寫
- 2-4-常見問題
- 2-9-值得一讀
- 8-數據結構與算法
- 0臨時文件
- 漢諾塔
- 8-數據-1數據結構
- HashMap
- HashMap、Hashtable、HashSet 和 ConcurrentHashMap 的比較
- 遲到一年HashMap解讀
- 8-數據-2算法
- 1個就夠了
- Java常用排序算法(必須掌握的8大排序算法)
- 常用排序算法總結(性能+代碼)
- 必須知道的八大種排序算法(java實現)
- 9-職業
- 閱讀
- 書單
- 面試
- 面試-01-java
- Java面試題全集駱昊(上)
- Java面試題全集駱昊(下)
- Java面試題全集駱昊(中)
- 面試-02-android
- 40道Android面試題
- 面試-03-開源源碼
- Android圖片加載框架最全解析(二),從源碼的角度理解Glide的執行流程
- 面試-07-設計模式
- 面試-08-算法
- 面試-09-其他
- SUMMARY
- 版權說明
- temp111