打开APP
userphoto
未登录

开通VIP,畅享免费电子书等14项超值服

开通VIP
libjpeg-turbo for android

I need libjpeg-turbo for android ndk. Did anyone managed to compile it as .a (static) lib? I have tryed a few time, but it gave me a lot of errors only.

share|improve this question
    
If you give me "-", please explain "why". –  KoVadim Sep 4 '12 at 9:43
    
You should probably explain what exactly you did that did not reproduce the results reported, among other sources, here on stackoverflow: stackoverflow.com/questions/9067172/… –  Alex Cohn Sep 4 '12 at 21:31
    
1) the link github.com/psquare/libtjpeg does not exists 2) this wiki.linaro.org/BenjaminGaignard/libjpeg-turboAndSkia is for replacing ant have to be compiled in android source tree. 3) Do you want to see a lot of errors line? –  KoVadim Sep 5 '12 at 6:49
1  
It's true that Benjamin's blog explains how to replace the built-in jpeg library with libjpeg-turbo in Android platform. But to build a standalone library, it's enough to download the sources (git clone git://git.linaro.org/people/tomgall/libjpeg-turbo/libjpeg-turbo.git -b linaro-android) and run ndk-build in the libjpeg-turbo directory created by git. Here is my command line: NDK_PROJECT_PATH=. APP_BUILD_SCRIPT=./Android.mk APP_ABI=armeabi-v7a. This results in a shared lib, though. I will post the command line for a static lib as an answer –  Alex Cohn Sep 6 '12 at 7:44

2 Answers

up vote 22 down vote accepted

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 := dummyendif

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
share|improve this answer
    
When I use your command line, it produce error Android.mk:11: Extraneous text after ifeq' directive Android NDK: WARNING: Unsupported source file extensions in Android.mk for module jpeg Android NDK: turbojpeg-mapfile make: *** No rule to make target obj/armeabi/libjpeg.a'. Stop. If I use ndk-build NDK_PROJECT_PATH=. APP_BUILD_SCRIPT=./Android.mk - it work, produce libjpeg.so but don't produce libjpeg.a any idea? –  KoVadim Sep 6 '12 at 12:01
1  
Oh, yes. I forgot about line 11. There is a definite bug in the git. Split the line between true) and LOCAL_CFLAGS. You can ignore the warning. Regarding libjpeg.a - my fault, again. The target should be obj/local/armeabi/libjpeg.a. I have fixed my answer accordingly. –  Alex Cohn Sep 6 '12 at 12:17
    
10tx. Now it is compiled. The next task - combine it with my code. –  KoVadim Sep 6 '12 at 12:33
    
The next task is often trickier. Good luck! FWIW, turbo has both legacy API and its own, which is considered more friendly. –  Alex Cohn Sep 6 '12 at 12:35
1  
Alex, any updates on support for x86 and mips? 3 years later? –  Paul Asiimwe Dec 17 '13 at 22:48

This answer expands on Alex Cohn's answer. Full credit goes to him for getting me started. This answer will allow you to build libjpeg-turbo with assembly for ARM (with or without NEON) as well as x86. Compatibility is also provided for MIPS so that you can be a good citizen and build your app for all of the platforms that the r8e version of the Android NDK supports.

I still a relative newbie to actually answering questions, so don't have permissions to include attachments. So I'm going to have to inline a bunch of code. I'm also sure there are better ways to do bits and pieces of the below, so am open to suggestions for improvement.

Getting this all to work was done in six main steps (step two has many sub-steps -- each of which can be found after the main six steps):

  1. Download via git the libjpeg-turbo library containing a set of code and .mk files for Android. I downloaded it from here with git:

    git clone git://git.linaro.org/people/tomgall/libjpeg-turbo/libjpeg-turbo.git -b linaro-android

    Full credit and thanks must be given to Tom Gall for doing the initial work.

  2. Download YASM (an assembler for x86) and configure the Android build environment to support it. See the set of instructions on configuring YASM for the Android NDK that I am including below the horizontal rule at the end of my Android.mk changes in step 6. Supporting x86 requires that you aren't shy about tweaking the NDK install.

    I perhaps could have used the NASM compiler, but was far enough down the YASM path before investigating NASM that I brought the YASM path to completion.

  3. Create the simd/jsmidcfg.inc file. The libjpeg-turbo library provides simd/jsmidcfg.inc.h. It is meant for the pre-processor to take the .h and convert it to a .inc. I'm sure there is a better way for it to happen than what I did. But couldn't get it sorted out due to time pressures. Instead, I manually ran one the gcc that came with Android to create the file using the following command:

    C:\development\android\ide\android-ndk-r8e-windows-x86_64\toolchains\x86-4.4.3\prebuilt\windows-x86_64\bin\i686-linux-android-gcc.exe -E C:\development\thirdparty\libjpeg-turbo\libjpeg-turbo-android-1.2.0\simd\jsimdcfg.inc.h -o C:\development\thirdparty\libjpeg-turbo\libjpeg-turbo-android1.2.0\simd\jsimdcfg.inc

    After the pre-processor completed, I had to hand-edit the file to get it into a usable state. I had to select all of the lines above "; -- jpeglib.h" and delete them.

    Next, I had to find each of the %defines that started with _cpp_protection_ and duplicate each of those %defines WITHOUT the _cpp_protection_. For example, %define _cpp_protection_RGB_RED 0 became %define RGB_RED 0

  4. For ARM, I wanted my code to dynamically support NEON instructions on hardware that had it, and to fallback to something simpler on hardware that didn't, I modified simd/jsimd_arm.c to dynamically query for the information. I didn't want to have to make that choice when building libjpeg-turbo.

    I added the following lines of code:

    #ifdef ANDROID#include <cpufeatures/cpu-features.h>#endif

    and

    #ifdef ANDROID  uint64_t cpuFeatures = android_getCpuFeatures();  if (cpuFeatures & ANDROID_CPU_ARM_FEATURE_NEON) {     simd_support |= JSIMD_ARM_NEON;  }#endif

    within the init_simd() method.

  5. Enabling MIPS.

    To be a good citizen, I wanted to enable compilation on MIPS. While there isn't any assembler code for MIPS, the code should at least compile and run. To do that, I copied simd/jsimd_arm.c to simd/jsimd_mips.c. I edited the file so that init_simd() set simd_support = 0; I also changed all of the jsimd_can_*() methods to return 0. Finally, I removed the implementation from all of the other methods.

  6. Because I was interested in more than just a build for ARM, I changed the Application.mk file to include the following lines:

    APP_ABI := allAPP_OPTIM := release

    The APP_OPTIM comes from How to optimize a native code with android-ndk (Speed Optimization)

    Within Android.mk, I commented out everything from the "cjpeg" comment block and below. To do a block comment, I followed the advice of How to add multi line comments in makefiles

    I next customized the Android.mk file itself so that I could build for all currently supported CPUs (ARM, x86, MIPS). Here is what I ended up with (some code commented out because I wanted a static library -- also to leave the original code in place so I can see what changed). You will most likely have to change (or remove) the addprefix method calls because the file below is customized for my build environment. But other than that, it should work for you.

.

#####################################################                simd                        #####################################################LOCAL_PATH := $(call my-dir)include $(CLEAR_VARS)#ifeq ($(ARCH_ARM_HAVE_NEON),true)#LOCAL_CFLAGS += -D__ARM_HAVE_NEON#endif# From autoconf-generated MakefileEXTRA_DIST = simd/nasm_lt.sh simd/jcclrmmx.asm simd/jcclrss2.asm simd/jdclrmmx.asm simd/jdclrss2.asm simd/jdmrgmmx.asm simd/jdmrgss2.asm simd/jcclrss2-64.asm simd/jdclrss2-64.asm simd/jdmrgss2-64.asm simd/CMakeLists.txt#libsimd_SOURCES_DIST = simd/jsimd_arm_neon.S                        simd/jsimd_arm.clibsimd_SOURCES_DIST :=ifeq ($(TARGET_ARCH),arm)libsimd_SOURCES_DIST := simd/jsimd_arm_neon.S                        simd/jsimd_arm.cendififeq ($(TARGET_ARCH),x86)#libsimd_SOURCES_DIST := simd/jsimd_mips.c# List of assembly files needed is derived from content within simd/CMakelists.txt# The Intel Atom supports x86 32-bit assembly.  So take those files and leave the# 64-bit behind.libsimd_SOURCES_DIST := simd/jsimd_i386.c simd/jsimdcpu.asm simd/jccolmmx.asm simd/jcgrammx.asm simd/jdcolmmx.asm simd/jcsammmx.asm simd/jdsammmx.asm     simd/jdmermmx.asm simd/jcqntmmx.asm simd/jfmmxfst.asm simd/jfmmxint.asm simd/jimmxred.asm simd/jimmxint.asm simd/jimmxfst.asm simd/jcqnt3dn.asm     simd/jf3dnflt.asm simd/ji3dnflt.asm simd/jcqntsse.asm simd/jfsseflt.asm simd/jisseflt.asm simd/jccolss2.asm simd/jcgrass2.asm simd/jdcolss2.asm     simd/jcsamss2.asm simd/jdsamss2.asm simd/jdmerss2.asm simd/jcqnts2i.asm simd/jfss2fst.asm simd/jfss2int.asm simd/jiss2red.asm simd/jiss2int.asm     simd/jiss2fst.asm simd/jcqnts2f.asm simd/jiss2flt.asmendififeq ($(TARGET_ARCH),mips)libsimd_SOURCES_DIST := simd/jsimd_mips.cendif#LOCAL_SRC_FILES := $(libsimd_SOURCES_DIST)#LOCAL_SRC_FILES := $(addprefix ../../libjpeg-turbo-android-1.2.0/,$(LOCAL_SRC_FILES))LOCAL_C_INCLUDES := $(LOCAL_PATH)/simd                     $(LOCAL_PATH)/androidLOCAL_C_INCLUDES := simd android#LOCAL_C_INCLUDES := $(addprefix ../../libjpeg-turbo-android-1.2.0/,$(LOCAL_C_INCLUDES))#AM_CFLAGS := -march=armv7-a -mfpu=neon#AM_CCASFLAGS := -march=armv7-a -mfpu=neon#LOCAL_MODULE_TAGS := debug#LOCAL_MODULE := libsimd#include $(BUILD_STATIC_LIBRARY)#########################################################           libjpeg.so                       #########################################################include $(CLEAR_VARS)# From autoconf-generated Makefilelibjpeg_SOURCES_DIST =  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 jidctfst.c jidctint.c         jidctred.c jquant1.c jquant2.c jutils.c jmemmgr.c jmemnobs.c jaricom.c jcarith.c jdarith.c turbojpeg.c transupp.c jdatadst-tj.c jdatasrc-tj.c #turbojpeg-mapfileLOCAL_SRC_FILES:= $(libjpeg_SOURCES_DIST) $(libsimd_SOURCES_DIST)#LOCAL_SRC_FILES:= $(libjpeg_SOURCES_DIST)LOCAL_SRC_FILES := $(addprefix ../../../libjpeg-turbo-android-1.2.0/,$(LOCAL_SRC_FILES))#LOCAL_SHARED_LIBRARIES := libcutils#LOCAL_STATIC_LIBRARIES := libsimd#LOCAL_C_INCLUDES := $(LOCAL_PATH) # Include C:/development/android/ide/android-ndk-r8e-windows-x86_64/sources/android# instead of the lower-level cpufeatures because of how I had to include# cpu-features.h.  It appears as if there is a naming conflict, so I had to# change how the file was included to avoid naming conflicts.LOCAL_C_INCLUDES := $(addprefix ../../../libjpeg-turbo-android-1.2.0/,$(LOCAL_C_INCLUDES)) C:/development/thirdparty/libjpeg-turbo/libjpeg-turbo-android-1.2.0 C:/development/android/ide/android-ndk-r8e-windows-x86_64/sources/android#LOCAL_C_INCLUDES := $(LOCAL_C_INCLUDES)) ./#LOCAL_C_INCLUDES := $(addprefix $(LOCAL_PATH),$(LOCAL_C_INCLUDES)) $(LOCAL_PATH)../../../libjpeg-turbo-android-1.2.0/LOCAL_CFLAGS := -DAVOID_TABLES  -O3 -fstrict-aliasing -fprefetch-loop-arrays  -DANDROID         -DANDROID_TILE_BASED_DECODE -DENABLE_ANDROID_NULL_CONVERTLOCAL_CFLAGS += -DJPEG_LIB_VERSION=80  # I need version 8 because of some of the methods I depend onLOCAL_YASMFLAGS := -P../../libjpeg-turbo-android-1.2.0/simd/jsimdcfg.inc#LOCAL_MODULE_PATH := $(TARGET_OUT_OPTIONAL_STATIC_LIBRARY)#LOCAL_MODULE_TAGS := debug#LOCAL_MODULE := libjpegLOCAL_MODULE := jpeg-turbo#include $(BUILD_SHARED_LIBRARY)#LOCAL_STATIC_LIBRARIES := cpufeaturesinclude $(BUILD_STATIC_LIBRARY)# We reference android/cpufeatures in the Android.mk file of our main app, so# we don't need to do anything here.#$(call import-module,android/cpufeatures)

Some of the source code that ships with libjpeg-turbo is in .asm format. That is, it needs to be compiled with the NASM assembler. As it ships, the Android NDK doesn't have support for it.

To get .asm support working with NDK, I followed the rough outline presented here: http://software.intel.com/en-us/articles/using-yasm-compiler-on-android-ndkbuild

Here are a set of more detailed instructions. Within android-ndk-r8\build\core, the following things need to occur:

  1. build-binary.mk:

    all_source_extensions := .c .s .S $(LOCAL_CPP_EXTENSION) => all_source_extensions := .c .s .asm .S $(LOCAL_CPP_EXTENSION)

    For me, the above was on line 228.

    After the line that starts with: "# Build the sources to object files" you will see several foreach loops. Add one like this (I added it on line 272):

    $(foreach src,$(filter %.asm,$(LOCAL_SRC_FILES)), $(call compile-asm-source,$(src),$(call get-object-name,$(src))))
  2. definitions.mk:

    Create a new compile-asm-source to match the new entry we added within the new for loop above. We also have to add a new define within the make file. I added the following. It is a combination and simplification of the various rules used to build .c files. We need a different set of options when using yasm that necessitate these changes.

    define  ev-compile-asm-source_SRC:=$$(LOCAL_PATH)/$(1)_OBJ:=$$(LOCAL_OBJS_DIR)/$(2)_FLAGS := -f elf -DELF -DPIC $$(LOCAL_YASMFLAGS)_TEXT := "Compile $$(call get-src-file-text,$1)"_CC   := $$(NDK_CCACHE) $$(TARGET_ASM)$$(_OBJ): PRIVATE_SRC      := $$(_SRC)$$(_OBJ): PRIVATE_OBJ      := $$(_OBJ)$$(_OBJ): PRIVATE_DEPS     := $$(call host-path,$$(_OBJ).d)$$(_OBJ): PRIVATE_MODULE   := $$(LOCAL_MODULE)$$(_OBJ): PRIVATE_TEXT     := "$$(_TEXT)"$$(_OBJ): PRIVATE_CC       := $$(_CC)$$(_OBJ): PRIVATE_CFLAGS   := $$(_FLAGS)ifeq ($$(LOCAL_SHORT_COMMANDS),true)_OPTIONS_LISTFILE := $$(_OBJ).cflags$$(_OBJ): $$(call generate-list-file,$$(_FLAGS),$$(_OPTIONS_LISTFILE))$$(_OBJ): PRIVATE_CFLAGS := @$$(call host-path,$$(_OPTIONS_LISTFILE))$$(_OBJ): $$(_OPTIONS_LISTFILE)endif$$(call generate-file-dir,$$(_OBJ))$$(_OBJ): $$(_SRC) $$(LOCAL_MAKEFILE) $$(NDK_APP_APPLICATION_MK) $$(NDK_DEPENDENCIES_CONVERTER)@$$(HOST_ECHO) "$$(PRIVATE_TEXT)  : $$(PRIVATE_MODULE) <= $$(notdir $$(PRIVATE_SRC))"$$(hide) $$(PRIVATE_CC) $$(PRIVATE_CFLAGS) $$(call host-path,$$(PRIVATE_SRC)) -o $$(call host-path,$$(PRIVATE_OBJ)) $$(call cmd-convert-deps,$$(PRIVATE_DEPS))endefcompile-asm-source = $(eval $(call ev-compile-asm-source,$1,$2))

    Search for the line that starts with 'compile-s-source'. I found it at line 1491. The new compile-asm-source can go right below that.

    Next, search for the line that starts with "get-object-name". I found it at line 1270. Add ".asm" to the inner for-loop. Put it together with the .c, .s, and .S

  3. import-locals.mk:

    Add the following line below the LOCAL_CFLAGS and the LOCAL_CPPFLAGS line

    LOCAL_YASMFLAGS  := $(LOCAL_CFLAGS) $(strip $(LOCAL_YASMFLAGS))
  4. default-build-commands.mk:

    Add the following line anywhere in the file. I put mine under the TARGET_CXX section and above the TARGET_LD section.

    TARGET_ASM       = $(TOOLCHAIN_PREFIX)yasm
  5. Download and copy yasm.exe to the build folders:

    Download a copy of YASM from here: http://yasm.tortall.net/

    I have the Win64 version of the NDK, so downloaded the Win64 version of YASM. If you have the Win32 version of the NDS, download th Win32 version of YASM.

    You should just get the .exe. Copy it to the following directories as yasm.exe. If you have any other toolchain versions, copy it to those directories as well:

    C:\development\android\ide\android-ndk-r8e-windows-x86_64\toolchains\x86-4.4.3\prebuilt\windows-x86_64\i686-linux-android\binC:\development\android\ide\android-ndk-r8e-windows-x86_64\toolchains\x86-4.6\prebuilt\windows-x86_64\i686-linux-android\binC:\development\android\ide\android-ndk-r8e-windows-x86_64\toolchains\x86-4.7\prebuilt\windows-x86_64\i686-linux-android\bin

    Then, copy the file again to the directories below as i686-linux-android-yasm.exe. And as above, if you have any other toolchain versions, copy it to those directories as well:

    C:\development\android\ide\android-ndk-r8e-windows-x86_64\toolchains\x86-4.4.3\prebuilt\windows-x86_64\binC:\development\android\ide\android-ndk-r8e-windows-x86_64\toolchains\x86-4.6\prebuilt\windows-x86_64\binC:\development\android\ide\android-ndk-r8e-windows-x86_64\toolchains\x86-4.7\prebuilt\windows-x86_64\bin
share|improve this answer
    
Thanks for sharing! People seem to be looking for these updates! –  Alex Cohn Dec 26 '13 at 10:26
    
And you're a "newbie"? Thanks alot –  Paul Asiimwe Dec 29 '13 at 20:26
    
I am trying to follow the steps mentioned above. I assume steps 2&3 are for x-86, step 4 is for arm and step 5 is for MIPS. Please correct me if this is wrong. I am interested only in ARM for now. When I cloned the git repo and try to make changes in Step 4, I do not see cpufeatures directory. I only see a cpu-features.h file under directory named 'machine'. Can you please advise? –  rajaramyadhav Aug 18 at 23:44
    
If you have a working version somewhere, I would love to take a look at it. I was able to get libjpegturbo working with Alex Kohn's version. However I am looking to do dynamic NEON detection as well. –  rajaramyadhav Aug 18 at 23:46
本站仅提供存储服务,所有内容均由用户发布,如发现有害或侵权内容,请点击举报
打开APP,阅读全文并永久保存 查看更多类似文章
猜你喜欢
类似文章
【热】打开小程序,算一算2024你的财运
Android C++高级编程
C++ Tutorial: C++ Articles 2015
Android C++开发环境搭建
Windows下cocos2d-x2.2.0&Android环境搭建
Android SDK Android NDK 版本号和官方下载地址
Visual C 下面编译 libpng, libjpeg 和 ImageMagick...
更多类似文章 >>
生活服务
热点新闻
分享 收藏 导长图 关注 下载文章
绑定账号成功
后续可登录账号畅享VIP特权!
如果VIP功能使用有故障,
可点击这里联系客服!

联系客服