一、图片的存在形式
1.文件形式(即以二进制形式存在于硬盘上)
2.流的形式(即以二进制形式存在于内存中)
3.Bitmap形式 (位图图像(bitmap), 亦称为点阵图像或绘制图像,是由称作像素(图片元素)的单个点组成的。这些点可以进行不同的排列和染色以构成图样。)
这三种形式的区别: 文件形式和流的形式对图片体积大小并没有影响,也就是说,如果你手机SD卡上的如果是100K,那么通过流的形式读到内存中,也一定是占100K的内存,注意是流的形式,不是Bitmap的形式,当图片以Bitmap的形式存在时,其占用的内存会瞬间变大, 我试过500K文件形式的图片加载到内存,以Bitmap形式存在时,占用内存将近10M,当然这个增大的倍数并不是固定的。
二、Android中图片形式
Android中图片是以位图(BitMap)形式存在的,位图常见的文件格式有:
.bmp
.jpg
.gif
.png
一张图片(BitMap)占用的内存主要和以下几个因数有关:图片长度,图片宽度,单位像素占用的字节数。
一张图片(BitMap)占用的内存=图片长度x图片宽度x单位像素占用的字节数
位图(BitMap)的优缺点:
位图(BitMap)色彩变化丰富,可以改变任何形状的区域的色彩显示效果,相应的,要实现的效果越复杂,需要的象素数越多,图像文件的大小长宽和体积[存储空间]越大。
位图的一个缺点是放大和缩小都会引起像素的增加和减小,这样会使得原由的图象的线条和形状变的参差不齐,与原图像相比出现失真;出现”锯齿形“。位图的另一个缺点就是数据量太大(如:长和宽分别为1024像素和768像素得24位色彩深度的图象就需要(1024×768×24÷8)=2304K个字节存储文件)。
三、看代码:
public class HomelActivity extends AppCompatActivity {
private static final int REQUEST_WRITE = 0;
@BindView(R.id.but)
Button but;
@BindView(R.id.img)
ImageView img;
private int width, height;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_homel);
ButterKnife.bind(this);
initData();
//获取系统宽高
WindowManager wm = (WindowManager) getSystemService(WINDOW_SERVICE);
Display defaultDisplay = wm.getDefaultDisplay();
width = defaultDisplay.getWidth();
height = defaultDisplay.getHeight();
}
// 动态获取权限
private void check() {
//判断是否6.0以上的手机 不是就不用
if (Build.VERSION.SDK_INT >= 23) {
if (ContextCompat.checkSelfPermission(this,
Manifest.permission.WRITE_EXTERNAL_STORAGE) !=
PackageManager.PERMISSION_GRANTED) {
ActivityCompat.requestPermissions(this,
new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE},
REQUEST_WRITE);
} else {
// writeToSdCard2();
// writeToSdCard3();
writeToSdCard();
}
}
}
// 动态获取权限
@Override
public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
super.onRequestPermissionsResult(requestCode, permissions, grantResults);
if (requestCode == REQUEST_WRITE && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
// writeToSdCard2();
// writeToSdCard3();
writeToSdCard();
}
}
裁剪压缩 压缩是图片尺寸 基于内存压缩的:
// //裁剪压缩 压缩是图片尺寸 基于内存压缩的
// private void writeToSdCard3() {
// Bitmap bitmap = BitmapFactory.decodeResource(getResources(), R.mipmap.ava);
// Matrix martx = new Matrix();
// martx.setScale(0.1F, 0.1F);
// Bitmap newBitmap = Bitmap.createBitmap(bitmap, 0, 0, bitmap.getWidth(), bitmap.getHeight(),
// martx, true);
// int mb = newBitmap.getByteCount() / 1024 / 1024;
// Log.e("TAG", "mb=====" + mb + "----------" +
// "M宽度为" + newBitmap.getWidth() + "高度为" + newBitmap.getHeight());
//
//
// img.setImageBitmap(newBitmap);
// }
二次采样:
// //图片二次采样 (采用两次尝试解析图片 第一次不是完全解析,第一次)
// public void click() {
//// check();
//
// //第一次解析图片 并不是直接解析整张图片 直接获取图片的宽和高
// BitmapFactory.Options options = new BitmapFactory.Options();
// options.inJustDecodeBounds = true;
// Bitmap bitmap = BitmapFactory.decodeResource(getResources(), R.mipmap.ava, options);
//
// int outWidth = options.outWidth;
// int outHeight = options.outHeight;
//
// int scale = 0;
// if (outWidth > width || outHeight > height) {
// int scaleWidth = outWidth / width;
// int scaleHeight = outHeight / height;
// scale = scaleWidth > scaleHeight ? scaleWidth : scaleHeight;
// }
//
// //将压缩比例赋值给options
// options.inSampleSize = scale;
// //options.inPreferredConfig = Bitmap.Config.RGB_565;
//
//
// //3.开始真正解析这个图片
// options.inJustDecodeBounds = false;
// bitmap = BitmapFactory.decodeResource(getResources(), R.mipmap.ava, options);
//
// img.setImageBitmap(bitmap);
//
//
//
// //按照图片格式压缩
//// BitmapFactory.Options op = new BitmapFactory.Options();
//// op.inPreferredConfig = Bitmap.Config.RGB_565;
//// Bitmap bitmap = BitmapFactory.decodeResource(getResources(), R.mipmap.a, op);
//// img.setImageBitmap(bitmap);
//
//
// }
从网络获取图片解析并压缩保存到CD卡
//
// //从网络获取图片解析并压缩
// private void writeToSdCard2() {
// if (!Environment.getExternalStorageState().
// equals(Environment.MEDIA_MOUNTED)) {
// Toast.makeText(this, "外部存储卡不能用", Toast.LENGTH_LONG).show();
// return;
// }
// final String save_path = Environment.getExternalStorageDirectory() + "/123/aaaaaaaa____aaaaaaaa.jpg";
//
//
//
// OkHttpClient client = new OkHttpClient.Builder().
// connectTimeout(5000, TimeUnit.MILLISECONDS).
// readTimeout(5000, TimeUnit.MILLISECONDS).build();
// Request request = new Request.Builder().url("https://timgsa.baidu.com/timg?image&quality=80&size=b9999_10000&sec=1565603767756&di=9a62675ce0212a8ad7d2e2395b960a32&imgtype=0&src=http%3A%2F%2Fimg2.fengniao.com%2Fg1%2FM00%2F02%2F29%2FCg-4q1V9RwaIa5k9AGH7UztR7qgAAI1kwGKc-IAYftr651.jpg").build();
// Call call = client.newCall(request);
// call.enqueue(new Callback() {
// @Override
// public void onFailure(Call call, IOException e) {
// Log.e("TAG", "请求失败" + e.getMessage());
// }
//
//
// @Override
// public void onResponse(Call call, Response response) throws IOException {
// ResponseBody body = response.body();
// InputStream inputStream = body.byteStream();
// final Bitmap bitmap = BitmapFactory.decodeStream(inputStream);
// FileOutputStream fos = new FileOutputStream(save_path);
// int count = 0;
// byte[] buffer = new byte[1024];
// while ((count = inputStream.read(buffer)) != -1) {
// fos.write(buffer, 0, count);
// }
// boolean flag = bitmap.compress(Bitmap.CompressFormat.JPEG, 90, fos);
// Log.e("TAG", flag + "==========");
// }
// });
// }
从assets文件夹,读取图片并压缩到SD卡里:
//从assets文件夹,读取图片并压缩到SD卡里
private void writeToSdCard() {
if (!Environment.getExternalStorageState().
equals(Environment.MEDIA_MOUNTED)) {
Toast.makeText(this, "外部存储卡不能用", Toast.LENGTH_LONG).show();
return;
}
String save_path = Environment.getExternalStorageDirectory() + "/123/xxxxxxxxxxxxxxxxx.jpg";
Bitmap bitmap = null;
try {
InputStream inputStream = getAssets().
open("a.jpg");
bitmap = BitmapFactory.decodeStream(inputStream);
//文件输出流 向sdcard里面写文件
FileOutputStream fos = new FileOutputStream(save_path);
int length = 0;
byte[] buffer = new byte[1024];
while ((length = inputStream.read(buffer)) != -1) {
fos.write(buffer, 0, length);
Log.e("TAG", "aaaaa");
}
//
bitmap.compress(Bitmap.CompressFormat.JPEG, 50, fos);
img.setImageBitmap(bitmap);
} catch (IOException e) {
e.printStackTrace();
Log.e("TAG", "===error======" + e.getLocalizedMessage());
}
}
以上是四种压缩放式!
private void initData() {
//按钮点击事件
but.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
// //图片二次采样 (采用两次尝试解析图片 第一次不是完全解析,第一次)
// click();
//获取权限
check();
}
});
}
}