Problem using SDL2_image and libjpeg

Hello everybody.

Just wanted to warn that my skill in English is not very good, since it is not my native language. I have a problem with trying to run a test example using SDL2, SDL2_image, libjpeg libraries.

I used the latest snapshot of SDL2, specifically version SDL_2.0.8_11785.
Version of SDL2_images - SLD2_image_2.0.2
Version of libjpeg - libjpeg-9b

When building libraries, the following changes were made to the Android.mk files:

The following code was added to the Android.mk of the SLD2_image project:

include $ (CLEAR_VARS)
SDL2_HOME_DIR: = PathToSDL2\SDL_2.0.8_11785
LOCAL_MODULE: = SDL2
LOCAL_SRC_FILES: = $ (SDL2_HOME_DIR) \ libs \ $ (TARGET_ARCH_ABI) \ libSDL2.so
LOCAL_EXPORT_C_INCLUDES: = $ (SDL2_HOME_DIR) \ include
include $ (PREBUILT_SHARED_LIBRARY)

ifeq ($ (SUPPORT_JPG), true)
    LOCAL_C_INCLUDES + = $ (LOCAL_PATH) / $ (JPG_LIBRARY_PATH)
    LOCAL_CFLAGS + = -DLOAD_JPG
    LOCAL_SHARED_LIBRARIES + = jpeg
endif

So I build three shared libraries with the necessary dependencies.

Below is the output of objdump program:

Dynamic Section:
  PLTGOT 0x00014db4
  PLTRELSZ 0x00000480
  JMPREL 0x00001da0
  PLTREL 0x00000011
  REL 0x00001b78
  RELSZ 0x00000228
  RELENT 0x00000008
  RELCOUNT 0x00000022
  SYMTAB 0x000001f0
  SYMENT 0x00000010
  STRTAB 0x00000c60
  STRSZ 0x000008bc
  HASH 0x0000151c
  NEEDED libSDL2.so
  NEEDED libjpeg.so
  NEEDED libc.so
  NEEDED libm.so
  NEEDED libstdc++.so
  NEEDED libdl.so
  SONAME libSDL2_image.so

Calling the IMG_Init () function of the form:

int flag = IMG_INIT_JPG;

if (IMG_Init (flag)! = flag) {
    ALOGD ("JPG init not success");
} else {
    ALOGD ("JPG init success");
}

says a successful initialization, but in the end, when you try to create a SDL_Surface in code like:

SDL_Surface * img_s = NULL;

img_s = IMG_Load ("foo.jpg");

Check of this type:

if (img == NULL) {
    ALOGD ("% s", IMG_GetError ());
}

returns “JPEG loading error”

Maybe I’m doing something wrong, help me figure it out.

Is there some specific reason why you want to build libjpeg as a separate dynamic lib? The version included in SDL_image builds it as a static library so you also need to change SDL_image/external/jpeg-9b/Android.mk to build a shared library (BUILD_SHARED_LIBRARY instead of BUILD_STATIC_LIBRARY).

In addition, you need to add jpeg (before SDL_image) to the Java code that is listing native libraries to be loaded (this is really required only on old devices. Recent versions of Android will load dependencies automatically).

In Android.mk files you should also be using ‘/’, not ‘\’ in file paths for portability.

I did a quick test and tried changing libjpeg to build a shared library in the setup I currently have and it seemed to work (although my test app is referencing both SDL and SDL_image sources directly unlike in your setup). I have some random relatively recent version from mercurial for both SDL and SDL_image. So that can also be the difference. Maybe try with the latest sources.

I usually try to avoid modifying libraries I’m using so I can keep them up to date with less hassle.

If you are only trying to build the libraries so you can use include them later as prebuilt binaries one way would be to use symlinks to where the libraries like described somewhere in the docs or another is to create a separate Android.mk that just includes all the libraries you want to build (I didn’t test this, but I think it should work). This way SDL_image knows about SDL without you needing to modify it:

SDL2_HOME_DIR ?= PathToSDL2/SDL_2.0.8_11785
include $(SDL2_HOME_DIR)/Android.mk
include path/to/SDL_image/Android.mk

If you want more control on how SDL is used in your project you can do something like this in your app:

LOCAL_PATH := $(call my-dir)

include $(CLEAR_VARS)
LOCAL_MODULE := main
LOCAL_SRC_FILES := src/main/cpp/main.c
LOCAL_C_INCLUDES := $(LOCAL_PATH)
LOCAL_LDLIBS :=
LOCAL_SHARED_LIBRARIES := SDL2 SDL2_image
include $(BUILD_SHARED_LIBRARY)

#
# Import external modules.
#
$(call import-add-path,external)
$(call import-module, SDL)
$(call import-module, SDL_image)

This assumes that there is a dir called external that contains dirs called SDL and SDL_image that contain the sources. Any library that is being used by your app will then be built automatically. You can add more search paths if needed.

With the above system you could also use a prebuilt SDL just by modifying what modules are imported. Create another separate Android.mk in for example external/SDL-prebuilt containing something like this:

include $(CLEAR_VARS)
LOCAL_MODULE := SDL2
LOCAL_SRC_FILES: = path/to/libs/$(TARGET_ARCH_ABI)/libSDL2.so
LOCAL_EXPORT_C_INCLUDES: = path/to/include
$(PREBUILT_SHARED_LIBRARY)

and change the import to $(call import-module, SDL-prebuilt)

Please don’t say this. When you apologize for perfectly fine English it always sounds to me like you want a pat on the head more than anything. I’m sure that’s not the case but apologizing is just unnecessary.

Thanks for the detailed answer. You shed some light on the construction of the process of building libraries. In fact, my problem was solved by building libraries of release versions. Perhaps there was some kind of discrepancy between libraries, but now everything works.