Skip to content

Commit

Permalink
support for transparent image encoding
Browse files Browse the repository at this point in the history
  • Loading branch information
succlz123 committed Oct 22, 2018
1 parent afc4d1f commit 6a635f5
Show file tree
Hide file tree
Showing 63 changed files with 749 additions and 736 deletions.
84 changes: 73 additions & 11 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,23 +6,23 @@ Idea from: [square/gifencoder](https://github.com/square/gifencoder)

BurstLinker is a simple C++ GIF encode library.

## Android
## Download

### Download
### Android

Gradle:

```
implementation 'com.bilibili:burst-linker:latest-version'
```

### Build Environment
#### Build Environment

Android Studio 3.1.4
Android Studio 3.2.1

NDK r17
NDK r18

### Basic usage
#### Basic usage

``` java
int delayMs = 1000;
Expand All @@ -48,7 +48,7 @@ try {
}
```

### Enable RenderScript Support
#### Enable RenderScript Support

> This is an untested experimental feature
Expand All @@ -57,7 +57,7 @@ try {
3. Uncomment the line 64 of the /lib/CMakeLists.txt
4. Run

## Linux & Mac
### Linux & Mac

1. Install [CMake](http://www.cmake.org/)
- Mac `brew install cmake`
Expand All @@ -73,7 +73,7 @@ try {
- `./BurstLinker 1000 1.jpg 2.jpg 3.jpg`
- See out.gif

## Windows
### Windows

1. Install [Microsoft Visual Studio](https://www.visualstudio.com/) & [CMake](http://www.cmake.org/)

Expand All @@ -89,7 +89,69 @@ try {
- `BurstLinker.exe 1000 1.jpg 2.jpg 3.jpg`
- See out.gif

# Thanks
## Samples

### Different quantizers & ditherers

- Original

![original](screenshot/lenna-original.png)

- Uniform + No

![uniform](screenshot/uniform.gif)

- MedianCut + No

![media-cut](screenshot/media-cut.gif)

- KMeans + No

![k-means](screenshot/k-means.gif)

- Random + No

![random](screenshot/random.gif)

- Octree + No

![octree](screenshot/octree.gif)

- NeuQuant - 10 + No

![neu-quant-10](screenshot/neu-quant-10.gif)

- NeuQuant - 1 + No

![neu-quant-1](screenshot/neu-quant-1.gif)

- Octree + M2

![uniform](screenshot/octree-m2.gif)

- Octree + Bayer

![octree-bayer](screenshot/octree-bayer.gif)

- Octree + FloydSteinberg

![octree-floyd-steinberg](screenshot/octree-floyd-steinberg.gif)

### Encoding with transparent image

- Original

![bilibili](screenshot/bilibili.png)

- Octree + No + Default (ARGB.a != 0)

![bilibili-octree](screenshot/bilibili-octree-default.gif)

- Octree + No + Ignore translucency (ARGB.a == 255)

![bilibili-octree](screenshot/bilibili-octree-ignore.gif)

## Thanks

[square/gifencoder](https://github.com/square/gifencoder)

Expand All @@ -107,7 +169,7 @@ try {

[progschj/ThreadPool](https://github.com/progschj/ThreadPool)

# License
## License

```
Copyright 2018 Bilibili
Expand Down
4 changes: 2 additions & 2 deletions android/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ buildscript {
}
dependencies {
classpath 'com.android.tools.build:gradle:3.1.4'
classpath 'com.novoda:bintray-release:0.8.0'
classpath 'com.novoda:bintray-release:0.8.1'
}
}

Expand All @@ -34,6 +34,6 @@ task clean(type: Delete) {
}

ext {
burstLinkerVer = '0.0.9'
burstLinkerVer = '0.0.11'
libs = ['burstLinkerVer': "com.bilibili:$burstLinkerVer"]
}
44 changes: 22 additions & 22 deletions android/lib/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -14,30 +14,30 @@ cmake_minimum_required(VERSION 3.4.1)

# link_directories(${ANDROID_NDK}/toolchains/renderscript/prebuilt/${ANDROID_HOST_TAG}/platform/${ANDROID_SYSROOT_ABI})

set(srcdir ../../src)
set(src_dir ../../src)

set(SOURCE_FILES
${srcdir}/GifEncoder.cpp
${srcdir}/GifBlockWriter.cpp
${srcdir}/KDTree.cpp
${srcdir}/LzwEncoder.cpp
${srcdir}/Logger.cpp

${srcdir}/NoDitherer.cpp
${srcdir}/BayerDitherer.cpp
${srcdir}/M2Ditherer.cpp
${srcdir}/FloydSteinbergDitherer.cpp

${srcdir}/OctreeQuantizer.cpp
${srcdir}/UniformQuantizer.cpp
${srcdir}/KMeansQuantizer.cpp
${srcdir}/MedianCutQuantizer.cpp
${srcdir}/RandomQuantizer.cpp
${srcdir}/NeuQuant.cpp
${srcdir}/NeuQuantQuantizer.cpp

# ${srcdir}/GifAnalyzer.h
${srcdir}/ThreadPool.h
${src_dir}/GifEncoder.cpp
${src_dir}/GifBlockWriter.cpp
${src_dir}/KDTree.cpp
${src_dir}/LzwEncoder.cpp
${src_dir}/Logger.cpp

${src_dir}/NoDitherer.cpp
${src_dir}/BayerDitherer.cpp
${src_dir}/M2Ditherer.cpp
${src_dir}/FloydSteinbergDitherer.cpp

${src_dir}/OctreeQuantizer.cpp
${src_dir}/UniformQuantizer.cpp
${src_dir}/KMeansQuantizer.cpp
${src_dir}/MedianCutQuantizer.cpp
${src_dir}/RandomQuantizer.cpp
${src_dir}/NeuQuant.cpp
${src_dir}/NeuQuantQuantizer.cpp

# ${src_dir}/GifAnalyzer.h
${src_dir}/ThreadPool.h

src/main/cpp/BurstLinker.cpp
# src/main/cpp/DithererWithRs.cpp
Expand Down
8 changes: 4 additions & 4 deletions android/lib/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -6,11 +6,11 @@ ext {
}

android {
compileSdkVersion 27
buildToolsVersion '27.0.3'
compileSdkVersion 28
buildToolsVersion '28.0.3'
defaultConfig {
minSdkVersion 14
targetSdkVersion 27
targetSdkVersion 28
versionCode 1
versionName VERSION_NAME.toString()
testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
Expand All @@ -25,7 +25,7 @@ android {
// arguments "-DANDROID_ARM_NEON=TRUE"
// arguments "-DANDROID_ABI=armeabi-v7a with NEON"
arguments "-DANDROID_STL=c++_static"
cppFlags "-std=c++11 -fno-rtti -fno-exceptions"
cppFlags "-std=c++14 -fno-rtti -fno-exceptions"
}
}
}
Expand Down
1 change: 0 additions & 1 deletion android/lib/src/main/cpp/BayerDithererWithRs.h
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,6 @@
#include <RenderScript.h>

using namespace android::RSC;
using namespace std;

class BayerDithererWithRs : public DithererWithRs {

Expand Down
2 changes: 1 addition & 1 deletion android/lib/src/main/cpp/BurstLinker.cpp

Large diffs are not rendered by default.

1 change: 0 additions & 1 deletion android/lib/src/main/cpp/DisableDithererWithRs.h
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,6 @@
#include <vector>

using namespace android::RSC;
using namespace std;

class DisableDithererWithRs : public DithererWithRs {

Expand Down
1 change: 0 additions & 1 deletion android/lib/src/main/cpp/NoDithererWithRs.h
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,6 @@
#include <vector>

using namespace android::RSC;
using namespace std;

class NoDithererWithRs : public DithererWithRs {

Expand Down
43 changes: 26 additions & 17 deletions android/lib/src/main/java/com/bilibili/burstlinker/BurstLinker.java
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,8 @@ public class BurstLinker {

private String mUseRenderScript;

private int mIgnoreTranslucency = 0;

private int mWidth;
private int mHeight;
private int mThreadCount;
Expand All @@ -41,10 +43,10 @@ public class BurstLinker {

private native long jniDebugLog(long gifEncoder, boolean debug);

private native String jniConnect(long gifEncoder, int quantizerType, int ditherType,
private native String jniConnect(long gifEncoder, int quantizerType, int ditherType, int ignoreTranslucency,
int left, int top, int delayMs, String cacheDir, Bitmap bitmap);

private native String jniConnectArray(long gifEncoder, int quantizerType, int ditherType,
private native String jniConnectArray(long gifEncoder, int quantizerType, int ditherType, int ignoreTranslucency,
int left, int top, int delayMs, String cacheDir, Bitmap[] bitmaps);

private native void jniRelease(long gifEncoder);
Expand All @@ -70,7 +72,7 @@ public void init(int width, int height, String path, int loopCount, Context cont
}

/**
* @param loopCount 0 repeat forever
* @param loopCount 0 = repeat forever
* @param context use for enable renderScript
*/
private void init(int width, int height, String path, int loopCount, int threadCount, Context context) throws GifEncodeException {
Expand Down Expand Up @@ -99,14 +101,18 @@ private void init(int width, int height, String path, int loopCount, int threadC
mThreadCount = threadCount;
mNative = jniInit(path, width, height, loopCount, threadCount);
if (mNative == 0) {
throw new GifEncodeException("init aborted!!! WTF");
throw new GifEncodeException("miao miao miao !!! init aborted");
}
}

public void debugLog(boolean debug) {
jniDebugLog(mNative, debug);
}

public void setIgnoreTranslucency(boolean ignoreTranslucency) {
mIgnoreTranslucency = ignoreTranslucency ? 1 : 0;
}

public void connect(Bitmap bitmap, int quantizerType, int ditherType, int delayMs) throws GifEncodeException {
connect(bitmap, quantizerType, ditherType, 0, 0, delayMs);
}
Expand All @@ -116,7 +122,7 @@ public void connect(Bitmap bitmap, int quantizerType, int ditherType, int delayM
*/
public void connect(Bitmap bitmap, int quantizerType, int ditherType, int left, int top, int delayMs) throws GifEncodeException {
if (mNative == 0) {
throw new GifEncodeException("please first initialization");
throw new GifEncodeException("please initialize first");
}
if (bitmap == null) {
throw new GifEncodeException("bitmap is null");
Expand All @@ -127,18 +133,18 @@ public void connect(Bitmap bitmap, int quantizerType, int ditherType, int left,
if (left + bitmap.getWidth() > mWidth || top + bitmap.getHeight() > mHeight) {
throw new GifEncodeException("image does not fit in screen");
}
String nativeMessage = jniConnect(mNative, quantizerType, ditherType, left, top,
String nativeMessage = jniConnect(mNative, quantizerType, ditherType, mIgnoreTranslucency, left, top,
delayMs, mUseRenderScript, bitmap);
if (!TextUtils.isEmpty(nativeMessage)) {
throw new GifEncodeException("native -> " + nativeMessage);
}
}

public void connectArray(List<Bitmap> bitmaps, int quantizerType, int ditherType, int delayMs) throws GifEncodeException {
connectArray(bitmaps, quantizerType, ditherType, 0, 0, delayMs);
public void connect(List<Bitmap> bitmaps, int quantizerType, int ditherType, int delayMs) throws GifEncodeException {
connect(bitmaps, quantizerType, ditherType, 0, 0, delayMs);
}

public void connectArray(List<Bitmap> bitmaps, int quantizerType, int ditherType, int left, int top, int delayMs) throws GifEncodeException {
public void connect(List<Bitmap> bitmaps, int quantizerType, int ditherType, int left, int top, int delayMs) throws GifEncodeException {
if (mNative == 0) {
throw new GifEncodeException("please first initialization");
}
Expand All @@ -156,7 +162,7 @@ public void connectArray(List<Bitmap> bitmaps, int quantizerType, int ditherType
String nativeMessage;
if (mThreadCount <= 1) {
for (Bitmap bitmap : bitmaps) {
nativeMessage = jniConnect(mNative, quantizerType, ditherType, left, top,
nativeMessage = jniConnect(mNative, quantizerType, ditherType, mIgnoreTranslucency, left, top,
delayMs, mUseRenderScript, bitmap);
if (!TextUtils.isEmpty(nativeMessage)) {
throw new GifEncodeException("native -> " + nativeMessage);
Expand All @@ -166,9 +172,9 @@ public void connectArray(List<Bitmap> bitmaps, int quantizerType, int ditherType
Bitmap[] bitmapArray;
int bitmapSize = bitmaps.size();
if (mThreadCount > bitmapSize) {
bitmapArray = bitmaps.toArray(new Bitmap[bitmapSize]);
nativeMessage = jniConnectArray(mNative, quantizerType, ditherType, left, top,
delayMs, mUseRenderScript, bitmapArray);
bitmapArray = bitmaps.toArray(new Bitmap[0]);
nativeMessage = jniConnectArray(mNative, quantizerType, ditherType, mIgnoreTranslucency,
left, top, delayMs, mUseRenderScript, bitmapArray);
if (!TextUtils.isEmpty(nativeMessage)) {
throw new GifEncodeException("native -> " + nativeMessage);
}
Expand All @@ -185,9 +191,9 @@ public void connectArray(List<Bitmap> bitmaps, int quantizerType, int ditherType
end = start + remain;
}
List<Bitmap> processBitmaps = bitmaps.subList(start, end);
bitmapArray = processBitmaps.toArray(new Bitmap[processBitmaps.size()]);
nativeMessage = jniConnectArray(mNative, quantizerType, ditherType, left, top,
delayMs, mUseRenderScript, bitmapArray);
bitmapArray = processBitmaps.toArray(new Bitmap[0]);
nativeMessage = jniConnectArray(mNative, quantizerType, ditherType, mIgnoreTranslucency,
left, top, delayMs, mUseRenderScript, bitmapArray);
if (!TextUtils.isEmpty(nativeMessage)) {
throw new GifEncodeException("native -> " + nativeMessage);
}
Expand All @@ -197,7 +203,10 @@ public void connectArray(List<Bitmap> bitmaps, int quantizerType, int ditherType
}

public void release() {
jniRelease(mNative);
if (mNative == 0) {
return;
}
// jniRelease(mNative);
mNative = 0;
}
}
Loading

0 comments on commit 6a635f5

Please sign in to comment.