图片优化,Android支持图片类型:
PNG: 支持透明度,占用空间大
JPEG: 不支持透明
WEBP : 支持透明,占用空间小
gif: android本身的不支持
1. 开发中图片处理
drawable/mipmap : 官方建议把启动图标放入mip 下,其他放入 drawable, 开发只要一套最大图片即可,
xxxdpi 3840*2016
xxhdpi 1920*1080
xhdpi 1280*720
hdpi 800*480
2. 超大图片加载方法
RGB_565 : 一个像素点占2个 字节
ARGB_8888: 一个像素点占4个字节
图片大小计算= 宽度* 高度* 每个像素字节数
从上面原理优化图片:
1. 尺寸压缩
2. 质量压缩
3. 内存重用
1. 图片的二次采样,避免图片太大OOM
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"></uses-permission>
public class MainActivity extends AppCompatActivity {
private ImageView showImg;
WindowManager wm=null;
int WindowHeight;
int WindowWidth;
String filepath="/sdcard/1moviestest/large.png";
private int MY_PERMISSIONS_REQUEST_CALL_PHONE=1000;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
// 权限申请
if (ContextCompat.checkSelfPermission(this,
Manifest.permission.WRITE_EXTERNAL_STORAGE)
!= PackageManager.PERMISSION_GRANTED)
{
ActivityCompat.requestPermissions(MainActivity.this,
new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE},MY_PERMISSIONS_REQUEST_CALL_PHONE);
} else
{
}
}
// 权限回调
@Override
public void onRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults)
{
if (requestCode == MY_PERMISSIONS_REQUEST_CALL_PHONE)
{
if (grantResults[0] == PackageManager.PERMISSION_GRANTED)
{
} else
{
// Permission Denied
Toast.makeText(MainActivity.this, "Permission Denied", Toast.LENGTH_SHORT).show();
}
return;
}
super.onRequestPermissionsResult(requestCode, permissions, grantResults);
}
// 避免图片太大挂了
// 默认情况下 每个 anroid 给应用分配最大 堆大小16M (VM heap)
public void sendNotification(View view) {
//得到手机宽高
wm=(WindowManager) getSystemService(WINDOW_SERVICE);
WindowHeight=wm.getDefaultDisplay().getHeight();
WindowWidth=wm.getDefaultDisplay().getWidth();
showImg = findViewById(R.id.showImg);
// 设置为true,那么不解析图片,获取图片部分信息
BitmapFactory.Options opts=new BitmapFactory.Options();
// 如果这里设置为true,那么就不为图片分配内存,而是起到对图片测量的公共
// 查看bitmap信息,获取图片的头部信息
opts.inJustDecodeBounds=true;
BitmapFactory.decodeFile(filepath,opts);
int imageHeight=opts.outHeight;
int imageWidth=opts.outWidth;
Log.e("Tag", "图片的高:"+imageHeight+ "WindowHeight:"+WindowHeight);
Log.e("Tag", "图片的宽:"+imageWidth +" WindowWidth:"+WindowWidth);
// 得到手机屏幕的宽高
double scaleX=imageWidth*1.0/WindowWidth;
double scaleY=imageHeight*1.0/WindowHeight;
double scale=1;
// 按照大的来缩放,避免显示到屏幕外面
if(scaleX>scaleY && scaleY>=1){
scale=scaleX;
}
if(scaleY>scaleX && scaleX>=1){
scale=scaleY;
}
Log.e("Tag", "double-->scale: "+ scale +"scale:"+(int)scale);
// 解析图片, 正在把图片加载到内存中
opts.inJustDecodeBounds=false;
// 1. 减低图片的采样率,图片大小,从图片大小入手
opts.inSampleSize=(int)scale;
// 2. 从图片质量入手
// RGB_565 : 一个像素点占2个 字节
// ARGB_8888: 一个像素点占4个字节
opts.inPreferredConfig= Bitmap.Config.RGB_565;
Bitmap bitmap=BitmapFactory.decodeFile(filepath,opts);
showImg.setImageBitmap(bitmap);
}
}
图片头信息读取Api:
通过api:ExifInterface
比如拍摄时间
ExifInterface exif= null;
try {
exif = new ExifInterface("/sdcard/1.jpg");
} catch (IOException e) {
Log.e("Tag", "图片异常");
e.printStackTrace();
}
String time=exif.getAttribute(ExifInterface.TAG_DATETIME); //通过getAttribute()获取照片的属性:时间、
Log.e("Tag", "拍摄时间:"+time);
String type=exif.getAttribute(ExifInterface.TAG_MODEL);
String location = exif.getAttribute(ExifInterface.TAG_GPS_LONGITUDE);
Log.e("Tag", "相机是:"+type);
Log.e("Tag", "拍摄地点:"+location);