版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/yrmao9893/article/details/70599061 </div>
<link rel="stylesheet" href="https://csdnimg.cn/release/phoenix/template/css/ck_htmledit_views-db05db230f.css">
<div class="htmledit_views" id="content_views">
<p>转载请说明出处 <a href="http://write.blog.csdn.net/postedit/70599061" rel="nofollow" target="_blank">http://write.blog.csdn.net/postedit/70599061</a></p>
最近公司又叫开发了一个新项目,这个项目中上传图片用的蛮多的,于是整理一下,记录自己的心得体验
刚入手的时候,对于图片的大小还没有概念,(以前上传图片都是用户头像,对大小没什么要求),心想之间上传就是了,和以前一样,那成想到,上传一张图片还好,上传多张图片慢成狗,这时候,我还是无动于衷,直到有一天,服务器端也意识到了,图片太大对数据库没好处,只会让数据库变得无比庞大,限制的上传图片的大小,单张图片最大为2w,此时的我,再也不能无动于衷了,默默的进行图片的压缩,而我对于图片的压缩可以用一无所知来形容,尽管上学的时候学习过,只好借鉴Google了,压缩图片方法大致分为如下几类,
1.质量压缩
2.采样率压缩
3.缩放法压缩
4.RGB_565
5.createScaledBitmap
参考文章:http://blog.csdn.net/harryweasley/article/details/51955467
而我采用的是质量压缩方法
废话不多说直接看看效果图(这里直接用了公司项目中的图片截的屏幕)
压缩前的图片截图:
点击其中一张图片
上传并压缩后的截图
点击其中一张小图
在送一张好图
由肉眼辨别,貌似压缩前和压缩后的分辨率·,没有什么区别。
我也简单的做了一下对比,压缩前图片的大小为5w左右,压缩后的大小为100k左右,这似乎满足了我的需求(内心有点小激动!)
代码说明 首先说明一下,使用的网络请求库是:Retrofit2+Rxjava2 ps 还不知道这个是什么东东的童鞋,I 服了you
压缩图片的工具类BitmapUtil
-
/**
-
* Created by yemao on 2017/3/15.
-
* 关于图片的工具类
-
*/
-
-
public
class BitmapUtil {
-
-
private
static String PHOTO_FILE_NAME =
"PMSManagerPhoto";
-
-
/**
-
* 获取图片的旋转角度
-
*
-
* @param filePath
-
* @return
-
*/
-
public static int getRotateAngle(String filePath) {
-
int rotate_angle =
0;
-
try {
-
ExifInterface exifInterface =
new ExifInterface(filePath);
-
int orientation = exifInterface.getAttributeInt(ExifInterface.TAG_ORIENTATION, ExifInterface.ORIENTATION_NORMAL);
-
switch (orientation) {
-
case ExifInterface.ORIENTATION_ROTATE_90:
-
rotate_angle =
90;
-
break;
-
case ExifInterface.ORIENTATION_ROTATE_180:
-
rotate_angle =
180;
-
break;
-
case ExifInterface.ORIENTATION_ROTATE_270:
-
rotate_angle =
270;
-
break;
-
}
-
}
catch (IOException e) {
-
e.printStackTrace();
-
}
-
return rotate_angle;
-
}
-
-
/**
-
* 旋转图片角度
-
*
-
* @param angle
-
* @param bitmap
-
* @return
-
*/
-
public static Bitmap setRotateAngle(int angle, Bitmap bitmap) {
-
-
if (bitmap !=
null) {
-
Matrix m =
new Matrix();
-
m.postRotate(angle);
-
bitmap = Bitmap.createBitmap(bitmap,
0,
0, bitmap.getWidth(),
-
bitmap.getHeight(), m,
true);
-
return bitmap;
-
}
-
return bitmap;
-
-
}
-
-
//转换为圆形状的bitmap
-
public static Bitmap createCircleImage(Bitmap source) {
-
int length = source.getWidth() < source.getHeight() ? source.getWidth() : source.getHeight();
-
Paint paint =
new Paint();
-
paint.setAntiAlias(
true);
-
Bitmap target = Bitmap.createBitmap(length, length, Bitmap.Config.ARGB_8888);
-
Canvas canvas =
new Canvas(target);
-
canvas.drawCircle(length /
2, length /
2, length /
2, paint);
-
paint.setXfermode(
new PorterDuffXfermode(PorterDuff.Mode.SRC_IN));
-
canvas.drawBitmap(source,
0,
0, paint);
-
return target;
-
}
-
-
-
-
/**
-
* 图片压缩-质量压缩
-
*
-
* @param filePath 源图片路径
-
* @return 压缩后的路径
-
*/
-
-
public static String compressImage(String filePath) {
-
-
//原文件
-
File oldFile =
new File(filePath);
-
-
-
//压缩文件路径 照片路径/
-
String targetPath = oldFile.getPath();
-
int quality =
50;
//压缩比例0-100
-
Bitmap bm = getSmallBitmap(filePath);
//获取一定尺寸的图片
-
int degree = getRotateAngle(filePath);
//获取相片拍摄角度
-
-
if (degree !=
0) {
//旋转照片角度,防止头像横着显示
-
bm = setRotateAngle(degree,bm);
-
}
-
File outputFile =
new File(targetPath);
-
try {
-
if (!outputFile.exists()) {
-
outputFile.getParentFile().mkdirs();
-
//outputFile.createNewFile();
-
}
else {
-
outputFile.delete();
-
}
-
FileOutputStream out =
new FileOutputStream(outputFile);
-
bm.compress(Bitmap.CompressFormat.JPEG, quality, out);
-
out.close();
-
}
catch (Exception e) {
-
e.printStackTrace();
-
return filePath;
-
}
-
return outputFile.getPath();
-
}
-
-
/**
-
* 根据路径获得图片信息并按比例压缩,返回bitmap
-
*/
-
public static Bitmap getSmallBitmap(String filePath) {
-
final BitmapFactory.Options options =
new BitmapFactory.Options();
-
options.inJustDecodeBounds =
true;
//只解析图片边沿,获取宽高
-
BitmapFactory.decodeFile(filePath, options);
-
// 计算缩放比
-
options.inSampleSize = calculateInSampleSize(options,
480,
800);
-
// 完整解析图片返回bitmap
-
options.inJustDecodeBounds =
false;
-
return BitmapFactory.decodeFile(filePath, options);
-
}
-
-
-
public static int calculateInSampleSize(BitmapFactory.Options options,
-
int reqWidth,
int reqHeight) {
-
final
int height = options.outHeight;
-
final
int width = options.outWidth;
-
int inSampleSize =
1;
-
if (height > reqHeight || width > reqWidth) {
-
final
int heightRatio = Math.round((
float) height / (
float) reqHeight);
-
final
int widthRatio = Math.round((
float) width / (
float) reqWidth);
-
inSampleSize = heightRatio < widthRatio ? heightRatio : widthRatio;
-
}
-
return inSampleSize;
-
}
-
-
-
}
//简单的封装了一下网络请求工具类RetorfitFactory
-
public
class RetrofitFactory {
-
-
private
static RetrofitFactory mRetrofitFactory;
-
private
static APIFunction mAPIFunction;
-
private RetrofitFactory(){
-
OkHttpClient mOkHttpClient=
new OkHttpClient.Builder()
-
.connectTimeout(HttpConfig.HTTP_TIME, TimeUnit.SECONDS)
-
.readTimeout(HttpConfig.HTTP_TIME, TimeUnit.SECONDS)
-
.writeTimeout(HttpConfig.HTTP_TIME, TimeUnit.SECONDS)
-
.build();
-
Retrofit mRetrofit=
new Retrofit.Builder()
-
.baseUrl(HttpConfig.BASE_URL)
-
.addConverterFactory(GsonConverterFactory.create())
//添加gson转换器
-
.addCallAdapterFactory(RxJava2CallAdapterFactory.create())
//添加rxjava转换器
-
.client(mOkHttpClient)
-
.build();
-
mAPIFunction=mRetrofit.create(APIFunction.class);
-
-
}
-
-
public static RetrofitFactory getInstence(){
-
if (mRetrofitFactory==
null){
-
synchronized (RetrofitFactory.class) {
-
if (mRetrofitFactory ==
null)
-
mRetrofitFactory =
new RetrofitFactory();
-
}
-
-
}
-
return mRetrofitFactory;
-
}
-
public APIFunction API(){
-
return mAPIFunction;
-
}
-
}
代理API接口类APIFunction
-
/**
-
* @author yemao
-
* @date 2017/4/9
-
* @description API接口!
-
*/
-
-
public
interface APIFunction {
-
-
-
//上传单张图片
-
@POST(
"服务器地址")
-
Observable<Object> imageUpload(@Part() MultipartBody.Part img);
-
//上传多张图片
-
@POST(
"服务器地址")
-
Observable<Object> imagesUpload(@Part() List<MultipartBody.Part> imgs);
-
}
上传图片的的工具类
-
package com.yr.example.utils;
-
-
import android.content.Context;
-
import android.os.AsyncTask;
-
-
import com.yr.example.http.RetrofitFactory;
-
-
import java.io.File;
-
import java.io.IOException;
-
import java.util.ArrayList;
-
import java.util.List;
-
-
import io.reactivex.Observable;
-
import io.reactivex.Observer;
-
import io.reactivex.android.schedulers.AndroidSchedulers;
-
import io.reactivex.schedulers.Schedulers;
-
import okhttp3.MediaType;
-
import okhttp3.MultipartBody;
-
import okhttp3.RequestBody;
-
-
/**
-
* @author yemao
-
* @date 2017/4/17
-
* @description null!
-
*/
-
-
public
class UploadUtil {
-
-
/**
-
* 上传单张图片
-
*
-
* @param filePath 图片本地路径
-
* @param observer 观察者
-
* @throws IOException
-
*/
-
public static void uploadImage(final String filePath, final Observer observer) {
-
new AsyncTask<Integer, Integer, File>() {
-
@Override
-
protected File doInBackground(Integer... params) {
-
//压缩图片
-
File file =
new File(BitmapUtil.compressImage(filePath));
-
return file;
-
}
-
-
@Override
-
protected void onPostExecute(File file) {
-
super.onPostExecute(file);
-
RequestBody requestBody = RequestBody.create(MediaType.parse(
"image/png"), file);
-
MultipartBody.Part part = MultipartBody.Part.createFormData(
"file", file.getName(), requestBody);
-
RetrofitFactory.getInstence().API()
-
.imageUpload( part)
-
.subscribeOn(Schedulers.io())
-
.observeOn(AndroidSchedulers.mainThread())
-
.subscribe(observer);
-
}
-
}.execute();
-
-
-
}
-
-
/**
-
* 上传多张照片
-
*
-
* @param mFilesPath 图片本地路径
-
* @param observer
-
*/
-
public static void uploadImages(final ArrayList<String> mFilesPath, final Observer observer) {
-
new AsyncTask<Integer, Integer, List<File>>() {
-
@Override
-
protected List<File> doInBackground(Integer... params) {
-
//压缩图片
-
final List<File> files =
new ArrayList<>();
-
for (String path : mFilesPath) {
-
File file =
new File(BitmapUtil.compressImage(path));
-
files.add(file);
-
-
}
-
return files;
-
}
-
-
@Override
-
protected void onPostExecute(List<File> files) {
-
super.onPostExecute(files);
-
List<MultipartBody.Part> xx = filesToMultipartBodyParts(files);
-
RetrofitFactory.getInstence().API()
-
.imagesUpload( xx)
-
.subscribeOn(Schedulers.io())
-
.observeOn(AndroidSchedulers.mainThread())
-
.subscribe(observer);
-
}
-
}.execute();
-
-
-
}
-
-
/**
-
* @param files 多图片文件转表单
-
* @return
-
*/
-
public
static List<MultipartBody.Part> filesToMultipartBodyParts(List<File> files) {
-
List<MultipartBody.Part> parts =
new ArrayList<>(files.size());
-
for (File file : files) {
-
RequestBody requestBody = RequestBody.create(MediaType.parse(
"image/png"), file);
-
MultipartBody.Part part = MultipartBody.Part.createFormData(
"files", file.getName(), requestBody);
-
parts.add(part);
-
}
-
return parts;
-
}
-
}
使用方法
上传单张图片
-
-
public void upload(){
-
String filepath=
"图片本地路径";
-
UploadUtil.uploadImage(filepath,
new Observer() {
-
@Override
-
public void onSubscribe(Disposable d) {
-
-
}
-
-
@Override
-
public void onNext(Object o) {
-
//返回结果
-
}
-
-
@Override
-
public void onError(Throwable e) {
-
//上传失败
-
}
-
-
@Override
-
public void onComplete() {
-
-
}
-
});
-
}
上传多张图片
-
public void uploads(){
-
ArrayList<String> listFilePath=
new ArrayList<>();
-
listFilePath.add(
"图片1路径");
-
listFilePath.add(
"图片2路径");
-
UploadUtil.uploadImages(listFilePath,
new Observer() {
-
@Override
-
public void onSubscribe(Disposable d) {
-
-
}
-
-
@Override
-
public void onNext(Object o) {
-
-
}
-
-
@Override
-
public void onError(Throwable e) {
-
-
}
-
-
@Override
-
public void onComplete() {
-
-
}
-
});
-
}
到了这里大功告成了哦!