├── .gitignore ├── .idea ├── compiler.xml ├── copyright │ └── profiles_settings.xml ├── encodings.xml ├── gradle.xml ├── inspectionProfiles │ ├── Project_Default.xml │ └── profiles_settings.xml ├── kotlinc.xml ├── misc.xml ├── modules.xml ├── runConfigurations.xml └── vcs.xml ├── README.md ├── app ├── .gitignore ├── build.gradle ├── proguard-rules.pro └── src │ └── main │ ├── AndroidManifest.xml │ ├── java │ └── com │ │ └── march │ │ └── gifmakersample │ │ ├── MainActivity.java │ │ └── MyApplication.java │ └── res │ ├── layout │ └── activity_main.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 ├── backup └── giflen │ ├── so │ ├── GifUtil.java │ ├── README.md │ ├── gifflen.jar │ └── libgifflen.so │ └── sourcecode │ ├── Android.mk │ ├── dib.c │ ├── dib.h │ ├── gifflen.cpp │ └── neuquant.h ├── build.gradle ├── gifmaker ├── .gitignore ├── build.gradle ├── proguard-rules.pro └── src │ └── main │ ├── AndroidManifest.xml │ ├── java │ └── com │ │ └── march │ │ └── gifmaker │ │ ├── GifMaker.java │ │ ├── base │ │ ├── GifEncoder.java │ │ ├── LZWEncoder.java │ │ └── NeuQuant.java │ │ ├── extend │ │ ├── LZWEncoderOrderHolder.java │ │ └── ThreadGifEncoder.java │ │ └── utils │ │ └── Util.java │ └── res │ └── values │ └── strings.xml ├── gradle.properties ├── gradle └── wrapper │ ├── gradle-wrapper.jar │ └── gradle-wrapper.properties ├── gradlew ├── gradlew.bat └── settings.gradle /.gitignore: -------------------------------------------------------------------------------- 1 | *.iml 2 | .gradle 3 | /local.properties 4 | /.idea/workspace.xml 5 | /.idea/libraries 6 | .DS_Store 7 | /build 8 | /captures 9 | .externalNativeBuild 10 | -------------------------------------------------------------------------------- /.idea/compiler.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | -------------------------------------------------------------------------------- /.idea/copyright/profiles_settings.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | -------------------------------------------------------------------------------- /.idea/encodings.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /.idea/gradle.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 18 | 19 | -------------------------------------------------------------------------------- /.idea/inspectionProfiles/Project_Default.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 10 | -------------------------------------------------------------------------------- /.idea/inspectionProfiles/profiles_settings.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 7 | -------------------------------------------------------------------------------- /.idea/kotlinc.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 7 | -------------------------------------------------------------------------------- /.idea/misc.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 19 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | Android 39 | 40 | 41 | Android > Lint > Correctness 42 | 43 | 44 | Class structureJava 45 | 46 | 47 | Code maturity issuesJava 48 | 49 | 50 | Java 51 | 52 | 53 | Java language level migration aidsJava 54 | 55 | 56 | Javadoc issuesJava 57 | 58 | 59 | Performance issuesJava 60 | 61 | 62 | TestNGJava 63 | 64 | 65 | Threading issuesJava 66 | 67 | 68 | 69 | 70 | Android 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 92 | -------------------------------------------------------------------------------- /.idea/modules.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | -------------------------------------------------------------------------------- /.idea/runConfigurations.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 11 | 12 | -------------------------------------------------------------------------------- /.idea/vcs.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | 2 | ## Android 合成 Gif 3 | 4 | 基于原先的 `LZWEncoder` 算法,使用多线程加快合成速度,现在合成编码速度在 20张/12s。 5 | 6 | **[查看博客介绍](http://zfyx.coding.me/article/3121499733/)** 7 | -------------------------------------------------------------------------------- /app/.gitignore: -------------------------------------------------------------------------------- 1 | /build 2 | -------------------------------------------------------------------------------- /app/build.gradle: -------------------------------------------------------------------------------- 1 | apply plugin: 'com.android.application' 2 | apply plugin: 'com.neenbedankt.android-apt' 3 | 4 | android { 5 | compileSdkVersion 25 6 | buildToolsVersion "25.0.3" 7 | defaultConfig { 8 | applicationId "com.march.gifmaker" 9 | minSdkVersion 15 10 | targetSdkVersion 25 11 | versionCode 1 12 | versionName "1.0" 13 | } 14 | buildTypes { 15 | release { 16 | minifyEnabled false 17 | proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' 18 | } 19 | } 20 | } 21 | 22 | dependencies { 23 | compile fileTree(include: ['*.jar'], dir: 'libs') 24 | 25 | compile rootProject.ext.support.design 26 | compile rootProject.ext.support.appcompat_v7 27 | 28 | apt rootProject.ext.support.butterknife840_processor 29 | compile rootProject.ext.support.butterknife840 30 | 31 | compile 'com.github.chendongMarch:devKit:0.0.4-beta1' 32 | 33 | compile project(':gifmaker') 34 | } 35 | -------------------------------------------------------------------------------- /app/proguard-rules.pro: -------------------------------------------------------------------------------- 1 | # Add project specific ProGuard rules here. 2 | # By default, the flags in this file are appended to flags specified 3 | # in /Users/march/AndroidRes/sdk/tools/proguard/proguard-android.txt 4 | # You can edit the include path and order by changing the proguardFiles 5 | # directive in build.gradle. 6 | # 7 | # For more details, see 8 | # http://developer.android.com/guide/developing/tools/proguard.html 9 | 10 | # Add any project specific keep options here: 11 | 12 | # If your project uses WebView with JS, uncomment the following 13 | # and specify the fully qualified class name to the JavaScript interface 14 | # class: 15 | #-keepclassmembers class fqcn.of.javascript.interface.for.webview { 16 | # public *; 17 | #} 18 | 19 | # Uncomment this to preserve the line number information for 20 | # debugging stack traces. 21 | #-keepattributes SourceFile,LineNumberTable 22 | 23 | # If you keep the line number information, uncomment this to 24 | # hide the original source file name. 25 | #-renamesourcefileattribute SourceFile 26 | -------------------------------------------------------------------------------- /app/src/main/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 6 | 7 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | -------------------------------------------------------------------------------- /app/src/main/java/com/march/gifmakersample/MainActivity.java: -------------------------------------------------------------------------------- 1 | package com.march.gifmakersample; 2 | 3 | import android.graphics.Bitmap; 4 | import android.os.Bundle; 5 | import android.os.Environment; 6 | import android.view.View; 7 | import android.widget.ImageView; 8 | 9 | import com.march.dev.app.activity.BaseActivity; 10 | import com.march.dev.model.ImageInfo; 11 | import com.march.dev.uikit.selectimg.SelectImageActivity; 12 | import com.march.dev.utils.BitmapUtils; 13 | import com.march.dev.utils.GlideUtils; 14 | import com.march.dev.utils.PermissionUtils; 15 | import com.march.gifmaker.GifMaker; 16 | 17 | import org.greenrobot.eventbus.Subscribe; 18 | import org.greenrobot.eventbus.ThreadMode; 19 | 20 | import java.io.File; 21 | import java.util.ArrayList; 22 | import java.util.List; 23 | import java.util.concurrent.ExecutorService; 24 | import java.util.concurrent.Executors; 25 | 26 | import butterknife.BindView; 27 | import butterknife.OnClick; 28 | import io.reactivex.Observable; 29 | import io.reactivex.android.schedulers.AndroidSchedulers; 30 | import io.reactivex.annotations.NonNull; 31 | import io.reactivex.functions.Consumer; 32 | import io.reactivex.functions.Function; 33 | import io.reactivex.schedulers.Schedulers; 34 | 35 | public class MainActivity extends BaseActivity { 36 | 37 | @BindView(R.id.iv_image) ImageView mImageView; 38 | 39 | private ExecutorService mExecutorService = Executors.newCachedThreadPool(); 40 | 41 | @Override 42 | protected int getLayoutId() { 43 | return R.layout.activity_main; 44 | } 45 | 46 | @Override 47 | public void onInitViews(View view, Bundle saveData) { 48 | super.onInitViews(view, saveData); 49 | mExecutorService = Executors.newCachedThreadPool(); 50 | } 51 | 52 | @OnClick({R.id.btn_compose}) 53 | public void onClickView(View view) { 54 | switch (view.getId()) { 55 | case R.id.btn_compose: 56 | SelectImageActivity.start(mActivity, 20); 57 | break; 58 | } 59 | } 60 | 61 | @Override 62 | protected String[] getPermission2Check() { 63 | return new String[]{PermissionUtils.PER_WRITE_EXTERNAL_STORAGE}; 64 | } 65 | 66 | @Subscribe(threadMode = ThreadMode.MAIN) 67 | public void onMainEvent(final SelectImageActivity.SelectImageEvent event) { 68 | switch (event.getMessage()) { 69 | case SelectImageActivity.SelectImageEvent.ON_SUCCESS: 70 | final List bitmaps = new ArrayList<>(); 71 | Observable.fromIterable(event.mImageInfos) 72 | .map(new Function() { 73 | @Override 74 | public Bitmap apply(@NonNull ImageInfo imageInfo) throws Exception { 75 | return BitmapUtils.decodeFile(imageInfo.getPath(), 600, 600); 76 | } 77 | }) 78 | .subscribeOn(Schedulers.io()) 79 | .observeOn(AndroidSchedulers.mainThread()) 80 | .subscribe(new Consumer() { 81 | @Override 82 | public void accept(@NonNull Bitmap bitmap) throws Exception { 83 | bitmaps.add(bitmap); 84 | if (bitmaps.size() == event.mImageInfos.size()) { 85 | composeGif(bitmaps); 86 | } 87 | } 88 | }); 89 | 90 | break; 91 | } 92 | } 93 | 94 | private void composeGif(List bitmaps) { 95 | String absolutePath = new File(Environment.getExternalStorageDirectory() 96 | , System.currentTimeMillis() + ".gif").getAbsolutePath(); 97 | new GifMaker(100, mExecutorService) 98 | .makeGifInThread(bitmaps, absolutePath, new GifMaker.OnGifMakerListener() { 99 | @Override 100 | public void onMakeGifSucceed(String outPath) { 101 | if (!isFinishing()) { 102 | GlideUtils.with(mActivity, outPath).into(mImageView); 103 | } 104 | } 105 | }); 106 | } 107 | } 108 | -------------------------------------------------------------------------------- /app/src/main/java/com/march/gifmakersample/MyApplication.java: -------------------------------------------------------------------------------- 1 | package com.march.gifmakersample; 2 | 3 | import com.march.dev.app.BaseApplication; 4 | 5 | /** 6 | * CreateAt : 7/13/17 7 | * Describe : 8 | * 9 | * @author chendong 10 | */ 11 | public class MyApplication extends BaseApplication { 12 | } 13 | -------------------------------------------------------------------------------- /app/src/main/res/layout/activity_main.xml: -------------------------------------------------------------------------------- 1 | 2 | 6 | 7 |