Use pngquant lib (libimagequant) in Android NDK - android

I am trying to use the png quantization library at pngquant.org/lib in my Android project using the NDK r10 (64bit) on OS X.
I am making progress in compiling the library. The problem I have now is that the size_t type cannot be resolved. I tried including the following folder:
LOCAL_C_INCLUDES := $(NDK_TOOLCHAIN)/arm-linux-androideabi-4.9/prebuilt/darwin-x86_64/lib/gcc/arm-linux-androideabi/4.9/include
but that does not help.
I would be really interested in an empty working Android project with pngquant included.
Any help is really appreciated.
NB sorry for changing the question, but the original question I asked had some incorrect facts in it.

I don't have enough information to directly solve your specific problem, are you trying to use the standalone toolchain ?
When building for Android, since you have more than one architecture to target and the toolchain is a bit complex, it's better to use the ndk-build script from the NDK.
I've made a project here that you can integrate to your Android project directory: https://github.com/android-native-libraries/pngquant-android
The original library is using configure script but instead of extending these I've rewritten NDK Makefiles to directly compile all the lib sources, with the same cflags (openmp, sse...)
Android.mk:
LOCAL_PATH := $(call my-dir)
SRC_PATH := pngquant/lib
include $(CLEAR_VARS)
LOCAL_MODULE := imagequant
LOCAL_SRC_FILES := \
$(SRC_PATH)/blur.c \
$(SRC_PATH)/libimagequant.c \
$(SRC_PATH)/mediancut.c \
$(SRC_PATH)/mempool.c \
$(SRC_PATH)/nearest.c \
$(SRC_PATH)/pam.c \
$(SRC_PATH)/viter.c
LOCAL_C_INCLUDES := pngquant/lib
LOCAL_CFLAGS += -O3 -fno-math-errno -funroll-loops -fomit-frame-pointer -Wall -std=c99 -fopenmp
LOCAL_LDFLAGS += -fopenmp
ifeq ($(TARGET_ARCH_ABI),x86)
LOCAL_CFLAGS += -mtune=atom -msse -mfpmath=sse -mssse3 -DUSE_SSE=1
endif
include $(BUILD_SHARED_LIBRARY)
You can extend this Android.mk file to add your own native library with your sources, that are using libimagequant:
include $(CLEAR_VARS)
LOCAL_MODULE := yourlib
LOCAL_SRC_FILES := yoursources.c
LOCAL_C_INCLUDES := pngquant/lib
LOCAL_SHARED_LIBRARIES := imagequant
LOCAL_CFLAGS += -O3 -fno-math-errno -funroll-loops -fomit-frame-pointer -Wall -std=c99 -fopenmp
LOCAL_LDFLAGS += -fopenmp
ifeq ($(TARGET_ARCH_ABI),x86)
LOCAL_CFLAGS += -mtune=atom -msse -mfpmath=sse -mssse3 -DUSE_SSE=1
endif
include $(BUILD_SHARED_LIBRARY)

If you just want to use this library with default settings, I've made a simple Android library that may suit your purposes.
In your build.gradle:
dependencies {
compile 'com.ndahlquist:pngquant-android:0.2'
}
In your Android app:
File inputPngFile = getYourPng();
File outputPngFile = getOutputFile()
new LibPngQuant().pngQuantFile(inputFile, outputFile);

Related

Android NDK: Module MediaEncoder depends on undefined modules: cutils gnustl dl

I covert a ADT project to Android Studio. however, i kept getting the error when building this project:
Error:(687) Android NDK: Module MediaEncoder depends on undefined modules: cutils gnustl dl
This is what is in the Android.mk. I am new to NTK, anybody can advise the issue here?
# building application library
#
include $(CLEAR_VARS)
LOCAL_MODULE := libMediaEncoder
LOCAL_CPP_EXTENSION := .cc .cpp
LOCAL_CPPFLAGS := -O2 -Werror -Wall
LOCAL_C_INCLUDES := $(MY_LOCAL_PATH)
LOCAL_SRC_FILES := main_jni.cpp \
h264encoder.cpp \
g72x/g726_32.c \
g72x/g711.c \
g72x/g72x.c
LOCAL_LDLIBS += -llog -lz
LOCAL_SHARED_LIBRARIES := libcutils\
libgnustl\
libdl
I believe that you use a project that was configured to be built in the context of AOSP build, not by NDK. But it could still work with a very old version of NDK.
The current version, r14 which is integrated into Android Studio 2.3, requires some changes to Android.mk.
include $(CLEAR_VARS)
LOCAL_MODULE := libMediaEncoder
LOCAL_CPPFLAGS := -O2 -Werror -Wall
LOCAL_C_INCLUDES := $(MY_LOCAL_PATH)
LOCAL_SRC_FILES := main_jni.cpp \
h264encoder.cpp \
g72x/g726_32.c \
g72x/g711.c \
g72x/g72x.c
LOCAL_LDLIBS += -llog -lz -ldl
LOCAL_SHARED_LIBRARIES := libcutils_prebuilt
include $(BUILD_SHARED_LIBRARY)
include $(CLEAR_VARS)
LOCAL_MODULE := libcutils_prebuilt
LOCAL_SRC_FILES := {full-path-to}/libcutils.so
include $(PREBUILT_SHARED_LIBRARY)
To resolve the dependency on gnustl, run ndk-build APP_STL=gnustl_static, or define APP_STL in your Application.mk file.
Note that your project uses non-public system library libcutils.so. This library was once included in NDK (see https://stackoverflow.com/a/22017733/192373), but for the last 3 years Google has been struggling to discourage linking to it.
You can build libcutils.so yourself as part of AOSP, or you can adb pull it from your device or even from a compatible emulator. You can also find this binary somewhere on the Web (e.g. GitHub).
The final blow comes with the announced changes to system linking for Android 7.0 Nougat. TL;NR: any app that depends on this library will not work on future Android versions.
You need to install an older version of ndk Android NDK, Revision 10e (May 2015) worked for me and then use that ndk-build

How to dynamically get the current compiler target file name in Android.mk's LOCAL_CFLAGS?

I am currently trying to build a native module using Android's NDK. My project consists of several source files (e.g.: FILENAME.c) and for each of them I need to declare a define in their CFLAGS (-DOPERATION_FILENAME).
In order to do that I need to dynamically fetch the name of the current target file of the Android NDK's cross-compiler and use it to for the define value.
I could not find any information about how to do this and the Makefile way (CFLAGS += -DOPERATION_echo $* | sed 's/_$$//') does not apply/work here.
My current Android.mk looks like this:
LOCAL_PATH:=$(call my-dir)
include $(CLEAR_VARS)
LOCAL_ARM_MODE := arm
LOCAL_MODULE := libmpn
LOCAL_SRC_FILES := \
<cut>
LOCAL_CFLAGS := \
-std=gnu99 \
-DHAVE_CONFIG_H \
-D__GMP_WITHIN_GMP \
-O2 \
-pedantic \
-fomit-frame-pointer \
-mfloat-abi=softfp \
-DOPERATION_`echo $* | sed 's/_$$//'`
include $(BUILD_SHARED_LIBRARY)
Does anyone know of a working way to get the file name of the current cross-compiler target in Android.mk? Thanks!
In the beginning of your Android.mk, add the line that redefines get-src-file-target-cflags, like here:
get-src-file-target-cflags = $(LOCAL_SRC_FILES_TARGET_CFLAGS.$1) -DOPERATION_$(basename $1)
LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
LOCAL_SRC_FILES := t.cpp qq.c
LOCAL_MODULE := tm
LOCAL_LDLIBS := -latomic
include $(BUILD_SHARED_LIBRARY)
You can put this line in Application.mk, if you choose.

Android native shared libraries installation path

I'm struggling to get a native Android application correctly link against a custom shared object built in the same AOSP tree.
I have a shared object built with
LOCAL_SRC_FILES += \
src/libscanengine.c
LOCAL_C_INCLUDES += $(LOCAL_PATH)
LOCAL_C_INCLUDES += $(LOCAL_PATH)/include/
LOCAL_C_INCLUDES += kernel/include/
#every module depending on us will
#automagically have this included
LOCAL_EXPORT_C_INCLUDES := \
$(LOCAL_PATH)/include
LOCAL_MODULE_TAGS := optional
LOCAL_MODULE := libscanengine
LOCAL_PRELINK_MODULE := false
include $(BUILD_SHARED_LIBRARY)
It gets built and installed as the mm command invocation
build/core/dynamic_binary.mk:141: warning: overriding commands for target `.so'
build/core/dynamic_binary.mk:118: warning: ignoring old commands for target `.so'
build/core/shared_library.mk:54: warning: overriding commands for target `.so'
build/core/dynamic_binary.mk:141: warning: ignoring old commands for target `.so'
No private recovery resources for TARGET_DEVICE X
No recovery.fstab for TARGET_DEVICE X
make: Circular .so <- .so dependency dropped.
make: Circular .so <- out/target/product/X/symbols/system/lib/libscanengine dependency dropped.
make: Circular .so <- .so dependency dropped.
target Non-prelinked: libscanengine (out/target/product/X/symbols/system/lib/libscanengine)
target Strip: libscanengine (out/target/product/X/obj/lib/libscanengine)
Install: out/target/product/X/system/lib/libscanengine.so
Once I try to buil a native application linked against the newly created .so with the following Android.mk
LOCAL_SRC_FILES := \
src/mores.c
LOCAL_C_INCLUDES += \
$(LOCAL_PATH)
LOCAL_C_INCLUDES += \
$(LOCAL_PATH)/include/
#not working: commented out
#LOCAL_LDLIBS += \
-lscanengine
#LOCAL_C_FLAGS += \
-L../../out/target/product/X/system/lib/
LOCAL_SHARED_LIBRARIES := \
libscanengine
LOCAL_MODULE_TAGS := optional
LOCAL_MODULE := mores
include $(BUILD_EXECUTABLE)
I get:
make: *** No rule to make target `out/target/product/X/obj/lib/libscanengine.so', needed by `out/target/product/X/obj/EXECUTABLES/mores_intermediates/LINKED/mores'. Stop.
I noticed two things: the shared library is installed under X/out/lib as libscanengine and not libscanenegine.so as it is required by the native application.
I have to manually copy the .so everytime, which is stupid since all of this should be handled in some way by the Android build system.
Furthermore, the LOCAL_EXPORT_C_INCLUDES directive does not work. Does it work only with PREBUILT_SHARED_OBJECTS?
Android version is 2.3, there is no Java involved, everything is built under AOSP.
Thank you
j
LOCAL_C_FLAGS += \
-L../../out/target/product/X/system/lib/
does not work because it should read
LOCAL_LDFLAGS += \
-Lout/target/product/X/system/lib
or
LOCAL_LDFLAGS += \
-L$(LOCAL_PATH)/out/target/product/X/system/lib
But this does not explain why LOCAL_SHARED_LIBRARIES is not working. What commands do you use to build?
Whilst not a good solution, if the libscanengine target can't be found implicitly via AOSP, then you can always include it manually, like so.
include $(AOSP_ROOT)/PATH/TO/libscanengine/Android.mk
Regarding why the shared object won't build correctly, a hacky solution is providing a static object directly after the shared one which references it, in the Android.mk. For instance, this I adapted from an existing jpeg port. What I wanted was a shared library I could work with in a separate compilation step, but it wouldn't be built unless it was required by something.
$(call my-dir)
include $(CLEAR_VARS)
LOCAL_ARM_MODE := arm
LOCAL_SRC_FILES := \
jcapimin.c jcapistd.c jccoefct.c jccolor.c jcdctmgr.c jchuff.c \
jcinit.c jcmainct.c jcmarker.c jcmaster.c jcomapi.c jcparam.c \
jcphuff.c jcprepct.c jcsample.c jctrans.c jdapimin.c jdapistd.c \
jdatadst.c jdatasrc.c jdcoefct.c jdcolor.c jddctmgr.c jdhuff.c \
jdinput.c jdmainct.c jdmarker.c jdmaster.c jdmerge.c jdphuff.c \
jdpostct.c jdsample.c jdtrans.c jerror.c jfdctflt.c jfdctfst.c \
jfdctint.c jidctflt.c jidctred.c jquant1.c \
jquant2.c jutils.c jmemmgr.c \
jmem-android.c
# the assembler is only for the ARM version, don't break the Linux sim
ifneq ($(TARGET_ARCH),arm)
ANDROID_JPEG_NO_ASSEMBLER := true
endif
# temp fix until we understand why this broke cnn.com
#ANDROID_JPEG_NO_ASSEMBLER := true
ifeq ($(strip $(ANDROID_JPEG_NO_ASSEMBLER)),true)
LOCAL_SRC_FILES += jidctint.c jidctfst.c
else
LOCAL_SRC_FILES += jidctint.c jidctfst.S
endif
LOCAL_CFLAGS += -I"$(LOCAL_PATH)/./include" -DAVOID_TABLES
LOCAL_CFLAGS += -O3 -fstrict-aliasing -fprefetch-loop-arrays
#LOCAL_CFLAGS += -march=armv6j
LOCAL_MODULE:= jpeg
include $(BUILD_STATIC_LIBRARY)
include $(CLEAR_VARS)
LOCAL_MODULE := jpeg2
LOCAL_STATIC_LIBRARIES := jpeg
include $(BUILD_SHARED_LIBRARY)
Whilst neither of these are true solutions, as they don't address the underlying reason behind your problems, they may aid you, as they did me, in getting stuff working quickly and automatically.

how to specify the use of g++ in Android.mk?

I have a c++ library that i've added to the android2.3.6 source code and i want to compile it and link using g++ instead of gcc and ld.
is it possible?
Also,i've added this line into my Android.mk file:
LOCAL_CXX=path/to/g++compiler
But the building still use gcc.
is there any solution?
Thanks in advance!
EDIT:
Full Android.mk
LOCAL_PATH := $(call my-dir)
libdash_src_files :=cppfiles
LOCAL_C_INCLUDES :=headers
include $(CLEAR_VARS)
LOCAL_C_INCLUDES += path_to/stlport
LOCAL_SRC_FILES := $(libdash_src_files)
include external/stlport/libstlport.mk
LOCAL_SHARED_LIBRARIES += libstlport libz LOCAL_SYSTEM_SHARED_LIBRARIES :=libdl libutils libc
LOCAL_LDLIBS := $(LOCAL_LDLIBS) -llog
LOCAL_LDFLAGS:= -lz -Wl -shared
LOCAL_CXX := $(CXX)
libdash_cppflags :=-g -fPIC -v -frtti -fexceptions
LOCAL_CPPFLAGS :=$(libdash_cppflags) -fpermissive -w
LOCAL_MODULE :=libdash
LOCAL_MODULE_TAGS :=optional
include $(BUILD_SHARED_LIBRARY)
i just followed jermaine indications and did a make clean
then build it again and it worked fine.
Thanks guys.

Android NDK linking

I am trying to build an android application that calls into a C++ backend. This backend uses ZeroMQ for messaging. Per the android build page on the ZeroMQ guide, I have built a native toolchain of ndk version 6 and used that to (successfully) build ZeroMQ.
However, when I build my own .so with the JNI implementations, I can't seem to make everything load properly. Specifically, if I call System.LoadLibrary("zmq"), this completes successfully, but if I then call *System.LoadLibrary("my_lib")* I always get an UnsatisfiedLinkError complaining that:
Cannot load library reloc_library[1244]: 29 cannot locate zmq_msg_init'...
The libmy_lib.so has been generated several different ways, each with no success. After generating it, I always copies libmy_lib.so (as well as libzmq.so) to my android project's folder: libs/armeabi/.
# Compile all object files - this part was done for all options
/opt/android-toolchain/bin/arm-linux-androideabi-g++ -fpic -c Client_Events.cpp \
Client Wrapper.cpp jni.cpp -I /opt/android-root/include/ -I /my/project/specific/stuff
# Option 1 - Don't link the lib in at all
/opt/android-toolchain/bin/arm-linux-androideabi-g++ -shared \
-Wl,-soname,libmy_lib.so -o libmy_lib.so jni.o Client_Events.o Client_Wrapper.o
# Option 2 - Link ZeroMQ in statically
/opt/android-toolchain/bin/arm-linux-androideabi-g++ -shared \
-Wl,-soname,libmy_lib.so -o libmy_lib.so jni.o Client_Events.o Client_Wrapper.o \
libzmq.a libstdc++.a -Wl,--whole-archive
# Option 3 - Explicitly link ZeroMQ in dynamically
/opt/android-toolchain/bin/arm-linux-androideabi-g++ -shared \
-Wl,-soname,libmy_lib.so -o libmy_lib.so jni.o Client_Events.o Client_Wrapper.o \
-L /opt/android-root/lib/ -lzmq
With each of these options I tried both explicitly calling System.LoadLibrary("zmq") before loading my own library and not. Nothing varied the results. Using nm confirms that, at least in the case of option #2, the missing symbol *zmq_msg_init* is indeed present in libmy_lib.so.
Any ideas as to why it cannot find the ZeroMQ symbols that are linked in?
I just learnt how to compile a 2nd library and link it to my main library in android ndk. Let me see if I am of any use to you.
The following is how I create my 2nd library (In my case, I build bullet physics library and the irrlicht rendering engine as 2 separate libraries for my game).
LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
LOCAL_C_INCLUDES := HEADER FILES
LOCAL_MODULE := bullet
LOCAL_SRC_FILES := SRC FILES
LOCAL_ARM_MODE := arm
LOCAL_CFLAGS := $(LOCAL_C_INCLUDES:%=-I%) -O3 -DANDROID_NDK -DDISABLE_IMPORTGL
LOCAL_LDLIBS := -ldl -llog
include $(BUILD_SHARED_LIBRARY)
Then copy your libxxxx.so (In my case, libbullet.so and libirrlicht.so) to your jni folder. And in your main library .mk file add the following.
LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
LOCAL_C_INCLUDES := (includes for bullet)
LOCAL_MODULE := bullet
LOCAL_SRC_FILES := libbullet.so
include $(PREBUILT_SHARED_LIBRARY)
include $(CLEAR_VARS)
LOCAL_C_INCLUDES := (includes for irrlicht)
LOCAL_MODULE := irrlicht
LOCAL_SRC_FILES := libirrlicht.so
include $(PREBUILT_SHARED_LIBRARY)
include $(CLEAR_VARS)
LOCAL_C_INCLUDES := (includes for bullet + includes for irrlicht + includes for main code)
LOCAL_SRC_FILES := main code src files
LOCAL_MODULE := gamescript
LOCAL_ARM_MODE := arm
LOCAL_CFLAGS := $(LOCAL_C_INCLUDES:%=-I%) -O3 -DANDROID_NDK -DDISABLE_IMPORTGL
LOCAL_LDLIBS := -lOpenSLES -landroid -ldl -llog
LOCAL_SHARED_LIBRARIES := bullet irrlicht
include $(BUILD_SHARED_LIBRARY)
And now, add all the libraries to your java code in right order.
System.loadLibrary("bullet");
System.loadLibrary("irrlicht");
System.loadLibrary("gamescript");

Categories

Resources