詳解Android Bitmap的使用
一 圖片表示原理
圖片是由每個(gè)像素點(diǎn)來組成 像素點(diǎn)就是小方塊
圖片的大小等于 寬*高*每個(gè)像素點(diǎn)的大小
二 加載圖片OOM異常

解決辦法
其中big.jpg是一張21.2MB的高清圖
public class MainActivity extends AppCompatActivity implements View.OnClickListener {
ImageView mImageView;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
findViewById(R.id.load).setOnClickListener(this);
mImageView = findViewById(R.id.image);
}
@Override
public void onClick(View view) {
switch (view.getId()) {
case R.id.load:
load();
break;
}
}
private void load() {
try {
BitmapFactory.Options option = new BitmapFactory.Options();
option.inJustDecodeBounds = true; //只會(huì)解析圖片的大小 不會(huì)加載圖片的內(nèi)容
BitmapFactory.decodeStream(getAssets().open("big.jpg"), null, option);
// 獲取圖片的寬高
int width = option.outWidth;
int height = option.outHeight;
// 獲取屏幕的寬高
int screenWidth = getScreenWidth();
int screenHeight = getScreenHeight();
// 把圖片的寬高和屏幕的寬高進(jìn)行對(duì)比
int scaleX = width / screenWidth;
int scaleY = height / screenHeight;
int scale = scaleX > scaleY ? scaleX : scaleY;
option.inJustDecodeBounds = false; //加載圖片的內(nèi)容
// 如果設(shè)置為>1 請(qǐng)求解碼器對(duì)原始數(shù)據(jù)進(jìn)行子采樣 例如inSampleSize==4返回圖像的寬度/高度是原始圖像的1/4
// 任何值<=1都與1相同
option.inSampleSize = scale;
Bitmap bitmap = BitmapFactory.decodeStream(getAssets().open("big.jpg"), null, option);
int byteCount = bitmap.getByteCount();
Log.i("HUANG", "byteCount=" + byteCount);
mImageView.setImageBitmap(bitmap);
} catch (IOException e) {
e.printStackTrace();
}
}
/** 得到設(shè)備屏幕的寬度 (像素) **/
private int getScreenWidth() {
return getResources().getDisplayMetrics().widthPixels;
}
/** 得到設(shè)備屏幕的高度 (像素) **/
private int getScreenHeight() {
return getResources().getDisplayMetrics().heightPixels;
}
}
三 圖片處理原理
Android里面所有的顯示效果都是繪制出來的
用Android封裝好的繪圖類去繪制圖片
Canvas: 畫布
Paint: 畫筆
Matrix: 圖形矩陣 3*3
Bitmap: 要繪制的圖片
四 圖片的旋轉(zhuǎn) 平移 縮放
其中mm.jpg是一張57KB的圖 屬于正常范圍 不需要額外處理
public class MainActivity extends AppCompatActivity implements View.OnClickListener {
ImageView mImageView, mCopyView;
Bitmap mBitmap;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
findViewById(R.id.change).setOnClickListener(this);
mImageView = findViewById(R.id.image);
mCopyView = findViewById(R.id.copy);
try {
mBitmap = BitmapFactory.decodeStream(getAssets().open("mm.jpg"));
mImageView.setImageBitmap(mBitmap);
} catch (IOException e) {
e.printStackTrace();
}
}
@Override
public void onClick(View view) {
switch (view.getId()) {
case R.id.change:
change();
break;
}
}
// 圖片的旋轉(zhuǎn) 平移 縮放
// 注意: 旋轉(zhuǎn) 平移 縮放 這三種效果在本案例中只能同時(shí)存在一種 分別打開注釋看效果
private void change() {
if (null == mBitmap) return;
// 新建空白的圖片 要和原圖的大小一樣
Bitmap bitmap = Bitmap.createBitmap(mBitmap.getWidth(), mBitmap.getHeight(), mBitmap.getConfig());
Canvas canvas = new Canvas(bitmap); //畫布 傳參必須是一個(gè)空白的圖片 否則報(bào)錯(cuò)
Paint paint = new Paint(); //畫筆
Matrix matrix = new Matrix(); //矩陣
// 旋轉(zhuǎn)30度 以圖片的中心為圓心
matrix.setRotate(30, mBitmap.getWidth() / 2, mBitmap.getHeight() / 2);
// X軸平移80
//matrix.setTranslate(80, 0);
// Y軸縮為原來的0.5
//matrix.setScale(1F, 0.5F, mBitmap.getWidth() / 2, mBitmap.getHeight() / 2);
canvas.drawColor(Color.WHITE); //繪制背景為白色
canvas.drawBitmap(mBitmap, matrix, paint); //繪制圖片
mCopyView.setImageBitmap(bitmap);
}
}
五 圖片的涂鴉操作
其中mm.jpg是一張57KB的圖 屬于正常范圍 不需要額外處理
public class MainActivity extends AppCompatActivity implements View.OnTouchListener {
ImageView mImageView;
Bitmap mNewBitmap;
Canvas mCanvas;
Paint mPaint;
Matrix mMatrix;
int mStartX, mStartY; //按下點(diǎn)的坐標(biāo)
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mImageView = findViewById(R.id.image);
try {
Bitmap bitmap = BitmapFactory.decodeStream(getAssets().open("mm.jpg"));
// 不能直接在原圖上進(jìn)行繪制 必須新建空白的圖片
mNewBitmap = Bitmap.createBitmap(bitmap.getWidth(), bitmap.getHeight(), bitmap.getConfig());
mCanvas = new Canvas(mNewBitmap);
mPaint = new Paint();
mPaint.setColor(Color.YELLOW);
mMatrix = new Matrix();
// 把原圖繪制在空白的圖片上
mCanvas.drawBitmap(bitmap, mMatrix, mPaint);
mImageView.setImageBitmap(mNewBitmap);
mImageView.setOnTouchListener(this); //設(shè)置觸摸監(jiān)聽
} catch (IOException e) {
e.printStackTrace();
}
}
@Override
public boolean onTouch(View v, MotionEvent event) {
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN: //按下
mStartX = (int) event.getX();
mStartY = (int) event.getY();
break;
case MotionEvent.ACTION_MOVE: //移動(dòng)
// 獲取移動(dòng)點(diǎn)的坐標(biāo)
int moveX = (int) event.getX();
int moveY = (int) event.getY();
// 畫線
mCanvas.drawLine(mStartX, mStartY, moveX, moveY, mPaint);
// 把新圖設(shè)置給ImageView
mImageView.setImageBitmap(mNewBitmap);
// 把移動(dòng)點(diǎn)置為開始點(diǎn)
mStartX = moveX;
mStartY = moveY;
break;
case MotionEvent.ACTION_UP: //彈起
break;
}
return true; //事件自己來處理
}
}
六 圖片的顏色處理
圖片是有顏色
核心原理就是重繪圖片
改變圖片的顏色就是對(duì)畫筆進(jìn)行操
其中mm.jpg是一張57KB的圖 屬于正常范圍 不需要額外處理
public class MainActivity extends AppCompatActivity implements View.OnClickListener {
ImageView mImageView;
Bitmap mBitmap, mNewBitmap;
Canvas mCanvas;
Paint mPaint;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mImageView = findViewById(R.id.image);
try {
mBitmap = BitmapFactory.decodeStream(getAssets().open("mm.jpg"));
mImageView.setImageBitmap(mBitmap);
mNewBitmap = Bitmap.createBitmap(mBitmap.getWidth(), mBitmap.getHeight(), mBitmap.getConfig());
mCanvas = new Canvas(mNewBitmap);
mPaint = new Paint();
findViewById(R.id.change).setOnClickListener(this);
} catch (IOException e) {
e.printStackTrace();
}
}
@Override
public void onClick(View view) {
switch (view.getId()) {
case R.id.change:
int randomR = (int) (Math.random() * 256); //0-255 隨機(jī)數(shù)
int randomG = (int) (Math.random() * 256); //0-255 隨機(jī)數(shù)
int randomB = (int) (Math.random() * 256); //0-255 隨機(jī)數(shù)
int randomA = (int) (Math.random() * 256); //0-255 隨機(jī)數(shù)
float colorR = (255 - randomR) / (float) 255;
float colorG = (255 - randomG) / (float) 255;
float colorB = (255 - randomB) / (float) 255;
float colorA = (255 - randomA) / (float) 255;
Log.i("HUANG", "randomR=" + randomR);
Log.i("HUANG", "randomG=" + randomG);
Log.i("HUANG", "randomB=" + randomB);
Log.i("HUANG", "randomA=" + randomA);
Log.i("HUANG", "colorR=" + colorR);
Log.i("HUANG", "colorG=" + colorG);
Log.i("HUANG", "colorB=" + colorB);
Log.i("HUANG", "colorA=" + colorA);
ColorMatrix matrix = new ColorMatrix(); //顏色矩陣 5*4
matrix.set(new float[]{
colorR, 0, 0, 0, 0, //red
0, colorG, 0, 0, 0, //green
0, 0, colorB, 0, 0, //blue
0, 0, 0, colorA, 0 //alpha
});
ColorMatrixColorFilter filter = new ColorMatrixColorFilter(matrix);
mPaint.setColorFilter(filter);
mCanvas.drawBitmap(mBitmap, new Matrix(), mPaint);
mImageView.setImageBitmap(mNewBitmap);
break;
}
}
}
七 內(nèi)存泄漏和內(nèi)存溢出
內(nèi)存泄漏(MemoryLeak)
有些對(duì)象只有有限的生命周期 當(dāng)它們的任務(wù)完成之后 它們將被回收 如果在對(duì)象的生命周期本該結(jié)束的時(shí)候 這個(gè)對(duì)象還被一系列的引用 這就會(huì)導(dǎo)致內(nèi)存泄漏
隨著泄漏的累積 App將消耗完內(nèi)存 內(nèi)存泄漏最終會(huì)導(dǎo)致內(nèi)存溢出
內(nèi)存泄漏的原因
1. 資源對(duì)象沒關(guān)閉(Cursor File...)
2. 沒有及時(shí)調(diào)用recycle()釋放不再使用的Bitmap
3. 廣播注冊(cè)沒取消
4. ...
神器: LeakCanary 內(nèi)存泄露檢測(cè)工具(https://github.com/square/leakcanary)
內(nèi)存溢出(OutOfMemoryError OOM)
內(nèi)存溢出是指當(dāng)對(duì)象的內(nèi)存占用已經(jīng)超出分配內(nèi)存的空間大小
內(nèi)存溢出的原因
1. Bitmap過大
2. 內(nèi)存泄露導(dǎo)致
3. ...
八 ImageView中scaleType屬性值含義

以上就是詳解Android Bitmap的使用的詳細(xì)內(nèi)容,更多關(guān)于Android Bitmap的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!
- android獲取圖片尺寸的兩種方式及bitmap的縮放操作
- Android 實(shí)現(xiàn)把bitmap圖片的某一部分的顏色改成其他顏色
- Android 實(shí)現(xiàn)將Bitmap 保存到本地
- Android中的Bitmap序列化失敗的解決方法
- Android BitmapUtils工具類使用詳解
- Android Bitmap的加載與緩存
- 詳解Android Bitmap的常用壓縮方式
- Android中的Bitmap的詳細(xì)介紹
- Android圖片處理工具類BitmapUtils
- Android開發(fā)中Bitmap高效加載使用詳解
- Android中Glide獲取圖片Path、Bitmap用法詳解
- Android Bitmap像素級(jí)操作詳解
相關(guān)文章
Android開發(fā)之完成登陸界面的數(shù)據(jù)保存回顯操作實(shí)例
這篇文章主要介紹了Android開發(fā)之完成登陸界面的數(shù)據(jù)保存回顯操作實(shí)現(xiàn)方法,結(jié)合完整實(shí)例形式較為詳細(xì)的分析了Android針對(duì)登錄數(shù)據(jù)的保存及回顯操作技巧,需要的朋友可以參考下2015-12-12
Android重寫View實(shí)現(xiàn)全新的控件
這篇文章主要介紹了Android重寫View來實(shí)現(xiàn)全新的控件,最難的一種自定義控件形式,感興趣的小伙伴們可以參考一下2016-05-05
c++ mk文件出錯(cuò)Jni調(diào)用產(chǎn)生java.lang.UnsatisfiedLinkError錯(cuò)誤解決方法
錯(cuò)誤產(chǎn)生在我把方法從c語(yǔ)言轉(zhuǎn)為c++語(yǔ)言后產(chǎn)生的,后來檢查到這種錯(cuò)誤是因?yàn)閙k文件出錯(cuò),加載c文件和加載c++的文件所用的代碼不一樣,下面請(qǐng)看2013-11-11
Android中隱藏狀態(tài)欄和標(biāo)題欄的方法匯總(隱藏狀態(tài)欄、標(biāo)題欄的五種方法)
這篇文章主要介紹了Android中隱藏狀態(tài)欄和標(biāo)題欄的方法匯總(隱藏狀態(tài)欄、標(biāo)題欄的五種方法),非常不錯(cuò),具有參考借鑒價(jià)值,需要的朋友可以參考下2017-02-02
基于TransactionTooLargeException異常分析
下面小編就為大家分享一篇基于TransactionTooLargeException異常分析,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過來看看吧2017-11-11
Android中系統(tǒng)默認(rèn)輸入法設(shè)置的方法(輸入法的顯示和隱藏)
這篇文章主要介紹了Android中系統(tǒng)默認(rèn)輸入法設(shè)置的方法(輸入法的顯示和隱藏)的相關(guān)資料,需要的朋友可以參考下2016-01-01

