網絡圖片框架
- 大圖片的處理原理
- ImageView(原生)
- SmartImageView(廢棄)
- Glide(Google)
- Picasso(Square)
- Fresco(FaceBooK)
- Universal ImageLoader(UIL)
01-圖片的處理原理
- 安卓中圖片支持的像素點: (jpg,png,webp)
Config.ARGB_4444 =16bit = 2byte
Config.ARGB_8888 =32bit = 4byte(默認)
Config.RGB_565 = 16bit = 2byte - 大圖片的加載 設置圖片的壓縮比例讀取
- 位圖類的作用:對於大圖片他都會等比例的縮放到ImageView中 與在選項中屬性中的比例設置無關,
- 總結:只要圖片的大小大於手機的分辨率,那麼ImageView加載位圖後都會等比例的縮放後適配在手機屏幕中 1.如果直接讀取會報ooM異常,如果在位圖設置選項比例後讀取的方法後讀取就不回會報異常,異常位圖中設置的 比例與顯示在屏幕中的比例無關,因爲位圖會自動適配加載到ImageView中,
//代碼步驟
1. 獲取圖片的元數據中的寬width和高height
2. 然後再獲取ImageView控件的寬和高 iv_width 和 iv_height
3. 分別計算寬和高應該縮放的倍率,然後取最大值Math.max(widht/iv_width,height/iv_height) = smpleSize(縮放比例);
4. 將jpg轉換爲Bitmap的時候,將sampleSize作爲參數傳入進去,讓API去縮放.得到一個縮放後的bitmap
5. 將縮放後的bitmap顯示到ImageView
<ImageView
android:layout_width="match_parent"
android:layout_height="match_parent" //下面需要獲得該控件的長度.
android:id="@+id/iv"
/>
public class MainActivity extends Activity {
private ImageView iv;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
iv = (ImageView) findViewById(R.id.iv);
//下面可以在onCreate的中可以獲得控件的長度
//iv.getViewTreeObserver().addOnGlobalLayoutListener(new OnGlobalLayoutListen() {
//@Override
//public void onGlobalLayout() {
// int iv_height = iv.getHeight();
// int iv_width = iv.getWidth();
// }
//});
//注意此處的因爲在OnCreate()的繪製View,在這裏不能夠獲得控件的長度.
int iv_height = iv.getHeight();
int iv_width = iv.getWidth();
Log.d("tag", "iv_height="+iv_height+"/iv_width="+iv_width);
}
public void load(View view){
//最普通的方式(不對圖片進行等比例縮放時)加載圖片的兩行核心代碼
//Bitmap bitmap = BitmapFactory.decodeFile("/mnt/sdcard/dog.jpg");
//iv.setImageBitmap(bitmap);
File file = new File(Environment.getExternalStorageDirectory(),"me.jpg");
//先將jpg或者png轉換爲Bitmap,然後將Bitmap設置給ImageView即可
Options opts = new Options();
//告訴bitmapFactory僅僅去獲取圖片的元數據(寬高),而不是去加載整個圖片
opts.inJustDecodeBounds = true;
//1. 獲取圖片的元數據中的寬width和高height
//如果傳入了opts.inJustDecodeBounds = true的opts,那麼該方法的返回值就爲null
//該方法將獲取到的結果又保存到了opts對象上,此時的返回值是null
BitmapFactory.decodeFile(file.getAbsolutePath(), opts);
int width = opts.outWidth;
int height = opts.outHeight;
//2. 然後再獲取ImageView控件的寬和高 iv_width 和 iv_height
/*
* 注意:imageView的寬和高寫的是match_parent才能獲取到,如果是wrap則拿到的是0
* 注意: 獲取控件的尺寸信息,一定要等界面完全繪製完了再去拿,不要再onCreate中獲取控件的寬和高
*/
int iv_height = iv.getHeight();
int iv_width = iv.getWidth();
Log.d("tag", "width="+width+"/height="+height+"\niv_width="+iv_width+"/iv_height="+iv_height);
//3. 分別計算寬和高應該縮放的倍率,然後取最大值Math.max(widht/iv_width,height/iv_height) = smpleSize(縮放比例);
//sampleSize=0-1之間的話 算作1
int sampleSize = Math.max(width/iv_width, height/iv_height);
Log.d("tag", "sampleSize="+sampleSize);
//4. 將jpg轉換爲Bitmap的時候,將sampleSize作爲參數傳入進去,讓API去縮放.得到一個縮放後的bitmap
opts.inJustDecodeBounds = false;//改爲false就代表需要真正的加載圖片
opts.inSampleSize = sampleSize;//設置等比例縮放的倍率
Bitmap bitmap = BitmapFactory.decodeFile(file.getAbsolutePath(), opts);
//5. 將縮放後的bitmap顯示到ImageView
iv.setImageBitmap(bitmap);
}
}
3. 圖片的特效處理
- 01-縮放
public void scale(View view){
//獲取一個logo.png的bitmap形式,然後縮放2倍,然後展示到ImageView
/*
* 1. 獲取一個模特加載原始Bitmap
*/
Bitmap bitmap = BitmapFactory.decodeResource(getResources(), R.drawable.logo);
/*
* 2. 創建一張空白的畫紙,畫紙的大小跟ImageView一樣大即可
*/
Bitmap newBitmap = Bitmap.createBitmap(iv.getWidth(), iv.getHeight(), Config.ARGB_8888);
/*
* 3. 將畫紙放到畫板上
*/
Canvas canvas = new Canvas(newBitmap);
//畫的方法
Matrix matrix = new Matrix();
float[] values = {
2,0,0,
0,1,0,
0,0,1
};
matrix.setValues(values);
// matrix.setScale(2f, 1f);//這種方法的設置也是可以的
/*
* 4. 將模特畫到畫紙上
* 參數1:模特對象
*/
canvas.drawBitmap(bitmap, matrix, null);//畫模特時不需要筆
/*
* 5. 將畫好的紙設置給ImageView
*/
iv.setImageBitmap(newBitmap);
}
- 02-平移
public void translate(View view){
/*
* 1. 獲取一個模特加載原始Bitmap
*/
Bitmap bitmap = BitmapFactory.decodeResource(getResources(), R.drawable.logo);
/*
* 2. 創建一張空白的畫紙,畫紙的大小跟ImageView一樣大即可
*/
Bitmap newBitmap = Bitmap.createBitmap(iv.getWidth(), iv.getHeight(), Config.ARGB_8888);
/*
* 3. 將畫紙放到畫板上
*/
Canvas canvas = new Canvas(newBitmap);
Matrix matrix = new Matrix();
//參數1:x方向的平移值
//參數2:y方向的平移值
matrix.setTranslate(20, 20);
//每一個像素點在用矩陣的表示
/*
* 4. 將模特畫到畫紙上
* 參數1:模特對象
*/
canvas.drawBitmap(bitmap, matrix, null);//畫模特時不需要筆
/*
* 5. 將畫好的紙設置給ImageView
*/
iv.setImageBitmap(newBitmap);
}
- 03-鏡面
public void reverse(View view){
/*
* 1. 獲取一個模特加載原始Bitmap
*/
Bitmap bitmap = BitmapFactory.decodeResource(getResources(), R.drawable.logo);
/*
* 2. 創建一張空白的畫紙,畫紙的大小跟ImageView一樣大即可
*/
Bitmap newBitmap = Bitmap.createBitmap(iv.getWidth(), iv.getHeight(), Config.ARGB_8888);
/*
* 3. 將畫紙放到畫板上
*/
Canvas canvas = new Canvas(newBitmap);
Matrix matrix = new Matrix();
float[] values = {
1,0,0,
0,-1,0,
0,0,1
};
matrix.setValues(values);
//matrix.setScale(1f, 1f);//這種方法的設置也是可以的
//在讓矩陣線y平移一個bitmap的高度值
//matrix.setTranslate(0, bitmap.getHeight());
//在原來值的基礎上再次修改
matrix.postTranslate(bitmap.getWidth(),0);
/*
* 4. 將模特畫到畫紙上
* 參數1:模特對象
*/
canvas.drawBitmap(bitmap, matrix, null);//畫模特時不需要筆
/*
* 5. 將畫好的紙設置給ImageView
*/
iv.setImageBitmap(newBitmap);
}
- 04-倒影
public void reverse(View view){
/*
* 1. 獲取一個模特加載原始Bitmap
*/
Bitmap bitmap = BitmapFactory.decodeResource(getResources(), R.drawable.logo);
/*
* 2. 創建一張空白的畫紙,畫紙的大小跟ImageView一樣大即可
*/
Bitmap newBitmap = Bitmap.createBitmap(iv.getWidth(), iv.getHeight(), Config.ARGB_8888);
/*
* 3. 將畫紙放到畫板上
*/
Canvas canvas = new Canvas(newBitmap);
Matrix matrix = new Matrix();
float[] values = {
1,0,0,
0,-1,0,
0,0,1
};
matrix.setValues(values);
// matrix.setScale(f, -1f);//這種方法的設置也是可以的
//在讓矩陣線y平移一個bitmap的高度值
// matrix.setTranslate(0, bitmap.getHeight());
//在原來值的基礎上再次修改
matrix.postTranslate(0,bitmap.getHeight());
/*
* 4. 將模特畫到畫紙上
* 參數1:模特對象
*/
canvas.drawBitmap(bitmap, matrix, null);//畫模特時不需要筆
/*
* 5. 將畫好的紙設置給ImageView
*/
iv.setImageBitmap(newBitmap);
}
- 05-旋轉
public void rotate(View view){
/*
* 1. 獲取一個模特加載原始Bitmap
*/
Bitmap bitmap = BitmapFactory.decodeResource(getResources(), R.drawable.logo);
/*
* 2. 創建一張空白的畫紙,畫紙的大小跟ImageView一樣大即可
*/
Bitmap newBitmap = Bitmap.createBitmap(iv.getWidth(), iv.getHeight(), Config.ARGB_8888);
/*
* 3. 將畫紙放到畫板上
*/
Canvas canvas = new Canvas(newBitmap);
Matrix matrix = new Matrix();
//默認繞着左上角旋轉
// matrix.setRotate(10);//0--360 0--2π
matrix.setRotate(180, bitmap.getWidth()/2, bitmap.getHeight()/2);
/*
* 4. 將模特畫到畫紙上
* 參數1:模特對象
*/
canvas.drawBitmap(bitmap, matrix, null);//畫模特時不需要筆
/*
* 5. 將畫好的紙設置給ImageView
*/
iv.setImageBitmap(newBitmap);
}
4. 實例:隨手塗鴉
01-監聽事件
02-監聽事件
03-保存圖片
04-在圖庫中預覽
public class MainActivity extends Activity {
private ImageView iv;
private Bitmap bitmap;
private Canvas canvas;
private Paint paint;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
iv = (ImageView) findViewById(R.id.iv);
/*
* 1. 給ImageView設置觸摸事件
*/
/*
* 2. 當滑動的時候,觸摸事件分爲3類:
* (1). down
* 記錄一下(startX,startY)
* (2). move
* 獲取到當前滑動到的座標(currentX,currentY)
* 根據兩個座標劃線
* 將畫好的Bitmap顯示到ImageView上
* (3). up
*
*/
iv.setOnTouchListener(new OnTouchListener() {
private float startX;
private float startY;
@Override
public boolean onTouch(View v, MotionEvent event) {
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
// Log.d("tag", "down");
//獲取當前事件的座標
startX = event.getX();
startY = event.getY();
if (bitmap==null) {
bitmap = Bitmap.createBitmap(iv.getWidth(), iv.getHeight(), Config.ARGB_8888);
canvas = new Canvas(bitmap);
//先給Bitmap繪製成白色的
canvas.drawColor(Color.WHITE);
paint = new Paint();
paint.setColor(Color.RED);
paint.setStrokeWidth(5);//畫筆的粗細 5個像素
}
break;
case MotionEvent.ACTION_MOVE:
// Log.d("tag", "move");
float currentX = event.getX();
float currentY = event.getY();
//畫線
canvas.drawLine(startX, startY, currentX, currentY, paint);
//一個新線條的起點就是上一個線條的終點
startX = currentX;
startY = currentY;
iv.setImageBitmap(bitmap);
break;
case MotionEvent.ACTION_UP:
// Log.d("tag", "up");
break;
default:
break;
}
//當前ImageView是否將這個事件給消費了
return true;
}
});
}
public void save(View view) throws FileNotFoundException{
//把Bitmap保存到sdcard上jpg
if (bitmap==null) {
Toast.makeText(this, "還沒畫呢,咋保存!", Toast.LENGTH_SHORT).show();
return;
}
File file = new File(Environment.getExternalStorageDirectory(), "yuze_"+new Date().getTime()+".jpg");
OutputStream fos = new FileOutputStream(file);
/*
* 參數1:壓縮的格式
* 參數2:圖片的質量
* 參數3:輸出流
*/
boolean compress = bitmap.compress(CompressFormat.JPEG, 100, fos);
Toast.makeText(this, compress?"成功":"失敗", Toast.LENGTH_SHORT).show();
//給系統圖庫發送廣播,告訴圖庫我在sdcard上保存了文件,請求添加到你的預覽圖中
Intent intent = new Intent();
intent.setAction(Intent.ACTION_MEDIA_SCANNER_SCAN_FILE);
//此處也可以設置掛載內存卡的事件,但4.4後安卓系統在不兼容,只能系統自己內部自己調用.
intent.setData(Uri.fromFile(file));
sendBroadcast(intent);
}
public void clear(View view){
bitmap = null;
iv.setImageBitmap(bitmap);
}
}
獲取屏幕的寬高
5. 實例:撕衣服遊戲
01 - 獲取屏幕的寬高
//事先已在XML定義好了全景的背景圖..
public class MainActivity extends Activity {
private ImageView iv;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
iv = (ImageView) findViewById(R.id.iv);
// 重新在內存中創建一張空白的紙Bitmap,然後將up.jpg繪製到這張紙上
// 獲取屏幕的寬和高
Display display = getWindowManager().getDefaultDisplay();
int width = display.getWidth();
int height = display.getHeight();
//獲取屏幕寬高的第二種方式:
// Point outSize = new Point();
// display.getSize(outSize);
// outSize.x;outSize.y
//這是上面的那張圖片的位圖,原圖是不能夠修改的,只有創建他的位圖的副本才能夠修改.
Bitmap bitmap = BitmapFactory.decodeResource(getResources(), R.drawable.ic_launcher);
// 192 288 288 432
// 由於這個bitmap是來自本地的資源文件,因此該bitmap不能修改,只能讀.
// bitmap.setPixel(20, 20, Color.TRANSPARENT);
// 在內存中創建一張空白的bitmap纔是可以被修改的
final Bitmap newbitmap = Bitmap.createBitmap(width, height, Config.ARGB_8888);
Canvas canvas = new Canvas(newbitmap);
Matrix matrix = new Matrix();// 默認就是單位矩陣
//放大該圖片,該圖片的真實大小不能夠佈滿整個屏幕
float[] values = { (width + 0f) / bitmap.getWidth(), 0, 0, 0, (height + 0f) / bitmap.getHeight(), 0, 0, 0, 1
};
matrix.setValues(values);
canvas.drawBitmap(bitmap, matrix, null);
iv.setImageBitmap(newbitmap);
// 給ImageView設置手機滑動的監聽
iv.setOnTouchListener(new OnTouchListener() {
@Override
public boolean onTouch(View v, MotionEvent event) {
// 獲取到當前觸摸到的座標,建議使用getRawX();
int x = (int) event.getX();
int y = (int) event.getY();
int startX = x - 5;
int endX = x + 5;
int startY = y - 5;
int endY = y + 5;
for (int i = startX; i < endX; i++) {
for (int j = startY; j < endY; j++) {
// 設置像素點不會越界的條件
if (i > 0 && i < 480 && j > 0 && j < 480) {
// 將newbitmap對應的(x,y)的像素設置爲透明的
newbitmap.setPixel(i, j, Color.TRANSPARENT);
}
}
}
// 重新將修改後的newbitmap設置給ImageView
iv.setImageBitmap(newbitmap);
return true;
}
});
}
}
2. ImageView(原生)
3. SmartImageView(廢棄)
4. Glide(Google)
Glide.with(this).load("http://h.hiphotos.baidu.com/image/pic/item/0ff41bd5ad6eddc49e5987f53bdbb6fd52663305.jpg")
.crossFade(5000)
.skipMemoryCache(true)//不使用內存緩存
.diskCacheStrategy(DiskCacheStrategy.ALL)
.placeholder(R.drawable.ic_launcher)
.error(R.drawable.error)
.into(iv);