Android实现图片压缩并上传到服务器

转载自 http://write.blog.csdn.net/postedit/70599061

最近公司又叫开发了一个新项目,这个项目中上传图片用的蛮多的,于是整理一下,记录自己的心得体验

刚入手的时候,对于图片的大小还没有概念,(以前上传图片都是用户头像,对大小没什么要求),心想之间上传就是了,和以前一样,那成想到,上传一张图片还好,上传多张图片慢成狗,这时候,我还是无动于衷,直到有一天,服务器端也意识到了,图片太大对数据库没好处,只会让数据库变得无比庞大,限制的上传图片的大小,单张图片最大为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


  
  
  1. /**
  2. * Created by yemao on 2017/3/15.
  3. * 关于图片的工具类
  4. */
  5. public class BitmapUtil {
  6. private static String PHOTO_FILE_NAME = "PMSManagerPhoto";
  7. /**
  8. * 获取图片的旋转角度
  9. *
  10. * @param filePath
  11. * @return
  12. */
  13. public static int getRotateAngle(String filePath) {
  14. int rotate_angle = 0;
  15. try {
  16. ExifInterface exifInterface = new ExifInterface(filePath);
  17. int orientation = exifInterface.getAttributeInt(ExifInterface.TAG_ORIENTATION, ExifInterface.ORIENTATION_NORMAL);
  18. switch (orientation) {
  19. case ExifInterface.ORIENTATION_ROTATE_90:
  20. rotate_angle = 90;
  21. break;
  22. case ExifInterface.ORIENTATION_ROTATE_180:
  23. rotate_angle = 180;
  24. break;
  25. case ExifInterface.ORIENTATION_ROTATE_270:
  26. rotate_angle = 270;
  27. break;
  28. }
  29. } catch (IOException e) {
  30. e.printStackTrace();
  31. }
  32. return rotate_angle;
  33. }
  34. /**
  35. * 旋转图片角度
  36. *
  37. * @param angle
  38. * @param bitmap
  39. * @return
  40. */
  41. public static Bitmap setRotateAngle(int angle, Bitmap bitmap) {
  42. if (bitmap != null) {
  43. Matrix m = new Matrix();
  44. m.postRotate(angle);
  45. bitmap = Bitmap.createBitmap(bitmap, 0, 0, bitmap.getWidth(),
  46. bitmap.getHeight(), m, true);
  47. return bitmap;
  48. }
  49. return bitmap;
  50. }
  51. //转换为圆形状的bitmap
  52. public static Bitmap createCircleImage(Bitmap source) {
  53. int length = source.getWidth() < source.getHeight() ? source.getWidth() : source.getHeight();
  54. Paint paint = new Paint();
  55. paint.setAntiAlias( true);
  56. Bitmap target = Bitmap.createBitmap(length, length, Bitmap.Config.ARGB_8888);
  57. Canvas canvas = new Canvas(target);
  58. canvas.drawCircle(length / 2, length / 2, length / 2, paint);
  59. paint.setXfermode( new PorterDuffXfermode(PorterDuff.Mode.SRC_IN));
  60. canvas.drawBitmap(source, 0, 0, paint);
  61. return target;
  62. }
  63. /**
  64. * 图片压缩-质量压缩
  65. *
  66. * @param filePath 源图片路径
  67. * @return 压缩后的路径
  68. */
  69. public static String compressImage(String filePath) {
  70. //原文件
  71. File oldFile = new File(filePath);
  72. //压缩文件路径 照片路径/
  73. String targetPath = oldFile.getPath();
  74. int quality = 50; //压缩比例0-100
  75. Bitmap bm = getSmallBitmap(filePath); //获取一定尺寸的图片
  76. int degree = getRotateAngle(filePath); //获取相片拍摄角度
  77. if (degree != 0) { //旋转照片角度,防止头像横着显示
  78. bm = setRotateAngle(degree,bm);
  79. }
  80. File outputFile = new File(targetPath);
  81. try {
  82. if (!outputFile.exists()) {
  83. outputFile.getParentFile().mkdirs();
  84. //outputFile.createNewFile();
  85. } else {
  86. outputFile.delete();
  87. }
  88. FileOutputStream out = new FileOutputStream(outputFile);
  89. bm.compress(Bitmap.CompressFormat.JPEG, quality, out);
  90. out.close();
  91. } catch (Exception e) {
  92. e.printStackTrace();
  93. return filePath;
  94. }
  95. return outputFile.getPath();
  96. }
  97. /**
  98. * 根据路径获得图片信息并按比例压缩,返回bitmap
  99. */
  100. public static Bitmap getSmallBitmap(String filePath) {
  101. final BitmapFactory.Options options = new BitmapFactory.Options();
  102. options.inJustDecodeBounds = true; //只解析图片边沿,获取宽高
  103. BitmapFactory.decodeFile(filePath, options);
  104. // 计算缩放比
  105. options.inSampleSize = calculateInSampleSize(options, 480, 800);
  106. // 完整解析图片返回bitmap
  107. options.inJustDecodeBounds = false;
  108. return BitmapFactory.decodeFile(filePath, options);
  109. }
  110. public static int calculateInSampleSize(BitmapFactory.Options options,
  111. int reqWidth, int reqHeight) {
  112. final int height = options.outHeight;
  113. final int width = options.outWidth;
  114. int inSampleSize = 1;
  115. if (height > reqHeight || width > reqWidth) {
  116. final int heightRatio = Math.round(( float) height / ( float) reqHeight);
  117. final int widthRatio = Math.round(( float) width / ( float) reqWidth);
  118. inSampleSize = heightRatio < widthRatio ? heightRatio : widthRatio;
  119. }
  120. return inSampleSize;
  121. }
  122. }
//简单的封装了一下网络请求工具类RetorfitFactory


  
  
  1. public class RetrofitFactory {
  2. private static RetrofitFactory mRetrofitFactory;
  3. private static APIFunction mAPIFunction;
  4. private RetrofitFactory(){
  5. OkHttpClient mOkHttpClient= new OkHttpClient.Builder()
  6. .connectTimeout(HttpConfig.HTTP_TIME, TimeUnit.SECONDS)
  7. .readTimeout(HttpConfig.HTTP_TIME, TimeUnit.SECONDS)
  8. .writeTimeout(HttpConfig.HTTP_TIME, TimeUnit.SECONDS)
  9. .build();
  10. Retrofit mRetrofit= new Retrofit.Builder()
  11. .baseUrl(HttpConfig.BASE_URL)
  12. .addConverterFactory(GsonConverterFactory.create()) //添加gson转换器
  13. .addCallAdapterFactory(RxJava2CallAdapterFactory.create()) //添加rxjava转换器
  14. .client(mOkHttpClient)
  15. .build();
  16. mAPIFunction=mRetrofit.create(APIFunction.class);
  17. }
  18. public static RetrofitFactory getInstence(){
  19. if (mRetrofitFactory== null){
  20. synchronized (RetrofitFactory.class) {
  21. if (mRetrofitFactory == null)
  22. mRetrofitFactory = new RetrofitFactory();
  23. }
  24. }
  25. return mRetrofitFactory;
  26. }
  27. public APIFunction API(){
  28. return mAPIFunction;
  29. }
  30. }

代理API接口类APIFunction


  
  
  1. /**
  2. * @author yemao
  3. * @date 2017/4/9
  4. * @description API接口!
  5. */
  6. public interface APIFunction {
  7. //上传单张图片
  8. @POST( "服务器地址")
  9. Observable<Object> imageUpload(@Part() MultipartBody.Part img);
  10. //上传多张图片
  11. @POST( "服务器地址")
  12. Observable<Object> imagesUpload(@Part() List<MultipartBody.Part> imgs);
  13. }




上传图片的的工具类


  
  
  1. package com.yr.example.utils;
  2. import android.content.Context;
  3. import android.os.AsyncTask;
  4. import com.yr.example.http.RetrofitFactory;
  5. import java.io.File;
  6. import java.io.IOException;
  7. import java.util.ArrayList;
  8. import java.util.List;
  9. import io.reactivex.Observable;
  10. import io.reactivex.Observer;
  11. import io.reactivex.android.schedulers.AndroidSchedulers;
  12. import io.reactivex.schedulers.Schedulers;
  13. import okhttp3.MediaType;
  14. import okhttp3.MultipartBody;
  15. import okhttp3.RequestBody;
  16. /**
  17. * @author yemao
  18. * @date 2017/4/17
  19. * @description null!
  20. */
  21. public class UploadUtil {
  22. /**
  23. * 上传单张图片
  24. *
  25. * @param filePath 图片本地路径
  26. * @param observer 观察者
  27. * @throws IOException
  28. */
  29. public static void uploadImage(final String filePath, final Observer observer) {
  30. new AsyncTask<Integer, Integer, File>() {
  31. @Override
  32. protected File doInBackground(Integer... params) {
  33. //压缩图片
  34. File file = new File(BitmapUtil.compressImage(filePath));
  35. return null;
  36. }
  37. @Override
  38. protected void onPostExecute(File file) {
  39. super.onPostExecute(file);
  40. RequestBody requestBody = RequestBody.create(MediaType.parse( "image/png"), file);
  41. MultipartBody.Part part = MultipartBody.Part.createFormData( "file", file.getName(), requestBody);
  42. RetrofitFactory.getInstence().API()
  43. .imageUpload( part)
  44. .subscribeOn(Schedulers.io())
  45. .observeOn(AndroidSchedulers.mainThread())
  46. .subscribe(observer);
  47. }
  48. }.execute();
  49. }
  50. /**
  51. * 上传多张照片
  52. *
  53. * @param mFilesPath 图片本地路径
  54. * @param observer
  55. */
  56. public static void uploadImages(final ArrayList<String> mFilesPath, final Observer observer) {
  57. new AsyncTask<Integer, Integer, List<File>>() {
  58. @Override
  59. protected List<File> doInBackground(Integer... params) {
  60. //压缩图片
  61. final List<File> files = new ArrayList<>();
  62. for (String path : mFilesPath) {
  63. File file = new File(BitmapUtil.compressImage(path));
  64. files.add(file);
  65. }
  66. return files;
  67. }
  68. @Override
  69. protected void onPostExecute(List<File> files) {
  70. super.onPostExecute(files);
  71. List<MultipartBody.Part> xx = filesToMultipartBodyParts(files);
  72. RetrofitFactory.getInstence().API()
  73. .imagesUpload( xx)
  74. .subscribeOn(Schedulers.io())
  75. .observeOn(AndroidSchedulers.mainThread())
  76. .subscribe(observer);
  77. }
  78. }.execute();
  79. }
  80. /**
  81. * @param files 多图片文件转表单
  82. * @return
  83. */
  84. public static List<MultipartBody.Part> filesToMultipartBodyParts(List<File> files) {
  85. List<MultipartBody.Part> parts = new ArrayList<>(files.size());
  86. for (File file : files) {
  87. RequestBody requestBody = RequestBody.create(MediaType.parse( "image/png"), file);
  88. MultipartBody.Part part = MultipartBody.Part.createFormData( "files", file.getName(), requestBody);
  89. parts.add(part);
  90. }
  91. return parts;
  92. }
  93. }

使用方法

上传单张图片


  
  
  1. public void upload(){
  2. String filepath= "图片本地路径";
  3. UploadUtil.uploadImage(filepath, new Observer() {
  4. @Override
  5. public void onSubscribe(Disposable d) {
  6. }
  7. @Override
  8. public void onNext(Object o) {
  9. //返回结果
  10. }
  11. @Override
  12. public void onError(Throwable e) {
  13. //上传失败
  14. }
  15. @Override
  16. public void onComplete() {
  17. }
  18. });
  19. }

上传多张图片


  
  
  1. public void uploads(){
  2. ArrayList<String> listFilePath= new ArrayList<>();
  3. listFilePath.add( "图片1路径");
  4. listFilePath.add( "图片2路径");
  5. UploadUtil.uploadImages(listFilePath, new Observer() {
  6. @Override
  7. public void onSubscribe(Disposable d) {
  8. }
  9. @Override
  10. public void onNext(Object o) {
  11. }
  12. @Override
  13. public void onError(Throwable e) {
  14. }
  15. @Override
  16. public void onComplete() {
  17. }
  18. });
  19. }

到了这里大功告成了哦!



猜你喜欢

转载自blog.csdn.net/xzytl60937234/article/details/82826728