使用了retrofit 以及Rxjava从网络下载数据
//要添加的依赖
implementation project(':library-demonstrate')
compile 'io.reactivex.rxjava2:rxjava:2.1.3'
compile 'io.reactivex.rxjava2:rxandroid:2.0.1'
compile 'com.squareup.retrofit2:retrofit:2.3.0'
compile 'com.squareup.okhttp3:okhttp:3.9.0'
//要添加的权限
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
//布局文件
<ScrollView xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
tools:context="com.think.bitmap.MainActivity">
<Button
android:id="@+id/btn"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="Android中图片压缩方案!" />
<TextView
android:id="@+id/tv_old"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="old" />
<TextView
android:id="@+id/tv"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="111"
android:textColor="@android:color/holo_red_light" />
<TextView
android:id="@+id/tv3"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="111"
android:textColor="@android:color/holo_red_light" />
<ImageView
android:id="@+id/iv"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
</LinearLayout>
</ScrollView>
//抽象类使用retrofit2
public interface NetServerInterface {
@GET
Call<ResponseBody> getBitmap(@Url String url);
}
//主要使用方法
/*
1,质量压缩法
1.1质量压缩不会减少图片的像素
1.2在像素不变的前提下改变图片的位深及透明度等,来达到压缩图片的目的。
1.3压缩的图片文件大小会有改变,但是导入成bitmap后占得内存是不变的
2,采样率压缩法
2.1内存的使用少,不会过多的占用内存
2.2可以先只读取图片的边,通过宽和高设定好取样率后再加载图片
2.3
3,缩放法
3.1通过缩放图片像素来减少图片占用内存大小
*/
public class MainActivity extends AppCompatActivity implements View.OnClickListener {
private static final String IMG_URL_0 = "http://pic.xiami.net/images/artistlogo/77/14677816895777.jpg";
protected TextView tvOld;
protected TextView tv3;
private String baseUrl = "http://pic.xiami.net";
private int contentLength;
private String IMG_URL_1 = "http://pic9.nipic.com/20100823/4361515_000842599423_2.jpg";
private String IMG_URL_2 = "http://attachments.gfan.com/forum/attachments2/201302/03/11281446n2st1its4152n5.jpg";
private String filePath = Environment.getExternalStorageDirectory().getAbsolutePath() + "/bitmaps/";
private void showList() {
DialogUtil.showListDialog(this, "Android中图片压缩方案", new String[]{
"0,加载原图",
"1,下载原图",
"2,质量压缩法,不压缩保存到本地",
"3,质量压缩法,质量压缩保存到本地",
"4,采样率压缩法,保存",
"5,缩放法,方式一!",
"6,缩放法,方式二!",
}, new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
switch (which) {
case 0:
//加载原图,并且展示!
load0();
break;
case 1:
//下载原图,并且保存本地,从本加载展示!
load1();
break;
case 2:
//
load2();
break;
case 3:
load3();
break;
case 4:
load4();
break;
case 5:
load5();
break;
case 6:
load6();
break;
}
}
});
}
private void load6() {
Observable.create(new ObservableOnSubscribe<String>() {
@Override
public void subscribe(ObservableEmitter<String> e) throws Exception {
ResponseBody body = new Retrofit.Builder()
.baseUrl(baseUrl)
.build()
.create(NetServerInterface.class)
.getBitmap(IMG_URL_1)
.execute()
.body();
contentLength = (int) body.contentLength() / 1024;
InputStream stream = body
.byteStream();
Bitmap image = BitmapFactory.decodeStream(stream);
ByteArrayOutputStream out = new ByteArrayOutputStream();
image.compress(Bitmap.CompressFormat.JPEG, 85, out);
int size = contentLength;
//--原大小/内存小小后,开平方根.
float zoom = (float)Math.sqrt(size * 1024 / (float)out.toByteArray().length);
//
Matrix matrix = new Matrix();
matrix.setScale(zoom, zoom);
Bitmap result = Bitmap.createBitmap(image, 0, 0, image.getWidth(), image.getHeight(), matrix, true);
//清空.
out.reset();
result.compress(Bitmap.CompressFormat.JPEG, 85, out);
while(out.toByteArray().length > size * 1024){
DemonstrateUtil.showLogResult(out.toByteArray().length+"***");
matrix.setScale(0.9f, 0.9f);
result = Bitmap.createBitmap(result, 0, 0, result.getWidth(), result.getHeight(), matrix, true);
out.reset();
result.compress(Bitmap.CompressFormat.JPEG, 85, out);
}
File file = new File(Environment.getExternalStorageDirectory(), "load6.jpg");
FileOutputStream fos = new FileOutputStream(file);
fos.write(out.toByteArray());
fos.flush();
fos.close();
String filePath = file.getPath();
e.onNext(filePath);
}
})
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(new Consumer<String>() {
@Override
public void accept(String path) throws Exception {
tvOld.setText("原始大小:" + contentLength + "kb");
File file = new File(path);
int fileLenth = (int) (file.length() / 1024);
tv.setText("保存后大小:" + fileLenth + "kb");
Bitmap bitmap = BitmapFactory.decodeFile(path);
int byteCount = bitmap.getByteCount() / 1024;
tv3.setText("加载到内存的大小:" + byteCount);
iv.setImageBitmap(bitmap);
}
});
}
private void load5() {
Observable.create(new ObservableOnSubscribe<String>() {
@Override
public void subscribe(ObservableEmitter<String> e) throws Exception {
ResponseBody body = new Retrofit.Builder()
.baseUrl(baseUrl)
.build()
.create(NetServerInterface.class)
.getBitmap(IMG_URL_1)
.execute()
.body();
contentLength = (int) body.contentLength() / 1024;
InputStream stream = body
.byteStream();
Bitmap bmp = BitmapFactory.decodeStream(stream);
// 尺寸压缩倍数,值越大,图片尺寸越小
int ratio = 2;
// 压缩Bitmap到对应尺寸
//int width,宽 int height,高 Config config,决定图片质量.
Bitmap result = Bitmap.createBitmap(bmp.getWidth() / ratio, bmp.getHeight() / ratio, Bitmap.Config.ARGB_8888);
Canvas canvas = new Canvas(result);
Rect rect = new Rect(0, 0, bmp.getWidth() / ratio, bmp.getHeight() / ratio);
canvas.drawBitmap(bmp, null, rect, null);
ByteArrayOutputStream baos = new ByteArrayOutputStream();
// 把压缩后的数据存放到baos中
result.compress(Bitmap.CompressFormat.JPEG, 100, baos);
File file = new File(Environment.getExternalStorageDirectory(), "load5.jpg");
FileOutputStream fos = new FileOutputStream(file);
fos.write(baos.toByteArray());
fos.flush();
fos.close();
String filePath = file.getPath();
e.onNext(filePath);
}
})
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(new Consumer<String>() {
@Override
public void accept(String path) throws Exception {
tvOld.setText("原始大小:" + contentLength + "kb");
File file = new File(path);
int fileLenth = (int) (file.length() / 1024);
tv.setText("保存后大小:" + fileLenth + "kb");
Bitmap bitmap = BitmapFactory.decodeFile(path);
int byteCount = bitmap.getByteCount() / 1024;
tv3.setText("加载到内存的大小:" + byteCount);
iv.setImageBitmap(bitmap);
}
});
}
private void load4() {
Observable.create(new ObservableOnSubscribe<String>() {
@Override
public void subscribe(ObservableEmitter<String> e) throws Exception {
ResponseBody body = new Retrofit.Builder()
.baseUrl(baseUrl)
.build()
.create(NetServerInterface.class)
.getBitmap(IMG_URL_2)
.execute()
.body();
contentLength = (int) body.contentLength() / 1024;
InputStream stream = body
.byteStream();
File file = new File(Environment.getExternalStorageDirectory(), "load4.jpg");
FileOutputStream out = new FileOutputStream(file);
out.write(body.bytes());
out.close();
String filePath = file.getPath();
e.onNext(filePath);
}
})
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(new Consumer<String>() {
@Override
public void accept(String path) throws Exception {
tvOld.setText("原始大小:" + contentLength + "kb");
File file = new File(path);
int fileLenth = (int) (file.length() / 1024);
tv.setText("保存后大小:" + fileLenth + "kb");
//使用采样率进行压缩
BitmapFactory.Options newOpts = new BitmapFactory.Options();
//开始读入图片,此时把options.inJustDecodeBounds 设回true了
newOpts.inJustDecodeBounds = true;
//此时返回bitmap为空
Bitmap bitmap = BitmapFactory.decodeFile(path, newOpts);
newOpts.inJustDecodeBounds = false;
int w = newOpts.outWidth;
int h = newOpts.outHeight;
//现在主流手机比较多是1280*720分辨率,所以高和宽我们设置为
//这里设置高度为1280f
float hh = 1280f;
//这里设置宽度为720f
float ww = 720f;
//缩放比。由于是固定比例缩放,只用高或者宽其中一个数据进行计算即可
//be=1表示不缩放
int be = 1;
if (w > h && w > ww) {//如果宽度大的话根据宽度固定大小缩放
be = (int) (newOpts.outWidth / ww);
} else if (w < h && h > hh) {//如果高度高的话根据高度固定大小缩放
be = (int) (newOpts.outHeight / hh);
}
if (be <= 0) {
be = 1;
}
//设置缩放比例
newOpts.inSampleSize = be;
//重新读入图片,注意此时已经把options.inJustDecodeBounds 设回false了
bitmap = BitmapFactory.decodeFile(path, newOpts);
//压缩好比例大小后再进行质量压缩
ByteArrayOutputStream baos = new ByteArrayOutputStream();
bitmap.compress(Bitmap.CompressFormat.JPEG, 100, baos);//质量压缩方法,这里100表示不压缩,把压缩后的数据存放到baos中
int options = 100;
while (baos.toByteArray().length / 1024 > 100) { //循环判断如果压缩后图片是否大于100kb,大于继续压缩
//重置baos即清空baos
baos.reset();
//这里压缩options%,把压缩后的数据存放到baos中
bitmap.compress(Bitmap.CompressFormat.JPEG, options, baos);
options -= 10;//每次都减少10
}
int len = baos.toByteArray().length / 1024;
tv3.setText("内存中的大小:" + len + "kb");
//把压缩后的数据baos存放到ByteArrayInputStream中
ByteArrayInputStream isBm = new ByteArrayInputStream(baos.toByteArray());
//把ByteArrayInputStream数据生成图片
Bitmap bitmap3 = BitmapFactory.decodeStream(isBm, null, null);
tv.setText("保存后大小:" + fileLenth + "kb"+"bitmap:"+bitmap3.getByteCount()/1024+"--");
iv.setImageBitmap(bitmap3);
/*File file5 = new File(Environment.getExternalStorageDirectory(), "load5.jpg");
FileOutputStream out = new FileOutputStream(file5);
out.write(baos.toByteArray());
out.close();
baos.close();*/
}
});
}
private void load3() {
Observable.create(new ObservableOnSubscribe<String>() {
@Override
public void subscribe(ObservableEmitter<String> e) throws Exception {
ResponseBody body = new Retrofit.Builder()
.baseUrl(baseUrl)
.build()
.create(NetServerInterface.class)
.getBitmap(IMG_URL_1)
.execute()
.body();
contentLength = (int) body.contentLength() / 1024;
InputStream stream = body
.byteStream();
Bitmap bitmap = BitmapFactory.decodeStream(stream);
ByteArrayOutputStream baos = new ByteArrayOutputStream();
bitmap.compress(Bitmap.CompressFormat.JPEG, 100, baos);//质量压缩方法,这里100表示不压缩,把压缩后的数据存放到baos中
int options = 100;
while (baos.toByteArray().length / 1024 > 100) { //循环判断如果压缩后图片是否大于100kb,大于继续压缩
//重置baos即清空baos
baos.reset();
//这里压缩options%,把压缩后的数据存放到baos中
bitmap.compress(Bitmap.CompressFormat.JPEG, options, baos);
options -= 10;//每次都减少10
}
File file = new File(Environment.getExternalStorageDirectory(), "load3.jpg");
FileOutputStream out = new FileOutputStream(file);
out.write(baos.toByteArray());
out.close();
baos.close();
String filePath = file.getPath();
e.onNext(filePath);
}
})
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(new Consumer<String>() {
@Override
public void accept(String path) throws Exception {
tvOld.setText("原始大小:" + contentLength + "kb");
File file = new File(path);
int fileLenth = (int) (file.length() / 1024);
tv.setText("保存后大小:" + fileLenth + "kb");
Bitmap bitmap = BitmapFactory.decodeFile(path);
int byteCount = bitmap.getByteCount() / 1024;
tv3.setText("加载到内存的大小:" + byteCount);
iv.setImageBitmap(bitmap);
}
});
}
private void load2() {
Observable.create(new ObservableOnSubscribe<String>() {
@Override
public void subscribe(ObservableEmitter<String> e) throws Exception {
ResponseBody body = new Retrofit.Builder()
.baseUrl(baseUrl)
.build()
.create(NetServerInterface.class)
.getBitmap(IMG_URL_1)
.execute()
.body();
contentLength = (int) body.contentLength() / 1024;
InputStream stream = body
.byteStream();
//压缩100,图片并将Bitmap保存到本地
Bitmap bitmap = BitmapFactory.decodeStream(stream);
File file = new File(Environment.getExternalStorageDirectory(), "load2.jpg");
FileOutputStream out = new FileOutputStream(file);
bitmap.compress(Bitmap.CompressFormat.JPEG, 100, out);
String filePath = file.getPath();
e.onNext(filePath);
}
})
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(new Consumer<String>() {
@Override
public void accept(String path) throws Exception {
tvOld.setText("原始大小:" + contentLength + "kb");
File file = new File(path);
int fileLenth = (int) (file.length() / 1024);
tv.setText("保存后大小:" + fileLenth + "kb");
Bitmap bitmap = BitmapFactory.decodeFile(path);
int byteCount = bitmap.getByteCount() / 1024;
tv3.setText("加载到内存的大小:" + byteCount);
iv.setImageBitmap(bitmap);
}
});
}
private void load1() {
Observable.create(new ObservableOnSubscribe<String>() {
@Override
public void subscribe(ObservableEmitter<String> e) throws Exception {
ResponseBody body = new Retrofit.Builder()
.baseUrl(baseUrl)
.build()
.create(NetServerInterface.class)
.getBitmap(IMG_URL_1)
.execute()
.body();
contentLength = (int) body.contentLength() / 1024;
InputStream stream = body
.byteStream();
//压缩图片并将Bitmap保存到本地
// Bitmap bitmap = BitmapFactory.decodeStream(stream);
// bitmap.compress(Bitmap.CompressFormat.JPEG, 100, out);
File file = new File(Environment.getExternalStorageDirectory(), "load1.jpg");
FileOutputStream out = new FileOutputStream(file);
out.write(body.bytes());
out.close();
String filePath = file.getPath();
e.onNext(filePath);
}
})
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(new Consumer<String>() {
@Override
public void accept(String path) throws Exception {
tvOld.setText("原始大小:" + contentLength + "kb");
File file = new File(path);
int fileLenth = (int) (file.length() / 1024);
tv.setText("保存后大小:" + fileLenth + "kb");
Bitmap bitmap = BitmapFactory.decodeFile(path);
int byteCount = bitmap.getByteCount() / 1024;
tv3.setText("加载到内存的大小:" + byteCount);
iv.setImageBitmap(bitmap);
}
});
}
private void load0() {
Observable
.create(new ObservableOnSubscribe<Bitmap>() {
@Override
public void subscribe(ObservableEmitter<Bitmap> e) throws Exception {
Response<ResponseBody> response = new Retrofit.Builder()
.baseUrl(baseUrl)
.build()
.create(NetServerInterface.class)
.getBitmap(IMG_URL_0)
.execute();
contentLength = (int) (response.body().contentLength() / 1024);
InputStream stream = response.body().byteStream();
Bitmap bitmap = BitmapFactory.decodeStream(stream);
e.onNext(bitmap);
}
}).subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(new Consumer<Bitmap>() {
@Override
public void accept(Bitmap bitmap) throws Exception {
tvOld.setText("原图片大小为:" + contentLength + "kb");
iv.setImageBitmap(bitmap);
}
});
}
protected Button btn;
protected TextView tv;
protected ImageView iv;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
super.setContentView(R.layout.activity_main);
initView();
}
@Override
public void onClick(View view) {
if (view.getId() == R.id.btn) {
showList();
}
}
private void initView() {
btn = (Button) findViewById(R.id.btn);
btn.setOnClickListener(MainActivity.this);
tv = (TextView) findViewById(R.id.tv);
iv = (ImageView) findViewById(R.id.iv);
tvOld = (TextView) findViewById(R.id.tv_old);
tv3 = (TextView) findViewById(R.id.tv3);
}
}