├── .idea
└── vcs.xml
├── README.md
├── app
├── .gitignore
├── build.gradle
└── src
│ └── main
│ ├── AndroidManifest.xml
│ ├── java
│ └── com
│ │ └── wgd
│ │ └── myimagelibrary
│ │ ├── App.java
│ │ ├── BagImageActivity.java
│ │ ├── BitmapFromUriUtil.java
│ │ ├── ImageGetInfoUtil.java
│ │ ├── ImageInfoBean.java
│ │ ├── MainActivity.java
│ │ └── PathFromUriUtil.java
│ └── res
│ ├── drawable-v24
│ └── ic_launcher_foreground.xml
│ ├── drawable
│ └── ic_launcher_background.xml
│ ├── layout
│ ├── activity_image_bag.xml
│ └── activity_main.xml
│ ├── mipmap-anydpi-v26
│ ├── ic_launcher.xml
│ └── ic_launcher_round.xml
│ ├── mipmap-hdpi
│ ├── ic_launcher.png
│ └── ic_launcher_round.png
│ ├── mipmap-mdpi
│ ├── ic_launcher.png
│ └── ic_launcher_round.png
│ ├── mipmap-xhdpi
│ ├── ic_launcher.png
│ └── ic_launcher_round.png
│ ├── mipmap-xxhdpi
│ ├── ic_launcher.png
│ └── ic_launcher_round.png
│ ├── mipmap-xxxhdpi
│ ├── ic_launcher.png
│ └── ic_launcher_round.png
│ ├── values
│ ├── colors.xml
│ ├── strings.xml
│ └── styles.xml
│ └── xml
│ └── file_paths_public.xml
├── build.gradle
├── gdcplibrary
├── build.gradle
└── src
│ ├── androidTest
│ └── java
│ │ └── com
│ │ └── wgd
│ │ └── gdcp
│ │ └── gdcplibrary
│ │ └── ExampleInstrumentedTest.java
│ ├── main
│ ├── AndroidManifest.xml
│ ├── java
│ │ └── com
│ │ │ └── wgd
│ │ │ └── gdcp
│ │ │ └── gdcplibrary
│ │ │ ├── GDBitmapUtil.java
│ │ │ ├── GDCompress.java
│ │ │ ├── GDCompressA.java
│ │ │ ├── GDCompressC.java
│ │ │ ├── GDCompressImageListener.java
│ │ │ ├── GDCompressImageListenerA.java
│ │ │ ├── GDCompressImageS.java
│ │ │ ├── GDCompressImageSListener.java
│ │ │ ├── GDCompressUtil.java
│ │ │ ├── GDConfig.java
│ │ │ ├── GDImageBean.java
│ │ │ ├── GDTools.java
│ │ │ ├── ImageUtils.java
│ │ │ └── thread
│ │ │ └── ThreadManager.java
│ ├── jniLibs
│ │ ├── arm64-v8a
│ │ │ ├── README.md
│ │ │ └── libgdimage.so
│ │ ├── armeabi-v7a
│ │ │ ├── README.md
│ │ │ └── libgdimage.so
│ │ └── armeabi
│ │ │ ├── README.md
│ │ │ └── libgdimage.so
│ └── res
│ │ └── values
│ │ └── strings.xml
│ └── test
│ └── java
│ └── com
│ └── wgd
│ └── gdcp
│ └── gdcplibrary
│ └── ExampleUnitTest.java
├── gradle.properties
├── gradle
└── wrapper
│ ├── gradle-wrapper.jar
│ └── gradle-wrapper.properties
└── settings.gradle
/.idea/vcs.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # ImageCompress
2 | ImageCompress是基于libjpeg-turbo来进行图片的压缩,它的优点在于相较于libjpeg来说压缩时间大大的缩短了(4.5M的图片压缩完耗时约1.2秒),而相较于Android系统的图片压缩来说ImageCompress在图片处理的过程使用了哈弗曼表,这大大的提高了相同体积下图片的清晰度。
3 |
4 | 查看使用与效果可以去这里:https://blog.csdn.net/hh7181521/article/details/81014839
5 |
6 |
7 | 特别声明:终于有时间来处理这个了,这次优化了OOM问题,总体上讲提供了两种方式(1、耗时短但OOM几率大;2、耗时长但OOM几率很小)
8 |
9 |
10 | 一:添加依赖
11 | 1、 对于Android Studio的用户,可以选择添加:
12 |
13 | compile 'com.wgd.gdcp.gdcplibrary:ImageCompress:1.0.10'
14 | 或
15 | implementation 'com.wgd.gdcp.gdcplibrary:ImageCompress:1.0.10'
16 | 如果报错的话可以在项目的build.gradle中加入
17 |
18 | allprojects {
19 | repositories {
20 | maven { url "https://dl.bintray.com/wangruijun/maven" }
21 | jcenter()
22 | }
23 | }
24 |
25 | 二:使用图片压缩
26 | (1)、直接用lib库压缩,不会调试旋转角度、图片分辨率大小等
27 |
28 | 强调:这里runOnUiThread 方法可以不用,但要注意的是:虽然jar包中处理了,但不保证一定是在主线程中回调。
29 |
30 |
31 | // path 为图片地址,savePath是图片要保存的地址
32 | new GDCompress(MainActivity.this, path, savePath, new GDCompressImageListener() {
33 | @Override
34 | public void OnSuccess(String path) {
35 | MainActivity.this.runOnUiThread(new Runnable() {
36 | @Override
37 | public void run() {
38 |
39 | }
40 | });
41 | }
42 |
43 | @Override
44 | public void OnError(int code, String errorMsg) {
45 |
46 | }
47 | });
48 |
49 | (2)、单个图片压缩,多线程模式
50 | new GDCompressC(MainActivity.this,
51 | new GDConfig().setmPath(tempCompressImgPath), new GDCompressImageListener() {
52 | @Override
53 | public void OnSuccess(String path) {
54 | MainActivity.this.runOnUiThread(new Runnable() {
55 | @Override
56 | public void run() {
57 |
58 | }
59 | });
60 | }
61 |
62 | @Override
63 | public void OnError(int code, String errorMsg) {
64 |
65 | }
66 | });
67 |
68 | (3)、单个图片压缩,单线程模式
69 | String tempCompressImgPath = mSelectedPath.get(0);//
70 | GDImageBean imageBeana = new GDImageBean();
71 | imageBeana.setmGDConfig(new GDConfig().setmPath(tempCompressImgPath));
72 | new GDCompressA(MainActivity.this, imageBeana
73 | , new GDCompressImageListenerA() {
74 | GDCompressImageListener() {
75 | @Override
76 | public void OnSuccess(GDImageBean gdImageBean) {
77 | MainActivity.this.runOnUiThread(new Runnable() {
78 | @Override
79 | public void run() {
80 |
81 | }
82 | });
83 | }
84 |
85 | @Override
86 | public void OnError(GDImageBean gdImageBean) {
87 |
88 | }
89 | });
90 |
91 | (4)、批量压缩,多线程模式,速度快,但OOM几率大
92 | GDCompressC gdCompressC = new GDCompressC(MainActivity.this, new GDCompressImageListener() {
93 | @Override
94 | public void OnSuccess(String path) {
95 | Log.i(TAG, "OnSuccess: ===批量=====图片压缩=====btn_img_c2========path==" + path);
96 | }
97 |
98 | @Override
99 | public void OnError(int code, String errorMsg) {
100 | Log.i(TAG, "OnError: ===批量=====图片压缩=====btn_img_c2==========");
101 | }
102 | });
103 | for (int i = 0; i < mSelected.size(); i++) {
104 | gdCompressC.start(new GDConfig().setmPath(mSelectedPath.get(i)));
105 | }
106 |
107 | (5)、批量压缩,单线程模式,速度慢,但OOM几率小很多
108 | GDCompressA gdCompressA = new GDCompressA(MainActivity.this, new GDCompressImageListenerA() {
109 | @Override
110 | public void OnSuccess(GDImageBean gdImageBean) {
111 | Log.i(TAG, "OnSuccess: ===批量=====图片压缩=====btn_img_c3========path==" + gdImageBean.getmGDConfig().getmPath());
112 | }
113 |
114 | @Override
115 | public void OnError(GDImageBean gdImageBean) {
116 | Log.i(TAG, "OnError: ===批量=====图片压缩=====btn_img_c3==========");
117 | }
118 | });
119 | for (int i = 0; i < mSelected.size(); i++) {
120 | GDImageBean imageBeana = new GDImageBean();
121 | imageBeana.setmGDConfig(new GDConfig().setmPath(mSelectedPath.get(i)));
122 | gdCompressA.start(imageBeana);
123 | }
124 |
125 | (6)、多个图片同时压缩(GDConfig中属性下边统一解释)
126 | 注:这里OnError方法中返回的数据GDImageBean中通过code字段来判断图片是否成功压缩;而OnSuccess方法中所有的图片都是压缩完成的(即只要有一 个图片压缩失败都是回调OnError方法)。
127 | List imageBeans = new ArrayList<>();
128 | for (int i = 0; i < selectList.size(); i++) {
129 | final String imgpath = selectList.get(i).getPath();
130 | imageBeans.add(new GDImageBean(new GDConfig().setmPath(imgpath)));
131 | }
132 | new GDCompressImageS(SendCircleActivity.this, imageBeans, new GDCompressImageSListener() { @Override
133 | public void OnSuccess(List imageBeanList) {
134 |
135 | }
136 |
137 | @Override
138 | public void OnError(List imageBeanList) {
139 |
140 | }
141 | });
142 |
143 | (7)、GDConfig中属性统一解释
144 | new GDConfig()
145 | .setmPath(tempCompressImgPath)//要压缩图片的原路径
146 | .setSavePath(tempCompressImgPath)//压缩图片的保存路径,如果不设置将替换原文件
147 | .setChangeWH(true)//是否要进行调整图片分辨率以压缩到更小
148 | .setWidth(720)//需要调整分辨率的时候有效,压缩后的宽度(按比例计算后的,而不是直接使用这个)
149 | .setHeight(1280)//需要调整分辨率的时候有效,压缩后的高度(按比例计算后的,而不是直接使用这个)
150 |
151 |
152 | 联系作者:QQ:1772889689 邮箱:1772889689@qq.com 微信:gdihh8180
153 | 注:联系请注明联系目的
154 |
--------------------------------------------------------------------------------
/app/.gitignore:
--------------------------------------------------------------------------------
1 | /build
2 |
--------------------------------------------------------------------------------
/app/build.gradle:
--------------------------------------------------------------------------------
1 | apply plugin: 'com.android.application'
2 |
3 | android {
4 | compileSdkVersion 27
5 | defaultConfig {
6 | applicationId "com.wgd.myimagelibrary"
7 | minSdkVersion 15
8 | targetSdkVersion 27
9 | versionCode 1
10 | versionName "1.0"
11 | testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
12 | }
13 | buildTypes {
14 | release {
15 | minifyEnabled false
16 | proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
17 | }
18 | }
19 | }
20 |
21 | dependencies {
22 | implementation fileTree(include: ['*.jar'], dir: 'libs')
23 | implementation 'com.android.support:appcompat-v7:27.1.1'
24 | implementation 'com.android.support.constraint:constraint-layout:1.1.2'
25 | testImplementation 'junit:junit:4.12'
26 | androidTestImplementation 'com.android.support.test:runner:1.0.2'
27 | androidTestImplementation 'com.android.support.test.espresso:espresso-core:3.0.2'
28 | implementation 'com.google.code.gson:gson:2.8.2'
29 | /*6.0权限申请依赖库 RxPermissions 和 RxJava2*/
30 | //RxPermissions
31 | implementation 'com.tbruyelle.rxpermissions2:rxpermissions:0.9.4@aar'
32 | //RxJava2
33 | implementation 'io.reactivex.rxjava2:rxjava:2.+'
34 |
35 | /* View注解依赖库 butterknife 项目地址:https://github.com/JakeWharton/butterknife*/
36 | implementation 'com.jakewharton:butterknife:8.8.1'
37 | annotationProcessor 'com.jakewharton:butterknife-compiler:8.8.1'
38 | /* 知乎开源的图片选择库 使用uri */
39 | implementation 'com.zhihu.android:matisse:0.+'
40 | /* 图片加载框架 */
41 | // implementation 'com.github.bumptech.glide:glide:3.8.0'
42 | implementation 'com.github.bumptech.glide:glide:3.+'
43 | annotationProcessor 'com.github.bumptech.glide:compiler:4.3.1'
44 | implementation 'com.android.support:multidex:1.0.1'
45 | implementation project(':gdcplibrary')
46 | }
47 |
--------------------------------------------------------------------------------
/app/src/main/AndroidManifest.xml:
--------------------------------------------------------------------------------
1 |
2 |
4 |
5 |
6 |
7 |
8 |
9 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
31 |
34 |
35 |
36 |
37 |
38 |
39 |
--------------------------------------------------------------------------------
/app/src/main/java/com/wgd/myimagelibrary/App.java:
--------------------------------------------------------------------------------
1 | package com.wgd.myimagelibrary;
2 |
3 | import android.support.multidex.MultiDexApplication;
4 |
5 | public class App extends MultiDexApplication {
6 |
7 |
8 |
9 | }
10 |
--------------------------------------------------------------------------------
/app/src/main/java/com/wgd/myimagelibrary/BagImageActivity.java:
--------------------------------------------------------------------------------
1 | package com.wgd.myimagelibrary;
2 |
3 | import android.app.Activity;
4 | import android.content.Intent;
5 | import android.graphics.BitmapFactory;
6 | import android.os.Bundle;
7 | import android.support.annotation.Nullable;
8 | import android.support.v7.app.AppCompatActivity;
9 | import android.widget.ImageView;
10 | import android.widget.TextView;
11 |
12 | //import butterknife.BindView;
13 | //import butterknife.ButterKnife;
14 |
15 | public class BagImageActivity extends AppCompatActivity {
16 |
17 | // @BindView(R.id.image)
18 | // ImageView image ;
19 | // @BindView(R.id.txt_image_info)
20 | // TextView txt_image_info ;
21 |
22 | public static void start(Activity activity, String path){
23 | Intent intent = new Intent(activity, BagImageActivity.class);
24 | intent.putExtra("path", path);
25 | activity.startActivity(intent);
26 | }
27 |
28 | @Override
29 | protected void onCreate(@Nullable Bundle savedInstanceState) {
30 | super.onCreate(savedInstanceState);
31 | setContentView(R.layout.activity_image_bag);
32 | // ButterKnife.bind(this);
33 | String path = getIntent().getStringExtra("path");
34 | // image.setImageBitmap(BitmapFactory
35 | // .decodeFile(path));
36 |
37 |
38 |
39 |
40 | // Bitmap bitmap = BitmapFactory.decodeFile(path);
41 |
42 | // ImageInfoBean imageInfoBean = new ImageGetInfoUtil().getImageInfo(path);
43 | //
44 | // txt_image_info.setText("imageWidth=" + imageInfoBean.getWightHeightSize()[0] + "\n"
45 | // + "imageHeight=" + imageInfoBean.getWightHeightSize()[1] + "\n"
46 | // + "imageSize=" + imageInfoBean.getFileSize() + "\n"
47 | //// + "imageWidthExif=" + imageInfo.getmExifInterface().getAttribute(ExifInterface.TAG_IMAGE_LENGTH ) + "\n"
48 | //// + "imageHeightExif=" + imageInfo.getmExifInterface().getAttribute(ExifInterface.TAG_IMAGE_LENGTH ) + "\n"
49 | // + "" );
50 |
51 | // ImageInfo imageInfo = ImageInfoUtils.getImageInfo(BagImageActivity.this, bitmap);
52 | // txt_image_info.setText("imageWidth=" + imageInfo.getImageWidth() + "\n"
53 | // + "imageHeight=" + imageInfo.getImageHeight() + "\n"
54 | // + "imageSize=" + imageInfo.getImageSize() + "\n"
55 | // + "imageWidthExif=" + imageInfo.getmExifInterface().getAttribute(ExifInterface.TAG_IMAGE_WIDTH ) + "\n"
56 | // + "imageHeightExif=" + imageInfo.getmExifInterface().getAttribute(ExifInterface.TAG_IMAGE_LENGTH ) + "\n"
57 | // + "" );
58 |
59 | }
60 | }
61 |
--------------------------------------------------------------------------------
/app/src/main/java/com/wgd/myimagelibrary/BitmapFromUriUtil.java:
--------------------------------------------------------------------------------
1 | package com.wgd.myimagelibrary;
2 |
3 | import android.content.Context;
4 | import android.graphics.Bitmap;
5 | import android.net.Uri;
6 | import android.provider.MediaStore;
7 | import android.util.Log;
8 |
9 | public class BitmapFromUriUtil {
10 |
11 | public static Bitmap getBitmapFromUri(Context context, Uri uri)
12 | {
13 | try
14 | {
15 | // 读取uri所在的图片
16 | Bitmap bitmap = MediaStore.Images.Media.getBitmap(context.getContentResolver(), uri);
17 | return bitmap;
18 | }
19 | catch (Exception e)
20 | {
21 | Log.e("[Android]", e.getMessage());
22 | Log.e("[Android]", "目录为:" + uri);
23 | e.printStackTrace();
24 | return null;
25 | }
26 | }
27 |
28 | }
29 |
--------------------------------------------------------------------------------
/app/src/main/java/com/wgd/myimagelibrary/ImageGetInfoUtil.java:
--------------------------------------------------------------------------------
1 | package com.wgd.myimagelibrary;
2 |
3 | import android.graphics.Bitmap;
4 | import android.graphics.BitmapFactory;
5 | import android.os.Environment;
6 |
7 | import java.io.File;
8 |
9 | public class ImageGetInfoUtil {
10 |
11 | public ImageInfoBean getImageInfo(Bitmap bitmap){
12 | ImageInfoBean imageInfoBean = new ImageInfoBean();
13 | try {
14 | int[] originSize = new int[2];
15 | originSize[0] = bitmap.getWidth();
16 | originSize[1] = bitmap.getHeight();
17 | String path = Environment.getExternalStorageDirectory() + "/imageinfo/cache01.jpg" ;
18 | imageInfoBean = new ImageInfoBean(originSize, "", new File(path).length() >> 10);
19 | }catch (Exception e){e.printStackTrace();}
20 | return imageInfoBean;
21 | }
22 |
23 | public ImageInfoBean getImageInfo(String path){
24 | int[] originSize = computeSize(path);
25 | return new ImageInfoBean(originSize, path, new File(path).length() >> 10);
26 | }
27 |
28 | private int[] computeSize(String srcImg) {
29 | int[] size = new int[2];
30 |
31 | BitmapFactory.Options options = new BitmapFactory.Options();
32 | options.inJustDecodeBounds = true;
33 | options.inSampleSize = 1;
34 |
35 | BitmapFactory.decodeFile(srcImg, options);
36 | size[0] = options.outWidth;
37 | size[1] = options.outHeight;
38 |
39 | return size;
40 | }
41 |
42 | }
43 |
--------------------------------------------------------------------------------
/app/src/main/java/com/wgd/myimagelibrary/ImageInfoBean.java:
--------------------------------------------------------------------------------
1 | package com.wgd.myimagelibrary;
2 |
3 | public class ImageInfoBean {
4 |
5 | private int[] wightHeightSize;
6 | private String filepath ;
7 | private long fileSize ;
8 |
9 | public ImageInfoBean(){}
10 | public ImageInfoBean(int[] wightHeightSize, String filepath, long fileSize){
11 | this.wightHeightSize = wightHeightSize;
12 | this.filepath = filepath;
13 | this.fileSize = fileSize;
14 | }
15 |
16 | public int[] getWightHeightSize() {
17 | return wightHeightSize;
18 | }
19 |
20 | public void setWightHeightSize(int[] wightHeightSize) {
21 | this.wightHeightSize = wightHeightSize;
22 | }
23 |
24 | public String getFilepath() {
25 | return filepath;
26 | }
27 |
28 | public void setFilepath(String filepath) {
29 | this.filepath = filepath;
30 | }
31 |
32 | public long getFileSize() {
33 | return fileSize;
34 | }
35 |
36 | public void setFileSize(long fileSize) {
37 | this.fileSize = fileSize;
38 | }
39 | }
40 |
--------------------------------------------------------------------------------
/app/src/main/java/com/wgd/myimagelibrary/MainActivity.java:
--------------------------------------------------------------------------------
1 | package com.wgd.myimagelibrary;
2 |
3 | import android.Manifest;
4 | import android.app.ProgressDialog;
5 | import android.content.Intent;
6 | import android.content.res.Resources;
7 | import android.graphics.Bitmap;
8 | import android.graphics.BitmapFactory;
9 | import android.net.Uri;
10 | import android.os.Bundle;
11 | import android.support.v7.app.AppCompatActivity;
12 | import android.util.Log;
13 | import android.view.View;
14 | import android.widget.Button;
15 | import android.widget.ImageView;
16 | import android.widget.TextView;
17 | import android.widget.Toast;
18 |
19 | import com.bumptech.glide.Glide;
20 | import com.tbruyelle.rxpermissions2.RxPermissions;
21 | import com.wgd.gdcp.gdcplibrary.GDCompress;
22 | import com.wgd.gdcp.gdcplibrary.GDCompressA;
23 | import com.wgd.gdcp.gdcplibrary.GDCompressC;
24 | import com.wgd.gdcp.gdcplibrary.GDCompressImageListener;
25 | import com.wgd.gdcp.gdcplibrary.GDCompressImageListenerA;
26 | import com.wgd.gdcp.gdcplibrary.GDCompressImageS;
27 | import com.wgd.gdcp.gdcplibrary.GDCompressImageSListener;
28 | import com.wgd.gdcp.gdcplibrary.GDConfig;
29 | import com.wgd.gdcp.gdcplibrary.GDImageBean;
30 | import com.wgd.gdcp.gdcplibrary.GDTools;
31 | import com.wgd.gdcp.gdcplibrary.ImageUtils;
32 | import com.zhihu.matisse.Matisse;
33 | import com.zhihu.matisse.MimeType;
34 | import com.zhihu.matisse.engine.impl.GlideEngine;
35 | import com.zhihu.matisse.internal.entity.CaptureStrategy;
36 |
37 | import java.util.ArrayList;
38 | import java.util.List;
39 |
40 | import butterknife.BindView;
41 | import butterknife.ButterKnife;
42 | import butterknife.OnClick;
43 | import io.reactivex.Observer;
44 | import io.reactivex.disposables.Disposable;
45 | /*
46 | *
47 | * //gradlew clean build bintrayUpload -PbintrayUser=wangruijun -PbintrayKey=a0d662943bb4c5ae83cd3d539113c91b04570499 -PdryRun=false
48 | * */
49 | public class MainActivity extends AppCompatActivity {
50 |
51 | private static final String TAG = "GDCimage";
52 | @BindView(R.id.btn_select_img)
53 | Button selectImg ;
54 | @BindView(R.id.image_view)
55 | ImageView image_view ;
56 | @BindView(R.id.btn_img_crop)
57 | Button btn_img_crop ;
58 | @BindView(R.id.image_view_c2)
59 | ImageView image_view_c2 ;
60 | @BindView(R.id.image_view_c3)
61 | ImageView image_view_c3 ;
62 | @BindView(R.id.image_view_crop)
63 | ImageView image_view_crop ;
64 | @BindView(R.id.txt_yuantu)
65 | TextView txt_yuantu ;
66 | @BindView(R.id.txt_crop)
67 | TextView txt_crop ;
68 | @BindView(R.id.txt_c2)
69 | TextView txt_c2 ;
70 | @BindView(R.id.txt_c3)
71 | TextView txt_c3 ;
72 |
73 | private final int REQUEST_CODE_CHOOSE= 1001 ;
74 |
75 | @Override
76 | protected void onCreate(Bundle savedInstanceState) {
77 | super.onCreate(savedInstanceState);
78 | setContentView(R.layout.activity_main);
79 | ButterKnife.bind(this);
80 | }
81 |
82 |
83 | @OnClick({R.id.btn_select_img, R.id.btn_img_crop, R.id.image_view, R.id.image_view_crop, R.id.btn_img_more
84 | ,R.id.btn_img_c2,R.id.btn_img_c3
85 | })
86 | public void onClick(View view) {
87 | switch (view.getId()){
88 | case R.id.btn_select_img :
89 | getRxPermissions();
90 | break;
91 | case R.id.btn_img_crop :
92 | if (null==mSelected || mSelected.size()<=0){
93 | Toast.makeText(MainActivity.this, "请先选择图片!", Toast.LENGTH_LONG).show();
94 | }else {
95 | String tempCompressImgPath = mSelectedPath.get(0);//事先准备好的sd卡目录下的图片
96 | // 单个图片压缩,多线程模式
97 | new GDCompressC(MainActivity.this,
98 | new GDConfig().setmPath(tempCompressImgPath), new GDCompressImageListener() {
99 | // new GDConfig().setmPath(tempCompressImgPath).setChangeWH(true), new GDCompressImageListener() {
100 | @Override
101 | public void OnSuccess(String path) {
102 | MainActivity.this.runOnUiThread(new Runnable() {
103 | @Override
104 | public void run() {
105 | image_view_crop.setImageBitmap(BitmapFactory
106 | .decodeFile(mSelectedPath.get(0)));
107 | ImageInfoBean imageInfoBean = new ImageGetInfoUtil().getImageInfo(mSelectedPath.get(0));
108 |
109 | txt_crop.setText("imageWidth=" + imageInfoBean.getWightHeightSize()[0] + "\n"
110 | + "imageHeight=" + imageInfoBean.getWightHeightSize()[1] + "\n"
111 | + "imageSize=" + imageInfoBean.getFileSize() + "\n"
112 | + "" );
113 | }
114 | });
115 | }
116 |
117 | @Override
118 | public void OnError(int code, String errorMsg) {
119 |
120 | }
121 | });
122 |
123 | }
124 | break;
125 | case R.id.btn_img_c2 :
126 | if (null==mSelected || mSelected.size()<=0){
127 | Toast.makeText(MainActivity.this, "请先选择图片!", Toast.LENGTH_LONG).show();
128 | }else if (1 == mSelected.size()){
129 | // 单个图片压缩,多线程模式
130 | String tempCompressImgPath = mSelectedPath.get(0);//事先准备好的sd卡目录下的图片
131 |
132 | new GDCompressC(MainActivity.this,
133 | new GDConfig().setmPath(tempCompressImgPath), new GDCompressImageListener() {
134 | // new GDConfig().setmPath(tempCompressImgPath).setChangeWH(true), new GDCompressImageListener() {
135 | @Override
136 | public void OnSuccess(String path) {
137 | MainActivity.this.runOnUiThread(new Runnable() {
138 | @Override
139 | public void run() {
140 | image_view_c2.setImageBitmap(BitmapFactory
141 | .decodeFile(mSelectedPath.get(0)));
142 | ImageInfoBean imageInfoBean = new ImageGetInfoUtil().getImageInfo(mSelectedPath.get(0));
143 |
144 | txt_c2.setText("imageWidth=" + imageInfoBean.getWightHeightSize()[0] + "\n"
145 | + "imageHeight=" + imageInfoBean.getWightHeightSize()[1] + "\n"
146 | + "imageSize=" + imageInfoBean.getFileSize() + "\n"
147 | + "" );
148 | }
149 | });
150 | }
151 |
152 | @Override
153 | public void OnError(int code, String errorMsg) {
154 |
155 | }
156 | });
157 |
158 | }else {
159 | // 批量压缩,多线程模式,速度快,但OOM的几率大
160 | GDCompressC gdCompressC = new GDCompressC(MainActivity.this, new GDCompressImageListener() {
161 | @Override
162 | public void OnSuccess(String path) {
163 | Log.i(TAG, "OnSuccess: ===批量=====图片压缩=====btn_img_c2========path==" + path);
164 | }
165 |
166 | @Override
167 | public void OnError(int code, String errorMsg) {
168 | Log.i(TAG, "OnError: ===批量=====图片压缩=====btn_img_c2==========");
169 | }
170 | });
171 | for (int i = 0; i < mSelected.size(); i++) {
172 | gdCompressC.start(new GDConfig().setmPath(mSelectedPath.get(i)));
173 | }
174 | }
175 | break;
176 | case R.id.btn_img_c3 :
177 | if (null==mSelected || mSelected.size()<=0){
178 | Toast.makeText(MainActivity.this, "请先选择图片!", Toast.LENGTH_LONG).show();
179 | }else if (1 == mSelected.size()){
180 | // 单个图片压缩,单线程模式
181 | String tempCompressImgPath = mSelectedPath.get(0);//事先准备好的sd卡目录下的图片
182 | GDImageBean imageBeana = new GDImageBean();
183 | imageBeana.setmGDConfig(new GDConfig().setmPath(tempCompressImgPath));
184 | new GDCompressA(MainActivity.this, imageBeana
185 | , new GDCompressImageListenerA() {
186 | // new GDConfig().setmPath(tempCompressImgPath).setChangeWH(true), new GDCompressImageListener() {
187 | @Override
188 | public void OnSuccess(GDImageBean gdImageBean) {
189 | MainActivity.this.runOnUiThread(new Runnable() {
190 | @Override
191 | public void run() {
192 | image_view_c3.setImageBitmap(BitmapFactory
193 | .decodeFile(mSelectedPath.get(0)));
194 | ImageInfoBean imageInfoBean = new ImageGetInfoUtil().getImageInfo(mSelectedPath.get(0));
195 |
196 | txt_c3.setText("imageWidth=" + imageInfoBean.getWightHeightSize()[0] + "\n"
197 | + "imageHeight=" + imageInfoBean.getWightHeightSize()[1] + "\n"
198 | + "imageSize=" + imageInfoBean.getFileSize() + "\n"
199 | + "" );
200 | }
201 | });
202 | }
203 |
204 | @Override
205 | public void OnError(GDImageBean gdImageBean) {
206 |
207 | }
208 | });
209 |
210 | }else {
211 | // 批量压缩,单线程模式,速度慢,但OOM几率小很多
212 | GDCompressA gdCompressA = new GDCompressA(MainActivity.this, new GDCompressImageListenerA() {
213 | @Override
214 | public void OnSuccess(GDImageBean gdImageBean) {
215 | Log.i(TAG, "OnSuccess: ===批量=====图片压缩=====btn_img_c3========path==" + gdImageBean.getmGDConfig().getmPath());
216 | }
217 |
218 | @Override
219 | public void OnError(GDImageBean gdImageBean) {
220 | Log.i(TAG, "OnError: ===批量=====图片压缩=====btn_img_c3==========");
221 | }
222 | });
223 | for (int i = 0; i < mSelected.size(); i++) {
224 | GDImageBean imageBeana = new GDImageBean();
225 | imageBeana.setmGDConfig(new GDConfig().setmPath(mSelectedPath.get(i)));
226 | gdCompressA.start(imageBeana);
227 | }
228 | }
229 | break;
230 | case R.id.image_view:
231 | case R.id.image_view_crop:
232 | BagImageActivity.start(MainActivity.this, mSelectedPath.get(0));
233 | break;
234 | case R.id.btn_img_more:
235 | if (null==mSelected || mSelected.size()<=0){
236 | Toast.makeText(MainActivity.this, "请先选择图片!", Toast.LENGTH_LONG).show();
237 | }else {
238 | // 批量压缩,单线程模式,速度慢,但OOM几率小很多,内部通过GDCompressA实现
239 | showProgress("", false);
240 | List data = new ArrayList<>();
241 | for (int i = 0; i < mSelectedPath.size(); i++) {
242 | GDImageBean gdImageBean = new GDImageBean();
243 | GDConfig gdConfig = new GDConfig();
244 | gdConfig.setmPath(mSelectedPath.get(i));
245 | Log.i("GDCimage", "onClick: ===============mSelectedPath.get(i)============" + mSelectedPath.get(i));
246 | gdImageBean.setmGDConfig(gdConfig);
247 | data.add(gdImageBean);
248 | }
249 | new GDCompressImageS(MainActivity.this, data, new GDCompressImageSListener() {
250 | @Override
251 | public void OnSuccess(List imageBeanList) {
252 | Toast.makeText(MainActivity.this, "图片批量压缩成功!", Toast.LENGTH_LONG).show();
253 | hideProgress();
254 | }
255 |
256 | @Override
257 | public void OnError(List imageBeanList) {
258 | // 这里的code为0是成功;为1是失败
259 | Toast.makeText(MainActivity.this, "图片批量压缩失败!" , Toast.LENGTH_LONG).show();
260 | hideProgress();
261 | }
262 | });
263 | }
264 | break;
265 | }
266 | }
267 |
268 |
269 | private void getRxPermissions(){
270 |
271 | RxPermissions rxPermission = new RxPermissions(MainActivity.this);
272 | //每条权限单独判断是否同意
273 | //一次直接返回是否全部同意
274 | rxPermission.request(Manifest.permission.WRITE_EXTERNAL_STORAGE, Manifest.permission.READ_EXTERNAL_STORAGE,
275 | Manifest.permission.CAMERA)
276 | .subscribe(new Observer() {
277 | @Override
278 | public void onSubscribe(Disposable d) {
279 | // Toast.makeText(MainActivity.this, "onSubscribe", Toast.LENGTH_SHORT).show();
280 | }
281 |
282 | @Override
283 | public void onNext(Boolean value) {
284 | if(value){
285 | // Toast.makeText(MainActivity.this, "同意权限", Toast.LENGTH_SHORT).show();
286 | getPic();
287 | }else {
288 | Toast.makeText(MainActivity.this, "拒绝权限", Toast.LENGTH_SHORT).show();
289 | }
290 | }
291 |
292 | @Override
293 | public void onError(Throwable e) {
294 | // Toast.makeText(MainActivity.this, "onError", Toast.LENGTH_SHORT).show();
295 | }
296 |
297 | @Override
298 | public void onComplete() {
299 | // Toast.makeText(MainActivity.this, "onComplete", Toast.LENGTH_SHORT).show();
300 | }
301 | });
302 |
303 | }
304 |
305 | private void getPic(){
306 | Matisse.from(MainActivity.this)
307 | .choose(MimeType.ofAll())//图片类型
308 | .countable(true)//true:选中后显示数字;false:选中后显示对号
309 | .maxSelectable(9)//可选的最大数
310 | .capture(true)//选择照片时,是否显示拍照
311 | .captureStrategy(new CaptureStrategy(true, "com.wgd.myimagelibrary.fileprovider"))//参数1 true表示拍照存储在共有目录,false表示存储在私有目录;参数2与 AndroidManifest中authorities值相同,用于适配7.0系统 必须设置
312 | .imageEngine(new GlideEngine())//图片加载引擎
313 | .forResult(REQUEST_CODE_CHOOSE);//
314 | }
315 |
316 | List mSelected;
317 | List mSelectedPath;
318 |
319 | @Override
320 | protected void onActivityResult(int requestCode, int resultCode, Intent data) {
321 | super.onActivityResult(requestCode, resultCode, data);
322 | if (requestCode == REQUEST_CODE_CHOOSE && resultCode == RESULT_OK) {
323 | try {
324 | mSelected = Matisse.obtainResult(data);
325 | mSelectedPath= Matisse.obtainPathResult(data);
326 | Glide.with(MainActivity.this)
327 | .load(mSelected.get(0))
328 | .thumbnail(0.1f)
329 | .into(image_view);
330 | // ImageInfoBean imageInfoBean = new ImageGetInfoUtil().getImageInfo(mSelectedPath.get(0));
331 | // txt_yuantu.setText("imageWidth=" + imageInfoBean.getWightHeightSize()[0] + "\n"
332 | // + "imageHeight=" + imageInfoBean.getWightHeightSize()[1] + "\n"
333 | // + "imageSize=" + imageInfoBean.getFileSize() + "\n"
334 | // + "" );
335 | }catch (Exception e){
336 | e.printStackTrace();
337 | }
338 | }
339 | }
340 |
341 | ProgressDialog progressDialog;
342 | public void showProgress(String message,boolean iscancel) {
343 | if (progressDialog != null) {
344 | if (progressDialog.isShowing()) {
345 | return;
346 | }
347 | progressDialog.setMessage(message != null ? message
348 | : "loading...");
349 | progressDialog.show();
350 | } else {
351 | progressDialog = new ProgressDialog(MainActivity.this);
352 | progressDialog.setProgressStyle(ProgressDialog.STYLE_SPINNER);
353 | progressDialog.setIndeterminate(false);
354 | progressDialog.setCancelable(iscancel);
355 | progressDialog.setMessage(message != null ? message
356 | : "loading...");
357 | progressDialog.show();
358 | }
359 | }
360 | public void hideProgress() {
361 | if (progressDialog != null&&progressDialog.isShowing()) {
362 | progressDialog.dismiss();
363 | }
364 | }
365 |
366 | }
367 |
--------------------------------------------------------------------------------
/app/src/main/java/com/wgd/myimagelibrary/PathFromUriUtil.java:
--------------------------------------------------------------------------------
1 | package com.wgd.myimagelibrary;
2 |
3 | import android.content.Context;
4 | import android.content.CursorLoader;
5 | import android.database.Cursor;
6 | import android.net.Uri;
7 | import android.os.Build;
8 | import android.provider.DocumentsContract;
9 | import android.provider.MediaStore;
10 | import android.support.annotation.RequiresApi;
11 |
12 | public class PathFromUriUtil {
13 |
14 | /**
15 | *
16 | * 这里由于Matisse返回的Uri格式问题,弃用
17 | *
18 | * 根据图片的Uri获取图片的绝对路径(已经适配多种API)
19 | * @return 如果Uri对应的图片存在,那么返回该图片的绝对路径,否则返回null
20 | */
21 | public static String getRealPathFromUri(Context context, Uri uri) {
22 | int sdkVersion = Build.VERSION.SDK_INT;
23 | if (sdkVersion < 11) {
24 | // SDK < Api11
25 | return getRealPathFromUri_BelowApi11(context, uri);
26 | }
27 | if (sdkVersion < 19) {
28 | // SDK > 11 && SDK < 19
29 | return getRealPathFromUri_Api11To18(context, uri);
30 | }
31 | // SDK > 19
32 | return getRealPathFromUri_AboveApi19(context, uri);
33 | }
34 |
35 | /**
36 | * 适配api19以上,根据uri获取图片的绝对路径
37 | */
38 | @RequiresApi(api = Build.VERSION_CODES.KITKAT)
39 | private static String getRealPathFromUri_AboveApi19(Context context, Uri uri) {
40 | String filePath = null;
41 | String wholeID = DocumentsContract.getDocumentId(uri);
42 |
43 | // 使用':'分割
44 | String id = wholeID.split(":")[1];
45 |
46 | String[] projection = { MediaStore.Images.Media.DATA };
47 | String selection = MediaStore.Images.Media._ID + "=?";
48 | String[] selectionArgs = { id };
49 |
50 | Cursor cursor = context.getContentResolver().query(
51 | MediaStore.Images.Media.EXTERNAL_CONTENT_URI, projection,
52 | selection, selectionArgs, null);
53 | int columnIndex = cursor.getColumnIndex(projection[0]);
54 |
55 | if (cursor.moveToFirst()) {
56 | filePath = cursor.getString(columnIndex);
57 | }
58 | cursor.close();
59 | return filePath;
60 | }
61 |
62 | /**
63 | * 适配api11-api18,根据uri获取图片的绝对路径
64 | */
65 | private static String getRealPathFromUri_Api11To18(Context context, Uri uri) {
66 | String filePath = null;
67 | String[] projection = { MediaStore.Images.Media.DATA };
68 |
69 | CursorLoader loader = new CursorLoader(context, uri, projection, null,
70 | null, null);
71 | Cursor cursor = loader.loadInBackground();
72 |
73 | if (cursor != null) {
74 | cursor.moveToFirst();
75 | filePath = cursor.getString(cursor.getColumnIndex(projection[0]));
76 | cursor.close();
77 | }
78 | return filePath;
79 | }
80 |
81 | /**
82 | * 适配api11以下(不包括api11),根据uri获取图片的绝对路径
83 | */
84 | private static String getRealPathFromUri_BelowApi11(Context context, Uri uri) {
85 | String filePath = null;
86 | String[] projection = { MediaStore.Images.Media.DATA };
87 | Cursor cursor = context.getContentResolver().query(uri, projection,
88 | null, null, null);
89 | if (cursor != null) {
90 | cursor.moveToFirst();
91 | filePath = cursor.getString(cursor.getColumnIndex(projection[0]));
92 | cursor.close();
93 | }
94 | return filePath;
95 | }
96 |
97 | }
98 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable-v24/ic_launcher_foreground.xml:
--------------------------------------------------------------------------------
1 |
7 |
12 |
13 |
19 |
22 |
25 |
26 |
27 |
28 |
34 |
35 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/ic_launcher_background.xml:
--------------------------------------------------------------------------------
1 |
2 |
7 |
10 |
15 |
20 |
25 |
30 |
35 |
40 |
45 |
50 |
55 |
60 |
65 |
70 |
75 |
80 |
85 |
90 |
95 |
100 |
105 |
110 |
115 |
120 |
125 |
130 |
135 |
140 |
145 |
150 |
155 |
160 |
165 |
170 |
171 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/activity_image_bag.xml:
--------------------------------------------------------------------------------
1 |
2 |
5 |
6 |
10 |
11 |
15 |
16 |
17 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/activity_main.xml:
--------------------------------------------------------------------------------
1 |
2 |
8 |
9 |
12 |
16 |
22 |
23 |
29 |
30 |
35 |
41 |
42 |
47 |
53 |
59 |
60 |
65 |
71 |
72 |
78 |
79 |
84 |
90 |
91 |
97 |
98 |
99 |
100 |
101 |
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-hdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/WGDrzjz/ImageCompress/ba307d81e9c2681001c3eeb492b684ca687a584f/app/src/main/res/mipmap-hdpi/ic_launcher.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-hdpi/ic_launcher_round.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/WGDrzjz/ImageCompress/ba307d81e9c2681001c3eeb492b684ca687a584f/app/src/main/res/mipmap-hdpi/ic_launcher_round.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-mdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/WGDrzjz/ImageCompress/ba307d81e9c2681001c3eeb492b684ca687a584f/app/src/main/res/mipmap-mdpi/ic_launcher.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-mdpi/ic_launcher_round.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/WGDrzjz/ImageCompress/ba307d81e9c2681001c3eeb492b684ca687a584f/app/src/main/res/mipmap-mdpi/ic_launcher_round.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-xhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/WGDrzjz/ImageCompress/ba307d81e9c2681001c3eeb492b684ca687a584f/app/src/main/res/mipmap-xhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-xhdpi/ic_launcher_round.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/WGDrzjz/ImageCompress/ba307d81e9c2681001c3eeb492b684ca687a584f/app/src/main/res/mipmap-xhdpi/ic_launcher_round.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-xxhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/WGDrzjz/ImageCompress/ba307d81e9c2681001c3eeb492b684ca687a584f/app/src/main/res/mipmap-xxhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/WGDrzjz/ImageCompress/ba307d81e9c2681001c3eeb492b684ca687a584f/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/WGDrzjz/ImageCompress/ba307d81e9c2681001c3eeb492b684ca687a584f/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/WGDrzjz/ImageCompress/ba307d81e9c2681001c3eeb492b684ca687a584f/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png
--------------------------------------------------------------------------------
/app/src/main/res/values/colors.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | #3F51B5
4 | #303F9F
5 | #FF4081
6 |
7 |
--------------------------------------------------------------------------------
/app/src/main/res/values/strings.xml:
--------------------------------------------------------------------------------
1 |
2 | MyImageLibrary
3 |
4 |
--------------------------------------------------------------------------------
/app/src/main/res/values/styles.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
10 |
11 |
12 |
--------------------------------------------------------------------------------
/app/src/main/res/xml/file_paths_public.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
7 |
8 |
--------------------------------------------------------------------------------
/build.gradle:
--------------------------------------------------------------------------------
1 | // Top-level build file where you can add configuration options common to all sub-projects/modules.
2 |
3 | buildscript {
4 |
5 | repositories {
6 | maven{ url 'http://maven.aliyun.com/nexus/content/groups/public/'}
7 | maven { url 'https://jitpack.io' }
8 | maven {
9 | url 'https://maven.google.com/'
10 | name 'Google'
11 | }
12 | // jcenter()
13 | jcenter(){url "https://maven.aliyun.com/repository/jcenter"}
14 | }
15 | dependencies {
16 | classpath 'com.android.tools.build:gradle:3.1.2'
17 | classpath 'com.novoda:bintray-release:0.8.0'
18 |
19 | // NOTE: Do not place your application dependencies here; they belong
20 | // in the individual module build.gradle files
21 | }
22 | }
23 | /*
24 | allprojects {
25 | repositories {
26 | maven { url "https://maven.aliyun.com/repository/jcenter"}
27 | maven { url 'http://maven.aliyun.com/nexus/content/groups/public/' }
28 | maven{ url 'http://maven.aliyun.com/nexus/content/repositories/jcenter'}
29 |
30 | jcenter(){url "https://maven.aliyun.com/repository/jcenter"}
31 | // jcenter(){url "https://maven.aliyun.com/repository/jcenter"}
32 | }
33 | tasks.withType(Javadoc) {
34 | options.addStringOption('Xdoclint:none', '-quiet')
35 | options.addStringOption('encoding', 'UTF-8')
36 | }
37 | }*/
38 |
39 | allprojects {
40 | repositories {
41 | maven { url "https://maven.aliyun.com/repository/jcenter"}
42 | mavenCentral()/*方法超限解决方法第一步*/
43 | maven { url "https://jitpack.io" }
44 | maven { url 'http://maven.aliyun.com/nexus/content/groups/public/' }
45 | maven{ url 'http://maven.aliyun.com/nexus/content/repositories/jcenter'}
46 | maven { url "https://dl.bintray.com/wangruijun/maven" }
47 | maven {
48 | url 'https://maven.google.com/'
49 | name 'Google'
50 | }
51 | // jcenter()
52 | jcenter(){url "https://maven.aliyun.com/repository/jcenter"}
53 | }
54 | }
55 |
56 | //allprojects {
57 | // repositories {
58 | // google()
59 | // jcenter()
60 | //// maven { url "https://dl.bintray.com/wangruijun/maven" }
61 | // }
62 | // tasks.withType(Javadoc) {
63 | // options.addStringOption('Xdoclint:none', '-quiet')
64 | // options.addStringOption('encoding', 'UTF-8')
65 | // }
66 | //}
67 | //gradlew clean build bintrayUpload -PbintrayUser=wangruijun -PbintrayKey=a0d662943bb4c5ae83cd3d539113c91b04570499 -PdryRun=false
68 | task clean(type: Delete) {
69 | delete rootProject.buildDir
70 | }
71 | tasks.getByPath(":gdcplibrary:releaseAndroidJavadocs").enabled = false
--------------------------------------------------------------------------------
/gdcplibrary/build.gradle:
--------------------------------------------------------------------------------
1 | apply plugin: 'com.android.library'
2 | //apply plugin: 'maven'
3 | apply plugin: 'com.novoda.bintray-release'
4 | android {
5 | compileSdkVersion 27
6 |
7 |
8 |
9 | defaultConfig {
10 | minSdkVersion 15
11 | targetSdkVersion 27
12 | versionCode 10
13 | versionName "1.0.10"
14 |
15 | testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
16 |
17 | }
18 |
19 | buildTypes {
20 | release {
21 | minifyEnabled false
22 | proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
23 | }
24 | }
25 |
26 | // javadoc {
27 | // options{
28 | // encoding "UTF-8"
29 | // charSet 'UTF-8'
30 | // author true
31 | // version true
32 | // links "http://docs.oracle.com/javase/7/docs/api"
33 | // }
34 | // }
35 |
36 | }
37 |
38 | dependencies {
39 | implementation fileTree(dir: 'libs', include: ['*.jar'])
40 |
41 | // implementation 'com.android.support:appcompat-v7:27.1.1'
42 | testImplementation 'junit:junit:4.12'
43 | // androidTestImplementation 'com.android.support.test:runner:1.0.2'
44 | // androidTestImplementation 'com.android.support.test.espresso:espresso-core:3.0.2'
45 |
46 | // 添加依赖
47 | implementation "com.github.yjfnypeu:EasyThread:0.6.0"
48 | }
49 |
50 | publish {
51 | userOrg = 'wangruijun'
52 | groupId = 'com.wgd.gdcp.gdcplibrary'
53 | artifactId = 'ImageCompress'
54 | version = '1.0.10'
55 | description = 'OOM problem optimization, image batch compression and so on in the compression process'
56 | website = "https://github.com/WGDrzjz/ImageCompress"
57 | }
58 |
59 |
--------------------------------------------------------------------------------
/gdcplibrary/src/androidTest/java/com/wgd/gdcp/gdcplibrary/ExampleInstrumentedTest.java:
--------------------------------------------------------------------------------
1 | package com.wgd.gdcp.gdcplibrary;
2 |
3 | import android.content.Context;
4 | import android.support.test.InstrumentationRegistry;
5 | import android.support.test.runner.AndroidJUnit4;
6 |
7 | import org.junit.Test;
8 | import org.junit.runner.RunWith;
9 |
10 | import static org.junit.Assert.*;
11 |
12 | /**
13 | * Instrumented test, which will execute on an Android device.
14 | *
15 | * @see Testing documentation
16 | */
17 | @RunWith(AndroidJUnit4.class)
18 | public class ExampleInstrumentedTest {
19 | @Test
20 | public void useAppContext() {
21 | // Context of the app under test.
22 | Context appContext = InstrumentationRegistry.getTargetContext();
23 |
24 | assertEquals("com.wgd.gdcp.gdcplibrary.test", appContext.getPackageName());
25 | }
26 | }
27 |
--------------------------------------------------------------------------------
/gdcplibrary/src/main/AndroidManifest.xml:
--------------------------------------------------------------------------------
1 |
3 |
--------------------------------------------------------------------------------
/gdcplibrary/src/main/java/com/wgd/gdcp/gdcplibrary/GDBitmapUtil.java:
--------------------------------------------------------------------------------
1 | package com.wgd.gdcp.gdcplibrary;
2 |
3 | import android.app.Activity;
4 | import android.content.Context;
5 | import android.graphics.Bitmap;
6 | import android.graphics.BitmapFactory;
7 | import android.graphics.Matrix;
8 | import android.media.ExifInterface;
9 | import android.util.Log;
10 | import android.view.Display;
11 | import android.view.WindowManager;
12 |
13 | import java.io.BufferedOutputStream;
14 | import java.io.File;
15 | import java.io.FileOutputStream;
16 | import java.io.IOException;
17 |
18 | public class GDBitmapUtil {
19 |
20 | public static int[] getBitmapWH(String path){
21 | int whSize[] = new int[2];
22 | // BitmapFactory.Options options = new BitmapFactory.Options();
23 | //
24 | // options.inJustDecodeBounds = true;
25 | // Bitmap bitmap = BitmapFactory.decodeFile(path, options);
26 | // whSize[0] = bitmap.getWidth();
27 | // whSize[1] = bitmap.getHeight();
28 |
29 | BitmapFactory.Options options = new BitmapFactory.Options();
30 | options.inJustDecodeBounds = true;
31 | options.inSampleSize = 1;
32 |
33 | BitmapFactory.decodeFile(path, options);
34 | whSize[0] = options.outWidth;
35 | whSize[1] = options.outHeight;
36 |
37 | return whSize;
38 | }
39 |
40 | public static File saveBitmapFile(Bitmap bitmap, String filepath){
41 | File file=new File(filepath);//
42 | try {
43 | BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream(file));
44 | bitmap.compress(Bitmap.CompressFormat.JPEG, 100, bos);
45 | bos.flush();
46 | bos.close();
47 | } catch (IOException e) {
48 | e.printStackTrace();
49 | }
50 | return file;
51 | }
52 |
53 | public static void saveBitmapFileVo(Bitmap bitmap, String filepath) throws Exception{
54 | File file=new File(filepath);//
55 | if (!file.exists()){
56 | file = new File(filepath);
57 | }
58 | // try {
59 | // BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream(file));
60 | // bitmap.compress(Bitmap.CompressFormat.JPEG, 100, bos);
61 | // bos.flush();
62 | // bos.close();
63 | // } catch (IOException e) {
64 | // e.printStackTrace();
65 | // }
66 | BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream(file));
67 | bitmap.compress(Bitmap.CompressFormat.JPEG, 100, bos);
68 | bos.flush();
69 | bos.close();
70 | }
71 |
72 | // public static Bitmap bitmapDegree(String path) throws Exception{
73 | // return bitmapDegree(null,path);
74 | // }
75 | public static Bitmap bitmapDegree(Context mContext, String path) throws Exception{
76 | Bitmap bitmap = null ;
77 | try {
78 | bitmap = BitmapFactory.decodeFile(path);
79 | }catch (Exception e){
80 | bitmap = adjustImage(mContext, path, 2);
81 | }
82 | boolean isRotate = false ;
83 | try {
84 | ExifInterface exifInterface = new ExifInterface(path);
85 | Matrix matrix = new Matrix();
86 | int angle = 0;
87 | int orientation = exifInterface.getAttributeInt(ExifInterface.TAG_ORIENTATION, ExifInterface.ORIENTATION_NORMAL);
88 | switch (orientation) {
89 | case ExifInterface.ORIENTATION_ROTATE_90:
90 | angle = 90;
91 | isRotate = true ;
92 | break;
93 | case ExifInterface.ORIENTATION_ROTATE_180:
94 | angle = 180;
95 | isRotate = true ;
96 | break;
97 | case ExifInterface.ORIENTATION_ROTATE_270:
98 | angle = 270;
99 | isRotate = true ;
100 | break;
101 | }
102 | matrix.postRotate(angle);
103 | // BitmapFactory.Options options = new BitmapFactory.Options();
104 | //
105 | // options.inJustDecodeBounds = true;
106 | // Bitmap bitmap = BitmapFactory.decodeFile(path, options);
107 |
108 | // return Bitmap.createBitmap(bitmap, 0, 0, options.outWidth, options.outHeight, matrix, true);
109 | if (isRotate)return Bitmap.createBitmap(bitmap, 0, 0, bitmap.getWidth(), bitmap.getHeight(), matrix, true);
110 | else return bitmap ;
111 | }catch (Exception e){e.printStackTrace();}
112 | return bitmap ;
113 |
114 | }
115 |
116 | private static Bitmap adjustImage(Context mContext, String absolutePath, int size) {
117 | Bitmap bm = null ;
118 | BitmapFactory.Options opt = new BitmapFactory.Options();
119 | //
120 | opt.inJustDecodeBounds = true;
121 | // bm = BitmapFactory.decodeFile(absolutePath, opt);
122 |
123 | //
124 | int picWidth = opt.outWidth;
125 | int picHeight = opt.outHeight;
126 |
127 | //
128 | WindowManager windowManager = ((Activity)mContext).getWindowManager();
129 | Display display = windowManager.getDefaultDisplay();
130 | int screenWidth = display.getWidth();
131 | int screenHeight = display.getHeight();
132 |
133 | //
134 | opt.inSampleSize = 1;
135 | //
136 | if (picWidth > picHeight) {
137 | if (picWidth > screenWidth)
138 | opt.inSampleSize = picWidth / screenWidth;
139 | } else {
140 | if (picHeight > screenHeight)
141 | opt.inSampleSize = picHeight / screenHeight;
142 | }
143 |
144 | if (opt.inSampleSize<=1)opt.inSampleSize = size ;
145 | //
146 | opt.inJustDecodeBounds = false;
147 | try {
148 | bm= BitmapFactory.decodeFile(absolutePath, opt);
149 | }catch (Exception e){
150 | bm = adjustImage(mContext, absolutePath, size+1);
151 | }
152 | return bm ;
153 | }
154 | //:gdcplibrary:bintrayUpload
155 | public static void saveBitmapDegree(String path){
156 | try {
157 | //
158 | ExifInterface exifInterface = new ExifInterface(path);
159 | Matrix matrix = new Matrix();
160 | int angle = 0;
161 | int orientation = exifInterface.getAttributeInt(ExifInterface.TAG_ORIENTATION, ExifInterface.ORIENTATION_NORMAL);
162 | switch (orientation) {
163 | case ExifInterface.ORIENTATION_ROTATE_90:
164 | angle = 90;
165 | break;
166 | case ExifInterface.ORIENTATION_ROTATE_180:
167 | angle = 180;
168 | break;
169 | case ExifInterface.ORIENTATION_ROTATE_270:
170 | angle = 270;
171 | break;
172 | }
173 | matrix.postRotate(angle);
174 | if (angle != 0){
175 | BitmapFactory.Options options = new BitmapFactory.Options();
176 | //
177 | options.inJustDecodeBounds = true;
178 | Bitmap bitmap = BitmapFactory.decodeFile(path, options);
179 | File saveBitmapFile = saveBitmapFile(Bitmap.createBitmap(bitmap, 0, 0, bitmap.getWidth(), bitmap.getHeight(), matrix, true), path);
180 | }
181 | }catch (Exception e){e.printStackTrace();}
182 |
183 | }
184 |
185 | public static Bitmap getBitmap(String path){
186 | try {
187 | return BitmapFactory.decodeFile(path);
188 |
189 | }catch (Exception e){e.printStackTrace();}
190 | Log.i("GDCimage", "getBitmap: ==============02==============");
191 | BitmapFactory.Options options = new BitmapFactory.Options();
192 | //
193 | // options.inJustDecodeBounds = true;
194 | options.inSampleSize = 2 ;
195 | Log.i("GDCimage", "getBitmap: ==============01==============");
196 | return BitmapFactory.decodeFile(path, options);
197 | }
198 |
199 |
200 | }
201 |
--------------------------------------------------------------------------------
/gdcplibrary/src/main/java/com/wgd/gdcp/gdcplibrary/GDCompress.java:
--------------------------------------------------------------------------------
1 | package com.wgd.gdcp.gdcplibrary;
2 |
3 | import android.app.Activity;
4 | import android.content.Context;
5 | import android.graphics.Bitmap;
6 | import android.graphics.BitmapFactory;
7 | import android.text.TextUtils;
8 |
9 | import com.wgd.gdcp.gdcplibrary.thread.ThreadManager;
10 |
11 | public class GDCompress {
12 |
13 | private Context mContext;
14 | private GDCompressImageListener mGDCompressImageListener;
15 | private String mPath ;
16 | private String savePath ;
17 |
18 | private Bitmap bitmap ;
19 |
20 | public GDCompress(Context context, String path, String savepath, GDCompressImageListener GDCompressImageListener){
21 | this.mContext = context ;
22 | this.mPath = path ;
23 | this.savePath = savepath ;
24 | this.mGDCompressImageListener = GDCompressImageListener;
25 |
26 | startCompress();
27 | }
28 |
29 | private void startCompress(){
30 | ThreadManager.getIO().execute(new Runnable() {
31 | @Override
32 | public void run() {
33 | if (compressLibJpeg(mPath)){
34 | InformCallSuccess(savePath);
35 | }else {
36 | InformCallError(0, "Image compression failure!");
37 | }
38 | }
39 | });
40 | }
41 |
42 | private void InformCallSuccess(final String path){
43 | try {
44 | GDBitmapUtil.saveBitmapDegree(path);
45 | }catch (Exception e){e.printStackTrace();}
46 | try {
47 | if(bitmap != null && !bitmap.isRecycled()){
48 | bitmap.recycle();
49 | bitmap = null;
50 | }
51 | System.gc();
52 | }catch (Exception e){e.printStackTrace();}
53 | try {
54 | ((Activity) mContext).runOnUiThread(new Runnable() {
55 | @Override
56 | public void run() {
57 | if (null!= mGDCompressImageListener) mGDCompressImageListener.OnSuccess(path);
58 | }
59 | });
60 | }catch (Exception e){
61 | e.printStackTrace();
62 | if (null!= mGDCompressImageListener) mGDCompressImageListener.OnSuccess(path);
63 | }
64 | }
65 | private void InformCallError(final int code, final String errorMsg){
66 |
67 | try {
68 | ((Activity) mContext).runOnUiThread(new Runnable() {
69 | @Override
70 | public void run() {
71 | if (null!= mGDCompressImageListener) mGDCompressImageListener.OnError(code, errorMsg);
72 | }
73 | });
74 | }catch (Exception e){
75 | e.printStackTrace();
76 | if (null!= mGDCompressImageListener) mGDCompressImageListener.OnError(code, errorMsg);
77 | }
78 | }
79 |
80 | private boolean compressLibJpeg(Bitmap bitmap, int quality){
81 | try {
82 | if (null==savePath || TextUtils.equals("", savePath)){
83 | savePath = mPath;
84 | }
85 | if (null==bitmap)return false;
86 | boolean codeString = ImageUtils.compressBitmap(bitmap, bitmap.getWidth(), bitmap.getHeight(), savePath, quality);
87 | return codeString;
88 | }catch (Exception e){e.printStackTrace();}
89 | return false;
90 | }
91 | /*
92 | * path 原图路径
93 | * */
94 | private boolean compressLibJpeg(String path){
95 | try {
96 | bitmap = BitmapFactory.decodeFile(path);
97 | return compressLibJpeg(bitmap, 20);
98 | }catch (Exception e){e.printStackTrace();}
99 | return false;
100 | }
101 | /*
102 | * path 原图路径
103 | * */
104 | private boolean compressLibJpeg(String path, int quality){
105 | try {
106 | bitmap = BitmapFactory.decodeFile(path);
107 | return compressLibJpeg(bitmap, quality);
108 | }catch (Exception e){e.printStackTrace();}
109 | return false;
110 | }
111 |
112 |
113 | }
114 |
--------------------------------------------------------------------------------
/gdcplibrary/src/main/java/com/wgd/gdcp/gdcplibrary/GDCompressA.java:
--------------------------------------------------------------------------------
1 | package com.wgd.gdcp.gdcplibrary;
2 |
3 | import android.app.Activity;
4 | import android.content.Context;
5 | import android.graphics.Bitmap;
6 | import android.graphics.BitmapFactory;
7 | import android.text.TextUtils;
8 |
9 | import com.wgd.gdcp.gdcplibrary.thread.ThreadManager;
10 |
11 | import java.util.ArrayList;
12 | import java.util.List;
13 |
14 | /*
15 | * change the picture width and height
16 | * Single picture compression
17 | *
18 | * Please apply for permission dynamically
19 | * android.permission.WRITE_EXTERNAL_STORAGE
20 | * android.permission.READ_EXTERNAL_STORAGE
21 | *
22 | * 这个处理方式中的优点是:
23 | * 使用单线程线程池,并将Bitmap设为全局变量
24 | * 只要只有一个GDCompressA实例
25 | * 那么循环调用压缩很多图片时大大降低了OOM的几率
26 | * 缺点是:
27 | * 这种方式导致批量压缩时线性的,处理时间将被拉长
28 | *
29 | * */
30 | public class GDCompressA {
31 |
32 | private Context mContext;
33 | private GDCompressImageListenerA mGDCompressImageListener;
34 |
35 | Bitmap bitmapMin = null;
36 |
37 | public GDCompressA(Context context, GDCompressImageListenerA mGDCompressImageListener){
38 | this.mContext = context ;
39 | this.mGDCompressImageListener = mGDCompressImageListener ;
40 | }
41 |
42 | public GDCompressA(Context context, GDImageBean mGDImageBean, GDCompressImageListenerA mGDCompressImageListener){
43 | this.mContext = context ;
44 | this.mGDCompressImageListener = mGDCompressImageListener ;
45 | start(mGDImageBean);
46 | }
47 |
48 | public void start(GDImageBean mGDImageBean){
49 | GDConfig gdConfig = null;
50 | if (null!=mGDImageBean) gdConfig = mGDImageBean.getmGDConfig();
51 | if (null==gdConfig)gdConfig = new GDConfig();
52 | if (!GDTools.ImageTesting(gdConfig.getmPath())){
53 | InformCallError(1, "Incorrect picture format!", mGDImageBean);
54 | return;
55 | }
56 | final GDConfig mGDConfig = gdConfig ;
57 | if (null==mGDConfig.getSavePath() || TextUtils.equals("", mGDConfig.getSavePath())){
58 | mGDConfig.setSavePath(mGDConfig.getmPath());
59 | }
60 | mGDImageBean.setmGDConfig(mGDConfig);
61 | final GDImageBean gdImageBean = mGDImageBean;
62 | ThreadManager.getIO1().execute(new Runnable() {
63 | @Override
64 | public void run() {
65 | if (mGDConfig.isChangeWH()) {
66 | if (mGDConfig.getWidth() <= 0 || mGDConfig.getHeight() <= 0) {
67 | try {
68 | bitmapMin = new GDCompressUtil().SysCompressMin(mGDConfig.getmPath());
69 | // bitmapMin= new GDCompressUtil().SysCompressMin(bitmap);
70 | } catch (Exception e) {
71 | e.printStackTrace();
72 | }
73 |
74 | if (null== bitmapMin){
75 | InformCallError(0, "Image compression failure!", gdImageBean);
76 | }else {
77 | if (new GDCompressUtil().compressLibJpeg(bitmapMin, mGDConfig.getSavePath())) {
78 | InformCallSuccess(mGDConfig.getSavePath(), gdImageBean);
79 | } else {
80 | InformCallError(0, "Image compression failure!", gdImageBean);
81 | }
82 | }
83 |
84 | } else {
85 |
86 | try {
87 | bitmapMin = new GDCompressUtil().SysCompressMySamp(mGDConfig.getmPath(), mGDConfig.getWidth(), mGDConfig.getHeight());
88 | // bitmapMin= new GDCompressUtil().SysCompressMin(bitmap);
89 | } catch (Exception e) {
90 | e.printStackTrace();
91 | }
92 |
93 | if (null== bitmapMin){
94 | InformCallError(0, "Image compression failure!", gdImageBean);
95 | }else {
96 | if (new GDCompressUtil().compressLibJpeg(bitmapMin, mGDConfig.getSavePath())) {
97 | InformCallSuccess(mGDConfig.getSavePath(), gdImageBean);
98 | } else {
99 | InformCallError(0, "Image compression failure!", gdImageBean);
100 | }
101 | }
102 |
103 | }
104 | } else {
105 | // Bitmap bitmap = null;
106 | try {
107 | bitmapMin = GDBitmapUtil.getBitmap(mGDConfig.getmPath());
108 | } catch (Exception e) {
109 | e.printStackTrace();
110 | bitmapMin = BitmapFactory.decodeFile(mGDConfig.getmPath());
111 | }
112 |
113 | if (null== bitmapMin){
114 | InformCallError(0, "Image compression failure!", gdImageBean);
115 | }else
116 | if (new GDCompressUtil().compressLibJpeg(bitmapMin, mGDConfig.getSavePath())) {
117 | InformCallSuccess(mGDConfig.getSavePath(), gdImageBean);
118 | } else {
119 | InformCallError(0, "Image compression failure!", gdImageBean);
120 | }
121 | }
122 | }
123 | });
124 | }
125 |
126 | private void InformCallSuccess(final String path, GDImageBean mGDImageBean){
127 | try {
128 | GDBitmapUtil.saveBitmapDegree(path);
129 | }catch (Exception e){e.printStackTrace();}
130 | try {
131 | if (null!=bitmapMin ){
132 | bitmapMin.recycle();
133 | bitmapMin = null;
134 | System.gc();
135 | }
136 | }catch (Exception e){e.printStackTrace();}
137 | mGDImageBean.setCode(0);
138 | try {
139 | final GDImageBean gDImageBean = mGDImageBean;
140 | ((Activity) mContext).runOnUiThread(new Runnable() {
141 | @Override
142 | public void run() {
143 | if (null!= mGDCompressImageListener) mGDCompressImageListener.OnSuccess(gDImageBean);
144 | }
145 | });
146 | }catch (Exception e){
147 | e.printStackTrace();
148 | if (null!= mGDCompressImageListener) mGDCompressImageListener.OnSuccess(mGDImageBean);
149 | }
150 | }
151 | private void InformCallError(final int code, final String errorMsg, final GDImageBean mGDImageBean){
152 | try {
153 | if (null!=bitmapMin ){
154 | bitmapMin.recycle();
155 | bitmapMin = null;
156 | System.gc();
157 | }
158 | }catch (Exception e){e.printStackTrace();}
159 | mGDImageBean.setCode(code);
160 | mGDImageBean.setErrorMsg(errorMsg);
161 | try {
162 | final GDImageBean gDImageBean = mGDImageBean;
163 | ((Activity) mContext).runOnUiThread(new Runnable() {
164 | @Override
165 | public void run() {
166 | if (null!= mGDCompressImageListener) mGDCompressImageListener.OnError(gDImageBean);
167 | }
168 | });
169 | }catch (Exception e){
170 | e.printStackTrace();
171 | if (null!= mGDCompressImageListener) mGDCompressImageListener.OnError(mGDImageBean);
172 | }
173 | }
174 |
175 |
176 | }
177 |
--------------------------------------------------------------------------------
/gdcplibrary/src/main/java/com/wgd/gdcp/gdcplibrary/GDCompressC.java:
--------------------------------------------------------------------------------
1 | package com.wgd.gdcp.gdcplibrary;
2 |
3 | import android.app.Activity;
4 | import android.content.Context;
5 | import android.graphics.Bitmap;
6 | import android.graphics.BitmapFactory;
7 | import android.graphics.Matrix;
8 | import android.media.ExifInterface;
9 | import android.text.TextUtils;
10 | import android.util.Log;
11 |
12 | import com.wgd.gdcp.gdcplibrary.thread.ThreadManager;
13 |
14 | import java.io.ByteArrayOutputStream;
15 | import java.util.ArrayList;
16 | import java.util.List;
17 |
18 | /*
19 | * change the picture width and height
20 | * Single picture compression
21 | *
22 | * Please apply for permission dynamically
23 | * android.permission.WRITE_EXTERNAL_STORAGE
24 | * android.permission.READ_EXTERNAL_STORAGE
25 | *
26 | * 备注:20190314
27 | * 通过处理批量压缩发现:
28 | * 这个逻辑的处理方式由于每创建一个线程,都会在线程中产生新的Bitmap,
29 | * 所以产生OOM的几率比较大
30 | * 故这里应该禁止通过循环调用此方式来大量处理图片
31 | *
32 | * */
33 | public class GDCompressC {
34 |
35 | private Context mContext;
36 | private GDCompressImageListener mGDCompressImageListener;
37 |
38 |
39 |
40 | //为了将Bitmap释放使用
41 | private List garbage = new ArrayList<>();
42 |
43 | public GDCompressC(Context context, GDConfig mGDConfig, GDCompressImageListener mGDCompressImageListener){
44 | this.mContext = context ;
45 | this.mGDCompressImageListener = mGDCompressImageListener ;
46 | start(mGDConfig);
47 | }
48 |
49 | public GDCompressC(Context context, GDCompressImageListener mGDCompressImageListener){
50 | this.mContext = context ;
51 | this.mGDCompressImageListener = mGDCompressImageListener ;
52 | }
53 |
54 |
55 | public void start(GDConfig gdConfig){
56 | if (null==gdConfig)gdConfig = new GDConfig();
57 | if (!GDTools.ImageTesting(gdConfig.getmPath())){
58 | InformCallError(1, "Incorrect picture format!");
59 | return;
60 | }
61 | if (null==gdConfig.getSavePath() || TextUtils.equals("", gdConfig.getSavePath())){
62 | gdConfig.setSavePath(gdConfig.getmPath());
63 | }
64 | final GDConfig mGDConfig = gdConfig;
65 | ThreadManager.getIO().execute(new Runnable() {
66 | @Override
67 | public void run() {
68 | Bitmap bitmapMin = null;
69 | if (mGDConfig.isChangeWH()) {
70 | if (mGDConfig.getWidth() <= 0 || mGDConfig.getHeight() <= 0) {
71 | try {
72 | bitmapMin = new GDCompressUtil().SysCompressMin(mGDConfig.getmPath());
73 | // bitmapMin= new GDCompressUtil().SysCompressMin(bitmap);
74 | } catch (Exception e) {
75 | e.printStackTrace();
76 | }
77 |
78 | garbage.add(bitmapMin);
79 | if (null== bitmapMin){
80 | InformCallError(0, "Image compression failure!");
81 | }else {
82 | if (new GDCompressUtil().compressLibJpeg(bitmapMin, mGDConfig.getSavePath())) {
83 | InformCallSuccess(mGDConfig.getSavePath());
84 | } else {
85 | InformCallError(0, "Image compression failure!");
86 | }
87 | }
88 |
89 | } else {
90 |
91 | try {
92 | bitmapMin = new GDCompressUtil().SysCompressMySamp(mGDConfig.getmPath(), mGDConfig.getWidth(), mGDConfig.getHeight());
93 | // bitmapMin= new GDCompressUtil().SysCompressMin(bitmap);
94 | } catch (Exception e) {
95 | e.printStackTrace();
96 | }
97 |
98 | garbage.add(bitmapMin);
99 | if (null== bitmapMin){
100 | InformCallError(0, "Image compression failure!");
101 | }else {
102 | if (new GDCompressUtil().compressLibJpeg(bitmapMin, mGDConfig.getSavePath())) {
103 | InformCallSuccess(mGDConfig.getSavePath());
104 | } else {
105 | InformCallError(0, "Image compression failure!");
106 | }
107 | }
108 |
109 | }
110 | } else {
111 | // Bitmap bitmap = null;
112 | try {
113 | bitmapMin = GDBitmapUtil.getBitmap(mGDConfig.getmPath());
114 | } catch (Exception e) {
115 | e.printStackTrace();
116 | bitmapMin = BitmapFactory.decodeFile(mGDConfig.getmPath());
117 | }
118 |
119 | garbage.add(bitmapMin);
120 | if (null== bitmapMin){
121 | InformCallError(0, "Image compression failure!");
122 | }else
123 | if (new GDCompressUtil().compressLibJpeg(bitmapMin, mGDConfig.getSavePath())) {
124 | InformCallSuccess(mGDConfig.getSavePath());
125 | } else {
126 | InformCallError(0, "Image compression failure!");
127 | }
128 | }
129 | }
130 | });
131 | }
132 |
133 | private void InformCallSuccess(final String path){
134 | try {
135 | GDBitmapUtil.saveBitmapDegree(path);
136 | }catch (Exception e){e.printStackTrace();}
137 | try {
138 | if (null!=garbage && garbage.size()>0){
139 | for (int i = 0; i < garbage.size(); i++) {
140 | Bitmap bitmap = garbage.get(i);
141 | if(bitmap != null && !bitmap.isRecycled()){
142 | bitmap.recycle();
143 | bitmap = null;
144 | }
145 | }
146 | garbage.clear();
147 | System.gc();
148 | }
149 | }catch (Exception e){e.printStackTrace();}
150 | try {
151 | ((Activity) mContext).runOnUiThread(new Runnable() {
152 | @Override
153 | public void run() {
154 | if (null!= mGDCompressImageListener) mGDCompressImageListener.OnSuccess(path);
155 | }
156 | });
157 | }catch (Exception e){
158 | e.printStackTrace();
159 | if (null!= mGDCompressImageListener) mGDCompressImageListener.OnSuccess(path);
160 | }
161 | }
162 | private void InformCallError(final int code, final String errorMsg){
163 | try {
164 | if (null!=garbage && garbage.size()>0){
165 | for (int i = 0; i < garbage.size(); i++) {
166 | Bitmap bitmap = garbage.get(i);
167 | if(bitmap != null && !bitmap.isRecycled()){
168 | bitmap.recycle();
169 | bitmap = null;
170 | }
171 | }
172 | garbage.clear();
173 | System.gc();
174 | }
175 | }catch (Exception e){e.printStackTrace();}
176 | try {
177 | ((Activity) mContext).runOnUiThread(new Runnable() {
178 | @Override
179 | public void run() {
180 | if (null!= mGDCompressImageListener) mGDCompressImageListener.OnError(code, errorMsg);
181 | }
182 | });
183 | }catch (Exception e){
184 | e.printStackTrace();
185 | if (null!= mGDCompressImageListener) mGDCompressImageListener.OnError(code, errorMsg);
186 | }
187 | }
188 |
189 |
190 |
191 | }
192 |
--------------------------------------------------------------------------------
/gdcplibrary/src/main/java/com/wgd/gdcp/gdcplibrary/GDCompressImageListener.java:
--------------------------------------------------------------------------------
1 | package com.wgd.gdcp.gdcplibrary;
2 |
3 | /*
4 | * 压缩回调接口
5 | * */
6 | public interface GDCompressImageListener {
7 |
8 | void OnSuccess(String path);
9 |
10 | void OnError(int code, String errorMsg);
11 |
12 | }
13 |
--------------------------------------------------------------------------------
/gdcplibrary/src/main/java/com/wgd/gdcp/gdcplibrary/GDCompressImageListenerA.java:
--------------------------------------------------------------------------------
1 | package com.wgd.gdcp.gdcplibrary;
2 |
3 | /*
4 | * 压缩回调接口
5 | * */
6 | public interface GDCompressImageListenerA {
7 |
8 | void OnSuccess(GDImageBean gdImageBean);
9 |
10 | void OnError(GDImageBean gdImageBean);
11 |
12 | }
13 |
--------------------------------------------------------------------------------
/gdcplibrary/src/main/java/com/wgd/gdcp/gdcplibrary/GDCompressImageS.java:
--------------------------------------------------------------------------------
1 | package com.wgd.gdcp.gdcplibrary;
2 |
3 | import android.app.Activity;
4 | import android.content.Context;
5 | import android.graphics.Bitmap;
6 | import android.graphics.BitmapFactory;
7 | import android.text.TextUtils;
8 | import android.util.Log;
9 |
10 | import com.wgd.gdcp.gdcplibrary.thread.ThreadManager;
11 |
12 | import java.util.ArrayList;
13 | import java.util.List;
14 |
15 | /*
16 | * Compression of Multiple Pictures
17 | *
18 | * Please apply for permission dynamically
19 | * android.permission.WRITE_EXTERNAL_STORAGE
20 | * android.permission.READ_EXTERNAL_STORAGE
21 | *
22 | * */
23 | public class GDCompressImageS {
24 |
25 | private Context mContext;
26 | private GDCompressImageSListener mGDCompressImageSListener;
27 | private List imageBeanList;
28 | List newImageBean = new ArrayList<>();
29 | private boolean isHaveFail = false ;
30 | private List garbage = new ArrayList<>();
31 |
32 | public GDCompressImageS(Context context, List imageBeanList, GDCompressImageSListener GDCompressImageSListener){
33 | this.mContext = context ;
34 | this.mGDCompressImageSListener = GDCompressImageSListener;
35 | this.imageBeanList = imageBeanList ;
36 | startCompressSA();
37 | // startCompressS();
38 | // startCompress();
39 | }
40 |
41 | //GDCompressA
42 | private void startCompressSA(){
43 | if (null!=imageBeanList && imageBeanList.size() >0) {
44 | newImageBean.clear();
45 | isHaveFail = false;
46 | GDCompressA gdCompressA = new GDCompressA(mContext, new GDCompressImageListenerA() {
47 | @Override
48 | public void OnSuccess(GDImageBean gdImageBean) {
49 | Log.i("GDCimage", "OnSuccess: ========0002========");
50 | InformCallFinish(gdImageBean);
51 | }
52 |
53 | @Override
54 | public void OnError(GDImageBean gdImageBean) {
55 | Log.i("GDCimage", "OnError: ========0003========");
56 | InformCallFinish(gdImageBean);
57 | }
58 | });
59 | for (int i = 0; i < imageBeanList.size(); i++) {
60 | final GDImageBean imageBeana = imageBeanList.get(i);
61 | gdCompressA.start(imageBeana);
62 | }
63 | }else {
64 | if (null!= mGDCompressImageSListener) mGDCompressImageSListener.OnError(newImageBean);
65 | }
66 | }
67 | private void startCompressS(){
68 | if (null!=imageBeanList && imageBeanList.size() >0){
69 | newImageBean.clear();
70 | isHaveFail = false ;
71 |
72 | for ( int i = 0; i < imageBeanList.size(); i++) {
73 | final GDImageBean imageBeana = imageBeanList.get(i);
74 | Log.i("GDCimage", "startCompressS: ========0001========" + i);
75 | new GDCompressC(mContext,
76 | imageBeana.getmGDConfig(), new GDCompressImageListener() {
77 | @Override
78 | public void OnSuccess(String path) {
79 | Log.i("GDCimage", "OnSuccess: ========0002========");
80 | GDImageBean imageBean = imageBeana;
81 | imageBean.setCode(0);
82 | InformCallFinish(imageBean);
83 | }
84 |
85 | @Override
86 | public void OnError(int code, String errorMsg) {
87 | Log.i("GDCimage", "OnError: ========0003========");
88 | GDImageBean imageBean = imageBeana;
89 | isHaveFail = true ;
90 | imageBean.setCode(1);
91 | imageBean.setErrorMsg("Image compression failure!");
92 | InformCallFinish(imageBean);
93 | }
94 | });
95 | }
96 | }else {
97 | if (null!= mGDCompressImageSListener) mGDCompressImageSListener.OnError(newImageBean);
98 | }
99 | }
100 | private void startCompress(){
101 | Log.i("GDCimage", "startCompress: ======imageBeanList.size()=======" + imageBeanList.size());
102 | if (null!=imageBeanList && imageBeanList.size() >0){
103 | newImageBean.clear();
104 | isHaveFail = false ;
105 | for ( int i = 0; i < imageBeanList.size(); i++) {
106 | final GDImageBean imageBeana = imageBeanList.get(i);
107 |
108 | ThreadManager.getIO().execute(new Runnable() {
109 | @Override
110 | public void run() {
111 | Bitmap bitmapMin = null;
112 | String mPath = imageBeana.getmGDConfig().getmPath();
113 | GDImageBean imageBean = imageBeana ;
114 | if (!GDTools.ImageTesting(mPath)){
115 | // InformCallError(1, "Incorrect picture format!");
116 | imageBean.setCode(1);
117 | imageBean.setErrorMsg("Image compression failure!");
118 | InformCallFinish(imageBean);
119 |
120 | // continue;
121 | }else {
122 | String savePath = imageBeana.getmGDConfig().getSavePath();
123 |
124 | if (null==savePath|| TextUtils.isEmpty(savePath)){
125 | GDConfig gdConfig = imageBeana.getmGDConfig();
126 | gdConfig.setSavePath(mPath);
127 | imageBean.setmGDConfig(gdConfig);
128 | }
129 |
130 | GDConfig mGDConfig = imageBean.getmGDConfig();
131 |
132 | if (mGDConfig.isChangeWH()){
133 | if (mGDConfig.getWidth() <=0 || mGDConfig.getHeight() <= 0){
134 | try {
135 | bitmapMin = new GDCompressUtil().SysCompressMin(mGDConfig.getmPath());
136 | // bitmapMin= new GDCompressUtil().SysCompressMin(bitmap);
137 | } catch (Exception e) {
138 | e.printStackTrace();
139 | }
140 | if (null==bitmapMin) Log.i("GDCimage", "startCompress: ====== null==bitmapMin =======" );
141 | garbage.add(bitmapMin);
142 | if (null== bitmapMin){
143 | isHaveFail = true ;
144 | imageBean.setCode(1);
145 | imageBean.setErrorMsg("Image compression failure!");
146 | }else {
147 | if (new GDCompressUtil().compressLibJpeg(bitmapMin, mGDConfig.getSavePath())) {
148 | imageBean.setCode(0);
149 | } else {
150 | isHaveFail = true ;
151 | imageBean.setCode(1);
152 | imageBean.setErrorMsg("Image compression failure!");
153 | }
154 | }
155 |
156 | InformCallFinish(imageBean);
157 |
158 | }else {
159 | try {
160 | bitmapMin = new GDCompressUtil().SysCompressMin(mGDConfig.getmPath());
161 | // bitmapMin= new GDCompressUtil().SysCompressMin(bitmap);
162 | } catch (Exception e) {
163 | e.printStackTrace();
164 | }
165 | garbage.add(bitmapMin);
166 | if (null== bitmapMin){
167 | isHaveFail = true ;
168 | imageBean.setCode(1);
169 | imageBean.setErrorMsg("Image compression failure!");
170 | }else {
171 | if (new GDCompressUtil().compressLibJpeg(bitmapMin, mGDConfig.getSavePath())) {
172 | imageBean.setCode(0);
173 | } else {
174 | isHaveFail = true ;
175 | imageBean.setCode(1);
176 | imageBean.setErrorMsg("Image compression failure!");
177 | }
178 | }
179 |
180 | InformCallFinish(imageBean);
181 | }
182 | }else {
183 | try {
184 | bitmapMin = GDBitmapUtil.getBitmap(mGDConfig.getmPath());
185 | } catch (Exception e) {
186 | e.printStackTrace();
187 | bitmapMin = BitmapFactory.decodeFile(mGDConfig.getmPath());
188 | }
189 | if (null==bitmapMin) Log.i("GDCimage", "startCompress: ==== else == null==bitmapMin =======" );
190 | garbage.add(bitmapMin);
191 | if (new GDCompressUtil().compressLibJpeg(bitmapMin, mGDConfig.getSavePath())){
192 | imageBean.setCode(0);
193 | }else {
194 | isHaveFail = true ;
195 | imageBean.setCode(1);
196 | imageBean.setErrorMsg("Image compression failure!");
197 | }
198 | InformCallFinish(imageBean);
199 | }
200 | }
201 | }
202 | });
203 | }
204 |
205 | }else {
206 | if (null!= mGDCompressImageSListener) mGDCompressImageSListener.OnError(newImageBean);
207 | }
208 | }
209 |
210 |
211 | private void InformCallFinish(final GDImageBean imageBean){
212 | newImageBean.add(imageBean);
213 | try {
214 | GDBitmapUtil.saveBitmapDegree(imageBean.getmGDConfig().getSavePath());
215 | }catch (Exception e){e.printStackTrace();}
216 | if (newImageBean.size() >= imageBeanList.size()){
217 | try {
218 | if (null!=garbage && garbage.size()>0){
219 | for (int i = 0; i < garbage.size(); i++) {
220 | Bitmap bitmap = garbage.get(i);
221 | if(bitmap != null && !bitmap.isRecycled()){
222 | bitmap.recycle();
223 | bitmap = null;
224 | }
225 | }
226 | System.gc();
227 | }
228 | }catch (Exception e){e.printStackTrace();}
229 | try {
230 | ((Activity) mContext).runOnUiThread(new Runnable() {
231 | @Override
232 | public void run() {
233 | if (null!= mGDCompressImageSListener){
234 | if (isHaveFail){
235 | mGDCompressImageSListener.OnError(newImageBean);
236 | }else {
237 | mGDCompressImageSListener.OnSuccess(newImageBean);
238 | }
239 | }
240 | }
241 | });
242 | }catch (Exception e){
243 | e.printStackTrace();
244 | if (null!= mGDCompressImageSListener){
245 | if (isHaveFail){
246 | mGDCompressImageSListener.OnError(newImageBean);
247 | }else {
248 | mGDCompressImageSListener.OnSuccess(newImageBean);
249 | }
250 | }
251 | }
252 | }
253 | }
254 |
255 | }
256 |
--------------------------------------------------------------------------------
/gdcplibrary/src/main/java/com/wgd/gdcp/gdcplibrary/GDCompressImageSListener.java:
--------------------------------------------------------------------------------
1 | package com.wgd.gdcp.gdcplibrary;
2 |
3 | import java.util.List;
4 |
5 | /*
6 | * 压缩回调接口
7 | * */
8 | public interface GDCompressImageSListener {
9 |
10 | void OnSuccess(List imageBeanList);
11 |
12 | void OnError(List imageBeanList);
13 |
14 | }
15 |
--------------------------------------------------------------------------------
/gdcplibrary/src/main/java/com/wgd/gdcp/gdcplibrary/GDCompressUtil.java:
--------------------------------------------------------------------------------
1 | package com.wgd.gdcp.gdcplibrary;
2 |
3 | import android.graphics.Bitmap;
4 | import android.graphics.BitmapFactory;
5 |
6 | import java.io.ByteArrayOutputStream;
7 | import java.io.FileInputStream;
8 |
9 | public class GDCompressUtil {
10 |
11 | private int computeSize(int srcWidth, int srcHeight) {
12 | srcWidth = srcWidth % 2 == 1 ? srcWidth + 1 : srcWidth;
13 | srcHeight = srcHeight % 2 == 1 ? srcHeight + 1 : srcHeight;
14 |
15 | int longSide = Math.max(srcWidth, srcHeight);
16 | int shortSide = Math.min(srcWidth, srcHeight);
17 |
18 | float scale = ((float) shortSide / longSide);
19 | if (scale <= 1 && scale > 0.5625) {
20 | if (longSide < 1664) {
21 | return 1;
22 | } else if (longSide >= 1664 && longSide < 4990) {
23 | return 2;
24 | } else if (longSide > 4990 && longSide < 10240) {
25 | return 4;
26 | } else {
27 | return longSide / 1280 == 0 ? 1 : longSide / 1280;
28 | }
29 | } else if (scale <= 0.5625 && scale > 0.5) {
30 | return longSide / 1280 == 0 ? 1 : longSide / 1280;
31 | } else {
32 | return (int) Math.ceil(longSide / (1280.0 / scale));
33 | }
34 | }
35 |
36 | /*
37 | * 系统压缩,图片大小会改变,以1280为基准
38 | */
39 | public Bitmap SysCompressMin(String imgFilePath) throws Exception {
40 |
41 | BitmapFactory.Options options = new BitmapFactory.Options();
42 | options.inJustDecodeBounds = true;
43 | FileInputStream inputStream = null;
44 | int imgWidth = 0 ;
45 | int imgHeight = 0 ;
46 | try {
47 | inputStream = new FileInputStream(imgFilePath);
48 | BitmapFactory.decodeStream(inputStream, null, options);//由于options.inJustDecodeBounds位true,所以这里并没有在内存中解码图片,只是为了得到原始图片的大小
49 | imgWidth = options.outWidth;
50 | imgHeight = options.outHeight;
51 | }catch (Exception e){e.printStackTrace();}
52 | if(inputStream != null){
53 | try {
54 | inputStream.close();
55 | } catch (Exception e) {
56 | }
57 | }
58 | options.inJustDecodeBounds = false ;
59 | // BitmapFactory.Options options = new BitmapFactory.Options();
60 | options.inSampleSize = computeSize(imgWidth, imgHeight);
61 |
62 | // FileInputStream inputStream = null;
63 | try {
64 | inputStream = new FileInputStream(imgFilePath);
65 | return BitmapFactory.decodeStream(inputStream, null, options);//加载原图
66 | }catch (Exception e){e.printStackTrace();}
67 |
68 | return null;
69 | }
70 | /*
71 | * 系统压缩,图片大小会改变,以1280为基准
72 | */
73 | public Bitmap SysCompressMin(Bitmap bitmap) throws Exception {
74 | BitmapFactory.Options options = new BitmapFactory.Options();
75 | options.inSampleSize = computeSize(bitmap.getWidth(), bitmap.getHeight());
76 | ByteArrayOutputStream stream = new ByteArrayOutputStream();
77 | bitmap.compress(Bitmap.CompressFormat.JPEG, 100, stream);
78 | byte[] byteArray = stream.toByteArray();
79 | // Bitmap tagBitmap = BitmapFactory.decodeByteArray(byteArray, 0, byteArray.length, options);
80 | // return tagBitmap;
81 | bitmap = BitmapFactory.decodeByteArray(byteArray, 0, byteArray.length, options);
82 | return bitmap;
83 | }
84 | /*
85 | * 系统压缩,图片大小会改变,
86 | */
87 | public Bitmap SysCompressMySamp(String imgFilePath, int width, int height) throws Exception {
88 |
89 |
90 | BitmapFactory.Options options = new BitmapFactory.Options();
91 | options.inJustDecodeBounds = true;
92 | FileInputStream inputStream = null;
93 | int imgWidth = 0 ;
94 | int imgHeight = 0 ;
95 | try {
96 | inputStream = new FileInputStream(imgFilePath);
97 | BitmapFactory.decodeStream(inputStream, null, options);//由于options.inJustDecodeBounds位true,所以这里并没有在内存中解码图片,只是为了得到原始图片的大小
98 | imgWidth = options.outWidth;
99 | imgHeight = options.outHeight;
100 | }catch (Exception e){e.printStackTrace();}
101 | if(inputStream != null){
102 | try {
103 | inputStream.close();
104 | } catch (Exception e) {
105 | }
106 | }
107 | options.inJustDecodeBounds = false ;
108 | // BitmapFactory.Options options = new BitmapFactory.Options();
109 | int samp = GDTools.getSampWHforImage(imgWidth, imgHeight, width, height);
110 | options.inSampleSize = samp;
111 |
112 | // FileInputStream inputStream = null;
113 | try {
114 | inputStream = new FileInputStream(imgFilePath);
115 | return BitmapFactory.decodeStream(inputStream, null, options);//加载原图
116 | }catch (Exception e){e.printStackTrace();}
117 |
118 | return null;
119 | }
120 |
121 |
122 | public boolean compressLibJpeg(Bitmap bitmap, String savePath){
123 | try {
124 | if (null==bitmap)return false;
125 | return compressLibJpeg(bitmap, savePath, 20);
126 | }catch (Exception e){e.printStackTrace();}
127 | return false;
128 | }
129 |
130 | public boolean compressLibJpeg(Bitmap bitmap, String savePath, int quality){
131 | try {
132 | if (null==bitmap)return false;
133 | boolean codeString = ImageUtils.compressBitmap(bitmap, bitmap.getWidth(), bitmap.getHeight(), savePath, quality);
134 | return codeString;
135 | }catch (Exception e){e.printStackTrace();}
136 | return false;
137 | }
138 | /*
139 | * path 原图路径
140 | * */
141 | public boolean compressLibJpeg(String path, String savePath){
142 | try {
143 | Bitmap bitmap = BitmapFactory.decodeFile(path);
144 | return compressLibJpeg(bitmap, savePath, 20);
145 | }catch (Exception e){e.printStackTrace();}
146 | return false;
147 | }
148 | /*
149 | * path 原图路径
150 | * */
151 | public boolean compressLibJpeg(String path, String savePath, int quality){
152 | try {
153 | Bitmap bitmap = BitmapFactory.decodeFile(path);
154 | return compressLibJpeg(bitmap, savePath, quality);
155 | }catch (Exception e){e.printStackTrace();}
156 | return false;
157 | }
158 |
159 |
160 |
161 | }
162 |
--------------------------------------------------------------------------------
/gdcplibrary/src/main/java/com/wgd/gdcp/gdcplibrary/GDConfig.java:
--------------------------------------------------------------------------------
1 | package com.wgd.gdcp.gdcplibrary;
2 |
3 | public class GDConfig {
4 |
5 | /*
6 | * Whether you want to change the picture width and height, so that the image compression is smaller.
7 | * */
8 | private boolean isChangeWH = false ;//
9 | private int width = 0 ;
10 | private int height = 0 ;
11 |
12 | private String mPath ;
13 | private String savePath ;
14 | // private GDCompressImageListener mGDCompressImageListener;
15 |
16 | public boolean isChangeWH() {
17 | return isChangeWH;
18 | }
19 |
20 | public GDConfig setChangeWH(boolean changeWH) {
21 | isChangeWH = changeWH;
22 | return this;
23 | }
24 |
25 | public int getWidth() {
26 | return width;
27 | }
28 |
29 | public GDConfig setWidth(int width) {
30 | this.width = width;
31 | return this;
32 | }
33 |
34 | public int getHeight() {
35 | return height;
36 | }
37 |
38 | public GDConfig setHeight(int height) {
39 | this.height = height;
40 | return this;
41 | }
42 |
43 | public String getmPath() {
44 | return mPath;
45 | }
46 |
47 | public GDConfig setmPath(String mPath) {
48 | this.mPath = mPath;
49 | return this;
50 | }
51 |
52 | public String getSavePath() {
53 | return savePath;
54 | }
55 |
56 | public GDConfig setSavePath(String savePath) {
57 | this.savePath = savePath;
58 | return this;
59 | }
60 |
61 | // public GDCompressImageListener getmGDCompressImageListener() {
62 | // return mGDCompressImageListener;
63 | // }
64 | //
65 | // public GDConfig setmGDCompressImageListener(GDCompressImageListener mGDCompressImageListener) {
66 | // this.mGDCompressImageListener = mGDCompressImageListener;
67 | // return this;
68 | // }
69 | }
70 |
--------------------------------------------------------------------------------
/gdcplibrary/src/main/java/com/wgd/gdcp/gdcplibrary/GDImageBean.java:
--------------------------------------------------------------------------------
1 | package com.wgd.gdcp.gdcplibrary;
2 |
3 | public class GDImageBean {
4 |
5 | private GDConfig mGDConfig;
6 |
7 | private int code = -1 ;//-1=Not operated;0=Success;1=fail
8 | private String errorMsg = "" ;
9 |
10 | public GDImageBean(){
11 |
12 | }
13 | public GDImageBean(GDConfig mGDConfig){
14 | this.mGDConfig = mGDConfig;
15 | }
16 |
17 | public int getCode() {
18 | return code;
19 | }
20 |
21 | public void setCode(int code) {
22 | this.code = code;
23 | }
24 |
25 | public String getErrorMsg() {
26 | return errorMsg;
27 | }
28 |
29 | public void setErrorMsg(String errorMsg) {
30 | this.errorMsg = errorMsg;
31 | }
32 |
33 | public GDConfig getmGDConfig() {
34 | return null==mGDConfig?new GDConfig():mGDConfig;
35 | }
36 |
37 | public void setmGDConfig(GDConfig mGDConfig) {
38 | this.mGDConfig = mGDConfig;
39 | }
40 | }
41 |
--------------------------------------------------------------------------------
/gdcplibrary/src/main/java/com/wgd/gdcp/gdcplibrary/GDTools.java:
--------------------------------------------------------------------------------
1 | package com.wgd.gdcp.gdcplibrary;
2 |
3 | import android.app.Activity;
4 | import android.content.Context;
5 | import android.content.res.Resources;
6 | import android.util.DisplayMetrics;
7 |
8 | public class GDTools {
9 |
10 | /*
11 | * 以720*1280为标准,计算图片宽高
12 | * */
13 | public static int[] getWH(int width, int height){
14 | int whSize[] = new int[2];
15 | double whb = (double) width / (double) height;
16 | double finwhb = 1280.0 / 720.0;
17 | int newwidth = 1280;
18 | int newheight = 720;
19 | if (whb > finwhb){//以高度为标准
20 | newwidth = (int) (720 * whb);
21 | }else if (whb < finwhb){//以宽度为标准
22 | newheight = (int) (1280 / whb);
23 | }
24 | whSize[0] = newwidth;
25 | whSize[1] = newheight;
26 | return whSize;
27 | }
28 | /*
29 | * 以实际设备宽高为标准,计算图片宽高
30 | * */
31 | public static int[] getDevWH(Context context){
32 | int whSize[] = new int[2];
33 |
34 | Resources resources = context.getResources();
35 | DisplayMetrics dm = resources.getDisplayMetrics();
36 | float density = dm.density;
37 | int width = dm.widthPixels;
38 | int height = dm.heightPixels;
39 |
40 | double whb = (double) width / (double) height;
41 | // double finwhb = 720.0 / 1280.0;
42 | double finwhb = 1280.0 / 720.0;
43 | int newwidth = 1280;
44 | int newheight = 720;
45 | if (whb > finwhb){//以高度为标准
46 | newwidth = (int) (720 * whb);
47 | }else if (whb < finwhb){//以宽度为标准
48 | newheight = (int) (1280 / whb);
49 | }
50 | whSize[0] = newwidth;
51 | whSize[1] = newheight;
52 |
53 | return whSize;
54 | }
55 |
56 | public static int getSampWHforImage(int imageWidth, int imageHeight, int width, int height){
57 | double whbIMG = (double) imageWidth / (double) imageHeight ;
58 | double whb = (double) width / (double) height ;
59 | int a = 1 ;
60 | if (whbIMG >= whb){
61 | a = imageWidth / width ;
62 | }else {
63 | a = imageHeight / height ;
64 | }
65 | if (a%2 == 1)a = a+1;
66 | return a ;
67 | }
68 | //
69 | public static boolean ImageTesting(String path){
70 | String mpath = path.toLowerCase();
71 | if (mpath.endsWith("png") || mpath.endsWith("jpg") || mpath.endsWith("jpeg") || mpath.endsWith("webp") )
72 | return true;
73 | else return false ;
74 | }
75 |
76 | }
77 |
--------------------------------------------------------------------------------
/gdcplibrary/src/main/java/com/wgd/gdcp/gdcplibrary/ImageUtils.java:
--------------------------------------------------------------------------------
1 | package com.wgd.gdcp.gdcplibrary;
2 |
3 | import android.graphics.Bitmap;
4 |
5 | /**
6 | *
7 | *
8 | * @author KINCAI
9 | *
10 | */
11 | public class ImageUtils {
12 | static {
13 | // System.loadLibrary("jpeg");// libjpeg
14 | System.loadLibrary("gdimage");//
15 | }
16 |
17 |
18 | // public static native String compressBitmap(Bitmap bitmap, int width,
19 | // int height, int quality, byte[] fileName, boolean optimize);
20 | public static native boolean compressBitmap(Bitmap bitmap, int width, int height, String fileName, int quality);
21 |
22 | }
23 |
--------------------------------------------------------------------------------
/gdcplibrary/src/main/java/com/wgd/gdcp/gdcplibrary/thread/ThreadManager.java:
--------------------------------------------------------------------------------
1 | package com.wgd.gdcp.gdcplibrary.thread;
2 |
3 | import com.lzh.easythread.Callback;
4 | import com.lzh.easythread.EasyThread;
5 |
6 | public final class ThreadManager {
7 |
8 | private final static EasyThread io;
9 | private final static EasyThread io1;
10 | private final static EasyThread cache;
11 | private final static EasyThread calculator;
12 | private final static EasyThread file;
13 |
14 | public static EasyThread getIO () {
15 | return io;
16 | }
17 | public static EasyThread getIO1 () {
18 | return io1;
19 | }
20 |
21 |
22 | public static EasyThread getCache() {
23 | return cache;
24 | }
25 |
26 | public static EasyThread getCalculator() {
27 | return calculator;
28 | }
29 |
30 | public static EasyThread getFile() {
31 | return file;
32 | }
33 |
34 | static {
35 | //创建一个可缓存线程池,如果线程池长度超过处理需要,可灵活回收空闲线程,若无可回收,则新建线程。
36 | cache = EasyThread.Builder.createCacheable().setName("cache").setCallback(new DefaultCallback()).build();
37 | //创建一个定长线程池,可控制线程最大并发数,超出的线程会在队列中等待。
38 | io = EasyThread.Builder.createFixed(6).setName("IO").setPriority(7).setCallback(new DefaultCallback()).build();
39 | io1 = EasyThread.Builder.createFixed(1).setName("IO1").setPriority(7).setCallback(new DefaultCallback()).build();
40 |
41 | calculator = EasyThread.Builder.createFixed(4).setName("calculator").setPriority(Thread.MAX_PRIORITY).setCallback(new DefaultCallback()).build();
42 | file = EasyThread.Builder.createFixed(4).setName("file").setPriority(3).setCallback(new DefaultCallback()).build();
43 | }
44 |
45 | private static class DefaultCallback implements Callback {
46 |
47 | @Override
48 | public void onError(String threadName, Throwable t) {
49 | // MyLog.e("Task with thread %s has occurs an error: %s", threadName, t.getMessage());
50 | }
51 |
52 | @Override
53 | public void onCompleted(String threadName) {
54 | // MyLog.d("Task with thread %s completed", threadName);
55 | }
56 |
57 | @Override
58 | public void onStart(String threadName) {
59 | // MyLog.d("Task with thread %s start running!", threadName);
60 | }
61 | }
62 |
63 | private void stop(){
64 |
65 | }
66 |
67 | }
68 |
--------------------------------------------------------------------------------
/gdcplibrary/src/main/jniLibs/arm64-v8a/README.md:
--------------------------------------------------------------------------------
1 |
2 | 这里需要两个so文件
3 | 1、libgdimage.so
4 | 2、libjpeg.so
5 | 这里的libjpeg.so文件需要去下载,下载地址为:https://download.csdn.net/download/hh7181521/10537394
6 |
--------------------------------------------------------------------------------
/gdcplibrary/src/main/jniLibs/arm64-v8a/libgdimage.so:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/WGDrzjz/ImageCompress/ba307d81e9c2681001c3eeb492b684ca687a584f/gdcplibrary/src/main/jniLibs/arm64-v8a/libgdimage.so
--------------------------------------------------------------------------------
/gdcplibrary/src/main/jniLibs/armeabi-v7a/README.md:
--------------------------------------------------------------------------------
1 | 这里需要两个so文件
2 | 1、libgdimage.so
3 | 2、libjpeg.so
4 | 这里的libjpeg.so文件需要去下载,下载地址为:https://download.csdn.net/download/hh7181521/10537408
--------------------------------------------------------------------------------
/gdcplibrary/src/main/jniLibs/armeabi-v7a/libgdimage.so:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/WGDrzjz/ImageCompress/ba307d81e9c2681001c3eeb492b684ca687a584f/gdcplibrary/src/main/jniLibs/armeabi-v7a/libgdimage.so
--------------------------------------------------------------------------------
/gdcplibrary/src/main/jniLibs/armeabi/README.md:
--------------------------------------------------------------------------------
1 | 这里需要两个so文件
2 | 1、libgdimage.so
3 | 2、libjpeg.so
4 | 这里的libjpeg.so文件需要去下载,下载地址为:https://download.csdn.net/download/hh7181521/10537408
--------------------------------------------------------------------------------
/gdcplibrary/src/main/jniLibs/armeabi/libgdimage.so:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/WGDrzjz/ImageCompress/ba307d81e9c2681001c3eeb492b684ca687a584f/gdcplibrary/src/main/jniLibs/armeabi/libgdimage.so
--------------------------------------------------------------------------------
/gdcplibrary/src/main/res/values/strings.xml:
--------------------------------------------------------------------------------
1 |
2 | GDCPlibrary
3 |
4 |
--------------------------------------------------------------------------------
/gdcplibrary/src/test/java/com/wgd/gdcp/gdcplibrary/ExampleUnitTest.java:
--------------------------------------------------------------------------------
1 | package com.wgd.gdcp.gdcplibrary;
2 |
3 | import org.junit.Test;
4 |
5 | import static org.junit.Assert.*;
6 |
7 | /**
8 | * Example local unit test, which will execute on the development machine (host).
9 | *
10 | * @see Testing documentation
11 | */
12 | public class ExampleUnitTest {
13 | @Test
14 | public void addition_isCorrect() {
15 | assertEquals(4, 2 + 2);
16 | }
17 | }
--------------------------------------------------------------------------------
/gradle.properties:
--------------------------------------------------------------------------------
1 | # Project-wide Gradle settings.
2 | # IDE (e.g. Android Studio) users:
3 | # Gradle settings configured through the IDE *will override*
4 | # any settings specified in this file.
5 | # For more details on how to configure your build environment visit
6 | # http://www.gradle.org/docs/current/userguide/build_environment.html
7 | # Specifies the JVM arguments used for the daemon process.
8 | # The setting is particularly useful for tweaking memory settings.
9 | org.gradle.jvmargs=-Xmx1536m
10 | # When configured, Gradle will run in incubating parallel mode.
11 | # This option should only be used with decoupled projects. More details, visit
12 | # http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects
13 | # org.gradle.parallel=true
14 |
--------------------------------------------------------------------------------
/gradle/wrapper/gradle-wrapper.jar:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/WGDrzjz/ImageCompress/ba307d81e9c2681001c3eeb492b684ca687a584f/gradle/wrapper/gradle-wrapper.jar
--------------------------------------------------------------------------------
/gradle/wrapper/gradle-wrapper.properties:
--------------------------------------------------------------------------------
1 | #Thu Jul 05 10:10:19 CST 2018
2 | distributionBase=GRADLE_USER_HOME
3 | distributionPath=wrapper/dists
4 | zipStoreBase=GRADLE_USER_HOME
5 | zipStorePath=wrapper/dists
6 | distributionUrl=https\://services.gradle.org/distributions/gradle-4.4-all.zip
7 |
--------------------------------------------------------------------------------
/settings.gradle:
--------------------------------------------------------------------------------
1 | include ':app', ':gdcplibrary'
2 |
--------------------------------------------------------------------------------