Android ImageMagick 7.1.0-16
This is a fully featured imagemagick build compatible with android and has Kotlin bindings (check out KMagick below). All libaries used are the absolute latest versions with the latest and greatest features. This repo automatically updates itself with the latest imagemagick releases and issues full binary releases!
It can be configured to both build as a binary (with shared libaries or statically linked), or as separate shared libraries (and no binary).
MagickWand and Magick++ are both available for compilation as well.
It comes compiled with the following features:
- OpenMP(3.1) / OpenCL (Qualcomm)
- HDRI support
- Q16 Quantum depth
It comes featured with the following delegates:
Also comes with (but these are not delegates, only support libraries):
- libicu4c (libicuuc and libicui18n)
- libltdl (required for libOpenCL)
Requires API >= 24 (>= Nougat)
Currently, only arm64-v8a is supported
You can test it with earlier versions, but I offer no support for it. If you're using only the binary, you almost certainly can compile for earlier versions. Nothing is stopping you from theoterically making it compatible with earlier Android versions too. If you get it working for earlier versions, let me know
Check out the release page for the latest built binaries. This is built using the default configuration. If you need a special configuration (for example OpenCL), you will need to build it for yourself from source.
- OpenCL support is available for Qualcomm. OpenCL is recommended over OpenMP. Please go here in order to learn how to setup OpenCL build for the project. You only need to find your own
libOpenCL.sofile and copy it over for your project. I can't host it here due to copyrights. For OpenCL support, you need to build the library yourself because of copyright issues (I can't host the OpenCL lib here, so GitHub can't build it for me). >Btw, Github Actions can do the build for you too, change the config file, and manually run the action.<
Check out the KMagick repo for instructions on how to use ImageMagick with Kotlin in your project (instead of the binary).
Quick Setup Instructions
- Android app setup code, including gradle files, assets, binary / java code, etc, can all be found under the app folder. This is not a 100% complete Android app, but rather it contains all the code examples needed for you to adapt it to your own project. Just copy / rewrite / delete code you want / don't need and combine it with your Android Studio project.
- Place your libs under the libs/arch folder. It's already setup to be noticed when your APK is built.
How to run the binary
- Put the generated binary in the assets bin folder. Put all libs in the libs/arch folder.
- Add environment variables before you run the binary.
- Execute binary with args.
- All example code and setup to do this is can be found in the example android app folder.
|ENV Variable||Description||Example Value|
||Temporary cache directory. Set to a directory writable by your app||
||The directory containing imagemagick xml config files. Should be set to the base directory, e.g.
||The directory containing the folder named
||Needed in order for the binary to find the
Building from Source
- In order to understand how to build the project, please install and setup NDK as per Google's instructions. Make sure you read how NDK works as it is important to getting your build successfully compiling. The required gradle files for building inside the app folder.
- Edit your build configuration under
Application.mkto your liking, then (next step below)
- Use your CMD in the root and execute
build-release.bat. Sorry, the build only currently works on Windows because I didn't have time to test the make files under Linux. Contributions are welcome.
Building with Docker
- Install Docker
- Run the build-with-docker script :)
-r for release, or
-d for debug build. No arguments means release mode
The script will ask you to download or build it yourself. It may be faster for you to build the image (cause there's less to download)
No Linux shell script currently exists, but there's nothing stopping you from setting it up yourself (just read the build-with-docker file).
Building with Github
- Fork the repo, change the config file (if you want), then use github actions to build it, and download the build artifacts. Pretty much almost no setup required in order to build. :)
Always latest builds? Are you serious?
Indeed I am!! I just took a bunch of time to write a program that automatically edits my source code, updates imagemagick, builds it, merges it into the main branch, and creates an automated release WITH updated binaries! All without any input from me at all! Unless the bot breaks and I have to take time to fix it*, this repo will automatically update itself!
The bot checks for updates every day on the 0, 6, 12, and 18'th hour UTC time, so if there's a new update, you can expect it to take maybe 30 minutes or so to automatically compile everything.
* that's unlikely to happen for a long time, and even if it does, it won't be hard to fix
What is the recommended way to build/run this?
Build it with OpenCL support (note, probably not all devices support OpenCL), statically linked, as a binary. HDRI on, quantum depth at 16. Make sure to use an AsyncTask to run it. Running it on your main thread WILL lock up your main UI. I can't host an OpenCL build here because I can't put the OpenCL lib here for an automatic build. So, only OpenMP builds are released.
Can I customize the build features?
Yes you can. Just go to Application.mk in the root directory and alter the variables inside to your desired configuration. Build configuration has been made very simple! Piece of cake!
Is there an easier way to build this without so much work?
Actually there is! Fork my repo, change the config to what you want, then use Github Actions to build it. Since I already have the build scripts configured, it's minimal work for you. In the case of wanting to do a openCL build, just follow the openCl instructions, change the config, then use Github Actions like before.
Why am I getting linking errors?
You probably didn't add the
LD_LIBRARY_PATH environment variable, so it doesn't know where to find any required libraries. Either that, or you don't have any libraries in your project at all. Check out the example android app for where to put your libs. Hint: put it in the
libs folder. And MAKE sure you went through the example android app and are using the supporting gradle / java code. It's all there.
Why won't the binary execute properly?
Either you are using the wrong architecture (we only support armv8a), or your source code for running the binary is wrong. Please make sure all the files in the assets are there and you're using the env variables properly. Please also see the example code in the example android app. Everything you need is here. In the case of API >= 29, see the below answer.
On API >= 29, I am getting permission denied errors!
Starting with API 29, Android disallows binary execution in the home directory. The only remaining location for executable code is the native lib directory.
There are 2 solutions for you on Android 10+:
Solution 1 - run the ELF binary from the native libs directory
- rename your binary file to something like
libmagick.soand place it in the
- Make sure you have
android:extractNativeLibs=truein your manifest.
- After this, you can make a bunch of symlinks to the
libmagick.sobinary in your native lib folder from your apps data homedirectory (e.g.
convert, etc). The symlinks allow you to act like you're using the normal
- As usual, make sure that your
libmagick.sohas the executable bit set on it
chmod +x. (This might or might not be the case by default)
libmagick.so is NOT a real shared library. It is the ELF
magick binary with a different filename, that's all. The naming allows us to copy the binary over with the other real libs.
Since it is a jni lib, you won't have to try executing anything, thereby bypassing all the problems. :) Also, it's easier to use and setup than a binary, although you should probably still run it in a separate thread regardless (don't block your main thread!). You can find KMagick here.
Solution 3 - use this project to create your own JNI lib which links against/integrates with the native imagemagick lib
Note: You should just use kmagick instead since I already made a Kotlin library for this.
- Read Oracle's documentation for how JNI works.
- Read the official Android mk guide. You can also study the make file setup I already have going. Specifically
Application.mk, and the files under the
makedirectory. After you're familiar enough with how it works, you can create your own
mkfile and integrate it into the project and tell it to build and link/integrate your own JNI lib against the real
libmagick.solib. You can do a static or shared library build (static meaning that there will be only 1 lib, which is yours, and all other libs like imagemagick will be inside it). Building a native imagemagick lib (shared or static) is already supported with a switch in the settings, so it will take minimal effort for you to integrate your build into it.
- Program all your C code / Rust code. I STRONGLY recommend using Rust as it's a better and much safer low level language compared to C. It has JNI bindings support already, and even imagemagick magick wand bindings. I STRONGLY recommend you use the imagemagick magick wand API instead of the other ones since it's much easier to do what you want using it. In the case of Rust, you're probably better off just using
release.batto build the project with static libs, then add a line below that for building your rust/jni lib against the generated static lib(s). Trust me, it's not as hard as one might think it would be (you can see here that I already have a kmagick script which links against the android lib)
- Do a bunch of Googling for any JNI, make file, imagemagick wand API, or C / Rust errors errors you encounter (as is always the case with programming!)
Kmagick? Why not Jmagick?
Well, you see. The thing is that the jmagick project hasn't been updated since 2018. Imagemagick has grown and changed so much that it's not even compatible with it anymore. Furthermore, they aren't even using the better magick wand API. Jmagick is mostly compatible with IM6, which is an older version. It's just not up to par.
So... I made a completely new one called Kmagick!! Yup, I really did make an entire ImageMagick API in Kotlin from the ground up! It's made to be compatible with the latest versions of ImageMagick, AND it uses Kotlin instead of Java! How cool is that?
I'm getting some errors about not being able to write TMP files..?
Create a tmpdir in your assets folder (same level as
usr folder), and call it
tmp (or something similar). Point to it using the
TMPDIR environment variable listed in the documentation.
Why do you only support arm64-v8a?
I didn't have time to test x86, x64, mips, armv7. There are a lot of specific configurations that need to take place such as ssize and so on that are specific to the different architectures. I don't know their required values. I'd also need to overhaul the make system to use different versions of these files in order for it to build properly. I'd love some contributions to this so we can get more archs working!!
It won't build on Linux!!
Only Windows is supported by the build system. The make files assume you have Windows. Use Windows. Or, you could also contribute to testing and fixing the makefile code that only supports Windows. If you want to help with Linux build support, then make a issue and we can work together on it.
Do you have any examples? / Where are the examples?
You can see all the example code you need for running the binary in the example android app. It also has an entire sample project setup to get you started quick.
Note: This is not a "copy all the files"-"change nothing"-"run it directly without figuring it out"-solution, but rather an example template to help you get yours right with copyable code examples. This won't work directly out of the box. But it is also generally complete, more than enough to even copy over and fix whatever needs fixing if you wanted to. So, you should be using your own project, then just gut out the example project into yours as needed.
Did this library help you?
If you found this library useful, please consider showing appreciation and sending a donation my way (maybe for a cup of coffee or a donut). I don't always have the time nor mental energy to keep this updated for free, so any donations will help this project continue to be supported for longer and get more frequent updates! Thanks for your support! <3