网络图片框架
- 大图片的处理原理
- 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);