WebP for Android

Use libwebp with NDK. libwebp-0.1.3 already comes with Android.mk file (outdated and with syntax errors, but still). It also got generated JNI bindings in /swig/ directory.

Here's how I got it working:

  1. Download NDK, put it in system PATH.
  2. download libwebp-0.1.3.tar.gz, place it in your_project_dir/jni
  3. Replace Android.mk with the one below.
  4. Create jni/src/libwebp_java_wrap.c with content from below.
  5. create jni/Application.mk, with content from below.
  6. run ndk-build from project directory. This generates .so files in /libs/. You can inspect them with nm -D libs/armeabi/libwebp.so. In the list you'll see both the native library functions (like WebPDecodeRGB) and their JNI counterparts (like Java_com_google_webp_libwebpJNI_WebPDecodeRGB)
  7. Add /jni/swig/libwebp.jar to build path of your Android project
  8. See below for example how to use it in Java code

Here's content for Android.mk. Changed from original: removed encoder bits as I don't need these, added libwebp_java_wrap.c, changed include $(BUILD_STATIC_LIBRARY) to include $(BUILD_SHARED_LIBRARY).

LOCAL_PATH:= $(call my-dir)

include $(CLEAR_VARS)
LOCAL_SRC_FILES := \
    src/dec/alpha.c \
    src/dec/frame.c \
    src/dec/idec.c \
    src/dec/layer.c \
    src/dec/quant.c \
    src/dec/tree.c \
    src/dec/vp8.c \
    src/dec/webp.c \
    src/dec/io.c \
    src/dec/buffer.c \
    src/dsp/yuv.c \
    src/dsp/upsampling.c \
    src/dsp/cpu.c \
    src/dsp/dec.c \
    src/dsp/dec_neon.c \
    src/dsp/enc.c \
    src/utils/bit_reader.c \
    src/utils/bit_writer.c \
    src/utils/thread.c \
    src/libwebp_java_wrap.c \

LOCAL_CFLAGS := -Wall -DANDROID -DHAVE_MALLOC_H -DHAVE_PTHREAD -DWEBP_USE_THREAD \
                -finline-functions -frename-registers -ffast-math \
                -s -fomit-frame-pointer -Isrc/webp

LOCAL_C_INCLUDES += $(LOCAL_PATH)/src

LOCAL_MODULE:= webp

include $(BUILD_SHARED_LIBRARY)

Content for libwebp_java_wrap.c is here, it's basically the same as bundled in libwebp tarball, except encoder bits removed.

Content for Application.mk:

# The ARMv7 is significanly faster due to the use of the hardware FPU
APP_ABI := armeabi armeabi-v7a
APP_PLATFORM := android-9

Here's how to use in Java code. Notice how it converts byte[] array to int[] color array--this will break if endianness changes, right? Also notice how it uses arrays instead of single integers for width and height so they are passed by reference.

static {
    System.loadLibrary("webp");
}

private Bitmap webpToBitmap(byte[] encoded) {

    int[] width = new int[] { 0 };
    int[] height = new int[] { 0 };
    byte[] decoded = libwebp.WebPDecodeARGB(encoded, encoded.length, width, height);

    int[] pixels = new int[decoded.length / 4];
    ByteBuffer.wrap(decoded).asIntBuffer().get(pixels);

    return Bitmap.createBitmap(pixels, width[0], height[0], Bitmap.Config.ARGB_8888);

}

WebP is supported for Android 4.0+, a.k.a. API level 14. You can check using android.os.Build.VERSION.SDK_INT >= 14.