diff --git a/content/learning-paths/mobile-graphics-and-gaming/android_halide/Figures/01.png b/content/learning-paths/mobile-graphics-and-gaming/android_halide/Figures/01.png new file mode 100644 index 000000000..98a272f84 Binary files /dev/null and b/content/learning-paths/mobile-graphics-and-gaming/android_halide/Figures/01.png differ diff --git a/content/learning-paths/mobile-graphics-and-gaming/android_halide/Figures/02.png b/content/learning-paths/mobile-graphics-and-gaming/android_halide/Figures/02.png new file mode 100644 index 000000000..d0b8df7cb Binary files /dev/null and b/content/learning-paths/mobile-graphics-and-gaming/android_halide/Figures/02.png differ diff --git a/content/learning-paths/mobile-graphics-and-gaming/android_halide/Figures/03.png b/content/learning-paths/mobile-graphics-and-gaming/android_halide/Figures/03.png new file mode 100644 index 000000000..80e41973f Binary files /dev/null and b/content/learning-paths/mobile-graphics-and-gaming/android_halide/Figures/03.png differ diff --git a/content/learning-paths/mobile-graphics-and-gaming/android_halide/Figures/04.png b/content/learning-paths/mobile-graphics-and-gaming/android_halide/Figures/04.png new file mode 100644 index 000000000..d098da4e1 Binary files /dev/null and b/content/learning-paths/mobile-graphics-and-gaming/android_halide/Figures/04.png differ diff --git a/content/learning-paths/mobile-graphics-and-gaming/android_halide/Figures/05.png b/content/learning-paths/mobile-graphics-and-gaming/android_halide/Figures/05.png new file mode 100644 index 000000000..8fa7609f6 Binary files /dev/null and b/content/learning-paths/mobile-graphics-and-gaming/android_halide/Figures/05.png differ diff --git a/content/learning-paths/mobile-graphics-and-gaming/android_halide/Figures/06.png b/content/learning-paths/mobile-graphics-and-gaming/android_halide/Figures/06.png new file mode 100644 index 000000000..a78e5ee6f Binary files /dev/null and b/content/learning-paths/mobile-graphics-and-gaming/android_halide/Figures/06.png differ diff --git a/content/learning-paths/mobile-graphics-and-gaming/android_halide/Figures/07.png b/content/learning-paths/mobile-graphics-and-gaming/android_halide/Figures/07.png new file mode 100644 index 000000000..5993f29b2 Binary files /dev/null and b/content/learning-paths/mobile-graphics-and-gaming/android_halide/Figures/07.png differ diff --git a/content/learning-paths/mobile-graphics-and-gaming/android_halide/Figures/08.png b/content/learning-paths/mobile-graphics-and-gaming/android_halide/Figures/08.png new file mode 100644 index 000000000..a01e883ef Binary files /dev/null and b/content/learning-paths/mobile-graphics-and-gaming/android_halide/Figures/08.png differ diff --git a/content/learning-paths/mobile-graphics-and-gaming/android_halide/Figures/09.png b/content/learning-paths/mobile-graphics-and-gaming/android_halide/Figures/09.png new file mode 100644 index 000000000..64d714c26 Binary files /dev/null and b/content/learning-paths/mobile-graphics-and-gaming/android_halide/Figures/09.png differ diff --git a/content/learning-paths/mobile-graphics-and-gaming/android_halide/Figures/10.png b/content/learning-paths/mobile-graphics-and-gaming/android_halide/Figures/10.png new file mode 100644 index 000000000..571783c51 Binary files /dev/null and b/content/learning-paths/mobile-graphics-and-gaming/android_halide/Figures/10.png differ diff --git a/content/learning-paths/mobile-graphics-and-gaming/android_halide/_index.md b/content/learning-paths/mobile-graphics-and-gaming/android_halide/_index.md new file mode 100644 index 000000000..56bbf291a --- /dev/null +++ b/content/learning-paths/mobile-graphics-and-gaming/android_halide/_index.md @@ -0,0 +1,46 @@ +--- +title: Halide Essentials. From Basics to Android Integration +minutes_to_complete: 180 + +who_is_this_for: This is an introductory topic for software developers interested in learning how to use Halide for image processing. + +learning_objectives: + - Introduction, Background, and Installation. + - Building a Simple Camera/Image Processing Workflow. + - Demonstrating Operation Fusion. + - Integrating Halide into an Android (Kotlin) Project + +prerequisites: + + +author: Dawid Borycki + +### Tags +skilllevels: Introductory +subjects: Performance and Architecture +armips: + - Cortex-A + - Cortex-X +operatingsystems: + - Android +tools_software_languages: + - Android Studio + - Coding + +further_reading: + - resource: + title: Halide 19.0.0 + link: https://halide-lang.org/docs/index.html + type: website + - resource: + title: Halide GitHub + link: https://github.com/halide/Halide + type: repository + + +### FIXED, DO NOT MODIFY +# ================================================================================ +weight: 1 # _index.md always has weight of 1 to order correctly +layout: "learningpathall" # All files under learning paths have this same wrapper +learning_path_main_page: "yes" # This should be surfaced when looking for related content. Only set for _index.md of learning path content. +--- diff --git a/content/learning-paths/mobile-graphics-and-gaming/android_halide/_next-steps.md b/content/learning-paths/mobile-graphics-and-gaming/android_halide/_next-steps.md new file mode 100644 index 000000000..c3db0de5a --- /dev/null +++ b/content/learning-paths/mobile-graphics-and-gaming/android_halide/_next-steps.md @@ -0,0 +1,8 @@ +--- +# ================================================================================ +# FIXED, DO NOT MODIFY THIS FILE +# ================================================================================ +weight: 21 # Set to always be larger than the content in this path to be at the end of the navigation. +title: "Next Steps" # Always the same, html page title. +layout: "learningpathall" # All files under learning paths have this same wrapper for Hugo processing. +--- diff --git a/content/learning-paths/mobile-graphics-and-gaming/android_halide/android.md b/content/learning-paths/mobile-graphics-and-gaming/android_halide/android.md new file mode 100644 index 000000000..e1809816b --- /dev/null +++ b/content/learning-paths/mobile-graphics-and-gaming/android_halide/android.md @@ -0,0 +1,410 @@ +--- +# User change +title: "Integrating Halide into an Android (Kotlin) Project" + +weight: 6 + +layout: "learningpathall" +--- + +## Objective +In this lesson, we’ll learn how to integrate a high-performance Halide image-processing pipeline into an Android application using Kotlin. + +## Overview of Mobile Integration with Halide +Android is the world’s most widely-used mobile operating system, powering billions of devices across diverse markets. This vast user base makes Android an ideal target platform for developers aiming to reach a broad audience, particularly in applications requiring sophisticated image and signal processing, such as augmented reality, photography, video editing, and real-time analytics. + +Kotlin, now the preferred programming language for Android development, combines concise syntax with robust language features, enabling developers to write maintainable, expressive, and safe code. It offers seamless interoperability with existing Java codebases and straightforward integration with native code via JNI, simplifying the development of performant mobile applications. + +## Benefits of Using Halide on Mobile +Integrating Halide into Android applications brings several key advantages: +1. Performance. Halide enables significant acceleration of complex image processing algorithms, often surpassing the speed of traditional Java or Kotlin implementations by leveraging optimized code generation. By generating highly optimized native code tailored for ARM CPUs or GPUs, Halide can dramatically increase frame rates and responsiveness, essential for real-time or interactive applications. +2. Efficiency. On mobile devices, resource efficiency translates directly to improved battery life and reduced thermal output. Halide’s scheduling strategies (such as operation fusion, tiling, parallelization, and vectorization) minimize unnecessary memory transfers, CPU usage, and GPU overhead. This optimization substantially reduces overall power consumption, extending battery life and enhancing the user experience by preventing overheating. +3. Portability. Halide abstracts hardware-specific details, allowing developers to write a single high-level pipeline that easily targets different processor architectures and hardware configurations. Pipelines can seamlessly run on various ARM-based CPUs and GPUs commonly found in Android smartphones and tablets, enabling developers to support a wide range of devices with minimal platform-specific modifications. + +In short, Halide delivers high-performance image processing without sacrificing portability or efficiency, a balance particularly valuable on resource-constrained mobile devices. + +### Android Development Ecosystem and Challenges +While Android presents abundant opportunities for developers, the mobile development ecosystem brings its own set of challenges, especially for performance-intensive applications: +1. Limited Hardware Resources. Unlike desktop or server environments, mobile devices have significant constraints on processing power, memory capacity, and battery life. Developers must optimize software meticulously to deliver smooth performance while carefully managing hardware resource consumption. Leveraging tools like Halide allows developers to overcome these constraints by optimizing computational workloads, making resource-intensive tasks feasible on constrained hardware. +2. Cross-Compilation Complexities. Developing native code for Android requires handling multiple hardware architectures (such as ARMv7, ARM64, and sometimes x86/x86_64). Cross-compilation introduces complexities due to different instruction sets, CPU features, and performance characteristics. Managing this complexity involves careful use of the Android NDK, understanding toolchains, and correctly configuring build systems (e.g., Gradle, CMake). Halide helps mitigate these issues by abstracting away many platform-specific optimizations, automatically generating code optimized for target architectures. +3. Image-Format Conversions (Bitmap ↔ Halide Buffer). Android typically handles images through the Bitmap class or similar platform-specific constructs, whereas Halide expects image data to be in raw, contiguous buffer formats. Developers must bridge the gap between Android-specific image representations (Bitmaps, YUV images from camera APIs, etc.) and Halide’s native buffer format. Proper management of these conversions—including considerations for pixel formats, stride alignment, and memory copying overhead—can significantly impact performance and correctness, necessitating careful design and efficient implementation of buffer-handling routines. + +## Project Requirements +Before integrating Halide into your Android application, ensure you have the necessary tools and libraries. + +### Tools and Prerequisites +1. Android Studio. [Download link](https://developer.android.com/studio). +2. Android NDK (Native Development Kit). Can be easily installed from Android Studio (Tools → SDK Manager → SDK Tools → Android NDK). + +## Setting Up the Android Project +### Creating the Project: +1. Open Android Studio. +2. Select New Project > Native C++. +![img4](Figures/04.png) + +### Configure the Project: +1. Set the project Name to Arm.Halide.AndroidDemo. +2. Choose Kotlin as the language. +3. Set Minimum SDK to API 24. +4. Click Next. +![img5](Figures/05.png) +5. Select C++17 from the C++ Standard dropdown list. +![img6](Figures/06.png) +6. Click Finish. + +## Configuring the Android Project +Next, configure your Android project to use the files generated in the previous step. First, copy blur_threshold_android.a and blur_threshold_android.h into ArmHalideAndroidDemo/app/src/main/cpp. Ensure your cpp directory contains the following files: +* native-lib.cpp +* blur_threshold_android.a +* blur_threshold_android.h +* CMakeLists.txt + +Open CMakeLists.txt and modify it as follows (replace /path/to/halide with your Halide installation directory):: +```cpp +cmake_minimum_required(VERSION 3.22.1) + +project("armhalideandroiddemo") +include_directories( + /path/to/halide/include +) + +add_library(blur_threshold_android STATIC IMPORTED) +set_target_properties(blur_threshold_android PROPERTIES IMPORTED_LOCATION + ${CMAKE_CURRENT_SOURCE_DIR}/blur_threshold_android.a +) + +add_library(${CMAKE_PROJECT_NAME} SHARED native-lib.cpp) + +target_link_libraries(${CMAKE_PROJECT_NAME} + blur_threshold_android + android + log) +``` + +Open build.gradle.kts and modify it as follows: + +```console +plugins { + alias(libs.plugins.android.application) + alias(libs.plugins.kotlin.android) +} + +android { + namespace = "com.arm.armhalideandroiddemo" + compileSdk = 35 + + defaultConfig { + applicationId = "com.arm.armhalideandroiddemo" + minSdk = 24 + targetSdk = 34 + versionCode = 1 + versionName = "1.0" + ndk { + abiFilters += "arm64-v8a" + } + testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner" + externalNativeBuild { + cmake { + cppFlags += "-std=c++17" + } + } + } + + buildTypes { + release { + isMinifyEnabled = false + proguardFiles( + getDefaultProguardFile("proguard-android-optimize.txt"), + "proguard-rules.pro" + ) + } + } + compileOptions { + sourceCompatibility = JavaVersion.VERSION_11 + targetCompatibility = JavaVersion.VERSION_11 + } + kotlinOptions { + jvmTarget = "11" + } + externalNativeBuild { + cmake { + path = file("src/main/cpp/CMakeLists.txt") + version = "3.22.1" + } + } + buildFeatures { + viewBinding = true + } +} + +dependencies { + + implementation(libs.androidx.core.ktx) + implementation(libs.androidx.appcompat) + implementation(libs.material) + implementation(libs.androidx.constraintlayout) + testImplementation(libs.junit) + androidTestImplementation(libs.androidx.junit) + androidTestImplementation(libs.androidx.espresso.core) +} +``` + +Click the Sync Now button at the top. To verify that everything is configured correctly, click Build > Make Project in Android Studio. + +## UI +Now, you'll define the application's User Interface, consisting of two buttons and an ImageView. One button loads the image, the other processes it, and the ImageView displays both the original and processed images. +1. Open the res/layout/activity_main.xml file, and modify it as follows: +```XML + + + + +