libjpeg-turbo for android
Install Android NDK. Following instructions were verified with r8b, older versions may have problems, I don't know.
Get the Android sources for libjpeg-turbo from Benjamin Gaignard:
git clone git://git.linaro.org/people/tomgall/libjpeg-turbo/libjpeg-turbo.git -b linaro-android
In the libjpeg-turbo directory created by git, edit file Android.mk: after line 70, LOCAL_MODULE := libjpeg
, add the following:
ifeq ($(notdir $(MAKECMDGOALS)),libjpeg.a)
LOCAL_SRC_FILES += $(libsimd_SOURCES_DIST)
include $(BUILD_STATIC_LIBRARY)
include $(CLEAR_VARS)
LOCAL_MODULE := dummy
endif
Run ndk-build:
ndk-build NDK_PROJECT_PATH=. APP_BUILD_SCRIPT=./Android.mk obj/local/armeabi/libjpeg.a
Profit!
PS: You may want the armeabi-v7a version:
ndk-build NDK_PROJECT_PATH=. APP_BUILD_SCRIPT=./Android.mk APP_ABI=armeabi-v7a obj/local/armeabi-v7a/libjpeg.a
Or compile for ARM, to improve performance, add to command line:
LOCAL_ARM_MODE=arm
If your target has NEON support, add to command line:
LOCAL_ARM_NEON=true ARCH_ARM_HAVE_NEON=true
UPDATE: to get it work with Android NDK r15 and later, remove all references to libcutils
from Android.mk.
How to add libjpeg-turbo Android NDK as static library
You receive the compile error because your CMake code doesn't specify the location of libjpeg
header files. You can specify the directory containing the libjpeg
headers by setting the INTERFACE_INCLUDE_DIRECTORIES
property for the imported libjpeg
target.
add_library( libjpeg STATIC IMPORTED )
set_target_properties( libjpeg
PROPERTIES
IMPORTED_LOCATION ${CMAKE_SOURCE_DIR}/libjpeg/${ANDROID_ABI}/libjpeg.a
INTERFACE_INCLUDE_DIRECTORIES ${CMAKE_SOURCE_DIR}/libjpeg/include
)
Note: You may have to modify the path to match where these headers reside on your machine.
With a couple other nit-picky notes (unrelated to the error), your updated CMake file may look something like this:
cmake_minimum_required(VERSION 3.4.1)
# You should always put the project directive at the top of your root CMakeLists.txt file.
project(MyProject)
add_library( libjpeg STATIC IMPORTED )
set_target_properties( libjpeg
PROPERTIES
IMPORTED_LOCATION ${CMAKE_SOURCE_DIR}/libjpeg/${ANDROID_ABI}/libjpeg.a
INTERFACE_INCLUDE_DIRECTORIES ${CMAKE_SOURCE_DIR}/libjpeg/include
)
# You can list multiple directories in one include_directories() call.
include_directories(
src/main/cpp/rapidjson/
src/main/cpp/Eigen
)
# Looks like this isn't used. Maybe you can remove it.
file(GLOB CPP_FILES "src/main/cpp/*.cpp")
add_library(
native-lib
SHARED
native-lib.cpp
common.cpp
archive.cpp
crc32.cpp
image.cpp
read_manifest.cpp
sensors.cpp
thumbnail.cpp
upf.cpp
upf-toolkit.cpp
write_manifest.cpp
write_upf.cpp
)
find_library(log-lib log)
# Always place the scoping argument (e.g. PUBLIC, PRIVATE) in this call.
target_link_libraries(native-lib PUBLIC libjpeg ${log-lib})
Integration or build instructions for libjpeg-turbo on Android
My bad, the file's in a branch in that repository.
Also found this info:
https://wiki.linaro.org/BenjaminGaignard/libjpeg-turboAndSkia
Is libjpeg always installed with Android?
Solution:
Thanks guys for the help, I was hoping libjpeg was accessible to my development but as pointed out is in Android though not public through the NDK.
So I spent sometime reading the spec for jpg and decided on writing a C decompresser from scratch until I fell upon jpgd by Rich Geldreich, and although C++ its single file implementation of jpeg decompresser in the public domain which Ive now used without any issues on Android.
He also has an accompanying jpge (encodeder) although surplus to my requirements for this project well worth noting.
My NO-JAVA application continues.
Solution:
C++ jpg Decompressor Android NDK
How to use jpeglib-turbo with android ndk?
Changes was required in tjDecompressHeader2 and we needed to use tjDecompressHeader3 in the library version, also we need to convert jbyteArray to unsigned char * and then back to jbyteArray in order to return a byte array to java, both of them can be observed in the code below.
#include <turbojpeg.h>
#include <jni.h>
#include <android/log.h>
#include <syslog.h>
JNIEXPORT jbyteArray
Java_com_serelay_jpegturbo_MainActivity_getImagePixelData( JNIEnv* env,
jobject this,
jbyteArray data,
jint dataLength)
{
long unsigned int _jpegSize=dataLength; //!< _jpegSize from above
unsigned char *_compressedImage; //!< _compressedImage from above
jboolean isCopy;
_compressedImage = (unsigned char*)(*env)->GetByteArrayElements(env, data,
&isCopy);
int width, height, jpegSubSamp, jpegColorSpace;
// int jpegSubSamp = TJSAMP_444;
tjhandle _jpegDecompressor = tjInitDecompress();
tjDecompressHeader3(_jpegDecompressor, _compressedImage, _jpegSize, &width,
&height, &jpegSubSamp, &jpegColorSpace);
long len = width * height * 4;
long pitch = width * 4;
syslog(LOG_CRIT, "====================");
syslog(LOG_CRIT, "jpegSize %lu", _jpegSize);
syslog(LOG_CRIT, "width %d", width);
syslog(LOG_CRIT, "height %d", height);
syslog(LOG_CRIT, "subsampl %d", jpegSubSamp);
syslog(LOG_CRIT, "colorSpace %d", jpegColorSpace);
syslog(LOG_CRIT, "len %lu", len);
syslog(LOG_CRIT, "pitch %lu", pitch);
syslog(LOG_CRIT, "====================");
syslog(LOG_CRIT, "===================0");
unsigned char* mumfer = (unsigned char*)malloc(len); //!< will contain the
decompressed image
syslog(LOG_CRIT, "===================1");
tjDecompress2(_jpegDecompressor, _compressedImage, _jpegSize, mumfer, width,
0, height, TJPF_RGBA, TJFLAG_FASTDCT);
syslog(LOG_CRIT, "===================2");
tjDestroy(_jpegDecompressor);
syslog(LOG_CRIT, "===================3");
// char array to byte array
jbyteArray array = (*env)->NewByteArray(env, len);
syslog(LOG_CRIT, "===================4");
//HERE I GET THE ERROR, I HAVE BEEN TRYING WITH len/2 and WORKS , PROBABLY
SOME BYTS ARE GETTING LOST.
(*env)->SetByteArrayRegion (env, array, 0, len, (jbyte*)(mumfer));
syslog(LOG_CRIT, "===================5");
return array;
}
Also in java we need to convert the byte[] to int[] in order to get the exact pixel color values which can be done with the help of the following function
public static int byteToColorInt(byte b) {
return b & 0xFF;
}
Android how to use libjpeg-turbo library through JNi example
You could create your own wrapper for the library in the native side if you need to perform it all from native code.
The steps are roughly these ones:
In the class where you call:
System.loadLibrary("libjpeg");
You declare the native methods you need to call in the Java side, without providing any implementation:
public static native readJPEGFile();
Then you can use the javah command to create a C file with the implementation of your native funcions in the native side. That will be called when you call the native function in Java side. Notice the full path of the function and the parameters, that will be automatically generated by the javah command and should not be changed, otherwise it won't work. The result should be something like that:
extern "C" {
JNIEXPORT void JNICALL Java_com_android_packagename_GL2JNILib_readJPEGFile(JNIEnv * env, jobject obj);
};
JNIEXPORT void JNICALL Java_com_android_packagename_GL2JNILib_readJPEGFile(JNIEnv * env, jobject obj) {
// Call your library's function
}After that you need to create a shared library in the jni folder (create it if it doesn't exist) containing your wrapper functions. You can do that creating an Android.mk file and running ndk-build to generate the shared library (.so file). A possible Android.mk could be like this one, you should check the names and dependencies though:
LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
LOCAL_MODULE := jpgturbo-wrapper
LOCAL_CFLAGS := -Werror
LOCAL_SRC_FILES := jpgturboWrapper.cpp
LOCAL_C_INCLUDES := $(LOCAL_PATH)
LOCAL_LDLIBS := -lm -llog -landroid
LOCAL_STATIC_LIBRARIES := jpegturbo # write all the libraries your project depend on here, separated by white spaces
include $(BUILD_SHARED_LIBRARY)Now you can run ndk-build and the .so file will be generated and copied to its correspondent folder.
You can check the NDK documentation to start with that, and especially the samples they provide:
http://developer.android.com/tools/sdk/ndk/index.html
Sometimes is also a good idea to make a quick search on github to see if someone else took the pain before you to make work the same library, or just to see some more advanced examples than the official samples.
libjpeg turbo android jpeg compression
Finally i made it work, with the help of this question
Thanks to the user who posted it.
The code exactly meet my requirement and am able to compress images.
Note: but problem for compressing big images (> 5-30 MB)
UPDATE:-
Problem for compressing big images (> 5-30 MB) can be solved by specifying the resizing dimensions as 1/8 of its original width and height (minimum).
libjpeg-turbo for Android: how to organize runtime selection of NEON / non-NEON code?
An old question but I'll add to it anyway just in case. Someone did go into detail and one of the issues was dynamically selecting NEON. It is explained here: https://stackoverflow.com/a/20697814/712413.
The relevant section is item 4 to modify some lines in the init_simd() method.
Related Topics
Flutter Does Not Find Android Sdk
How to Hide System Navigation Bar in Tablets
Android App Bundle with In-App Locale Change
Drawable-Hdpi, Drawable-Mdpi, Drawable-Ldpi Android
How to Detect When the User Has Changed the Clock Time on Their Device
Close Application and Remove from Recent Apps/
Android: Overlay on Android Camera Preview
Setresult Does Not Work When Back Button Pressed
Android Studio - Creating Modules Without Copying Files
How to Change Bitmap Image Color in Android
Google Glass Gdk: How to Communicate with Android Device
The Process of the Service Is Killed After the Application Is Removed from the Application Tray
How to Make the Text Direction from Right to Left
Overriding Referenced Style Attributes